示例#1
0
        public void ReadOnlyFrontBytesEnumeration()
        {
            for (int i = 0; i < 7; i++)
            {
                var multibytes = Parse("A|CD|EFG");
                multibytes = multibytes.Slice(0, i);

                {
                    Collections.Sequences.Position position = multibytes.First;
                    var length = 0;
                    while (multibytes.TryGet(ref position, out ReadOnlyMemory <byte> segment))
                    {
                        length += segment.Length;
                    }
                    Assert.Equal(i, length);
                }
                //{
                //    var length = 0;
                //    foreach (var segment in multibytes)
                //    {
                //        length += segment.Length;
                //    }
                //    Assert.Equal(i, length);
                //}
            }
        }
示例#2
0
        public void ReadOnlyBytesEnumeration()
        {
            var buffer = new byte[] { 1, 2, 3, 4, 5, 6 };
            var bytes  = new ReadOnlyBytes(buffer);

            Collections.Sequences.Position position = bytes.First;
            int length = 0;
            ReadOnlyMemory <byte> segment;

            while (bytes.TryGet(ref position, out segment))
            {
                length += segment.Length;
            }
            Assert.Equal(buffer.Length, length);

            var multibytes = Parse("A|CD|EFG");

            position = multibytes.First;
            length   = 0;
            while (multibytes.TryGet(ref position, out segment))
            {
                length += segment.Length;
            }
            Assert.Equal(6, length);
        }
示例#3
0
        public ReadWriteBytes(Collections.Sequences.Position first, Collections.Sequences.Position last)
        {
            (_start, _startIndex) = first.Get <object>();
            (_end, _endIndex)     = last.Get <object>();

            Validate();
        }
示例#4
0
        Collections.Sequences.Position? AdvanceToDelimiter(byte value)
        {
            var unread = Unread;
            var index  = unread.IndexOf(value);

            if (index != -1)
            {
                _currentSpanIndex += index;
                var result = _currentSegmentPosition + _currentSpanIndex;
                _currentSpanIndex++; // skip delimiter
                return(result);
            }

            var nextPosition     = _nextSegmentPosition;
            var currentPosition  = _currentSegmentPosition;
            var previousPosition = _nextSegmentPosition;

            while (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory))
            {
                var span = memory.Span;
                index = span.IndexOf(value);
                if (index != -1)
                {
                    _currentSegmentPosition = previousPosition;
                    _currentSpan            = span;
                    _currentSpanIndex       = index + 1;
                    return(_currentSegmentPosition + index);
                }
                previousPosition = _nextSegmentPosition;
            }

            _nextSegmentPosition    = nextPosition;
            _currentSegmentPosition = currentPosition;
            return(null);
        }
示例#5
0
        public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemory <byte> item, bool advance = true)
        {
            var result = TryGet(ref position, out Memory <byte> memory, advance);

            item = memory;
            return(result);
        }
示例#6
0
        public int CopyTo(Span <byte> buffer)
        {
            int copied = 0;

            Collections.Sequences.Position position = default;
            var free = buffer;

            while (TryGet(ref position, out ReadOnlyMemory <byte> segment, true))
            {
                if (segment.Length > free.Length)
                {
                    segment.Span.Slice(0, free.Length).CopyTo(free);
                    copied += free.Length;
                }
                else
                {
                    segment.Span.CopyTo(free);
                    copied += segment.Length;
                }
                free = buffer.Slice(copied);
                if (free.Length == 0)
                {
                    break;
                }
            }
            return(copied);
        }
示例#7
0
 public BufferReader(ReadOnlySpan <byte> bytes)
 {
     _bytes = default;
     _nextSegmentPosition    = default;
     _currentSegmentPosition = 0;
     _currentSpan            = bytes;
     _currentSpanIndex       = 0;
 }
