using System; using System.IO; namespace Shared.Util { /// /// A wrapper around another stream that adds a prefix and postfix /// to the content of the stream. /// public class WrapperStream : Stream { /// /// The prefix position. /// private int prefixPosition; /// /// The prefix (readonly). /// private readonly string Prefix; /// /// The wrapped stream (readonly). /// private readonly Stream WrappedStream; /// /// The postfix position. /// private int postfixPosition; /// /// The postfix (readonly). /// private readonly string Postfix; /// /// Gets a value indicating whether /// public override bool CanRead => true; /// /// Gets a value indicating whether /// public override bool CanSeek => false; /// /// Gets a value indicating whether /// public override bool CanWrite => false; /// /// Gets the length. /// public override long Length => throw new NotSupportedException(); /// /// Gets or sets the position. /// public override long Position { get => prefixPosition + WrappedStream.Position + postfixPosition; set => throw new NotSupportedException(); } /// /// Initializes a new instance of the class. /// /// The prefix. /// The wrappedStream. /// The postfix. /// The wrappedstream, prefix or postfix cannot be null /// Must be able to read from the wrapped stream 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"); } } /// /// The flush. /// public override void Flush() { prefixPosition = 0; postfixPosition = 0; WrappedStream.Flush(); } /// /// The seek. /// /// The offset. /// The origin. /// The . /// public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } /// /// Set the length. /// /// The value. /// public override void SetLength(long value) { throw new NotSupportedException(); } /// /// Read. /// /// The buffer. /// The offset. /// The count. /// The . 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; } /// /// Write. /// /// The buffer. /// The offset. /// The count. /// public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } } }