Esempio n. 1
0
 public ReadOnlyBytes(IMemoryList <byte> segments, long length)
 {
     // TODO: should we skip all empty buffers, i.e. of _first.IsEmpty?
     _first = segments.Memory;
     _all   = segments;
     _totalLengthOrVirtualIndex = length;
 }
Esempio n. 2
0
 private ReadOnlyBytes(ReadOnlyMemory <byte> first, IMemoryList <byte> all, long length)
 {
     // TODO: add assert that first overlaps all (once we have Overlap on Span)
     _first = first;
     _all   = all;
     _totalLengthOrVirtualIndex = _all == null ? 0 : length;
 }
Esempio n. 3
0
        /// <summary>
        /// Creates an instance of <see cref="ReadOnlySequence{T}"/> from linked memory list represented by start and end segments
        /// and corresponding indexes in them.
        /// </summary>
        public ReadOnlySequence(IMemoryList <T> startSegment, int startIndex, IMemoryList <T> endSegment, int endIndex)
        {
            if (startSegment == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.startSegment);
            }
            if (endSegment == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endSegment);
            }
            if (startIndex < 0 || startSegment.Memory.Length < startIndex)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex);
            }
            if (endIndex < 0 || endSegment.Memory.Length < endIndex)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.endIndex);
            }
            if (startSegment == endSegment && endIndex < startIndex)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.endIndex);
            }

            _sequenceStart = new SequencePosition(startSegment, startIndex | MemoryListStartMask);
            _sequenceEnd   = new SequencePosition(endSegment, endIndex | MemoryListEndMask);
        }
Esempio n. 4
0
        public static long IndexOf(this IMemoryList <byte> sequence, byte value)
        {
            var  first = sequence.Memory.Span;
            long index = first.IndexOf(value);

            if (index != -1)
            {
                return(index);
            }

            Position position     = default;
            int      virtualIndex = first.Length;

            while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory))
            {
                index = memory.Span.IndexOf(value);
                if (index != -1)
                {
                    return(index + virtualIndex);
                }
                virtualIndex += memory.Length;
            }

            return(-1);
        }
