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