예제 #1
0
 /// <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;
 }
예제 #2
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;
        }
예제 #3
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;
        }
예제 #4
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));
        }
예제 #6
0
 internal void Realloc(MemoryAllocator <T>?allocator, int length)
 {
     owner.Dispose();
     owner = allocator.Invoke(length, false);
 }
예제 #7
0
        /// <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;
        }