/// <summary>
        /// Removes a front portion of the memory stream.
        /// </summary>
        public static void TrimStart(this ChunkedMemoryStream stream, int length)
        {
            // TODO: change RecyclableMemoryStream to allow every block to have
            // an offset, so we don't need to shift data

            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            stream.Position = 0;

            if (length == 0)
            {
                return;
            }

            var helper = stream.GetBlockOffset(length);

            stream.RemoveBlockRange(0, helper.Block);

            // Now we need to shift data in trailing blocks.
            for (int i = 0; i < stream.BlockCount; i++)
            {
                var currentBlock = stream.GetBlock(i);

                int previous = i - 1;
                if (previous >= 0)
                {
                    var previousBlock = stream.GetBlock(previous);

                    var bytesToMoveBack = currentBlock.Slice(0, helper.Offset);
                    var backDst         = previousBlock[^ helper.Offset..];
Beispiel #2
0
        /// <summary>
        /// Removes a front portion of the memory stream.
        /// </summary>
        public static void TrimStart(this ChunkedMemoryStream stream, int length)
        {
            // TODO: change ChunkedMemoryStream to allow every block to have
            //  an offset, so we don't need to shift data at least as much?

            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            stream.Position = 0;

            if (length == 0)
            {
                return;
            }

            (int block, int offset) = stream.GetBlockOffset(length);
            stream.RemoveBlockRange(0, block);

            // Now we need to shift data in trailing blocks.
            for (int i = 0; i < stream.BlockCount; i++)
            {
                Memory <byte> currentBlock = stream.GetBlock(i);

                int previous = i - 1;
                if (previous >= 0)
                {
                    Memory <byte> bytesToMoveBack = currentBlock.Slice(0, offset);
                    Memory <byte> previousBlock   = stream.GetBlock(previous);
                    Memory <byte> backDestination = previousBlock[^ offset..];
Beispiel #3
0
        /// <summary>
        /// Retrieve a new MemoryStream object with the given tag and with contents copied from the provided
        /// buffer. The provided buffer is not wrapped or used after construction.
        /// </summary>
        /// <remarks>The new stream's position is set to the beginning of the stream when returned.</remarks>
        /// <param name="id">A unique identifier which can be used to trace usages of the stream.</param>
        /// <param name="tag">A tag which can be used to track the source of the stream.</param>
        /// <param name="buffer">The byte buffer to copy data from.</param>
        /// <param name="offset">The offset from the start of the buffer to copy from.</param>
        /// <param name="count">The number of bytes to copy from the buffer.</param>
        /// <returns>A MemoryStream.</returns>
        public ChunkedMemoryStream GetStream(Guid id, string?tag, byte[] buffer, int offset, int count)
        {
            ChunkedMemoryStream?stream = null;

            try
            {
                stream = new ChunkedMemoryStream(this, id, tag, count);
                stream.Write(buffer, offset, count);
                stream.Position = 0;
                return(stream);
            }
            catch
            {
                stream?.Dispose();
                throw;
            }
        }