Esempio n. 5
0
        private void BoundsCheck(SequencePosition start, SequencePosition position)
        {
            int          startIndex = start.Index;
            int          endIndex   = position.Index;
            SequenceType type       = GetSequenceType();

            startIndex = GetIndex(startIndex);
            endIndex   = GetIndex(endIndex);

            switch (type)
            {
            case SequenceType.OwnedMemory:
            case SequenceType.Array:
                if (endIndex > startIndex)
                {
                    ThrowHelper.ThrowArgumentOutOfRangeException_PositionOutOfRange();
                }
                return;

            case SequenceType.MemoryList:
                IMemoryList <T> segment    = (IMemoryList <T>)position.Segment;
                IMemoryList <T> memoryList = (IMemoryList <T>)start.Segment;

                if (segment.RunningIndex - startIndex > memoryList.RunningIndex - endIndex)
                {
                    ThrowHelper.ThrowArgumentOutOfRangeException_PositionOutOfRange();
                }
                return;

            default:
                ThrowHelper.ThrowInvalidOperationException_UnexpectedSegmentType();
                return;
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Get <see cref="IMemoryList{T}"/> from the underlying <see cref="ReadOnlySequence{T}"/>.
 /// If unable to get the <see cref="IMemoryList{T}"/>, return false.
 /// </summary>
 public static bool TryGetMemoryList <T>(ReadOnlySequence <T> sequence,
                                         out IMemoryList <T> startSegment,
                                         out int startIndex,
                                         out IMemoryList <T> endSegment,
                                         out int endIndex)
 {
     return(sequence.TryGetMemoryList(out startSegment, out startIndex, out endSegment, out endIndex));
 }
Esempio n. 7
0
        public ReadWriteBytes(IMemoryList <byte> first, IMemoryList <byte> last)
        {
            _start      = first;
            _startIndex = 0;
            _end        = last;
            _endIndex   = last.Memory.Length;

            Validate();
        }
Esempio n. 8
0
        public ReadOnlyBuffer(IMemoryList <T> startSegment, int offset, IMemoryList <T> endSegment, int endIndex)
        {
            Debug.Assert(startSegment != null);
            Debug.Assert(endSegment != null);
            Debug.Assert(startSegment.Memory.Length >= offset);
            Debug.Assert(endSegment.Memory.Length >= endIndex);

            BufferStart = new SequencePosition(startSegment, offset | MemoryListStartMask);
            BufferEnd   = new SequencePosition(endSegment, endIndex | MemoryListEndMask);
        }
Esempio n. 9
0
        public BufferSegment Append(Memory <byte> memory)
        {
            var segment = new BufferSegment(memory)
            {
                RunningIndex = RunningIndex + Memory.Length
            };

            Next = segment;
            return(segment);
        }
Esempio n. 10
0
        internal ReadableBuffer(IMemoryList <byte> startSegment, int startIndex, IMemoryList <byte> endSegment, int endIndex)
        {
            Debug.Assert(startSegment != null);
            Debug.Assert(endSegment != null);
            Debug.Assert(startSegment.Memory.Length >= startIndex);
            Debug.Assert(endSegment.Memory.Length >= endIndex);

            BufferStart = new ReadCursor(startSegment, startIndex);
            BufferEnd   = new ReadCursor(endSegment, endIndex);
        }
Esempio n. 11
0
        public ReadOnlyBuffer(IMemoryList <byte> startSegment, int offset, IMemoryList <byte> endSegment, int endIndex)
        {
            Debug.Assert(startSegment != null);
            Debug.Assert(endSegment != null);
            Debug.Assert(startSegment.Memory.Length >= offset);
            Debug.Assert(endSegment.Memory.Length >= endIndex);

            BufferStart = new Position(startSegment, offset);
            BufferEnd   = new Position(endSegment, endIndex);
        }
Esempio n. 12
0
        private static long GetLength(IMemoryList <T> start, int startIndex, IMemoryList <T> endSegment, int endIndex)
        {
            if (start == endSegment)
            {
                return(endIndex - startIndex);
            }

            return((endSegment.RunningIndex - start.Next.RunningIndex) // Length of data in between first and last segment
                   + (start.Memory.Length - startIndex)                // Length of data in first segment
                   + endIndex);                                        // Length of data in last segment
        }
Esempio n. 13
0
 public static Position PositionOf(this IMemoryList <byte> sequence, byte value)
 {
     while (sequence != null)
     {
         var index = sequence.Memory.Span.IndexOf(value);
         if (index != -1)
         {
             return(Position.Create(index, sequence));
         }
         sequence = sequence.Rest;
     }
     return(Position.End);
 }
Esempio n. 14
0
 public static Position?PositionOf(this IMemoryList <byte> list, byte value)
 {
     while (list != null)
     {
         var current = list.Memory.Span;
         var index   = current.IndexOf(value);
         if (index != -1)
         {
             return(Position.Create(list, index));
         }
         list = list.Next;
     }
     return(null);
 }
Esempio n. 15
0
        /// <summary>
        /// Creates an instance of <see cref="ReadOnlySequence{T}"/> from linked memory list represented by start and end segments
        /// and corresponding indexes in them.
        /// </summary>
        public ReadOnlySequence(IMemoryList <T> startSegment, int startIndex, IMemoryList <T> endSegment, int endIndex)
        {
            if (startSegment == null ||
                endSegment == null ||
                (uint)startSegment.Memory.Length < (uint)startIndex ||
                (uint)endSegment.Memory.Length < (uint)endIndex ||
                (startSegment == endSegment && endIndex < startIndex))
            {
                ThrowHelper.ThrowArgumentValidationException(startSegment, startIndex, endSegment);
            }

            _sequenceStart = new SequencePosition(startSegment, ReadOnlySequence.MemoryListToSequenceStart(startIndex));
            _sequenceEnd   = new SequencePosition(endSegment, ReadOnlySequence.MemoryListToSequenceEnd(endIndex));
        }
Esempio n. 16
0
        private static SequencePosition SeekMultiSegment(IMemoryList <byte> start, int startIndex, IMemoryList <byte> end, int endPosition, long count, bool checkEndReachable)
        {
            SequencePosition   result      = default;
            bool               foundResult = false;
            IMemoryList <byte> current     = start;
            int currentIndex = startIndex;

            while (current != null)
            {
                // We need to loop up until the end to make sure start and end are connected
                // if end is not trusted
                if (!foundResult)
                {
                    var isEnd         = current == end;
                    int currentEnd    = isEnd ? endPosition : current.Memory.Length;
                    int currentLength = currentEnd - currentIndex;

                    // We would prefer to put position in the beginning of next segment
                    // then past the end of previous one, but only if we are not leaving current buffer
                    if (currentLength > count ||
                        (currentLength == count && isEnd))
                    {
                        result      = new SequencePosition(current, currentIndex + (int)count);
                        foundResult = true;
                        if (!checkEndReachable)
                        {
                            break;
                        }
                    }

                    count -= currentLength;
                }

                if (current.Next == null && current != end)
                {
                    ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
                }

                current      = current.Next;
                currentIndex = 0;
            }

            if (!foundResult)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException_CountOutOfRange();
            }

            return(result);
        }
Esempio n. 17
0
        private static SequencePosition SeekMultiSegment(IMemoryList <byte> start, int startIndex, IMemoryList <byte> end, int endPosition, long bytes, bool checkEndReachable)
        {
            SequencePosition result = default(SequencePosition);
            var foundResult         = false;
            var current             = start;
            var currentIndex        = startIndex;

            while (current != null)
            {
                // We need to loop up until the end to make sure start and end are connected
                // if end is not trusted
                if (!foundResult)
                {
                    var memory     = current.Memory;
                    var currentEnd = current == end ? endPosition : memory.Length;

                    memory = memory.Slice(0, currentEnd - currentIndex);
                    // We would prefer to put cursor in the beginning of next segment
                    // then past the end of previous one, but only if we are not leaving current buffer
                    if (memory.Length > bytes ||
                        (memory.Length == bytes && current == end))
                    {
                        result      = new SequencePosition(current, currentIndex + (int)bytes);
                        foundResult = true;
                        if (!checkEndReachable)
                        {
                            break;
                        }
                    }

                    bytes -= memory.Length;
                }

                if (current.Next == null && current != end)
                {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached);
                }

                current      = current.Next;
                currentIndex = 0;
            }

            if (!foundResult)
            {
                ThrowHelper.ThrowCursorOutOfBoundsException();
            }

            return(result);
        }
