//
package net.sf.zipme;
/**
* Computes Adler32 checksum for a stream of data. An Adler32
* checksum is not as reliable as a CRC32 checksum, but a lot faster to
* compute.
* <p>
* The specification for Adler32 may be found in RFC 1950.
* (ZLIB Compressed Data Format Specification version 3.3)
* <p>
* <p>
* From that document:
* <p>
* "ADLER32 (Adler-32 checksum)
* This contains a checksum value of the uncompressed data
* (excluding any dictionary data) computed according to Adler-32
* algorithm. This algorithm is a 32-bit extension and improvement
* of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
* standard.
* <p>
* Adler-32 is composed of two sums accumulated per byte: s1 is
* the sum of all bytes, s2 is the sum of all s1 values. Both sums
* are done modulo 65521. s1 is initialized to 1, s2 to zero. The
* Adler-32 checksum is stored as s2*65536 + s1 in most-
* significant-byte first (network) order."
* <p>
* "8.2. The Adler-32 algorithm
* <p>
* The Adler-32 algorithm is much faster than the CRC32 algorithm yet
* still provides an extremely low probability of undetected errors.
* <p>
* The modulo on unsigned long accumulators can be delayed for 5552
* bytes, so the modulo operation time is negligible. If the bytes
* are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
* and order sensitive, unlike the first sum, which is just a
* checksum. That 65521 is prime is important to avoid a possible
* large class of two-byte errors that leave the check unchanged.
* (The Fletcher checksum uses 255, which is not prime and which also
* makes the Fletcher check insensitive to single byte changes 0 <->
* 255.)
* <p>
* The sum s1 is initialized to 1 instead of zero to make the length
* of the sequence part of s2, so that the length does not have to be
* checked separately. (Any sequence of zeroes has a Fletcher
* checksum of zero.)"
* @author John Leuner, Per Bothner
* @since JDK 1.1
* @see InflaterInputStream
* @see DeflaterOutputStream
*/
public class Adler32 implements Checksum {
/**
* largest prime smaller than 65536
*/
private static final int BASE=65521;
private int checksum;
/**
* Creates a new instance of the <code>Adler32</code> class.
* The checksum starts off with a value of 1.
*/
public Adler32(){
reset();
}
/**
* Resets the Adler32 checksum to the initial value.
*/
public void reset(){
checksum=1;
}
/**
* Updates the checksum with the byte b.
* @param bval the data value to add. The high byte of the int is ignored.
*/
public void update( int bval){
int s1=checksum & 0xffff;
int s2=checksum >>> 16;
s1=(s1 + (bval & 0xFF)) % BASE;
s2=(s1 + s2) % BASE;
checksum=(s2 << 16) + s1;
}
/**
* Updates the checksum with the bytes taken from the array.
* @param buffer an array of bytes
*/
public void update( byte[] buffer){
update(buffer,0,buffer.length);
}
/**
* Updates the checksum with the bytes taken from the array.
* @param buf an array of bytes
* @param off the start of the data used for this update
* @param len the number of bytes to use for this update
*/
public void update( byte[] buf, int off, int len){
int s1=checksum & 0xffff;
int s2=checksum >>> 16;
while (len > 0) {
int n=3800;
if (n > len) n=len;
len-=n;
while (--n >= 0) {
s1=s1 + (buf[off++] & 0xFF);
s2=s2 + s1;
}
s1%=BASE;
s2%=BASE;
}
checksum=(s2 << 16) | s1;
}
/**
* Returns the Adler32 data checksum computed so far.
*/
public long getValue(){
return (long)checksum & 0xffffffffL;
}
}