public void InsertTest3() { using ValueStringBuilder sb = ValueStringBuilder.CreateFrom("llo ".AsSpan()); sb.Insert(0, "He".AsSpan()); sb.Insert(6, "World".AsSpan()); Assert.AreEqual(11, sb.Length); Assert.AreEqual("Hello World", sb.ToString()); }
public void Insert_IntCharInt_MatchesStringBuilder() { var sb = new StringBuilder(); var vsb = new ValueStringBuilder(); var rand = new Random(42); for (int i = 1; i <= 100; i++) { int index = rand.Next(sb.Length); sb.Insert(index, new string((char)i, 1), i); vsb.Insert(index, (char)i, i); } Assert.Equal(sb.Length, vsb.Length); Assert.Equal(sb.ToString(), vsb.ToString()); }
public unsafe string Translate(int clilocNum, string arg = "", bool capitalize = false) { string baseCliloc = GetString(clilocNum); if (baseCliloc == null) { return(null); } if (arg == null) { arg = ""; } var roChars = arg.AsSpan(); // get count of valid args int i = 0; int totalArgs = 0; int trueStart = -1; for (; i < roChars.Length; ++i) { if (roChars[i] != '\t') { if (trueStart == -1) { trueStart = i; } } else if (trueStart >= 0) { ++totalArgs; } } if (trueStart == -1) { trueStart = 0; } // store index locations Point *locations = stackalloc Point[++totalArgs]; i = trueStart; for (int j = 0; i < roChars.Length; ++i) { if (roChars[i] == '\t') { locations[j].X = trueStart; locations[j].Y = i; trueStart = i + 1; ++j; } } bool has_arguments = totalArgs - 1 > 0; locations[totalArgs - 1].X = trueStart; locations[totalArgs - 1].Y = i; ValueStringBuilder sb = new ValueStringBuilder(baseCliloc.AsSpan()); { int index, pos = 0; while (pos < sb.Length) { int poss = pos; pos = sb.RawChars.Slice(pos, sb.Length - pos).IndexOf('~'); if (pos == -1) { break; } pos += poss; int pos2 = sb.RawChars.Slice(pos + 1, sb.Length - (pos + 1)).IndexOf('~'); if (pos2 == -1) //non valid arg { break; } pos2 += pos + 1; index = sb.RawChars.Slice(pos + 1, pos2 - (pos + 1)).IndexOf('_'); if (index == -1) { //there is no underscore inside the bounds, so we use all the part to get the number of argument index = pos2; } else { index += pos + 1; } int start = pos + 1; int max = index - start; int count = 0; for (; count < max; count++) { if (!char.IsNumber(sb.RawChars[start + count])) { break; } } if (!int.TryParse(sb.RawChars.Slice(start, count).ToString(), out index)) { return($"MegaCliloc: error for {clilocNum}"); } --index; var a = index < 0 || index >= totalArgs?string.Empty.AsSpan() : arg.AsSpan().Slice(locations[index].X, locations[index].Y - locations[index].X); if (a.Length > 1) { if (a[0] == '#') { if (int.TryParse(a.Slice(1).ToString(), out int id1)) { var ss = GetString(id1); if (string.IsNullOrEmpty(ss)) { a = string.Empty.AsSpan(); } else { a = ss.AsSpan(); } } } else if (has_arguments && int.TryParse(a.ToString(), out int clil)) { if (_entries.TryGetValue(clil, out string value) && !string.IsNullOrEmpty(value)) { a = value.AsSpan(); } } } sb.Remove(pos, pos2 - pos + 1); sb.Insert(pos, a); if (index >= 0 && index < totalArgs) { pos += a.Length /*locations[index].Y - locations[index].X*/; } } baseCliloc = sb.ToString(); sb.Dispose(); if (capitalize) { baseCliloc = StringHelper.CapitalizeAllWords(baseCliloc); } return(baseCliloc); } }
private static string FormatBigIntegerToHex(bool targetSpan, BigInteger value, char format, int digits, NumberFormatInfo info, Span <char> destination, out int charsWritten, out bool spanSuccess) { Debug.Assert(format == 'x' || format == 'X'); // Get the bytes that make up the BigInteger. byte[] arrayToReturnToPool = null; Span <byte> bits = stackalloc byte[64]; // arbitrary threshold if (!value.TryWriteOrCountBytes(bits, out int bytesWrittenOrNeeded)) { bits = arrayToReturnToPool = ArrayPool <byte> .Shared.Rent(bytesWrittenOrNeeded); bool success = value.TryWriteBytes(bits, out bytesWrittenOrNeeded); Debug.Assert(success); } bits = bits.Slice(0, bytesWrittenOrNeeded); Span <char> stackSpace = stackalloc char[128]; // each byte is typically two chars var sb = new ValueStringBuilder(stackSpace); int cur = bits.Length - 1; if (cur > -1) { // [FF..F8] drop the high F as the two's complement negative number remains clear // [F7..08] retain the high bits as the two's complement number is wrong without it // [07..00] drop the high 0 as the two's complement positive number remains clear bool clearHighF = false; byte head = bits[cur]; if (head > 0xF7) { head -= 0xF0; clearHighF = true; } if (head < 0x08 || clearHighF) { // {0xF8-0xFF} print as {8-F} // {0x00-0x07} print as {0-7} sb.Append(head < 10 ? (char)(head + '0') : format == 'X' ? (char)((head & 0xF) - 10 + 'A') : (char)((head & 0xF) - 10 + 'a')); cur--; } } if (cur > -1) { Span <char> chars = sb.AppendSpan((cur + 1) * 2); int charsPos = 0; string hexValues = format == 'x' ? "0123456789abcdef" : "0123456789ABCDEF"; while (cur > -1) { byte b = bits[cur--]; chars[charsPos++] = hexValues[b >> 4]; chars[charsPos++] = hexValues[b & 0xF]; } } if (digits > sb.Length) { // Insert leading zeros, e.g. user specified "X5" so we create "0ABCD" instead of "ABCD" sb.Insert( 0, value._sign >= 0 ? '0' : (format == 'x') ? 'f' : 'F', digits - sb.Length); } if (arrayToReturnToPool != null) { ArrayPool <byte> .Shared.Return(arrayToReturnToPool); } if (targetSpan) { spanSuccess = sb.TryCopyTo(destination, out charsWritten); return(null); } else { charsWritten = 0; spanSuccess = false; return(sb.ToString()); } }
private static string FormatBigIntegerToHex(BigInteger value, char format, int digits, NumberFormatInfo info) { Debug.Assert(format == 'x' || format == 'X'); // Get the bytes that make up the BigInteger. Span <byte> bits = stackalloc byte[64]; // arbitrary limit to switch from stack to heap bits = value.TryWriteBytes(bits, out int bytesWritten) ? bits.Slice(0, bytesWritten) : value.ToByteArray(); Span <char> stackSpace = stackalloc char[128]; // each byte is typically two chars var sb = new ValueStringBuilder(stackSpace); int cur = bits.Length - 1; if (cur > -1) { // [FF..F8] drop the high F as the two's complement negative number remains clear // [F7..08] retain the high bits as the two's complement number is wrong without it // [07..00] drop the high 0 as the two's complement positive number remains clear bool clearHighF = false; byte head = bits[cur]; if (head > 0xF7) { head -= 0xF0; clearHighF = true; } if (head < 0x08 || clearHighF) { // {0xF8-0xFF} print as {8-F} // {0x00-0x07} print as {0-7} sb.Append(head < 10 ? (char)(head + '0') : format == 'X' ? (char)((head & 0xF) - 10 + 'A') : (char)((head & 0xF) - 10 + 'a')); cur--; } } if (cur > -1) { Span <char> chars = sb.AppendSpan((cur + 1) * 2); int charsPos = 0; string hexValues = format == 'x' ? "0123456789abcdef" : "0123456789ABCDEF"; while (cur > -1) { byte b = bits[cur--]; chars[charsPos++] = hexValues[b >> 4]; chars[charsPos++] = hexValues[b & 0xF]; } } if (digits > sb.Length) { // Insert leading zeros, e.g. user specified "X5" so we create "0ABCD" instead of "ABCD" sb.Insert( 0, value._sign >= 0 ? '0' : (format == 'x') ? 'f' : 'F', digits - sb.Length); } return(sb.ToString()); }