6321472: Add CRC-32C API
Summary: to add CRC-32C api and implementation
Reviewed-by: sherman
Contributed-by: staffan.friberg@oracle.com
--- a/jdk/src/java.base/share/classes/java/util/zip/Adler32.java Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/Adler32.java Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,8 @@
* can be computed much faster.
*
* <p> Passing a {@code null} argument to a method in this class will cause
- * a {@link NullPointerException} to be thrown.
+ * a {@link NullPointerException} to be thrown.</p>
*
- * @see Checksum
* @author David Connelly
*/
public
@@ -53,9 +52,8 @@
/**
* Updates the checksum with the specified byte (the low eight
* bits of the argument b).
- *
- * @param b the byte to update the checksum with
*/
+ @Override
public void update(int b) {
adler = update(adler, b);
}
@@ -63,11 +61,12 @@
/**
* Updates the checksum with the specified array of bytes.
*
- * @throws ArrayIndexOutOfBoundsException
- * if {@code off} is negative, or {@code len} is negative,
- * or {@code off+len} is greater than the length of the
- * array {@code b}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code off} is negative, or {@code len} is negative, or
+ * {@code off+len} is negative or greater than the length of
+ * the array {@code b}.
*/
+ @Override
public void update(byte[] b, int off, int len) {
if (b == null) {
throw new NullPointerException();
@@ -79,28 +78,15 @@
}
/**
- * Updates the checksum with the specified array of bytes.
- *
- * @param b the byte array to update the checksum with
- */
- public void update(byte[] b) {
- adler = updateBytes(adler, b, 0, b.length);
- }
-
-
- /**
* Updates the checksum with the bytes from the specified buffer.
*
- * The checksum is updated using
- * buffer.{@link java.nio.Buffer#remaining() remaining()}
- * bytes starting at
- * buffer.{@link java.nio.Buffer#position() position()}
- * Upon return, the buffer's position will be updated to its
- * limit; its limit will not have been changed.
+ * The checksum is updated with the remaining bytes in the buffer, starting
+ * at the buffer's position. Upon return, the buffer's position will be
+ * updated to its limit; its limit will not have been changed.
*
- * @param buffer the ByteBuffer to update the checksum with
* @since 1.8
*/
+ @Override
public void update(ByteBuffer buffer) {
int pos = buffer.position();
int limit = buffer.limit();
@@ -113,9 +99,12 @@
} else if (buffer.hasArray()) {
adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);
} else {
- byte[] b = new byte[rem];
- buffer.get(b);
- adler = updateBytes(adler, b, 0, b.length);
+ byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+ while (buffer.hasRemaining()) {
+ int length = Math.min(buffer.remaining(), b.length);
+ buffer.get(b, 0, length);
+ update(b, 0, length);
+ }
}
buffer.position(limit);
}
@@ -123,6 +112,7 @@
/**
* Resets the checksum to initial value.
*/
+ @Override
public void reset() {
adler = 1;
}
@@ -130,6 +120,7 @@
/**
* Returns the checksum value.
*/
+ @Override
public long getValue() {
return (long)adler & 0xffffffffL;
}
--- a/jdk/src/java.base/share/classes/java/util/zip/CRC32.java Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32.java Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,8 @@
* A class that can be used to compute the CRC-32 of a data stream.
*
* <p> Passing a {@code null} argument to a method in this class will cause
- * a {@link NullPointerException} to be thrown.
+ * a {@link NullPointerException} to be thrown.</p>
*
- * @see Checksum
* @author David Connelly
*/
public
@@ -51,9 +50,8 @@
/**
* Updates the CRC-32 checksum with the specified byte (the low
* eight bits of the argument b).
- *
- * @param b the byte to update the checksum with
*/
+ @Override
public void update(int b) {
crc = update(crc, b);
}
@@ -61,11 +59,12 @@
/**
* Updates the CRC-32 checksum with the specified array of bytes.
*
- * @throws ArrayIndexOutOfBoundsException
- * if {@code off} is negative, or {@code len} is negative,
- * or {@code off+len} is greater than the length of the
- * array {@code b}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code off} is negative, or {@code len} is negative, or
+ * {@code off+len} is negative or greater than the length of
+ * the array {@code b}.
*/
+ @Override
public void update(byte[] b, int off, int len) {
if (b == null) {
throw new NullPointerException();
@@ -77,27 +76,15 @@
}
/**
- * Updates the CRC-32 checksum with the specified array of bytes.
+ * Updates the CRC-32 checksum with the bytes from the specified buffer.
*
- * @param b the array of bytes to update the checksum with
- */
- public void update(byte[] b) {
- crc = updateBytes(crc, b, 0, b.length);
- }
-
- /**
- * Updates the checksum with the bytes from the specified buffer.
+ * The checksum is updated with the remaining bytes in the buffer, starting
+ * at the buffer's position. Upon return, the buffer's position will be
+ * updated to its limit; its limit will not have been changed.
*
- * The checksum is updated using
- * buffer.{@link java.nio.Buffer#remaining() remaining()}
- * bytes starting at
- * buffer.{@link java.nio.Buffer#position() position()}
- * Upon return, the buffer's position will
- * be updated to its limit; its limit will not have been changed.
- *
- * @param buffer the ByteBuffer to update the checksum with
* @since 1.8
*/
+ @Override
public void update(ByteBuffer buffer) {
int pos = buffer.position();
int limit = buffer.limit();
@@ -110,9 +97,12 @@
} else if (buffer.hasArray()) {
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem);
} else {
- byte[] b = new byte[rem];
- buffer.get(b);
- crc = updateBytes(crc, b, 0, b.length);
+ byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+ while (buffer.hasRemaining()) {
+ int length = Math.min(buffer.remaining(), b.length);
+ buffer.get(b, 0, length);
+ update(b, 0, length);
+ }
}
buffer.position(limit);
}
@@ -120,6 +110,7 @@
/**
* Resets CRC-32 to initial value.
*/
+ @Override
public void reset() {
crc = 0;
}
@@ -127,6 +118,7 @@
/**
* Returns CRC-32 value.
*/
+ @Override
public long getValue() {
return (long)crc & 0xffffffffL;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.zip;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import sun.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
+/**
+ * A class that can be used to compute the CRC-32C of a data stream.
+ *
+ * <p>
+ * CRC-32C is defined in <a href="http://www.ietf.org/rfc/rfc3720.txt">RFC
+ * 3720</a>: Internet Small Computer Systems Interface (iSCSI).
+ * </p>
+ *
+ * <p>
+ * Passing a {@code null} argument to a method in this class will cause a
+ * {@link NullPointerException} to be thrown.
+ * </p>
+ *
+ * @since 1.9
+ */
+public final class CRC32C implements Checksum {
+
+ /*
+ * This CRC-32C implementation uses the 'slicing-by-8' algorithm described
+ * in the paper "A Systematic Approach to Building High Performance
+ * Software-Based CRC Generators" by Michael E. Kounavis and Frank L. Berry,
+ * Intel Research and Development
+ */
+
+ /**
+ * CRC-32C Polynomial
+ */
+ private static final int CRC32C_POLY = 0x1EDC6F41;
+ private static final int REVERSED_CRC32C_POLY = Integer.reverse(CRC32C_POLY);
+
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+ // Lookup tables
+ // Lookup table for single byte calculations
+ private static final int[] byteTable;
+ // Lookup tables for bulk operations in 'slicing-by-8' algorithm
+ private static final int[][] byteTables = new int[8][256];
+ private static final int[] byteTable0 = byteTables[0];
+ private static final int[] byteTable1 = byteTables[1];
+ private static final int[] byteTable2 = byteTables[2];
+ private static final int[] byteTable3 = byteTables[3];
+ private static final int[] byteTable4 = byteTables[4];
+ private static final int[] byteTable5 = byteTables[5];
+ private static final int[] byteTable6 = byteTables[6];
+ private static final int[] byteTable7 = byteTables[7];
+
+ static {
+ // Generate lookup tables
+ // High-order polynomial term stored in LSB of r.
+ for (int index = 0; index < byteTables[0].length; index++) {
+ int r = index;
+ for (int i = 0; i < Byte.SIZE; i++) {
+ if ((r & 1) != 0) {
+ r = (r >>> 1) ^ REVERSED_CRC32C_POLY;
+ } else {
+ r >>>= 1;
+ }
+ }
+ byteTables[0][index] = r;
+ }
+
+ for (int index = 0; index < byteTables[0].length; index++) {
+ int r = byteTables[0][index];
+
+ for (int k = 1; k < byteTables.length; k++) {
+ r = byteTables[0][r & 0xFF] ^ (r >>> 8);
+ byteTables[k][index] = r;
+ }
+ }
+
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ byteTable = byteTables[0];
+ } else { // ByteOrder.BIG_ENDIAN
+ byteTable = new int[byteTable0.length];
+ System.arraycopy(byteTable0, 0, byteTable, 0, byteTable0.length);
+ for (int[] table : byteTables) {
+ for (int index = 0; index < table.length; index++) {
+ table[index] = Integer.reverseBytes(table[index]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Calculated CRC-32C value
+ */
+ private int crc = 0xFFFFFFFF;
+
+ /**
+ * Creates a new CRC32C object.
+ */
+ public CRC32C() {
+ }
+
+ /**
+ * Updates the CRC-32C checksum with the specified byte (the low eight bits
+ * of the argument b).
+ */
+ @Override
+ public void update(int b) {
+ crc = (crc >>> 8) ^ byteTable[(crc ^ (b & 0xFF)) & 0xFF];
+ }
+
+ /**
+ * Updates the CRC-32C checksum with the specified array of bytes.
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code off} is negative, or {@code len} is negative, or
+ * {@code off+len} is negative or greater than the length of
+ * the array {@code b}.
+ */
+ @Override
+ public void update(byte[] b, int off, int len) {
+ if (b == null) {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ crc = updateBytes(crc, b, off, (off + len));
+ }
+
+ /**
+ * Updates the CRC-32C checksum with the bytes from the specified buffer.
+ *
+ * The checksum is updated with the remaining bytes in the buffer, starting
+ * at the buffer's position. Upon return, the buffer's position will be
+ * updated to its limit; its limit will not have been changed.
+ */
+ @Override
+ public void update(ByteBuffer buffer) {
+ int pos = buffer.position();
+ int limit = buffer.limit();
+ assert (pos <= limit);
+ int rem = limit - pos;
+ if (rem <= 0) {
+ return;
+ }
+
+ if (buffer instanceof DirectBuffer) {
+ crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(),
+ pos, limit);
+ } else if (buffer.hasArray()) {
+ crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(),
+ limit + buffer.arrayOffset());
+ } else {
+ byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+ while (buffer.hasRemaining()) {
+ int length = Math.min(buffer.remaining(), b.length);
+ buffer.get(b, 0, length);
+ update(b, 0, length);
+ }
+ }
+ buffer.position(limit);
+ }
+
+ /**
+ * Resets CRC-32C to initial value.
+ */
+ @Override
+ public void reset() {
+ crc = 0xFFFFFFFF;
+ }
+
+ /**
+ * Returns CRC-32C value.
+ */
+ @Override
+ public long getValue() {
+ return (~crc) & 0xFFFFFFFFL;
+ }
+
+ /**
+ * Updates the CRC-32C checksum with the specified array of bytes.
+ */
+ private static int updateBytes(int crc, byte[] b, int off, int end) {
+
+ // Do only byte reads for arrays so short they can't be aligned
+ // or if bytes are stored with a larger witdh than one byte.,%
+ if (end - off >= 8 && Unsafe.ARRAY_BYTE_INDEX_SCALE == 1) {
+
+ // align on 8 bytes
+ int alignLength
+ = (8 - ((Unsafe.ARRAY_BYTE_BASE_OFFSET + off) & 0x7)) & 0x7;
+ for (int alignEnd = off + alignLength; off < alignEnd; off++) {
+ crc = (crc >>> 8) ^ byteTable[(crc ^ b[off]) & 0xFF];
+ }
+
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+ crc = Integer.reverseBytes(crc);
+ }
+
+ // slicing-by-8
+ for (; off < (end - Long.BYTES); off += Long.BYTES) {
+ int firstHalf;
+ int secondHalf;
+ if (Unsafe.ADDRESS_SIZE == 4) {
+ // On 32 bit platforms read two ints instead of a single 64bit long
+ firstHalf = UNSAFE.getInt(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off);
+ secondHalf = UNSAFE.getInt(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off
+ + Integer.BYTES);
+ } else {
+ long value = UNSAFE.getLong(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off);
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ firstHalf = (int) value;
+ secondHalf = (int) (value >>> 32);
+ } else { // ByteOrder.BIG_ENDIAN
+ firstHalf = (int) (value >>> 32);
+ secondHalf = (int) value;
+ }
+ }
+ crc ^= firstHalf;
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ crc = byteTable7[crc & 0xFF]
+ ^ byteTable6[(crc >>> 8) & 0xFF]
+ ^ byteTable5[(crc >>> 16) & 0xFF]
+ ^ byteTable4[crc >>> 24]
+ ^ byteTable3[secondHalf & 0xFF]
+ ^ byteTable2[(secondHalf >>> 8) & 0xFF]
+ ^ byteTable1[(secondHalf >>> 16) & 0xFF]
+ ^ byteTable0[secondHalf >>> 24];
+ } else { // ByteOrder.BIG_ENDIAN
+ crc = byteTable0[secondHalf & 0xFF]
+ ^ byteTable1[(secondHalf >>> 8) & 0xFF]
+ ^ byteTable2[(secondHalf >>> 16) & 0xFF]
+ ^ byteTable3[secondHalf >>> 24]
+ ^ byteTable4[crc & 0xFF]
+ ^ byteTable5[(crc >>> 8) & 0xFF]
+ ^ byteTable6[(crc >>> 16) & 0xFF]
+ ^ byteTable7[crc >>> 24];
+ }
+ }
+
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+ crc = Integer.reverseBytes(crc);
+ }
+ }
+
+ // Tail
+ for (; off < end; off++) {
+ crc = (crc >>> 8) ^ byteTable[(crc ^ b[off]) & 0xFF];
+ }
+
+ return crc;
+ }
+
+ /**
+ * Updates the CRC-32C checksum reading from the specified address.
+ */
+ private static int updateDirectByteBuffer(int crc, long address,
+ int off, int end) {
+
+ // Do only byte reads for arrays so short they can't be aligned
+ if (end - off >= 8) {
+
+ // align on 8 bytes
+ int alignLength = (8 - (int) ((address + off) & 0x7)) & 0x7;
+ for (int alignEnd = off + alignLength; off < alignEnd; off++) {
+ crc = (crc >>> 8)
+ ^ byteTable[(crc ^ UNSAFE.getByte(address + off)) & 0xFF];
+ }
+
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+ crc = Integer.reverseBytes(crc);
+ }
+
+ // slicing-by-8
+ for (; off <= (end - Long.BYTES); off += Long.BYTES) {
+ // Always reading two ints as reading a long followed by
+ // shifting and casting was slower.
+ int firstHalf = UNSAFE.getInt(address + off);
+ int secondHalf = UNSAFE.getInt(address + off + Integer.BYTES);
+ crc ^= firstHalf;
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ crc = byteTable7[crc & 0xFF]
+ ^ byteTable6[(crc >>> 8) & 0xFF]
+ ^ byteTable5[(crc >>> 16) & 0xFF]
+ ^ byteTable4[crc >>> 24]
+ ^ byteTable3[secondHalf & 0xFF]
+ ^ byteTable2[(secondHalf >>> 8) & 0xFF]
+ ^ byteTable1[(secondHalf >>> 16) & 0xFF]
+ ^ byteTable0[secondHalf >>> 24];
+ } else { // ByteOrder.BIG_ENDIAN
+ crc = byteTable0[secondHalf & 0xFF]
+ ^ byteTable1[(secondHalf >>> 8) & 0xFF]
+ ^ byteTable2[(secondHalf >>> 16) & 0xFF]
+ ^ byteTable3[secondHalf >>> 24]
+ ^ byteTable4[crc & 0xFF]
+ ^ byteTable5[(crc >>> 8) & 0xFF]
+ ^ byteTable6[(crc >>> 16) & 0xFF]
+ ^ byteTable7[crc >>> 24];
+ }
+ }
+
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+ crc = Integer.reverseBytes(crc);
+ }
+ }
+
+ // Tail
+ for (; off < end; off++) {
+ crc = (crc >>> 8)
+ ^ byteTable[(crc ^ UNSAFE.getByte(address + off)) & 0xFF];
+ }
+
+ return crc;
+ }
+}
--- a/jdk/src/java.base/share/classes/java/util/zip/Checksum.java Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/Checksum.java Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,17 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+package java.util.zip;
-package java.util.zip;
+import java.nio.ByteBuffer;
/**
* An interface representing a data checksum.
*
- * @author David Connelly
+ * @author David Connelly
*/
-public
-interface Checksum {
+public interface Checksum {
+
/**
* Updates the current checksum with the specified byte.
*
@@ -41,6 +42,24 @@
/**
* Updates the current checksum with the specified array of bytes.
+ *
+ * @implSpec This default implementation is equal to calling
+ * {@code update(b, 0, b.length)}.
+ *
+ * @param b the array of bytes to update the checksum with
+ *
+ * @throws NullPointerException
+ * if {@code b} is {@code null}
+ *
+ * @since 1.9
+ */
+ default public void update(byte[] b) {
+ update(b, 0, b.length);
+ }
+
+ /**
+ * Updates the current checksum with the specified array of bytes.
+ *
* @param b the byte array to update the checksum with
* @param off the start offset of the data
* @param len the number of bytes to use for the update
@@ -48,7 +67,64 @@
public void update(byte[] b, int off, int len);
/**
+ * Updates the current checksum with the bytes from the specified buffer.
+ *
+ * The checksum is updated with the remaining bytes in the buffer, starting
+ * at the buffer's position. Upon return, the buffer's position will be
+ * updated to its limit; its limit will not have been changed.
+ *
+ * @apiNote For best performance with DirectByteBuffer and other ByteBuffer
+ * implementations without a backing array implementers of this interface
+ * should override this method.
+ *
+ * @implSpec The default implementation has the following behavior.<br>
+ * For ByteBuffers backed by an accessible byte array.
+ * <pre>{@code
+ * update(buffer.array(),
+ * buffer.position() + buffer.arrayOffset(),
+ * buffer.remaining());
+ * }</pre>
+ * For ByteBuffers not backed by an accessible byte array.
+ * <pre>{@code
+ * byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+ * while (buffer.hasRemaining()) {
+ * int length = Math.min(buffer.remaining(), b.length);
+ * buffer.get(b, 0, length);
+ * update(b, 0, length);
+ * }
+ * }</pre>
+ *
+ * @param buffer the ByteBuffer to update the checksum with
+ *
+ * @throws NullPointerException
+ * if {@code buffer} is {@code null}
+ *
+ * @since 1.9
+ */
+ default public void update(ByteBuffer buffer) {
+ int pos = buffer.position();
+ int limit = buffer.limit();
+ assert (pos <= limit);
+ int rem = limit - pos;
+ if (rem <= 0) {
+ return;
+ }
+ if (buffer.hasArray()) {
+ update(buffer.array(), pos + buffer.arrayOffset(), rem);
+ } else {
+ byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+ while (buffer.hasRemaining()) {
+ int length = Math.min(buffer.remaining(), b.length);
+ buffer.get(b, 0, length);
+ update(b, 0, length);
+ }
+ }
+ buffer.position(limit);
+ }
+
+ /**
* Returns the current checksum value.
+ *
* @return the current checksum value
*/
public long getValue();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/zip/package-info.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides classes for reading and writing the standard ZIP and GZIP file
+ * formats. Also includes classes for compressing and decompressing data using
+ * the DEFLATE compression algorithm, which is used by the ZIP and GZIP file
+ * formats. Additionally, there are utility classes for computing the CRC-32,
+ * CRC-32C and Adler-32 checksums of arbitrary input streams.
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ * <li><a href="http://www.info-zip.org/doc/appnote-19970311-iz.zip">
+ * Info-ZIP Application Note 970311</a> - a detailed description of
+ * the Info-ZIP format upon which the {@code java.util.zip} classes
+ * are based.
+ * <li><a name="zip64">An implementation may optionally support the
+ * ZIP64(tm) format extensions defined by the</a>
+ * <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
+ * PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format
+ * extensions are used to overcome the size limitations of the
+ * original ZIP format.
+ * <li><a name="lang_encoding">APPENDIX D of</a>
+ * <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
+ * PKWARE ZIP File Format Specification</a> - Language Encoding Flag
+ * (EFS) to encode ZIP entry filename and comment fields using UTF-8.
+ * <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
+ * ZLIB Compressed Data Format Specification version 3.3</a>
+ *
+ * <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
+ * (RFC 1950)
+ * <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
+ * DEFLATE Compressed Data Format Specification version 1.3</a>
+ *
+ * <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
+ * (RFC 1951)
+ * <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
+ * GZIP file format specification version 4.3</a>
+ *
+ * <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
+ * (RFC 1952)
+ * <li>CRC-32 checksum is described in RFC 1952 (above)
+ * <li>CRC-32C checksum is described in
+ * <a href="http://www.ietf.org/rfc/rfc3720.txt">Internet Small
+ * Computer Systems Interface (iSCSI)</a>
+ *
+ * <a href="http://www.ietf.org/rfc/rfc3720.txt.pdf">(pdf)</a>
+ * (RFC 3720)
+ * <li>Adler-32 checksum is described in RFC 1950 (above)
+ * </ul>
+ *
+ * @since 1.1
+ */
+package java.util.zip;
--- a/jdk/src/java.base/share/classes/java/util/zip/package.html Fri Nov 21 16:05:11 2014 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation. Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-
-</head>
-<body bgcolor="white">
-
-Provides classes for reading and writing the standard ZIP and GZIP
-file formats. Also includes classes for compressing and decompressing
-data using the DEFLATE compression algorithm, which is used by the
-ZIP and GZIP file formats. Additionally, there are utility classes
-for computing the CRC-32 and Adler-32 checksums of arbitrary
-input streams.
-
-
-<h2>Package Specification</h2>
-
-<ul>
- <li><a href="http://www.info-zip.org/doc/appnote-19970311-iz.zip">
- Info-ZIP Application Note 970311
- </a> - a detailed description of the Info-ZIP format upon which
- the <code>java.util.zip</code> classes are based.
- <li><a name="zip64">An implementation may optionally support the ZIP64(tm) format extensions
- defined by the </a>
- <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
- PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
- are used to overcome the size limitations of the original ZIP format.
- <li><a name="lang_encoding">APPENDIX D of </a><a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
- PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
- encode ZIP entry filename and comment fields using UTF-8.
- <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
- ZLIB Compressed Data Format Specification version 3.3</a>
-
- <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
- (RFC 1950)
- <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
- DEFLATE Compressed Data Format Specification version 1.3</a>
-
- <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
- (RFC 1951)
- <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
- GZIP file format specification version 4.3</a>
-
- <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
- (RFC 1952)
- <li>CRC-32 checksum is described in RFC 1952 (above)
- <li>Adler-32 checksum is described in RFC 1950 (above)
-</ul>
-
-
-<!--
-<h2>Related Documentation</h2>
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
- <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
-</ul>
--->
-
-@since 1.1
-</body>
-</html>
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ChecksumBase.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Base class for Checksum tests
+ */
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.zip.Checksum;
+
+public class ChecksumBase {
+
+ private final static byte[] BYTES_123456789 = "123456789".getBytes(StandardCharsets.US_ASCII);
+
+ public static void testAll(Checksum checksum, long expected) {
+ testBytes(checksum, expected);
+ testByteArray(checksum, expected);
+ testWrappedByteBuffer(checksum, expected);
+ testReadonlyByteBuffer(checksum, expected);
+ testDirectByteBuffer(checksum, expected);
+ testByteArrayOffset(checksum, expected);
+ testDirectByteBufferOffset(checksum, expected);
+ testLittleEndianDirectByteBufferOffset(checksum, expected);
+ testWrappedByteBufferOffset(checksum, expected);
+ testLittleEndianWrappedByteBufferOffset(checksum, expected);
+ testReadonlyByteBufferOffset(checksum, expected);
+ testLittleEndianReadonlyByteBufferOffset(checksum, expected);
+ }
+
+ private static void testBytes(Checksum checksum, long expected) {
+ checksum.reset();
+ for (byte bits : BYTES_123456789) {
+ checksum.update(bits);
+ }
+ checkChecksum(checksum, expected);
+ }
+
+ private static void testByteArray(Checksum checksum, long expected) {
+ checksum.reset();
+ checksum.update(BYTES_123456789);
+ checkChecksum(checksum, expected);
+ }
+
+ private static void testWrappedByteBuffer(Checksum checksum, long expected) {
+ checksum.reset();
+ ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789);
+ checksum.update(bb);
+ checkChecksum(checksum, expected);
+ }
+
+ private static void testReadonlyByteBuffer(Checksum checksum, long expected) {
+ checksum.reset();
+ ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789).asReadOnlyBuffer();
+ checksum.update(bb);
+ checkChecksum(checksum, expected);
+ }
+
+ private static void testDirectByteBuffer(Checksum checksum, long expected) {
+ checksum.reset();
+ ByteBuffer bb = ByteBuffer.allocateDirect(BYTES_123456789.length);
+ bb.put(BYTES_123456789);
+ bb.rewind();
+ checksum.update(bb);
+ checkChecksum(checksum, expected);
+ }
+
+ private static void checkChecksum(Checksum checksum, long expected) {
+ if (checksum.getValue() != expected) {
+ throw new RuntimeException("Calculated checksum result was invalid."
+ + " Expected " + Long.toHexString(expected)
+ + ", but got " + Long.toHexString(checksum.getValue()) + ".");
+ }
+ }
+
+ private static void testByteArrayOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ checksum.update(unaligned_bytes_123456789, i, BYTES_123456789.length);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testDirectByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ bb.put(unaligned_bytes_123456789);
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testLittleEndianDirectByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ bb.put(unaligned_bytes_123456789);
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testWrappedByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testLittleEndianWrappedByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testReadonlyByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void testLittleEndianReadonlyByteBufferOffset(Checksum checksum, long expected) {
+ byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+ for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+ checksum.reset();
+ System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+ ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.position(i);
+ bb.limit(i + BYTES_123456789.length);
+ checksum.update(bb);
+ checkChecksumOffset(checksum, expected, i);
+ }
+ }
+
+ private static void checkChecksumOffset(Checksum checksum, long expected, int offset) {
+ if (checksum.getValue() != expected) {
+ throw new RuntimeException("Calculated CRC32C result was invalid. Array offset "
+ + offset + ". Expected: " + Long.toHexString(expected) + ", Got: "
+ + Long.toHexString(checksum.getValue()));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestCRC32.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,40 @@
+
+import java.util.zip.CRC32;
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Check that CRC-32 returns the expected CRC value for the
+ * string 123456789
+ * http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32
+ * @build ChecksumBase
+ * @run main TestCRC32
+ */
+
+public class TestCRC32 {
+
+ public static void main(String[] args) {
+ ChecksumBase.testAll(new CRC32(), 0xCBF43926L);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestCRC32C.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,40 @@
+
+import java.util.zip.CRC32C;
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Check that CRC-32C returns the expected CRC value for the
+ * string 123456789
+ * http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32c
+ * @build ChecksumBase
+ * @run main TestCRC32C
+ */
+
+public class TestCRC32C {
+
+ public static void main(String[] args) {
+ ChecksumBase.testAll(new CRC32C(), 0xE3069283L);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestChecksum.java Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Test that default methods in Checksum works as expected
+ * @build ChecksumBase
+ * @run main TestChecksum
+ */
+import java.util.zip.CRC32C;
+import java.util.zip.Checksum;
+
+public class TestChecksum {
+
+ public static void main(String[] args) {
+ ChecksumBase.testAll(new MyCRC32C(), 0xE3069283L);
+ }
+
+ /**
+ * Only implementing required methods
+ */
+ private static class MyCRC32C implements Checksum {
+
+ private final CRC32C crc32c = new CRC32C();
+
+ @Override
+ public void update(int b) {
+ crc32c.update(b);
+ }
+
+ @Override
+ public void update(byte[] b, int off, int len) {
+ crc32c.update(b, off, len);
+ }
+
+ @Override
+ public long getValue() {
+ return crc32c.getValue();
+ }
+
+ @Override
+ public void reset() {
+ crc32c.reset();
+ }
+
+ }
+}