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