d3ullist icon

WrappedStream

d3ullist | PRO | 07/13/21 02:48:29 PM UTC | 0 ⭐ | 1093 👁️ | Never ⏰ | []
C# |

5.71 KB

|

None

|

0 👍

/

0 👎

using System;
using System.IO;
 
namespace Shared.Util
{
    /// <summary>
    /// A wrapper around another stream that adds a prefix and postfix
    /// to the content of the stream.
    /// </summary>
    public class WrapperStream : Stream
    {
        /// <summary>
        /// The prefix position.
        /// </summary>
        private int prefixPosition;
 
        /// <summary>
        /// The prefix (readonly).
        /// </summary>
        private readonly string Prefix;
 
        /// <summary>
        /// The wrapped stream (readonly).
        /// </summary>
        private readonly Stream WrappedStream;
 
        /// <summary>
        /// The postfix position.
        /// </summary>
        private int postfixPosition;
 
        /// <summary>
        /// The postfix (readonly).
        /// </summary>
        private readonly string Postfix;
 
        /// <summary>
        /// Gets a value indicating whether
        /// </summary>
        public override bool CanRead => true;
 
        /// <summary>
        /// Gets a value indicating whether
        /// </summary>
        public override bool CanSeek => false;
 
        /// <summary>
        /// Gets a value indicating whether
        /// </summary>
        public override bool CanWrite => false;
 
        /// <summary>
        /// Gets the length.
        /// </summary>
        public override long Length => throw new NotSupportedException();
 
        /// <summary>
        /// Gets or sets the position.
        /// </summary>
        public override long Position { get => prefixPosition + WrappedStream.Position + postfixPosition; set => throw new NotSupportedException(); }
 
        /// <summary>
        /// Initializes a new instance of the <see cref="WrapperStream"/> class.
        /// </summary>
        /// <param name="prefix">The prefix.</param>
        /// <param name="wrappedStream">The wrappedStream.</param>
        /// <param name="postfix">The postfix.</param>
        /// <exception cref="ArgumentException">The wrappedstream, prefix or postfix cannot be null</exception>
        /// <exception cref="ArgumentException">Must be able to read from the wrapped stream</exception>
        public WrapperStream(string prefix, Stream wrappedStream, string postfix)
        {
            Prefix = prefix;
            Postfix = postfix;
            WrappedStream = wrappedStream;
 
            if (wrappedStream == null || prefix == null || postfix == null)
            {
                throw new ArgumentException("The wrappedstream, prefix or postfix cannot be null");
            }
            if (!wrappedStream.CanRead)
            {
                throw new ArgumentException("Must be able to read from the wrapped stream");
            }
        }
 
        /// <summary>
        /// The flush.
        /// </summary>
        public override void Flush()
        {
            prefixPosition = 0;
            postfixPosition = 0;
            WrappedStream.Flush();
        }
 
        /// <summary>
        /// The seek.
        /// </summary>
        /// <param name="offset">The offset.</param>
        /// <param name="origin">The origin.</param>
        /// <returns>The <see cref="long"/>.</returns>
        /// <exception cref="NotSupportedException"></exception>
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }
 
        /// <summary>
        /// Set the length.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <exception cref="NotSupportedException"></exception>
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
 
        /// <summary>
        /// Read.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="count">The count.</param>
        /// <returns>The <see cref="int"/>.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int readBytes = 0;
            // If bytes need to be read from the prefix set those bytes in the buffer
            for (; readBytes < count && prefixPosition < Prefix.Length; ++readBytes)
            {
                buffer[offset + readBytes] = (byte)Prefix[prefixPosition++];
            }
 
            // If bytes need to be read from the wrapped stream read them
            if (readBytes < count)
            {
                readBytes += WrappedStream.Read(buffer, offset + readBytes, count - readBytes);
            }
 
            // If we still need to read bytes but can't read them from the wrapped
            // stream object read them from the postfix. There is no real way to
            // know when there are no bytes anymore in the WrappedStream object
            // unless reading from it returns a 0.
            if (readBytes == 0 && postfixPosition < Postfix.Length)
            {
                for (; readBytes < count && postfixPosition < Postfix.Length; ++readBytes)
                {
                    buffer[offset + readBytes] = (byte)Postfix[postfixPosition++];
                }
            }
 
            return readBytes;
        }
 
        /// <summary>
        /// Write.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="count">The count.</param>
        /// <exception cref="NotSupportedException"></exception>
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }
    }
}

Comments