Esempio n. 18
0
        private static long GetLength(
            IMemoryList <T> start,
            int startIndex,
            IMemoryList <T> endSegment,
            int endIndex)
        {
            if (start == endSegment)
            {
                return(endIndex - startIndex);
            }

            return((endSegment.RunningIndex - start.Next.RunningIndex)
                   + (start.Memory.Length - startIndex)
                   + endIndex);
        }
Esempio n. 19
0
        internal bool TryGetMemoryList(out IMemoryList <T> startSegment, out int startIndex, out IMemoryList <T> endSegment, out int endIndex)
        {
            if (Start.GetObject() == null || GetSequenceType() != SequenceType.MemoryList)
            {
                startSegment = null;
                endSegment   = null;
                startIndex   = 0;
                endIndex     = 0;
                return(false);
            }

            startIndex   = GetIndex(Start.GetInteger());
            endIndex     = GetIndex(End.GetInteger());
            startSegment = (IMemoryList <T>)Start.GetObject();
            endSegment   = (IMemoryList <T>)End.GetObject();
            return(true);
        }
Esempio n. 20
0
 private static Exception CreateArgumentValidationException <T>(IMemoryList <T> startSegment, int startIndex, IMemoryList <T> endSegment)
 {
     if (startSegment == null)
     {
         return(CreateArgumentNullException(ExceptionArgument.startSegment));
     }
     else if (endSegment == null)
     {
         return(CreateArgumentNullException(ExceptionArgument.endSegment));
     }
     else if ((uint)startSegment.Memory.Length < (uint)startIndex)
     {
         return(CreateArgumentOutOfRangeException(ExceptionArgument.startIndex));
     }
     else
     {
         return(CreateArgumentOutOfRangeException(ExceptionArgument.endIndex));
     }
 }
Esempio n. 21
0
        public static long IndexOf(this IMemoryList <byte> list, ReadOnlySpan <byte> value)
        {
            var first = list.Memory.Span;
            var index = first.IndexOf(value);

            if (index != -1)
            {
                return(index);
            }

            var rest = list.Next;

            if (rest == null)
            {
                return(-1);
            }

            return(IndexOfStraddling(first, list.Next, value));
        }
Esempio n. 22
0
        public static int CopyTo(this IMemoryList <byte> list, Span <byte> destination)
        {
            var current = list.Memory.Span;
            int copied  = 0;

            while (destination.Length > 0)
            {
                if (current.Length >= destination.Length)
                {
                    current.Slice(0, destination.Length).CopyTo(destination);
                    copied += destination.Length;
                    return(copied);
                }
                else
                {
                    current.CopyTo(destination);
                    copied     += current.Length;
                    destination = destination.Slice(current.Length);
                }
            }
            return(copied);
        }
Esempio n. 23
0
 public ReadWriteBytes(IMemoryList <byte> segments) :
     this(segments.First, segments.Rest, Unspecified)
 {
 }
Esempio n. 24
0
 //
 // ReadOnlySequence .ctor validation Throws coalesced to enable inlining of the .ctor
 //
 public static void ThrowArgumentValidationException <T>(IMemoryList <T> startSegment, int startIndex, IMemoryList <T> endSegment)
 => throw CreateArgumentValidationException(startSegment, startIndex, endSegment);
Esempio n. 25
0
 long IndexOf(IMemoryList <byte> sequence, byte value)
 => sequence.IndexOf(value);
