private void ValidatePropertyNameAndDepth(ref ReadOnlySpan <byte> propertyName)
 {
     // TODO: Use throw helper with proper error messages
     if (propertyName.Length > JsonConstants.MaxTokenSize || CurrentDepth >= JsonConstants.MaxWriterDepth)
     {
         JsonThrowHelper.ThrowJsonWriterOrArgumentException(propertyName, _currentDepth);
     }
 }
示例#2
0
 public static void ValidateValue(ref ReadOnlySpan <char> value)
 {
     // TODO: Use throw helper with proper error messages
     if (value.Length > JsonConstants.MaxCharacterTokenSize)
     {
         JsonThrowHelper.ThrowArgumentException("Argument too large.");
     }
 }
示例#3
0
 public static void ValidatePropertyAndValue(ReadOnlySpan <char> propertyName, ReadOnlySpan <byte> value)
 {
     // TODO: Use throw helper with proper error messages
     if (propertyName.Length > JsonConstants.MaxCharacterTokenSize || value.Length > JsonConstants.MaxTokenSize)
     {
         JsonThrowHelper.ThrowArgumentException(propertyName, value);
     }
 }
示例#4
0
 public static void ValidateProperty(ref ReadOnlySpan <byte> propertyName)
 {
     // TODO: Use throw helper with proper error messages
     if (propertyName.Length > JsonConstants.MaxTokenSize)
     {
         JsonThrowHelper.ThrowArgumentException("Argument too large.");
     }
 }
示例#5
0
        public StackRow Peek()
        {
            if (_topOfStack > _stackSpace.Length - StackRow.Size)
            {
                JsonThrowHelper.ThrowInvalidOperationException();
            }

            return(MemoryMarshal.Read <StackRow>(_stackSpace.Slice(_topOfStack)));
        }
示例#6
0
        private bool TryWriteAttributeUtf8(ReadOnlySpan <byte> nameSpanByte, ReadOnlySpan <byte> valueSpanByte)
        {
            int idx = 0;

            try
            {
                Span <byte> byteBuffer = _bufferWriter.Buffer;

                if (_indent < 0)
                {
                    byteBuffer[idx++] = JsonConstants.ListSeperator;
                }

                byteBuffer[idx++] = JsonConstants.Quote;

                OperationStatus status = Encodings.Utf16.ToUtf8(nameSpanByte, byteBuffer.Slice(idx), out int consumed, out int written);
                if (status == OperationStatus.DestinationTooSmall)
                {
                    return(false);
                }
                if (status != OperationStatus.Done)
                {
                    JsonThrowHelper.ThrowFormatException();
                }
                Debug.Assert(consumed == nameSpanByte.Length);
                idx += written;

                byteBuffer[idx++] = JsonConstants.Quote;

                byteBuffer[idx++] = JsonConstants.KeyValueSeperator;

                byteBuffer[idx++] = JsonConstants.Quote;

                status = Encodings.Utf16.ToUtf8(valueSpanByte, byteBuffer.Slice(idx), out consumed, out written);
                if (status == OperationStatus.DestinationTooSmall)
                {
                    return(false);
                }
                if (status != OperationStatus.Done)
                {
                    JsonThrowHelper.ThrowFormatException();
                }
                Debug.Assert(consumed == valueSpanByte.Length);
                idx += written;

                byteBuffer[idx++] = JsonConstants.Quote;
            }
            catch (IndexOutOfRangeException)
            {
                return(false);
            }

            _bufferWriter.Advance(idx);
            _indent |= 1 << 31;
            return(true);
        }
示例#7
0
        public void Flush(bool isFinalBlock = true)
        {
            //TODO: Fix exception message and check other potential conditions for invalid end.
            if (isFinalBlock && !_writerOptions.SkipValidation && CurrentDepth != 0)
            {
                JsonThrowHelper.ThrowJsonWriterException("Invalid end of JSON.");
            }

            Flush();
        }