示例#8
0
        public static bool TryParse <TSequence>(TSequence sequence, out int value, out Collections.Sequences.Position consumed) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            if (!TryParse(sequence, out value, out int consumedBytes))
            {
                consumed = default;
                return(false);
            }

            consumed = sequence.PositionAt(consumedBytes).GetValueOrDefault();
            return(true);
        }
示例#9
0
        public static string Utf8ToString <TSequence>(this TSequence bytes) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            var sb = new StringBuilder();

            Collections.Sequences.Position position = bytes.First;
            while (bytes.TryGet(ref position, out ReadOnlyMemory <byte> segment))
            {
                sb.Append(new Utf8Span(segment.Span).ToString());
            }
            return(sb.ToString());
        }
示例#10
0
        public static ReadOnlySpan <byte> ToSpan <T>(this T sequence) where T : ISequence <ReadOnlyMemory <byte> >
        {
            Collections.Sequences.Position position = sequence.First;
            ResizableArray <byte>          array    = new ResizableArray <byte>(1024);

            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> buffer))
            {
                array.AddAll(buffer.Span);
            }
            array.Resize(array.Count);
            return(array.Span.Slice(0, array.Count));
        }
示例#11
0
 public void Advance(Collections.Sequences.Position position)
 {
     _currentSegmentPosition = position;
     _nextSegmentPosition    = position;
     if (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory))
     {
         _currentSpan = memory.Span;
     }
     else
     {
         _currentSpan = default;
     }
     _currentSpanIndex = 0;
 }
示例#12
0
 // TODO: should there be a ctor that takes sequence + position?
 // TODO: should there be a type that is sequence + position?
 public BufferReader(TSequence bytes)
 {
     _bytes = bytes;
     _nextSegmentPosition    = bytes.First;
     _currentSegmentPosition = _nextSegmentPosition;
     if (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory))
     {
         _currentSpan = memory.Span;
     }
     else
     {
         _currentSpan = ReadOnlySpan <byte> .Empty;
     }
     _currentSpanIndex = 0;
 }
示例#13
0
        public bool TryGet(ref Collections.Sequences.Position position, out Memory <byte> item, bool advance = true)
        {
            if (position == default)
            {
                item = default;
                return(false);
            }

            var(list, index) = position.Get <MemoryList>();
            item             = list._data.Slice(index);
            if (advance)
            {
                position = Collections.Sequences.Position.Create(list._next);
            }
            return(true);
        }
示例#14
0
        public ReadWriteBytes Slice(Collections.Sequences.Position position)
        {
            var kind = Kind;

            switch (kind)
            {
            case Type.Array:
                var(array, index) = position.Get <byte[]>();
                return(new ReadWriteBytes(array, index, array.Length - index));

            case Type.MemoryList:
                return(Slice(position, Collections.Sequences.Position.Create((IMemoryList <byte>)_end, _endIndex)));

            default: throw new NotImplementedException();
            }
        }
示例#15
0
        // TODO: this cannot be an extension method (as I would like it to be).
        // If I make it an extensions method, the compiler complains Span<T> cannot
        // be used as a type parameter.
        public static long IndexOf <TSequence>(TSequence sequence, byte value) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            Collections.Sequences.Position position = sequence.First;
            int totalIndex = 0;

            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory))
            {
                var index = memory.Span.IndexOf(value);
                if (index != -1)
                {
                    return(index + totalIndex);
                }
                totalIndex += memory.Length;
            }
            return(-1);
        }
示例#16
0
        public bool TryGet(ref Collections.Sequences.Position position, out Memory <byte> item, bool advance = true)
        {
            if (position == default)
            {
                item = default;
                return(false);
            }

            var array = _start as byte[];

            if (array != null)
            {
                var start  = _startIndex + (int)position;
                var length = _endIndex - _startIndex - (int)position;
                item = new Memory <byte>(array, start, length);
                if (advance)
                {
                    position = default;
                }
                return(true);
            }

            if (Kind == Type.MemoryList)
            {
                var(node, index) = position.Get <IMemoryList <byte> >();
                item             = node.Memory.Slice(index);
                if (ReferenceEquals(node, _end))
                {
                    item = item.Slice(0, _endIndex - index);
                    if (advance)
                    {
                        position = default;
                    }
                }
                else
                {
                    if (advance)
                    {
                        position = Collections.Sequences.Position.Create(node.Next);
                    }
                }
                return(true);
            }

            throw new NotImplementedException();
        }
