sourcepawn/compiler/zlib/crc32.c
author David Anderson <dvander@alliedmods.net>
Sun Aug 30 00:21:42 2009 -0700 (2009-08-30)
changeset 2783 5f333027ef04
parent 27 764c6dd3dc25
permissions -rw-r--r--
Imported support for new build system.
dvander@27
     1
/* crc32.c -- compute the CRC-32 of a data stream
dvander@27
     2
 * Copyright (C) 1995-2005 Mark Adler
dvander@27
     3
 * For conditions of distribution and use, see copyright notice in zlib.h
dvander@27
     4
 *
dvander@27
     5
 * Thanks to Rodney Brown <[email protected]> for his contribution of faster
dvander@27
     6
 * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
dvander@27
     7
 * tables for updating the shift register in one step with three exclusive-ors
dvander@27
     8
 * instead of four steps with four exclusive-ors.  This results in about a
dvander@27
     9
 * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
dvander@27
    10
 */
dvander@27
    11
dvander@27
    12
/* @(#) $Id$ */
dvander@27
    13
dvander@27
    14
/*
dvander@27
    15
  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
dvander@27
    16
  protection on the static variables used to control the first-use generation
dvander@27
    17
  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
dvander@27
    18
  first call get_crc_table() to initialize the tables before allowing more than
dvander@27
    19
  one thread to use crc32().
dvander@27
    20
 */
dvander@27
    21
dvander@2783
    22
#include <stdio.h>
dvander@27
    23
#ifdef MAKECRCH
dvander@27
    24
#  include <stdio.h>
dvander@27
    25
#  ifndef DYNAMIC_CRC_TABLE
dvander@27
    26
#    define DYNAMIC_CRC_TABLE
dvander@27
    27
#  endif /* !DYNAMIC_CRC_TABLE */
dvander@27
    28
#endif /* MAKECRCH */
dvander@27
    29
dvander@27
    30
#include "zutil.h"      /* for STDC and FAR definitions */
dvander@27
    31
dvander@27
    32
#define local static
dvander@27
    33
dvander@27
    34
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
dvander@27
    35
#ifndef NOBYFOUR
dvander@27
    36
#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
dvander@27
    37
#    include <limits.h>
dvander@27
    38
#    define BYFOUR
dvander@27
    39
#    if (UINT_MAX == 0xffffffffUL)
dvander@27
    40
       typedef unsigned int u4;
dvander@27
    41
#    else
dvander@27
    42
#      if (ULONG_MAX == 0xffffffffUL)
dvander@27
    43
         typedef unsigned long u4;
dvander@27
    44
#      else
dvander@27
    45
#        if (USHRT_MAX == 0xffffffffUL)
dvander@27
    46
           typedef unsigned short u4;
dvander@27
    47
#        else
dvander@27
    48
#          undef BYFOUR     /* can't find a four-byte integer type! */
dvander@27
    49
#        endif
dvander@27
    50
#      endif
dvander@27
    51
#    endif
dvander@27
    52
#  endif /* STDC */
dvander@27
    53
#endif /* !NOBYFOUR */
dvander@27
    54
dvander@27
    55
/* Definitions for doing the crc four data bytes at a time. */
dvander@27
    56
#ifdef BYFOUR
dvander@27
    57
#  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
dvander@27
    58
                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
dvander@27
    59
   local unsigned long crc32_little OF((unsigned long,
dvander@27
    60
                        const unsigned char FAR *, unsigned));
dvander@27
    61
   local unsigned long crc32_big OF((unsigned long,
dvander@27
    62
                        const unsigned char FAR *, unsigned));
dvander@27
    63
#  define TBLS 8
dvander@27
    64
#else
dvander@27
    65
#  define TBLS 1
dvander@27
    66
#endif /* BYFOUR */
dvander@27
    67
dvander@27
    68
/* Local functions for crc concatenation */
dvander@27
    69
local unsigned long gf2_matrix_times OF((unsigned long *mat,
dvander@27
    70
                                         unsigned long vec));
dvander@27
    71
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
dvander@27
    72
dvander@27
    73
#ifdef DYNAMIC_CRC_TABLE
dvander@27
    74
dvander@27
    75
local volatile int crc_table_empty = 1;
dvander@27
    76
