emul/mini/src/main/java/java/util/zip/Adler32.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
jaroslav@640
     1
/* Adler32.java - Computes Adler32 data checksum of a data stream
jaroslav@640
     2
   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
jaroslav@640
     3
jaroslav@640
     4
This file is part of GNU Classpath.
jaroslav@640
     5
jaroslav@640
     6
GNU Classpath is free software; you can redistribute it and/or modify
jaroslav@640
     7
it under the terms of the GNU General Public License as published by
jaroslav@640
     8
the Free Software Foundation; either version 2, or (at your option)
jaroslav@640
     9
any later version.
jaroslav@640
    10
jaroslav@640
    11
GNU Classpath is distributed in the hope that it will be useful, but
jaroslav@640
    12
WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@640
    13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
jaroslav@640
    14
General Public License for more details.
jaroslav@640
    15
jaroslav@640
    16
You should have received a copy of the GNU General Public License
jaroslav@640
    17
along with GNU Classpath; see the file COPYING.  If not, write to the
jaroslav@640
    18
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
jaroslav@640
    19
02111-1307 USA.
jaroslav@640
    20
jaroslav@640
    21
Linking this library statically or dynamically with other modules is
jaroslav@640
    22
making a combined work based on this library.  Thus, the terms and
jaroslav@640
    23
conditions of the GNU General Public License cover the whole
jaroslav@640
    24
combination.
jaroslav@640
    25
jaroslav@640
    26
As a special exception, the copyright holders of this library give you
jaroslav@640
    27
permission to link this library with independent modules to produce an
jaroslav@640
    28
executable, regardless of the license terms of these independent
jaroslav@640
    29
modules, and to copy and distribute the resulting executable under
jaroslav@640
    30
terms of your choice, provided that you also meet, for each linked
jaroslav@640
    31
independent module, the terms and conditions of the license of that
jaroslav@640
    32
module.  An independent module is a module which is not derived from
jaroslav@640
    33
or based on this library.  If you modify this library, you may extend
jaroslav@640
    34
this exception to your version of the library, but you are not
jaroslav@640
    35
obligated to do so.  If you do not wish to do so, delete this
jaroslav@640
    36
exception statement from your version. */
jaroslav@640
    37
jaroslav@640
    38
package java.util.zip;
jaroslav@640
    39
jaroslav@640
    40
/*
jaroslav@640
    41
 * Written using on-line Java Platform 1.2 API Specification, as well
jaroslav@640
    42
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
jaroslav@640
    43
 * The actual Adler32 algorithm is taken from RFC 1950.
jaroslav@640
    44
 * Status:  Believed complete and correct.
jaroslav@640
    45
 */
jaroslav@640
    46
jaroslav@640
    47
