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