...
Source file src/pkg/hash/crc32/crc32.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package crc32
14
15 import (
16 "errors"
17 "hash"
18 "sync"
19 )
20
21
22 const Size = 4
23
24
25 const (
26
27
28 IEEE = 0xedb88320
29
30
31
32
33 Castagnoli = 0x82f63b78
34
35
36
37
38 Koopman = 0xeb31d82e
39 )
40
41
42 type Table [256]uint32
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 var castagnoliTable *Table
77 var castagnoliTable8 *slicing8Table
78 var castagnoliArchImpl bool
79 var updateCastagnoli func(crc uint32, p []byte) uint32
80 var castagnoliOnce sync.Once
81
82 func castagnoliInit() {
83 castagnoliTable = simpleMakeTable(Castagnoli)
84 castagnoliArchImpl = archAvailableCastagnoli()
85
86 if castagnoliArchImpl {
87 archInitCastagnoli()
88 updateCastagnoli = archUpdateCastagnoli
89 } else {
90
91 castagnoliTable8 = slicingMakeTable(Castagnoli)
92 updateCastagnoli = func(crc uint32, p []byte) uint32 {
93 return slicingUpdate(crc, castagnoliTable8, p)
94 }
95 }
96 }
97
98
99 var IEEETable = simpleMakeTable(IEEE)
100
101
102 var ieeeTable8 *slicing8Table
103 var ieeeArchImpl bool
104 var updateIEEE func(crc uint32, p []byte) uint32
105 var ieeeOnce sync.Once
106
107 func ieeeInit() {
108 ieeeArchImpl = archAvailableIEEE()
109
110 if ieeeArchImpl {
111 archInitIEEE()
112 updateIEEE = archUpdateIEEE
113 } else {
114
115 ieeeTable8 = slicingMakeTable(IEEE)
116 updateIEEE = func(crc uint32, p []byte) uint32 {
117 return slicingUpdate(crc, ieeeTable8, p)
118 }
119 }
120 }
121
122
123
124 func MakeTable(poly uint32) *Table {
125 switch poly {
126 case IEEE:
127 ieeeOnce.Do(ieeeInit)
128 return IEEETable
129 case Castagnoli:
130 castagnoliOnce.Do(castagnoliInit)
131 return castagnoliTable
132 }
133 return simpleMakeTable(poly)
134 }
135
136
137 type digest struct {
138 crc uint32
139 tab *Table
140 }
141
142
143
144
145
146
147 func New(tab *Table) hash.Hash32 {
148 if tab == IEEETable {
149 ieeeOnce.Do(ieeeInit)
150 }
151 return &digest{0, tab}
152 }
153
154
155
156
157
158
159 func NewIEEE() hash.Hash32 { return New(IEEETable) }
160
161 func (d *digest) Size() int { return Size }
162
163 func (d *digest) BlockSize() int { return 1 }
164
165 func (d *digest) Reset() { d.crc = 0 }
166
167 const (
168 magic = "crc\x01"
169 marshaledSize = len(magic) + 4 + 4
170 )
171
172 func (d *digest) MarshalBinary() ([]byte, error) {
173 b := make([]byte, 0, marshaledSize)
174 b = append(b, magic...)
175 b = appendUint32(b, tableSum(d.tab))
176 b = appendUint32(b, d.crc)
177 return b, nil
178 }
179
180 func (d *digest) UnmarshalBinary(b []byte) error {
181 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
182 return errors.New("hash/crc32: invalid hash state identifier")
183 }
184 if len(b) != marshaledSize {
185 return errors.New("hash/crc32: invalid hash state size")
186 }
187 if tableSum(d.tab) != readUint32(b[4:]) {
188 return errors.New("hash/crc32: tables do not match")
189 }
190 d.crc = readUint32(b[8:])
191 return nil
192 }
193
194 func appendUint32(b []byte, x uint32) []byte {
195 a := [4]byte{
196 byte(x >> 24),
197 byte(x >> 16),
198 byte(x >> 8),
199 byte(x),
200 }
201 return append(b, a[:]...)
202 }
203
204 func readUint32(b []byte) uint32 {
205 _ = b[3]
206 return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
207 }
208
209
210 func Update(crc uint32, tab *Table, p []byte) uint32 {
211 switch tab {
212 case castagnoliTable:
213 return updateCastagnoli(crc, p)
214 case IEEETable:
215
216
217 ieeeOnce.Do(ieeeInit)
218 return updateIEEE(crc, p)
219 default:
220 return simpleUpdate(crc, tab, p)
221 }
222 }
223
224 func (d *digest) Write(p []byte) (n int, err error) {
225 switch d.tab {
226 case castagnoliTable:
227 d.crc = updateCastagnoli(d.crc, p)
228 case IEEETable:
229
230
231 d.crc = updateIEEE(d.crc, p)
232 default:
233 d.crc = simpleUpdate(d.crc, d.tab, p)
234 }
235 return len(p), nil
236 }
237
238 func (d *digest) Sum32() uint32 { return d.crc }
239
240 func (d *digest) Sum(in []byte) []byte {
241 s := d.Sum32()
242 return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
243 }
244
245
246
247 func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
248
249
250
251 func ChecksumIEEE(data []byte) uint32 {
252 ieeeOnce.Do(ieeeInit)
253 return updateIEEE(0, data)
254 }
255
256
257 func tableSum(t *Table) uint32 {
258 var a [1024]byte
259 b := a[:0]
260 if t != nil {
261 for _, x := range t {
262 b = appendUint32(b, x)
263 }
264 }
265 return ChecksumIEEE(b)
266 }
267
View as plain text