/**
jaroslav@640
    48
 * Computes Adler32 checksum for a stream of data. An Adler32 
jaroslav@640
    49
 * checksum is not as reliable as a CRC32 checksum, but a lot faster to 
jaroslav@640
    50
 * compute.
jaroslav@640
    51
 *<p>
jaroslav@640
    52
 * The specification for Adler32 may be found in RFC 1950.
jaroslav@640
    53
 * (ZLIB Compressed Data Format Specification version 3.3)
jaroslav@640
    54
 *<p>
jaroslav@640
    55
 *<p>
jaroslav@640
    56
 * From that document:
jaroslav@640
    57
 *<p>
jaroslav@640
    58
 *      "ADLER32 (Adler-32 checksum)
jaroslav@640
    59
 *       This contains a checksum value of the uncompressed data
jaroslav@640
    60
 *       (excluding any dictionary data) computed according to Adler-32
jaroslav@640
    61
 *       algorithm. This algorithm is a 32-bit extension and improvement
jaroslav@640
    62
 *       of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
jaroslav@640
    63
 *       standard. 
jaroslav@640
    64
 *<p>
jaroslav@640
    65
 *       Adler-32 is composed of two sums accumulated per byte: s1 is
jaroslav@640
    66
 *       the sum of all bytes, s2 is the sum of all s1 values. Both sums
jaroslav@640
    67
 *       are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
jaroslav@640
    68
 *       Adler-32 checksum is stored as s2*65536 + s1 in most-
jaroslav@640
    69
 *       significant-byte first (network) order."
jaroslav@640
    70
 *<p>
jaroslav@640
    71
 * "8.2. The Adler-32 algorithm
jaroslav@640
    72
 *<p>
jaroslav@640
    73
 *    The Adler-32 algorithm is much faster than the CRC32 algorithm yet
jaroslav@640
    74
 *    still provides an extremely low probability of undetected errors.
jaroslav@640
    75
 *<p>
jaroslav@640
    76
 *    The modulo on unsigned long accumulators can be delayed for 5552
jaroslav@640
    77
 *    bytes, so the modulo operation time is negligible.  If the bytes
jaroslav@640
    78
 *    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
jaroslav@640
    79
 *    and order sensitive, unlike the first sum, which is just a
jaroslav@640
    80
 *    checksum.  That 65521 is prime is important to avoid a possible
jaroslav@640
    81
 *    large class of two-byte errors that leave the check unchanged.
jaroslav@640
    82
 *    (The Fletcher checksum uses 255, which is not prime and which also
jaroslav@640
    83
 *    makes the Fletcher check insensitive to single byte changes 0 <->
jaroslav@640
    84
 *    255.)
jaroslav@640
    85
 *<p>
jaroslav@640
    86
 *    The sum s1 is initialized to 1 instead of zero to make the length
jaroslav@640
    87
 *    of the sequence part of s2, so that the length does not have to be
jaroslav@640
    88
 *   checked separately. (Any sequence of zeroes has a Fletcher
jaroslav@640
    89
 *    checksum of zero.)"
jaroslav@640
    90
 *
jaroslav@640
    91
 * @author John Leuner, Per Bothner
jaroslav@640
    92
 * @since JDK 1.1
jaroslav@640
    93
 *
jaroslav@640
    94
 * @see InflaterInputStream
jaroslav@640
    95
 * @see DeflaterOutputStream
jaroslav@640
    96
 */
jaroslav@640
    97
