/// <summary> /// Clears the data written to the underlying buffer. /// </summary> /// <exception cref="ObjectDisposedException">This writer has been disposed.</exception> public override void Clear() { ThrowIfDisposed(); buffer.Dispose(); buffer = default; position = 0; }
public override void Clear() => Clear(false); // TODO: Remove this method in future /// <summary> /// Clears the data written to the underlying memory. /// </summary> /// <param name="reuseBuffer"><see langword="true"/> to reuse the internal buffer; <see langword="false"/> to destroy the internal buffer.</param> /// <exception cref="ObjectDisposedException">This writer has been disposed.</exception> public override void Clear(bool reuseBuffer) { ThrowIfDisposed(); if (!reuseBuffer) { buffer.Dispose(); buffer = default; } position = 0; }
/// <summary> /// Clears the data written to the underlying memory. /// </summary> /// <param name="reuseBuffer"><see langword="true"/> to reuse the internal buffer; <see langword="false"/> to destroy the internal buffer.</param> /// <exception cref="ObjectDisposedException">This writer has been disposed.</exception> public override void Clear(bool reuseBuffer) { ThrowIfDisposed(); if (!reuseBuffer) { buffer.Dispose(); } else if (RuntimeHelpers.IsReferenceOrContainsReferences <T>()) { buffer.Memory.Span.Clear(); } position = 0; }
/// <summary> /// Returns the memory to write to that is at least the requested size. /// </summary> /// <param name="sizeHint">The minimum length of the returned memory.</param> /// <returns>The memory block of at least the size <paramref name="sizeHint"/>.</returns> /// <exception cref="OutOfMemoryException">The requested buffer size is not available.</exception> public Span <T> GetSpan(int sizeHint = 0) { if (sizeHint < 0) { throw new ArgumentOutOfRangeException(nameof(sizeHint)); } Span <T> result; int? newSize; if (extraBuffer.IsEmpty) { newSize = IGrowableBuffer <T> .GetBufferSize(sizeHint, initialBuffer.Length, position); // need to copy initial buffer if (newSize.HasValue) { extraBuffer = allocator.Invoke(newSize.GetValueOrDefault(), false); initialBuffer.CopyTo(extraBuffer.Memory.Span); initialBuffer.Clear(); result = extraBuffer.Memory.Span; } else { result = initialBuffer; } } else { newSize = IGrowableBuffer <T> .GetBufferSize(sizeHint, extraBuffer.Length, position); // no need to copy initial buffer if (newSize.HasValue) { var newBuffer = allocator.Invoke(newSize.GetValueOrDefault(), false); extraBuffer.Memory.CopyTo(newBuffer.Memory); extraBuffer.Dispose(); extraBuffer = newBuffer; } result = extraBuffer.Memory.Span; } return(result.Slice(position)); }
public Memory <byte> GetMemory(int sizeHint) { if (sizeHint < 0) { throw new ArgumentOutOfRangeException(nameof(sizeHint)); } if (sizeHint == 0) { sizeHint = 1; } if (sizeHint > buffer.Length - position) { buffer.Dispose(); buffer = allocator(sizeHint); } return(buffer.Memory.Slice(position)); }
internal void Realloc(MemoryAllocator <T>?allocator, int length) { owner.Dispose(); owner = allocator.Invoke(length, false); }
/// <summary> /// Writes elements to this buffer. /// </summary> /// <param name="input">The span of elements to be written.</param> /// <exception cref="InsufficientMemoryException">Pre-allocated initial buffer size is not enough to place <paramref name="input"/> elements to it and this builder is not growable.</exception> /// <exception cref="OverflowException">The size of the internal buffer becomes greater than <see cref="int.MaxValue"/>.</exception> public void Write(ReadOnlySpan <T> input) { var newSize = checked (position + input.Length); Span <T> output; int offset; MemoryOwner <T> newBuffer; if (copyOnOverflow) { // grow if needed if (newSize > initialBuffer.Length) { if (extraBuffer.IsEmpty) { extraBuffer = allocator.Invoke(newSize, false); initialBuffer.CopyTo(extraBuffer.Memory.Span); initialBuffer.Clear(); } else if (newSize > extraBuffer.Length) { newBuffer = allocator.Invoke(newSize, false); extraBuffer.Memory.CopyTo(newBuffer.Memory); extraBuffer.Dispose(); extraBuffer = newBuffer; } output = extraBuffer.Memory.Span; } else { output = initialBuffer; } offset = position; } else { // grow if needed if (newSize > initialBuffer.Length && newSize - initialBuffer.Length > extraBuffer.Length) { newBuffer = allocator.Invoke(newSize, false); extraBuffer.Memory.CopyTo(newBuffer.Memory); extraBuffer.Dispose(); extraBuffer = newBuffer; } // append elements if (position < initialBuffer.Length) { var writtenCount = Math.Min(initialBuffer.Length - position, input.Length); input.Slice(0, writtenCount).CopyTo(initialBuffer.Slice(position)); input = input.Slice(writtenCount); offset = 0; } else { offset = position - initialBuffer.Length; } output = extraBuffer.Memory.Span; } input.CopyTo(output.Slice(offset)); position = newSize; }