示例#8
0
 public void Dispose()
 {
     if (_pool == null)
     {
         JsonThrowHelper.ThrowInvalidOperationException("Only root object can (and should) be disposed.");
     }
     _pool.Return(_rentedBuffer);
     Span  = Span <byte> .Empty;
     Index = 0;
 }
示例#9
0
 public     JsonObject this[Utf8Span name]
 {
     get
     {
         if (TryGetValue(name, out JsonObject value))
         {
             return(value);
         }
         JsonThrowHelper.ThrowKeyNotFoundException();
         return(default);
示例#10
0
        public bool TryGetValue(Utf8Span propertyName, out JsonObject value)
        {
            DbRow record = _database.Get();

            if (record.JsonType != JsonType.StartObject)
            {
                JsonThrowHelper.ThrowInvalidOperationException();
            }

            for (int i = DbRow.Size; i < _database.Length; i += DbRow.Size)
            {
                record = _database.Get(i);

                if (!record.IsSimpleValue)
                {
                    if (record.SizeOrLength != 0)
                    {
                        i += DbRow.Size * record.NumberOfRows;
                    }
                    continue;
                }

                Debug.Assert(record.JsonType == JsonType.String);

                int   startIndex = i + DbRow.Size;
                DbRow nextRecord = _database.Get(startIndex);

                if (_jsonData.Slice(record.Location, record.SizeOrLength).SequenceEqual(propertyName.Bytes))
                {
                    int length = DbRow.Size;
                    if (!nextRecord.IsSimpleValue)
                    {
                        if (nextRecord.SizeOrLength != 0)
                        {
                            length += DbRow.Size * nextRecord.NumberOfRows;
                        }
                    }

                    value = CreateJsonObject(startIndex, length);
                    return(true);
                }

                // Skip primitive value since we are looking for keys
                if (nextRecord.IsSimpleValue)
                {
                    i += DbRow.Size;
                }
            }

            value = default;
            return(false);
        }
示例#11
0
        private void WriteAttributeUtf8(ReadOnlySpan <byte> nameSpanByte, ReadOnlySpan <byte> valueSpanByte, int bytesNeeded)
        {
            Span <byte> byteBuffer = EnsureBuffer(bytesNeeded);
            int         idx        = 0;

            if (!_firstItem)
            {
                byteBuffer[idx++] = JsonConstants.ListSeperator;
            }

            if (_prettyPrint)
            {
                idx += AddNewLineAndIndentation(byteBuffer.Slice(idx));
            }

            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;

            if (_prettyPrint)
            {
                byteBuffer[idx++] = JsonConstants.Space;
            }

            byteBuffer[idx++] = JsonConstants.Quote;

            status = Encodings.Utf16.ToUtf8(valueSpanByte, byteBuffer.Slice(idx), out consumed, out written);
            Debug.Assert(consumed == valueSpanByte.Length);
            if (status != OperationStatus.Done)
            {
                JsonThrowHelper.ThrowFormatException();
            }
            idx += written;

            byteBuffer[idx++] = JsonConstants.Quote;

            _bufferWriter.Advance(idx);
            _firstItem = false;
        }
示例#12
0
        private void ValidateStart(ref ReadOnlySpan <byte> propertyName, byte token)
        {
            if (JsonWriterHelper.IndexOfAnyEscape(propertyName) != -1)
            {
                JsonThrowHelper.ThrowJsonWriterException("Property name must be properly escaped."); //TODO: Fix message
            }
            if (!_inObject)
            {
                Debug.Assert(_tokenType != JsonTokenType.StartObject);
                JsonThrowHelper.ThrowJsonWriterException(token);    //TODO: Add resouce message
            }

            UpdateBitStackOnStart(token);
        }
示例#13
0
        public Utf8JsonReaderStream(Stream jsonStream)
        {
            if (!jsonStream.CanRead || !jsonStream.CanSeek)
                JsonThrowHelper.ThrowArgumentException("Stream must be readable and seekable.");

            _pooledArray = ArrayPool<byte>.Shared.Rent(FirstSegmentSize);
            int numberOfBytes = jsonStream.Read(_pooledArray, 0, FirstSegmentSize);
            _buffer = _pooledArray.AsSpan(0, numberOfBytes);
            _stream = jsonStream;

            _isFinalBlock = numberOfBytes == 0;
            _jsonReader = new Utf8JsonReader(_buffer, _isFinalBlock);
            _consumed = 0;
        }
示例#14
0
        public bool TryGetValue(string propertyName, out JsonObject value)
        {
            var record = GetRecord(0);

            if (record.Length == 0)
            {
                JsonThrowHelper.ThrowKeyNotFoundException();
            }

            if (record.Type != JsonValueType.Object)
            {
                JsonThrowHelper.ThrowInvalidOperationException();
            }

            for (int i = DbRow.Size; i < _database.Length; i += DbRow.Size)
            {
                record = MemoryMarshal.Read <DbRow>(_database.Slice(i));

                if (!record.IsSimpleValue)
                {
                    i += record.Length * DbRow.Size;
                    continue;
                }

                if (new Utf8Span(_jsonData.Slice(record.Location, record.Length)) == propertyName)
                {
                    int newStart = i + DbRow.Size;
                    int newEnd   = newStart + DbRow.Size;

                    record = MemoryMarshal.Read <DbRow>(_database.Slice(newStart));

                    if (!record.IsSimpleValue)
                    {
                        newEnd = newEnd + DbRow.Size * record.Length;
                    }

                    value = new JsonObject(_jsonData, _database.Slice(newStart, newEnd - newStart));
                    return(true);
                }

                var valueType = MemoryMarshal.Read <JsonValueType>(_database.Slice(i + DbRow.Size + 8));
                if (valueType != JsonValueType.Object && valueType != JsonValueType.Array)
                {
                    i += DbRow.Size;
                }
            }

            value = default;
            return(false);
        }
示例#15
0
        private bool TryWriteAttributeUtf8(ReadOnlySpan <byte> nameSpanByte, long value)
        {
            int idx = 0;

            try
            {
                Span <byte> byteBuffer = _bufferWriter.Buffer;

                if (_indent < 0)
                {
                    byteBuffer[idx++] = JsonConstants.ListSeperator;
                }

                byteBuffer[idx++] = JsonConstants.Quote;

                OperationStatus status = Encodings.Utf16.ToUtf8(nameSpanByte, byteBuffer.Slice(idx), out int consumed, out int written);
                if (status == OperationStatus.DestinationTooSmall)
                {
                    return(false);
                }
                if (status != OperationStatus.Done)
                {
                    JsonThrowHelper.ThrowFormatException();
                }
                Debug.Assert(consumed == nameSpanByte.Length);
                idx += written;

                byteBuffer[idx++] = JsonConstants.Quote;

                byteBuffer[idx++] = JsonConstants.KeyValueSeperator;

                if (!JsonWriterHelper.TryFormatInt64Default(value, byteBuffer.Slice(idx), out int bytesWritten))
                {
                    return(false);
                }
                // Using Utf8Formatter with default StandardFormat is roughly 30% slower (17 ns versus 12 ns)
                // See: https://github.com/dotnet/corefx/issues/25425
                //if (!Utf8Formatter.TryFormat(value, byteBuffer.Slice(idx), out int bytesWritten)) return false;
                idx += bytesWritten;
            }
            catch (IndexOutOfRangeException)
            {
                return(false);
            }

            _bufferWriter.Advance(idx);
            _indent |= 1 << 31;
            return(true);
        }
示例#16
0
 private void ValidateWritingValue()
 {
     if (_inObject)
     {
         Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray);
         JsonThrowHelper.ThrowJsonWriterException(_tokenType);    //TODO: Add resource message
     }
     else
     {
         if (!_isNotPrimitive && _tokenType != JsonTokenType.None)
         {
             JsonThrowHelper.ThrowJsonWriterException(_tokenType);    //TODO: Add resource message
         }
     }
 }
示例#17
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);
        }
