private static int EscapeNextBytes(ReadOnlySpan <byte> value, Span <byte> destination, ref int written)
        {
            SequenceValidity status = PeekFirstSequence(value, out int numBytesConsumed, out int scalar);

            if (status != SequenceValidity.WellFormed)
            {
                ThrowHelper.ThrowArgumentException_InvalidUTF8(value);
            }

            destination[written++] = (byte)'\\';
            switch (scalar)
            {
            case JsonConstants.LineFeed:
                destination[written++] = (byte)'n';
                break;

            case JsonConstants.CarriageReturn:
                destination[written++] = (byte)'r';
                break;

            case JsonConstants.Tab:
                destination[written++] = (byte)'t';
                break;

            case JsonConstants.BackSlash:
                destination[written++] = (byte)'\\';
                break;

            case JsonConstants.BackSpace:
                destination[written++] = (byte)'b';
                break;

            case JsonConstants.FormFeed:
                destination[written++] = (byte)'f';
                break;

            default:
                destination[written++] = (byte)'u';
                if (scalar < JsonConstants.UnicodePlane01StartValue)
                {
                    bool result = Utf8Formatter.TryFormat(scalar, destination.Slice(written), out int bytesWritten, format: s_hexStandardFormat);
                    Debug.Assert(result);
                    Debug.Assert(bytesWritten == 4);
                    written += bytesWritten;
                }
                else
                {
                    // Divide by 0x400 to shift right by 10 in order to find the surrogate pairs from the scalar
                    // High surrogate = ((scalar -  0x10000) / 0x400) + D800
                    // Low surrogate = ((scalar -  0x10000) % 0x400) + DC00
                    int  quotient  = Math.DivRem(scalar - JsonConstants.UnicodePlane01StartValue, JsonConstants.ShiftRightBy10, out int remainder);
                    int  firstChar = quotient + JsonConstants.HighSurrogateStartValue;
                    int  nextChar  = remainder + JsonConstants.LowSurrogateStartValue;
                    bool result    = Utf8Formatter.TryFormat(firstChar, destination.Slice(written), out int bytesWritten, format: s_hexStandardFormat);
                    Debug.Assert(result);
                    Debug.Assert(bytesWritten == 4);
                    written += bytesWritten;
                    destination[written++] = (byte)'\\';
                    destination[written++] = (byte)'u';
                    result = Utf8Formatter.TryFormat(nextChar, destination.Slice(written), out bytesWritten, format: s_hexStandardFormat);
                    Debug.Assert(result);
                    Debug.Assert(bytesWritten == 4);
                    written += bytesWritten;
                }
                break;
            }
            return(numBytesConsumed);
        }
示例#2
0
        private static int EscapeNextBytes(ReadOnlySpan <byte> value, ref Span <byte> destination, ref int written)
        {
            SequenceValidity status = Utf8Utility.PeekFirstSequence(value, out int numBytesConsumed, out UnicodeScalar unicodeScalar);

            if (status != SequenceValidity.WellFormed)
            {
                JsonThrowHelper.ThrowJsonWriterException("Invalid UTF-8 string.");
            }

            destination[written++] = (byte)'\\';
            int scalar = unicodeScalar.Value;

            switch (scalar)
            {
            case '\n':
                destination[written++] = (byte)'n';
                break;

            case '\r':
                destination[written++] = (byte)'r';
                break;

            case '\t':
                destination[written++] = (byte)'t';
                break;

            case '\\':
                destination[written++] = (byte)'\\';
                break;

            case '/':
                destination[written++] = (byte)'/';
                break;

            case '\b':
                destination[written++] = (byte)'b';
                break;

            case '\f':
                destination[written++] = (byte)'f';
                break;

            default:
                destination[written++] = (byte)'u';
                if (scalar < 0x10000)
                {
                    WriteHex(scalar, ref destination, ref written);
                }
                else
                {
                    int quotient  = DivMod(scalar - 0x10000, 0x400, out int remainder);
                    int firstChar = quotient + 0xD800;
                    int nextChar  = remainder + 0xDC00;
                    WriteHex(firstChar, ref destination, ref written);
                    destination[written++] = (byte)'\\';
                    destination[written++] = (byte)'u';
                    WriteHex(nextChar, ref destination, ref written);
                }
                break;
            }
            return(numBytesConsumed);
        }