Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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);
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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++;
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
        }