Example #1
0
        internal SequencePosition Seek(SequencePosition start, SequencePosition end, long count, bool checkEndReachable = true)
        {
            int          startIndex = start.Index;
            int          endIndex   = end.Index;
            SequenceType type       = GetSequenceType();

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

            switch (type)
            {
            case SequenceType.MemoryList:
                if (start.Segment == end.Segment && endIndex - startIndex >= count)
                {
                    // end.Index >= count + Index and end.Index is int
                    return(new SequencePosition(start.Segment, startIndex + (int)count));
                }
                return(SeekMultiSegment((IMemoryList <byte>)start.Segment, startIndex, (IMemoryList <byte>)end.Segment, endIndex, count, checkEndReachable));

            case SequenceType.OwnedMemory:
            case SequenceType.Array:
                if (endIndex - startIndex >= count)
                {
                    // end.Index >= count + Index and end.Index is int
                    return(new SequencePosition(start.Segment, startIndex + (int)count));
                }

                ThrowHelper.ThrowArgumentOutOfRangeException_CountOutOfRange();
                return(default);

            default:
                ThrowHelper.ThrowInvalidOperationException_UnexpectedSegmentType();
                return(default);
            }
        }
Example #2
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);
        }
Example #3
0
        internal SequencePosition Seek(SequencePosition start, SequencePosition end, int count, bool checkEndReachable = true)
        {
            int          startIndex = start.GetInteger();
            int          endIndex   = end.GetInteger();
            SequenceType type       = GetSequenceType();

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

            switch (type)
            {
            case SequenceType.MemoryList:
                if (start.GetObject() == end.GetObject() && endIndex - startIndex >= count)
                {
                    return(new SequencePosition(start.GetObject(), startIndex + count));
                }
                return(SeekMultiSegment((IMemoryList <byte>)start.GetObject(), startIndex, (IMemoryList <byte>)end.GetObject(), endIndex, count, checkEndReachable));

            case SequenceType.OwnedMemory:
            case SequenceType.Array:
                if (start.GetObject() != end.GetObject())
                {
                    ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
                }

                if (endIndex - startIndex >= count)
                {
                    return(new SequencePosition(start.GetObject(), startIndex + count));
                }

                ThrowHelper.ThrowArgumentOutOfRangeException_CountOutOfRange();
                return(default);

            default:
                ThrowHelper.ThrowInvalidOperationException_UnexpectedSegmentType();
                return(default);
            }
        }