mirror of https://github.com/madler/zlib.git
parent
7a6955760b
commit
79fbcdc939
55 changed files with 2167 additions and 194 deletions
Binary file not shown.
@ -0,0 +1,21 @@ |
||||
Microsoft Visual Studio Solution File, Format Version 8.00 |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotZLib", "DotZLib\DotZLib.csproj", "{BB1EE0B1-1808-46CB-B786-949D91117FC5}" |
||||
ProjectSection(ProjectDependencies) = postProject |
||||
EndProjectSection |
||||
EndProject |
||||
Global |
||||
GlobalSection(SolutionConfiguration) = preSolution |
||||
Debug = Debug |
||||
Release = Release |
||||
EndGlobalSection |
||||
GlobalSection(ProjectConfiguration) = postSolution |
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.ActiveCfg = Debug|.NET |
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.Build.0 = Debug|.NET |
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.ActiveCfg = Release|.NET |
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.Build.0 = Release|.NET |
||||
EndGlobalSection |
||||
GlobalSection(ExtensibilityGlobals) = postSolution |
||||
EndGlobalSection |
||||
GlobalSection(ExtensibilityAddIns) = postSolution |
||||
EndGlobalSection |
||||
EndGlobal |
@ -0,0 +1,58 @@ |
||||
using System.Reflection; |
||||
using System.Runtime.CompilerServices; |
||||
|
||||
// |
||||
// General Information about an assembly is controlled through the following |
||||
// set of attributes. Change these attribute values to modify the information |
||||
// associated with an assembly. |
||||
// |
||||
[assembly: AssemblyTitle("DotZLib")] |
||||
[assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("Henrik Ravn")] |
||||
[assembly: AssemblyProduct("")] |
||||
[assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
||||
|
||||
// |
||||
// Version information for an assembly consists of the following four values: |
||||
// |
||||
// Major Version |
||||
// Minor Version |
||||
// Build Number |
||||
// Revision |
||||
// |
||||
// You can specify all the values or you can default the Revision and Build Numbers |
||||
// by using the '*' as shown below: |
||||
|
||||
[assembly: AssemblyVersion("1.0.*")] |
||||
|
||||
// |
||||
// In order to sign your assembly you must specify a key to use. Refer to the |
||||
// Microsoft .NET Framework documentation for more information on assembly signing. |
||||
// |
||||
// Use the attributes below to control which key is used for signing. |
||||
// |
||||
// Notes: |
||||
// (*) If no key is specified, the assembly is not signed. |
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service |
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains |
||||
// a key. |
||||
// (*) If the KeyFile and the KeyName values are both specified, the |
||||
// following processing occurs: |
||||
// (1) If the KeyName can be found in the CSP, that key is used. |
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key |
||||
// in the KeyFile is installed into the CSP and used. |
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. |
||||
// When specifying the KeyFile, the location of the KeyFile should be |
||||
// relative to the project output directory which is |
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is |
||||
// located in the project directory, you would specify the AssemblyKeyFile |
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] |
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework |
||||
// documentation for more information on this. |
||||
// |
||||
[assembly: AssemblyDelaySign(false)] |
||||
[assembly: AssemblyKeyFile("")] |
||||
[assembly: AssemblyKeyName("")] |
@ -0,0 +1,202 @@ |
||||
// |
||||
// © 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; |
||||
using System.Text; |
||||
|
||||
|
||||
namespace DotZLib |
||||
{ |
||||
#region ChecksumGeneratorBase |
||||
/// <summary> |
||||
/// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s |
||||
/// </summary> |
||||
/// <example></example> |
||||
public abstract class ChecksumGeneratorBase : ChecksumGenerator |
||||
{ |
||||
/// <summary> |
||||
/// The value of the current checksum |
||||
/// </summary> |
||||
protected uint _current; |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the checksum generator base - the current checksum is |
||||
/// set to zero |
||||
/// </summary> |
||||
public ChecksumGeneratorBase() |
||||
{ |
||||
_current = 0; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the checksum generator basewith a specified value |
||||
/// </summary> |
||||
/// <param name="initialValue">The value to set the current checksum to</param> |
||||
public ChecksumGeneratorBase(uint initialValue) |
||||
{ |
||||
_current = initialValue; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Resets the current checksum to zero |
||||
/// </summary> |
||||
public void Reset() { _current = 0; } |
||||
|
||||
/// <summary> |
||||
/// Gets the current checksum value |
||||
/// </summary> |
||||
public uint Value { get { return _current; } } |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with part of an array of bytes |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
/// <param name="offset">Where in <c>data</c> to start updating</param> |
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param> |
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> |
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> |
||||
/// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. |
||||
/// This is therefore the only method a derived class has to implement</remarks> |
||||
public abstract void Update(byte[] data, int offset, int count); |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with an array of bytes. |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
public void Update(byte[] data) |
||||
{ |
||||
Update(data, 0, data.Length); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with the data from a string |
||||
/// </summary> |
||||
/// <param name="data">The string to update the checksum with</param> |
||||
/// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> |
||||
public void Update(string data) |
||||
{ |
||||
Update(Encoding.UTF8.GetBytes(data)); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with the data from a string, using a specific encoding |
||||
/// </summary> |
||||
/// <param name="data">The string to update the checksum with</param> |
||||
/// <param name="encoding">The encoding to use</param> |
||||
public void Update(string data, Encoding encoding) |
||||
{ |
||||
Update(encoding.GetBytes(data)); |
||||
} |
||||
|
||||
} |
||||
#endregion |
||||
|
||||
#region CRC32 |
||||
/// <summary> |
||||
/// Implements a CRC32 checksum generator |
||||
/// </summary> |
||||
public sealed class CRC32Checksum : ChecksumGeneratorBase |
||||
{ |
||||
#region DLL imports |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern uint crc32(uint crc, int data, uint length); |
||||
|
||||
#endregion |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the CRC32 checksum generator |
||||
/// </summary> |
||||
public CRC32Checksum() : base() {} |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the CRC32 checksum generator with a specified value |
||||
/// </summary> |
||||
/// <param name="initialValue">The value to set the current checksum to</param> |
||||
public CRC32Checksum(uint initialValue) : base(initialValue) {} |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with part of an array of bytes |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
/// <param name="offset">Where in <c>data</c> to start updating</param> |
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param> |
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> |
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> |
||||
public override void Update(byte[] data, int offset, int count) |
||||
{ |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > data.Length) throw new ArgumentException(); |
||||
GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); |
||||
try |
||||
{ |
||||
_current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); |
||||
} |
||||
finally |
||||
{ |
||||
hData.Free(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
#endregion |
||||
|
||||
#region Adler |
||||
/// <summary> |
||||
/// Implements a checksum generator that computes the Adler checksum on data |
||||
/// </summary> |
||||
public sealed class AdlerChecksum : ChecksumGeneratorBase |
||||
{ |
||||
#region DLL imports |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern uint adler32(uint adler, int data, uint length); |
||||
|
||||
#endregion |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the Adler checksum generator |
||||
/// </summary> |
||||
public AdlerChecksum() : base() {} |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the Adler checksum generator with a specified value |
||||
/// </summary> |
||||
/// <param name="initialValue">The value to set the current checksum to</param> |
||||
public AdlerChecksum(uint initialValue) : base(initialValue) {} |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with part of an array of bytes |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
/// <param name="offset">Where in <c>data</c> to start updating</param> |
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param> |
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> |
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> |
||||
public override void Update(byte[] data, int offset, int count) |
||||
{ |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > data.Length) throw new ArgumentException(); |
||||
GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); |
||||
try |
||||
{ |
||||
_current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); |
||||
} |
||||
finally |
||||
{ |
||||
hData.Free(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
#endregion |
||||
|
||||
} |
@ -0,0 +1,83 @@ |
||||
// |
||||
// © 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.Diagnostics; |
||||
|
||||
namespace DotZLib |
||||
{ |
||||
|
||||
/// <summary> |
||||
/// This class implements a circular buffer |
||||
/// </summary> |
||||
internal class CircularBuffer |
||||
{ |
||||
#region Private data |
||||
private int _capacity; |
||||
private int _head; |
||||
private int _tail; |
||||
private int _size; |
||||
private byte[] _buffer; |
||||
#endregion |
||||
|
||||
public CircularBuffer(int capacity) |
||||
{ |
||||
Debug.Assert( capacity > 0 ); |
||||
_buffer = new byte[capacity]; |
||||
_capacity = capacity; |
||||
_head = 0; |
||||
_tail = 0; |
||||
_size = 0; |
||||
} |
||||
|
||||
public int Size { get { return _size; } } |
||||
|
||||
public int Put(byte[] source, int offset, int count) |
||||
{ |
||||
Debug.Assert( count > 0 ); |
||||
int trueCount = Math.Min(count, _capacity - Size); |
||||
for (int i = 0; i < trueCount; ++i) |
||||
_buffer[(_tail+i) % _capacity] = source[offset+i]; |
||||
_tail += trueCount; |
||||
_tail %= _capacity; |
||||
_size += trueCount; |
||||
return trueCount; |
||||
} |
||||
|
||||
public bool Put(byte b) |
||||
{ |
||||
if (Size == _capacity) // no room |
||||
return false; |
||||
_buffer[_tail++] = b; |
||||
_tail %= _capacity; |
||||
++_size; |
||||
return true; |
||||
} |
||||
|
||||
public int Get(byte[] destination, int offset, int count) |
||||
{ |
||||
int trueCount = Math.Min(count,Size); |
||||
for (int i = 0; i < trueCount; ++i) |
||||
destination[offset + i] = _buffer[(_head+i) % _capacity]; |
||||
_head += trueCount; |
||||
_head %= _capacity; |
||||
_size -= trueCount; |
||||
return trueCount; |
||||
} |
||||
|
||||
public int Get() |
||||
{ |
||||
if (Size == 0) |
||||
return -1; |
||||
|
||||
int result = (int)_buffer[_head++ % _capacity]; |
||||
--_size; |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,198 @@ |
||||
// |
||||
// © 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 |
||||
|
||||
} |
||||
} |
@ -0,0 +1,106 @@ |
||||
// |
||||
// © 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.Diagnostics; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace DotZLib |
||||
{ |
||||
|
||||
/// <summary> |
||||
/// Implements a data compressor, using the deflate algorithm in the ZLib dll |
||||
/// </summary> |
||||
public sealed class Deflater : CodecBase |
||||
{ |
||||
#region Dll imports |
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] |
||||
private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int deflate(ref ZStream sz, int flush); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int deflateReset(ref ZStream sz); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int deflateEnd(ref ZStream sz); |
||||
#endregion |
||||
|
||||
/// <summary> |
||||
/// Constructs an new instance of the <c>Deflater</c> |
||||
/// </summary> |
||||
/// <param name="level">The compression level to use for this <c>Deflater</c></param> |
||||
public Deflater(CompressLevel level) : base() |
||||
{ |
||||
int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); |
||||
if (retval != 0) |
||||
throw new ZLibException(retval, "Could not initialize deflater"); |
||||
|
||||
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> |
||||
/// <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> |
||||
public override void Add(byte[] data, int offset, int count) |
||||
{ |
||||
if (data == null) throw new ArgumentNullException(); |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > data.Length) throw new ArgumentException(); |
||||
|
||||
int total = count; |
||||
int inputIndex = offset; |
||||
int err = 0; |
||||
|
||||
while (err >= 0 && inputIndex < total) |
||||
{ |
||||
copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); |
||||
while (err >= 0 && _ztream.avail_in > 0) |
||||
{ |
||||
err = deflate(ref _ztream, (int)FlushTypes.None); |
||||
if (err == 0) |
||||
while (_ztream.avail_out == 0) |
||||
{ |
||||
OnDataAvailable(); |
||||
err = deflate(ref _ztream, (int)FlushTypes.None); |
||||
} |
||||
inputIndex += (int)_ztream.total_in; |
||||
} |
||||
} |
||||
setChecksum( _ztream.adler ); |
||||
} |
||||
|
||||
|
||||
/// <summary> |
||||
/// Finishes up any pending data that needs to be processed and handled. |
||||
/// </summary> |
||||
public override void Finish() |
||||
{ |
||||
int err; |
||||
do |
||||
{ |
||||
err = deflate(ref _ztream, (int)FlushTypes.Finish); |
||||
OnDataAvailable(); |
||||
} |
||||
while (err == 0); |
||||
setChecksum( _ztream.adler ); |
||||
deflateReset(ref _ztream); |
||||
resetOutput(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Closes the internal zlib deflate stream |
||||
/// </summary> |
||||
protected override void CleanUp() { deflateEnd(ref _ztream); } |
||||
|
||||
} |
||||
} |
@ -0,0 +1,288 @@ |
||||
// |
||||
// © 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.IO; |
||||
using System.Runtime.InteropServices; |
||||
using System.Text; |
||||
|
||||
|
||||
namespace DotZLib |
||||
{ |
||||
|
||||
#region Internal types |
||||
|
||||
/// <summary> |
||||
/// Defines constants for the various flush types used with zlib |
||||
/// </summary> |
||||
internal enum FlushTypes |
||||
{ |
||||
None, Partial, Sync, Full, Finish, Block |
||||
} |
||||
|
||||
#region ZStream structure |
||||
// internal mapping of the zlib zstream structure for marshalling |
||||
[StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] |
||||
internal struct ZStream |
||||
{ |
||||
public IntPtr next_in; |
||||
public uint avail_in; |
||||
public uint total_in; |
||||
|
||||
public IntPtr next_out; |
||||
public uint avail_out; |
||||
public uint total_out; |
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)] |
||||
string msg; |
||||
uint state; |
||||
|
||||
uint zalloc; |
||||
uint zfree; |
||||
uint opaque; |
||||
|
||||
int data_type; |
||||
public uint adler; |
||||
uint reserved; |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
#endregion |
||||
|
||||
#region Public enums |
||||
/// <summary> |
||||
/// Defines constants for the available compression levels in zlib |
||||
/// </summary> |
||||
public enum CompressLevel : int |
||||
{ |
||||
/// <summary> |
||||
/// The default compression level with a reasonable compromise between compression and speed |
||||
/// </summary> |
||||
Default = -1, |
||||
/// <summary> |
||||
/// No compression at all. The data are passed straight through. |
||||
/// </summary> |
||||
None = 0, |
||||
/// <summary> |
||||
/// The maximum compression rate available. |
||||
/// </summary> |
||||
Best = 9, |
||||
/// <summary> |
||||
/// The fastest available compression level. |
||||
/// </summary> |
||||
Fastest = 1 |
||||
} |
||||
#endregion |
||||
|
||||
#region Exception classes |
||||
/// <summary> |
||||
/// The exception that is thrown when an error occurs on the zlib dll |
||||
/// </summary> |
||||
public class ZLibException : ApplicationException |
||||
{ |
||||
/// <summary> |
||||
/// Initializes a new instance of the <see cref="ZLibException"/> class with a specified |
||||
/// error message and error code |
||||
/// </summary> |
||||
/// <param name="errorCode">The zlib error code that caused the exception</param> |
||||
/// <param name="msg">A message that (hopefully) describes the error</param> |
||||
public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) |
||||
{ |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Initializes a new instance of the <see cref="ZLibException"/> class with a specified |
||||
/// error code |
||||
/// </summary> |
||||
/// <param name="errorCode">The zlib error code that caused the exception</param> |
||||
public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) |
||||
{ |
||||
} |
||||
} |
||||
#endregion |
||||
|
||||
#region Interfaces |
||||
|
||||
/// <summary> |
||||
/// Declares methods and properties that enables a running checksum to be calculated |
||||
/// </summary> |
||||
public interface ChecksumGenerator |
||||
{ |
||||
/// <summary> |
||||
/// Gets the current value of the checksum |
||||
/// </summary> |
||||
uint Value { get; } |
||||
|
||||
/// <summary> |
||||
/// Clears the current checksum to 0 |
||||
/// </summary> |
||||
void Reset(); |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with an array of bytes |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
void Update(byte[] data); |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with part of an array of bytes |
||||
/// </summary> |
||||
/// <param name="data">The data to update the checksum with</param> |
||||
/// <param name="offset">Where in <c>data</c> to start updating</param> |
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param> |
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> |
||||
/// <exception cref="ArgumentNullException"><c>data</c> is a null reference</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> |
||||
void Update(byte[] data, int offset, int count); |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with the data from a string |
||||
/// </summary> |
||||
/// <param name="data">The string to update the checksum with</param> |
||||
/// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> |
||||
void Update(string data); |
||||
|
||||
/// <summary> |
||||
/// Updates the current checksum with the data from a string, using a specific encoding |
||||
/// </summary> |
||||
/// <param name="data">The string to update the checksum with</param> |
||||
/// <param name="encoding">The encoding to use</param> |
||||
void Update(string data, Encoding encoding); |
||||
} |
||||
|
||||
|
||||
/// <summary> |
||||
/// Represents the method that will be called from a codec when new data |
||||
/// are available. |
||||
/// </summary> |
||||
/// <paramref name="data">The byte array containing the processed data</paramref> |
||||
/// <paramref name="startIndex">The index of the first processed byte in <c>data</c></paramref> |
||||
/// <paramref name="count">The number of processed bytes available</paramref> |
||||
/// <remarks>On return from this method, the data may be overwritten, so grab it while you can. |
||||
/// You cannot assume that startIndex will be zero. |
||||
/// </remarks> |
||||
public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); |
||||
|
||||
/// <summary> |
||||
/// Declares methods and events for implementing compressors/decompressors |
||||
/// </summary> |
||||
public interface Codec |
||||
{ |
||||
/// <summary> |
||||
/// Occurs when more processed data are available. |
||||
/// </summary> |
||||
event DataAvailableHandler DataAvailable; |
||||
|
||||
/// <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> |
||||
void Add(byte[] data); |
||||
|
||||
/// <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> |
||||
void Add(byte[] data, int offset, int count); |
||||
|
||||
/// <summary> |
||||
/// Finishes up any pending data that needs to be processed and handled. |
||||
/// </summary> |
||||
void Finish(); |
||||
|
||||
/// <summary> |
||||
/// Gets the checksum of the data that has been added so far |
||||
/// </summary> |
||||
uint Checksum { get; } |
||||
|
||||
|
||||
} |
||||
|
||||
#endregion |
||||
|
||||
#region Classes |
||||
/// <summary> |
||||
/// Encapsulates general information about the ZLib library |
||||
/// </summary> |
||||
public class Info |
||||
{ |
||||
#region DLL imports |
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern uint zlibCompileFlags(); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern string zlibVersion(); |
||||
#endregion |
||||
|
||||
#region Private stuff |
||||
private uint _flags; |
||||
|
||||
// helper function that unpacks a bitsize mask |
||||
private static int bitSize(uint bits) |
||||
{ |
||||
switch (bits) |
||||
{ |
||||
case 0: return 16; |
||||
case 1: return 32; |
||||
case 2: return 64; |
||||
} |
||||
return -1; |
||||
} |
||||
#endregion |
||||
|
||||
/// <summary> |
||||
/// Constructs an instance of the <c>Info</c> class. |
||||
/// </summary> |
||||
public Info() |
||||
{ |
||||
_flags = zlibCompileFlags(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// True if the library is compiled with debug info |
||||
/// </summary> |
||||
public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } |
||||
|
||||
/// <summary> |
||||
/// True if the library is compiled with assembly optimizations |
||||
/// </summary> |
||||
public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } |
||||
|
||||
/// <summary> |
||||
/// Gets the size of the unsigned int that was compiled into Zlib |
||||
/// </summary> |
||||
public int SizeOfUInt { get { return bitSize(_flags & 3); } } |
||||
|
||||
/// <summary> |
||||
/// Gets the size of the unsigned long that was compiled into Zlib |
||||
/// </summary> |
||||
public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } |
||||
|
||||
/// <summary> |
||||
/// Gets the size of the pointers that were compiled into Zlib |
||||
/// </summary> |
||||
public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } |
||||
|
||||
/// <summary> |
||||
/// Gets the size of the z_off_t type that was compiled into Zlib |
||||
/// </summary> |
||||
public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } |
||||
|
||||
/// <summary> |
||||
/// Gets the version of ZLib as a string, e.g. "1.2.1" |
||||
/// </summary> |
||||
public static string Version { get { return zlibVersion(); } } |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
} |
@ -0,0 +1,141 @@ |
||||
<VisualStudioProject> |
||||
<CSHARP |
||||
ProjectType = "Local" |
||||
ProductVersion = "7.10.3077" |
||||
SchemaVersion = "2.0" |
||||
ProjectGuid = "{BB1EE0B1-1808-46CB-B786-949D91117FC5}" |
||||
> |
||||
<Build> |
||||
<Settings |
||||
ApplicationIcon = "" |
||||
AssemblyKeyContainerName = "" |
||||
AssemblyName = "DotZLib" |
||||
AssemblyOriginatorKeyFile = "" |
||||
DefaultClientScript = "JScript" |
||||
DefaultHTMLPageLayout = "Grid" |
||||
DefaultTargetSchema = "IE50" |
||||
DelaySign = "false" |
||||
OutputType = "Library" |
||||
PreBuildEvent = "" |
||||
PostBuildEvent = "" |
||||
RootNamespace = "DotZLib" |
||||
RunPostBuildEvent = "OnBuildSuccess" |
||||
StartupObject = "" |
||||
> |
||||
<Config |
||||
Name = "Debug" |
||||
AllowUnsafeBlocks = "false" |
||||
BaseAddress = "285212672" |
||||
CheckForOverflowUnderflow = "false" |
||||
ConfigurationOverrideFile = "" |
||||
DefineConstants = "DEBUG;TRACE" |
||||
DocumentationFile = "docs\DotZLib.xml" |
||||
DebugSymbols = "true" |
||||
FileAlignment = "4096" |
||||
IncrementalBuild = "false" |
||||
NoStdLib = "false" |
||||
NoWarn = "1591" |
||||
Optimize = "false" |
||||
OutputPath = "bin\Debug\" |
||||
RegisterForComInterop = "false" |
||||
RemoveIntegerChecks = "false" |
||||
TreatWarningsAsErrors = "false" |
||||
WarningLevel = "4" |
||||
/> |
||||
<Config |
||||
Name = "Release" |
||||
AllowUnsafeBlocks = "false" |
||||
BaseAddress = "285212672" |
||||
CheckForOverflowUnderflow = "false" |
||||
ConfigurationOverrideFile = "" |
||||
DefineConstants = "TRACE" |
||||
DocumentationFile = "docs\DotZLib.xml" |
||||
DebugSymbols = "false" |
||||
FileAlignment = "4096" |
||||
IncrementalBuild = "false" |
||||
NoStdLib = "false" |
||||
NoWarn = "" |
||||
Optimize = "true" |
||||
OutputPath = "bin\Release\" |
||||
RegisterForComInterop = "false" |
||||
RemoveIntegerChecks = "false" |
||||
TreatWarningsAsErrors = "false" |
||||
WarningLevel = "4" |
||||
/> |
||||
</Settings> |
||||
<References> |
||||
<Reference |
||||
Name = "System" |
||||
AssemblyName = "System" |
||||
HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.dll" |
||||
/> |
||||
<Reference |
||||
Name = "System.Data" |
||||
AssemblyName = "System.Data" |
||||
HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" |
||||
/> |
||||
<Reference |
||||
Name = "System.XML" |
||||
AssemblyName = "System.Xml" |
||||
HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" |
||||
/> |
||||
<Reference |
||||
Name = "nunit.framework" |
||||
AssemblyName = "nunit.framework" |
||||
HintPath = "E:\apps\NUnit V2.1\\bin\nunit.framework.dll" |
||||
AssemblyFolderKey = "hklm\dn\nunit.framework" |
||||
/> |
||||
</References> |
||||
</Build> |
||||
<Files> |
||||
<Include> |
||||
<File |
||||
RelPath = "AssemblyInfo.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "ChecksumImpl.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "CircularBuffer.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "CodecBase.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "Deflater.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "DotZLib.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "GZipStream.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "Inflater.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
<File |
||||
RelPath = "UnitTests.cs" |
||||
SubType = "Code" |
||||
BuildAction = "Compile" |
||||
/> |
||||
</Include> |
||||
</Files> |
||||
</CSHARP> |
||||
</VisualStudioProject> |
||||
|
@ -0,0 +1,301 @@ |
||||
// |
||||
// © 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.IO; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace DotZLib |
||||
{ |
||||
/// <summary> |
||||
/// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format. |
||||
/// </summary> |
||||
public class GZipStream : Stream, IDisposable |
||||
{ |
||||
#region Dll Imports |
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] |
||||
private static extern IntPtr gzopen(string name, string mode); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int gzclose(IntPtr gzFile); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int gzwrite(IntPtr gzFile, int data, int length); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int gzread(IntPtr gzFile, int data, int length); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int gzgetc(IntPtr gzFile); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int gzputc(IntPtr gzFile, int c); |
||||
|
||||
#endregion |
||||
|
||||
#region Private data |
||||
private IntPtr _gzFile; |
||||
private bool _isDisposed = false; |
||||
private bool _isWriting; |
||||
#endregion |
||||
|
||||
#region Constructors |
||||
/// <summary> |
||||
/// Creates a new file as a writeable GZipStream |
||||
/// </summary> |
||||
/// <param name="fileName">The name of the compressed file to create</param> |
||||
/// <param name="level">The compression level to use when adding data</param> |
||||
/// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception> |
||||
public GZipStream(string fileName, CompressLevel level) |
||||
{ |
||||
_isWriting = true; |
||||
_gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); |
||||
if (_gzFile == IntPtr.Zero) |
||||
throw new ZLibException(-1, "Could not open " + fileName); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Opens an existing file as a readable GZipStream |
||||
/// </summary> |
||||
/// <param name="fileName">The name of the file to open</param> |
||||
/// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception> |
||||
public GZipStream(string fileName) |
||||
{ |
||||
_isWriting = false; |
||||
_gzFile = gzopen(fileName, "rb"); |
||||
if (_gzFile == IntPtr.Zero) |
||||
throw new ZLibException(-1, "Could not open " + fileName); |
||||
|
||||
} |
||||
#endregion |
||||
|
||||
#region Access properties |
||||
/// <summary> |
||||
/// Returns true of this stream can be read from, false otherwise |
||||
/// </summary> |
||||
public override bool CanRead |
||||
{ |
||||
get |
||||
{ |
||||
return !_isWriting; |
||||
} |
||||
} |
||||
|
||||
|
||||
/// <summary> |
||||
/// Returns false. |
||||
/// </summary> |
||||
public override bool CanSeek |
||||
{ |
||||
get |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Returns true if this tsream is writeable, false otherwise |
||||
/// </summary> |
||||
public override bool CanWrite |
||||
{ |
||||
get |
||||
{ |
||||
return _isWriting; |
||||
} |
||||
} |
||||
#endregion |
||||
|
||||
#region Destructor & IDispose stuff |
||||
|
||||
/// <summary> |
||||
/// Destroys this instance |
||||
/// </summary> |
||||
~GZipStream() |
||||
{ |
||||
cleanUp(false); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Closes the external file handle |
||||
/// </summary> |
||||
public void Dispose() |
||||
{ |
||||
cleanUp(true); |
||||
} |
||||
|
||||
// Does the actual closing of the file handle. |
||||
private void cleanUp(bool isDisposing) |
||||
{ |
||||
if (!_isDisposed) |
||||
{ |
||||
gzclose(_gzFile); |
||||
_isDisposed = true; |
||||
} |
||||
} |
||||
#endregion |
||||
|
||||
#region Basic reading and writing |
||||
/// <summary> |
||||
/// Attempts to read a number of bytes from the stream. |
||||
/// </summary> |
||||
/// <param name="buffer">The destination data buffer</param> |
||||
/// <param name="offset">The index of the first destination byte in <c>buffer</c></param> |
||||
/// <param name="count">The number of bytes requested</param> |
||||
/// <returns>The number of bytes read</returns> |
||||
/// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception> |
||||
/// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception> |
||||
/// <exception cref="NotSupportedException">If this stream is not readable.</exception> |
||||
/// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> |
||||
public override int Read(byte[] buffer, int offset, int count) |
||||
{ |
||||
if (!CanRead) throw new NotSupportedException(); |
||||
if (buffer == null) throw new ArgumentNullException(); |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > buffer.Length) throw new ArgumentException(); |
||||
if (_isDisposed) throw new ObjectDisposedException("GZipStream"); |
||||
|
||||
GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); |
||||
int result; |
||||
try |
||||
{ |
||||
result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); |
||||
if (result < 0) |
||||
throw new IOException(); |
||||
} |
||||
finally |
||||
{ |
||||
h.Free(); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Attempts to read a single byte from the stream. |
||||
/// </summary> |
||||
/// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns> |
||||
public override int ReadByte() |
||||
{ |
||||
if (!CanRead) throw new NotSupportedException(); |
||||
if (_isDisposed) throw new ObjectDisposedException("GZipStream"); |
||||
return gzgetc(_gzFile); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Writes a number of bytes to the stream |
||||
/// </summary> |
||||
/// <param name="buffer"></param> |
||||
/// <param name="offset"></param> |
||||
/// <param name="count"></param> |
||||
/// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception> |
||||
/// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception> |
||||
/// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception> |
||||
/// <exception cref="NotSupportedException">If this stream is not writeable.</exception> |
||||
/// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> |
||||
public override void Write(byte[] buffer, int offset, int count) |
||||
{ |
||||
if (!CanWrite) throw new NotSupportedException(); |
||||
if (buffer == null) throw new ArgumentNullException(); |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > buffer.Length) throw new ArgumentException(); |
||||
if (_isDisposed) throw new ObjectDisposedException("GZipStream"); |
||||
|
||||
GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); |
||||
try |
||||
{ |
||||
int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); |
||||
if (result < 0) |
||||
throw new IOException(); |
||||
} |
||||
finally |
||||
{ |
||||
h.Free(); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Writes a single byte to the stream |
||||
/// </summary> |
||||
/// <param name="value">The byte to add to the stream.</param> |
||||
/// <exception cref="NotSupportedException">If this stream is not writeable.</exception> |
||||
/// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> |
||||
public override void WriteByte(byte value) |
||||
{ |
||||
if (!CanWrite) throw new NotSupportedException(); |
||||
if (_isDisposed) throw new ObjectDisposedException("GZipStream"); |
||||
|
||||
int result = gzputc(_gzFile, (int)value); |
||||
if (result < 0) |
||||
throw new IOException(); |
||||
} |
||||
#endregion |
||||
|
||||
#region Position & length stuff |
||||
/// <summary> |
||||
/// Not supported. |
||||
/// </summary> |
||||
/// <param name="value"></param> |
||||
/// <exception cref="NotSupportedException">Always thrown</exception> |
||||
public override void SetLength(long value) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Not suppported. |
||||
/// </summary> |
||||
/// <param name="offset"></param> |
||||
/// <param name="origin"></param> |
||||
/// <returns></returns> |
||||
/// <exception cref="NotSupportedException">Always thrown</exception> |
||||
public override long Seek(long offset, SeekOrigin origin) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Flushes the <c>GZipStream</c>. |
||||
/// </summary> |
||||
/// <remarks>In this implementation, this method does nothing. This is because excessive |
||||
/// flushing may degrade the achievable compression rates.</remarks> |
||||
public override void Flush() |
||||
{ |
||||
// left empty on purpose |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets/sets the current position in the <c>GZipStream</c>. Not suppported. |
||||
/// </summary> |
||||
/// <remarks>In this implementation this property is not supported</remarks> |
||||
/// <exception cref="NotSupportedException">Always thrown</exception> |
||||
public override long Position |
||||
{ |
||||
get |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
set |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets the size of the stream. Not suppported. |
||||
/// </summary> |
||||
/// <remarks>In this implementation this property is not supported</remarks> |
||||
/// <exception cref="NotSupportedException">Always thrown</exception> |
||||
public override long Length |
||||
{ |
||||
get |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
#endregion |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
// |
||||
// © 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.Diagnostics; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace DotZLib |
||||
{ |
||||
|
||||
/// <summary> |
||||
/// Implements a data decompressor, using the inflate algorithm in the ZLib dll |
||||
/// </summary> |
||||
public class Inflater : CodecBase |
||||
{ |
||||
#region Dll imports |
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] |
||||
private static extern int inflateInit_(ref ZStream sz, string vs, int size); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int inflate(ref ZStream sz, int flush); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int inflateReset(ref ZStream sz); |
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] |
||||
private static extern int inflateEnd(ref ZStream sz); |
||||
#endregion |
||||
|
||||
/// <summary> |
||||
/// Constructs an new instance of the <c>Inflater</c> |
||||
/// </summary> |
||||
public Inflater() : base() |
||||
{ |
||||
int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); |
||||
if (retval != 0) |
||||
throw new ZLibException(retval, "Could not initialize inflater"); |
||||
|
||||
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> |
||||
/// <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> |
||||
public override void Add(byte[] data, int offset, int count) |
||||
{ |
||||
if (data == null) throw new ArgumentNullException(); |
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); |
||||
if ((offset+count) > data.Length) throw new ArgumentException(); |
||||
|
||||
int total = count; |
||||
int inputIndex = offset; |
||||
int err = 0; |
||||
|
||||
while (err >= 0 && inputIndex < total) |
||||
{ |
||||
copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); |
||||
err = inflate(ref _ztream, (int)FlushTypes.None); |
||||
if (err == 0) |
||||
while (_ztream.avail_out == 0) |
||||
{ |
||||
OnDataAvailable(); |
||||
err = inflate(ref _ztream, (int)FlushTypes.None); |
||||
} |
||||
|
||||
inputIndex += (int)_ztream.total_in; |
||||
} |
||||
setChecksum( _ztream.adler ); |
||||
} |
||||
|
||||
|
||||
/// <summary> |
||||
/// Finishes up any pending data that needs to be processed and handled. |
||||
/// </summary> |
||||
public override void Finish() |
||||
{ |
||||
int err; |
||||
do |
||||
{ |
||||
err = inflate(ref _ztream, (int)FlushTypes.Finish); |
||||
OnDataAvailable(); |
||||
} |
||||
while (err == 0); |
||||
setChecksum( _ztream.adler ); |
||||
inflateReset(ref _ztream); |
||||
resetOutput(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Closes the internal zlib inflate stream |
||||
/// </summary> |
||||
protected override void CleanUp() { inflateEnd(ref _ztream); } |
||||
|
||||
|
||||
} |
||||
} |
@ -0,0 +1,274 @@ |
||||
// |
||||
// © 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.Collections; |
||||
using System.IO; |
||||
|
||||
// uncomment the define below to include unit tests |
||||
//#define nunit |
||||
#if nunit |
||||
using NUnit.Framework; |
||||
|
||||
// Unit tests for the DotZLib class library |
||||
// ---------------------------------------- |
||||
// |
||||
// Use this with NUnit 2 from http://www.nunit.org |
||||
// |
||||
|
||||
namespace DotZLibTests |
||||
{ |
||||
using DotZLib; |
||||
|
||||
// helper methods |
||||
internal class Utils |
||||
{ |
||||
public static bool byteArrEqual( byte[] lhs, byte[] rhs ) |
||||
{ |
||||
if (lhs.Length != rhs.Length) |
||||
return false; |
||||
for (int i = lhs.Length-1; i >= 0; --i) |
||||
if (lhs[i] != rhs[i]) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
[TestFixture] |
||||
public class CircBufferTests |
||||
{ |
||||
#region Circular buffer tests |
||||
[Test] |
||||
public void SinglePutGet() |
||||
{ |
||||
CircularBuffer buf = new CircularBuffer(10); |
||||
Assert.AreEqual( 0, buf.Size ); |
||||
Assert.AreEqual( -1, buf.Get() ); |
||||
|
||||
Assert.IsTrue(buf.Put( 1 )); |
||||
Assert.AreEqual( 1, buf.Size ); |
||||
Assert.AreEqual( 1, buf.Get() ); |
||||
Assert.AreEqual( 0, buf.Size ); |
||||
Assert.AreEqual( -1, buf.Get() ); |
||||
} |
||||
|
||||
[Test] |
||||
public void BlockPutGet() |
||||
{ |
||||
CircularBuffer buf = new CircularBuffer(10); |
||||
byte[] arr = {1,2,3,4,5,6,7,8,9,10}; |
||||
Assert.AreEqual( 10, buf.Put(arr,0,10) ); |
||||
Assert.AreEqual( 10, buf.Size ); |
||||
Assert.IsFalse( buf.Put(11) ); |
||||
Assert.AreEqual( 1, buf.Get() ); |
||||
Assert.IsTrue( buf.Put(11) ); |
||||
|
||||
byte[] arr2 = (byte[])arr.Clone(); |
||||
Assert.AreEqual( 9, buf.Get(arr2,1,9) ); |
||||
Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); |
||||
} |
||||
|
||||
#endregion |
||||
} |
||||
|
||||
[TestFixture] |
||||
public class ChecksumTests |
||||
{ |
||||
#region CRC32 Tests |
||||
[Test] |
||||
public void CRC32_Null() |
||||
{ |
||||
CRC32Checksum crc32 = new CRC32Checksum(); |
||||
Assert.AreEqual( 0, crc32.Value ); |
||||
|
||||
crc32 = new CRC32Checksum(1); |
||||
Assert.AreEqual( 1, crc32.Value ); |
||||
|
||||
crc32 = new CRC32Checksum(556); |
||||
Assert.AreEqual( 556, crc32.Value ); |
||||
} |
||||
|
||||
[Test] |
||||
public void CRC32_Data() |
||||
{ |
||||
CRC32Checksum crc32 = new CRC32Checksum(); |
||||
byte[] data = { 1,2,3,4,5,6,7 }; |
||||
crc32.Update(data); |
||||
Assert.AreEqual( 0x70e46888, crc32.Value ); |
||||
|
||||
crc32 = new CRC32Checksum(); |
||||
crc32.Update("penguin"); |
||||
Assert.AreEqual( 0x0e5c1a120, crc32.Value ); |
||||
|
||||
crc32 = new CRC32Checksum(1); |
||||
crc32.Update("penguin"); |
||||
Assert.AreEqual(0x43b6aa94, crc32.Value); |
||||
|
||||
} |
||||
#endregion |
||||
|
||||
#region Adler tests |
||||
|
||||
[Test] |
||||
public void Adler_Null() |
||||
{ |
||||
AdlerChecksum adler = new AdlerChecksum(); |
||||
Assert.AreEqual(0, adler.Value); |
||||
|
||||
adler = new AdlerChecksum(1); |
||||
Assert.AreEqual( 1, adler.Value ); |
||||
|
||||
adler = new AdlerChecksum(556); |
||||
Assert.AreEqual( 556, adler.Value ); |
||||
} |
||||
|
||||
[Test] |
||||
public void Adler_Data() |
||||
{ |
||||
AdlerChecksum adler = new AdlerChecksum(1); |
||||
byte[] data = { 1,2,3,4,5,6,7 }; |
||||
adler.Update(data); |
||||
Assert.AreEqual( 0x5b001d, adler.Value ); |
||||
|
||||
adler = new AdlerChecksum(); |
||||
adler.Update("penguin"); |
||||
Assert.AreEqual(0x0bcf02f6, adler.Value ); |
||||
|
||||
adler = new AdlerChecksum(1); |
||||
adler.Update("penguin"); |
||||
Assert.AreEqual(0x0bd602f7, adler.Value); |
||||
|
||||
} |
||||
#endregion |
||||
} |
||||
|
||||
[TestFixture] |
||||
public class InfoTests |
||||
{ |
||||
#region Info tests |
||||
[Test] |
||||
public void Info_Version() |
||||
{ |
||||
Info info = new Info(); |
||||
Assert.AreEqual("1.2.2", Info.Version); |
||||
Assert.AreEqual(32, info.SizeOfUInt); |
||||
Assert.AreEqual(32, info.SizeOfULong); |
||||
Assert.AreEqual(32, info.SizeOfPointer); |
||||
Assert.AreEqual(32, info.SizeOfOffset); |
||||
} |
||||
#endregion |
||||
} |
||||
|
||||
[TestFixture] |
||||
public class DeflateInflateTests |
||||
{ |
||||
#region Deflate tests |
||||
[Test] |
||||
public void Deflate_Init() |
||||
{ |
||||
using (Deflater def = new Deflater(CompressLevel.Default)) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
private ArrayList compressedData = new ArrayList(); |
||||
private uint adler1; |
||||
|
||||
private ArrayList uncompressedData = new ArrayList(); |
||||
private uint adler2; |
||||
|
||||
public void CDataAvail(byte[] data, int startIndex, int count) |
||||
{ |
||||
for (int i = 0; i < count; ++i) |
||||
compressedData.Add(data[i+startIndex]); |
||||
} |
||||
|
||||
[Test] |
||||
public void Deflate_Compress() |
||||
{ |
||||
compressedData.Clear(); |
||||
|
||||
byte[] testData = new byte[35000]; |
||||
for (int i = 0; i < testData.Length; ++i) |
||||
testData[i] = 5; |
||||
|
||||
using (Deflater def = new Deflater((CompressLevel)5)) |
||||
{ |
||||
def.DataAvailable += new DataAvailableHandler(CDataAvail); |
||||
def.Add(testData); |
||||
def.Finish(); |
||||
adler1 = def.Checksum; |
||||
} |
||||
} |
||||
#endregion |
||||
|
||||
#region Inflate tests |
||||
[Test] |
||||
public void Inflate_Init() |
||||
{ |
||||
using (Inflater inf = new Inflater()) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
private void DDataAvail(byte[] data, int startIndex, int count) |
||||
{ |
||||
for (int i = 0; i < count; ++i) |
||||
uncompressedData.Add(data[i+startIndex]); |
||||
} |
||||
|
||||
[Test] |
||||
public void Inflate_Expand() |
||||
{ |
||||
uncompressedData.Clear(); |
||||
|
||||
using (Inflater inf = new Inflater()) |
||||
{ |
||||
inf.DataAvailable += new DataAvailableHandler(DDataAvail); |
||||
inf.Add((byte[])compressedData.ToArray(typeof(byte))); |
||||
inf.Finish(); |
||||
adler2 = inf.Checksum; |
||||
} |
||||
Assert.AreEqual( adler1, adler2 ); |
||||
} |
||||
#endregion |
||||
} |
||||
|
||||
[TestFixture] |
||||
public class GZipStreamTests |
||||
{ |
||||
#region GZipStream test |
||||
[Test] |
||||
public void GZipStream_WriteRead() |
||||
{ |
||||
using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) |
||||
{ |
||||
BinaryWriter writer = new BinaryWriter(gzOut); |
||||
writer.Write("hi there"); |
||||
writer.Write(Math.PI); |
||||
writer.Write(42); |
||||
} |
||||
|
||||
using (GZipStream gzIn = new GZipStream("gzstream.gz")) |
||||
{ |
||||
BinaryReader reader = new BinaryReader(gzIn); |
||||
string s = reader.ReadString(); |
||||
Assert.AreEqual("hi there",s); |
||||
double d = reader.ReadDouble(); |
||||
Assert.AreEqual(Math.PI, d); |
||||
int i = reader.ReadInt32(); |
||||
Assert.AreEqual(42,i); |
||||
} |
||||
|
||||
} |
||||
#endregion |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,23 @@ |
||||
Boost Software License - Version 1.0 - August 17th, 2003 |
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization |
||||
obtaining a copy of the software and accompanying documentation covered by |
||||
this license (the "Software") to use, reproduce, display, distribute, |
||||
execute, and transmit the Software, and to prepare derivative works of the |
||||
Software, and to permit third-parties to whom the Software is furnished to |
||||
do so, all subject to the following: |
||||
|
||||
The copyright notices in the Software and this entire statement, including |
||||
the above license grant, this restriction and the following disclaimer, |
||||
must be included in all copies of the Software, in whole or in part, and |
||||
all derivative works of the Software, unless such copies or derivative |
||||
works are solely in the form of machine-executable object code generated by |
||||
a source language processor. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,58 @@ |
||||
This directory contains a .Net wrapper class library for the ZLib1.dll |
||||
|
||||
The wrapper includes support for inflating/deflating memory buffers, |
||||
.Net streaming wrappers for the gz streams part of zlib, and wrappers |
||||
for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. |
||||
|
||||
Directory structure: |
||||
-------------------- |
||||
|
||||
LICENSE_1_0.txt - License file. |
||||
readme.txt - This file. |
||||
DotZLib.chm - Class library documentation |
||||
DotZLib.build - NAnt build file |
||||
DotZLib.sln - Microsoft Visual Studio 2003 solution file |
||||
|
||||
DotZLib\*.cs - Source files for the class library |
||||
|
||||
Unit tests: |
||||
----------- |
||||
The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. |
||||
To include unit tests in the build, define nunit before building. |
||||
|
||||
|
||||
Build instructions: |
||||
------------------- |
||||
|
||||
1. Using Visual Studio.Net 2003: |
||||
Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) |
||||
will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on |
||||
you are building the release or debug version of the library. Check |
||||
DotZLib/UnitTests.cs for instructions on how to include unit tests in the |
||||
build. |
||||
|
||||
2. Using NAnt: |
||||
Open a command prompt with access to the build environment and run nant |
||||
in the same directory as the DotZLib.build file. |
||||
You can define 2 properties on the nant command-line to control the build: |
||||
debug={true|false} to toggle between release/debug builds (default=true). |
||||
nunit={true|false} to include or esclude unit tests (default=true). |
||||
Also the target clean will remove binaries. |
||||
Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release |
||||
or ./DotZLib/bin/debug, depending on whether you are building the release |
||||
or debug version of the library. |
||||
|
||||
Examples: |
||||
nant -D:debug=false -D:nunit=false |
||||
will build a release mode version of the library without unit tests. |
||||
nant |
||||
will build a debug version of the library with unit tests |
||||
nant clean |
||||
will remove all previously built files. |
||||
|
||||
|
||||
--------------------------------- |
||||
Copyright (c) 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) |
@ -1,3 +1,3 @@ |
||||
This directory contains files that have not been updated for zlib 1.2.1 |
||||
This directory contains files that have not been updated for zlib 1.2.x |
||||
|
||||
(Volunteers are encouraged to help clean this up. Thanks.) |
||||
|
@ -0,0 +1,3 @@ |
||||
|
||||
To build zlib using the Microsoft Visual C++ environment, |
||||
use the appropriate project from the projects/ directory. |
Loading…
Reference in new issue