示例#18
0
 /// <summary>
 /// Read the next token from the data buffer.
 /// </summary>
 /// <returns>True if the token was read successfully, else false.</returns>
 public bool Read()
 {
     if (UseFastUtf8)
     {
         return(ReadUtf8());
     }
     else if (UseFastUtf16)
     {
         return(ReadUtf16());
     }
     else
     {
         JsonThrowHelper.ThrowNotImplementedException();
         return(false);
     }
 }
示例#19
0
 private void ValidateStart(byte token)
 {
     if (_inObject)
     {
         Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray);
         JsonThrowHelper.ThrowJsonWriterException(token, _tokenType);
     }
     else
     {
         Debug.Assert(_tokenType != JsonTokenType.StartObject);
         if (_tokenType != JsonTokenType.None && !_isNotPrimitive)
         {
             JsonThrowHelper.ThrowJsonWriterException(token, _tokenType);
         }
     }
 }
示例#20
0
        private void WriteStartUtf8Pretty(ReadOnlySpan <byte> nameSpanByte, int bytesNeeded, byte token)
        {
            int         indent     = _indent & RemoveFlagsBitMask;
            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);
        }
示例#21
0
        public bool TryGetValue(Utf8Span propertyName, out JsonObject value)
        {
            DbRow record = GetRecord(0);

            if (record.Length == 0)
            {
                JsonThrowHelper.ThrowKeyNotFoundException();
            }
            if (record.Type != JsonValueType.Object)
            {
                JsonThrowHelper.ThrowInvalidOperationException();
            }

            for (int i = DbRow.Size; i <= _database.Length; i += DbRow.Size)
            {
                record = GetRecord(i);

                if (!record.IsSimpleValue)
                {
                    i += record.Length * DbRow.Size;
                    continue;
                }

                if (_jsonData.Slice(record.Location, record.Length).SequenceEqual(propertyName.Bytes))
                {
                    int newStart = i + DbRow.Size;

                    record = GetRecord(newStart);

                    int newEnd = record.IsSimpleValue ? i + 2 * DbRow.Size : i + (record.Length + 2) * DbRow.Size;

                    value = new JsonObject(_jsonData, _database.Slice(newStart, newEnd - newStart));
                    return(true);
                }

                JsonValueType valueType = GetType(i + DbRow.Size);
                if (valueType > JsonValueType.Array)
                {
                    i += DbRow.Size;
                }
            }

            value = default;
            return(false);
        }
