Home | History | Annotate | Download | only in adler32
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package adler32 implements the Adler-32 checksum.
      6 //
      7 // It is defined in RFC 1950:
      8 //	Adler-32 is composed of two sums accumulated per byte: s1 is
      9 //	the sum of all bytes, s2 is the sum of all s1 values. Both sums
     10 //	are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
     11 //	Adler-32 checksum is stored as s2*65536 + s1 in most-
     12 //	significant-byte first (network) order.
     13 package adler32
     14 
     15 import "hash"
     16 
     17 const (
     18 	// mod is the largest prime that is less than 65536.
     19 	mod = 65521
     20 	// nmax is the largest n such that
     21 	// 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
     22 	// It is mentioned in RFC 1950 (search for "5552").
     23 	nmax = 5552
     24 )
     25 
     26 // The size of an Adler-32 checksum in bytes.
     27 const Size = 4
     28 
     29 // digest represents the partial evaluation of a checksum.
     30 // The low 16 bits are s1, the high 16 bits are s2.
     31 type digest uint32
     32 
     33 func (d *digest) Reset() { *d = 1 }
     34 
     35 // New returns a new hash.Hash32 computing the Adler-32 checksum.
     36 // Its Sum method will lay the value out in big-endian byte order.
     37 func New() hash.Hash32 {
     38 	d := new(digest)
     39 	d.Reset()
     40 	return d
     41 }
     42 
     43 func (d *digest) Size() int { return Size }
     44 
     45 func (d *digest) BlockSize() int { return 4 }
     46 
     47 // Add p to the running checksum d.
     48 func update(d digest, p []byte) digest {
     49 	s1, s2 := uint32(d&0xffff), uint32(d>>16)
     50 	for len(p) > 0 {
     51 		var q []byte
     52 		if len(p) > nmax {
     53 			p, q = p[:nmax], p[nmax:]
     54 		}
     55 		for len(p) >= 4 {
     56 			s1 += uint32(p[0])
     57 			s2 += s1
     58 			s1 += uint32(p[1])
     59 			s2 += s1
     60 			s1 += uint32(p[2])
     61 			s2 += s1
     62 			s1 += uint32(p[3])
     63 			s2 += s1
     64 			p = p[4:]
     65 		}
     66 		for _, x := range p {
     67 			s1 += uint32(x)
     68 			s2 += s1
     69 		}
     70 		s1 %= mod
     71 		s2 %= mod
     72 		p = q
     73 	}
     74 	return digest(s2<<16 | s1)
     75 }
     76 
     77 func (d *digest) Write(p []byte) (nn int, err error) {
     78 	*d = update(*d, p)
     79 	return len(p), nil
     80 }
     81 
     82 func (d *digest) Sum32() uint32 { return uint32(*d) }
     83 
     84 func (d *digest) Sum(in []byte) []byte {
     85 	s := uint32(*d)
     86 	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
     87 }
     88 
     89 // Checksum returns the Adler-32 checksum of data.
     90 func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
     91