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