|
0
|
1 #include "crc32.h"
|
|
|
2 #include "crc32i.h"
|
|
|
3 #include <stdio.h>
|
|
|
4 #include <string.h>
|
|
|
5 #include <inttypes.h>
|
|
|
6 #include <assert.h>
|
|
|
7 #include <stdlib.h>
|
|
|
8 #include <time.h>
|
|
|
9
|
|
|
10 /* Align to a byte offset using the given crc function. */
|
|
|
11 static void crc32_align(uint32_t *crc, crc32_r_spec crcfunc, size_t align, const unsigned char **message, size_t *sz)
|
|
|
12 {
|
|
|
13 size_t sz8, szs;
|
|
|
14
|
|
|
15 /* Alignment check */
|
|
|
16 if (ALIGNED(*message, align))
|
|
|
17 return;
|
|
|
18
|
|
|
19 /* Calculate size needed to align */
|
|
|
20 sz8 = align - ((uintptr_t)message % align);
|
|
|
21 szs = MIN(*sz, sz8);
|
|
|
22
|
|
|
23 *crc = crcfunc(*crc, *message, sz8);
|
|
|
24 *message += sz8;
|
|
|
25 *sz -= sz8;
|
|
|
26
|
|
|
27 if (szs == sz8) assert(ALIGNED(*message, align));
|
|
|
28 }
|
|
|
29
|
|
|
30 CRC32_API
|
|
|
31 uint32_t crc32(const unsigned char *message, size_t sz)
|
|
|
32 {
|
|
|
33 uint32_t crc;
|
|
|
34 size_t i;
|
|
|
35
|
|
|
36 if (!sz)
|
|
|
37 return 0;
|
|
|
38
|
|
|
39 crc = 0xFFFFFFFF;
|
|
|
40 crc32_align(&crc, crc32c_r, ALIGNOF(uint32_t), &message, &sz);
|
|
|
41 if (!sz) return ~crc;
|
|
|
42 #ifdef __x86_64__
|
|
|
43 crc32_align(&crc, crc32qw_r, 16, &message, &sz);
|
|
|
44 if (!sz) return ~crc;
|
|
|
45
|
|
|
46 return ~crc32x86_vpclmulqdq_r(crc, message, sz);
|
|
|
47 #else
|
|
|
48 return ~crc32qw_r(crc, message, sz);
|
|
|
49 #endif
|
|
|
50 }
|