adler32.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. // Package adler32 implements the Adler-32 checksum.
  5. //
  6. // It is 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. import "hash"
  14. const (
  15. // mod is the largest prime that is less than 65536.
  16. mod = 65521
  17. // nmax is the largest n such that
  18. // 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
  19. // It is mentioned in RFC 1950 (search for "5552").
  20. nmax = 5552
  21. )
  22. // The size of an Adler-32 checksum in bytes.
  23. const Size = 4
  24. // digest represents the partial evaluation of a checksum.
  25. // The low 16 bits are s1, the high 16 bits are s2.
  26. type digest uint32
  27. func (d *digest) Reset() { *d = 1 }
  28. // New returns a new hash.Hash32 computing the Adler-32 checksum.
  29. func New() hash.Hash32 {
  30. d := new(digest)
  31. d.Reset()
  32. return d
  33. }
  34. func (d *digest) Size() int { return Size }
  35. func (d *digest) BlockSize() int { return 1 }
  36. // Add p to the running checksum d.
  37. func update(d digest, p []byte) digest {
  38. s1, s2 := uint32(d&0xffff), uint32(d>>16)
  39. for len(p) > 0 {
  40. var q []byte
  41. if len(p) > nmax {
  42. p, q = p[:nmax], p[nmax:]
  43. }
  44. for _, x := range p {
  45. s1 += uint32(x)
  46. s2 += s1
  47. }
  48. s1 %= mod
  49. s2 %= mod
  50. p = q
  51. }
  52. return digest(s2<<16 | s1)
  53. }
  54. func (d *digest) Write(p []byte) (nn int, err error) {
  55. *d = update(*d, p)
  56. return len(p), nil
  57. }
  58. func (d *digest) Sum32() uint32 { return uint32(*d) }
  59. func (d *digest) Sum(in []byte) []byte {
  60. s := uint32(*d)
  61. return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
  62. }
  63. // Checksum returns the Adler-32 checksum of data.
  64. func Checksum(data []byte) uint32 { return uint32(update(1, data)) }