|
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> |
|
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> |
|
40 public ChecksumGeneratorBase(uint initialValue) |
|
41 { |
|
42 _current = initialValue; |
|
43 } |
|
44 |
|
45 /// <summary> |
|
46 /// Resets the current checksum to zero |
|
47 /// </summary> |
|
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> |
|
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> |
|
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> |
|
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> |
|
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)] |
|
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> |
|
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> |
|
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> |
|
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)] |
|
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> |
|
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> |
|
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> |
|
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 } |