crc

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2018 License: BSD-3-Clause Imports: 0 Imported by: 37

README

crc GoDoc

This package implements generic CRC calculations up to 64 bits wide. It aims to be fairly fast and fairly complete, allowing users to match pretty much any CRC algorithm used in the wild by choosing appropriate Parameters. This obviously includes all popular CRC algorithms, such as CRC64-ISO, CRC64-ECMA, CRC32, CRC32C, CRC16, CCITT, XMODEM and many others. See http://reveng.sourceforge.net/crc-catalogue/ for a good list of CRC algorithms and their parameters.

This package has been largely inspired by Ross Williams' 1993 paper "A Painless Guide to CRC Error Detection Algorithms".

Installation

To install, simply execute:

go get github.com/snksoft/crc

or:

go get gopkg.in/snksoft/crc.v1

Usage

Using crc is easy. Here is an example of calculating a CCITT crc.

package main

import (
	"fmt"
	"github.com/snksoft/crc"
)

func main() {
	data := "123456789"
	ccittCrc := crc.CalculateCRC(crc.CCITT, []byte(data))
	fmt.Printf("CRC is 0x%04X\n", ccittCrc) // prints "CRC is 0x29B1"
}

For larger data, table driven implementation is faster. Note that crc.Hash implements hash.Hash interface, so you can use it instead if you want.
Here is how to use it:

package main

import (
	"fmt"
	"github.com/snksoft/crc"
)

func main() {
	data := "123456789"
	hash := crc.NewHash(crc.XMODEM)
	xmodemCrc := hash.CalculateCRC([]byte(data))
	fmt.Printf("CRC is 0x%04X\n", xmodemCrc) // prints "CRC is 0x31C3"

	// You can also reuse hash instance for another crc calculation
	// And if data is too big, you may feed it in chunks
	hash.Reset() // Discard crc data accumulated so far
	hash.Update([]byte("123456789")) // feed first chunk
	hash.Update([]byte("01234567890")) // feed next chunk
	xmodemCrc2 := hash.CRC() // gets CRC of whole data "12345678901234567890"
	fmt.Printf("CRC is 0x%04X\n", xmodemCrc2) // prints "CRC is 0x2C89"
}

New in version 1.1

In this version I have separated actual CRC caclulations and Hash interface implementation. New Table type incorporates table based implementation which can be used without creating a Hash instance. The main difference is that Table instances are essentially immutable once initialized. This greatly simplifies concurrent use as Table instances can be safely used in concurrent applications without tricky copying or synchronization. The downside is, however, that feeding data in multiple chunks becomes a bit more verbose (as you essentially maintain intermediate crc in your code and keep feeding it back to subsequent calls). So, you might prefer one or the other depending on situation at hand and personal preferences. You even can ask a Hash instance for a Table instance it uses internally and then use both in parallel without recalculating the crc table.

Anyway, here is how to use a Table directly.

package main

import (
	"fmt"
	"github.com/snksoft/crc"
)

func main() {
	data := []byte("123456789")

	// create a Table
	crcTable := crc.NewTable(crc.XMODEM)

	// Simple calculation all in one go
	xmodemCrc := crcTable.CalculateCRC(data)
	fmt.Printf("CRC is 0x%04X\n", xmodemCrc) // prints "CRC is 0x31C3"

	// You can also reuse same Table for another crc calculation
	// or even calculate multiple crc in parallel using same Table
	crc1 := crcTable.InitCrc()
	crc1 = crcTable.UpdateCrc(crc1, []byte("1234567890")) // feed first chunk to first crc
	crc2 := crcTable.InitCrc()
	crc2 = crcTable.UpdateCrc(crc2, data)                  // feed first chunk to second crc
	crc1 = crcTable.UpdateCrc(crc1, []byte("1234567890")) // feed second chunk to first crc

	// Now finish calcuation for both
	crc1 = crcTable.CRC(crc1)
	crc2 = crcTable.CRC(crc2)

	fmt.Printf("CRC is 0x%04X\n", crc1) // prints "CRC is 0x2C89"
	fmt.Printf("CRC is 0x%04X\n", crc2) // prints "CRC is 0x31C3"
}

