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