private void BoundsCheck(SequencePosition start, SequencePosition newCursor) { var startIndex = start.Index; var endIndex = newCursor.Index; var type = GetBufferType(); startIndex = GetIndex(startIndex); endIndex = GetIndex(endIndex); switch (type) { case BufferType.OwnedMemory: case BufferType.Array: if (endIndex > startIndex) { ThrowHelper.ThrowCursorOutOfBoundsException(); } return; case BufferType.MemoryList: var segment = (IMemoryList <T>)newCursor.Segment; var memoryList = (IMemoryList <T>)start.Segment; if (segment.RunningIndex - startIndex > memoryList.RunningIndex - endIndex) { ThrowHelper.ThrowCursorOutOfBoundsException(); } return; default: ThrowHelper.ThrowCursorOutOfBoundsException(); return; } }
internal SequencePosition Seek(SequencePosition start, SequencePosition end, long bytes, bool checkEndReachable = true) { var startIndex = start.Index; var endIndex = end.Index; var type = GetBufferType(); startIndex = GetIndex(startIndex); endIndex = GetIndex(endIndex); switch (type) { case BufferType.MemoryList: if (start.Segment == end.Segment && endIndex - startIndex >= bytes) { // end.Index >= bytes + Index and end.Index is int return(new SequencePosition(start.Segment, startIndex + (int)bytes)); } return(SeekMultiSegment((IMemoryList <byte>)start.Segment, startIndex, (IMemoryList <byte>)end.Segment, endIndex, bytes, checkEndReachable)); case BufferType.OwnedMemory: case BufferType.Array: if (endIndex - startIndex >= bytes) { // end.Index >= bytes + Index and end.Index is int return(new SequencePosition(start.Segment, startIndex + (int)bytes)); } ThrowHelper.ThrowCursorOutOfBoundsException(); return(default); } ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); return(default);
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); }
private static Position SeekMultiSegment(Position begin, Position end, long bytes, bool checkEndReachable) { Position result = default; var foundResult = false; var current = begin; while (TryGetBuffer(begin, end, out var memory, out begin)) { // We need to loop up until the end to make sure start and end are connected // if end is not trusted if (!foundResult) { // We would prefer to put cursor in the beginning of next segment // then past the end of previous one, but only if next exists if (memory.Length > bytes || (memory.Length == bytes && begin.Segment == null)) { result = new Position(current.Segment, current.Index + (int)bytes); foundResult = true; if (!checkEndReachable) { break; } } bytes -= memory.Length; } current = begin; } if (!foundResult) { ThrowHelper.ThrowCursorOutOfBoundsException(); } return(result); }