local unsigned long FAR crc_table[TBLS][256];
dvander@27
    77
local void make_crc_table OF((void));
dvander@27
    78
#ifdef MAKECRCH
dvander@27
    79
   local void write_table OF((FILE *, const unsigned long FAR *));
dvander@27
    80
#endif /* MAKECRCH */
dvander@27
    81
/*
dvander@27
    82
  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
dvander@27
    83
  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.
dvander@27
    84
dvander@27
    85
  Polynomials over GF(2) are represented in binary, one bit per coefficient,
dvander@27
    86
  with the lowest powers in the most significant bit.  Then adding polynomials
dvander@27
    87
  is just exclusive-or, and multiplying a polynomial by x is a right shift by
dvander@27
    88
  one.  If we call the above polynomial p, and represent a byte as the
dvander@27
    89
  polynomial q, also with the lowest power in the most significant bit (so the
dvander@27
    90
  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
dvander@27
    91
  where a mod b means the remainder after dividing a by b.
dvander@27
    92
dvander@27
    93
  This calculation is done using the shift-register method of multiplying and
dvander@27
    94
  taking the remainder.  The register is initialized to zero, and for each
dvander@27
    95
  incoming bit, x^32 is added mod p to the register if the bit is a one (where
dvander@27
    96
  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
dvander@27
    97
  x (which is shifting right by one and adding x^32 mod p if the bit shifted
dvander@27
    98
  out is a one).  We start with the highest power (least significant bit) of
dvander@27
    99
  q and repeat for all eight bits of q.
dvander@27
   100
dvander@27
   101
  The first table is simply the CRC of all possible eight bit values.  This is
dvander@27
   102
  all the information needed to generate CRCs on data a byte at a time for all
dvander@27
   103
  combinations of CRC register values and incoming bytes.  The remaining tables
dvander@27
   104
  allow for word-at-a-time CRC calculation for both big-endian and little-
dvander@27
   105
  endian machines, where a word is four bytes.
dvander@27
   106
*/
dvander@27
   107
local void make_crc_table()
dvander@27
   108
{
dvander@27
   109
    unsigned long c;
dvander@27
   110
    int n, k;
dvander@27
   111
    unsigned long poly;                 /* polynomial exclusive-or pattern */
dvander@27
   112
    /* terms of polynomial defining this crc (except x^32): */
dvander@27
   113
    static volatile int first = 1;      /* flag to limit concurrent making */
dvander@27
   114
    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
dvander@27
   115
dvander@27
   116
    /* See if another task is already doing this (not thread-safe, but better
dvander@27
   117
       than nothing -- significantly reduces duration of vulnerability in
dvander@27
   118
       case the advice about DYNAMIC_CRC_TABLE is ignored) */
dvander@27
   119
    if (first) {
dvander@27
   120
        first = 0;
dvander@27
   121
dvander@27
   122
        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
dvander@27
   123
        poly = 0UL;
dvander@27
   124
        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
dvander@27
   125
            poly |= 1UL << (31 - p[n]);
dvander@27
   126
dvander@27
   127
        /* generate a crc for every 8-bit value */
dvander@27
   128
        for (n = 0; n < 256; n++) {
dvander@27
   129
            c = (unsigned long)n;
dvander@27
   130
            for (k = 0; k < 8; k++)
dvander@27
   131
                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
dvander@27
   132
            crc_table[0][n] = c;
dvander@27
   133
        }
dvander@27
   134
dvander@27
   135
#ifdef BYFOUR
dvander@27
   136
        /* generate crc for each value followed by one, two, and three zeros,
dvander@27
   137
           and then the byte reversal of those as well as the first table */
dvander@27
   138
        for (n = 0; n < 256; n++) {
dvander@27
   139
            c = crc_table[0][n];
dvander@27
   140
            crc_table[4][n] = REV(c);
dvander@27
   141
            for (k = 1; k < 4; k++) {
dvander@27
   142
                c = crc_table[0][c & 0xff] ^ (c >> 8);
dvander@27
   143
                crc_table[k][n] = c;
dvander@27
   144
                crc_table[k + 4][n] = REV(c);
dvander@27
   145
            }
dvander@27
   146
        }
dvander@27
   147
#endif /* BYFOUR */
dvander@27
   148
dvander@27
   149
        crc_table_empty = 0;
dvander@27
   150
    }
dvander@27
   151
    else {      /* not first */
dvander@27
   152
        /* wait for the other guy to finish (not efficient, but rare) */
dvander@27
   153
        while (crc_table_empty)
dvander@27
   154
            ;
dvander@27
   155
    }
dvander@27
   156
dvander@27
   157
#ifdef MAKECRCH
dvander@27
   158
    /* write out CRC tables to crc32.h */
dvander@27
   159
    {
dvander@27
   160
        FILE *out;
dvander@27
   161
dvander@27
   162
        out = fopen("crc32.h", "w");
dvander@27
   163
        if (out == NULL) return;
dvander@27
   164
        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
dvander@27
   165
        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
dvander@27
   166
        fprintf(out, "local const unsigned long FAR ");
dvander@27
   167
        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
dvander@27
   168
        write_table(out, crc_table[0]);
dvander@27
   169
#  ifdef BYFOUR
dvander@27
   170
        fprintf(out, "#ifdef BYFOUR\n");
dvander@27
   171
        for (k = 1; k < 8; k++) {
dvander@27
   172
            fprintf(out, "  },\n  {\n");
dvander@27
   173
            write_table(out, crc_table[k]);
dvander@27
   174
        }
dvander@27
   175
        fprintf(out, "#endif\n");
dvander@27
   176
#  endif /* BYFOUR */
dvander@27
   177
        fprintf(out, "  }\n};\n");
dvander@27
   178
        fclose(out);
dvander@27
   179
    }
dvander@27
   180
#endif /* MAKECRCH */
dvander@27
   181
}
dvander@27
   182
