/* 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 listEntries(InputStream input) throws IOException { List result = new ArrayList(); 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. * *

{@code CRC64(data) = -1 ^ updateCrc64((... updateCrc64(-1, firstBlock), ...), lastBlock);} *

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(); } }