示例#22
0
        private bool ReadNext()
        {
            bool result = false;

            do
            {
                _consumed += _jsonReader.BytesConsumed;
                int leftOver     = _buffer.Length - (int)_jsonReader.BytesConsumed;
                int amountToRead = StreamSegmentSize;
                if (leftOver > 0)
                {
                    _stream.Position -= leftOver;

                    if (_jsonReader.BytesConsumed == 0)
                    {
                        if (leftOver > 1_000_000_000)
                        {
                            JsonThrowHelper.ThrowArgumentException("Cannot fit left over data from the previous chunk and the next chunk of data into a 2 GB buffer.");
                        }

                        // This is guaranteed to not overflow due to the check above.
                        amountToRead += leftOver * 2;
                        ResizeBuffer(amountToRead);
                    }
                }

                if (_pooledArray.Length < StreamSegmentSize)
                {
                    ResizeBuffer(StreamSegmentSize);
                }

                int numberOfBytes = _stream.Read(_pooledArray, 0, amountToRead);
                _isFinalBlock = numberOfBytes == 0; // TODO: Can this be inferred differently based on leftOver and numberOfBytes

                _buffer = _pooledArray.AsSpan(0, numberOfBytes);

                _jsonReader = new JsonUtf8Reader(_buffer, _isFinalBlock, _jsonReader.CurrentState);
                result      = _jsonReader.Read();
            } while (!result && !_isFinalBlock);

            return(result);
        }
