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