if (jsonData.IsSingleSegment)
{
_nextPosition = default;
- _currentPosition = default;
+ _currentPosition = jsonData.Start;
_isLastSegment = isFinalBlock;
_isSingleSegment = true;
}
else
{
- _nextPosition = jsonData.Start;
+ _currentPosition = jsonData.Start;
+ _nextPosition = _currentPosition;
if (_buffer.Length == 0)
{
+ // Once we find a non-empty segment, we need to set current position to it.
+ // Therefore, track the next position in a copy before it gets advanced to the next segment.
+ SequencePosition previousNextPosition = _nextPosition;
while (jsonData.TryGet(ref _nextPosition, out ReadOnlyMemory<byte> memory, advance: true))
{
+ // _currentPosition should point to the segment right befor the segment that _nextPosition points to.
+ _currentPosition = previousNextPosition;
if (memory.Length != 0)
{
_buffer = memory.Span;
break;
}
+ previousNextPosition = _nextPosition;
}
}
- _currentPosition = _nextPosition;
_isLastSegment = !jsonData.TryGet(ref _nextPosition, out _, advance: true) && isFinalBlock; // Don't re-order to avoid short-circuiting
_isSingleSegment = false;
}
int prevConsumed = _consumed;
long prevPosition = _bytePositionInLine;
long prevLineNumber = _lineNumber;
+ SequencePosition copy = _currentPosition;
retVal = ConsumePropertyNameMultiSegment();
if (!retVal)
{
_bytePositionInLine = prevPosition;
_lineNumber = prevLineNumber;
_totalConsumed = prevTotalConsumed;
+ _currentPosition = copy;
}
goto Done;
}
ReadOnlyMemory<byte> memory = default;
while (true)
{
+ Debug.Assert(_isSingleSegment || _currentPosition.GetObject() != null);
SequencePosition copy = _currentPosition;
_currentPosition = _nextPosition;
bool noMoreData = !_sequence.TryGet(ref _nextPosition, out memory, advance: true);
// _currentPosition needs to point to last non-empty segment
// Since memory.Length == 0, we need to revert back to previous.
_currentPosition = copy;
+ Debug.Assert(_isSingleSegment || _currentPosition.GetObject() != null);
}
if (_isFinalBlock)
case JsonCommentHandling.Allow:
if (marker == JsonConstants.Slash)
{
- return ConsumeCommentMultiSegment();
+ SequencePosition copy = _currentPosition;
+ if (!ConsumeCommentMultiSegment())
+ {
+ _currentPosition = copy;
+ return false;
+ }
+ return true;
}
break;
default:
Debug.Assert(_readerOptions.CommentHandling == JsonCommentHandling.Skip);
if (marker == JsonConstants.Slash)
{
+ SequencePosition copy = _currentPosition;
if (SkipCommentMultiSegment())
{
if (_consumed >= (uint)_buffer.Length)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive);
}
+ _currentPosition = copy;
return false;
}
}
SkipWhiteSpaceMultiSegment();
if (!HasMoreDataMultiSegment())
{
+ _currentPosition = copy;
return false;
}
marker = _buffer[_consumed];
// Skip comments and consume the actual JSON value.
continue;
}
+ _currentPosition = copy;
return false;
}
break;
int written = 0;
long prevTotalConsumed = _totalConsumed;
+ SequencePosition copy = _currentPosition;
if (span.Length >= literal.Length || IsLastSpan)
{
_bytePositionInLine += FindMismatch(span, literal);
{
_totalConsumed = prevTotalConsumed;
consumed = default;
+ _currentPosition = copy;
if (IsLastSpan)
{
goto Throw;
Throw:
_totalConsumed = prevTotalConsumed;
consumed = default;
+ _currentPosition = copy;
throw GetInvalidLiteralMultiSegment(readSoFar.Slice(0, written).ToArray());
}
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed - 1;
+ _currentPosition = startPosition;
if (IsLastSpan)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound);
int index = JsonConstants.EscapableChars.IndexOf(currentByte);
if (index == -1)
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAfterEscapeWithinString, currentByte);
}
byte nextByte = localBuffer[j];
if (!JsonReaderHelper.IsHexDigit(nextByte))
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidHexCharacterWithinString, nextByte);
}
if (j - idx > numberOfHexDigits)
if (!GetNextSpan())
{
+ _currentPosition = startPosition;
if (IsLastSpan)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound);
}
else if (currentByte < JsonConstants.Space)
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterWithinString, currentByte);
}
if (!GetNextSpan())
{
+ _currentPosition = startPosition;
if (IsLastSpan)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound);
int index = JsonConstants.EscapableChars.IndexOf(currentByte);
if (index == -1)
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAfterEscapeWithinString, currentByte);
}
byte nextByte = data[j];
if (!JsonReaderHelper.IsHexDigit(nextByte))
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidHexCharacterWithinString, nextByte);
}
if (j - idx > numberOfHexDigits)
if (!GetNextSpan())
{
+ _currentPosition = startPosition;
if (IsLastSpan)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound);
}
else if (currentByte < JsonConstants.Space)
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterWithinString, currentByte);
}
if (!GetNextSpan())
{
+ _currentPosition = startPosition;
if (IsLastSpan)
{
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound);
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
if (result == ConsumeNumberResult.Success)
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
if (result == ConsumeNumberResult.Success)
nextByte = data[i];
if (nextByte != '.' && nextByte != 'E' && nextByte != 'e')
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, nextByte);
}
}
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
if (result == ConsumeNumberResult.Success)
nextByte = data[i];
if (nextByte != 'E' && nextByte != 'e')
{
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedNextDigitEValueNotFound, nextByte);
}
}
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
_totalConsumed = prevTotalConsumed;
_bytePositionInLine = prevPosition;
_consumed = startConsumed;
+ _currentPosition = startPosition;
return false;
}
if (resultExponent == ConsumeNumberResult.Success)
Debug.Assert(resultExponent == ConsumeNumberResult.OperationIncomplete);
+ _currentPosition = startPosition;
ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, data[i]);
Done:
long prevPosition = _bytePositionInLine;
long prevLineNumber = _lineNumber;
JsonTokenType prevTokenType = _tokenType;
+ SequencePosition prevSequencePosition = _currentPosition;
ConsumeTokenResult result = ConsumeNextTokenMultiSegment(marker);
if (result == ConsumeTokenResult.Success)
{
_bytePositionInLine = prevPosition;
_lineNumber = prevLineNumber;
_totalConsumed = prevTotalConsumed;
+ _currentPosition = prevSequencePosition;
}
return false;
}
int prevConsumed = _consumed;
long prevPosition = _bytePositionInLine;
long prevLineNumber = _lineNumber;
+ SequencePosition copy = _currentPosition;
if (!ConsumePropertyNameMultiSegment())
{
// roll back potential changes
_bytePositionInLine = prevPosition;
_lineNumber = prevLineNumber;
_totalConsumed = prevTotalConsumed;
+ _currentPosition = copy;
goto IncompleteNoRollback;
}
goto Done;
byte[] dataUtf8 = Encoding.UTF8.GetBytes(jsonString);
ReadOnlyMemory<byte> dataMemory = dataUtf8;
- var sequences = new List<ReadOnlySequence<byte>>();
+ var sequences = new List<ReadOnlySequence<byte>>
+ {
+ new ReadOnlySequence<byte>(dataMemory)
+ };
for (int i = 0; i < dataUtf8.Length; i++)
{
{
Assert.Equal(expectedlineNumber, ex.LineNumber);
Assert.Equal(expectedBytePosition, ex.BytePositionInLine);
- byte[] consumed = dataUtf8.AsSpan(0, (int)json.BytesConsumed).ToArray();
- Assert.Equal(consumed, sequence.Slice(0, json.Position).ToArray());
- Assert.Equal(consumed, sequence.Slice(0, json.CurrentState.Position).ToArray());
}
}
}
public static void AllowCommentStackMismatchMultiSegment(string jsonString, string expectedWithoutComments, string expectedWithComments)
{
byte[] data = Encoding.UTF8.GetBytes(jsonString);
- ReadOnlySequence<byte> sequence = JsonTestHelper.GetSequence(data, 1);
+ var sequence = new ReadOnlySequence<byte>(data);
+ TestReadingJsonWithComments(data, sequence, expectedWithoutComments, expectedWithComments);
+
+ sequence = JsonTestHelper.GetSequence(data, 1);
TestReadingJsonWithComments(data, sequence, expectedWithoutComments, expectedWithComments);
var firstSegment = new BufferSegment<byte>(ReadOnlyMemory<byte>.Empty);
ReadOnlyMemory<byte> secondMem = data;
BufferSegment<byte> secondSegment = firstSegment.Append(secondMem);
sequence = new ReadOnlySequence<byte>(firstSegment, 0, secondSegment, secondMem.Length);
-
TestReadingJsonWithComments(data, sequence, expectedWithoutComments, expectedWithComments);
}
public static void SingleJsonValueMultiSegment(string jsonString, string expectedString)
{
byte[] dataUtf8 = Encoding.UTF8.GetBytes(jsonString);
- ReadOnlySequence<byte> sequence = JsonTestHelper.GetSequence(dataUtf8, 1);
+ var sequence = new ReadOnlySequence<byte>(dataUtf8);
+ TestReadingSingleValueJson(dataUtf8, sequence, expectedString);
+ sequence = JsonTestHelper.GetSequence(dataUtf8, 1);
TestReadingSingleValueJson(dataUtf8, sequence, expectedString);
var firstSegment = new BufferSegment<byte>(ReadOnlyMemory<byte>.Empty);
ReadOnlyMemory<byte> secondMem = dataUtf8;
BufferSegment<byte> secondSegment = firstSegment.Append(secondMem);
sequence = new ReadOnlySequence<byte>(firstSegment, 0, secondSegment, secondMem.Length);
-
TestReadingSingleValueJson(dataUtf8, sequence, expectedString);
}