private void WriteStringEscapeProperty(ReadOnlySpan <byte> utf8PropertyName, DateTimeOffset value, int firstEscapeIndexProp) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); Span <byte> escapedPropertyName = length <= JsonConstants.StackallocByteThreshold ? stackalloc byte[JsonConstants.StackallocByteThreshold] : (propertyArray = ArrayPool <byte> .Shared.Rent(length)); JsonWriterHelper.EscapeString(utf8PropertyName, escapedPropertyName, firstEscapeIndexProp, _options.Encoder, out int written); WriteStringByOptions(escapedPropertyName.Slice(0, written), value); if (propertyArray != null) { ArrayPool <byte> .Shared.Return(propertyArray); } }
private void WriteNumberEscapeProperty(ReadOnlySpan <char> propertyName, decimal value, int firstEscapeIndexProp) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); Span <char> escapedPropertyName = length <= JsonConstants.StackallocCharThreshold ? stackalloc char[JsonConstants.StackallocCharThreshold] : (propertyArray = ArrayPool <char> .Shared.Rent(length)); JsonWriterHelper.EscapeString(propertyName, escapedPropertyName, firstEscapeIndexProp, _options.Encoder, out int written); WriteNumberByOptions(escapedPropertyName.Slice(0, written), value); if (propertyArray != null) { ArrayPool <char> .Shared.Return(propertyArray); } }
private void WriteCommentIndented(ReadOnlySpan <char> value) { int indent = Indentation; Debug.Assert(indent <= 2 * JsonConstants.MaxWriterDepth); Debug.Assert(value.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 4 - s_newLineLength); // All ASCII, /*...*/ => escapedValue.Length + 4 // Optionally, 1-2 bytes for new line, and up to 3x growth when transcoding int maxRequired = indent + (value.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 4 + s_newLineLength; if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } JsonWriterHelper.WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; output[BytesPending++] = JsonConstants.Slash; output[BytesPending++] = JsonConstants.Asterisk; ReadOnlySpan <byte> byteSpan = MemoryMarshal.AsBytes(value); OperationStatus status = JsonWriterHelper.ToUtf8(byteSpan, output.Slice(BytesPending), out int _, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); BytesPending += written; output[BytesPending++] = JsonConstants.Asterisk; output[BytesPending++] = JsonConstants.Slash; }
/// <summary> /// Writes the value (as a JSON number) as an element of a JSON array. /// </summary> /// <param name="utf8FormattedNumber">The value to write.</param> /// <exception cref="ArgumentException"> /// Thrown when <paramref name="utf8FormattedNumber"/> does not represent a valid JSON number. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown if this would result in invalid JSON being written (while validation is enabled). /// </exception> /// <remarks> /// Writes the <see cref="int"/> using the default <see cref="StandardFormat"/> (that is, 'G'), for example: 32767. /// </remarks> internal void WriteNumberValue(ReadOnlySpan <byte> utf8FormattedNumber) { JsonWriterHelper.ValidateValue(utf8FormattedNumber); JsonWriterHelper.ValidateNumber(utf8FormattedNumber); if (!_options.SkipValidation) { ValidateWritingValue(); } if (_options.Indented) { WriteNumberValueIndented(utf8FormattedNumber); } else { WriteNumberValueMinimized(utf8FormattedNumber); } SetFlagToAddListSeparatorBeforeNextItem(); _tokenType = JsonTokenType.Number; }
private void WriteStringEscapeValue(ReadOnlySpan <byte> utf8Value, int firstEscapeIndexVal) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(firstEscapeIndexVal >= 0 && firstEscapeIndexVal < utf8Value.Length); byte[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); Span <byte> escapedValue = length <= JsonConstants.StackallocThreshold ? stackalloc byte[length] : (valueArray = ArrayPool <byte> .Shared.Rent(length)); JsonWriterHelper.EscapeString(utf8Value, escapedValue, firstEscapeIndexVal, _options.Encoder, out int written); WriteStringByOptions(escapedValue.Slice(0, written)); if (valueArray != null) { ArrayPool <byte> .Shared.Return(valueArray); } }
private void WriteBase64EscapeProperty(ReadOnlySpan <char> propertyName, ReadOnlySpan <byte> bytes, int firstEscapeIndexProp) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); char[] propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); Span <char> escapedPropertyName = length <= JsonConstants.StackallocThreshold ? stackalloc char[length] : (propertyArray = ArrayPool <char> .Shared.Rent(length)); JsonWriterHelper.EscapeString(propertyName, escapedPropertyName, firstEscapeIndexProp, out int written); WriteBase64ByOptions(escapedPropertyName.Slice(0, written), bytes); if (propertyArray != null) { ArrayPool <char> .Shared.Return(propertyArray); } }
// TODO: https://github.com/dotnet/corefx/issues/36958 private void WriteStringIndented(ReadOnlySpan <byte> escapedValue) { int indent = Indentation; Debug.Assert(indent <= 2 * JsonConstants.MaxWriterDepth); Debug.Assert(escapedValue.Length < int.MaxValue - indent - 3 - s_newLineLength); int minRequired = indent + escapedValue.Length + 2; // 2 quotes int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } JsonWriterHelper.WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; output[BytesPending++] = JsonConstants.Quote; escapedValue.CopyTo(output.Slice(BytesPending)); BytesPending += escapedValue.Length; output[BytesPending++] = JsonConstants.Quote; }
// TODO: https://github.com/dotnet/corefx/issues/36958 private void WriteStringIndented(ReadOnlySpan <char> escapedValue) { int indent = Indentation; Debug.Assert(indent <= 2 * JsonConstants.MaxWriterDepth); Debug.Assert(escapedValue.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 3 - s_newLineLength); // All ASCII, 2 quotes => indent + escapedValue.Length + 2 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding int maxRequired = indent + (escapedValue.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 3 + s_newLineLength; if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } JsonWriterHelper.WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; output[BytesPending++] = JsonConstants.Quote; TranscodeAndWrite(escapedValue, output); output[BytesPending++] = JsonConstants.Quote; }
private void WriteStringMinimized(ReadOnlySpan <char> escapedPropertyName, DateTimeOffset value) { Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - JsonConstants.MaximumFormatDateTimeOffsetLength - 6); // All ASCII, 2 quotes for property name, 2 quotes for date, and 1 colon => escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 5 // Optionally, 1 list separator, and up to 3x growth when transcoding int maxRequired = (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDateTimeOffsetLength + 6; if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } output[BytesPending++] = JsonConstants.Quote; TranscodeAndWrite(escapedPropertyName, output); output[BytesPending++] = JsonConstants.Quote; output[BytesPending++] = JsonConstants.KeyValueSeperator; output[BytesPending++] = JsonConstants.Quote; Span <byte> tempSpan = stackalloc byte[JsonConstants.MaximumFormatDateTimeOffsetLength]; bool result = Utf8Formatter.TryFormat(value, tempSpan, out int bytesWritten, s_dateTimeStandardFormat); Debug.Assert(result); JsonWriterHelper.TrimDateTimeOffset(tempSpan.Slice(0, bytesWritten), out bytesWritten); tempSpan.Slice(0, bytesWritten).CopyTo(output.Slice(BytesPending)); BytesPending += bytesWritten; output[BytesPending++] = JsonConstants.Quote; }
private void WriteStringMinimized(ReadOnlySpan <byte> escapedPropertyName, DateTimeOffset value) { Debug.Assert(escapedPropertyName.Length < int.MaxValue - JsonConstants.MaximumFormatDateTimeOffsetLength - 6); int minRequired = escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 5; // 2 quotes for property name, 2 quotes for date, and 1 colon int maxRequired = minRequired + 1; // Optionally, 1 list separator if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } output[BytesPending++] = JsonConstants.Quote; escapedPropertyName.CopyTo(output.Slice(BytesPending)); BytesPending += escapedPropertyName.Length; output[BytesPending++] = JsonConstants.Quote; output[BytesPending++] = JsonConstants.KeyValueSeperator; output[BytesPending++] = JsonConstants.Quote; Span <byte> tempSpan = stackalloc byte[JsonConstants.MaximumFormatDateTimeOffsetLength]; bool result = Utf8Formatter.TryFormat(value, tempSpan, out int bytesWritten, s_dateTimeStandardFormat); Debug.Assert(result); JsonWriterHelper.TrimDateTimeOffset(tempSpan.Slice(0, bytesWritten), out bytesWritten); tempSpan.Slice(0, bytesWritten).CopyTo(output.Slice(BytesPending)); BytesPending += bytesWritten; output[BytesPending++] = JsonConstants.Quote; }
private void WriteStringValueIndented(DateTimeOffset value) { int indent = Indentation; Debug.Assert(indent <= 2 * JsonConstants.MaxWriterDepth); // 2 quotes, and optionally, 1 list separator and 1-2 bytes for new line int maxRequired = indent + JsonConstants.MaximumFormatDateTimeOffsetLength + 3 + s_newLineLength; if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } if (_tokenType != JsonTokenType.PropertyName) { if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } JsonWriterHelper.WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; } output[BytesPending++] = JsonConstants.Quote; JsonWriterHelper.WriteDateTimeOffsetTrimmed(output.Slice(BytesPending), value, out int bytesWritten); BytesPending += bytesWritten; output[BytesPending++] = JsonConstants.Quote; }
private void WriteStringValueMinimized(DateTimeOffset value) { int maxRequired = JsonConstants.MaximumFormatDateTimeOffsetLength + 3; // 2 quotes, and optionally, 1 list separator if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } output[BytesPending++] = JsonConstants.Quote; JsonWriterHelper.WriteDateTimeOffsetTrimmed(output.Slice(BytesPending), value, out int bytesWritten); BytesPending += bytesWritten; output[BytesPending++] = JsonConstants.Quote; }
private void WriteCommentIndented(ReadOnlySpan <byte> utf8Value) { int indent = Indentation; Debug.Assert(indent <= 2 * _options.MaxDepth); Debug.Assert(utf8Value.Length < int.MaxValue - indent - 4 - s_newLineLength); int minRequired = indent + utf8Value.Length + 4; // /*...*/ int maxRequired = minRequired + s_newLineLength; // Optionally, 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span <byte> output = _memory.Span; if (_tokenType != JsonTokenType.PropertyName) { if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } JsonWriterHelper.WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; } output[BytesPending++] = JsonConstants.Slash; output[BytesPending++] = JsonConstants.Asterisk; utf8Value.CopyTo(output.Slice(BytesPending)); BytesPending += utf8Value.Length; output[BytesPending++] = JsonConstants.Asterisk; output[BytesPending++] = JsonConstants.Slash; }
private static JsonEncodedText TranscodeAndEncode(ReadOnlySpan <char> value) { JsonWriterHelper.ValidateValue(value); int expectedByteCount = JsonReaderHelper.GetUtf8ByteCount(value); byte[] utf8Bytes = ArrayPool <byte> .Shared.Rent(expectedByteCount); JsonEncodedText encodedText; // Since GetUtf8ByteCount above already throws on invalid input, the transcoding // to UTF-8 is guaranteed to succeed here. Therefore, there's no need for a try-catch-finally block. int actualByteCount = JsonReaderHelper.GetUtf8FromText(value, utf8Bytes); Debug.Assert(expectedByteCount == actualByteCount); encodedText = EncodeHelper(utf8Bytes.AsSpan(0, actualByteCount)); // On the basis that this is user data, go ahead and clear it. utf8Bytes.AsSpan(0, expectedByteCount).Clear(); ArrayPool <byte> .Shared.Return(utf8Bytes); return(encodedText); }
private static byte[] GetEscapedString(ReadOnlySpan <byte> utf8Value, int firstEscapeIndexVal, JavaScriptEncoder encoder) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(firstEscapeIndexVal >= 0 && firstEscapeIndexVal < utf8Value.Length); byte[] valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); Span <byte> escapedValue = length <= JsonConstants.StackallocThreshold ? stackalloc byte[length] : (valueArray = ArrayPool <byte> .Shared.Rent(length)); JsonWriterHelper.EscapeString(utf8Value, escapedValue, firstEscapeIndexVal, encoder, out int written); byte[] escapedString = escapedValue.Slice(0, written).ToArray(); if (valueArray != null) { ArrayPool <byte> .Shared.Return(valueArray); } return(escapedString); }
private void WriteStringEscapePropertyOrValue(ReadOnlySpan <byte> utf8PropertyName, ReadOnlySpan <char> value, int firstEscapeIndexProp, int firstEscapeIndexVal) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= value.Length); Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); char[] valueArray = null; byte[] propertyArray = null; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); Span <char> escapedValue; if (length > JsonConstants.StackallocThreshold) { valueArray = ArrayPool <char> .Shared.Rent(length); escapedValue = valueArray; } else { // Cannot create a span directly since it gets assigned to parameter and passed down. unsafe { char *ptr = stackalloc char[length]; escapedValue = new Span <char>(ptr, length); } } JsonWriterHelper.EscapeString(value, escapedValue, firstEscapeIndexVal, out int written); value = escapedValue.Slice(0, written); } if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); Span <byte> escapedPropertyName; if (length > JsonConstants.StackallocThreshold) { propertyArray = ArrayPool <byte> .Shared.Rent(length); escapedPropertyName = propertyArray; } else { // Cannot create a span directly since it gets assigned to parameter and passed down. unsafe { byte *ptr = stackalloc byte[length]; escapedPropertyName = new Span <byte>(ptr, length); } } JsonWriterHelper.EscapeString(utf8PropertyName, escapedPropertyName, firstEscapeIndexProp, out int written); utf8PropertyName = escapedPropertyName.Slice(0, written); } WriteStringByOptions(utf8PropertyName, value); if (valueArray != null) { ArrayPool <char> .Shared.Return(valueArray); } if (propertyArray != null) { ArrayPool <byte> .Shared.Return(propertyArray); } }
private int WritePropertyNameIndented(ReadOnlySpan <char> escapedPropertyName) { int idx = 0; if (_currentDepth < 0) { if (_buffer.Length <= idx) { GrowAndEnsure(); } _buffer[idx++] = JsonConstants.ListSeparator; } if (_tokenType != JsonTokenType.None) { WriteNewLine(ref idx); } int indent = Indentation; while (true) { bool result = JsonWriterHelper.TryWriteIndentation(_buffer.Slice(idx), indent, out int bytesWritten); idx += bytesWritten; if (result) { break; } indent -= bytesWritten; AdvanceAndGrow(ref idx); } if (_buffer.Length <= idx) { AdvanceAndGrow(ref idx); } _buffer[idx++] = JsonConstants.Quote; ReadOnlySpan <byte> byteSpan = MemoryMarshal.AsBytes(escapedPropertyName); int partialConsumed = 0; while (true) { OperationStatus status = JsonWriterHelper.ToUtf8(byteSpan.Slice(partialConsumed), _buffer.Slice(idx), out int consumed, out int written); idx += written; if (status == OperationStatus.Done) { break; } partialConsumed += consumed; AdvanceAndGrow(ref idx); } if (_buffer.Length <= idx) { AdvanceAndGrow(ref idx); } _buffer[idx++] = JsonConstants.Quote; if (_buffer.Length <= idx) { AdvanceAndGrow(ref idx); } _buffer[idx++] = JsonConstants.KeyValueSeperator; if (_buffer.Length <= idx) { AdvanceAndGrow(ref idx); } _buffer[idx++] = JsonConstants.Space; return(idx); }