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();
}
}
}