start populating the new System.Web.Configuration_2.0 dir
[mono.git] / mcs / class / ICSharpCode.SharpZipLib / ICSharpCode.SharpZipLib / Checksums / Adler32.cs
1 // Adler32.cs - Computes Adler32 data checksum of a data stream\r
2 // Copyright (C) 2001 Mike Krueger\r
3 //\r
4 // This file was translated from java, it was part of the GNU Classpath\r
5 // Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.\r
6 //\r
7 // This program is free software; you can redistribute it and/or\r
8 // modify it under the terms of the GNU General Public License\r
9 // as published by the Free Software Foundation; either version 2\r
10 // of the License, or (at your option) any later version.\r
11 //\r
12 // This program is distributed in the hope that it will be useful,\r
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 // GNU General Public License for more details.\r
16 //\r
17 // You should have received a copy of the GNU General Public License\r
18 // along with this program; if not, write to the Free Software\r
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
20 //\r
21 // Linking this library statically or dynamically with other modules is\r
22 // making a combined work based on this library.  Thus, the terms and\r
23 // conditions of the GNU General Public License cover the whole\r
24 // combination.\r
25 // \r
26 // As a special exception, the copyright holders of this library give you\r
27 // permission to link this library with independent modules to produce an\r
28 // executable, regardless of the license terms of these independent\r
29 // modules, and to copy and distribute the resulting executable under\r
30 // terms of your choice, provided that you also meet, for each linked\r
31 // independent module, the terms and conditions of the license of that\r
32 // module.  An independent module is a module which is not derived from\r
33 // or based on this library.  If you modify this library, you may extend\r
34 // this exception to your version of the library, but you are not\r
35 // obligated to do so.  If you do not wish to do so, delete this\r
36 // exception statement from your version.\r
37 \r
38 using System;\r
39 \r
40 namespace ICSharpCode.SharpZipLib.Checksums \r
41 {\r
42         \r
43         /// <summary>\r
44         /// Computes Adler32 checksum for a stream of data. An Adler32\r
45         /// checksum is not as reliable as a CRC32 checksum, but a lot faster to\r
46         /// compute.\r
47         /// \r
48         /// The specification for Adler32 may be found in RFC 1950.\r
49         /// ZLIB Compressed Data Format Specification version 3.3)\r
50         /// \r
51         /// \r
52         /// From that document:\r
53         /// \r
54         ///      "ADLER32 (Adler-32 checksum)\r
55         ///       This contains a checksum value of the uncompressed data\r
56         ///       (excluding any dictionary data) computed according to Adler-32\r
57         ///       algorithm. This algorithm is a 32-bit extension and improvement\r
58         ///       of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073\r
59         ///       standard.\r
60         /// \r
61         ///       Adler-32 is composed of two sums accumulated per byte: s1 is\r
62         ///       the sum of all bytes, s2 is the sum of all s1 values. Both sums\r
63         ///       are done modulo 65521. s1 is initialized to 1, s2 to zero.  The\r
64         ///       Adler-32 checksum is stored as s2*65536 + s1 in most-\r
65         ///       significant-byte first (network) order."\r
66         /// \r
67         ///  "8.2. The Adler-32 algorithm\r
68         /// \r
69         ///    The Adler-32 algorithm is much faster than the CRC32 algorithm yet\r
70         ///    still provides an extremely low probability of undetected errors.\r
71         /// \r
72         ///    The modulo on unsigned long accumulators can be delayed for 5552\r
73         ///    bytes, so the modulo operation time is negligible.  If the bytes\r
74         ///    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position\r
75         ///    and order sensitive, unlike the first sum, which is just a\r
76         ///    checksum.  That 65521 is prime is important to avoid a possible\r
77         ///    large class of two-byte errors that leave the check unchanged.\r
78         ///    (The Fletcher checksum uses 255, which is not prime and which also\r
79         ///    makes the Fletcher check insensitive to single byte changes 0 -\r
80         ///    255.)\r
81         /// \r
82         ///    The sum s1 is initialized to 1 instead of zero to make the length\r
83         ///    of the sequence part of s2, so that the length does not have to be\r
84         ///    checked separately. (Any sequence of zeroes has a Fletcher\r
85         ///    checksum of zero.)"\r
86         /// </summary>\r
87         /// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream"/>\r
88         /// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream"/>\r
89         public sealed class Adler32 : IChecksum\r
90         {\r
91                 /// <summary>\r
92                 /// largest prime smaller than 65536\r
93                 /// </summary>\r
94                 readonly static uint BASE = 65521;\r
95                 \r
96                 uint checksum;\r
97                 \r
98                 /// <summary>\r
99                 /// Returns the Adler32 data checksum computed so far.\r
100                 /// </summary>\r
101                 public long Value {\r
102                         get {\r
103                                 return checksum;\r
104                         }\r
105                 }\r
106                 \r
107                 /// <summary>\r
108                 /// Creates a new instance of the Adler32 class.\r
109                 /// The checksum starts off with a value of 1.\r
110                 /// </summary>\r
111                 public Adler32()\r
112                 {\r
113                         Reset();\r
114                 }\r
115                 \r
116                 /// <summary>\r
117                 /// Resets the Adler32 checksum to the initial value.\r
118                 /// </summary>\r
119                 public void Reset()\r
120                 {\r
121                         checksum = 1;\r
122                 }\r
123                 \r
124                 /// <summary>\r
125                 /// Updates the checksum with the byte b.\r
126                 /// </summary>\r
127                 /// <param name="bval">\r
128                 /// The data value to add. The high byte of the int is ignored.\r
129                 /// </param>\r
130                 public void Update(int bval)\r
131                 {\r
132                         // We could make a length 1 byte array and call update again, but I\r
133                         // would rather not have that overhead\r
134                         uint s1 = checksum & 0xFFFF;\r
135                         uint s2 = checksum >> 16;\r
136                         \r
137                         s1 = (s1 + ((uint)bval & 0xFF)) % BASE;\r
138                         s2 = (s1 + s2) % BASE;\r
139                         \r
140                         checksum = (s2 << 16) + s1;\r
141                 }\r
142                 \r
143                 /// <summary>\r
144                 /// Updates the checksum with an array of bytes.\r
145                 /// </summary>\r
146                 /// <param name="buffer">\r
147                 /// The source of the data to update with.\r
148                 /// </param>\r
149                 public void Update(byte[] buffer)\r
150                 {\r
151                         Update(buffer, 0, buffer.Length);\r
152                 }\r
153                 \r
154                 /// <summary>\r
155                 /// Updates the checksum with the bytes taken from the array.\r
156                 /// </summary>\r
157                 /// <param name="buf">\r
158                 /// an array of bytes\r
159                 /// </param>\r
160                 /// <param name="off">\r
161                 /// the start of the data used for this update\r
162                 /// </param>\r
163                 /// <param name="len">\r
164                 /// the number of bytes to use for this update\r
165                 /// </param>\r
166                 public void Update(byte[] buf, int off, int len)\r
167                 {\r
168                         if (buf == null) {\r
169                                 throw new ArgumentNullException("buf");\r
170                         }\r
171                         \r
172                         if (off < 0 || len < 0 || off + len > buf.Length) {\r
173                                 throw new ArgumentOutOfRangeException();\r
174                         }\r
175                         \r
176                         //(By Per Bothner)\r
177                         uint s1 = checksum & 0xFFFF;\r
178                         uint s2 = checksum >> 16;\r
179                         \r
180                         while (len > 0) {\r
181                                 // We can defer the modulo operation:\r
182                                 // s1 maximally grows from 65521 to 65521 + 255 * 3800\r
183                                 // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31\r
184                                 int n = 3800;\r
185                                 if (n > len) {\r
186                                         n = len;\r
187                                 }\r
188                                 len -= n;\r
189                                 while (--n >= 0) {\r
190                                         s1 = s1 + (uint)(buf[off++] & 0xFF);\r
191                                         s2 = s2 + s1;\r
192                                 }\r
193                                 s1 %= BASE;\r
194                                 s2 %= BASE;\r
195                         }\r
196                         \r
197                         checksum = (s2 << 16) | s1;\r
198                 }\r
199         }\r
200 }\r