2008-07-30 00:01:23 +04:00
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright ( C ) 1995 - 2005 Mark Adler
* For conditions of distribution and use , see copyright notice in zlib . h
*
* Thanks to Rodney Brown < rbrown64 @ csc . com . au > for his contribution of faster
* CRC methods : exclusive - oring 32 bits of data at a time , and pre - computing
* tables for updating the shift register in one step with three exclusive - ors
* instead of four steps with four exclusive - ors . This results in about a
* factor of two increase in speed on a Power PC G4 ( PPC7455 ) using gcc - O3 .
*/
/* @(#) $Id$ */
2008-08-15 15:32:51 +04:00
# include "zutil.h" /* for STDC and FAR definitions */
2008-07-30 00:01:23 +04:00
/*
Note on the use of DYNAMIC_CRC_TABLE : there is no mutex or semaphore
protection on the static variables used to control the first - use generation
of the crc tables . Therefore , if you # define DYNAMIC_CRC_TABLE , you should
first call get_crc_table ( ) to initialize the tables before allowing more than
one thread to use crc32 ( ) .
*/
# ifdef MAKECRCH
# include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE
# define DYNAMIC_CRC_TABLE
# endif /* !DYNAMIC_CRC_TABLE */
# endif /* MAKECRCH */
# define local static
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
# ifndef NOBYFOUR
# ifdef STDC /* need ANSI C limits.h to determine sizes */
# include <limits.h>
# define BYFOUR
# if (UINT_MAX == 0xffffffffUL)
typedef unsigned int u4 ;
# else
# if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long u4 ;
# else
# if (USHRT_MAX == 0xffffffffUL)
typedef unsigned short u4 ;
# else
# undef BYFOUR /* can't find a four-byte integer type! */
# endif
# endif
# endif
# endif /* STDC */
# endif /* !NOBYFOUR */
/* Definitions for doing the crc four data bytes at a time. */
# ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
( ( ( w ) & 0xff00 ) < < 8 ) + ( ( ( w ) & 0xff ) < < 24 ) )
local unsigned long crc32_little OF ( ( unsigned long ,
const unsigned char FAR * , unsigned ) ) ;
local unsigned long crc32_big OF ( ( unsigned long ,
const unsigned char FAR * , unsigned ) ) ;
# define TBLS 8
# else
# define TBLS 1
# endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF ( ( unsigned long * mat ,
unsigned long vec ) ) ;
local void gf2_matrix_square OF ( ( unsigned long * square , unsigned long * mat ) ) ;
# ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1 ;
local unsigned long FAR crc_table [ TBLS ] [ 256 ] ;
local void make_crc_table OF ( ( void ) ) ;
# ifdef MAKECRCH
local void write_table OF ( ( FILE * , const unsigned long FAR * ) ) ;
# endif /* MAKECRCH */
/*
Generate tables for a byte - wise 32 - bit CRC calculation on the polynomial :
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.
Polynomials over GF ( 2 ) are represented in binary , one bit per coefficient ,
with the lowest powers in the most significant bit . Then adding polynomials
is just exclusive - or , and multiplying a polynomial by x is a right shift by
one . If we call the above polynomial p , and represent a byte as the
polynomial q , also with the lowest power in the most significant bit ( so the
byte 0xb1 is the polynomial x ^ 7 + x ^ 3 + x + 1 ) , then the CRC is ( q * x ^ 32 ) mod p ,
where a mod b means the remainder after dividing a by b .
This calculation is done using the shift - register method of multiplying and
taking the remainder . The register is initialized to zero , and for each
incoming bit , x ^ 32 is added mod p to the register if the bit is a one ( where
x ^ 32 mod p is p + x ^ 32 = x ^ 26 + . . . + 1 ) , and the register is multiplied mod p by
x ( which is shifting right by one and adding x ^ 32 mod p if the bit shifted
out is a one ) . We start with the highest power ( least significant bit ) of
q and repeat for all eight bits of q .
The first table is simply the CRC of all possible eight bit values . This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes . The remaining tables
allow for word - at - a - time CRC calculation for both big - endian and little -
endian machines , where a word is four bytes .
*/
local void make_crc_table ( )
{
unsigned long c ;
int n , k ;
unsigned long poly ; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1 ; /* flag to limit concurrent making */
static const unsigned char p [ ] = { 0 , 1 , 2 , 4 , 5 , 7 , 8 , 10 , 11 , 12 , 16 , 22 , 23 , 26 } ;
/* See if another task is already doing this (not thread-safe, but better
than nothing - - significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored ) */
if ( first ) {
first = 0 ;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL ;
for ( n = 0 ; n < sizeof ( p ) / sizeof ( unsigned char ) ; n + + )
poly | = 1UL < < ( 31 - p [ n ] ) ;
/* generate a crc for every 8-bit value */
for ( n = 0 ; n < 256 ; n + + ) {
c = ( unsigned long ) n ;
for ( k = 0 ; k < 8 ; k + + )
c = c & 1 ? poly ^ ( c > > 1 ) : c > > 1 ;
crc_table [ 0 ] [ n ] = c ;
}
# ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for ( n = 0 ; n < 256 ; n + + ) {
c = crc_table [ 0 ] [ n ] ;
crc_table [ 4 ] [ n ] = REV ( c ) ;
for ( k = 1 ; k < 4 ; k + + ) {
c = crc_table [ 0 ] [ c & 0xff ] ^ ( c > > 8 ) ;
crc_table [ k ] [ n ] = c ;
crc_table [ k + 4 ] [ n ] = REV ( c ) ;
}
}
# endif /* BYFOUR */
crc_table_empty = 0 ;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while ( crc_table_empty )
;
}
# ifdef MAKECRCH
/* write out CRC tables to crc32.h */
{
FILE * out ;
out = fopen ( " crc32.h " , " w " ) ;
if ( out = = NULL ) return ;
fprintf ( out , " /* crc32.h -- tables for rapid CRC calculation \n " ) ;
fprintf ( out , " * Generated automatically by crc32.c \n */ \n \n " ) ;
fprintf ( out , " local const unsigned long FAR " ) ;
fprintf ( out , " crc_table[TBLS][256] = \n { \n { \n " ) ;
write_table ( out , crc_table [ 0 ] ) ;
# ifdef BYFOUR
fprintf ( out , " #ifdef BYFOUR \n " ) ;
for ( k = 1 ; k < 8 ; k + + ) {
fprintf ( out , " }, \n { \n " ) ;
write_table ( out , crc_table [ k ] ) ;
}
fprintf ( out , " #endif \n " ) ;
# endif /* BYFOUR */
fprintf ( out , " } \n }; \n " ) ;
fclose ( out ) ;
}
# endif /* MAKECRCH */
}
# ifdef MAKECRCH
local void write_table ( out , table )
FILE * out ;
const unsigned long FAR * table ;
{
int n ;
for ( n = 0 ; n < 256 ; n + + )
fprintf ( out , " %s0x%08lxUL%s " , n % 5 ? " " : " " , table [ n ] ,
n = = 255 ? " \n " : ( n % 5 = = 4 ? " , \n " : " , " ) ) ;
}
# endif /* MAKECRCH */
# else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
* Tables of CRC - 32 s of all single - byte values , made by make_crc_table ( ) .
*/
# include "crc32.h"
# endif /* DYNAMIC_CRC_TABLE */
/* =========================================================================
* This function can be used by asm versions of crc32 ( )
*/
const unsigned long FAR * ZEXPORT get_crc_table ( )
{
# ifdef DYNAMIC_CRC_TABLE
if ( crc_table_empty )
make_crc_table ( ) ;
# endif /* DYNAMIC_CRC_TABLE */
return ( const unsigned long FAR * ) crc_table ;
}
/* ========================================================================= */
# define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
# define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */
unsigned long ZEXPORT crc32 ( crc , buf , len )
unsigned long crc ;
const unsigned char FAR * buf ;
unsigned len ;
{
if ( buf = = Z_NULL ) return 0UL ;
# ifdef DYNAMIC_CRC_TABLE
if ( crc_table_empty )
make_crc_table ( ) ;
# endif /* DYNAMIC_CRC_TABLE */
# ifdef BYFOUR
if ( sizeof ( void * ) = = sizeof ( ptrdiff_t ) ) {
u4 endian ;
endian = 1 ;
if ( * ( ( unsigned char * ) ( & endian ) ) )
return crc32_little ( crc , buf , len ) ;
else
return crc32_big ( crc , buf , len ) ;
}
# endif /* BYFOUR */
crc = crc ^ 0xffffffffUL ;
while ( len > = 8 ) {
DO8 ;
len - = 8 ;
}
if ( len ) do {
DO1 ;
} while ( - - len ) ;
return crc ^ 0xffffffffUL ;
}
# ifdef BYFOUR
/* ========================================================================= */
# define DOLIT4 c ^= *buf4++; \
c = crc_table [ 3 ] [ c & 0xff ] ^ crc_table [ 2 ] [ ( c > > 8 ) & 0xff ] ^ \
crc_table [ 1 ] [ ( c > > 16 ) & 0xff ] ^ crc_table [ 0 ] [ c > > 24 ]
# define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */
local unsigned long crc32_little ( crc , buf , len )
unsigned long crc ;
const unsigned char FAR * buf ;
unsigned len ;
{
register u4 c ;
register const u4 FAR * buf4 ;
c = ( u4 ) crc ;
c = ~ c ;
while ( len & & ( ( ptrdiff_t ) buf & 3 ) ) {
c = crc_table [ 0 ] [ ( c ^ * buf + + ) & 0xff ] ^ ( c > > 8 ) ;
len - - ;
}
buf4 = ( const u4 FAR * ) ( const void FAR * ) buf ;
while ( len > = 32 ) {
DOLIT32 ;
len - = 32 ;
}
while ( len > = 4 ) {
DOLIT4 ;
len - = 4 ;
}
buf = ( const unsigned char FAR * ) buf4 ;
if ( len ) do {
c = crc_table [ 0 ] [ ( c ^ * buf + + ) & 0xff ] ^ ( c > > 8 ) ;
} while ( - - len ) ;
c = ~ c ;
return ( unsigned long ) c ;
}
/* ========================================================================= */
# define DOBIG4 c ^= *++buf4; \
c = crc_table [ 4 ] [ c & 0xff ] ^ crc_table [ 5 ] [ ( c > > 8 ) & 0xff ] ^ \
crc_table [ 6 ] [ ( c > > 16 ) & 0xff ] ^ crc_table [ 7 ] [ c > > 24 ]
# define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */
local unsigned long crc32_big ( crc , buf , len )
unsigned long crc ;
const unsigned char FAR * buf ;
unsigned len ;
{
register u4 c ;
register const u4 FAR * buf4 ;
c = REV ( ( u4 ) crc ) ;
c = ~ c ;
while ( len & & ( ( ptrdiff_t ) buf & 3 ) ) {
c = crc_table [ 4 ] [ ( c > > 24 ) ^ * buf + + ] ^ ( c < < 8 ) ;
len - - ;
}
buf4 = ( const u4 FAR * ) ( const void FAR * ) buf ;
buf4 - - ;
while ( len > = 32 ) {
DOBIG32 ;
len - = 32 ;
}
while ( len > = 4 ) {
DOBIG4 ;
len - = 4 ;
}
buf4 + + ;
buf = ( const unsigned char FAR * ) buf4 ;
if ( len ) do {
c = crc_table [ 4 ] [ ( c > > 24 ) ^ * buf + + ] ^ ( c < < 8 ) ;
} while ( - - len ) ;
c = ~ c ;
return ( unsigned long ) ( REV ( c ) ) ;
}
# endif /* BYFOUR */
# define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times ( mat , vec )
unsigned long * mat ;
unsigned long vec ;
{
unsigned long sum ;
sum = 0 ;
while ( vec ) {
if ( vec & 1 )
sum ^ = * mat ;
vec > > = 1 ;
mat + + ;
}
return sum ;
}
/* ========================================================================= */
local void gf2_matrix_square ( square , mat )
unsigned long * square ;
unsigned long * mat ;
{
int n ;
for ( n = 0 ; n < GF2_DIM ; n + + )
square [ n ] = gf2_matrix_times ( mat , mat [ n ] ) ;
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine ( crc1 , crc2 , len2 )
uLong crc1 ;
uLong crc2 ;
z_off_t len2 ;
{
int n ;
unsigned long row ;
unsigned long even [ GF2_DIM ] ; /* even-power-of-two zeros operator */
unsigned long odd [ GF2_DIM ] ; /* odd-power-of-two zeros operator */
/* degenerate case */
if ( len2 = = 0 )
return crc1 ;
/* put operator for one zero bit in odd */
odd [ 0 ] = 0xedb88320L ; /* CRC-32 polynomial */
row = 1 ;
for ( n = 1 ; n < GF2_DIM ; n + + ) {
odd [ n ] = row ;
row < < = 1 ;
}
/* put operator for two zero bits in even */
gf2_matrix_square ( even , odd ) ;
/* put operator for four zero bits in odd */
gf2_matrix_square ( odd , even ) ;
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte , eight zero bits , in even ) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square ( even , odd ) ;
if ( len2 & 1 )
crc1 = gf2_matrix_times ( even , crc1 ) ;
len2 > > = 1 ;
/* if no more bits set, then done */
if ( len2 = = 0 )
break ;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square ( odd , even ) ;
if ( len2 & 1 )
crc1 = gf2_matrix_times ( odd , crc1 ) ;
len2 > > = 1 ;
/* if no more bits set, then done */
} while ( len2 ! = 0 ) ;
/* return combined crc */
crc1 ^ = crc2 ;
return crc1 ;
}