SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
Adler32.cpp
Go to the documentation of this file.
1/*
2 * Copyright notice:
3 *
4 * (C) 1995-2024 Jean-loup Gailly and Mark Adler
5 *
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
9 *
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
13 *
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 * 3. This notice may not be removed or altered from any source distribution.
21 *
22 * Jean-loup Gailly Mark Adler
23 * jloup@gzip.org madler@alumni.caltech.edu
24 */
25
27
28using namespace sourcepp;
29
30constexpr uint32_t BASE = 65521u; /* largest prime smaller than 65536 */
31constexpr std::size_t NMAX = 5552u;
32
33#define DO1(buffer,i) {adler += static_cast<unsigned char>((buffer)[i]); sum2 += adler;}
34#define DO2(buffer,i) DO1(buffer,i) DO1(buffer,i+1)
35#define DO4(buffer,i) DO2(buffer,i) DO2(buffer,i+2)
36#define DO8(buffer,i) DO4(buffer,i) DO4(buffer,i+4)
37#define DO16(buffer) DO8(buffer,0) DO8(buffer,8)
38
39uint32_t crypto::computeAdler32(std::span<const std::byte> buffer) {
40 const std::byte* cur = buffer.data();
41 uint64_t len = buffer.size();
42
43 uint32_t adler = 0;
44
45 /* split Adler-32 into component sums */
46 uint32_t sum2 = (adler >> 16) & 0xffff;
47 adler &= 0xffff;
48
49 /* in case user likes doing a byte at a time, keep it fast */
50 if (len == 1) {
51 adler += static_cast<unsigned char>(buffer[0]);
52 if (adler >= BASE)
53 adler -= BASE;
54 sum2 += adler;
55 if (sum2 >= BASE)
56 sum2 -= BASE;
57 return adler | (sum2 << 16);
58 }
59
60 /* initial Adler-32 value (deferred check for len == 1 speed) */
61 if (!cur)
62 return 1L;
63
64 /* in case short lengths are provided, keep it somewhat fast */
65 if (len < 16) {
66 while (len--) {
67 adler += static_cast<unsigned char>(*cur++);
68 sum2 += adler;
69 }
70 if (adler >= BASE)
71 adler -= BASE;
72 sum2 %= BASE; /* only added so many BASE's */
73 return adler | (sum2 << 16);
74 }
75
76 /* do length NMAX blocks -- requires just one modulo operation */
77 while (len >= NMAX) {
78 len -= NMAX;
79 uint32_t n = NMAX / 16; /* NMAX is divisible by 16 */
80 do {
81 DO16(buffer) /* 16 sums unrolled */
82 cur += 16;
83 } while (--n);
84 adler %= BASE;
85 sum2 %= BASE;
86 }
87
88 /* do remaining bytes (less than NMAX, still just one modulo) */
89 if (len) { /* avoid modulos if none remaining */
90 while (len >= 16) {
91 len -= 16;
92 DO16(buffer)
93 cur += 16;
94 }
95 while (len--) {
96 adler += static_cast<unsigned char>(*cur++);
97 sum2 += adler;
98 }
99 adler %= BASE;
100 sum2 %= BASE;
101 }
102
103 /* return recombined sums */
104 return adler | (sum2 << 16);
105}
constexpr uint32_t BASE
Definition: Adler32.cpp:30
#define DO16(buffer)
Definition: Adler32.cpp:37
constexpr std::size_t NMAX
Definition: Adler32.cpp:31
uint32_t computeAdler32(std::span< const std::byte > buffer)
Definition: Adler32.cpp:39
Definition: LZMA.h:11