dvander@27
   183
#ifdef MAKECRCH
dvander@27
   184
local void write_table(out, table)
dvander@27
   185
    FILE *out;
dvander@27
   186
    const unsigned long FAR *table;
dvander@27
   187
{
dvander@27
   188
    int n;
dvander@27
   189
dvander@27
   190
    for (n = 0; n < 256; n++)
dvander@27
   191
        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
dvander@27
   192
                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
dvander@27
   193
}
dvander@27
   194
#endif /* MAKECRCH */
dvander@27
   195
dvander@27
   196
#else /* !DYNAMIC_CRC_TABLE */
dvander@27
   197
/* ========================================================================
dvander@27
   198
 * Tables of CRC-32s of all single-byte values, made by make_crc_table().
dvander@27
   199
 */
dvander@27
   200
#include "crc32.h"
dvander@27
   201
#endif /* DYNAMIC_CRC_TABLE */
dvander@27
   202
dvander@27
   203
/* =========================================================================
dvander@27
   204
 * This function can be used by asm versions of crc32()
dvander@27
   205
 */
dvander@27
   206
const unsigned long FAR * ZEXPORT get_crc_table()
dvander@27
   207
{
dvander@27
   208
#ifdef DYNAMIC_CRC_TABLE
dvander@27
   209
    if (crc_table_empty)
dvander@27
   210
        make_crc_table();
dvander@27
   211
#endif /* DYNAMIC_CRC_TABLE */
dvander@27
   212
    return (const unsigned long FAR *)crc_table;
dvander@27
   213
}
dvander@27
   214
dvander@27
   215
/* ========================================================================= */
dvander@27
   216
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
dvander@27
   217
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
dvander@27
   218
dvander@27
   219
/* ========================================================================= */
dvander@27
   220
unsigned long ZEXPORT crc32(crc, buf, len)
dvander@27
   221
    unsigned long crc;
dvander@27
   222
    const unsigned char FAR *buf;
dvander@27
   223
    unsigned len;
