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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #6
0
        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;
        }
예제 #9
0
        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;
        }
예제 #10
0
        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;
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
            }
        }
예제 #17
0
        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);
        }