emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/CRC32.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
jaroslav@694
     1
/* -*-mode:java; c-basic-offset:2; -*- */
jaroslav@694
     2
/*
jaroslav@694
     3
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
jaroslav@694
     4
jaroslav@694
     5
Redistribution and use in source and binary forms, with or without
jaroslav@694
     6
modification, are permitted provided that the following conditions are met:
jaroslav@694
     7
jaroslav@694
     8
  1. Redistributions of source code must retain the above copyright notice,
jaroslav@694
     9
     this list of conditions and the following disclaimer.
jaroslav@694
    10
jaroslav@694
    11
  2. Redistributions in binary form must reproduce the above copyright 
jaroslav@694
    12
     notice, this list of conditions and the following disclaimer in 
jaroslav@694
    13
     the documentation and/or other materials provided with the distribution.
jaroslav@694
    14
jaroslav@694
    15
  3. The names of the authors may not be used to endorse or promote products
jaroslav@694
    16
     derived from this software without specific prior written permission.
jaroslav@694
    17
jaroslav@694
    18
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
jaroslav@694
    19
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
jaroslav@694
    20
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
jaroslav@694
    21
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
jaroslav@694
    22
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
jaroslav@694
    23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
jaroslav@694
    24
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
jaroslav@694
    25
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
jaroslav@694
    26
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
jaroslav@694
    27
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jaroslav@694
    28
 */
jaroslav@694
    29
/*
jaroslav@694
    30
 * This program is based on zlib-1.1.3, so all credit should go authors
jaroslav@694
    31
 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
jaroslav@694
    32
 * and contributors of zlib.
jaroslav@694
    33
 */
jaroslav@694
    34
jaroslav@694
    35
package org.apidesign.bck2brwsr.emul.zip;
jaroslav@694
    36
jaroslav@694
    37
import org.apidesign.bck2brwsr.emul.lang.System;
jaroslav@694
    38
jaroslav@694
    39
