public ReadOnlyBuffer(OwnedMemory <byte> data, int offset, int length) { if (data == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.data); } if (offset < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset); } if (length < 0 || length > data.Length - offset) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); } BufferStart = new Position(data, offset); BufferEnd = new Position(data, offset + length); }
private static long GetLength(Position begin, Position end) { if (begin.Segment == null) { return(0); } var segment = begin.Segment; switch (segment) { case IMemoryList <byte> bufferSegment: return(GetLength(bufferSegment, begin.Index, end.GetSegment <IMemoryList <byte> >(), end.Index)); case byte[] _: case OwnedMemory <byte> _: return(end.Index - begin.Index); } ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); return(default);
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); }
public sealed override MemoryHandle Pin(int byteOffset = 0) { unsafe { Retain(); // this checks IsDisposed try { if ((IntPtr.Size == 4 && (uint)byteOffset > (uint)_array.Length * (uint)Unsafe.SizeOf <T>()) || (IntPtr.Size != 4 && (ulong)byteOffset > (uint)_array.Length * (ulong)Unsafe.SizeOf <T>())) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteOffset); } GCHandle handle = GCHandle.Alloc(_array, GCHandleType.Pinned); return(new MemoryHandle(this, ((byte *)handle.AddrOfPinnedObject()) + byteOffset, handle)); } catch { Release(); throw; } } }
internal static bool TryGetBuffer(Position begin, Position end, out ReadOnlyMemory <byte> data, out Position next) { var segment = begin.Segment; switch (segment) { case null: data = default; next = default; return(false); case IMemoryList <byte> bufferSegment: var startIndex = begin.Index; var endIndex = bufferSegment.Memory.Length; if (segment == end.Segment) { endIndex = end.Index; next = default; } else { var nextSegment = bufferSegment.Next; if (nextSegment == null) { if (end.Segment != null) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); } next = default; } else { next = new Position(nextSegment, 0); } } data = bufferSegment.Memory.Slice(startIndex, endIndex - startIndex); return(true); case OwnedMemory <byte> ownedMemory: data = ownedMemory.Memory.Slice(begin.Index, end.Index - begin.Index); if (segment != end.Segment) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); } next = default; return(true); case byte[] array: data = new Memory <byte>(array, begin.Index, end.Index - begin.Index); if (segment != end.Segment) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); } next = default; return(true); } ThrowHelper.ThrowNotSupportedException(); next = default; return(false); }