/src/zlib-ng/arch/generic/adler32_c.c
Line | Count | Source |
1 | | /* adler32.c -- compute the Adler-32 checksum of a data stream |
2 | | * Copyright (C) 1995-2011, 2016 Mark Adler |
3 | | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | | */ |
5 | | |
6 | | #include "zbuild.h" |
7 | | #include "arch_functions.h" |
8 | | |
9 | | #ifdef ADLER32_FALLBACK |
10 | | |
11 | | #include "functable.h" |
12 | | #include "adler32_p.h" |
13 | | |
14 | 0 | Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len) { |
15 | 0 | uint32_t sum2; |
16 | 0 | size_t n; |
17 | | |
18 | | /* split Adler-32 into component sums */ |
19 | 0 | sum2 = (adler >> 16) & 0xffff; |
20 | 0 | adler &= 0xffff; |
21 | | |
22 | | /* in case user likes doing a byte at a time, keep it fast */ |
23 | 0 | if (UNLIKELY(len == 1)) |
24 | 0 | return adler32_copy_tail(adler, NULL, buf, 1, sum2, 1, 1, 0); |
25 | | |
26 | | /* in case short lengths are provided, keep it somewhat fast */ |
27 | 0 | if (UNLIKELY(len < 16)) |
28 | 0 | return adler32_copy_tail(adler, NULL, buf, len, sum2, 1, 15, 0); |
29 | | |
30 | | /* Align source to 8 bytes so SWAR loads are naturally aligned */ |
31 | 0 | size_t align_diff = ALIGN_DIFF(buf, 8); |
32 | 0 | size_t nmax = NMAX_ALIGNED8; |
33 | 0 | if (align_diff) { |
34 | 0 | adler32_copy_align(&adler, NULL, buf, align_diff, &sum2, 7, 0); |
35 | 0 | buf += align_diff; |
36 | 0 | len -= align_diff; |
37 | 0 | nmax = ALIGN_DOWN(nmax - align_diff, (size_t)8); |
38 | 0 | } |
39 | | |
40 | | /* do length at most NMAX blocks -- requires just one modulo operation */ |
41 | 0 | while (len >= nmax) { |
42 | 0 | len -= nmax; |
43 | 0 | n = nmax; |
44 | |
|
45 | 0 | do { |
46 | 0 | size_t chunk = MIN(ALIGN_DOWN(n, (size_t)8), (size_t)ADLER32_SWAR_MAX_BYTES); |
47 | 0 | adler32_swar(&adler, NULL, buf, chunk, &sum2, 0); |
48 | 0 | buf += chunk; |
49 | 0 | n -= chunk; |
50 | 0 | } while (n >= 8); |
51 | |
|
52 | 0 | adler %= BASE; |
53 | 0 | sum2 %= BASE; |
54 | 0 | nmax = NMAX_ALIGNED8; |
55 | 0 | } |
56 | | |
57 | | /* do remaining bytes (less than NMAX, still just one modulo) */ |
58 | 0 | return adler32_copy_tail(adler, NULL, buf, len, sum2, len != 0, NMAX - 1, 0); |
59 | 0 | } |
60 | | |
61 | 0 | Z_INTERNAL uint32_t adler32_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { |
62 | 0 | adler = adler32_c(adler, src, len); |
63 | 0 | memcpy(dst, src, len); |
64 | 0 | return adler; |
65 | 0 | } |
66 | | |
67 | | #endif /* ADLER32_FALLBACK */ |