Features:
- Bitwise and lookup table crc algorithms
- Support for all parameterized crc algos from CRC RevEng (except >32 for now)
- Precomputations at compile time to speed up the calculation of parameterized crc algos
- Calculating any user-defined crc
- Calculating crc in parts (corresponding
balance
feature) - Calculating crc from file
- Support for x32/x64 architectures
- Pure nim
Todo:
- BE test (not tested yet)
- Docs
- Shift4 and Shift8 intel algos implementation
- Crc64 support
- Better
crcFromFile
Common use (the calculated CrcKind is known at compiletime):
import std/strutils
let
str = "123456789"
bytes = @[0x31'u8, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
assert str.crcBitwise(crc32Posix) == crc32Posix.takeCrcSpec.check
assert bytes.crcBitwise(crc16MaximDow).toHex(4) == "44C2"
Completely runtime:
for k in Crc32Kind:
# slower, larger executable file size -> not recommended use case
# instead use constant CrcKinds wherever is possible
discard "rt".crcBitwise(k.takeCrcSpec)
# first we initialize lookup
const ct = static: crc8.initLookup()
let rt = crc8.initLookup()
# then
assert "😎".crcLut(crc8, rt) == @[0xf0'u8, 0x9f, 0x98, 0x8e].crcLut(crc8, ct)
# additional import required
import w8crc/params/[crcbookplus, crckindsplus]
assert "123456789".crcBitwise(crc12Umts.takeCrcSpec) == crc12Umts.takeCrcSpec.check
To calculate custom crc we need to initialize CrcSpec. CrcSpec also needs check
value, specify it as the last argument of initCrcSpec
if you know, otherwise it will be calculated automatically.
var ❓ = initCrcSpec(
name = "CRC-8/???",
size = 8,
poly = 0x9b'u32,
init = 0x00'u32,
refin = false,
refout = false,
xorout = 0x00'u32
)
assert "123456789".crcBitwise(❓) == crc8Lte.takeCrcSpec.check
assert " ".crcBitwise(❓) == " ".crcBitwise(crc8Lte.takeCrcSpec)
The calculation of crc can easily be broken into parts. But not all parameterized crc can be used for this out of the box (init xor xorout > 0). Use a balance
to fix this.
let
bigdat = @[0x31'u8, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
(p0, p1) = (@[0x31'u8, 0x32, 0x33, 0x34, 0x35], @[0x36'u8, 0x37, 0x38, 0x39])
assert crc32Pkzip.balanceNeeded == false # no need to use balance()
assert crc32Posix.balanceNeeded == true
let
lookup = crc32Posix.initLookup()
check = bigdat.crcLut(crc32Posix, lookup)
var r0 = p0.crcLut(crc32Posix, lookup, prev = 0)
var r1 = p1.crcLut(crc32Posix, lookup, prev = r0)
assert r1 != check
crc32Posix.balance(r0)
r1 = p1.crcLut(crc32Posix, lookup, prev = r0)
assert r1 == check
let lookup = crc16CcitFalse.initLookup()
discard "example.bin".crcFromFile(crc16CcitFalse, lookup)
-d:useBranchFree64
(uses int64 to calculate crc32❗). The branch free version of the remainder calculation doubles the bitwise calculation speed on modern cpu's (which is also used in the calculation of lookup tables). For x32 compatibility, theuseBranchFree64
switch is disabled by default.