v / vlib / hash / crc64 / interop / crc64_ref.c
98 lines · 81 sloc · 2.23 KB · 0de4244590b0fd16cdba621a4dfa4609ebd6defc
Raw
1// Standard CRC64-ECMA reference implementation in C
2// Compiles with: gcc -std=c99 crc64_ref.c -o crc64_ref
3
4#include <stdio.h>
5#include <stdint.h>
6#include <string.h>
7#include <stdlib.h>
8
9#define CRC64_ECMA 0x42F0E1EBA9EA3693ULL
10
11static uint64_t crc64_table[256];
12
13void crc64_init_table(void) {
14 for (int i = 0; i < 256; i++) {
15 uint64_t crc = (uint64_t)i << 56;
16 for (int j = 0; j < 8; j++) {
17 if (crc & 0x8000000000000000ULL) {
18 crc = (crc << 1) ^ CRC64_ECMA;
19 } else {
20 crc <<= 1;
21 }
22 }
23 crc64_table[i] = crc;
24 }
25}
26
27uint64_t crc64_checksum(const uint8_t *data, size_t len) {
28 uint64_t crc = 0ULL;
29 for (size_t i = 0; i < len; i++) {
30 uint8_t byte = data[i];
31 crc = crc64_table[(uint8_t)((crc >> 56) ^ byte)] ^ (crc << 8);
32 }
33 return crc;
34}
35
36int main(int argc, char *argv[]) {
37 crc64_init_table();
38
39 if (argc < 2) {
40 fprintf(stderr, "Usage: %s <action> [data...]\n", argv[0]);
41 fprintf(stderr, " checksum <hexstring> - compute CRC64 of hex data\n");
42 fprintf(stderr, " table - print first 16 table entries\n");
43 return 1;
44 }
45
46 const char *action = argv[1];
47
48 if (strcmp(action, "table") == 0) {
49 printf("CRC64_ECMA table (first 16):\n");
50 for (int i = 0; i < 16; i++) {
51 printf(" [%d] = 0x%016llx\n", i, (unsigned long long)crc64_table[i]);
52 }
53 return 0;
54 }
55
56 if (strcmp(action, "checksum") == 0) {
57 const char *hexstr = (argc > 2) ? argv[2] : "";
58 size_t hexlen = strlen(hexstr);
59
60 if (hexlen == 0) {
61 // Empty input
62 uint64_t crc = crc64_checksum(NULL, 0);
63 printf("%016llx\n", (unsigned long long)crc);
64 return 0;
65 }
66
67 if (hexlen % 2 != 0) {
68 fprintf(stderr, "Error: hex string must have even length\n");
69 return 1;
70 }
71
72 size_t datalen = hexlen / 2;
73 uint8_t *data = malloc(datalen);
74 if (!data) {
75 fprintf(stderr, "Error: memory allocation failed\n");
76 return 1;
77 }
78
79 for (size_t i = 0; i < datalen; i++) {
80 unsigned int byte;
81 if (sscanf(&hexstr[i * 2], "%2x", &byte) != 1) {
82 fprintf(stderr, "Error: invalid hex character\n");
83 free(data);
84 return 1;
85 }
86 data[i] = (uint8_t)byte;
87 }
88
89 uint64_t crc = crc64_checksum(data, datalen);
90 printf("%016llx\n", (unsigned long long)crc);
91 free(data);
92 return 0;
93 }
94
95 fprintf(stderr, "Error: unknown action '%s'\n", action);
96 return 1;
97}
98
99