/* Copyright 2016 Google Inc. All Rights Reserved.
|
|
Distributed under MIT license.
|
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
*/
|
|
package org.brotli.integration;
|
|
import java.io.ByteArrayOutputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.math.BigInteger;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipInputStream;
|
|
/**
|
* Utilities to work test files bundles in zip archive.
|
*/
|
public class BundleHelper {
|
private BundleHelper() { }
|
|
public static List<String> listEntries(InputStream input) throws IOException {
|
List<String> result = new ArrayList<String>();
|
ZipInputStream zis = new ZipInputStream(input);
|
ZipEntry entry;
|
try {
|
while ((entry = zis.getNextEntry()) != null) {
|
if (!entry.isDirectory()) {
|
result.add(entry.getName());
|
}
|
zis.closeEntry();
|
}
|
} finally {
|
zis.close();
|
}
|
return result;
|
}
|
|
public static byte[] readStream(InputStream input) throws IOException {
|
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
byte[] buffer = new byte[65536];
|
int bytesRead;
|
while ((bytesRead = input.read(buffer)) != -1) {
|
result.write(buffer, 0, bytesRead);
|
}
|
return result.toByteArray();
|
}
|
|
public static byte[] readEntry(InputStream input, String entryName) throws IOException {
|
ZipInputStream zis = new ZipInputStream(input);
|
ZipEntry entry;
|
try {
|
while ((entry = zis.getNextEntry()) != null) {
|
if (entry.getName().equals(entryName)) {
|
byte[] result = readStream(zis);
|
zis.closeEntry();
|
return result;
|
}
|
zis.closeEntry();
|
}
|
} finally {
|
zis.close();
|
}
|
/* entry not found */
|
return null;
|
}
|
|
/** ECMA CRC64 polynomial. */
|
private static final long CRC_64_POLY =
|
new BigInteger("C96C5795D7870F42", 16).longValue();
|
|
/**
|
* Rolls CRC64 calculation.
|
*
|
* <p> {@code CRC64(data) = -1 ^ updateCrc64((... updateCrc64(-1, firstBlock), ...), lastBlock);}
|
* <p> This simple and reliable checksum is chosen to make is easy to calculate the same value
|
* across the variety of languages (C++, Java, Go, ...).
|
*/
|
public static long updateCrc64(long crc, byte[] data, int offset, int length) {
|
for (int i = offset; i < offset + length; ++i) {
|
long c = (crc ^ (long) (data[i] & 0xFF)) & 0xFF;
|
for (int k = 0; k < 8; k++) {
|
c = ((c & 1) == 1) ? CRC_64_POLY ^ (c >>> 1) : c >>> 1;
|
}
|
crc = c ^ (crc >>> 8);
|
}
|
return crc;
|
}
|
|
/**
|
* Calculates CRC64 of stream contents.
|
*/
|
public static long fingerprintStream(InputStream input) throws IOException {
|
byte[] buffer = new byte[65536];
|
long crc = -1;
|
while (true) {
|
int len = input.read(buffer);
|
if (len <= 0) {
|
break;
|
}
|
crc = updateCrc64(crc, buffer, 0, len);
|
}
|
return ~crc;
|
}
|
|
public static long getExpectedFingerprint(String entryName) {
|
int dotIndex = entryName.indexOf('.');
|
String entryCrcString = (dotIndex == -1) ? entryName : entryName.substring(0, dotIndex);
|
return new BigInteger(entryCrcString, 16).longValue();
|
}
|
}
|