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)) }