dvander@27
   224
{
dvander@27
   225
    if (buf == Z_NULL) return 0UL;
dvander@27
   226
dvander@27
   227
#ifdef DYNAMIC_CRC_TABLE
dvander@27
   228
    if (crc_table_empty)
dvander@27
   229
        make_crc_table();
dvander@27
   230
#endif /* DYNAMIC_CRC_TABLE */
dvander@27
   231
dvander@27
   232
#ifdef BYFOUR
dvander@27
   233
    if (sizeof(void *) == sizeof(ptrdiff_t)) {
dvander@27
   234
        u4 endian;
dvander@27
   235
dvander@27
   236
        endian = 1;
dvander@27
   237
        if (*((unsigned char *)(&endian)))
dvander@27
   238
            return crc32_little(crc, buf, len);
dvander@27
   239
        else
dvander@27
   240
            return crc32_big(crc, buf, len);
dvander@27
   241
    }
dvander@27
   242
#endif /* BYFOUR */
dvander@27
   243
    crc = crc ^ 0xffffffffUL;
dvander@27
   244
    while (len >= 8) {
dvander@27
   245
        DO8;
dvander@27
   246
        len -= 8;
dvander@27
   247
    }
dvander@27
   248
    if (len) do {
dvander@27
   249
        DO1;
dvander@27
   250
    } while (--len);
dvander@27
   251
    return crc ^ 0xffffffffUL;
dvander@27
   252
}
dvander@27
   253
dvander@27
   254
#ifdef BYFOUR
dvander@27
   255
dvander@27
   256
/* ========================================================================= */
dvander@27
   257
#define DOLIT4 c ^= *buf4++; \
dvander@27
   258
        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
dvander@27
   259
            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
dvander@27
   260
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
dvander@27
   261
dvander@27
   262
/* ========================================================================= */
dvander@27
   263
local unsigned long crc32_little(crc, buf, len)
dvander@27
   264
    unsigned long crc;
dvander@27
   265
    const unsigned char FAR *buf;
dvander@27
   266
    unsigned len;
dvander@27
   267
{
dvander@27
   268
    register u4 c;
dvander@27
   269
    register const u4 FAR *buf4;
dvander@27
   270
dvander@27
   271
    c = (u4)crc;
dvander@27
   272
    c = ~c;
dvander@27
   273
    while (len && ((ptrdiff_t)buf & 3)) {
dvander@27
   274
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
dvander@27
   275
        len--;
dvander@27
   276
    }
dvander@27
   277
dvander@27
   278
    buf4 = (const u4 FAR *)(const void FAR *)buf;
dvander@27
   279
    while (len >= 32) {
dvander@27
   280
        DOLIT32;
dvander@27
   281
        len -= 32;
dvander@27
   282
    }
dvander@27
   283
    while (len >= 4) {
dvander@27
   284
        DOLIT4;
dvander@27
   285
        len -= 4;
dvander@27
   286
    }
dvander@27
   287
    buf = (const unsigned char FAR *)buf4;
dvander@27
   288
dvander@27
   289
    if (len) do {
dvander@27
   290
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
dvander@27
   291
    } while (--len);
dvander@27
   292
    c = ~c;
dvander@27
   293
    return (unsigned long)c;
dvander@27
   294
}
dvander@27
   295
dvander@27
   296
/* ========================================================================= */
dvander@27
   297
#define DOBIG4 c ^= *++buf4; \
dvander@27
   298
        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
dvander@27
   299
            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
dvander@27
   300
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
dvander@27
   301
dvander@27
   302
/* ========================================================================= */
dvander@27
   303
local unsigned long crc32_big(crc, buf, len)
dvander@27
   304
    unsigned long crc;
dvander@27
   305
    const unsigned char FAR *buf;
dvander@27
   306
    unsigned len;
dvander@27
   307
{
dvander@27
   308
    register u4 c;
dvander@27
   309
    register const u4 FAR *buf4;
dvander@27
   310
dvander@27
   311
    c = REV((u4)crc);
dvander@27
   312
    c = ~c;
dvander@27
   313
    while (len && ((ptrdiff_t)buf & 3)) {
dvander@27
   314
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
dvander@27
   315
        len--;
dvander@27
   316
    }
dvander@27
   317
dvander@27
   318
    buf4 = (const u4 FAR *)(const void FAR *)buf;
dvander@27
   319
    buf4--;
dvander@27
   320
    while (len >= 32) {
dvander@27
   321
        DOBIG32;
dvander@27
   322
        len -= 32;
dvander@27
   323
    }
dvander@27
   324
    while (len >= 4) {
dvander@27
   325
        DOBIG4;
dvander@27
   326
        len -= 4;
dvander@27
   327
    }
dvander@27
   328
    buf4++;
dvander@27
   329
    buf = (const unsigned char FAR *)buf4;
dvander@27
   330
dvander@27
   331
    if (len) do {
dvander@27
   332
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
dvander@27
   333
    } while (--len);
dvander@27
   334
    c = ~c;
dvander@27
   335
    return (unsigned long)(REV(c));
dvander@27
   336
}
dvander@27
   337
