• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/zlib/crc32.c

00001 /* crc32.c -- compute the CRC-32 of a data stream
00002  * Copyright (C) 1995-2006, 2010 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  *
00005  * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
00006  * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
00007  * tables for updating the shift register in one step with three exclusive-ors
00008  * instead of four steps with four exclusive-ors.  This results in about a
00009  * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
00010  */
00011 
00012 /* @(#) $Id$ */
00013 
00014 /*
00015   Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
00016   protection on the static variables used to control the first-use generation
00017   of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
00018   first call get_crc_table() to initialize the tables before allowing more than
00019   one thread to use crc32().
00020  */
00021 
00022 #ifdef MAKECRCH
00023 #  include <stdio.h>
00024 #  ifndef DYNAMIC_CRC_TABLE
00025 #    define DYNAMIC_CRC_TABLE
00026 #  endif /* !DYNAMIC_CRC_TABLE */
00027 #endif /* MAKECRCH */
00028 
00029 #include "zutil.h"      /* for STDC and FAR definitions */
00030 
00031 #define local static
00032 
00033 /* Find a four-byte integer type for crc32_little() and crc32_big(). */
00034 #ifndef NOBYFOUR
00035 #  ifdef STDC           /* need ANSI C limits.h to determine sizes */
00036 #    include <limits.h>
00037 #    define BYFOUR
00038 #    if (UINT_MAX == 0xffffffffUL)
00039        typedef unsigned int u4;
00040 #    else
00041 #      if (ULONG_MAX == 0xffffffffUL)
00042          typedef unsigned long u4;
00043 #      else
00044 #        if (USHRT_MAX == 0xffffffffUL)
00045            typedef unsigned short u4;
00046 #        else
00047 #          undef BYFOUR     /* can't find a four-byte integer type! */
00048 #        endif
00049 #      endif
00050 #    endif
00051 #  endif /* STDC */
00052 #endif /* !NOBYFOUR */
00053 
00054 /* Definitions for doing the crc four data bytes at a time. */
00055 #ifdef BYFOUR
00056 #  define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
00057                 (((w)&0xff00)<<8)+(((w)&0xff)<<24))
00058    local unsigned long crc32_little OF((unsigned long,
00059                         const unsigned char FAR *, unsigned));
00060    local unsigned long crc32_big OF((unsigned long,
00061                         const unsigned char FAR *, unsigned));
00062 #  define TBLS 8
00063 #else
00064 #  define TBLS 1
00065 #endif /* BYFOUR */
00066 
00067 /* Local functions for crc concatenation */
00068 local unsigned long gf2_matrix_times OF((unsigned long *mat,
00069                                          unsigned long vec));
00070 local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
00071 local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
00072 
00073 
00074 #ifdef DYNAMIC_CRC_TABLE
00075 
00076 local volatile int crc_table_empty = 1;
00077 local unsigned long FAR crc_table[TBLS][256];
00078 local void make_crc_table OF((void));
00079 #ifdef MAKECRCH
00080    local void write_table OF((FILE *, const unsigned long FAR *));
00081 #endif /* MAKECRCH */
00082 /*
00083   Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
00084   x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
00085 
00086   Polynomials over GF(2) are represented in binary, one bit per coefficient,
00087   with the lowest powers in the most significant bit.  Then adding polynomials
00088   is just exclusive-or, and multiplying a polynomial by x is a right shift by
00089   one.  If we call the above polynomial p, and represent a byte as the
00090   polynomial q, also with the lowest power in the most significant bit (so the
00091   byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
00092   where a mod b means the remainder after dividing a by b.
00093 
00094   This calculation is done using the shift-register method of multiplying and
00095   taking the remainder.  The register is initialized to zero, and for each
00096   incoming bit, x^32 is added mod p to the register if the bit is a one (where
00097   x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
00098   x (which is shifting right by one and adding x^32 mod p if the bit shifted
00099   out is a one).  We start with the highest power (least significant bit) of
00100   q and repeat for all eight bits of q.
00101 
00102   The first table is simply the CRC of all possible eight bit values.  This is
00103   all the information needed to generate CRCs on data a byte at a time for all
00104   combinations of CRC register values and incoming bytes.  The remaining tables
00105   allow for word-at-a-time CRC calculation for both big-endian and little-
00106   endian machines, where a word is four bytes.
00107 */
00108 local void make_crc_table()
00109 {
00110     unsigned long c;
00111     int n, k;
00112     unsigned long poly;                 /* polynomial exclusive-or pattern */
00113     /* terms of polynomial defining this crc (except x^32): */
00114     static volatile int first = 1;      /* flag to limit concurrent making */
00115     static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
00116 
00117     /* See if another task is already doing this (not thread-safe, but better
00118        than nothing -- significantly reduces duration of vulnerability in
00119        case the advice about DYNAMIC_CRC_TABLE is ignored) */
00120     if (first) {
00121         first = 0;
00122 
00123         /* make exclusive-or pattern from polynomial (0xedb88320UL) */
00124         poly = 0UL;
00125         for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
00126             poly |= 1UL << (31 - p[n]);
00127 
00128         /* generate a crc for every 8-bit value */
00129         for (n = 0; n < 256; n++) {
00130             c = (unsigned long)n;
00131             for (k = 0; k < 8; k++)
00132                 c = c & 1 ? poly ^ (c >> 1) : c >> 1;
00133             crc_table[0][n] = c;
00134         }
00135 
00136 #ifdef BYFOUR
00137         /* generate crc for each value followed by one, two, and three zeros,
00138            and then the byte reversal of those as well as the first table */
00139         for (n = 0; n < 256; n++) {
00140             c = crc_table[0][n];
00141             crc_table[4][n] = REV(c);
00142             for (k = 1; k < 4; k++) {
00143                 c = crc_table[0][c & 0xff] ^ (c >> 8);
00144                 crc_table[k][n] = c;
00145                 crc_table[k + 4][n] = REV(c);
00146             }
00147         }
00148 #endif /* BYFOUR */
00149 
00150         crc_table_empty = 0;
00151     }
00152     else {      /* not first */
00153         /* wait for the other guy to finish (not efficient, but rare) */
00154         while (crc_table_empty)
00155             ;
00156     }
00157 
00158 #ifdef MAKECRCH
00159     /* write out CRC tables to crc32.h */
00160     {
00161         FILE *out;
00162 
00163         out = fopen("crc32.h", "w");
00164         if (out == NULL) return;
00165         fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
00166         fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
00167         fprintf(out, "local const unsigned long FAR ");
00168         fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
00169         write_table(out, crc_table[0]);
00170 #  ifdef BYFOUR
00171         fprintf(out, "#ifdef BYFOUR\n");
00172         for (k = 1; k < 8; k++) {
00173             fprintf(out, "  },\n  {\n");
00174             write_table(out, crc_table[k]);
00175         }
00176         fprintf(out, "#endif\n");
00177 #  endif /* BYFOUR */
00178         fprintf(out, "  }\n};\n");
00179         fclose(out);
00180     }
00181 #endif /* MAKECRCH */
00182 }
00183 
00184 #ifdef MAKECRCH
00185 local void write_table(out, table)
00186     FILE *out;
00187     const unsigned long FAR *table;
00188 {
00189     int n;
00190 
00191     for (n = 0; n < 256; n++)
00192         fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
00193                 n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
00194 }
00195 #endif /* MAKECRCH */
00196 
00197 #else /* !DYNAMIC_CRC_TABLE */
00198 /* ========================================================================
00199  * Tables of CRC-32s of all single-byte values, made by make_crc_table().
00200  */
00201 #include "crc32.h"
00202 #endif /* DYNAMIC_CRC_TABLE */
00203 
00204 /* =========================================================================
00205  * This function can be used by asm versions of crc32()
00206  */
00207 const unsigned long FAR * ZEXPORT get_crc_table()
00208 {
00209 #ifdef DYNAMIC_CRC_TABLE
00210     if (crc_table_empty)
00211         make_crc_table();
00212 #endif /* DYNAMIC_CRC_TABLE */
00213     return (const unsigned long FAR *)crc_table;
00214 }
00215 
00216 /* ========================================================================= */
00217 #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
00218 #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
00219 
00220 /* ========================================================================= */
00221 unsigned long ZEXPORT crc32(crc, buf, len)
00222     unsigned long crc;
00223     const unsigned char FAR *buf;
00224     uInt len;
00225 {
00226     if (buf == Z_NULL) return 0UL;
00227 
00228 #ifdef DYNAMIC_CRC_TABLE
00229     if (crc_table_empty)
00230         make_crc_table();
00231 #endif /* DYNAMIC_CRC_TABLE */
00232 
00233 #ifdef BYFOUR
00234     if (sizeof(void *) == sizeof(ptrdiff_t)) {
00235         u4 endian;
00236 
00237         endian = 1;
00238         if (*((unsigned char *)(&endian)))
00239             return crc32_little(crc, buf, len);
00240         else
00241             return crc32_big(crc, buf, len);
00242     }
00243 #endif /* BYFOUR */
00244     crc = crc ^ 0xffffffffUL;
00245     while (len >= 8) {
00246         DO8;
00247         len -= 8;
00248     }
00249     if (len) do {
00250         DO1;
00251     } while (--len);
00252     return crc ^ 0xffffffffUL;
00253 }
00254 
00255 #ifdef BYFOUR
00256 
00257 /* ========================================================================= */
00258 #define DOLIT4 c ^= *buf4++; \
00259         c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
00260             crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
00261 #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
00262 
00263 /* ========================================================================= */
00264 local unsigned long crc32_little(crc, buf, len)
00265     unsigned long crc;
00266     const unsigned char FAR *buf;
00267     unsigned len;
00268 {
00269     register u4 c;
00270     register const u4 FAR *buf4;
00271 
00272     c = (u4)crc;
00273     c = ~c;
00274     while (len && ((ptrdiff_t)buf & 3)) {
00275         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
00276         len--;
00277     }
00278 
00279     buf4 = (const u4 FAR *)(const void FAR *)buf;
00280     while (len >= 32) {
00281         DOLIT32;
00282         len -= 32;
00283     }
00284     while (len >= 4) {
00285         DOLIT4;
00286         len -= 4;
00287     }
00288     buf = (const unsigned char FAR *)buf4;
00289 
00290     if (len) do {
00291         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
00292     } while (--len);
00293     c = ~c;
00294     return (unsigned long)c;
00295 }
00296 
00297 /* ========================================================================= */
00298 #define DOBIG4 c ^= *++buf4; \
00299         c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
00300             crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
00301 #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
00302 
00303 /* ========================================================================= */
00304 local unsigned long crc32_big(crc, buf, len)
00305     unsigned long crc;
00306     const unsigned char FAR *buf;
00307     unsigned len;
00308 {
00309     register u4 c;
00310     register const u4 FAR *buf4;
00311 
00312     c = REV((u4)crc);
00313     c = ~c;
00314     while (len && ((ptrdiff_t)buf & 3)) {
00315         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
00316         len--;
00317     }
00318 
00319     buf4 = (const u4 FAR *)(const void FAR *)buf;
00320     buf4--;
00321     while (len >= 32) {
00322         DOBIG32;
00323         len -= 32;
00324     }
00325     while (len >= 4) {
00326         DOBIG4;
00327         len -= 4;
00328     }
00329     buf4++;
00330     buf = (const unsigned char FAR *)buf4;
00331 
00332     if (len) do {
00333         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
00334     } while (--len);
00335     c = ~c;
00336     return (unsigned long)(REV(c));
00337 }
00338 
00339 #endif /* BYFOUR */
00340 
00341 #define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
00342 
00343 /* ========================================================================= */
00344 local unsigned long gf2_matrix_times(mat, vec)
00345     unsigned long *mat;
00346     unsigned long vec;
00347 {
00348     unsigned long sum;
00349 
00350     sum = 0;
00351     while (vec) {
00352         if (vec & 1)
00353             sum ^= *mat;
00354         vec >>= 1;
00355         mat++;
00356     }
00357     return sum;
00358 }
00359 
00360 /* ========================================================================= */
00361 local void gf2_matrix_square(square, mat)
00362     unsigned long *square;
00363     unsigned long *mat;
00364 {
00365     int n;
00366 
00367     for (n = 0; n < GF2_DIM; n++)
00368         square[n] = gf2_matrix_times(mat, mat[n]);
00369 }
00370 
00371 /* ========================================================================= */
00372 local uLong crc32_combine_(crc1, crc2, len2)
00373     uLong crc1;
00374     uLong crc2;
00375     z_off64_t len2;
00376 {
00377     int n;
00378     unsigned long row;
00379     unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
00380     unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
00381 
00382     /* degenerate case (also disallow negative lengths) */
00383     if (len2 <= 0)
00384         return crc1;
00385 
00386     /* put operator for one zero bit in odd */
00387     odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
00388     row = 1;
00389     for (n = 1; n < GF2_DIM; n++) {
00390         odd[n] = row;
00391         row <<= 1;
00392     }
00393 
00394     /* put operator for two zero bits in even */
00395     gf2_matrix_square(even, odd);
00396 
00397     /* put operator for four zero bits in odd */
00398     gf2_matrix_square(odd, even);
00399 
00400     /* apply len2 zeros to crc1 (first square will put the operator for one
00401        zero byte, eight zero bits, in even) */
00402     do {
00403         /* apply zeros operator for this bit of len2 */
00404         gf2_matrix_square(even, odd);
00405         if (len2 & 1)
00406             crc1 = gf2_matrix_times(even, crc1);
00407         len2 >>= 1;
00408 
00409         /* if no more bits set, then done */
00410         if (len2 == 0)
00411             break;
00412 
00413         /* another iteration of the loop with odd and even swapped */
00414         gf2_matrix_square(odd, even);
00415         if (len2 & 1)
00416             crc1 = gf2_matrix_times(odd, crc1);
00417         len2 >>= 1;
00418 
00419         /* if no more bits set, then done */
00420     } while (len2 != 0);
00421 
00422     /* return combined crc */
00423     crc1 ^= crc2;
00424     return crc1;
00425 }
00426 
00427 /* ========================================================================= */
00428 uLong ZEXPORT crc32_combine(crc1, crc2, len2)
00429     uLong crc1;
00430     uLong crc2;
00431     z_off_t len2;
00432 {
00433     return crc32_combine_(crc1, crc2, len2);
00434 }
00435 
00436 uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
00437     uLong crc1;
00438     uLong crc2;
00439     z_off64_t len2;
00440 {
00441     return crc32_combine_(crc1, crc2, len2);
00442 }

Generated on Wed Oct 20 2010 11:12:17 for APBS by  doxygen 1.7.2