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: }