Esempio n. 26
0
        internal bool TryGetBuffer(SequencePosition start, SequencePosition end, out ReadOnlyMemory <T> data, out SequencePosition next)
        {
            if (start.Segment == null)
            {
                data = default;
                next = default;
                return(false);
            }

            int          startIndex = start.Index;
            int          endIndex   = end.Index;
            SequenceType type       = GetSequenceType();

            startIndex = GetIndex(startIndex);
            endIndex   = GetIndex(endIndex);

            switch (type)
            {
            case SequenceType.MemoryList:
                var        segment             = (IMemoryList <T>)start.Segment;
                Memory <T> bufferSegmentMemory = segment.Memory;
                int        currentEndIndex     = bufferSegmentMemory.Length;

                if (segment == end.Segment)
                {
                    currentEndIndex = endIndex;
                    next            = default;
                }
                else
                {
                    IMemoryList <T> nextSegment = segment.Next;
                    if (nextSegment == null)
                    {
                        if (end.Segment != null)
                        {
                            ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
                        }

                        next = default;
                    }
                    else
                    {
                        next = new SequencePosition(nextSegment, 0);
                    }
                }

                data = bufferSegmentMemory.Slice(startIndex, currentEndIndex - startIndex);
                return(true);

            case SequenceType.OwnedMemory:
                var ownedMemory = (OwnedMemory <T>)start.Segment;
                if (ownedMemory != end.Segment)
                {
                    ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
                }

                data = ownedMemory.Memory.Slice(startIndex, endIndex - startIndex);
                next = default;
                return(true);

            case SequenceType.Array:
                var array = (T[])start.Segment;

                if (array != end.Segment)
                {
                    ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
                }

                data = new Memory <T>(array, startIndex, endIndex - startIndex);
                next = default;
                return(true);

            default:
                ThrowHelper.ThrowInvalidOperationException_UnexpectedSegmentType();
                next = default;
                data = default;
                return(false);
            }
        }
Esempio n. 27
0
 public ReadWriteBytes(Memory <byte> first, IMemoryList <byte> rest) :
     this(first, rest, Unspecified)
 {
 }
Esempio n. 28
0
 public ReadWriteBytes(IMemoryList <byte> segments, int length) :
     this(segments.First, segments.Rest, length)
 {
 }
Esempio n. 29
0
        // TODO (pri 3): I am pretty sure this whole routine can be written much better

        // searches values that potentially straddle between first and rest
        internal static long IndexOfStraddling(this ReadOnlySpan <byte> first, IMemoryList <byte> rest, ReadOnlySpan <byte> value)
        {
            Debug.Assert(first.IndexOf(value) == -1);
            if (rest == null)
            {
                return(-1);
            }

            // we only need to search the end of the first buffer. More precisely, only up to value.Length - 1 bytes in the first buffer
            // The other bytes in first, were already search and presumably did not match
            int bytesToSkipFromFirst = 0;

            if (first.Length > value.Length - 1)
            {
                bytesToSkipFromFirst = first.Length - value.Length - 1;
            }

            // now that we know how many bytes we need to skip, create slice of first buffer with bytes that need to be searched.
            ReadOnlySpan <byte> bytesToSearchAgain;

            if (bytesToSkipFromFirst > 0)
            {
                bytesToSearchAgain = first.Slice(bytesToSkipFromFirst);
            }
            else
            {
                bytesToSearchAgain = first;
            }

            long index;

            // now combine the bytes from the end of the first buffer with bytes in the rest, and serarch the combined buffer
            // this check is a small optimization: if the first byte from the value does not exist in the bytesToSearchAgain, there is no reason to combine
            if (bytesToSearchAgain.IndexOf(value[0]) != -1)
            {
                var combinedBufferLength = value.Length << 1;
                var combined             = combinedBufferLength < 128 ?
                                           stackalloc byte[combinedBufferLength] :
                                           // TODO (pri 3): I think this could be eliminated by chunking values
                                           new byte[combinedBufferLength];

                bytesToSearchAgain.CopyTo(combined);
                int combinedLength = bytesToSearchAgain.Length + rest.CopyTo(combined.Slice(bytesToSearchAgain.Length));
                combined = combined.Slice(0, combinedLength);

                if (combined.Length < value.Length)
                {
                    return(-1);
                }

                index = combined.IndexOf(value);
                if (index != -1)
                {
                    return(index + bytesToSkipFromFirst);
                }
            }

            // try to find the bytes in _rest
            index = rest.IndexOf(value);
            if (index != -1)
            {
                return(first.Length + index);
            }

            return(-1);
        }
Esempio n. 30
0
 private ReadOnlyBytes(ReadOnlyMemory <byte> memory, int virtualIndex)
 {
     _first = memory;
     _all   = null;
     _totalLengthOrVirtualIndex = virtualIndex;
 }