Summary

Class:ICSharpCode.SharpZipLib.Checksum.Adler32
Assembly:ICSharpCode.SharpZipLib
File(s):C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Checksum\Adler32.cs
Covered lines:35
Uncovered lines:6
Coverable lines:41
Total lines:175
Line coverage:85.3%
Branch coverage:100%

Metrics

MethodCyclomatic ComplexitySequence CoverageBranch Coverage
.ctor()1100100
Reset()1100100
Update(...)100
Update(...)2100100
Update(...)9100100
.cctor()1100100

File(s)

C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Checksum\Adler32.cs

#LineLine coverage
 1using System;
 2
 3namespace ICSharpCode.SharpZipLib.Checksum
 4{
 5  /// <summary>
 6  /// Computes Adler32 checksum for a stream of data. An Adler32
 7  /// checksum is not as reliable as a CRC32 checksum, but a lot faster to
 8  /// compute.
 9  ///
 10  /// The specification for Adler32 may be found in RFC 1950.
 11  /// ZLIB Compressed Data Format Specification version 3.3)
 12  ///
 13  ///
 14  /// From that document:
 15  ///
 16  ///      "ADLER32 (Adler-32 checksum)
 17  ///       This contains a checksum value of the uncompressed data
 18  ///       (excluding any dictionary data) computed according to Adler-32
 19  ///       algorithm. This algorithm is a 32-bit extension and improvement
 20  ///       of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
 21  ///       standard.
 22  ///
 23  ///       Adler-32 is composed of two sums accumulated per byte: s1 is
 24  ///       the sum of all bytes, s2 is the sum of all s1 values. Both sums
 25  ///       are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
 26  ///       Adler-32 checksum is stored as s2*65536 + s1 in most-
 27  ///       significant-byte first (network) order."
 28  ///
 29  ///  "8.2. The Adler-32 algorithm
 30  ///
 31  ///    The Adler-32 algorithm is much faster than the CRC32 algorithm yet
 32  ///    still provides an extremely low probability of undetected errors.
 33  ///
 34  ///    The modulo on unsigned long accumulators can be delayed for 5552
 35  ///    bytes, so the modulo operation time is negligible.  If the bytes
 36  ///    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
 37  ///    and order sensitive, unlike the first sum, which is just a
 38  ///    checksum.  That 65521 is prime is important to avoid a possible
 39  ///    large class of two-byte errors that leave the check unchanged.
 40  ///    (The Fletcher checksum uses 255, which is not prime and which also
 41  ///    makes the Fletcher check insensitive to single byte changes 0 -
 42  ///    255.)
 43  ///
 44  ///    The sum s1 is initialized to 1 instead of zero to make the length
 45  ///    of the sequence part of s2, so that the length does not have to be
 46  ///    checked separately. (Any sequence of zeroes has a Fletcher
 47  ///    checksum of zero.)"
 48  /// </summary>
 49  /// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream"/>
 50  /// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream"/>
 51  public sealed class Adler32 : IChecksum
 52  {
 53    #region Instance Fields
 54    /// <summary>
 55    /// largest prime smaller than 65536
 56    /// </summary>
 157    readonly static uint BASE = 65521;
 58
 59    /// <summary>
 60    /// The CRC data checksum so far.
 61    /// </summary>
 62    uint checkValue;
 63    #endregion
 64
 65    /// <summary>
 66    /// Initialise a default instance of <see cref="Adler32"></see>
 67    /// </summary>
 70968    public Adler32()
 69    {
 70970      Reset();
 70971    }
 72
 73    /// <summary>
 74    /// Resets the Adler32 data checksum as if no update was ever called.
 75    /// </summary>
 76    public void Reset()
 77    {
 114378      checkValue = 1;
 114379    }
 80
 81    /// <summary>
 82    /// Returns the Adler32 data checksum computed so far.
 83    /// </summary>
 84    public long Value {
 85      get {
 1886        return checkValue;
 87      }
 88    }
 89
 90    /// <summary>
 91    /// Updates the checksum with the byte b.
 92    /// </summary>
 93    /// <param name="bval">
 94    /// The data value to add. The high byte of the int is ignored.
 95    /// </param>
 96    public void Update(int bval)
 97    {
 98      // We could make a length 1 byte array and call update again, but I
 99      // would rather not have that overhead
 0100      uint s1 = checkValue & 0xFFFF;
 0101      uint s2 = checkValue >> 16;
 102
 0103      s1 = (s1 + ((uint)bval & 0xFF)) % BASE;
 0104      s2 = (s1 + s2) % BASE;
 105
 0106      checkValue = (s2 << 16) + s1;
 0107    }
 108
 109    /// <summary>
 110    /// Updates the Adler32 data checksum with the bytes taken from
 111    /// a block of data.
 112    /// </summary>
 113    /// <param name="buffer">Contains the data to update the checksum with.</param>
 114    public void Update(byte[] buffer)
 115    {
 2116       if (buffer == null) {
 1117        throw new ArgumentNullException(nameof(buffer));
 118      }
 119
 1120      Update(buffer, 0, buffer.Length);
 1121    }
 122
 123    /// <summary>
 124    /// Update Adler32 data checksum based on a portion of a block of data
 125    /// </summary>
 126    /// <param name = "buffer">Contains the data to update the CRC with.</param>
 127    /// <param name = "offset">The offset into the buffer where the data starts</param>
 128    /// <param name = "count">The number of data bytes to update the CRC with.</param>
 129    public void Update(byte[] buffer, int offset, int count)
 130    {
 6204131       if (buffer == null) {
 1132        throw new ArgumentNullException(nameof(buffer));
 133      }
 134
 6203135       if (offset < 0) {
 1136        throw new ArgumentOutOfRangeException(nameof(offset), "cannot be less than zero");
 137      }
 138
 6202139       if (offset >= buffer.Length) {
 1140        throw new ArgumentOutOfRangeException(nameof(offset), "not a valid index into buffer");
 141      }
 142
 6201143       if (count < 0) {
 1144        throw new ArgumentOutOfRangeException(nameof(count), "cannot be less than zero");
 145      }
 146
 6200147       if (offset + count > buffer.Length) {
 1148        throw new ArgumentOutOfRangeException(nameof(count), "exceeds buffer size");
 149      }
 150
 151      //(By Per Bothner)
 6199152      uint s1 = checkValue & 0xFFFF;
 6199153      uint s2 = checkValue >> 16;
 154
 13890155       while (count > 0) {
 156        // We can defer the modulo operation:
 157        // s1 maximally grows from 65521 to 65521 + 255 * 3800
 158        // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
 7691159        int n = 3800;
 7691160         if (n > count) {
 6199161          n = count;
 162        }
 7691163        count -= n;
 8355525164         while (--n >= 0) {
 8347834165          s1 = s1 + (uint)(buffer[offset++] & 0xff);
 8347834166          s2 = s2 + s1;
 167        }
 7691168        s1 %= BASE;
 7691169        s2 %= BASE;
 170      }
 171
 6199172      checkValue = (s2 << 16) | s1;
 6199173    }
 174  }
 175}