示例#17
0
        public static int Copy <TSequence>(TSequence sequence, Collections.Sequences.Position from, Span <byte> buffer) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            int copied = 0;

            while (sequence.TryGet(ref from, out ReadOnlyMemory <byte> memory, true))
            {
                var span   = memory.Span;
                var toCopy = Math.Min(span.Length, buffer.Length - copied);
                span.Slice(0, toCopy).CopyTo(buffer.Slice(copied));
                copied += toCopy;
                if (copied >= buffer.Length)
                {
                    break;
                }
            }
            return(copied);
        }
示例#18
0
        public static string ToString <TSequence>(this TSequence bytes, SymbolTable symbolTable) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            var sb = new StringBuilder();

            if (symbolTable == SymbolTable.InvariantUtf8)
            {
                Collections.Sequences.Position position = bytes.First;
                while (bytes.TryGet(ref position, out ReadOnlyMemory <byte> segment))
                {
                    sb.Append(new Utf8Span(segment.Span).ToString());
                }
            }
            else
            {
                throw new NotImplementedException();
            }
            return(sb.ToString());
        }
示例#19
0
        public ReadWriteBytes Slice(Collections.Sequences.Position start, Collections.Sequences.Position end)
        {
            var kind = Kind;

            switch (kind)
            {
            case Type.Array:
                var(array, index) = start.Get <byte[]>();
                return(new ReadWriteBytes(array, index, (int)end - index));

            case Type.MemoryList:
                var(startList, startIndex) = start.Get <IMemoryList <byte> >();
                var(endList, endIndex)     = end.Get <IMemoryList <byte> >();
                return(new ReadWriteBytes(startList, startIndex, endList, endIndex));

            default:
                throw new NotImplementedException();
            }
        }
示例#20
0
        public static long IndexOf <TSequence>(TSequence sequence, byte v1, byte v2) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            Collections.Sequences.Position position = sequence.First;
            int totalIndex = 0;

            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory))
            {
                var span  = memory.Span;
                var index = span.IndexOf(v1);
                if (index != -1)
                {
                    if (span.Length > index + 1)
                    {
                        if (span[index + 1] == v2)
                        {
                            return(index + totalIndex);
                        }
                        else
                        {
                            throw new NotImplementedException();  // need to check farther in the span
                        }
                    }
                    else
                    {
                        if (sequence.TryGet(ref position, out var next, false))
                        {
                            var nextSpan = next.Span;
                            if (nextSpan.Length > 0)
                            {
                                if (next.Span[0] == v2)
                                {
                                    return(totalIndex + index);
                                }
                            }
                        }
                    }
                }
                totalIndex += memory.Length;
            }
            return(-1);
        }
示例#21
0
        public static Collections.Sequences.Position?PositionOf <TSequence>(this TSequence sequence, byte value) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            if (sequence == null)
            {
                return(null);
            }

            Collections.Sequences.Position position = sequence.First;
            Collections.Sequences.Position result   = position;
            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory))
            {
                var index = MemoryExtensions.IndexOf(memory.Span, value);
                if (index != -1)
                {
                    result += index;
                    return(result);
                }
                result = position;
            }
            return(null);
        }
示例#22
0
        public static Collections.Sequences.Position?PositionAt <TSequence>(this TSequence sequence, long index) where TSequence : ISequence <ReadOnlyMemory <byte> >
        {
            if (sequence == null)
            {
                return(null);
            }

            Collections.Sequences.Position position = sequence.First;
            Collections.Sequences.Position result   = position;
            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory))
            {
                var span = memory.Span;
                if (span.Length > index)
                {
                    result += (int)index;
                    return(result);
                }
                index -= span.Length;
                result = position;
            }

            return(null);
        }
