#include #include #include #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); }