using Renci.SshNet.Security;
using System.IO;
using System;
namespace Renci.SshNet.Compression
{
///
/// Represents base class for compression algorithm implementation
///
public abstract class Compressor : Algorithm, IDisposable
{
private readonly ZlibStream _compressor;
private readonly ZlibStream _decompressor;
private MemoryStream _compressorStream;
private MemoryStream _decompressorStream;
///
/// Gets or sets a value indicating whether compression is active.
///
///
/// true if compression is active; otherwise, false.
///
protected bool IsActive { get; set; }
///
/// Gets the session.
///
protected Session Session { get; private set; }
///
/// Initializes a new instance of the class.
///
protected Compressor()
{
_compressorStream = new MemoryStream();
_decompressorStream = new MemoryStream();
_compressor = new ZlibStream(_compressorStream, CompressionMode.Compress);
_decompressor = new ZlibStream(_decompressorStream, CompressionMode.Decompress);
}
///
/// Initializes the algorithm
///
/// The session.
public virtual void Init(Session session)
{
Session = session;
}
///
/// Compresses the specified data.
///
/// Data to compress.
/// Compressed data
public virtual byte[] Compress(byte[] data)
{
return Compress(data, 0, data.Length);
}
///
/// Compresses the specified data.
///
/// Data to compress.
/// The zero-based byte offset in at which to begin reading the data to compress.
/// The number of bytes to be compressed.
///
/// The compressed data.
///
public virtual byte[] Compress(byte[] data, int offset, int length)
{
if (!IsActive)
{
if (offset == 0 && length == data.Length)
return data;
var buffer = new byte[length];
Buffer.BlockCopy(data, offset, buffer, 0, length);
return buffer;
}
_compressorStream.SetLength(0);
_compressor.Write(data, offset, length);
return _compressorStream.ToArray();
}
///
/// Decompresses the specified data.
///
/// Compressed data.
///
/// The decompressed data.
///
public virtual byte[] Decompress(byte[] data)
{
return Decompress(data, 0, data.Length);
}
///
/// Decompresses the specified data.
///
/// Compressed data.
/// The zero-based byte offset in at which to begin reading the data to decompress.
/// The number of bytes to be read from the compressed data.
///
/// The decompressed data.
///
public virtual byte[] Decompress(byte[] data, int offset, int length)
{
if (!IsActive)
{
if (offset == 0 && length == data.Length)
return data;
var buffer = new byte[length];
Buffer.BlockCopy(data, offset, buffer, 0, length);
return buffer;
}
_decompressorStream.SetLength(0);
_decompressor.Write(data, offset, length);
return _decompressorStream.ToArray();
}
#region IDisposable Members
private bool _isDisposed;
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!_isDisposed)
{
// If disposing equals true, dispose all managed
// and unmanaged ResourceMessages.
if (disposing)
{
// Dispose managed ResourceMessages.
if (_compressorStream != null)
{
_compressorStream.Dispose();
_compressorStream = null;
}
if (_decompressorStream != null)
{
_decompressorStream.Dispose();
_decompressorStream = null;
}
}
// Note disposing has been done.
_isDisposed = true;
}
}
///
/// Releases unmanaged resources and performs other cleanup operations before the
/// is reclaimed by garbage collection.
///
~Compressor()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
#endregion
}
}