1 /* 2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.util.zip; 27 28 import java.lang.reflect.Field; 29 import java.nio.ByteBuffer; 30 import sun.nio.ch.DirectBuffer; 31 32 /** 33 * A class that can be used to compute the CRC-32 of a data stream. 34 * 35 * <p> Passing a {@code null} argument to a method in this class will cause 36 * a {@link NullPointerException} to be thrown. 37 * 38 * @see Checksum 39 * @author David Connelly 40 */ 41 public 42 class CRC32 implements Checksum { 43 private int crc; 44 45 /** 46 * Creates a new CRC32 object. 47 */ 48 public CRC32() { 49 } 50 51 52 /** 53 * Updates the CRC-32 checksum with the specified byte (the low 54 * eight bits of the argument b). 55 * 56 * @param b the byte to update the checksum with 57 */ 58 public void update(int b) { 59 int c = ~ crc; 60 b = timesXtoThe32[(b ^ c) & 0xFF]; 61 b = b ^ (c >>> 8); 62 crc = ~b; 63 } 64 65 /** 66 * Updates the CRC-32 checksum with the specified array of bytes. 67 */ 68 public void update(byte[] b, int off, int len) { 69 if (b == null) { 70 throw new NullPointerException(); 71 } 72 if (off < 0 || len < 0 || off > b.length - len) { 73 throw new ArrayIndexOutOfBoundsException(); 74 } 75 76 if (len < javaCRCIfSmallerThan) { 77 crc = updateBytesSimple(crc, b, off, len); 78 } else { 79 crc = updateBytes(crc, b, off, len); 80 } 81 } 82 83 /** 84 * Updates the CRC-32 checksum with the specified array of bytes. 85 * 86 * @param b the array of bytes to update the checksum with 87 */ 88 public void update(byte[] b) { 89 crc = updateBytes(crc, b, 0, b.length); 90 } 91 92 /** 93 * Updates the checksum with the bytes from the specified buffer. 94 * 95 * The checksum is updated using 96 * buffer.{@link java.nio.Buffer#remaining() remaining()} 97 * bytes starting at 98 * buffer.{@link java.nio.Buffer#position() position()} 99 * Upon return, the buffer's position will 100 * be updated to its limit; its limit will not have been changed. 101 * 102 * @param buffer the ByteBuffer to update the checksum with 103 * @since 1.8 104 */ 105 public void update(ByteBuffer buffer) { 106 int pos = buffer.position(); 107 int limit = buffer.limit(); 108 assert (pos <= limit); 109 int rem = limit - pos; 110 if (rem <= 0) 111 return; 112 if (buffer instanceof DirectBuffer) { 113 crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem); 114 } else if (buffer.hasArray()) { 115 crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem); 116 } else { 117 byte[] b = new byte[rem]; 118 buffer.get(b); 119 crc = updateBytes(crc, b, 0, b.length); 120 } 121 buffer.position(limit); 122 } 123 124 /** 125 * Resets CRC-32 to initial value. 126 */ 127 public void reset() { 128 crc = 0; 129 } 130 131 /** 132 * Returns CRC-32 value. 133 */ 134 public long getValue() { 135 return (long)crc & 0xffffffffL; 136 } 137 138 private native static int update(int crc, int b); 139 private native static int updateBytes(int crc, byte[] b, int off, int len); 140 141 private native static int updateByteBuffer(int adler, long addr, 142 int off, int len); 143 144 /** 145 * Simple byte-at-a-time CRC for avoiding the overhead of native call. 146 * Breakeven ranges between 60 and 100 bytes. 147 */ 148 private static int updateBytesSimple(int crc, byte[] b, int off, int len) { 149 int[] a = timesXtoThe32; 150 if (a.length < 256) 151 throw new ArrayIndexOutOfBoundsException(); 152 int c = ~crc; 153 for (int i = 0; i < len; i++ ) { 154 int x0 = b[i + off]; 155 x0 = a[(x0 ^ c) & 0xFF]; 156 c = x0 ^ (c >>> 8); 157 } 158 return ~c; 159 } 160 161 /** 162 * Returns true if CLMUL is both requested and supported. 163 */ 164 private native static boolean init(int[] timesXtoThe32, boolean try_use_clmul); 165 166 /** 167 * timesXtoThe32[a] = rep(poly(a)*x**32) 168 */ 169 static int[] timesXtoThe32; 170 171 /** 172 * Estimated CRC size below which the JNI overhead is too large. 173 * May be modified depending on platform properties. 174 */ 175 static int javaCRCIfSmallerThan = 80; 176 177 static { 178 timesXtoThe32 = new int[256]; 179 boolean try_use_clmul = 180 "true".equals(sun.misc.VM.getSavedProperty("sun.zip.clmulSupported")); 181 init(timesXtoThe32, try_use_clmul); 182 } 183 }