Re: rigth crc32 implementation

From: Marcel Moolenaar <marcel_at_xcllnt.net>
Date: Tue, 26 Apr 2005 12:42:08 -0700
On Tue, Apr 26, 2005 at 11:43:54AM +0200, Jose M Rodriguez wrote:
> 
> My first think was use the libkern based one, but I found:
> sys/linkern/crc32.c
> 
> - the code may not be endian safe.

It operates on bytes, so it's endian-safe. Note that the uint32_t
that's returned is not subject to endianness issues: it's always
in the native byte order. The caller of crc32 needs to byteswap
if it needs to compare this integral with a CRC that's not in
the native byte order.

> - the code lacks support for processing chuncks.

This should be easy enough to add. We could add an alternative
version that also takes the initial CRC value. The initial CRC
value can be the calculated CRC of a previous chunk. This also
solves the problem that some CRC calculations start with a CRC
of 0U, while others start with a CRC of ~0U. See also:
  http://www.repairfaq.org/filipg/LINK/F_crc_v34.html#CRCV_003

Roughly speaking (ok, not quite) this is what needs to happen:

uint32_t
crc32_raw(const void *buf, size_t size, uint32_t crc)
{
	const uint8_t *p = buf;

	while (size--)
		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);

	return (crc);
}

uint32_t
crc32(const void *buf, size_t size)
{
	uint32_t crc;

	crc = crc32_raw(buf, size, ~0U);
	return (crc ^ ~0U);
}

Here, crc32_raw() allows the caller to specify the initial CRC value
as well as allows the caller to handle the final XOR.

Does the above solve your CRC problems?

-- 
 Marcel Moolenaar	  USPA: A-39004		 marcel_at_xcllnt.net
Received on Tue Apr 26 2005 - 17:42:11 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:33 UTC