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