root/trunk/BazaReklam.Updater/ICSharpCode.SharpZipLib/Checksums/Adler32.cs @ 806

Wersja 597, 7.7 KB (wprowadzona przez marek, 17 years temu)

re #165

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