Update API to v1.0.0 (#537)

Make Java decoder fully transpilable to C#.
This commit is contained in:
Eugene Kliuchnikov
2017-04-10 15:39:00 +02:00
committed by GitHub
parent 46c1a881b4
commit 66e798d46a
10 changed files with 52 additions and 99 deletions

View File

@@ -79,7 +79,8 @@ final class BitReader {
try {
while (bytesRead < BYTE_READ_SIZE) {
int len = br.input.read(br.byteBuffer, bytesRead, BYTE_READ_SIZE - bytesRead);
if (len == -1) {
// EOF is -1 in Java, but 0 in C#.
if (len <= 0) {
br.endOfStreamReached = true;
br.tailBytes = bytesRead;
bytesRead += 3;

View File

@@ -166,5 +166,7 @@ public class BrotliInputStream extends InputStream {
} catch (BrotliRuntimeException ex) {
throw new IOException("Brotli stream decoding failed", ex);
}
// <{[INJECTED CODE]}>
}
}

View File

@@ -126,7 +126,8 @@ final class Decode {
return sym;
}
offset += sym;
offset += (val & ((1L << bits) - 1)) >>> HUFFMAN_TABLE_BITS;
int mask = (1 << bits) - 1;
offset += (val & mask) >>> HUFFMAN_TABLE_BITS;
br.bitOffset += ((table[offset] >> 16) + HUFFMAN_TABLE_BITS);
return table[offset] & 0xFFFF;
}

View File

@@ -11,7 +11,6 @@ import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -26,18 +25,20 @@ public class DecodeTest {
byte[] buffer = new byte[65536];
ByteArrayInputStream input = new ByteArrayInputStream(data);
ByteArrayOutputStream output = new ByteArrayOutputStream();
InputStream brotliInput = new BrotliInputStream(input);
BrotliInputStream brotliInput = new BrotliInputStream(input);
if (byByte) {
byte[] oneByte = new byte[1];
while (true) {
int next = brotliInput.read();
if (next == -1) {
break;
}
output.write(next);
oneByte[0] = (byte) next;
output.write(oneByte, 0, 1);
}
} else {
while (true) {
int len = brotliInput.read(buffer);
int len = brotliInput.read(buffer, 0, buffer.length);
if (len <= 0) {
break;
}
@@ -52,10 +53,10 @@ public class DecodeTest {
byte[] buffer = new byte[65536];
ByteArrayInputStream input = new ByteArrayInputStream(data);
ByteArrayOutputStream output = new ByteArrayOutputStream();
InputStream brotliInput = new BrotliInputStream(
BrotliInputStream brotliInput = new BrotliInputStream(
input, BrotliInputStream.DEFAULT_INTERNAL_BUFFER_SIZE, dictionary);
while (true) {
int len = brotliInput.read(buffer);
int len = brotliInput.read(buffer, 0, buffer.length);
if (len <= 0) {
break;
}

View File

@@ -8,8 +8,6 @@ package org.brotli.dec;
import static org.junit.Assert.assertEquals;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -20,12 +18,20 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class DictionaryTest {
private static long crc64(byte[] data) {
long crc = -1;
for (int i = 0; i < data.length; ++i) {
long c = (crc ^ (long) (data[i] & 0xFF)) & 0xFF;
for (int k = 0; k < 8; k++) {
c = (c >>> 1) ^ (-(c & 1L) & -3932672073523589310L);
}
crc = c ^ (crc >>> 8);
}
return ~crc;
}
@Test
public void testGetData() throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(Dictionary.getData());
byte[] digest = md.digest();
String sha256 = String.format("%064x", new java.math.BigInteger(1, digest));
assertEquals("20e42eb1b511c21806d4d227d07e5dd06877d8ce7b3a817f378f313653f35c70", sha256);
public void testGetData() {
assertEquals(37084801881332636L, crc64(Dictionary.getData()));
}
}

View File

@@ -12,8 +12,6 @@ import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -28,9 +26,9 @@ public class SynthTest {
byte[] buffer = new byte[65536];
ByteArrayInputStream input = new ByteArrayInputStream(data);
ByteArrayOutputStream output = new ByteArrayOutputStream();
InputStream brotliInput = new BrotliInputStream(input);
BrotliInputStream brotliInput = new BrotliInputStream(input);
while (true) {
int len = brotliInput.read(buffer);
int len = brotliInput.read(buffer, 0, buffer.length);
if (len <= 0) {
break;
}
@@ -2024,33 +2022,6 @@ public class SynthTest {
false, "");
}
@Ignore("Java implementation forbids extra bytes after the stream end.")
@Test
public void testSimplePrefixPlusExtraData() {
byte[] compressed = {
(byte) 0x1b, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0xa0, (byte) 0xc3, (byte) 0xc4,
(byte) 0xc6, (byte) 0xc8, (byte) 0x02, (byte) 0x00, (byte) 0x70, (byte) 0xb0, (byte) 0x65,
(byte) 0x12, (byte) 0x03, (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xee, (byte) 0xb4,
(byte) 0x51, (byte) 0xa0, (byte) 0x1d, (byte) 0x55, (byte) 0xaa
};
checkSynth(
/*
main_header
metablock_header_begin: 1, 0, 4, 0
metablock_header_trivial_context
huffman_simple: 1,4,256, 97,98,99,100 // ascii codes for a, b, c, d
huffman_fixed: 704
huffman_fixed: 64
command_inscopy_easy: 4, 0
command_literal_bits: 0, 10, 110, 111 // a, b, c, d
byte_boundary
bits: "01010101", "10101010"
*/
compressed,
true, ""
+ "abcd");
}
@Test
public void testTooManySymbolsRepeated() {
byte[] compressed = {

View File

@@ -9,9 +9,6 @@ package org.brotli.dec;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -22,29 +19,44 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class TransformTest {
private static long crc64(byte[] data) {
long crc = -1;
for (int i = 0; i < data.length; ++i) {
long c = (crc ^ (long) (data[i] & 0xFF)) & 0xFF;
for (int k = 0; k < 8; k++) {
c = (c >>> 1) ^ (-(c & 1L) & -3932672073523589310L);
}
crc = c ^ (crc >>> 8);
}
return ~crc;
}
@Test
public void testTrimAll() {
byte[] output = new byte[2];
byte[] input = "word".getBytes(StandardCharsets.UTF_8);
byte[] input = {119, 111, 114, 100}; // "word"
Transform transform = new Transform("[", WordTransformType.OMIT_FIRST_5, "]");
Transform.transformDictionaryWord(output, 0, input, 0, input.length, transform);
assertArrayEquals(output, "[]".getBytes(StandardCharsets.UTF_8));
byte[] expectedOutput = {91, 93}; // "[]"
assertArrayEquals(expectedOutput, output);
}
@Test
public void testCapitalize() {
byte[] output = new byte[8];
byte[] input = "qæप".getBytes(StandardCharsets.UTF_8);
byte[] input = {113, -61, -90, -32, -92, -86}; // "qæप"
Transform transform = new Transform("[", WordTransformType.UPPERCASE_ALL, "]");
Transform.transformDictionaryWord(output, 0, input, 0, input.length, transform);
assertArrayEquals(output, "[QÆय]".getBytes(StandardCharsets.UTF_8));
byte[] expectedOutput = {91, 81, -61, -122, -32, -92, -81, 93}; // "[QÆय]"
assertArrayEquals(expectedOutput, output);
}
@Test
public void testAllTransforms() throws NoSuchAlgorithmException {
public void testAllTransforms() {
/* This string allows to apply all transforms: head and tail cutting, capitalization and
turning to upper case; all results will be mutually different. */
byte[] testWord = Transform.readUniBytes("o123456789abcdef");
// "o123456789abcdef"
byte[] testWord = {111, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
byte[] output = new byte[2259];
int offset = 0;
for (int i = 0; i < Transform.TRANSFORMS.length; ++i) {
@@ -53,11 +65,6 @@ public class TransformTest {
output[offset++] = -1;
}
assertEquals(output.length, offset);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(output);
byte[] digest = md.digest();
String sha256 = String.format("%064x", new java.math.BigInteger(1, digest));
assertEquals("60f1c7e45d788e24938c5a3919aaf41a7d8ad474d0ced6b9e4c0079f4d1da8c4", sha256);
assertEquals(8929191060211225186L, crc64(output));
}
}