crcutil

package module
v0.1.0-alpha2 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2022 License: MIT Imports: 5 Imported by: 0

README

Go Reference

crcutil

This module implements support for CRC calculation.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func BitwiseUpdateFn

func BitwiseUpdateFn[T, D Word](poly *Poly[T]) func(poly *Poly[T], crc T, data D, dataWidth int) T

BitwiseUpdateFn returns a function that returns the result of adding the bits defined by data and dataWidth into the crc. The actual function returned depends on the polynomial's representation (normal or reversed form).

func UpdateBitwise

func UpdateBitwise[T, D Word](poly *Poly[T], crc T, data D, dataWidth int) T

Types

type Impl

type Impl[T Word] interface {
	Update(crc T, tab []T, p []byte) T
	Append(b []byte, crc T) []byte
}

type Inst

type Inst[T Word] struct {
	// contains filtered or unexported fields
}

Inst is an instance of a Model; it contains the current state of the crc calculation. current state of

func (*Inst[T]) AppendSum

func (inst *Inst[T]) AppendSum(in []byte) []byte

AppendSum appends the crc checksum to the provided slice and returns the resulting slice. If AppendSumXORed is set, it will apply, if specified, the final inversion or final xor value before appending the checksum, otherwise this step will be skipped. Calling AppendSum does not change the instance's current state.

func (*Inst[T]) Reset

func (inst *Inst[T]) Reset()

Reset sets the instance back to its initial state.

func (*Inst[T]) Sum

func (inst *Inst[T]) Sum() T

Sum returns the crc checksum; it does not change the current state.

func (*Inst[T]) Update

func (inst *Inst[T]) Update(p []byte)

Update adds bytes in p to the crc

func (*Inst[T]) Write

func (inst *Inst[T]) Write(p []byte) (n int, err error)

Write implements an io.Writer to add bytes to the crc.

type InstOption

type InstOption func(*instConf)

func AppendSumSkipFinalXOR

func AppendSumSkipFinalXOR() InstOption

AppendSumSkipFinalXOR ensures that when calling AppendSum the final inversion or xor-ing will be skipped.

type Model

type Model[T Word] struct {
	Poly *Poly[T]

	// Table may be assigned an alternative table to be used for
	// calculation. On default, MakeTable derives a table from Poly.
	Table []T

	// Initial is the start value to be used for crc calculation.
	// If left empty, zero will be used.
	Initial T

	// InitialInvert may be set to true, if the initial value shall
	// be inverted. If Initial is left empty, setting InitialInvert
	// has the effect of an initial value with all bits set.
	InitialInvert bool

	// FinalInvert may be set to true, if a crc value shall
	// be inverted before being returned as checksum.
	// Alternatively, FinalXOR could be set to a value with all bits set
	// for the same effect.
	FinalInvert bool

	// FinalXOR may contain a value to be XORed into the crc value
	// before returning the checksum. In most cases leaving FinalXOR
	// empty, and setting FinalInvert instead will suffice, as cases
	// where the final step isn't either a no-op or an inversion,
	// but an XOR-operation with a specific value seem rare.
	FinalXOR T
}

Model defines how a concrete CRC calculation should be performed, based on a polynomial, and parameters. To calculate a crc value, an instance needs to be created using New, followed by calls to methods Write or Update, and if appropriate, Reset.

A Model may also be used to create a hash.Hash using packages github.com/knieriem/hash/crc8 or packages github.com/knieriem/hash/crc16.

Example

This example calculates a Modbus crc over an example frame; see “MODBUS over serial line specification and implementation guide V1.02”, p. 41

package main

import (
	"fmt"

	"github.com/knieriem/crcutil"
	"github.com/knieriem/crcutil/crc16"
	"github.com/knieriem/crcutil/poly16"
)

var (
	ibmcrc = &crcutil.Model[uint16]{
		Poly:          poly16.IBM.ReversedForm(),
		InitialInvert: true,
	}
)

// This example calculates a Modbus crc over an example frame;
// see “MODBUS over serial line specification and implementation guide V1.02”, p. 41
func main() {
	inst := ibmcrc.New()
	inst.Update([]byte{2, 7})

	fmt.Printf("%#04x\n", inst.Sum())

	// Alternatively, use a predefined model:
	sum := crc16.Modbus.Checksum([]byte{2, 7})
	fmt.Printf("%#04x", sum)
}
Output:

0x1241
0x1241

func (*Model[T]) Checksum

func (m *Model[T]) Checksum(data []byte) T

Checksum returns the CRC checksum calculated over the bytes in the data slice.

func (*Model[T]) MakeTable

func (m *Model[T]) MakeTable() []T

MakeTable returns the lookup table stored in the Table field. If this field is nil, a table generated by Poly.MakeTable() will be returned.

func (*Model[T]) New

func (m *Model[T]) New(opts ...InstOption) *Inst[T]

NewInst returns a new instance of the Model.

type Poly

type Poly[T Word] struct {
	Word       T
	Width      int
	Reversed   bool
	Reciprocal bool
}

Poly defines a polynomial in a specific representation.

Example

This example calculates representations of the CCITT-16 polynomial as shown in https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Polynomial_representations

package main

import (
	"fmt"

	"github.com/knieriem/crcutil"
	"github.com/knieriem/crcutil/poly16"
)