public class Adler32 implements Checksum
jaroslav@640
    98
{
jaroslav@640
    99
jaroslav@640
   100
  /** largest prime smaller than 65536 */
jaroslav@640
   101
  private static final int BASE = 65521;
jaroslav@640
   102
jaroslav@640
   103
  private int checksum; //we do all in int.
jaroslav@640
   104
jaroslav@640
   105
  //Note that java doesn't have unsigned integers,
jaroslav@640
   106
  //so we have to be careful with what arithmetic 
jaroslav@640
   107
  //we do. We return the checksum as a long to 
jaroslav@640
   108
  //avoid sign confusion.
jaroslav@640
   109
jaroslav@640
   110
  /**
jaroslav@640
   111
   * Creates a new instance of the <code>Adler32</code> class. 
jaroslav@640
   112
   * The checksum starts off with a value of 1. 
jaroslav@640
   113
   */
jaroslav@640
   114
  public Adler32 ()
jaroslav@640
   115
  {
jaroslav@640
   116
    reset();
jaroslav@640
   117
  }
jaroslav@640
   118
jaroslav@640
   119
  /**
jaroslav@640
   120
   * Resets the Adler32 checksum to the initial value.
jaroslav@640
   121
   */
jaroslav@640
   122
  public void reset () 
jaroslav@640
   123
  {
jaroslav@640
   124
    checksum = 1; //Initialize to 1    
jaroslav@640
   125
  }
jaroslav@640
   126
jaroslav@640
   127
  /**
jaroslav@640
   128
   * Updates the checksum with the byte b. 
jaroslav@640
   129
   *
jaroslav@640
   130
   * @param bval the data value to add. The high byte of the int is ignored.
jaroslav@640
   131
   */
jaroslav@640
   132
  public void update (int bval)
jaroslav@640
   133
  {
jaroslav@640
   134
    //We could make a length 1 byte array and call update again, but I
jaroslav@640
   135
    //would rather not have that overhead
jaroslav@640
   136
    int s1 = checksum & 0xffff;
jaroslav@640
   137
    int s2 = checksum >>> 16;
jaroslav@640
   138
    
jaroslav@640
   139
    s1 = (s1 + (bval & 0xFF)) % BASE;
jaroslav@640
   140
    s2 = (s1 + s2) % BASE;
jaroslav@640
   141
    
jaroslav@640
   142
    checksum = (s2 << 16) + s1;
jaroslav@640
   143
  }
jaroslav@640
   144
jaroslav@640
   145
  /**
jaroslav@640
   146
   * Updates the checksum with the bytes taken from the array. 
jaroslav@640
   147
   * 
jaroslav@640
   148
   * @param buffer an array of bytes
jaroslav@640
   149
   */
jaroslav@640
   150
  public void update (byte[] buffer)
jaroslav@640
   151
  {
jaroslav@640
   152
    update(buffer, 0, buffer.length);
jaroslav@640
   153
  }
jaroslav@640
   154
jaroslav@640
   155
  /**
jaroslav@640
   156
   * Updates the checksum with the bytes taken from the array. 
jaroslav@640
   157
   * 
jaroslav@640
   158
   * @param buf an array of bytes
jaroslav@640
   159
   * @param off the start of the data used for this update
jaroslav@640
   160
   * @param len the number of bytes to use for this update
jaroslav@640
   161
   */
jaroslav@640
   162
  public void update (byte[] buf, int off, int len)
jaroslav@640
   163
  {
jaroslav@640
   164
    //(By Per Bothner)
jaroslav@640
   165
    int s1 = checksum & 0xffff;
jaroslav@640
   166
    int s2 = checksum >>> 16;
jaroslav@640
   167
jaroslav@640
   168
    while (len > 0)
jaroslav@640
   169
      {
jaroslav@640
   170
	// We can defer the modulo operation:
jaroslav@640
   171
	// s1 maximally grows from 65521 to 65521 + 255 * 3800
jaroslav@640
   172
	// s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
jaroslav@640
   173
	int n = 3800;
jaroslav@640
   174
	if (n > len)
jaroslav@640
   175
	  n = len;
jaroslav@640
   176
	len -= n;
jaroslav@640
   177
	while (--n >= 0)
jaroslav@640
   178
	  {
jaroslav@640
   179
	    s1 = s1 + (buf[off++] & 0xFF);
jaroslav@640
   180
	    s2 = s2 + s1;
jaroslav@640
   181
	  }
jaroslav@640
   182
	s1 %= BASE;
jaroslav@640
   183
	s2 %= BASE;
jaroslav@640
   184
      }
jaroslav@640
   185
jaroslav@640
   186
    /*Old implementation, borrowed from somewhere:
jaroslav@640
   187
    int n;
jaroslav@640
   188
    
jaroslav@640
   189
    while (len-- > 0) {
jaroslav@640
   190
jaroslav@640
   191
      s1 = (s1 + (bs[offset++] & 0xff)) % BASE; 
jaroslav@640
   192
      s2 = (s2 + s1) % BASE;
jaroslav@640
   193
    }*/
jaroslav@640
   194
    
jaroslav@640
   195
    checksum = (s2 << 16) | s1;
jaroslav@640
   196
  }
jaroslav@640
   197
jaroslav@640
   198
  /**
jaroslav@640
   199
   * Returns the Adler32 data checksum computed so far.
jaroslav@640
   200
   */
jaroslav@640
   201
  public long getValue()
jaroslav@640
   202
  {
jaroslav@640
   203
    return (long) checksum & 0xffffffffL;
jaroslav@640
   204
  }
jaroslav@640
   205
}