Esempio n. 1
0
        public void TryCopyTo_FailsWhenDestinationIsTooSmall_SucceedsWhenItsLargeEnough()
        {
            var vsb = new ValueStringBuilder();

            const string Text = "expected text";

            vsb.Append(Text);
            Assert.Equal(Text.Length, vsb.Length);

            Span <char> dst = new char[Text.Length - 1];

            Assert.False(vsb.TryCopyTo(dst, out int charsWritten));
            Assert.Equal(0, charsWritten);

            dst = new char[Text.Length];
            Assert.True(vsb.TryCopyTo(dst, out charsWritten));
            Assert.Equal(Text.Length, charsWritten);
            Assert.Equal(0, vsb.Length);
        }
Esempio n. 2
0
        public void TryCopyTo_ClearsBuilder_ThenReusable()
        {
            const string Text1 = "test";
            var          vsb   = new ValueStringBuilder();

            vsb.Append(Text1);
            Assert.Equal(Text1.Length, vsb.Length);

            Span <char> dst = new char[Text1.Length];

            Assert.True(vsb.TryCopyTo(dst, out int charsWritten));
            Assert.Equal(Text1.Length, charsWritten);
            Assert.Equal(Text1, new string(dst));

            Assert.Equal(0, vsb.Length);
            Assert.Equal(string.Empty, vsb.ToString());
            Assert.True(vsb.TryCopyTo(Span <char> .Empty, out _));

            const string Text2 = "another test";

            vsb.Append(Text2);
            Assert.Equal(Text2.Length, vsb.Length);
            Assert.Equal(Text2, vsb.ToString());
        }
Esempio n. 3
0
        public void Dispose_ClearsBuilder_ThenReusable()
        {
            const string Text1 = "test";
            var          vsb   = new ValueStringBuilder();

            vsb.Append(Text1);
            Assert.Equal(Text1.Length, vsb.Length);

            vsb.Dispose();

            Assert.Equal(0, vsb.Length);
            Assert.Equal(string.Empty, vsb.ToString());
            Assert.True(vsb.TryCopyTo(Span <char> .Empty, out _));

            const string Text2 = "another test";

            vsb.Append(Text2);
            Assert.Equal(Text2.Length, vsb.Length);
            Assert.Equal(Text2, vsb.ToString());
        }
Esempio n. 4
0
        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());
            }
        }