Source file src/pkg/hash/adler32/adler32.go
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 // Defined in RFC 1950: 7 // Adler-32 is composed of two sums accumulated per byte: s1 is 8 // the sum of all bytes, s2 is the sum of all s1 values. Both sums 9 // are done modulo 65521. s1 is initialized to 1, s2 to zero. The 10 // Adler-32 checksum is stored as s2*65536 + s1 in most- 11 // significant-byte first (network) order. 12 package adler32 13 14 import "hash" 15 16 const ( 17 mod = 65521 18 ) 19 20 // The size of an Adler-32 checksum in bytes. 21 const Size = 4 22 23 // digest represents the partial evaluation of a checksum. 24 type digest struct { 25 // invariant: (a < mod && b < mod) || a <= b 26 // invariant: a + b + 255 <= 0xffffffff 27 a, b uint32 28 } 29 30 func (d *digest) Reset() { d.a, d.b = 1, 0 } 31 32 // New returns a new hash.Hash32 computing the Adler-32 checksum. 33 func New() hash.Hash32 { 34 d := new(digest) 35 d.Reset() 36 return d 37 } 38 39 func (d *digest) Size() int { return Size } 40 41 func (d *digest) BlockSize() int { return 1 } 42 43 // Add p to the running checksum a, b. 44 func update(a, b uint32, p []byte) (aa, bb uint32) { 45 for _, pi := range p { 46 a += uint32(pi) 47 b += a 48 // invariant: a <= b 49 if b > (0xffffffff-255)/2 { 50 a %= mod 51 b %= mod 52 // invariant: a < mod && b < mod 53 } else { 54 // invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff 55 } 56 } 57 return a, b 58 } 59 60 // Return the 32-bit checksum corresponding to a, b. 61 func finish(a, b uint32) uint32 { 62 if b >= mod { 63 a %= mod 64 b %= mod 65 } 66 return b<<16 | a 67 } 68 69 func (d *digest) Write(p []byte) (nn int, err error) { 70 d.a, d.b = update(d.a, d.b, p) 71 return len(p), nil 72 } 73 74 func (d *digest) Sum32() uint32 { return finish(d.a, d.b) } 75 76 func (d *digest) Sum(in []byte) []byte { 77 s := d.Sum32() 78 in = append(in, byte(s>>24)) 79 in = append(in, byte(s>>16)) 80 in = append(in, byte(s>>8)) 81 in = append(in, byte(s)) 82 return in 83 } 84 85 // Checksum returns the Adler-32 checksum of data. 86 func Checksum(data []byte) uint32 { return finish(update(1, 0, data)) }