| // | |
| // © 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 | |
| { | |
| /// <summary> | |
| /// Implements the common functionality needed for all <see cref="Codec"/>s | |
| /// </summary> | |
| public abstract class CodecBase : Codec, IDisposable | |
| { | |
| #region Data members | |
| /// <summary> | |
| /// Instance of the internal zlib buffer structure that is | |
| /// passed to all functions in the zlib dll | |
| /// </summary> | |
| internal ZStream _ztream = new ZStream(); | |
| /// <summary> | |
| /// True if the object instance has been disposed, false otherwise | |
| /// </summary> | |
| protected bool _isDisposed = false; | |
| /// <summary> | |
| /// The size of the internal buffers | |
| /// </summary> | |
| 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 | |
| /// <summary> | |
| /// Initializes a new instance of the <c>CodeBase</c> class. | |
| /// </summary> | |
| public CodecBase() | |
| { | |
| try | |
| { | |
| _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); | |
| _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); | |
| } | |
| catch (Exception) | |
| { | |
| CleanUp(false); | |
| throw; | |
| } | |
| } | |
| #region Codec Members | |
| /// <summary> | |
| /// Occurs when more processed data are available. | |
| /// </summary> | |
| public event DataAvailableHandler DataAvailable; | |
| /// <summary> | |
| /// Fires the <see cref="DataAvailable"/> event | |
| /// </summary> | |
| protected void OnDataAvailable() | |
| { | |
| if (_ztream.total_out > 0) | |
| { | |
| if (DataAvailable != null) | |
| DataAvailable( _outBuffer, 0, (int)_ztream.total_out); | |
| resetOutput(); | |
| } | |
| } | |
| /// <summary> | |
| /// Adds more data to the codec to be processed. | |
| /// </summary> | |
| /// <param name="data">Byte array containing the data to be added to the codec</param> | |
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | |
| public void Add(byte[] data) | |
| { | |
| Add(data,0,data.Length); | |
| } | |
| /// <summary> | |
| /// Adds more data to the codec to be processed. | |
| /// </summary> | |
| /// <param name="data">Byte array containing the data to be added to the codec</param> | |
| /// <param name="offset">The index of the first byte to add from <c>data</c></param> | |
| /// <param name="count">The number of bytes to add</param> | |
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | |
| /// <remarks>This must be implemented by a derived class</remarks> | |
| public abstract void Add(byte[] data, int offset, int count); | |
| /// <summary> | |
| /// Finishes up any pending data that needs to be processed and handled. | |
| /// </summary> | |
| /// <remarks>This must be implemented by a derived class</remarks> | |
| public abstract void Finish(); | |
| /// <summary> | |
| /// Gets the checksum of the data that has been added so far | |
| /// </summary> | |
| public uint Checksum { get { return _checksum; } } | |
| #endregion | |
| #region Destructor & IDisposable stuff | |
| /// <summary> | |
| /// Destroys this instance | |
| /// </summary> | |
| ~CodecBase() | |
| { | |
| CleanUp(false); | |
| } | |
| /// <summary> | |
| /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class | |
| /// </summary> | |
| public void Dispose() | |
| { | |
| CleanUp(true); | |
| } | |
| /// <summary> | |
| /// Performs any codec specific cleanup | |
| /// </summary> | |
| /// <remarks>This must be implemented by a derived class</remarks> | |
| protected abstract void CleanUp(); | |
| // performs the release of the handles and calls the dereived 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 | |
| /// <summary> | |
| /// Copies a number of bytes to the internal codec buffer - ready for proccesing | |
| /// </summary> | |
| /// <param name="data">The byte array that contains the data to copy</param> | |
| /// <param name="startIndex">The index of the first byte to copy</param> | |
| /// <param name="count">The number of bytes to copy from <c>data</c></param> | |
| 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; | |
| } | |
| /// <summary> | |
| /// Resets the internal output buffers to a known state - ready for processing | |
| /// </summary> | |
| protected void resetOutput() | |
| { | |
| _ztream.total_out = 0; | |
| _ztream.avail_out = kBufferSize; | |
| _ztream.next_out = _hOutput.AddrOfPinnedObject(); | |
| } | |
| /// <summary> | |
| /// Updates the running checksum property | |
| /// </summary> | |
| /// <param name="newSum">The new checksum value</param> | |
| protected void setChecksum(uint newSum) | |
| { | |
| _checksum = newSum; | |
| } | |
| #endregion | |
| } | |
| } |