You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.2 KiB
198 lines
6.2 KiB
// |
|
// © 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 |
|
|
|
} |
|
}
|
|
|