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