xref: /aosp_15_r20/external/libwebsockets/win32port/zlib/adler32.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /* adler32.c -- compute the Adler-32 checksum of a data stream
2*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 1995-2007 Mark Adler
3*1c60b9acSAndroid Build Coastguard Worker  * For conditions of distribution and use, see copyright notice in zlib.h
4*1c60b9acSAndroid Build Coastguard Worker  */
5*1c60b9acSAndroid Build Coastguard Worker 
6*1c60b9acSAndroid Build Coastguard Worker /* \param (#) $Id$ */
7*1c60b9acSAndroid Build Coastguard Worker 
8*1c60b9acSAndroid Build Coastguard Worker #include "zutil.h"
9*1c60b9acSAndroid Build Coastguard Worker 
10*1c60b9acSAndroid Build Coastguard Worker #define local static
11*1c60b9acSAndroid Build Coastguard Worker 
12*1c60b9acSAndroid Build Coastguard Worker local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
13*1c60b9acSAndroid Build Coastguard Worker 
14*1c60b9acSAndroid Build Coastguard Worker #define BASE 65521UL    /* largest prime smaller than 65536 */
15*1c60b9acSAndroid Build Coastguard Worker #define NMAX 5552
16*1c60b9acSAndroid Build Coastguard Worker /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
17*1c60b9acSAndroid Build Coastguard Worker 
18*1c60b9acSAndroid Build Coastguard Worker #define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
19*1c60b9acSAndroid Build Coastguard Worker #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
20*1c60b9acSAndroid Build Coastguard Worker #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
21*1c60b9acSAndroid Build Coastguard Worker #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
22*1c60b9acSAndroid Build Coastguard Worker #define DO16(buf)   DO8(buf,0); DO8(buf,8);
23*1c60b9acSAndroid Build Coastguard Worker 
24*1c60b9acSAndroid Build Coastguard Worker /* use NO_DIVIDE if your processor does not do division in hardware */
25*1c60b9acSAndroid Build Coastguard Worker #ifdef NO_DIVIDE
26*1c60b9acSAndroid Build Coastguard Worker #  define MOD(a) \
27*1c60b9acSAndroid Build Coastguard Worker     do { \
28*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 16)) a -= (BASE << 16); \
29*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 15)) a -= (BASE << 15); \
30*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 14)) a -= (BASE << 14); \
31*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 13)) a -= (BASE << 13); \
32*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 12)) a -= (BASE << 12); \
33*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 11)) a -= (BASE << 11); \
34*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 10)) a -= (BASE << 10); \
35*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 9)) a -= (BASE << 9); \
36*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 8)) a -= (BASE << 8); \
37*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 7)) a -= (BASE << 7); \
38*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 6)) a -= (BASE << 6); \
39*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 5)) a -= (BASE << 5); \
40*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 4)) a -= (BASE << 4); \
41*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 3)) a -= (BASE << 3); \
42*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 2)) a -= (BASE << 2); \
43*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 1)) a -= (BASE << 1); \
44*1c60b9acSAndroid Build Coastguard Worker         if (a >= BASE) a -= BASE; \
45*1c60b9acSAndroid Build Coastguard Worker     } while (0)
46*1c60b9acSAndroid Build Coastguard Worker #  define MOD4(a) \
47*1c60b9acSAndroid Build Coastguard Worker     do { \
48*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 4)) a -= (BASE << 4); \
49*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 3)) a -= (BASE << 3); \
50*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 2)) a -= (BASE << 2); \
51*1c60b9acSAndroid Build Coastguard Worker         if (a >= (BASE << 1)) a -= (BASE << 1); \
52*1c60b9acSAndroid Build Coastguard Worker         if (a >= BASE) a -= BASE; \
53*1c60b9acSAndroid Build Coastguard Worker     } while (0)
54*1c60b9acSAndroid Build Coastguard Worker #else
55*1c60b9acSAndroid Build Coastguard Worker #  define MOD(a) a %= BASE
56*1c60b9acSAndroid Build Coastguard Worker #  define MOD4(a) a %= BASE
57*1c60b9acSAndroid Build Coastguard Worker #endif
58*1c60b9acSAndroid Build Coastguard Worker 
59*1c60b9acSAndroid Build Coastguard Worker /* ========================================================================= */
adler32(adler,buf,len)60*1c60b9acSAndroid Build Coastguard Worker uLong ZEXPORT adler32(adler, buf, len)
61*1c60b9acSAndroid Build Coastguard Worker     uLong adler;
62*1c60b9acSAndroid Build Coastguard Worker     const Bytef *buf;
63*1c60b9acSAndroid Build Coastguard Worker     uInt len;
64*1c60b9acSAndroid Build Coastguard Worker {
65*1c60b9acSAndroid Build Coastguard Worker     unsigned long sum2;
66*1c60b9acSAndroid Build Coastguard Worker     unsigned n;
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker     /* split Adler-32 into component sums */
69*1c60b9acSAndroid Build Coastguard Worker     sum2 = (adler >> 16) & 0xffff;
70*1c60b9acSAndroid Build Coastguard Worker     adler &= 0xffff;
71*1c60b9acSAndroid Build Coastguard Worker 
72*1c60b9acSAndroid Build Coastguard Worker     /* in case user likes doing a byte at a time, keep it fast */
73*1c60b9acSAndroid Build Coastguard Worker     if (len == 1) {
74*1c60b9acSAndroid Build Coastguard Worker         adler += buf[0];
75*1c60b9acSAndroid Build Coastguard Worker         if (adler >= BASE)
76*1c60b9acSAndroid Build Coastguard Worker             adler -= BASE;
77*1c60b9acSAndroid Build Coastguard Worker         sum2 += adler;
78*1c60b9acSAndroid Build Coastguard Worker         if (sum2 >= BASE)
79*1c60b9acSAndroid Build Coastguard Worker             sum2 -= BASE;
80*1c60b9acSAndroid Build Coastguard Worker         return adler | (sum2 << 16);
81*1c60b9acSAndroid Build Coastguard Worker     }
82*1c60b9acSAndroid Build Coastguard Worker 
83*1c60b9acSAndroid Build Coastguard Worker     /* initial Adler-32 value (deferred check for len == 1 speed) */
84*1c60b9acSAndroid Build Coastguard Worker     if (buf == Z_NULL)
85*1c60b9acSAndroid Build Coastguard Worker         return 1L;
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker     /* in case short lengths are provided, keep it somewhat fast */
88*1c60b9acSAndroid Build Coastguard Worker     if (len < 16) {
89*1c60b9acSAndroid Build Coastguard Worker         while (len--) {
90*1c60b9acSAndroid Build Coastguard Worker             adler += *buf++;
91*1c60b9acSAndroid Build Coastguard Worker             sum2 += adler;
92*1c60b9acSAndroid Build Coastguard Worker         }
93*1c60b9acSAndroid Build Coastguard Worker         if (adler >= BASE)
94*1c60b9acSAndroid Build Coastguard Worker             adler -= BASE;
95*1c60b9acSAndroid Build Coastguard Worker         MOD4(sum2);             /* only added so many BASE's */
96*1c60b9acSAndroid Build Coastguard Worker         return adler | (sum2 << 16);
97*1c60b9acSAndroid Build Coastguard Worker     }
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker     /* do length NMAX blocks -- requires just one modulo operation */
100*1c60b9acSAndroid Build Coastguard Worker     while (len >= NMAX) {
101*1c60b9acSAndroid Build Coastguard Worker         len -= NMAX;
102*1c60b9acSAndroid Build Coastguard Worker         n = NMAX / 16;          /* NMAX is divisible by 16 */
103*1c60b9acSAndroid Build Coastguard Worker         do {
104*1c60b9acSAndroid Build Coastguard Worker             DO16(buf);          /* 16 sums unrolled */
105*1c60b9acSAndroid Build Coastguard Worker             buf += 16;
106*1c60b9acSAndroid Build Coastguard Worker         } while (--n);
107*1c60b9acSAndroid Build Coastguard Worker         MOD(adler);
108*1c60b9acSAndroid Build Coastguard Worker         MOD(sum2);
109*1c60b9acSAndroid Build Coastguard Worker     }
110*1c60b9acSAndroid Build Coastguard Worker 
111*1c60b9acSAndroid Build Coastguard Worker     /* do remaining bytes (less than NMAX, still just one modulo) */
112*1c60b9acSAndroid Build Coastguard Worker     if (len) {                  /* avoid modulos if none remaining */
113*1c60b9acSAndroid Build Coastguard Worker         while (len >= 16) {
114*1c60b9acSAndroid Build Coastguard Worker             len -= 16;
115*1c60b9acSAndroid Build Coastguard Worker             DO16(buf);
116*1c60b9acSAndroid Build Coastguard Worker             buf += 16;
117*1c60b9acSAndroid Build Coastguard Worker         }
118*1c60b9acSAndroid Build Coastguard Worker         while (len--) {
119*1c60b9acSAndroid Build Coastguard Worker             adler += *buf++;
120*1c60b9acSAndroid Build Coastguard Worker             sum2 += adler;
121*1c60b9acSAndroid Build Coastguard Worker         }
122*1c60b9acSAndroid Build Coastguard Worker         MOD(adler);
123*1c60b9acSAndroid Build Coastguard Worker         MOD(sum2);
124*1c60b9acSAndroid Build Coastguard Worker     }
125*1c60b9acSAndroid Build Coastguard Worker 
126*1c60b9acSAndroid Build Coastguard Worker     /* return recombined sums */
127*1c60b9acSAndroid Build Coastguard Worker     return adler | (sum2 << 16);
128*1c60b9acSAndroid Build Coastguard Worker }
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker /* ========================================================================= */
adler32_combine_(adler1,adler2,len2)131*1c60b9acSAndroid Build Coastguard Worker local uLong adler32_combine_(adler1, adler2, len2)
132*1c60b9acSAndroid Build Coastguard Worker     uLong adler1;
133*1c60b9acSAndroid Build Coastguard Worker     uLong adler2;
134*1c60b9acSAndroid Build Coastguard Worker     z_off64_t len2;
135*1c60b9acSAndroid Build Coastguard Worker {
136*1c60b9acSAndroid Build Coastguard Worker     unsigned long sum1;
137*1c60b9acSAndroid Build Coastguard Worker     unsigned long sum2;
138*1c60b9acSAndroid Build Coastguard Worker     unsigned rem;
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker     /* the derivation of this formula is left as an exercise for the reader */
141*1c60b9acSAndroid Build Coastguard Worker     rem = (unsigned)(len2 % BASE);
142*1c60b9acSAndroid Build Coastguard Worker     sum1 = adler1 & 0xffff;
143*1c60b9acSAndroid Build Coastguard Worker     sum2 = rem * sum1;
144*1c60b9acSAndroid Build Coastguard Worker     MOD(sum2);
145*1c60b9acSAndroid Build Coastguard Worker     sum1 += (adler2 & 0xffff) + BASE - 1;
146*1c60b9acSAndroid Build Coastguard Worker     sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
147*1c60b9acSAndroid Build Coastguard Worker     if (sum1 >= BASE) sum1 -= BASE;
148*1c60b9acSAndroid Build Coastguard Worker     if (sum1 >= BASE) sum1 -= BASE;
149*1c60b9acSAndroid Build Coastguard Worker     if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
150*1c60b9acSAndroid Build Coastguard Worker     if (sum2 >= BASE) sum2 -= BASE;
151*1c60b9acSAndroid Build Coastguard Worker     return sum1 | (sum2 << 16);
152*1c60b9acSAndroid Build Coastguard Worker }
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker /* ========================================================================= */
adler32_combine(adler1,adler2,len2)155*1c60b9acSAndroid Build Coastguard Worker uLong ZEXPORT adler32_combine(adler1, adler2, len2)
156*1c60b9acSAndroid Build Coastguard Worker     uLong adler1;
157*1c60b9acSAndroid Build Coastguard Worker     uLong adler2;
158*1c60b9acSAndroid Build Coastguard Worker     z_off_t len2;
159*1c60b9acSAndroid Build Coastguard Worker {
160*1c60b9acSAndroid Build Coastguard Worker     return adler32_combine_(adler1, adler2, len2);
161*1c60b9acSAndroid Build Coastguard Worker }
162*1c60b9acSAndroid Build Coastguard Worker 
adler32_combine64(adler1,adler2,len2)163*1c60b9acSAndroid Build Coastguard Worker uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
164*1c60b9acSAndroid Build Coastguard Worker     uLong adler1;
165*1c60b9acSAndroid Build Coastguard Worker     uLong adler2;
166*1c60b9acSAndroid Build Coastguard Worker     z_off64_t len2;
167*1c60b9acSAndroid Build Coastguard Worker {
168*1c60b9acSAndroid Build Coastguard Worker     return adler32_combine_(adler1, adler2, len2);
169*1c60b9acSAndroid Build Coastguard Worker }
170