xref: /xnu-8020.140.41/libkern/zlib/adler32.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1*27b03b36SApple OSS Distributions /*
2*27b03b36SApple OSS Distributions  * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
3*27b03b36SApple OSS Distributions  *
4*27b03b36SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*27b03b36SApple OSS Distributions  *
6*27b03b36SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*27b03b36SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*27b03b36SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*27b03b36SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*27b03b36SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*27b03b36SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*27b03b36SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*27b03b36SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*27b03b36SApple OSS Distributions  *
15*27b03b36SApple OSS Distributions  * Please obtain a copy of the License at
16*27b03b36SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*27b03b36SApple OSS Distributions  *
18*27b03b36SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*27b03b36SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*27b03b36SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*27b03b36SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*27b03b36SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*27b03b36SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*27b03b36SApple OSS Distributions  * limitations under the License.
25*27b03b36SApple OSS Distributions  *
26*27b03b36SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*27b03b36SApple OSS Distributions  */
28*27b03b36SApple OSS Distributions /* adler32.c -- compute the Adler-32 checksum of a data stream
29*27b03b36SApple OSS Distributions  * Copyright (C) 1995-2004 Mark Adler
30*27b03b36SApple OSS Distributions  * For conditions of distribution and use, see copyright notice in zlib.h
31*27b03b36SApple OSS Distributions  */
32*27b03b36SApple OSS Distributions 
33*27b03b36SApple OSS Distributions /* @(#) $Id$ */
34*27b03b36SApple OSS Distributions 
35*27b03b36SApple OSS Distributions 
36*27b03b36SApple OSS Distributions #define ZLIB_INTERNAL
37*27b03b36SApple OSS Distributions #if KERNEL
38*27b03b36SApple OSS Distributions     #include <libkern/zlib.h>
39*27b03b36SApple OSS Distributions #else
40*27b03b36SApple OSS Distributions     #include "zlib.h"
41*27b03b36SApple OSS Distributions #endif /* KERNEL */
42*27b03b36SApple OSS Distributions 
43*27b03b36SApple OSS Distributions 
44*27b03b36SApple OSS Distributions #define BASE 65521UL    /* largest prime smaller than 65536 */
45*27b03b36SApple OSS Distributions #define NMAX 5552
46*27b03b36SApple OSS Distributions /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
47*27b03b36SApple OSS Distributions 
48*27b03b36SApple OSS Distributions #define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
49*27b03b36SApple OSS Distributions #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
50*27b03b36SApple OSS Distributions #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
51*27b03b36SApple OSS Distributions #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
52*27b03b36SApple OSS Distributions #define DO16(buf)   DO8(buf,0); DO8(buf,8);
53*27b03b36SApple OSS Distributions 
54*27b03b36SApple OSS Distributions /* use NO_DIVIDE if your processor does not do division in hardware */
55*27b03b36SApple OSS Distributions #ifdef NO_DIVIDE
56*27b03b36SApple OSS Distributions #  define MOD(a) \
57*27b03b36SApple OSS Distributions     do { \
58*27b03b36SApple OSS Distributions         if (a >= (BASE << 16)) a -= (BASE << 16); \
59*27b03b36SApple OSS Distributions         if (a >= (BASE << 15)) a -= (BASE << 15); \
60*27b03b36SApple OSS Distributions         if (a >= (BASE << 14)) a -= (BASE << 14); \
61*27b03b36SApple OSS Distributions         if (a >= (BASE << 13)) a -= (BASE << 13); \
62*27b03b36SApple OSS Distributions         if (a >= (BASE << 12)) a -= (BASE << 12); \
63*27b03b36SApple OSS Distributions         if (a >= (BASE << 11)) a -= (BASE << 11); \
64*27b03b36SApple OSS Distributions         if (a >= (BASE << 10)) a -= (BASE << 10); \
65*27b03b36SApple OSS Distributions         if (a >= (BASE << 9)) a -= (BASE << 9); \
66*27b03b36SApple OSS Distributions         if (a >= (BASE << 8)) a -= (BASE << 8); \
67*27b03b36SApple OSS Distributions         if (a >= (BASE << 7)) a -= (BASE << 7); \
68*27b03b36SApple OSS Distributions         if (a >= (BASE << 6)) a -= (BASE << 6); \
69*27b03b36SApple OSS Distributions         if (a >= (BASE << 5)) a -= (BASE << 5); \
70*27b03b36SApple OSS Distributions         if (a >= (BASE << 4)) a -= (BASE << 4); \
71*27b03b36SApple OSS Distributions         if (a >= (BASE << 3)) a -= (BASE << 3); \
72*27b03b36SApple OSS Distributions         if (a >= (BASE << 2)) a -= (BASE << 2); \
73*27b03b36SApple OSS Distributions         if (a >= (BASE << 1)) a -= (BASE << 1); \
74*27b03b36SApple OSS Distributions         if (a >= BASE) a -= BASE; \
75*27b03b36SApple OSS Distributions     } while (0)
76*27b03b36SApple OSS Distributions #  define MOD4(a) \
77*27b03b36SApple OSS Distributions     do { \
78*27b03b36SApple OSS Distributions         if (a >= (BASE << 4)) a -= (BASE << 4); \
79*27b03b36SApple OSS Distributions         if (a >= (BASE << 3)) a -= (BASE << 3); \
80*27b03b36SApple OSS Distributions         if (a >= (BASE << 2)) a -= (BASE << 2); \
81*27b03b36SApple OSS Distributions         if (a >= (BASE << 1)) a -= (BASE << 1); \
82*27b03b36SApple OSS Distributions         if (a >= BASE) a -= BASE; \
83*27b03b36SApple OSS Distributions     } while (0)
84*27b03b36SApple OSS Distributions #else
85*27b03b36SApple OSS Distributions #  define MOD(a) a %= BASE
86*27b03b36SApple OSS Distributions #  define MOD4(a) a %= BASE
87*27b03b36SApple OSS Distributions #endif
88*27b03b36SApple OSS Distributions 
89*27b03b36SApple OSS Distributions /* ========================================================================= */
90*27b03b36SApple OSS Distributions uLong ZEXPORT
adler32(uLong adler,const Bytef * buf,uInt len)91*27b03b36SApple OSS Distributions adler32(uLong adler, const Bytef *buf, uInt len)
92*27b03b36SApple OSS Distributions {
93*27b03b36SApple OSS Distributions     unsigned long sum2;
94*27b03b36SApple OSS Distributions     unsigned n;
95*27b03b36SApple OSS Distributions 
96*27b03b36SApple OSS Distributions     /* split Adler-32 into component sums */
97*27b03b36SApple OSS Distributions     sum2 = (adler >> 16) & 0xffff;
98*27b03b36SApple OSS Distributions     adler &= 0xffff;
99*27b03b36SApple OSS Distributions 
100*27b03b36SApple OSS Distributions     /* in case user likes doing a byte at a time, keep it fast */
101*27b03b36SApple OSS Distributions     if (len == 1) {
102*27b03b36SApple OSS Distributions         adler += buf[0];
103*27b03b36SApple OSS Distributions         if (adler >= BASE)
104*27b03b36SApple OSS Distributions             adler -= BASE;
105*27b03b36SApple OSS Distributions         sum2 += adler;
106*27b03b36SApple OSS Distributions         if (sum2 >= BASE)
107*27b03b36SApple OSS Distributions             sum2 -= BASE;
108*27b03b36SApple OSS Distributions         return adler | (sum2 << 16);
109*27b03b36SApple OSS Distributions     }
110*27b03b36SApple OSS Distributions 
111*27b03b36SApple OSS Distributions     /* initial Adler-32 value (deferred check for len == 1 speed) */
112*27b03b36SApple OSS Distributions     if (buf == Z_NULL)
113*27b03b36SApple OSS Distributions         return 1L;
114*27b03b36SApple OSS Distributions 
115*27b03b36SApple OSS Distributions     /* in case short lengths are provided, keep it somewhat fast */
116*27b03b36SApple OSS Distributions     if (len < 16) {
117*27b03b36SApple OSS Distributions         while (len--) {
118*27b03b36SApple OSS Distributions             adler += *buf++;
119*27b03b36SApple OSS Distributions             sum2 += adler;
120*27b03b36SApple OSS Distributions         }
121*27b03b36SApple OSS Distributions         if (adler >= BASE)
122*27b03b36SApple OSS Distributions             adler -= BASE;
123*27b03b36SApple OSS Distributions         MOD4(sum2);             /* only added so many BASE's */
124*27b03b36SApple OSS Distributions         return adler | (sum2 << 16);
125*27b03b36SApple OSS Distributions     }
126*27b03b36SApple OSS Distributions 
127*27b03b36SApple OSS Distributions 
128*27b03b36SApple OSS Distributions     /* do length NMAX blocks -- requires just one modulo operation */
129*27b03b36SApple OSS Distributions     while (len >= NMAX) {
130*27b03b36SApple OSS Distributions         len -= NMAX;
131*27b03b36SApple OSS Distributions         n = NMAX / 16;          /* NMAX is divisible by 16 */
132*27b03b36SApple OSS Distributions         do {
133*27b03b36SApple OSS Distributions             DO16(buf);          /* 16 sums unrolled */
134*27b03b36SApple OSS Distributions             buf += 16;
135*27b03b36SApple OSS Distributions         } while (--n);
136*27b03b36SApple OSS Distributions         MOD(adler);
137*27b03b36SApple OSS Distributions         MOD(sum2);
138*27b03b36SApple OSS Distributions     }
139*27b03b36SApple OSS Distributions 
140*27b03b36SApple OSS Distributions     /* do remaining bytes (less than NMAX, still just one modulo) */
141*27b03b36SApple OSS Distributions     if (len) {                  /* avoid modulos if none remaining */
142*27b03b36SApple OSS Distributions         while (len >= 16) {
143*27b03b36SApple OSS Distributions             len -= 16;
144*27b03b36SApple OSS Distributions             DO16(buf);
145*27b03b36SApple OSS Distributions             buf += 16;
146*27b03b36SApple OSS Distributions         }
147*27b03b36SApple OSS Distributions         while (len--) {
148*27b03b36SApple OSS Distributions             adler += *buf++;
149*27b03b36SApple OSS Distributions             sum2 += adler;
150*27b03b36SApple OSS Distributions         }
151*27b03b36SApple OSS Distributions         MOD(adler);
152*27b03b36SApple OSS Distributions         MOD(sum2);
153*27b03b36SApple OSS Distributions     }
154*27b03b36SApple OSS Distributions 
155*27b03b36SApple OSS Distributions     /* return recombined sums */
156*27b03b36SApple OSS Distributions     return adler | (sum2 << 16);
157*27b03b36SApple OSS Distributions }
158*27b03b36SApple OSS Distributions 
159*27b03b36SApple OSS Distributions /* ========================================================================= */
160*27b03b36SApple OSS Distributions uLong ZEXPORT
adler32_combine(uLong adler1,uLong adler2,z_off_t len2)161*27b03b36SApple OSS Distributions adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
162*27b03b36SApple OSS Distributions {
163*27b03b36SApple OSS Distributions     unsigned long sum1;
164*27b03b36SApple OSS Distributions     unsigned long sum2;
165*27b03b36SApple OSS Distributions     unsigned rem;
166*27b03b36SApple OSS Distributions 
167*27b03b36SApple OSS Distributions     /* the derivation of this formula is left as an exercise for the reader */
168*27b03b36SApple OSS Distributions     rem = (unsigned)(len2 % BASE);
169*27b03b36SApple OSS Distributions     sum1 = adler1 & 0xffff;
170*27b03b36SApple OSS Distributions     sum2 = rem * sum1;
171*27b03b36SApple OSS Distributions     MOD(sum2);
172*27b03b36SApple OSS Distributions     sum1 += (adler2 & 0xffff) + BASE - 1;
173*27b03b36SApple OSS Distributions     sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
174*27b03b36SApple OSS Distributions     if (sum1 > BASE) sum1 -= BASE;
175*27b03b36SApple OSS Distributions     if (sum1 > BASE) sum1 -= BASE;
176*27b03b36SApple OSS Distributions     if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
177*27b03b36SApple OSS Distributions     if (sum2 > BASE) sum2 -= BASE;
178*27b03b36SApple OSS Distributions     return sum1 | (sum2 << 16);
179*27b03b36SApple OSS Distributions }
180