//
// © 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
///
/// Implements the common functionality needed for all s
///
///
public abstract class ChecksumGeneratorBase : ChecksumGenerator
{
///
/// The value of the current checksum
///
protected uint _current;
///
/// Initializes a new instance of the checksum generator base - the current checksum is
/// set to zero
///
public ChecksumGeneratorBase()
{
_current = 0;
}
///
/// Initializes a new instance of the checksum generator base with a specified value
///
/// The value to set the current checksum to
public ChecksumGeneratorBase(uint initialValue)
{
_current = initialValue;
}
///
/// Resets the current checksum to zero
///
public void Reset() { _current = 0; }
///
/// Gets the current checksum value
///
public uint Value { get { return _current; } }
///
/// Updates the current checksum with part of an array of bytes
///
/// The data to update the checksum with
/// Where in data to start updating
/// The number of bytes from data to use
/// The sum of offset and count is larger than the length of data
/// data is a null reference
/// Offset or count is negative.
/// All the other Update methods are implemented in terms of this one.
/// This is therefore the only method a derived class has to implement
public abstract void Update(byte[] data, int offset, int count);
///
/// Updates the current checksum with an array of bytes.
///
/// The data to update the checksum with
public void Update(byte[] data)
{
Update(data, 0, data.Length);
}
///
/// Updates the current checksum with the data from a string
///
/// The string to update the checksum with
/// The characters in the string are converted by the UTF-8 encoding
public void Update(string data)
{
Update(Encoding.UTF8.GetBytes(data));
}
///
/// Updates the current checksum with the data from a string, using a specific encoding
///
/// The string to update the checksum with
/// The encoding to use
public void Update(string data, Encoding encoding)
{
Update(encoding.GetBytes(data));
}
}
#endregion
#region CRC32
///
/// Implements a CRC32 checksum generator
///
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
///
/// Initializes a new instance of the CRC32 checksum generator
///
public CRC32Checksum() : base() {}
///
/// Initializes a new instance of the CRC32 checksum generator with a specified value
///
/// The value to set the current checksum to
public CRC32Checksum(uint initialValue) : base(initialValue) {}
///
/// Updates the current checksum with part of an array of bytes
///
/// The data to update the checksum with
/// Where in data to start updating
/// The number of bytes from data to use
/// The sum of offset and count is larger than the length of data
/// data is a null reference
/// Offset or count is negative.
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
///
/// Implements a checksum generator that computes the Adler checksum on data
///
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
///
/// Initializes a new instance of the Adler checksum generator
///
public AdlerChecksum() : base() {}
///
/// Initializes a new instance of the Adler checksum generator with a specified value
///
/// The value to set the current checksum to
public AdlerChecksum(uint initialValue) : base(initialValue) {}
///
/// Updates the current checksum with part of an array of bytes
///
/// The data to update the checksum with
/// Where in data to start updating
/// The number of bytes from data to use
/// The sum of offset and count is larger than the length of data
/// data is a null reference
/// Offset or count is negative.
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
}