using System.IO;
#if NET6_0_OR_GREATER
using System.IO.Compression;
#else
using Org.BouncyCastle.Utilities.Zlib;
#endif
namespace Renci.SshNet.Compression
{
///
/// Represents the "zlib" compression algorithm.
///
#pragma warning disable CA1724 // Type names should not match namespaces
public class Zlib : Compressor
#pragma warning restore CA1724 // Type names should not match namespaces
{
#if NET6_0_OR_GREATER
private readonly ZLibStream _compressor;
private readonly ZLibStream _decompressor;
#else
private readonly ZOutputStream _compressor;
private readonly ZOutputStream _decompressor;
#endif
private MemoryStream _compressorStream;
private MemoryStream _decompressorStream;
private bool _isDisposed;
///
/// Initializes a new instance of the class.
///
public Zlib()
: this(delayedCompression: false)
{
}
///
/// Initializes a new instance of the class.
///
///
///
///
protected Zlib(bool delayedCompression)
: base(delayedCompression)
{
_compressorStream = new MemoryStream();
_decompressorStream = new MemoryStream();
#if NET6_0_OR_GREATER
_compressor = new ZLibStream(_compressorStream, CompressionMode.Compress);
_decompressor = new ZLibStream(_decompressorStream, CompressionMode.Decompress);
#else
_compressor = new ZOutputStream(_compressorStream, level: JZlib.Z_DEFAULT_COMPRESSION) { FlushMode = JZlib.Z_PARTIAL_FLUSH };
_decompressor = new ZOutputStream(_decompressorStream) { FlushMode = JZlib.Z_PARTIAL_FLUSH };
#endif
}
///
public override string Name
{
get { return "zlib"; }
}
///
protected override byte[] CompressCore(byte[] data, int offset, int length)
{
_compressorStream.SetLength(0);
_compressor.Write(data, offset, length);
_compressor.Flush();
return _compressorStream.ToArray();
}
///
protected override byte[] DecompressCore(byte[] data, int offset, int length)
{
#if NET6_0_OR_GREATER
_decompressorStream.Write(data, offset, length);
_decompressorStream.Position = 0;
using var outputStream = new MemoryStream();
_decompressor.CopyTo(outputStream);
_decompressorStream.SetLength(0);
return outputStream.ToArray();
#else
_decompressorStream.SetLength(0);
_decompressor.Write(data, offset, length);
_decompressor.Flush();
return _decompressorStream.ToArray();
#endif
}
///
/// Releases unmanaged and - optionally - managed resources.
///
/// to release both managed and unmanaged resources; to release only unmanaged resources.
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_isDisposed)
{
return;
}
if (disposing)
{
var compressorStream = _compressorStream;
if (compressorStream != null)
{
compressorStream.Dispose();
_compressorStream = null;
}
var decompressorStream = _decompressorStream;
if (decompressorStream != null)
{
decompressorStream.Dispose();
_decompressorStream = null;
}
_isDisposed = true;
}
}
}
}