示例#23
0
        private void WriteStart(ref ReadOnlySpan <byte> propertyName, byte token)
        {
            // TODO: Use throw helper with proper error messages
            if (propertyName.Length > JsonConstants.MaxTokenSize || CurrentDepth >= JsonConstants.MaxPossibleDepth)
            {
                JsonThrowHelper.ThrowJsonWriterOrArgumentException(propertyName, _currentDepth);
            }

            if (_writerOptions.SlowPath)
            {
                WriteStartSlow(ref propertyName, token);
            }
            else
            {
                WriteStartFast(ref propertyName, token);
            }

            _currentDepth &= JsonConstants.RemoveFlagsBitMask;
            _currentDepth++;
        }
示例#24
0
        public void WriteArray(ReadOnlySpan <byte> propertyName, ReadOnlySpan <DateTime> values)
        {
            // TODO: Use throw helper with proper error messages
            if (propertyName.Length > JsonConstants.MaxTokenSize || CurrentDepth >= JsonConstants.MaxPossibleDepth)
            {
                JsonThrowHelper.ThrowJsonWriterOrArgumentException(propertyName, _currentDepth);
            }

            if (_writerOptions.SlowPath)
            {
                WriteArraySlow(ref propertyName, ref values);
            }
            else
            {
                WriteArrayFast(ref propertyName, ref values);
            }

            _currentDepth |= 1 << 31;
            _tokenType     = JsonTokenType.EndArray;
        }
示例#25
0
        private void WriteStart(byte token)
        {
            // TODO: Use throw helper with proper error messages
            if (CurrentDepth >= JsonConstants.MaxWriterDepth)
            {
                JsonThrowHelper.ThrowJsonWriterException("Depth too large.");
            }

            if (_writerOptions.SlowPath)
            {
                WriteStartSlow(token);
            }
            else
            {
                WriteStartMinimized(token);
            }

            _currentDepth &= JsonConstants.RemoveFlagsBitMask;
            _currentDepth++;
            _isNotPrimitive = true;
        }
示例#26
0
        private void ValidateStart(byte token)
        {
            if (_inObject)
            {
                Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray);
                if (_tokenType != JsonTokenType.PropertyName)
                {
                    JsonThrowHelper.ThrowJsonWriterException(token, _tokenType);    //TODO: Add resource message
                }
            }
            else
            {
                Debug.Assert(_tokenType != JsonTokenType.StartObject);
                if (_tokenType == JsonTokenType.PropertyName || (_tokenType != JsonTokenType.None && !_isNotPrimitive))
                {
                    JsonThrowHelper.ThrowJsonWriterException(token, _tokenType);    //TODO: Add resource message
                }
            }

            UpdateBitStackOnStart(token);
        }
示例#27
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);
        }
示例#28
0
        private static void EscapeNextChars(ref ReadOnlySpan <char> value, int firstChar, ref Span <char> destination, ref int consumed, ref int written)
        {
            int nextChar = -1;

            if (InRange(firstChar, 0xD800, 0xDFFF))
            {
                consumed++;
                if (value.Length <= consumed || firstChar >= 0xDC00)
                {
                    JsonThrowHelper.ThrowJsonWriterException("Invalid UTF-16 string ending in an invalid surrogate pair.");
                }

                nextChar = value[consumed];
                if (!InRange(nextChar, 0xDC00, 0xDFFF))
                {
                    JsonThrowHelper.ThrowJsonWriterException("Invalid UTF-16 string ending in an invalid surrogate pair.");
                }
            }

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

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

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

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

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

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

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

            default:
                destination[written++] = 'u';
                WriteHex(firstChar, ref destination, ref written);
                if (nextChar != -1)
                {
                    destination[written++] = '\\';
                    destination[written++] = 'u';
                    WriteHex(nextChar, ref destination, ref written);
                }
                break;
            }
        }
示例#29
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);
        }
示例#30
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);
        }