Notes

Beware that Hash instance is not thread safe. If you want to do parallel CRC calculations (and actually need it to be Hash, not Table), then either use NewHash() to create multiple Hash instances or simply make a copy of Hash whehever you need it. Latter option avoids recalculating CRC table, but keep in mind that NewHash() returns a pointer, so simple assignement will point to the same instance. Use either

hash2 := &crc.Hash{}
*hash2 = *hash

or simply

var hash2 = *hash

Documentation

Overview

Package crc implements generic CRC calculations up to 64 bits wide. It aims to be fairly complete, allowing users to match pretty much any CRC algorithm used in the wild by choosing appropriate Parameters. And it's also fairly fast for everyday use.

This package has been largely inspired by Ross Williams' 1993 paper "A Painless Guide to CRC Error Detection Algorithms". A good list of parameter sets for various CRC algorithms can be found at http://reveng.sourceforge.net/crc-catalogue/.

Index

Constants

This section is empty.

Variables

View Source
var (
	// X-25 CRC parameters, also known as CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
	X25 = &Parameters{Width: 16, Polynomial: 0x1021, Init: 0xFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFF}
	// CCITT CRC parameters
	CCITT = &Parameters{Width: 16, Polynomial: 0x1021, Init: 0xFFFF, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}
	// CRC16 CRC parameters, also known as ARC
	CRC16 = &Parameters{Width: 16, Polynomial: 0x8005, Init: 0x0000, ReflectIn: true, ReflectOut: true, FinalXor: 0x0}
	// XMODEM is a set of CRC parameters commonly referred as "XMODEM"
	XMODEM = &Parameters{Width: 16, Polynomial: 0x1021, Init: 0x0000, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}
	// XMODEM2 is another set of CRC parameters commonly referred as "XMODEM"
	XMODEM2 = &Parameters{Width: 16, Polynomial: 0x8408, Init: 0x0000, ReflectIn: true, ReflectOut: true, FinalXor: 0x0}

	// CRC32 is by far the the most commonly used CRC-32 polynom and set of parameters
	CRC32 = &Parameters{Width: 32, Polynomial: 0x04C11DB7, Init: 0xFFFFFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF}
	// IEEE is an alias to CRC32
	IEEE = CRC32
	// Castagnoli polynomial. used in iSCSI. And also provided by hash/crc32 package.
	Castagnoli = &Parameters{Width: 32, Polynomial: 0x1EDC6F41, Init: 0xFFFFFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF}
	// CRC32C is an alias to Castagnoli
	CRC32C = Castagnoli
	// Koopman polynomial
	Koopman = &Parameters{Width: 32, Polynomial: 0x741B8CD7, Init: 0xFFFFFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF}

	// CRC64ISO is set of parameters commonly known as CRC64-ISO
	CRC64ISO = &Parameters{Width: 64, Polynomial: 0x000000000000001B, Init: 0xFFFFFFFFFFFFFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFFFFFFFFFF}
	// CRC64ECMA is set of parameters commonly known as CRC64-ECMA
	CRC64ECMA = &Parameters{Width: 64, Polynomial: 0x42F0E1EBA9EA3693, Init: 0xFFFFFFFFFFFFFFFF, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFFFFFFFFFF}
)

Functions

func CalculateCRC

func CalculateCRC(crcParams *Parameters, data []byte) uint64

CalculateCRC implements simple straight forward bit by bit calculation. It is relatively slow for large amounts of data, but does not require any preparation steps. As a result, it might be faster in some cases then building a table required for faster calculation.

Note: this implementation follows section 8 ("A Straightforward CRC Implementation") of Ross N. Williams paper as even though final/sample implementation of this algorithm provided near the end of that paper (and followed by most other implementations) is a bit faster, it does not work for polynomials shorter then 8 bits. And if you need speed, you shoud probably be using table based implementation anyway.

Types

type Hash

type Hash struct {
	// contains filtered or unexported fields
}

Hash represents the partial evaluation of a checksum using table-driven implementation. It also implements hash.Hash interface.

