private void WriteValueFormattedWithEncodingValue(ref ReadOnlySpan <byte> escapedValue) { int indent = Indentation; // This is guaranteed not to overflow. Debug.Assert(int.MaxValue - escapedValue.Length / 2 * 3 - 3 - JsonWriterHelper.NewLineUtf8.Length - indent >= 0); // Calculated based on the following: ',\r\n "encoded value"' int bytesNeeded = escapedValue.Length / 2 * 3 + 3 + JsonWriterHelper.NewLineUtf8.Length + indent; Span <byte> byteBuffer = WriteValueFormatted(bytesNeeded, indent, out int idx); byteBuffer[idx++] = JsonConstants.Quote; OperationStatus status = Encodings.Utf16.ToUtf8(escapedValue, byteBuffer.Slice(idx), out int consumed, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } Debug.Assert(consumed == escapedValue.Length); idx += written; byteBuffer[idx++] = JsonConstants.Quote; Advance(idx); }
private void WriteCommentFastWithEncodingValue(ref ReadOnlySpan <byte> escapedValue) { // This is guaranteed not to overflow. Debug.Assert(int.MaxValue - escapedValue.Length / 2 * 3 - 4 >= 0); // Calculated based on the following: '/*encoded value*/' int bytesNeeded = escapedValue.Length / 2 * 3 + 4; Ensure(bytesNeeded); Span <byte> byteBuffer = _buffer; int idx = 0; byteBuffer[idx++] = JsonConstants.Solidus; byteBuffer[idx++] = (byte)'*'; // TODO: Replace with JsonConstants.Asterisk OperationStatus status = Encodings.Utf16.ToUtf8(escapedValue, byteBuffer.Slice(idx), out int consumed, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } Debug.Assert(consumed == escapedValue.Length); idx += written; byteBuffer[idx++] = (byte)'*'; // TODO: Replace with JsonConstants.Asterisk byteBuffer[idx++] = JsonConstants.Solidus; Advance(idx); }
/// <summary> /// Write a quoted string value along with a property name into the current object. /// </summary> /// <param name="name">The name of the property (i.e. key) within the containing object.</param> /// <param name="value">The string value that will be quoted within the JSON data.</param> public void WriteAttribute(string name, string value) { ReadOnlySpan <byte> nameSpan = MemoryMarshal.AsBytes(name.AsSpan()); ReadOnlySpan <byte> valueSpan = MemoryMarshal.AsBytes(value.AsSpan()); //quote {name} quote colon quote {value} quote, hence 5 int bytesNeeded = 5; if (_indent < 0) { bytesNeeded++; } if (Encodings.Utf16.ToUtf8Length(nameSpan, out int bytesNeededName) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } if (Encodings.Utf16.ToUtf8Length(valueSpan, out int bytesNeededValue) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } bytesNeeded += bytesNeededName; bytesNeeded += bytesNeededValue; if (_prettyPrint) { bytesNeeded += JsonWriterHelper.NewLineUtf8.Length + 1 + (_indent & RemoveFlagsBitMask) * 2; WriteAttributeUtf8Pretty(nameSpan, valueSpan, bytesNeeded); } else { WriteAttributeUtf8(nameSpan, valueSpan, bytesNeeded); } }
private void WriteValueFastWithEncodingValue(ref ReadOnlySpan <byte> escapedValue) { // This is guaranteed not to overflow. Debug.Assert(int.MaxValue - escapedValue.Length / 2 * 3 - 6 >= 0); // Calculated based on the following: ',"encoded value"' int bytesNeeded = escapedValue.Length / 2 * 3 + 3; if (_currentDepth >= 0) { bytesNeeded--; } Ensure(bytesNeeded); Span <byte> byteBuffer = WriteValue(bytesNeeded, out int idx); byteBuffer[idx++] = JsonConstants.Quote; OperationStatus status = Encodings.Utf16.ToUtf8(escapedValue, byteBuffer.Slice(idx), out int consumed, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } Debug.Assert(consumed == escapedValue.Length); idx += written; byteBuffer[idx++] = JsonConstants.Quote; Advance(idx); }
/// <summary> /// Write the starting tag of an array. This is used for adding an array to a /// nested object. If this is used while inside a nested array, the property /// name will be written and result in invalid JSON. /// </summary> /// <param name="name">The name of the property (i.e. key) within the containing object.</param> public void WriteArrayStart(string name) { ReadOnlySpan <byte> nameSpan = MemoryMarshal.AsBytes(name.AsSpan()); // quote {name} quote colon open-brace, hence 4 int bytesNeeded = 4; if (_indent < 0) { bytesNeeded++; } if (Encodings.Utf16.ToUtf8Length(nameSpan, out int bytesNeededValue) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } bytesNeeded += bytesNeededValue; if (_prettyPrint) { // For the new line, \r\n or \n, and the space after the colon bytesNeeded += JsonWriterHelper.NewLineUtf8.Length + 1 + (_indent & RemoveFlagsBitMask) * 2; WriteStartUtf8Pretty(nameSpan, bytesNeeded, JsonConstants.OpenBracket); } else { WriteStartUtf8(nameSpan, bytesNeeded, JsonConstants.OpenBracket); } _indent &= RemoveFlagsBitMask; _indent++; }
private void WriteCommentFormattedWithEncodingValue(ref ReadOnlySpan <byte> escapedValue) { int indent = Indentation; // This is guaranteed not to overflow. Debug.Assert(int.MaxValue - escapedValue.Length / 2 * 3 - 4 - JsonWriterHelper.NewLineUtf8.Length - indent >= 0); // Calculated based on the following: '\r\n /*encoded value*/' int bytesNeeded = escapedValue.Length / 2 * 3 + 4 + JsonWriterHelper.NewLineUtf8.Length + indent; if (_tokenType == JsonTokenType.None) { bytesNeeded -= JsonWriterHelper.NewLineUtf8.Length; } Ensure(bytesNeeded); Span <byte> byteBuffer = _buffer; int idx = 0; if (_tokenType != JsonTokenType.None) { WriteNewLine(ref byteBuffer, ref idx); } idx += JsonWriterHelper.WriteIndentation(byteBuffer.Slice(idx, indent)); byteBuffer[idx++] = JsonConstants.Solidus; byteBuffer[idx++] = (byte)'*'; // TODO: Replace with JsonConstants.Asterisk OperationStatus status = Encodings.Utf16.ToUtf8(escapedValue, byteBuffer.Slice(idx), out int consumed, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } Debug.Assert(consumed == escapedValue.Length); idx += written; byteBuffer[idx++] = (byte)'*'; // TODO: Replace with JsonConstants.Asterisk byteBuffer[idx++] = JsonConstants.Solidus; Advance(idx); }
private void WriteAttributeUtf8Pretty(ReadOnlySpan <byte> nameSpan, ReadOnlySpan <byte> valueSpan) { //quote {name} quote colon quote {value} quote, hence 5 int bytesNeeded = 5; if (_indent < 0) { bytesNeeded++; } if (Encodings.Utf16.ToUtf8Length(nameSpan, out int bytesNeededName) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } if (Encodings.Utf16.ToUtf8Length(valueSpan, out int bytesNeededValue) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } bytesNeeded += bytesNeededName; bytesNeeded += bytesNeededValue; bytesNeeded += JsonWriterHelper.NewLineUtf8.Length + 1 + (_indent & RemoveFlagsBitMask) * 2; WriteAttributeUtf8Pretty(nameSpan, valueSpan, bytesNeeded); }
private void WriteAttributeUtf8Pretty(ReadOnlySpan <byte> nameSpan, long value) { // quote {name} quote colon, hence 3 int bytesNeeded = 3; if (_indent < 0) { bytesNeeded++; } if (Encodings.Utf16.ToUtf8Length(nameSpan, out int bytesNeededName) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } bytesNeeded += bytesNeededName; // For the new line, \r\n or \n, and the space after the colon bytesNeeded += JsonWriterHelper.NewLineUtf8.Length + 1 + (_indent & RemoveFlagsBitMask) * 2; bool insertNegationSign = false; if (value < 0) { insertNegationSign = true; value = -value; bytesNeeded += 1; } int digitCount = JsonWriterHelper.CountDigits((ulong)value); bytesNeeded += digitCount; Span <byte> byteBuffer = EnsureBuffer(bytesNeeded); int idx = 0; if (_indent < 0) { byteBuffer[idx++] = JsonConstants.ListSeperator; } idx += AddNewLineAndIndentation(byteBuffer.Slice(idx)); byteBuffer[idx++] = JsonConstants.Quote; OperationStatus status = Encodings.Utf16.ToUtf8(nameSpan, byteBuffer.Slice(idx), out int consumed, out int written); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowFormatException(); } Debug.Assert(consumed == nameSpan.Length); idx += written; byteBuffer[idx++] = JsonConstants.Quote; byteBuffer[idx++] = JsonConstants.KeyValueSeperator; byteBuffer[idx++] = JsonConstants.Space; _indent |= 1 << 31; if (insertNegationSign) { byteBuffer[idx++] = (byte)'-'; } JsonWriterHelper.WriteDigitsUInt64D((ulong)value, byteBuffer.Slice(idx, digitCount)); _bufferWriter.Advance(bytesNeeded); }
private void WriteStartUtf8Pretty(ReadOnlySpan <byte> nameSpanByte, byte token) { // quote {name} quote colon open-brace, hence 4 int bytesNeeded = 4; if (_indent < 0) { bytesNeeded++; } if (Encodings.Utf16.ToUtf8Length(nameSpanByte, out int bytesNeededValue) != OperationStatus.Done) { JsonThrowHelper.ThrowArgumentExceptionInvalidUtf8String(); } bytesNeeded += bytesNeededValue; int indent = _indent & RemoveFlagsBitMask; // For the new line, \r\n or \n, and the space after the colon bytesNeeded += JsonWriterHelper.NewLineUtf8.Length + 1 + indent * 2; Span <byte> byteBuffer = EnsureBuffer(bytesNeeded); int idx = 0; if (_indent < 0) { byteBuffer[idx++] = JsonConstants.ListSeperator; } // \r\n versus \n, depending on OS if (JsonWriterHelper.NewLineUtf8.Length == 2) { byteBuffer[idx++] = JsonConstants.CarriageReturn; } byteBuffer[idx++] = JsonConstants.LineFeed; while (indent-- > 0) { byteBuffer[idx++] = JsonConstants.Space; byteBuffer[idx++] = JsonConstants.Space; } byteBuffer[idx++] = JsonConstants.Quote; OperationStatus status = Encodings.Utf16.ToUtf8(nameSpanByte, byteBuffer.Slice(idx), out int consumed, out int written); Debug.Assert(consumed == nameSpanByte.Length); if (status != OperationStatus.Done) { JsonThrowHelper.ThrowFormatException(); } idx += written; byteBuffer[idx++] = JsonConstants.Quote; byteBuffer[idx++] = JsonConstants.KeyValueSeperator; byteBuffer[idx++] = JsonConstants.Space; byteBuffer[idx++] = token; _bufferWriter.Advance(idx); }