var ccitt16 = poly16.CCITT

// This example calculates representations of the CCITT-16
// polynomial as shown in
// https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Polynomial_representations
func main() {
	reversed := ccitt16.ReversedForm()

	formatPoly("reversed", reversed)
	formatPoly("reciprocal", ccitt16.ReciprocalForm())
	formatPoly("reversed reciprocal", reversed.ReciprocalForm())

}

func formatPoly[T crcutil.Word](variant string, poly *crcutil.Poly[T]) {
	fmt.Printf("%#04x\t%s\n", poly.Word, variant)
}
Output:

0x8408	reversed
0x0811	reciprocal
0x8810	reversed reciprocal

func (*Poly[T]) Impl

func (p *Poly[T]) Impl() Impl[T]

func (*Poly[T]) LSBitFirst

func (p *Poly[T]) LSBitFirst() bool

LSBitFirst reports whether the polynomial's representation is lsbit-first.

func (*Poly[T]) MakeTable

func (poly *Poly[T]) MakeTable(opts ...TableOption) []T

MakeTable creates a lookup table for the specified polynomial. The size of the table returned equals the length of the value range determined by the number of data bits.

Example
package main

import (
	"fmt"

	"github.com/knieriem/crcutil"
	"github.com/knieriem/crcutil/poly3"
)

// This example shows how to calculate a 3-bit CRC over
// 13 bits of data from two bytes of a frame of a serial
// communication protocol:
//
//	byte 0: crc (3 bits) | device address (5 bits)
//	byte 1: function code + length (8 bits)
//
// A specific algorithm will be used: 3-bit polynomial 0x3 (GSM),
// in reversed form. With an initial value of 5, the crc is calculated first
// over the five bits of the first byte, then the 8 bits of the second byte.
// After adding the 8 bit value, the crc result shall be mirrored (reflected).
// We will create
// -	one table for the 5 bit lookup, which already
// 	regards for the initial value, and
// -	one table for the 8 bit lookup, which produces a reflected result.

type crcTabs struct {
	t1 []uint8
	t2 []uint8
}

var crc3 crcTabs

func init() {
	poly := poly3.GSM.ReversedForm()

	initialValue := crcutil.WithInitialValue(5)
	fiveBits := crcutil.WithDataWidth(5)

	crc3.t1 = poly.MakeTable(initialValue, fiveBits)
	crc3.t2 = poly.MakeTable(crcutil.WithReversedBits())
}

// Then we can calculate the checksum by performing
// a table lookup first for the 5-bit data part, XOR-ing the result
// with the 8-bit data part, and doing a lookup of this value with
// the other table.
func (tabs *crcTabs) checksum(v1, v2 uint8) uint8 {
	crc := tabs.t1[v1]
	return tabs.t2[crc^v2]
}

// With the 5-bit device address being 10, and a value of the second
// byte of 0b0111_0101, the checksum should be 4.

func main() {
	sum := crc3.checksum(10, 0b0111_0101)
	fmt.Println(sum)
}
Output:

4

func (*Poly[T]) NormalForm

func (p *Poly[T]) NormalForm() *Poly[T]

NormalForm returns the normal form of the polynomial.

Example

This example calculates the normal representation of the x^16 + x^15 + x^2 + 1 polynomial back from its reversed and reversed reciprocal representations.

package main

import (
	"fmt"

	"github.com/knieriem/crcutil/poly16"
)

func main() {
	r := &poly16.Poly{Word: 0x8408, Width: poly16.N, Reversed: true}
	rr := &poly16.Poly{Word: 0x8810, Width: poly16.N, Reversed: true, Reciprocal: true}

	fmt.Printf("%#04x %#04x", r.NormalForm().Word, rr.NormalForm().Word)
}
Output:

0x1021 0x1021

func (*Poly[T]) ReciprocalForm

func (p *Poly[T]) ReciprocalForm() *Poly[T]

ReciprocalForm returns the reciprocal form of the polynomial that can be obtained by mirroring its coefficients. It returns the unchanged polynomial if it is already in its reciprocal form.

func (*Poly[T]) ReversedForm

func (p *Poly[T]) ReversedForm() *Poly[T]

ReversedForm returns the reversed, lsbit-first form of the polynomial. It returns the unchanged polynomial if it is already in its reversed form.

type TableOption

type TableOption func(*tableConf)

func WithDataWidth

func WithDataWidth(n int) TableOption

WithDataWidth sets the data width to n bits, which will result in a table of 2^n entries for n-bit-wise processing. The default width is 8 bits for byte-wise processing.

func WithInitialValue

func WithInitialValue(initial uint32) TableOption

WithInitialValue ensures that when a table is created the specified initial value will be applied to the calculation of each table entry. In cases where a table later is used manually, like when a CRC is calulated over some bits only, this saves one XOR operation.

func WithReversedBits

func WithReversedBits() TableOption

WithReversedBits table option mirrors the bits of each table entry.

type Word

type Word interface {
	uint8 | uint16 | uint32
}

A Word holds the word representation of a polynomial.

Directories

Path Synopsis
internal
impl
Package impl contains implementations of the crcutil.Impl interface.
Package impl contains implementations of the crcutil.Impl interface.

Jump to

Keyboard shortcuts

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