1
2
3
4
5
6
7
8 package crc32
9
10 import (
11 "hash"
12 "os"
13 "sync"
14 )
15
16
17 const Size = 4
18
19
20 const (
21
22
23 IEEE = 0xedb88320
24
25
26
27
28 Castagnoli = 0x82f63b78
29
30
31
32
33 Koopman = 0xeb31d82e
34 )
35
36
37 type Table [256]uint32
38
39
40
41
42
43 var castagnoliTable *Table
44 var castagnoliOnce sync.Once
45
46 func castagnoliInit() {
47 castagnoliTable = makeTable(Castagnoli)
48 }
49
50
51 var IEEETable = makeTable(IEEE)
52
53
54 func MakeTable(poly uint32) *Table {
55 switch poly {
56 case IEEE:
57 return IEEETable
58 case Castagnoli:
59 castagnoliOnce.Do(castagnoliInit)
60 return castagnoliTable
61 }
62 return makeTable(poly)
63 }
64
65
66 func makeTable(poly uint32) *Table {
67 t := new(Table)
68 for i := 0; i < 256; i++ {
69 crc := uint32(i)
70 for j := 0; j < 8; j++ {
71 if crc&1 == 1 {
72 crc = (crc >> 1) ^ poly
73 } else {
74 crc >>= 1
75 }
76 }
77 t[i] = crc
78 }
79 return t
80 }
81
82
83 type digest struct {
84 crc uint32
85 tab *Table
86 }
87
88
89
90 func New(tab *Table) hash.Hash32 { return &digest{0, tab} }
91
92
93
94 func NewIEEE() hash.Hash32 { return New(IEEETable) }
95
96 func (d *digest) Size() int { return Size }
97
98 func (d *digest) Reset() { d.crc = 0 }
99
100 func update(crc uint32, tab *Table, p []byte) uint32 {
101 crc = ^crc
102 for _, v := range p {
103 crc = tab[byte(crc)^v] ^ (crc >> 8)
104 }
105 return ^crc
106 }
107
108
109 func Update(crc uint32, tab *Table, p []byte) uint32 {
110 if tab == castagnoliTable {
111 return updateCastagnoli(crc, p)
112 }
113 return update(crc, tab, p)
114 }
115
116 func (d *digest) Write(p []byte) (n int, err os.Error) {
117 d.crc = Update(d.crc, d.tab, p)
118 return len(p), nil
119 }
120
121 func (d *digest) Sum32() uint32 { return d.crc }
122
123 func (d *digest) Sum() []byte {
124 p := make([]byte, 4)
125 s := d.Sum32()
126 p[0] = byte(s >> 24)
127 p[1] = byte(s >> 16)
128 p[2] = byte(s >> 8)
129 p[3] = byte(s)
130 return p
131 }
132
133
134
135 func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
136
137
138
139 func ChecksumIEEE(data []byte) uint32 { return update(0, IEEETable, data) }