202 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			202 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | // | |||
|  | // <20> 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 | |||
|  |     /// <summary> | |||
|  |     /// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s | |||
|  |     /// </summary> | |||
|  |     /// <example></example> | |||
|  |     public abstract class ChecksumGeneratorBase : ChecksumGenerator | |||
|  |     { | |||
|  |         /// <summary> | |||
|  |         /// The value of the current checksum | |||
|  |         /// </summary> | |||
|  |         protected uint _current; | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the checksum generator base - the current checksum is | |||
|  |         /// set to zero | |||
|  |         /// </summary> | |||
|  |         public ChecksumGeneratorBase() | |||
|  |         { | |||
|  |             _current = 0; | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the checksum generator basewith a specified value | |||
|  |         /// </summary> | |||
|  |         /// <param name="initialValue">The value to set the current checksum to</param> | |||
|  |         public ChecksumGeneratorBase(uint initialValue) | |||
|  |         { | |||
|  |             _current = initialValue; | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Resets the current checksum to zero | |||
|  |         /// </summary> | |||
|  |         public void Reset() { _current = 0; } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Gets the current checksum value | |||
|  |         /// </summary> | |||
|  |         public uint Value { get { return _current; } } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with part of an array of bytes | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The data to update the checksum with</param> | |||
|  |         /// <param name="offset">Where in <c>data</c> to start updating</param> | |||
|  |         /// <param name="count">The number of bytes from <c>data</c> to use</param> | |||
|  |         /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | |||
|  |         /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | |||
|  |         /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | |||
|  |         /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. | |||
|  |         /// This is therefore the only method a derived class has to implement</remarks> | |||
|  |         public abstract void Update(byte[] data, int offset, int count); | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with an array of bytes. | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The data to update the checksum with</param> | |||
|  |         public void Update(byte[] data) | |||
|  |         { | |||
|  |             Update(data, 0, data.Length); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with the data from a string | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The string to update the checksum with</param> | |||
|  |         /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> | |||
|  |         public void Update(string data) | |||
|  |         { | |||
|  | 			Update(Encoding.UTF8.GetBytes(data)); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with the data from a string, using a specific encoding | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The string to update the checksum with</param> | |||
|  |         /// <param name="encoding">The encoding to use</param> | |||
|  |         public void Update(string data, Encoding encoding) | |||
|  |         { | |||
|  |             Update(encoding.GetBytes(data)); | |||
|  |         } | |||
|  | 
 | |||
|  |     } | |||
|  |     #endregion | |||
|  | 
 | |||
|  |     #region CRC32 | |||
|  |     /// <summary> | |||
|  |     /// Implements a CRC32 checksum generator | |||
|  |     /// </summary> | |||
|  |     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 | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the CRC32 checksum generator | |||
|  |         /// </summary> | |||
|  |         public CRC32Checksum() : base() {} | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the CRC32 checksum generator with a specified value | |||
|  |         /// </summary> | |||
|  |         /// <param name="initialValue">The value to set the current checksum to</param> | |||
|  |         public CRC32Checksum(uint initialValue) : base(initialValue) {} | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with part of an array of bytes | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The data to update the checksum with</param> | |||
|  |         /// <param name="offset">Where in <c>data</c> to start updating</param> | |||
|  |         /// <param name="count">The number of bytes from <c>data</c> to use</param> | |||
|  |         /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | |||
|  |         /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | |||
|  |         /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | |||
|  |         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 | |||
|  |     /// <summary> | |||
|  |     /// Implements a checksum generator that computes the Adler checksum on data | |||
|  |     /// </summary> | |||
|  |     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 | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the Adler checksum generator | |||
|  |         /// </summary> | |||
|  |         public AdlerChecksum() : base() {} | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Initializes a new instance of the Adler checksum generator with a specified value | |||
|  |         /// </summary> | |||
|  |         /// <param name="initialValue">The value to set the current checksum to</param> | |||
|  |         public AdlerChecksum(uint initialValue) : base(initialValue) {} | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Updates the current checksum with part of an array of bytes | |||
|  |         /// </summary> | |||
|  |         /// <param name="data">The data to update the checksum with</param> | |||
|  |         /// <param name="offset">Where in <c>data</c> to start updating</param> | |||
|  |         /// <param name="count">The number of bytes from <c>data</c> to use</param> | |||
|  |         /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | |||
|  |         /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | |||
|  |         /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | |||
|  |         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 | |||
|  | 
 | |||
|  | } |