// 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 crc32 implements the 32-bit cyclic redundancy check, or CRC-32,// checksum. See https://en.wikipedia.org/wiki/Cyclic_redundancy_check for// information.//// Polynomials are represented in LSB-first form also known as reversed representation.//// See https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials// for information.
package crc32import ()// The size of a CRC-32 checksum in bytes.constSize = 4// Predefined polynomials.const (// IEEE is by far and away the most common CRC-32 polynomial. // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...IEEE = 0xedb88320// Castagnoli's polynomial, used in iSCSI. // Has better error detection characteristics than IEEE. // https://dx.doi.org/10.1109/26.231911Castagnoli = 0x82f63b78// Koopman's polynomial. // Also has better error detection characteristics than IEEE. // https://dx.doi.org/10.1109/DSN.2002.1028931Koopman = 0xeb31d82e)// Table is a 256-word table representing the polynomial for efficient processing.typeTable [256]uint32// This file makes use of functions implemented in architecture-specific files.// The interface that they implement is as follows://// // archAvailableIEEE reports whether an architecture-specific CRC32-IEEE// // algorithm is available.// archAvailableIEEE() bool//// // archInitIEEE initializes the architecture-specific CRC3-IEEE algorithm.// // It can only be called if archAvailableIEEE() returns true.// archInitIEEE()//// // archUpdateIEEE updates the given CRC32-IEEE. It can only be called if// // archInitIEEE() was previously called.// archUpdateIEEE(crc uint32, p []byte) uint32//// // archAvailableCastagnoli reports whether an architecture-specific// // CRC32-C algorithm is available.// archAvailableCastagnoli() bool//// // archInitCastagnoli initializes the architecture-specific CRC32-C// // algorithm. It can only be called if archAvailableCastagnoli() returns// // true.// archInitCastagnoli()//// // archUpdateCastagnoli updates the given CRC32-C. It can only be called// // if archInitCastagnoli() was previously called.// archUpdateCastagnoli(crc uint32, p []byte) uint32// castagnoliTable points to a lazily initialized Table for the Castagnoli// polynomial. MakeTable will always return this value when asked to make a// Castagnoli table so we can compare against it to find when the caller is// using this polynomial.varcastagnoliTable *TablevarcastagnoliTable8 *slicing8TablevarupdateCastagnolifunc(crc uint32, p []byte) uint32varcastagnoliOncesync.OncevarhaveCastagnoliatomic.Boolfunc () {castagnoliTable = simpleMakeTable(Castagnoli)ifarchAvailableCastagnoli() {archInitCastagnoli()updateCastagnoli = archUpdateCastagnoli } else {// Initialize the slicing-by-8 table.castagnoliTable8 = slicingMakeTable(Castagnoli)updateCastagnoli = func( uint32, []byte) uint32 {returnslicingUpdate(, castagnoliTable8, ) } }haveCastagnoli.Store(true)}// IEEETable is the table for the IEEE polynomial.varIEEETable = simpleMakeTable(IEEE)// ieeeTable8 is the slicing8Table for IEEEvarieeeTable8 *slicing8TablevarupdateIEEEfunc(crc uint32, p []byte) uint32varieeeOncesync.Oncefunc () {ifarchAvailableIEEE() {archInitIEEE()updateIEEE = archUpdateIEEE } else {// Initialize the slicing-by-8 table.ieeeTable8 = slicingMakeTable(IEEE)updateIEEE = func( uint32, []byte) uint32 {returnslicingUpdate(, ieeeTable8, ) } }}// MakeTable returns a Table constructed from the specified polynomial.// The contents of this Table must not be modified.func ( uint32) *Table {switch {caseIEEE:ieeeOnce.Do(ieeeInit)returnIEEETablecaseCastagnoli:castagnoliOnce.Do(castagnoliInit)returncastagnoliTabledefault:returnsimpleMakeTable() }}// digest represents the partial evaluation of a checksum.typedigeststruct {crcuint32tab *Table}// New creates a new hash.Hash32 computing the CRC-32 checksum using the// polynomial represented by the Table. Its Sum method will lay the// value out in big-endian byte order. The returned Hash32 also// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to// marshal and unmarshal the internal state of the hash.func ( *Table) hash.Hash32 {if == IEEETable {ieeeOnce.Do(ieeeInit) }return &digest{0, }}// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum using// the IEEE polynomial. Its Sum method will lay the value out in// big-endian byte order. The returned Hash32 also implements// encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal// and unmarshal the internal state of the hash.func () hash.Hash32 { returnNew(IEEETable) }func ( *digest) () int { returnSize }func ( *digest) () int { return1 }func ( *digest) () { .crc = 0 }const (magic = "crc\x01"marshaledSize = len(magic) + 4 + 4)func ( *digest) () ([]byte, error) { := make([]byte, 0, marshaledSize) = append(, magic...) = appendUint32(, tableSum(.tab)) = appendUint32(, .crc)return , nil}func ( *digest) ( []byte) error {iflen() < len(magic) || string([:len(magic)]) != magic {returnerrors.New("hash/crc32: invalid hash state identifier") }iflen() != marshaledSize {returnerrors.New("hash/crc32: invalid hash state size") }iftableSum(.tab) != readUint32([4:]) {returnerrors.New("hash/crc32: tables do not match") } .crc = readUint32([8:])returnnil}func ( []byte, uint32) []byte { := [4]byte{byte( >> 24),byte( >> 16),byte( >> 8),byte(), }returnappend(, [:]...)}func ( []byte) uint32 { _ = [3]returnuint32([3]) | uint32([2])<<8 | uint32([1])<<16 | uint32([0])<<24}func ( uint32, *Table, []byte, bool) uint32 {switch {casehaveCastagnoli.Load() && == castagnoliTable:returnupdateCastagnoli(, )case == IEEETable:if {ieeeOnce.Do(ieeeInit) }returnupdateIEEE(, )default:returnsimpleUpdate(, , ) }}// Update returns the result of adding the bytes in p to the crc.func ( uint32, *Table, []byte) uint32 {// Unfortunately, because IEEETable is exported, IEEE may be used without a // call to MakeTable. We have to make sure it gets initialized in that case.returnupdate(, , , true)}func ( *digest) ( []byte) ( int, error) {// We only create digest objects through New() which takes care of // initialization in this case. .crc = update(.crc, .tab, , false)returnlen(), nil}func ( *digest) () uint32 { return .crc }func ( *digest) ( []byte) []byte { := .Sum32()returnappend(, byte(>>24), byte(>>16), byte(>>8), byte())}// Checksum returns the CRC-32 checksum of data// using the polynomial represented by the Table.func ( []byte, *Table) uint32 { returnUpdate(0, , ) }// ChecksumIEEE returns the CRC-32 checksum of data// using the IEEE polynomial.func ( []byte) uint32 {ieeeOnce.Do(ieeeInit)returnupdateIEEE(0, )}// tableSum returns the IEEE checksum of table t.func ( *Table) uint32 {var [1024]byte := [:0]if != nil {for , := range { = appendUint32(, ) } }returnChecksumIEEE()}
The pages are generated with Goldsv0.6.7. (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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds.