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