//
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
using System;
using System.Runtime.InteropServices;
namespace DotZLib
{
///
/// Implements the common functionality needed for all s
///
public abstract class CodecBase : Codec, IDisposable
{
#region Data members
///
/// Instance of the internal zlib buffer structure that is
/// passed to all functions in the zlib dll
///
internal ZStream _ztream = new ZStream();
///
/// True if the object instance has been disposed, false otherwise
///
protected bool _isDisposed = false;
///
/// The size of the internal buffers
///
protected const int kBufferSize = 16384;
private byte[] _outBuffer = new byte[kBufferSize];
private byte[] _inBuffer = new byte[kBufferSize];
private GCHandle _hInput;
private GCHandle _hOutput;
private uint _checksum = 0;
#endregion
///
/// Initializes a new instance of the CodeBase class.
///
public CodecBase()
{
try
{
_hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned);
_hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned);
}
catch (Exception)
{
CleanUp(false);
throw;
}
}
#region Codec Members
///
/// Occurs when more processed data are available.
///
public event DataAvailableHandler DataAvailable;
///
/// Fires the event
///
protected void OnDataAvailable()
{
if (_ztream.total_out > 0)
{
if (DataAvailable != null)
DataAvailable( _outBuffer, 0, (int)_ztream.total_out);
resetOutput();
}
}
///
/// Adds more data to the codec to be processed.
///
/// Byte array containing the data to be added to the codec
/// Adding data may, or may not, raise the DataAvailable event
public void Add(byte[] data)
{
Add(data,0,data.Length);
}
///
/// Adds more data to the codec to be processed.
///
/// Byte array containing the data to be added to the codec
/// The index of the first byte to add from data
/// The number of bytes to add
/// Adding data may, or may not, raise the DataAvailable event
/// This must be implemented by a derived class
public abstract void Add(byte[] data, int offset, int count);
///
/// Finishes up any pending data that needs to be processed and handled.
///
/// This must be implemented by a derived class
public abstract void Finish();
///
/// Gets the checksum of the data that has been added so far
///
public uint Checksum { get { return _checksum; } }
#endregion
#region Destructor & IDisposable stuff
///
/// Destroys this instance
///
~CodecBase()
{
CleanUp(false);
}
///
/// Releases any unmanaged resources and calls the method of the derived class
///
public void Dispose()
{
CleanUp(true);
}
///
/// Performs any codec specific cleanup
///
/// This must be implemented by a derived class
protected abstract void CleanUp();
// performs the release of the handles and calls the derived CleanUp()
private void CleanUp(bool isDisposing)
{
if (!_isDisposed)
{
CleanUp();
if (_hInput.IsAllocated)
_hInput.Free();
if (_hOutput.IsAllocated)
_hOutput.Free();
_isDisposed = true;
}
}
#endregion
#region Helper methods
///
/// Copies a number of bytes to the internal codec buffer - ready for processing
///
/// The byte array that contains the data to copy
/// The index of the first byte to copy
/// The number of bytes to copy from data
protected void copyInput(byte[] data, int startIndex, int count)
{
Array.Copy(data, startIndex, _inBuffer,0, count);
_ztream.next_in = _hInput.AddrOfPinnedObject();
_ztream.total_in = 0;
_ztream.avail_in = (uint)count;
}
///
/// Resets the internal output buffers to a known state - ready for processing
///
protected void resetOutput()
{
_ztream.total_out = 0;
_ztream.avail_out = kBufferSize;
_ztream.next_out = _hOutput.AddrOfPinnedObject();
}
///
/// Updates the running checksum property
///
/// The new checksum value
protected void setChecksum(uint newSum)
{
_checksum = newSum;
}
#endregion
}
}