// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.
// Package crc64 implements the 64-bit cyclic redundancy check, or CRC-64,// checksum. See https://en.wikipedia.org/wiki/Cyclic_redundancy_check for// information.
package crc64import ()// The size of a CRC-64 checksum in bytes.constSize = 8// Predefined polynomials.const (// The ISO polynomial, defined in ISO 3309 and used in HDLC.ISO = 0xD800000000000000// The ECMA polynomial, defined in ECMA 182.ECMA = 0xC96C5795D7870F42)// Table is a 256-word table representing the polynomial for efficient processing.typeTable [256]uint64var ( slicing8TableISO *[8]Table slicing8TableECMA *[8]Table)var buildSlicing8TablesOnce = sync.OnceFunc(buildSlicing8Tables)func buildSlicing8Tables() {slicing8TableISO = makeSlicingBy8Table(makeTable(ISO))slicing8TableECMA = makeSlicingBy8Table(makeTable(ECMA))}// MakeTable returns a [Table] constructed from the specified polynomial.// The contents of this [Table] must not be modified.func ( uint64) *Table {buildSlicing8TablesOnce()switch {caseISO:return &slicing8TableISO[0]caseECMA:return &slicing8TableECMA[0]default:returnmakeTable() }}func makeTable( uint64) *Table { := new(Table)for := 0; < 256; ++ { := uint64()for := 0; < 8; ++ {if &1 == 1 { = ( >> 1) ^ } else { >>= 1 } } [] = }return}func makeSlicingBy8Table( *Table) *[8]Table {var [8]Table [0] = *for := 0; < 256; ++ { := []for := 1; < 8; ++ { = [&0xff] ^ ( >> 8) [][] = } }return &}// digest represents the partial evaluation of a checksum.type digest struct { crc uint64 tab *Table}// New creates a new hash.Hash64 computing the CRC-64 checksum using the// polynomial represented by the [Table]. Its Sum method will lay the// value out in big-endian byte order. The returned Hash64 also// implements [encoding.BinaryMarshaler] and [encoding.BinaryUnmarshaler] to// marshal and unmarshal the internal state of the hash.func ( *Table) hash.Hash64 { return &digest{0, } }func ( *digest) () int { returnSize }func ( *digest) () int { return1 }func ( *digest) () { .crc = 0 }const ( magic = "crc\x02" marshaledSize = len(magic) + 8 + 8)func ( *digest) ( []byte) ([]byte, error) { = append(, magic...) = byteorder.BEAppendUint64(, tableSum(.tab)) = byteorder.BEAppendUint64(, .crc)return , nil}func ( *digest) () ([]byte, error) {return .AppendBinary(make([]byte, 0, marshaledSize))}func ( *digest) ( []byte) error {iflen() < len(magic) || string([:len(magic)]) != magic {returnerrors.New("hash/crc64: invalid hash state identifier") }iflen() != marshaledSize {returnerrors.New("hash/crc64: invalid hash state size") }iftableSum(.tab) != byteorder.BEUint64([4:]) {returnerrors.New("hash/crc64: tables do not match") } .crc = byteorder.BEUint64([12:])returnnil}func update( uint64, *Table, []byte) uint64 {buildSlicing8TablesOnce() = ^// Table comparison is somewhat expensive, so avoid it for small sizesforlen() >= 64 {var *[8]Tableif * == slicing8TableECMA[0] { = slicing8TableECMA } elseif * == slicing8TableISO[0] { = slicing8TableISO// For smaller sizes creating extended table takes too much time } elseiflen() >= 2048 {// According to the tests between various x86 and arm CPUs, 2k is a reasonable // threshold for now. This may change in the future. = makeSlicingBy8Table() } else {break }// Update using slicing-by-8forlen() > 8 { ^= byteorder.LEUint64() = [7][&0xff] ^ [6][(>>8)&0xff] ^ [5][(>>16)&0xff] ^ [4][(>>24)&0xff] ^ [3][(>>32)&0xff] ^ [2][(>>40)&0xff] ^ [1][(>>48)&0xff] ^ [0][>>56] = [8:] } }// For reminders or small sizesfor , := range { = [byte()^] ^ ( >> 8) }return ^}// Update returns the result of adding the bytes in p to the crc.func ( uint64, *Table, []byte) uint64 {returnupdate(, , )}func ( *digest) ( []byte) ( int, error) { .crc = update(.crc, .tab, )returnlen(), nil}func ( *digest) () uint64 { return .crc }func ( *digest) ( []byte) []byte { := .Sum64()returnappend(, byte(>>56), byte(>>48), byte(>>40), byte(>>32), byte(>>24), byte(>>16), byte(>>8), byte())}// Checksum returns the CRC-64 checksum of data// using the polynomial represented by the [Table].func ( []byte, *Table) uint64 { returnupdate(0, , ) }// tableSum returns the ISO checksum of table t.func tableSum( *Table) uint64 {var [2048]byte := [:0]if != nil {for , := range { = byteorder.BEAppendUint64(, ) } }returnChecksum(, MakeTable(ISO))}
The pages are generated with Goldsv0.7.3. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.