PR c++/86342 - -Wdeprecated-copy and system headers.
[official-gcc.git] / libgo / go / hash / crc64 / crc64.go
blob3b24c2440628aac249818fd2e1aaab7c9d6b1a56
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.
5 // Package crc64 implements the 64-bit cyclic redundancy check, or CRC-64,
6 // checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
7 // information.
8 package crc64
10 import (
11 "errors"
12 "hash"
15 // The size of a CRC-64 checksum in bytes.
16 const Size = 8
18 // Predefined polynomials.
19 const (
20 // The ISO polynomial, defined in ISO 3309 and used in HDLC.
21 ISO = 0xD800000000000000
23 // The ECMA polynomial, defined in ECMA 182.
24 ECMA = 0xC96C5795D7870F42
27 // Table is a 256-word table representing the polynomial for efficient processing.
28 type Table [256]uint64
30 var (
31 slicing8TableISO = makeSlicingBy8Table(makeTable(ISO))
32 slicing8TableECMA = makeSlicingBy8Table(makeTable(ECMA))
35 // MakeTable returns a Table constructed from the specified polynomial.
36 // The contents of this Table must not be modified.
37 func MakeTable(poly uint64) *Table {
38 switch poly {
39 case ISO:
40 return &slicing8TableISO[0]
41 case ECMA:
42 return &slicing8TableECMA[0]
43 default:
44 return makeTable(poly)
48 func makeTable(poly uint64) *Table {
49 t := new(Table)
50 for i := 0; i < 256; i++ {
51 crc := uint64(i)
52 for j := 0; j < 8; j++ {
53 if crc&1 == 1 {
54 crc = (crc >> 1) ^ poly
55 } else {
56 crc >>= 1
59 t[i] = crc
61 return t
64 func makeSlicingBy8Table(t *Table) *[8]Table {
65 var helperTable [8]Table
66 helperTable[0] = *t
67 for i := 0; i < 256; i++ {
68 crc := t[i]
69 for j := 1; j < 8; j++ {
70 crc = t[crc&0xff] ^ (crc >> 8)
71 helperTable[j][i] = crc
74 return &helperTable
77 // digest represents the partial evaluation of a checksum.
78 type digest struct {
79 crc uint64
80 tab *Table
83 // New creates a new hash.Hash64 computing the CRC-64 checksum using the
84 // polynomial represented by the Table. Its Sum method will lay the
85 // value out in big-endian byte order. The returned Hash64 also
86 // implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
87 // marshal and unmarshal the internal state of the hash.
88 func New(tab *Table) hash.Hash64 { return &digest{0, tab} }
90 func (d *digest) Size() int { return Size }
92 func (d *digest) BlockSize() int { return 1 }
94 func (d *digest) Reset() { d.crc = 0 }
96 const (
97 magic = "crc\x02"
98 marshaledSize = len(magic) + 8 + 8
101 func (d *digest) MarshalBinary() ([]byte, error) {
102 b := make([]byte, 0, marshaledSize)
103 b = append(b, magic...)
104 b = appendUint64(b, tableSum(d.tab))
105 b = appendUint64(b, d.crc)
106 return b, nil
109 func (d *digest) UnmarshalBinary(b []byte) error {
110 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
111 return errors.New("hash/crc64: invalid hash state identifier")
113 if len(b) != marshaledSize {
114 return errors.New("hash/crc64: invalid hash state size")
116 if tableSum(d.tab) != readUint64(b[4:]) {
117 return errors.New("hash/crc64: tables do not match")
119 d.crc = readUint64(b[12:])
120 return nil
123 func appendUint64(b []byte, x uint64) []byte {
124 a := [8]byte{
125 byte(x >> 56),
126 byte(x >> 48),
127 byte(x >> 40),
128 byte(x >> 32),
129 byte(x >> 24),
130 byte(x >> 16),
131 byte(x >> 8),
132 byte(x),
134 return append(b, a[:]...)
137 func readUint64(b []byte) uint64 {
138 _ = b[7]
139 return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
140 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
143 func update(crc uint64, tab *Table, p []byte) uint64 {
144 crc = ^crc
145 // Table comparison is somewhat expensive, so avoid it for small sizes
146 for len(p) >= 64 {
147 var helperTable *[8]Table
148 if *tab == slicing8TableECMA[0] {
149 helperTable = slicing8TableECMA
150 } else if *tab == slicing8TableISO[0] {
151 helperTable = slicing8TableISO
152 // For smaller sizes creating extended table takes too much time
153 } else if len(p) > 16384 {
154 helperTable = makeSlicingBy8Table(tab)
155 } else {
156 break
158 // Update using slicing-by-8
159 for len(p) > 8 {
160 crc ^= uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
161 uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
162 crc = helperTable[7][crc&0xff] ^
163 helperTable[6][(crc>>8)&0xff] ^
164 helperTable[5][(crc>>16)&0xff] ^
165 helperTable[4][(crc>>24)&0xff] ^
166 helperTable[3][(crc>>32)&0xff] ^
167 helperTable[2][(crc>>40)&0xff] ^
168 helperTable[1][(crc>>48)&0xff] ^
169 helperTable[0][crc>>56]
170 p = p[8:]
173 // For reminders or small sizes
174 for _, v := range p {
175 crc = tab[byte(crc)^v] ^ (crc >> 8)
177 return ^crc
180 // Update returns the result of adding the bytes in p to the crc.
181 func Update(crc uint64, tab *Table, p []byte) uint64 {
182 return update(crc, tab, p)
185 func (d *digest) Write(p []byte) (n int, err error) {
186 d.crc = update(d.crc, d.tab, p)
187 return len(p), nil
190 func (d *digest) Sum64() uint64 { return d.crc }
192 func (d *digest) Sum(in []byte) []byte {
193 s := d.Sum64()
194 return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
197 // Checksum returns the CRC-64 checksum of data
198 // using the polynomial represented by the Table.
199 func Checksum(data []byte, tab *Table) uint64 { return update(0, tab, data) }
201 // tableSum returns the ISO checksum of table t.
202 func tableSum(t *Table) uint64 {
203 var a [2048]byte
204 b := a[:0]
205 if t != nil {
206 for _, x := range t {
207 b = appendUint64(b, x)
210 return Checksum(b, MakeTable(ISO))