60 lines
1.2 KiB
C
60 lines
1.2 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifndef BUFFER
|
|
#define BUFFER 4096
|
|
#endif
|
|
uint8_t msg[BUFFER];
|
|
|
|
/* CRC-32, eg. ethernet */
|
|
const uint32_t crc32_tbl[] = {
|
|
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
|
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
|
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
|
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
|
|
};
|
|
|
|
/* the idea is to act on nybbles instead of bytes to require less CPU cache */
|
|
uint32_t crc32_calc(uint8_t *ptr, int cnt, uint32_t crc)
|
|
{
|
|
while (cnt--) {
|
|
crc = (crc >> 4) ^ crc32_tbl[(crc & 0xf) ^ (*ptr & 0xf)];
|
|
crc = (crc >> 4) ^ crc32_tbl[(crc & 0xf) ^ (*(ptr++) >> 4)];
|
|
}
|
|
return crc;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int len;
|
|
uint32_t v32 = ~0;
|
|
FILE *f;
|
|
|
|
if (argc == 1) {
|
|
freopen(NULL, "rb", stdin);
|
|
f = stdin;
|
|
} else if (argc == 2) {
|
|
f = fopen(argv[1], "rb");
|
|
if (f == NULL) {
|
|
perror(argv[1]);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
fputs("usage: crc32 [filename]", stderr);
|
|
exit(1);
|
|
}
|
|
|
|
do {
|
|
len = fread(msg, 1, BUFFER, f);
|
|
if (ferror(f)) {
|
|
perror(NULL);
|
|
exit(1);
|
|
}
|
|
v32 = crc32_calc(msg, len, v32);
|
|
} while (!feof(f));
|
|
|
|
fclose(f);
|
|
|
|
printf("%08lX\n", (unsigned long) ~v32);
|
|
}
|