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); }
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); }