// | |
// © 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 | |
} |