• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 Google Inc. All Rights Reserved.
2 
3    Distributed under MIT license.
4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */
6 
7 package org.brotli.integration;
8 
9 import java.io.ByteArrayOutputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.zip.ZipEntry;
16 import java.util.zip.ZipInputStream;
17 
18 /**
19  * Utilities to work test files bundles in zip archive.
20  */
21 public class BundleHelper {
BundleHelper()22   private BundleHelper() { }
23 
listEntries(InputStream input)24   public static List<String> listEntries(InputStream input) throws IOException {
25     List<String> result = new ArrayList<String>();
26     ZipInputStream zis = new ZipInputStream(input);
27     ZipEntry entry;
28     try {
29       while ((entry = zis.getNextEntry()) != null) {
30         if (!entry.isDirectory()) {
31           result.add(entry.getName());
32         }
33         zis.closeEntry();
34       }
35     } finally {
36       zis.close();
37     }
38     return result;
39   }
40 
readStream(InputStream input)41   public static byte[] readStream(InputStream input) throws IOException {
42     ByteArrayOutputStream result = new ByteArrayOutputStream();
43     byte[] buffer = new byte[65536];
44     int bytesRead;
45     while ((bytesRead = input.read(buffer)) != -1) {
46       result.write(buffer, 0, bytesRead);
47     }
48     return result.toByteArray();
49   }
50 
readEntry(InputStream input, String entryName)51   public static byte[] readEntry(InputStream input, String entryName) throws IOException {
52     ZipInputStream zis = new ZipInputStream(input);
53     ZipEntry entry;
54     try {
55       while ((entry = zis.getNextEntry()) != null) {
56         if (entry.getName().equals(entryName)) {
57           byte[] result = readStream(zis);
58           zis.closeEntry();
59           return result;
60         }
61         zis.closeEntry();
62       }
63     } finally {
64       zis.close();
65     }
66     /* entry not found */
67     return null;
68   }
69 
70   /** ECMA CRC64 polynomial. */
71   private static final long CRC_64_POLY =
72       new BigInteger("C96C5795D7870F42", 16).longValue();
73 
74   /**
75    * Rolls CRC64 calculation.
76    *
77    * <p> {@code CRC64(data) = -1 ^ updateCrc64((... updateCrc64(-1, firstBlock), ...), lastBlock);}
78    * <p> This simple and reliable checksum is chosen to make is easy to calculate the same value
79    * across the variety of languages (C++, Java, Go, ...).
80    */
updateCrc64(long crc, byte[] data, int offset, int length)81   public static long updateCrc64(long crc, byte[] data, int offset, int length) {
82     for (int i = offset; i < offset + length; ++i) {
83       long c = (crc ^ (long) (data[i] & 0xFF)) & 0xFF;
84       for (int k = 0; k < 8; k++) {
85         c = ((c & 1) == 1) ? CRC_64_POLY ^ (c >>> 1) : c >>> 1;
86       }
87       crc = c ^ (crc >>> 8);
88     }
89     return crc;
90   }
91 
92   /**
93    * Calculates CRC64 of stream contents.
94    */
fingerprintStream(InputStream input)95   public static long fingerprintStream(InputStream input) throws IOException {
96     byte[] buffer = new byte[65536];
97     long crc = -1;
98     while (true) {
99       int len = input.read(buffer);
100       if (len <= 0) {
101         break;
102       }
103       crc = updateCrc64(crc, buffer, 0, len);
104     }
105     return ~crc;
106   }
107 
getExpectedFingerprint(String entryName)108   public static long getExpectedFingerprint(String entryName) {
109     int dotIndex = entryName.indexOf('.');
110     String entryCrcString = (dotIndex == -1) ? entryName : entryName.substring(0, dotIndex);
111     return new BigInteger(entryCrcString, 16).longValue();
112   }
113 }
114