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); } }
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); }
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); } }