示例#23
0
        public static void Pipe(this IBufferOperation transformation, ReadOnlyBytes source, IOutput destination)
        {
            int afterMergeSlice = 0;

            // Assign 'remainder' to something formally stack-referring.
            // The default classification is "returnable, not referring to stack", we want the opposite in this case.
            ReadOnlySpan <byte> remainder = stackalloc byte[0];
            Span <byte>         stackSpan = stackalloc byte[stackLength];

            Collections.Sequences.Position poisition = default;
            while (source.TryGet(ref poisition, out var sourceBuffer))
            {
                Span <byte>         outputSpan = destination.GetSpan();
                ReadOnlySpan <byte> sourceSpan = sourceBuffer.Span;

                if (!remainder.IsEmpty)
                {
                    int leftOverBytes = remainder.Length;
                    remainder.CopyTo(stackSpan);
                    int amountToCopy = Math.Min(sourceSpan.Length, stackSpan.Length - leftOverBytes);
                    sourceSpan.Slice(0, amountToCopy).CopyTo(stackSpan.Slice(leftOverBytes));
                    int amountOfData = leftOverBytes + amountToCopy;

                    Span <byte> spanToTransform = stackSpan.Slice(0, amountOfData);

TryTransformWithRemainder:
                    OperationStatus status = transformation.Execute(spanToTransform, outputSpan, out int bytesConsumed, out int bytesWritten);
                    if (status != OperationStatus.Done)
                    {
                        destination.Advance(bytesWritten);
                        spanToTransform = spanToTransform.Slice(bytesConsumed);

                        if (status == OperationStatus.DestinationTooSmall)
                        {
                            destination.Enlarge();  // output buffer is too small
                            outputSpan = destination.GetSpan();

                            if (outputSpan.Length - bytesWritten < 3)
                            {
                                return; // no more output space, user decides what to do.
                            }
                            goto TryTransformWithRemainder;
                        }
                        else
                        {
                            if (status == OperationStatus.InvalidData)
                            {
                                continue; // source buffer contains invalid bytes, user decides what to do for fallback
                            }

                            // at this point, status = TransformationStatus.NeedMoreSourceData
                            // left over bytes in stack span
                            remainder = spanToTransform;
                        }
                        continue;
                    }
                    else    // success
                    {
                        afterMergeSlice = bytesConsumed - remainder.Length;
                        remainder       = Span <byte> .Empty;
                        destination.Advance(bytesWritten);
                        outputSpan = destination.GetSpan();
                    }
                }

TryTransform:
                OperationStatus result = transformation.Execute(sourceSpan.Slice(afterMergeSlice), outputSpan, out int consumed, out int written);
                afterMergeSlice        = 0;
                destination.Advance(written);
                sourceSpan = sourceSpan.Slice(consumed);

                if (result == OperationStatus.Done)
                {
                    continue;
                }

                // Not successful
                if (result == OperationStatus.DestinationTooSmall)
                {
                    destination.Enlarge();  // output buffer is too small
                    outputSpan = destination.GetSpan();
                    if (outputSpan.Length - written < 3)
                    {
                        return; // no more output space, user decides what to do.
                    }
                    goto TryTransform;
                }
                else
                {
                    if (result == OperationStatus.InvalidData)
                    {
                        continue; // source buffer contains invalid bytes, user decides what to do for fallback
                    }

                    // at this point, result = TransformationStatus.NeedMoreSourceData
                    // left over bytes in source span
                    remainder = sourceSpan;
                }
            }
            return;
        }
示例#24
0
 public PositionRange(Collections.Sequences.Position start, Collections.Sequences.Position end)
 {
     Start = start;
     End   = end;
 }