示例#1
0
        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;
        }
示例#2
0
 public SequenceFormatter(TSequence buffers, SymbolTable symbolTable)
 {
     _symbolTable          = symbolTable;
     _buffers              = buffers;
     _currentPosition      = _buffers.First;
     _previousWrittenBytes = -1;
 }
示例#3
0
        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;
        }
示例#4
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);
        }
示例#5
0
        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);
        }