dvander@27
   338
#endif /* BYFOUR */
dvander@27
   339
dvander@27
   340
#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
dvander@27
   341
dvander@27
   342
/* ========================================================================= */
dvander@27
   343
local unsigned long gf2_matrix_times(mat, vec)
dvander@27
   344
    unsigned long *mat;
dvander@27
   345
    unsigned long vec;
dvander@27
   346
{
dvander@27
   347
    unsigned long sum;
dvander@27
   348
dvander@27
   349
    sum = 0;
dvander@27
   350
    while (vec) {
dvander@27
   351
        if (vec & 1)
dvander@27
   352
            sum ^= *mat;
dvander@27
   353
        vec >>= 1;
dvander@27
   354
        mat++;
dvander@27
   355
    }
dvander@27
   356
    return sum;
dvander@27
   357
}
dvander@27
   358
dvander@27
   359
/* ========================================================================= */
dvander@27
   360
local void gf2_matrix_square(square, mat)
dvander@27
   361
    unsigned long *square;
dvander@27
   362
    unsigned long *mat;
dvander@27
   363
{
dvander@27
   364
    int n;
dvander@27
   365
dvander@27
   366
    for (n = 0; n < GF2_DIM; n++)
dvander@27
   367
        square[n] = gf2_matrix_times(mat, mat[n]);
dvander@27
   368
}
dvander@27
   369
dvander@27
   370
/* ========================================================================= */
dvander@27
   371
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
dvander@27
   372
    uLong crc1;
dvander@27
   373
    uLong crc2;
dvander@27
   374
    z_off_t len2;
dvander@27
   375
{
dvander@27
   376
    int n;
dvander@27
   377
    unsigned long row;
dvander@27
   378
    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
dvander@27
   379
    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
dvander@27
   380
dvander@27
   381
    /* degenerate case */
dvander@27
   382
    if (len2 == 0)
dvander@27
   383
        return crc1;
dvander@27
   384
dvander@27
   385
    /* put operator for one zero bit in odd */
dvander@27
   386
    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
dvander@27
   387
    row = 1;
dvander@27
   388
    for (n = 1; n < GF2_DIM; n++) {
dvander@27
   389
        odd[n] = row;
dvander@27
   390
        row <<= 1;
dvander@27
   391
    }
dvander@27
   392
dvander@27
   393
    /* put operator for two zero bits in even */
dvander@27
   394
    gf2_matrix_square(even, odd);
dvander@27
   395
dvander@27
   396
    /* put operator for four zero bits in odd */
dvander@27
   397
    gf2_matrix_square(odd, even);
dvander@27
   398
dvander@27
   399
    /* apply len2 zeros to crc1 (first square will put the operator for one
dvander@27
   400
       zero byte, eight zero bits, in even) */
dvander@27
   401
    do {
dvander@27
   402
        /* apply zeros operator for this bit of len2 */
dvander@27
   403
        gf2_matrix_square(even, odd);
dvander@27
   404
        if (len2 & 1)
dvander@27
   405
            crc1 = gf2_matrix_times(even, crc1);
dvander@27
   406
        len2 >>= 1;
dvander@27
   407
dvander@27
   408
        /* if no more bits set, then done */
dvander@27
   409
        if (len2 == 0)
dvander@27
   410
            break;
dvander@27
   411
dvander@27
   412
        /* another iteration of the loop with odd and even swapped */
dvander@27
   413
        gf2_matrix_square(odd, even);
dvander@27
   414
        if (len2 & 1)
dvander@27
   415
            crc1 = gf2_matrix_times(odd, crc1);
dvander@27
   416
        len2 >>= 1;
dvander@27
   417
dvander@27
   418
        /* if no more bits set, then done */
dvander@27
   419
    } while (len2 != 0);
dvander@27
   420
dvander@27
   421
    /* return combined crc */
dvander@27
   422
    crc1 ^= crc2;
dvander@27
   423
    return crc1;
dvander@27
   424
}