void IOutput.Advance(int bytes) { var current = Current; if (NeedShift) { var previous = Previous; var spaceInPrevious = previous.Length - _previousWrittenBytes; if (spaceInPrevious < bytes) { current.Slice(0, spaceInPrevious).Span.CopyTo(previous.Span.Slice(_previousWrittenBytes)); current.Slice(spaceInPrevious, bytes - spaceInPrevious).Span.CopyTo(current.Span); _previousWrittenBytes = -1; _currentWrittenBytes = bytes - spaceInPrevious; } else { current.Slice(0, bytes).Span.CopyTo(previous.Span.Slice(_previousWrittenBytes)); _currentPosition = _previousPosition; _currentWrittenBytes = _previousWrittenBytes + bytes; } } else { if (current.Length - _currentWrittenBytes < bytes) { throw new NotImplementedException(); } _currentWrittenBytes += bytes; } _totalWritten += bytes; }
public SequenceFormatter(TSequence buffers, SymbolTable symbolTable) { _symbolTable = symbolTable; _buffers = buffers; _currentPosition = _buffers.First; _previousWrittenBytes = -1; }
void IOutput.Enlarge(int desiredBufferLength) { if (NeedShift) { throw new NotImplementedException("need to allocate temp array"); } _previousPosition = _currentPosition; _previousWrittenBytes = _currentWrittenBytes; if (!_buffers.TryGet(ref _currentPosition, out Memory <byte> span)) { throw new InvalidOperationException(); } _currentWrittenBytes = 0; }
public bool TryGet(ref Position position, out ReadOnlyMemory <byte> item, bool advance = true) { if (position == default) { item = default; return(false); } var(buffer, index) = position.Get <BufferSequence>(); item = buffer.WrittenMemory.Slice(index); if (advance) { position = Position.Create(buffer._next); } return(true); }
public static bool TryParseUInt64 <T>(this T bufferSequence, out ulong value, out int consumed) where T : ISequence <ReadOnlyMemory <byte> > { value = default; consumed = default; Position position = default; // Fetch the first segment if (!bufferSequence.TryGet(ref position, out ReadOnlyMemory <byte> first)) { return(false); } // Attempt to parse the first segment. If it works (and it should in most cases), then return success. bool parsed = Utf8Parser.TryParse(first.Span, out value, out consumed); if (parsed && consumed < first.Length) { return(true); } // Apparently the we need data from the second segment to succesfully parse, and so fetch the second segment. if (!bufferSequence.TryGet(ref position, out ReadOnlyMemory <byte> second)) { // if there is no second segment and the first parsed succesfully, return the result of the parsing. if (parsed) { return(true); } return(false); } // Combine the first, the second, and potentially more segments into a stack allocated buffer if (first.Length < StackBufferSize) { Span <byte> destination = stackalloc byte[StackBufferSize]; first.Span.CopyTo(destination); var free = destination.Slice(first.Length); if (second.Length > free.Length) { second = second.Slice(0, free.Length); } second.Span.CopyTo(free); free = free.Slice(second.Length); while (free.Length > 0) { if (bufferSequence.TryGet(ref position, out ReadOnlyMemory <byte> next)) { if (next.Length > free.Length) { next = next.Slice(0, free.Length); } next.Span.CopyTo(free); free = free.Slice(next.Length); } else { break; } } var combinedStackSpan = destination.Slice(0, StackBufferSize - free.Length); // if the stack allocated buffer parsed succesfully (and for uint it should always do), then return success. if (Utf8Parser.TryParse(combinedStackSpan, out value, out consumed)) { if (consumed < combinedStackSpan.Length || combinedStackSpan.Length < StackBufferSize) { return(true); } } } // for invariant culture, we should never reach this point, as invariant uint text is never longer than 127 bytes. // I left this code here, as we will need it for custom cultures and possibly when we shrink the stack allocated buffer. var combinedSpan = bufferSequence.ToSpan(); if (!Utf8Parser.TryParse(combinedSpan, out value, out consumed)) { return(false); } return(true); }