final class CRC32 implements Checksum {
jaroslav@694
    40
jaroslav@694
    41
  /*
jaroslav@694
    42
   *  The following logic has come from RFC1952.
jaroslav@694
    43
   */
jaroslav@694
    44
  private int v = 0;
jaroslav@694
    45
  private static int[] crc_table = null;
jaroslav@694
    46
  static {
jaroslav@694
    47
    crc_table = new int[256];
jaroslav@694
    48
    for (int n = 0; n < 256; n++) {
jaroslav@694
    49
      int c = n;
jaroslav@694
    50
      for (int k = 8;  --k >= 0; ) {
jaroslav@694
    51
        if ((c & 1) != 0)
jaroslav@694
    52
	  c = 0xedb88320 ^ (c >>> 1);
jaroslav@694
    53
        else
jaroslav@694
    54
          c = c >>> 1;
jaroslav@694
    55
      }
jaroslav@694
    56
      crc_table[n] = c;
jaroslav@694
    57
    }
jaroslav@694
    58
  }
jaroslav@694
    59
jaroslav@694
    60
  public void update (byte[] buf, int index, int len) {
jaroslav@694
    61
    int c = ~v;
jaroslav@694
    62
    while (--len >= 0)
jaroslav@694
    63
      c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
jaroslav@694
    64
    v = ~c;
jaroslav@694
    65
  }
jaroslav@694
    66
jaroslav@694
    67
  public void reset(){
jaroslav@694
    68
    v = 0;
jaroslav@694
    69
  }
jaroslav@694
    70
jaroslav@694
    71
  public void reset(long vv){
jaroslav@694
    72
    v = (int)(vv&0xffffffffL);
jaroslav@694
    73
  }
jaroslav@694
    74
jaroslav@694
    75
  public long getValue(){
jaroslav@694
    76
    return (long)(v&0xffffffffL);
jaroslav@694
    77
  }
jaroslav@694
    78
jaroslav@694
    79
  // The following logic has come from zlib.1.2.
jaroslav@694
    80
  private static final int GF2_DIM = 32;
jaroslav@694
    81
  static long combine(long crc1, long crc2, long len2){
jaroslav@694
    82
    long row;
jaroslav@694
    83
    long[] even = new long[GF2_DIM];
jaroslav@694
    84
    long[] odd = new long[GF2_DIM];
jaroslav@694
    85
jaroslav@694
    86
    // degenerate case (also disallow negative lengths)
jaroslav@694
    87
    if (len2 <= 0)
jaroslav@694
    88
      return crc1;
jaroslav@694
    89
jaroslav@694
    90
    // put operator for one zero bit in odd
jaroslav@694
    91
    odd[0] = 0xedb88320L;          // CRC-32 polynomial
jaroslav@694
    92
    row = 1;
jaroslav@694
    93
    for (int n = 1; n < GF2_DIM; n++) {
jaroslav@694
    94
        odd[n] = row;
jaroslav@694
    95
        row <<= 1;
jaroslav@694
    96
    }
jaroslav@694
    97
jaroslav@694
    98
    // put operator for two zero bits in even
jaroslav@694
    99
    gf2_matrix_square(even, odd);
jaroslav@694
   100
jaroslav@694
   101
    // put operator for four zero bits in odd
jaroslav@694
   102
    gf2_matrix_square(odd, even);
jaroslav@694
   103
jaroslav@694
   104
    // apply len2 zeros to crc1 (first square will put the operator for one
jaroslav@694
   105
    // zero byte, eight zero bits, in even)
jaroslav@694
   106
    do {
jaroslav@694
   107
      // apply zeros operator for this bit of len2
jaroslav@694
   108
      gf2_matrix_square(even, odd);
jaroslav@694
   109
      if ((len2 & 1)!=0)
jaroslav@694
   110
        crc1 = gf2_matrix_times(even, crc1);
jaroslav@694
   111
      len2 >>= 1;
jaroslav@694
   112
jaroslav@694
   113
      // if no more bits set, then done
jaroslav@694
   114
      if (len2 == 0)
jaroslav@694
   115
        break;
jaroslav@694
   116
jaroslav@694
   117
      // another iteration of the loop with odd and even swapped
jaroslav@694
   118
      gf2_matrix_square(odd, even);
jaroslav@694
   119
      if ((len2 & 1)!=0)
jaroslav@694
   120
        crc1 = gf2_matrix_times(odd, crc1);
jaroslav@694
   121
      len2 >>= 1;
jaroslav@694
   122
jaroslav@694
   123
      // if no more bits set, then done
jaroslav@694
   124
    } while (len2 != 0);
jaroslav@694
   125
jaroslav@694
   126
    /* return combined crc */
jaroslav@694
   127
    crc1 ^= crc2;
jaroslav@694
   128
    return crc1;
jaroslav@694
   129
  }
jaroslav@694
   130
jaroslav@694
   131
  private static long gf2_matrix_times(long[] mat, long vec){
jaroslav@694
   132
    long sum = 0;
jaroslav@694
   133
    int index = 0;
jaroslav@694
   134
    while (vec!=0) {
jaroslav@694
   135
      if ((vec & 1)!=0)
jaroslav@694
   136
        sum ^= mat[index];
jaroslav@694
   137
      vec >>= 1;
jaroslav@694
   138
      index++;
jaroslav@694
   139
    }
jaroslav@694
   140
    return sum;
jaroslav@694
   141
  }
jaroslav@694
   142
jaroslav@694
   143
  static final void gf2_matrix_square(long[] square, long[] mat) {
jaroslav@694
   144
    for (int n = 0; n < GF2_DIM; n++)
jaroslav@694
   145
      square[n] = gf2_matrix_times(mat, mat[n]);
jaroslav@694
   146
  }
jaroslav@694
   147
jaroslav@694
   148
  /*
jaroslav@694
   149
  private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
jaroslav@694
   150
jaroslav@694
   151
  public void update(byte[] buf, int index, int len){
jaroslav@694
   152
    if(buf==null) {crc32.reset();}
jaroslav@694
   153
    else{crc32.update(buf, index, len);}
jaroslav@694
   154
  }
jaroslav@694
   155
  public void reset(){
jaroslav@694
   156
    crc32.reset();
jaroslav@694
   157
  }
jaroslav@694
   158
  public void reset(long init){
jaroslav@694
   159
    if(init==0L){
jaroslav@694
   160
      crc32.reset();
jaroslav@694
   161
    }
jaroslav@694
   162
    else{
jaroslav@694
   163
      System.err.println("unsupported operation");
jaroslav@694
   164
    }
jaroslav@694
   165
  }
jaroslav@694
   166
  public long getValue(){
jaroslav@694
   167
    return crc32.getValue();
jaroslav@694
   168
  }
jaroslav@694
   169
*/
jaroslav@694
   170
  public CRC32 copy(){
jaroslav@694
   171
    CRC32 foo = new CRC32();
jaroslav@694
   172
    foo.v = this.v;
jaroslav@694
   173
    return foo;
jaroslav@694
   174
  }
jaroslav@694
   175
jaroslav@694
   176
  public static int[] getCRC32Table(){
jaroslav@694
   177
    int[] tmp = new int[crc_table.length];
jaroslav@694
   178
    System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
jaroslav@694
   179
    return tmp;
jaroslav@694
   180
  }
jaroslav@694
   181
}