1*44bedb31SLionel Sambuc // 2*44bedb31SLionel Sambuc // � Copyright Henrik Ravn 2004 3*44bedb31SLionel Sambuc // 4*44bedb31SLionel Sambuc // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 5*44bedb31SLionel Sambuc // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6*44bedb31SLionel Sambuc // 7*44bedb31SLionel Sambuc 8*44bedb31SLionel Sambuc using System; 9*44bedb31SLionel Sambuc using System.Runtime.InteropServices; 10*44bedb31SLionel Sambuc using System.Text; 11*44bedb31SLionel Sambuc 12*44bedb31SLionel Sambuc 13*44bedb31SLionel Sambuc namespace DotZLib 14*44bedb31SLionel Sambuc { 15*44bedb31SLionel Sambuc #region ChecksumGeneratorBase 16*44bedb31SLionel Sambuc /// <summary> 17*44bedb31SLionel Sambuc /// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s 18*44bedb31SLionel Sambuc /// </summary> 19*44bedb31SLionel Sambuc /// <example></example> 20*44bedb31SLionel Sambuc public abstract class ChecksumGeneratorBase : ChecksumGenerator 21*44bedb31SLionel Sambuc { 22*44bedb31SLionel Sambuc /// <summary> 23*44bedb31SLionel Sambuc /// The value of the current checksum 24*44bedb31SLionel Sambuc /// </summary> 25*44bedb31SLionel Sambuc protected uint _current; 26*44bedb31SLionel Sambuc 27*44bedb31SLionel Sambuc /// <summary> 28*44bedb31SLionel Sambuc /// Initializes a new instance of the checksum generator base - the current checksum is 29*44bedb31SLionel Sambuc /// set to zero 30*44bedb31SLionel Sambuc /// </summary> ChecksumGeneratorBase()31*44bedb31SLionel Sambuc public ChecksumGeneratorBase() 32*44bedb31SLionel Sambuc { 33*44bedb31SLionel Sambuc _current = 0; 34*44bedb31SLionel Sambuc } 35*44bedb31SLionel Sambuc 36*44bedb31SLionel Sambuc /// <summary> 37*44bedb31SLionel Sambuc /// Initializes a new instance of the checksum generator basewith a specified value 38*44bedb31SLionel Sambuc /// </summary> 39*44bedb31SLionel Sambuc /// <param name="initialValue">The value to set the current checksum to</param> ChecksumGeneratorBase(uint initialValue)40*44bedb31SLionel Sambuc public ChecksumGeneratorBase(uint initialValue) 41*44bedb31SLionel Sambuc { 42*44bedb31SLionel Sambuc _current = initialValue; 43*44bedb31SLionel Sambuc } 44*44bedb31SLionel Sambuc 45*44bedb31SLionel Sambuc /// <summary> 46*44bedb31SLionel Sambuc /// Resets the current checksum to zero 47*44bedb31SLionel Sambuc /// </summary> Reset()48*44bedb31SLionel Sambuc public void Reset() { _current = 0; } 49*44bedb31SLionel Sambuc 50*44bedb31SLionel Sambuc /// <summary> 51*44bedb31SLionel Sambuc /// Gets the current checksum value 52*44bedb31SLionel Sambuc /// </summary> 53*44bedb31SLionel Sambuc public uint Value { get { return _current; } } 54*44bedb31SLionel Sambuc 55*44bedb31SLionel Sambuc /// <summary> 56*44bedb31SLionel Sambuc /// Updates the current checksum with part of an array of bytes 57*44bedb31SLionel Sambuc /// </summary> 58*44bedb31SLionel Sambuc /// <param name="data">The data to update the checksum with</param> 59*44bedb31SLionel Sambuc /// <param name="offset">Where in <c>data</c> to start updating</param> 60*44bedb31SLionel Sambuc /// <param name="count">The number of bytes from <c>data</c> to use</param> 61*44bedb31SLionel Sambuc /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> 62*44bedb31SLionel Sambuc /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> 63*44bedb31SLionel Sambuc /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> 64*44bedb31SLionel Sambuc /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. 65*44bedb31SLionel Sambuc /// This is therefore the only method a derived class has to implement</remarks> Update(byte[] data, int offset, int count)66*44bedb31SLionel Sambuc public abstract void Update(byte[] data, int offset, int count); 67*44bedb31SLionel Sambuc 68*44bedb31SLionel Sambuc /// <summary> 69*44bedb31SLionel Sambuc /// Updates the current checksum with an array of bytes. 70*44bedb31SLionel Sambuc /// </summary> 71*44bedb31SLionel Sambuc /// <param name="data">The data to update the checksum with</param> Update(byte[] data)72*44bedb31SLionel Sambuc public void Update(byte[] data) 73*44bedb31SLionel Sambuc { 74*44bedb31SLionel Sambuc Update(data, 0, data.Length); 75*44bedb31SLionel Sambuc } 76*44bedb31SLionel Sambuc 77*44bedb31SLionel Sambuc /// <summary> 78*44bedb31SLionel Sambuc /// Updates the current checksum with the data from a string 79*44bedb31SLionel Sambuc /// </summary> 80*44bedb31SLionel Sambuc /// <param name="data">The string to update the checksum with</param> 81*44bedb31SLionel Sambuc /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> Update(string data)82*44bedb31SLionel Sambuc public void Update(string data) 83*44bedb31SLionel Sambuc { 84*44bedb31SLionel Sambuc Update(Encoding.UTF8.GetBytes(data)); 85*44bedb31SLionel Sambuc } 86*44bedb31SLionel Sambuc 87*44bedb31SLionel Sambuc /// <summary> 88*44bedb31SLionel Sambuc /// Updates the current checksum with the data from a string, using a specific encoding 89*44bedb31SLionel Sambuc /// </summary> 90*44bedb31SLionel Sambuc /// <param name="data">The string to update the checksum with</param> 91*44bedb31SLionel Sambuc /// <param name="encoding">The encoding to use</param> Update(string data, Encoding encoding)92*44bedb31SLionel Sambuc public void Update(string data, Encoding encoding) 93*44bedb31SLionel Sambuc { 94*44bedb31SLionel Sambuc Update(encoding.GetBytes(data)); 95*44bedb31SLionel Sambuc } 96*44bedb31SLionel Sambuc 97*44bedb31SLionel Sambuc } 98*44bedb31SLionel Sambuc #endregion 99*44bedb31SLionel Sambuc 100*44bedb31SLionel Sambuc #region CRC32 101*44bedb31SLionel Sambuc /// <summary> 102*44bedb31SLionel Sambuc /// Implements a CRC32 checksum generator 103*44bedb31SLionel Sambuc /// </summary> 104*44bedb31SLionel Sambuc public sealed class CRC32Checksum : ChecksumGeneratorBase 105*44bedb31SLionel Sambuc { 106*44bedb31SLionel Sambuc #region DLL imports 107*44bedb31SLionel Sambuc 108*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] crc32(uint crc, int data, uint length)109*44bedb31SLionel Sambuc private static extern uint crc32(uint crc, int data, uint length); 110*44bedb31SLionel Sambuc 111*44bedb31SLionel Sambuc #endregion 112*44bedb31SLionel Sambuc 113*44bedb31SLionel Sambuc /// <summary> 114*44bedb31SLionel Sambuc /// Initializes a new instance of the CRC32 checksum generator 115*44bedb31SLionel Sambuc /// </summary> CRC32Checksum()116*44bedb31SLionel Sambuc public CRC32Checksum() : base() {} 117*44bedb31SLionel Sambuc 118*44bedb31SLionel Sambuc /// <summary> 119*44bedb31SLionel Sambuc /// Initializes a new instance of the CRC32 checksum generator with a specified value 120*44bedb31SLionel Sambuc /// </summary> 121*44bedb31SLionel Sambuc /// <param name="initialValue">The value to set the current checksum to</param> CRC32Checksum(uint initialValue)122*44bedb31SLionel Sambuc public CRC32Checksum(uint initialValue) : base(initialValue) {} 123*44bedb31SLionel Sambuc 124*44bedb31SLionel Sambuc /// <summary> 125*44bedb31SLionel Sambuc /// Updates the current checksum with part of an array of bytes 126*44bedb31SLionel Sambuc /// </summary> 127*44bedb31SLionel Sambuc /// <param name="data">The data to update the checksum with</param> 128*44bedb31SLionel Sambuc /// <param name="offset">Where in <c>data</c> to start updating</param> 129*44bedb31SLionel Sambuc /// <param name="count">The number of bytes from <c>data</c> to use</param> 130*44bedb31SLionel Sambuc /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> 131*44bedb31SLionel Sambuc /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> 132*44bedb31SLionel Sambuc /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> Update(byte[] data, int offset, int count)133*44bedb31SLionel Sambuc public override void Update(byte[] data, int offset, int count) 134*44bedb31SLionel Sambuc { 135*44bedb31SLionel Sambuc if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); 136*44bedb31SLionel Sambuc if ((offset+count) > data.Length) throw new ArgumentException(); 137*44bedb31SLionel Sambuc GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); 138*44bedb31SLionel Sambuc try 139*44bedb31SLionel Sambuc { 140*44bedb31SLionel Sambuc _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); 141*44bedb31SLionel Sambuc } 142*44bedb31SLionel Sambuc finally 143*44bedb31SLionel Sambuc { 144*44bedb31SLionel Sambuc hData.Free(); 145*44bedb31SLionel Sambuc } 146*44bedb31SLionel Sambuc } 147*44bedb31SLionel Sambuc 148*44bedb31SLionel Sambuc } 149*44bedb31SLionel Sambuc #endregion 150*44bedb31SLionel Sambuc 151*44bedb31SLionel Sambuc #region Adler 152*44bedb31SLionel Sambuc /// <summary> 153*44bedb31SLionel Sambuc /// Implements a checksum generator that computes the Adler checksum on data 154*44bedb31SLionel Sambuc /// </summary> 155*44bedb31SLionel Sambuc public sealed class AdlerChecksum : ChecksumGeneratorBase 156*44bedb31SLionel Sambuc { 157*44bedb31SLionel Sambuc #region DLL imports 158*44bedb31SLionel Sambuc 159*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] adler32(uint adler, int data, uint length)160*44bedb31SLionel Sambuc private static extern uint adler32(uint adler, int data, uint length); 161*44bedb31SLionel Sambuc 162*44bedb31SLionel Sambuc #endregion 163*44bedb31SLionel Sambuc 164*44bedb31SLionel Sambuc /// <summary> 165*44bedb31SLionel Sambuc /// Initializes a new instance of the Adler checksum generator 166*44bedb31SLionel Sambuc /// </summary> AdlerChecksum()167*44bedb31SLionel Sambuc public AdlerChecksum() : base() {} 168*44bedb31SLionel Sambuc 169*44bedb31SLionel Sambuc /// <summary> 170*44bedb31SLionel Sambuc /// Initializes a new instance of the Adler checksum generator with a specified value 171*44bedb31SLionel Sambuc /// </summary> 172*44bedb31SLionel Sambuc /// <param name="initialValue">The value to set the current checksum to</param> AdlerChecksum(uint initialValue)173*44bedb31SLionel Sambuc public AdlerChecksum(uint initialValue) : base(initialValue) {} 174*44bedb31SLionel Sambuc 175*44bedb31SLionel Sambuc /// <summary> 176*44bedb31SLionel Sambuc /// Updates the current checksum with part of an array of bytes 177*44bedb31SLionel Sambuc /// </summary> 178*44bedb31SLionel Sambuc /// <param name="data">The data to update the checksum with</param> 179*44bedb31SLionel Sambuc /// <param name="offset">Where in <c>data</c> to start updating</param> 180*44bedb31SLionel Sambuc /// <param name="count">The number of bytes from <c>data</c> to use</param> 181*44bedb31SLionel Sambuc /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> 182*44bedb31SLionel Sambuc /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> 183*44bedb31SLionel Sambuc /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> Update(byte[] data, int offset, int count)184*44bedb31SLionel Sambuc public override void Update(byte[] data, int offset, int count) 185*44bedb31SLionel Sambuc { 186*44bedb31SLionel Sambuc if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); 187*44bedb31SLionel Sambuc if ((offset+count) > data.Length) throw new ArgumentException(); 188*44bedb31SLionel Sambuc GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); 189*44bedb31SLionel Sambuc try 190*44bedb31SLionel Sambuc { 191*44bedb31SLionel Sambuc _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); 192*44bedb31SLionel Sambuc } 193*44bedb31SLionel Sambuc finally 194*44bedb31SLionel Sambuc { 195*44bedb31SLionel Sambuc hData.Free(); 196*44bedb31SLionel Sambuc } 197*44bedb31SLionel Sambuc } 198*44bedb31SLionel Sambuc 199*44bedb31SLionel Sambuc } 200*44bedb31SLionel Sambuc #endregion 201*44bedb31SLionel Sambuc 202*44bedb31SLionel Sambuc }