cannam@89: //
cannam@89: // © Copyright Henrik Ravn 2004
cannam@89: //
cannam@89: // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
cannam@89: // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
cannam@89: //
cannam@89:
cannam@89: using System;
cannam@89: using System.Runtime.InteropServices;
cannam@89: using System.Text;
cannam@89:
cannam@89:
cannam@89: namespace DotZLib
cannam@89: {
cannam@89: #region ChecksumGeneratorBase
cannam@89: ///
cannam@89: /// Implements the common functionality needed for all s
cannam@89: ///
cannam@89: ///
cannam@89: public abstract class ChecksumGeneratorBase : ChecksumGenerator
cannam@89: {
cannam@89: ///
cannam@89: /// The value of the current checksum
cannam@89: ///
cannam@89: protected uint _current;
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the checksum generator base - the current checksum is
cannam@89: /// set to zero
cannam@89: ///
cannam@89: public ChecksumGeneratorBase()
cannam@89: {
cannam@89: _current = 0;
cannam@89: }
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the checksum generator basewith a specified value
cannam@89: ///
cannam@89: /// The value to set the current checksum to
cannam@89: public ChecksumGeneratorBase(uint initialValue)
cannam@89: {
cannam@89: _current = initialValue;
cannam@89: }
cannam@89:
cannam@89: ///
cannam@89: /// Resets the current checksum to zero
cannam@89: ///
cannam@89: public void Reset() { _current = 0; }
cannam@89:
cannam@89: ///
cannam@89: /// Gets the current checksum value
cannam@89: ///
cannam@89: public uint Value { get { return _current; } }
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with part of an array of bytes
cannam@89: ///
cannam@89: /// The data to update the checksum with
cannam@89: /// Where in data to start updating
cannam@89: /// The number of bytes from data to use
cannam@89: /// The sum of offset and count is larger than the length of data
cannam@89: /// data is a null reference
cannam@89: /// Offset or count is negative.
cannam@89: /// All the other Update methods are implmeneted in terms of this one.
cannam@89: /// This is therefore the only method a derived class has to implement
cannam@89: public abstract void Update(byte[] data, int offset, int count);
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with an array of bytes.
cannam@89: ///
cannam@89: /// The data to update the checksum with
cannam@89: public void Update(byte[] data)
cannam@89: {
cannam@89: Update(data, 0, data.Length);
cannam@89: }
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with the data from a string
cannam@89: ///
cannam@89: /// The string to update the checksum with
cannam@89: /// The characters in the string are converted by the UTF-8 encoding
cannam@89: public void Update(string data)
cannam@89: {
cannam@89: Update(Encoding.UTF8.GetBytes(data));
cannam@89: }
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with the data from a string, using a specific encoding
cannam@89: ///
cannam@89: /// The string to update the checksum with
cannam@89: /// The encoding to use
cannam@89: public void Update(string data, Encoding encoding)
cannam@89: {
cannam@89: Update(encoding.GetBytes(data));
cannam@89: }
cannam@89:
cannam@89: }
cannam@89: #endregion
cannam@89:
cannam@89: #region CRC32
cannam@89: ///
cannam@89: /// Implements a CRC32 checksum generator
cannam@89: ///
cannam@89: public sealed class CRC32Checksum : ChecksumGeneratorBase
cannam@89: {
cannam@89: #region DLL imports
cannam@89:
cannam@89: [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
cannam@89: private static extern uint crc32(uint crc, int data, uint length);
cannam@89:
cannam@89: #endregion
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the CRC32 checksum generator
cannam@89: ///
cannam@89: public CRC32Checksum() : base() {}
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the CRC32 checksum generator with a specified value
cannam@89: ///
cannam@89: /// The value to set the current checksum to
cannam@89: public CRC32Checksum(uint initialValue) : base(initialValue) {}
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with part of an array of bytes
cannam@89: ///
cannam@89: /// The data to update the checksum with
cannam@89: /// Where in data to start updating
cannam@89: /// The number of bytes from data to use
cannam@89: /// The sum of offset and count is larger than the length of data
cannam@89: /// data is a null reference
cannam@89: /// Offset or count is negative.
cannam@89: public override void Update(byte[] data, int offset, int count)
cannam@89: {
cannam@89: if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
cannam@89: if ((offset+count) > data.Length) throw new ArgumentException();
cannam@89: GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
cannam@89: try
cannam@89: {
cannam@89: _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
cannam@89: }
cannam@89: finally
cannam@89: {
cannam@89: hData.Free();
cannam@89: }
cannam@89: }
cannam@89:
cannam@89: }
cannam@89: #endregion
cannam@89:
cannam@89: #region Adler
cannam@89: ///
cannam@89: /// Implements a checksum generator that computes the Adler checksum on data
cannam@89: ///
cannam@89: public sealed class AdlerChecksum : ChecksumGeneratorBase
cannam@89: {
cannam@89: #region DLL imports
cannam@89:
cannam@89: [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
cannam@89: private static extern uint adler32(uint adler, int data, uint length);
cannam@89:
cannam@89: #endregion
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the Adler checksum generator
cannam@89: ///
cannam@89: public AdlerChecksum() : base() {}
cannam@89:
cannam@89: ///
cannam@89: /// Initializes a new instance of the Adler checksum generator with a specified value
cannam@89: ///
cannam@89: /// The value to set the current checksum to
cannam@89: public AdlerChecksum(uint initialValue) : base(initialValue) {}
cannam@89:
cannam@89: ///
cannam@89: /// Updates the current checksum with part of an array of bytes
cannam@89: ///
cannam@89: /// The data to update the checksum with
cannam@89: /// Where in data to start updating
cannam@89: /// The number of bytes from data to use
cannam@89: /// The sum of offset and count is larger than the length of data
cannam@89: /// data is a null reference
cannam@89: /// Offset or count is negative.
cannam@89: public override void Update(byte[] data, int offset, int count)
cannam@89: {
cannam@89: if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
cannam@89: if ((offset+count) > data.Length) throw new ArgumentException();
cannam@89: GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
cannam@89: try
cannam@89: {
cannam@89: _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
cannam@89: }
cannam@89: finally
cannam@89: {
cannam@89: hData.Free();
cannam@89: }
cannam@89: }
cannam@89:
cannam@89: }
cannam@89: #endregion
cannam@89:
cannam@89: }