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