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