| 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: | // As a special exception, if you link this library with other files to | |
| 22: | // produce an executable, this library does not by itself cause the | |
| 23: | // resulting executable to be covered by the GNU General Public License. | |
| 24: | // This exception does not however invalidate any other reasons why the | |
| 25: | // executable file might be covered by the GNU General Public License. | |
| 26: | ||
| 27: | using System; | |
| 28: | ||
| 29: | namespace NZlib.Checksums { | |
| 30: | ||
| 31: | /// <summary> | |
| 32: | /// Computes Adler32 checksum for a stream of data. An Adler32 | |
| 33: | /// checksum is not as reliable as a CRC32 checksum, but a lot faster to | |
| 34: | /// compute. | |
| 35: | /// | |
| 36: | /// The specification for Adler32 may be found in RFC 1950. | |
| 37: | /// ZLIB Compressed Data Format Specification version 3.3) | |
| 38: | /// | |
| 39: | /// | |
| 40: | /// From that document: | |
| 41: | /// | |
| 42: | /// "ADLER32 (Adler-32 checksum) | |
| 43: | /// This contains a checksum value of the uncompressed data | |
| 44: | /// (excluding any dictionary data) computed according to Adler-32 | |
| 45: | /// algorithm. This algorithm is a 32-bit extension and improvement | |
| 46: | /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 | |
| 47: | /// standard. | |
| 48: | /// | |
| 49: | /// Adler-32 is composed of two sums accumulated per byte: s1 is | |
| 50: | /// the sum of all bytes, s2 is the sum of all s1 values. Both sums | |
| 51: | /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The | |
| 52: | /// Adler-32 checksum is stored as s2*65536 + s1 in most- | |
| 53: | /// significant-byte first (network) order." | |
| 54: | /// | |
| 55: | /// "8.2. The Adler-32 algorithm | |
| 56: | /// | |
| 57: | /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet | |
| 58: | /// still provides an extremely low probability of undetected errors. | |
| 59: | /// | |
| 60: | /// The modulo on unsigned long accumulators can be delayed for 5552 | |
| 61: | /// bytes, so the modulo operation time is negligible. If the bytes | |
| 62: | /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position | |
| 63: | /// and order sensitive, unlike the first sum, which is just a | |
| 64: | /// checksum. That 65521 is prime is important to avoid a possible | |
| 65: | /// large class of two-byte errors that leave the check unchanged. | |
| 66: | /// (The Fletcher checksum uses 255, which is not prime and which also | |
| 67: | /// makes the Fletcher check insensitive to single byte changes 0 - | |
| 68: | /// 255.) | |
| 69: | /// | |
| 70: | /// The sum s1 is initialized to 1 instead of zero to make the length | |
| 71: | /// of the sequence part of s2, so that the length does not have to be | |
| 72: | /// checked separately. (Any sequence of zeroes has a Fletcher | |
| 73: | /// checksum of zero.)" | |
| 74: | /// </summary> | |
| 75: | /// <see cref="NZlib.Streams.InflaterInputStream"/> | |
| 76: | /// <see cref="NZlib.Streams.DeflaterOutputStream"/> | |
| 77: | public sealed class Adler32 : IChecksum | |
| 78: | { | |
| 79: | /// <summary> | |
| 80: | /// largest prime smaller than 65536 | |
| 81: | /// </summary> | |
| 82: | readonly static uint BASE = 65521; | |
| 83: | ||
| 84: | uint checksum; | |
| 85: | ||
| 86: | /// <summary> | |
| 87: | /// Returns the Adler32 data checksum computed so far. | |
| 88: | /// </summary> | |
| 89: | public long Value { | |
| 90: | get { | |
| 91: | return (long) checksum & 0xFFFFFFFFL; | |
| 92: | } | |
| 93: | } | |
| 94: | ||
| 95: | /// <summary> | |
| 96: | /// Creates a new instance of the <code>Adler32</code> class. | |
| 97: | /// The checksum starts off with a value of 1. | |
| 98: | /// </summary> | |
| 99: | public Adler32() | |
| 100: | { | |
| 101: | Reset(); | |
| 102: | } | |
| 103: | ||
| 104: | /// <summary> | |
| 105: | /// Resets the Adler32 checksum to the initial value. | |
| 106: | /// </summary> | |
| 107: | public void Reset() | |
| 108: | { | |
| 109: | checksum = 1; //Initialize to 1 | |
| 110: | } | |
| 111: | ||
| 112: | /// <summary> | |
| 113: | /// Updates the checksum with the byte b. | |
| 114: | /// </summary> | |
| 115: | /// <param name="bval"> | |
| 116: | /// the data value to add. The high byte of the int is ignored. | |
| 117: | /// </param> | |
| 118: | public void Update(int bval) | |
| 119: | { | |
| 120: | //We could make a length 1 byte array and call update again, but I | |
| 121: | //would rather not have that overhead | |
| 122: | uint s1 = checksum & 0xFFFF; | |
| 123: | uint s2 = checksum >> 16; | |
| 124: | ||
| 125: | s1 = (s1 + ((uint)bval & 0xFF)) % BASE; | |
| 126: | s2 = (s1 + s2) % BASE; | |
| 127: | ||
| 128: | checksum = (s2 << 16) + s1; | |
| 129: | } | |
| 130: | ||
| 131: | /// <summary> | |
| 132: | /// Updates the checksum with the bytes taken from the array. | |
| 133: | /// </summary> | |
| 134: | /// <param name="buffer"> | |
| 135: | /// buffer an array of bytes | |
| 136: | /// </param> | |
| 137: | public void Update(byte[] buffer) | |
| 138: | { | |
| 139: | Update(buffer, 0, buffer.Length); | |
| 140: | } | |
| 141: | ||
| 142: | /// <summary> | |
| 143: | /// Updates the checksum with the bytes taken from the array. | |
| 144: | /// </summary> | |
| 145: | /// <param name="buf"> | |
| 146: | /// an array of bytes | |
| 147: | /// </param> | |
| 148: | /// <param name="off"> | |
| 149: | /// the start of the data used for this update | |
| 150: | /// </param> | |
| 151: | /// <param name="len"> | |
| 152: | /// the number of bytes to use for this update | |
| 153: | /// </param> | |
| 154: | public void Update(byte[] buf, int off, int len) | |
| 155: | { | |
| 156: | if (buf == null) { | |
| 157: | throw new ArgumentNullException("buf"); | |
| 158: | } | |
| 159: | ||
| 160: | if (off < 0 || len < 0 || off + len > buf.Length) { | |
| 161: | throw new ArgumentOutOfRangeException(); | |
| 162: | } | |
| 163: | ||
| 164: | //(By Per Bothner) | |
| 165: | uint s1 = checksum & 0xFFFF; | |
| 166: | uint s2 = checksum >> 16; | |
| 167: | ||
| 168: | while (len > 0) { | |
| 169: | // We can defer the modulo operation: | |
| 170: | // s1 maximally grows from 65521 to 65521 + 255 * 3800 | |
| 171: | // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 | |
| 172: | int n = 3800; | |
| 173: | if (n > len) { | |
| 174: | n = len; | |
| 175: | } | |
| 176: | len -= n; | |
| 177: | while (--n >= 0) { | |
| 178: | s1 = s1 + (uint)(buf[off++] & 0xFF); | |
| 179: | s2 = s2 + s1; | |
| 180: | } | |
| 181: | s1 %= BASE; | |
| 182: | s2 %= BASE; | |
| 183: | } | |
| 184: | ||
| 185: | checksum = (s2 << 16) | s1; | |
| 186: | } | |
| 187: | } | |
| 188: | } |
This page was automatically generated by SharpDevelop.