func NewHash

func NewHash(crcParams *Parameters) *Hash

NewHash creates a new Hash instance configured for table driven CRC calculation according to parameters specified.

func NewHashWithTable added in v1.1.0

func NewHashWithTable(table *Table) *Hash

NewHashWithTable creates a new Hash instance configured for table driven CRC calculation using a Table instance created elsewhere.

func (*Hash) BlockSize

func (h *Hash) BlockSize() int

BlockSize returns the hash's underlying block size. The Write method must be able to accept any amount of data, but it may operate more efficiently if all writes are a multiple of the block size. See hash.Hash interface.

func (*Hash) CRC

func (h *Hash) CRC() uint64

CRC returns current CRC value for the data processed so far.

func (*Hash) CRC16

func (h *Hash) CRC16() uint16

CRC16 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Hash) CRC32

func (h *Hash) CRC32() uint32

CRC32 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Hash) CRC8

func (h *Hash) CRC8() uint8

CRC8 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Hash) CalculateCRC

func (h *Hash) CalculateCRC(data []byte) uint64

CalculateCRC is a convenience function allowing to calculate CRC in one call.

func (*Hash) Reset

func (h *Hash) Reset()

Reset resets the Hash to its initial state. See hash.Hash interface.

func (*Hash) Size

func (h *Hash) Size() int

Size returns the number of bytes Sum will return. See hash.Hash interface.

func (*Hash) Sum

func (h *Hash) Sum(in []byte) []byte

Sum appends the current hash to b and returns the resulting slice. It does not change the underlying hash state. See hash.Hash interface.

func (*Hash) Table added in v1.1.0

func (h *Hash) Table() *Table

Table used by this Hash under the hood

func (*Hash) Update

func (h *Hash) Update(p []byte)

Update updates process supplied bytes and updates current (partial) CRC accordingly.

func (*Hash) Write

func (h *Hash) Write(p []byte) (n int, err error)

Write implements io.Writer interface which is part of hash.Hash interface.

type Parameters

type Parameters struct {
	Width      uint   // Width of the CRC expressed in bits
	Polynomial uint64 // Polynomial used in this CRC calculation
	ReflectIn  bool   // ReflectIn indicates whether input bytes should be reflected
	ReflectOut bool   // ReflectOut indicates whether input bytes should be reflected
	Init       uint64 // Init is initial value for CRC calculation
	FinalXor   uint64 // Xor is a value for final xor to be applied before returning result
}

Parameters represents set of parameters defining a particular CRC algorithm.

type Table added in v1.1.0

type Table struct {
	// contains filtered or unexported fields
}

Table represents the partial evaluation of a checksum using table-driven implementation. It is essentially immutable once initialized and thread safe as a result.

func NewTable added in v1.1.0

func NewTable(crcParams *Parameters) *Table

NewTable creates and initializes a new Table for the CRC algorithm specified by the crcParams.

func (*Table) CRC added in v1.1.0

func (t *Table) CRC(curValue uint64) uint64

CRC returns CRC value for the data processed so far.

func (*Table) CRC16 added in v1.1.0

func (t *Table) CRC16(curValue uint64) uint16

CRC16 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Table) CRC32 added in v1.1.0

func (t *Table) CRC32(curValue uint64) uint32

CRC32 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Table) CRC8 added in v1.1.0

func (t *Table) CRC8(curValue uint64) uint8

CRC8 is a convenience method to spare end users from explicit type conversion every time this package is used. Underneath, it just calls CRC() method.

func (*Table) CalculateCRC added in v1.1.0

func (t *Table) CalculateCRC(data []byte) uint64

CalculateCRC is a convenience function allowing to calculate CRC in one call.

func (*Table) InitCrc added in v1.1.0

func (t *Table) InitCrc() uint64

InitCrc returns a stating value for a new CRC calculation

func (*Table) UpdateCrc added in v1.1.0

func (t *Table) UpdateCrc(curValue uint64, p []byte) uint64

UpdateCrc process supplied bytes and updates current (partial) CRC accordingly. It can be called repetitively to process larger data in chunks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL