-
Notifications
You must be signed in to change notification settings - Fork 0
/
adler32.cpp
121 lines (105 loc) · 2.86 KB
/
adler32.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Plain (and also slow) implementation of the Adler-32 checksum.
#include <cstddef> // One stupid extra header just for size_t...
#include <cstdint>
#include <initializer_list>
#ifdef __STDC_HOSTED__
#include <algorithm>
#include <array>
#include <vector>
#ifdef __cpp_lib_span
#include <span>
using std::span;
#endif
using std::array, std::vector;
#endif
#include "adler32.hpp"
using std::initializer_list;
using std::size_t, std::uint32_t;
static constexpr uint16_t modulus = 65521;
namespace zlite {
#ifdef __STDC_HOSTED__
template <size_t len>
uint32_t adler32(const array<unsigned char, len> &data) {
return zlite::adler32(data.data());
}
uint32_t adler32(const vector<unsigned char> &data) {
uint32_t a = 1, b = 0;
if (data.empty())
return 1;
// Process each byte of the data in order
for (const auto &byte : data) {
a = (a + byte) % modulus;
b = (b + a) % modulus;
}
return (b << 16) | a;
}
#ifdef __cpp_lib_span
uint32_t adler32(const span<const unsigned char> &data) {
uint32_t a = 1, b = 0;
if (data.empty())
return 1;
// Process each byte of the data in order
for (const auto &byte : data) {
a = (a + byte) % modulus;
b = (b + a) % modulus;
}
return (b << 16) | a;
}
#endif
#endif
template <size_t len>
uint32_t adler32(const unsigned char (&data)[len]) {
if (len == 0)
return 1;
uint32_t a = 1, b = 0;
for (decltype(len) i = 0; i < len; i++) {
a = (a + data[i]) % modulus;
b = (b + a) % modulus;
}
return (b << 16) | a;
}
uint32_t adler32(initializer_list<unsigned char>& data) {
if (data.size() == 0)
return 1;
uint32_t a = 1, b = 0;
for (const auto &i : data) {
a = (a + i) % modulus;
b = (b + a) % modulus;
}
return (b << 16) | a;
}
uint32_t combine_adler32(uint32_t adler1, uint32_t adler2,
long long len) {
// In zlib, if len < 0, the function returns 0xffff ffff.
constexpr auto invalid_adler{0xffffffff};
if (len < 0)
return invalid_adler;
unsigned rem = (len %= modulus);
uint32_t sum1 = adler1 & 0xffff;
uint32_t sum2 = rem * sum1;
sum2 %= modulus;
sum1 += (adler2 & 0xffff) + modulus - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + modulus - rem;
if (sum1 >= modulus)
sum1 -= modulus;
if (sum2 >= modulus << 1)
sum2 -= (modulus << 1);
if (sum2 >= modulus)
sum2 -= modulus;
return sum1 | (sum2 << 16);
}
} // namespace zlite
extern "C" {
uint32_t adler32_z(unsigned long adler, const unsigned char *data, size_t len) {
(void)adler;
return zlite::adler32({data[len]});
}
uint32_t adler32(unsigned long adler, const unsigned char *data,
unsigned int len) {
return adler32_z(adler, data, len);
}
uint32_t adler32_combine(unsigned long adler1, unsigned long adler2,
unsigned long long len) {
return zlite::combine_adler32(adler1, adler2, len);
}
}