From fc608b1c63a487c596074f204dc01881715761e8 Mon Sep 17 00:00:00 2001 From: Armand <4831c0@proton.me> Date: Sat, 30 Aug 2025 20:30:36 +0200 Subject: [PATCH] android: move brotli to a git submodule --- .gitmodules | 4 +- firka/android/app/src/main/java/org/brotli | 1 + .../brotli/common/SharedDictionaryType.java | 15 - .../main/java/org/brotli/dec/BitReader.java | 289 ---- .../org/brotli/dec/BrotliInputStream.java | 172 --- .../brotli/dec/BrotliRuntimeException.java | 21 - .../src/main/java/org/brotli/dec/Context.java | 58 - .../src/main/java/org/brotli/dec/Decode.java | 1357 ----------------- .../src/main/java/org/brotli/dec/Decoder.java | 72 - .../main/java/org/brotli/dec/Dictionary.java | 94 -- .../java/org/brotli/dec/DictionaryData.java | 75 - .../src/main/java/org/brotli/dec/Huffman.java | 137 -- .../src/main/java/org/brotli/dec/State.java | 100 -- .../main/java/org/brotli/dec/Transform.java | 236 --- .../src/main/java/org/brotli/dec/Utils.java | 119 -- .../org/brotli/enc/PreparedDictionary.java | 16 - .../enc/PreparedDictionaryGenerator.java | 185 --- .../android/app/src/main/java/org/brotli | 1 + .../brotli/common/SharedDictionaryType.java | 15 - .../main/java/org/brotli/dec/BitReader.java | 289 ---- .../org/brotli/dec/BrotliInputStream.java | 172 --- .../brotli/dec/BrotliRuntimeException.java | 21 - .../src/main/java/org/brotli/dec/Context.java | 58 - .../src/main/java/org/brotli/dec/Decode.java | 1357 ----------------- .../src/main/java/org/brotli/dec/Decoder.java | 72 - .../main/java/org/brotli/dec/Dictionary.java | 94 -- .../java/org/brotli/dec/DictionaryData.java | 75 - .../src/main/java/org/brotli/dec/Huffman.java | 137 -- .../src/main/java/org/brotli/dec/State.java | 100 -- .../main/java/org/brotli/dec/Transform.java | 236 --- .../src/main/java/org/brotli/dec/Utils.java | 119 -- .../org/brotli/enc/PreparedDictionary.java | 16 - .../enc/PreparedDictionaryGenerator.java | 185 --- 33 files changed, 5 insertions(+), 5893 deletions(-) create mode 160000 firka/android/app/src/main/java/org/brotli delete mode 100644 firka/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/BitReader.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Context.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Decode.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Decoder.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Dictionary.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/DictionaryData.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Huffman.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/State.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Transform.java delete mode 100644 firka/android/app/src/main/java/org/brotli/dec/Utils.java delete mode 100644 firka/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java delete mode 100644 firka/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java create mode 120000 firka_wear/android/app/src/main/java/org/brotli delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/BitReader.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Context.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Decode.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Decoder.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Dictionary.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/DictionaryData.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Huffman.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/State.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Transform.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/dec/Utils.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java delete mode 100644 firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java diff --git a/.gitmodules b/.gitmodules index 496bbedb..e10d69d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,4 +13,6 @@ [submodule "firka_wear/vendor/wear_plus"] path = firka_wear/vendor/wear_plus url = https://git.firka.app/firka/wear_plus - +[submodule "firka/android/app/src/main/java/org/brotli"] + path = firka/android/app/src/main/java/org/brotli + url = https://git.firka.app/firka/org_brotli diff --git a/firka/android/app/src/main/java/org/brotli b/firka/android/app/src/main/java/org/brotli new file mode 160000 index 00000000..da8f3294 --- /dev/null +++ b/firka/android/app/src/main/java/org/brotli @@ -0,0 +1 @@ +Subproject commit da8f329432ff3e7deaedb4a60026138db2920a3a diff --git a/firka/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java b/firka/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java deleted file mode 100644 index b592d2b4..00000000 --- a/firka/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright 2018 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.common; - -/** POJO enum that mirrors C BrotliSharedDictionaryType. */ -public class SharedDictionaryType { - // Disallow instantiation. - private SharedDictionaryType() {} - - public static final int RAW = 0; - public static final int SERIALIZED = 1; -} diff --git a/firka/android/app/src/main/java/org/brotli/dec/BitReader.java b/firka/android/app/src/main/java/org/brotli/dec/BitReader.java deleted file mode 100644 index bae9452d..00000000 --- a/firka/android/app/src/main/java/org/brotli/dec/BitReader.java +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright 2015 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.dec; - -/** - * Bit reading helpers. - */ -final class BitReader { - - // Possible values: {5, 6}. 5 corresponds to 32-bit build, 6 to 64-bit. This value is used for - // JIT conditional compilation. - private static final int LOG_BITNESS = Utils.getLogBintness(); - - // Not only Java compiler prunes "if (const false)" code, but JVM as well. - // Code under "if (DEBUG != 0)" have zero performance impact (outside unit tests). - private static final int DEBUG = Utils.isDebugMode(); - - static final int BITNESS = 1 << LOG_BITNESS; - - private static final int BYTENESS = BITNESS / 8; - private static final int CAPACITY = 4096; - // After encountering the end of the input stream, this amount of zero bytes will be appended. - private static final int SLACK = 64; - private static final int BUFFER_SIZE = CAPACITY + SLACK; - // Don't bother to replenish the buffer while this number of bytes is available. - private static final int SAFEGUARD = 36; - private static final int WATERLINE = CAPACITY - SAFEGUARD; - - // "Half" refers to "half of native integer type", i.e. on 64-bit machines it is 32-bit type, - // on 32-bit machines it is 16-bit. - private static final int HALF_BITNESS = BITNESS / 2; - private static final int HALF_SIZE = BYTENESS / 2; - private static final int HALVES_CAPACITY = CAPACITY / HALF_SIZE; - private static final int HALF_BUFFER_SIZE = BUFFER_SIZE / HALF_SIZE; - private static final int HALF_WATERLINE = WATERLINE / HALF_SIZE; - - private static final int LOG_HALF_SIZE = LOG_BITNESS - 4; - - /** - * Fills up the input buffer. - * - *
No-op if there are at least 36 bytes present after current position. - * - *
After encountering the end of the input stream, 64 additional zero bytes are copied to the - * buffer. - */ - static void readMoreInput(State s) { - if (s.halfOffset > HALF_WATERLINE) { - doReadMoreInput(s); - } - } - - static void doReadMoreInput(State s) { - if (s.endOfStreamReached != 0) { - if (halfAvailable(s) >= -2) { - return; - } - throw new BrotliRuntimeException("No more input"); - } - final int readOffset = s.halfOffset << LOG_HALF_SIZE; - int bytesInBuffer = CAPACITY - readOffset; - // Move unused bytes to the head of the buffer. - Utils.copyBytesWithin(s.byteBuffer, 0, readOffset, CAPACITY); - s.halfOffset = 0; - while (bytesInBuffer < CAPACITY) { - final int spaceLeft = CAPACITY - bytesInBuffer; - final int len = Utils.readInput(s.input, s.byteBuffer, bytesInBuffer, spaceLeft); - // EOF is -1 in Java, but 0 in C#. - if (len <= 0) { - s.endOfStreamReached = 1; - s.tailBytes = bytesInBuffer; - bytesInBuffer += HALF_SIZE - 1; - break; - } - bytesInBuffer += len; - } - bytesToNibbles(s, bytesInBuffer); - } - - static void checkHealth(State s, int endOfStream) { - if (s.endOfStreamReached == 0) { - return; - } - final int byteOffset = (s.halfOffset << LOG_HALF_SIZE) + ((s.bitOffset + 7) >> 3) - BYTENESS; - if (byteOffset > s.tailBytes) { - throw new BrotliRuntimeException("Read after end"); - } - if ((endOfStream != 0) && (byteOffset != s.tailBytes)) { - throw new BrotliRuntimeException("Unused bytes after end"); - } - } - - static void assertAccumulatorHealthy(State s) { - if (s.bitOffset > BITNESS) { - throw new IllegalStateException("Accumulator underloaded: " + s.bitOffset); - } - } - - static void fillBitWindow(State s) { - if (DEBUG != 0) { - assertAccumulatorHealthy(s); - } - if (s.bitOffset >= HALF_BITNESS) { - // Same as doFillBitWindow. JVM fails to inline it. - if (BITNESS == 64) { - s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS) - | (s.accumulator64 >>> HALF_BITNESS); - } else { - s.accumulator32 = ((int) s.shortBuffer[s.halfOffset++] << HALF_BITNESS) - | (s.accumulator32 >>> HALF_BITNESS); - } - s.bitOffset -= HALF_BITNESS; - } - } - - static void doFillBitWindow(State s) { - if (DEBUG != 0) { - assertAccumulatorHealthy(s); - } - if (BITNESS == 64) { - s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS) - | (s.accumulator64 >>> HALF_BITNESS); - } else { - s.accumulator32 = ((int) s.shortBuffer[s.halfOffset++] << HALF_BITNESS) - | (s.accumulator32 >>> HALF_BITNESS); - } - s.bitOffset -= HALF_BITNESS; - } - - static int peekBits(State s) { - if (BITNESS == 64) { - return (int) (s.accumulator64 >>> s.bitOffset); - } else { - return s.accumulator32 >>> s.bitOffset; - } - } - - /** - * Fetches bits from accumulator. - * - * WARNING: accumulator MUST contain at least the specified amount of bits, - * otherwise BitReader will become broken. - */ - static int readFewBits(State s, int n) { - final int val = peekBits(s) & ((1 << n) - 1); - s.bitOffset += n; - return val; - } - - static int readBits(State s, int n) { - if (HALF_BITNESS >= 24) { - return readFewBits(s, n); - } else { - return (n <= 16) ? readFewBits(s, n) : readManyBits(s, n); - } - } - - private static int readManyBits(State s, int n) { - final int low = readFewBits(s, 16); - doFillBitWindow(s); - return low | (readFewBits(s, n - 16) << 16); - } - - static void initBitReader(State s) { - s.byteBuffer = new byte[BUFFER_SIZE]; - if (BITNESS == 64) { - s.accumulator64 = 0; - s.intBuffer = new int[HALF_BUFFER_SIZE]; - } else { - s.accumulator32 = 0; - s.shortBuffer = new short[HALF_BUFFER_SIZE]; - } - s.bitOffset = BITNESS; - s.halfOffset = HALVES_CAPACITY; - s.endOfStreamReached = 0; - prepare(s); - } - - private static void prepare(State s) { - readMoreInput(s); - checkHealth(s, 0); - doFillBitWindow(s); - doFillBitWindow(s); - } - - static void reload(State s) { - if (s.bitOffset == BITNESS) { - prepare(s); - } - } - - static void jumpToByteBoundary(State s) { - final int padding = (BITNESS - s.bitOffset) & 7; - if (padding != 0) { - final int paddingBits = readFewBits(s, padding); - if (paddingBits != 0) { - throw new BrotliRuntimeException("Corrupted padding bits"); - } - } - } - - static int halfAvailable(State s) { - int limit = HALVES_CAPACITY; - if (s.endOfStreamReached != 0) { - limit = (s.tailBytes + (HALF_SIZE - 1)) >> LOG_HALF_SIZE; - } - return limit - s.halfOffset; - } - - static void copyRawBytes(State s, byte[] data, int offset, int length) { - if ((s.bitOffset & 7) != 0) { - throw new BrotliRuntimeException("Unaligned copyBytes"); - } - - // Drain accumulator. - while ((s.bitOffset != BITNESS) && (length != 0)) { - data[offset++] = (byte) peekBits(s); - s.bitOffset += 8; - length--; - } - if (length == 0) { - return; - } - - // Get data from shadow buffer with "sizeof(int)" granularity. - final int copyNibbles = Math.min(halfAvailable(s), length >> LOG_HALF_SIZE); - if (copyNibbles > 0) { - final int readOffset = s.halfOffset << LOG_HALF_SIZE; - final int delta = copyNibbles << LOG_HALF_SIZE; - System.arraycopy(s.byteBuffer, readOffset, data, offset, delta); - offset += delta; - length -= delta; - s.halfOffset += copyNibbles; - } - if (length == 0) { - return; - } - - // Read tail bytes. - if (halfAvailable(s) > 0) { - // length = 1..3 - fillBitWindow(s); - while (length != 0) { - data[offset++] = (byte) peekBits(s); - s.bitOffset += 8; - length--; - } - checkHealth(s, 0); - return; - } - - // Now it is possible to copy bytes directly. - while (length > 0) { - final int len = Utils.readInput(s.input, data, offset, length); - if (len == -1) { - throw new BrotliRuntimeException("Unexpected end of input"); - } - offset += len; - length -= len; - } - } - - /** - * Translates bytes to halves (int/short). - */ - static void bytesToNibbles(State s, int byteLen) { - final byte[] byteBuffer = s.byteBuffer; - final int halfLen = byteLen >> LOG_HALF_SIZE; - if (BITNESS == 64) { - final int[] intBuffer = s.intBuffer; - for (int i = 0; i < halfLen; ++i) { - intBuffer[i] = ((byteBuffer[i * 4] & 0xFF)) - | ((byteBuffer[(i * 4) + 1] & 0xFF) << 8) - | ((byteBuffer[(i * 4) + 2] & 0xFF) << 16) - | ((byteBuffer[(i * 4) + 3] & 0xFF) << 24); - } - } else { - final short[] shortBuffer = s.shortBuffer; - for (int i = 0; i < halfLen; ++i) { - shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF) - | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8)); - } - } - } -} diff --git a/firka/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java b/firka/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java deleted file mode 100644 index 7bbe2f63..00000000 --- a/firka/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright 2015 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.dec; - -import java.io.IOException; -import java.io.InputStream; - -/** - * {@link InputStream} decorator that decompresses brotli data. - * - *
Not thread-safe. - */ -public class BrotliInputStream extends InputStream { - - public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 256; - - /** - * Value expected by InputStream contract when stream is over. - * - * In Java it is -1. - * In C# it is 0 (should be patched during transpilation). - */ - private static final int END_OF_STREAM_MARKER = -1; - - /** - * Internal buffer used for efficient byte-by-byte reading. - */ - private byte[] buffer; - - /** - * Number of decoded but still unused bytes in internal buffer. - */ - private int remainingBufferBytes; - - /** - * Next unused byte offset. - */ - private int bufferOffset; - - /** - * Decoder state. - */ - private final State state = new State(); - - /** - * Creates a {@link InputStream} wrapper that decompresses brotli data. - * - *
For byte-by-byte reading ({@link #read()}) internal buffer with - * {@link #DEFAULT_INTERNAL_BUFFER_SIZE} size is allocated and used. - * - *
Will block the thread until first {@link BitReader#CAPACITY} bytes of data of source - * are available. - * - * @param source underlying data source - * @throws IOException in case of corrupted data or source stream problems - */ - public BrotliInputStream(InputStream source) throws IOException { - this(source, DEFAULT_INTERNAL_BUFFER_SIZE); - } - - /** - * Creates a {@link InputStream} wrapper that decompresses brotli data. - * - *
For byte-by-byte reading ({@link #read()}) internal buffer of specified size is - * allocated and used. - * - *
Will block the thread until first {@link BitReader#CAPACITY} bytes of data of source
- * are available.
- *
- * @param source compressed data source
- * @param byteReadBufferSize size of internal buffer used in case of
- * byte-by-byte reading
- * @throws IOException in case of corrupted data or source stream problems
- */
- public BrotliInputStream(InputStream source, int byteReadBufferSize) throws IOException {
- if (byteReadBufferSize <= 0) {
- throw new IllegalArgumentException("Bad buffer size:" + byteReadBufferSize);
- } else if (source == null) {
- throw new IllegalArgumentException("source is null");
- }
- this.buffer = new byte[byteReadBufferSize];
- this.remainingBufferBytes = 0;
- this.bufferOffset = 0;
- try {
- Decode.initState(state, source);
- } catch (BrotliRuntimeException ex) {
- throw new IOException("Brotli decoder initialization failed", ex);
- }
- }
-
- public void attachDictionaryChunk(byte[] data) {
- Decode.attachDictionaryChunk(state, data);
- }
-
- public void enableEagerOutput() {
- Decode.enableEagerOutput(state);
- }
-
- public void enableLargeWindow() {
- Decode.enableLargeWindow(state);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void close() throws IOException {
- Decode.close(state);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int read() throws IOException {
- if (bufferOffset >= remainingBufferBytes) {
- remainingBufferBytes = read(buffer, 0, buffer.length);
- bufferOffset = 0;
- if (remainingBufferBytes == END_OF_STREAM_MARKER) {
- // Both Java and C# return the same value for EOF on single-byte read.
- return -1;
- }
- }
- return buffer[bufferOffset++] & 0xFF;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int read(byte[] destBuffer, int destOffset, int destLen) throws IOException {
- if (destOffset < 0) {
- throw new IllegalArgumentException("Bad offset: " + destOffset);
- } else if (destLen < 0) {
- throw new IllegalArgumentException("Bad length: " + destLen);
- } else if (destOffset + destLen > destBuffer.length) {
- throw new IllegalArgumentException(
- "Buffer overflow: " + (destOffset + destLen) + " > " + destBuffer.length);
- } else if (destLen == 0) {
- return 0;
- }
- int copyLen = Math.max(remainingBufferBytes - bufferOffset, 0);
- if (copyLen != 0) {
- copyLen = Math.min(copyLen, destLen);
- System.arraycopy(buffer, bufferOffset, destBuffer, destOffset, copyLen);
- bufferOffset += copyLen;
- destOffset += copyLen;
- destLen -= copyLen;
- if (destLen == 0) {
- return copyLen;
- }
- }
- try {
- state.output = destBuffer;
- state.outputOffset = destOffset;
- state.outputLength = destLen;
- state.outputUsed = 0;
- Decode.decompress(state);
- copyLen += state.outputUsed;
- copyLen = (copyLen > 0) ? copyLen : END_OF_STREAM_MARKER;
- return copyLen;
- } catch (BrotliRuntimeException ex) {
- throw new IOException("Brotli stream decoding failed", ex);
- }
-
- // <{[INJECTED CODE]}>
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java b/firka/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java
deleted file mode 100644
index 18449072..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2015 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.dec;
-
-/**
- * Unchecked exception used internally.
- */
-class BrotliRuntimeException extends RuntimeException {
-
- BrotliRuntimeException(String message) {
- super(message);
- }
-
- BrotliRuntimeException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/Context.java b/firka/android/app/src/main/java/org/brotli/dec/Context.java
deleted file mode 100644
index 10bf0cbc..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/Context.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2015 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.dec;
-
-/**
- * Common context lookup table for all context modes.
- */
-final class Context {
-
- static final int[] LOOKUP = new int[2048];
-
- private static final String UTF_MAP = " !! ! \"#$##%#$&'##(#)#+++++++++"
- + "+((&*'##,---,---,-----,-----,-----'###.///.///./////./////./////'# ";
- private static final String UTF_RLE = "A/* ': & : $ \u0081 @";
-
- private static void unpackLookupTable(int[] lookup, String map, String rle) {
- // LSB6, MSB6, SIGNED
- for (int i = 0; i < 256; ++i) {
- lookup[i] = i & 0x3F;
- lookup[512 + i] = i >> 2;
- lookup[1792 + i] = 2 + (i >> 6);
- }
- // UTF8
- for (int i = 0; i < 128; ++i) {
- lookup[1024 + i] = 4 * (map.charAt(i) - 32);
- }
- for (int i = 0; i < 64; ++i) {
- lookup[1152 + i] = i & 1;
- lookup[1216 + i] = 2 + (i & 1);
- }
- int offset = 1280;
- for (int k = 0; k < 19; ++k) {
- final int value = k & 3;
- final int rep = rle.charAt(k) - 32;
- for (int i = 0; i < rep; ++i) {
- lookup[offset++] = value;
- }
- }
- // SIGNED
- for (int i = 0; i < 16; ++i) {
- lookup[1792 + i] = 1;
- lookup[2032 + i] = 6;
- }
- lookup[1792] = 0;
- lookup[2047] = 7;
- for (int i = 0; i < 256; ++i) {
- lookup[1536 + i] = lookup[1792 + i] << 3;
- }
- }
-
- static {
- unpackLookupTable(LOOKUP, UTF_MAP, UTF_RLE);
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/Decode.java b/firka/android/app/src/main/java/org/brotli/dec/Decode.java
deleted file mode 100644
index bf9b6817..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/Decode.java
+++ /dev/null
@@ -1,1357 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-/**
- * API for Brotli decompression.
- */
-final class Decode {
-
- static final int MIN_LARGE_WINDOW_BITS = 10;
- /* Maximum was chosen to be 30 to allow efficient decoder implementation.
- * Format allows bigger window, but Java does not support 2G+ arrays. */
- static final int MAX_LARGE_WINDOW_BITS = 30;
-
- //----------------------------------------------------------------------------
- // RunningState
- //----------------------------------------------------------------------------
- private static final int UNINITIALIZED = 0;
- private static final int INITIALIZED = 1;
- private static final int BLOCK_START = 2;
- private static final int COMPRESSED_BLOCK_START = 3;
- private static final int MAIN_LOOP = 4;
- private static final int READ_METADATA = 5;
- private static final int COPY_UNCOMPRESSED = 6;
- private static final int INSERT_LOOP = 7;
- private static final int COPY_LOOP = 8;
- private static final int USE_DICTIONARY = 9;
- private static final int FINISHED = 10;
- private static final int CLOSED = 11;
- private static final int INIT_WRITE = 12;
- private static final int WRITE = 13;
- private static final int COPY_FROM_COMPOUND_DICTIONARY = 14;
-
- private static final int DEFAULT_CODE_LENGTH = 8;
- private static final int CODE_LENGTH_REPEAT_CODE = 16;
- private static final int NUM_LITERAL_CODES = 256;
- private static final int NUM_COMMAND_CODES = 704;
- private static final int NUM_BLOCK_LENGTH_CODES = 26;
- private static final int LITERAL_CONTEXT_BITS = 6;
- private static final int DISTANCE_CONTEXT_BITS = 2;
-
- private static final int CD_BLOCK_MAP_BITS = 8;
- private static final int HUFFMAN_TABLE_BITS = 8;
- private static final int HUFFMAN_TABLE_MASK = 0xFF;
-
- /**
- * Maximum possible Huffman table size for an alphabet size of (index * 32),
- * max code length 15 and root table bits 8.
- * The biggest alphabet is "command" - 704 symbols. Though "distance" alphabet could theoretically
- * outreach that limit (for 62 extra bit distances), practically it is limited by
- * MAX_ALLOWED_DISTANCE and never gets bigger than 544 symbols.
- */
- static final int[] MAX_HUFFMAN_TABLE_SIZE = {
- 256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
- 854, 886, 920, 952, 984, 1016, 1048, 1080
- };
-
- private static final int HUFFMAN_TABLE_SIZE_26 = 396;
- private static final int HUFFMAN_TABLE_SIZE_258 = 632;
-
- private static final int CODE_LENGTH_CODES = 18;
- private static final int[] CODE_LENGTH_CODE_ORDER = {
- 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- };
-
- private static final int NUM_DISTANCE_SHORT_CODES = 16;
- private static final int[] DISTANCE_SHORT_CODE_INDEX_OFFSET = {
- 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3
- };
-
- private static final int[] DISTANCE_SHORT_CODE_VALUE_OFFSET = {
- 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
- };
-
- /**
- * Static Huffman code for the code length code lengths.
- */
- private static final int[] FIXED_TABLE = {
- 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040001,
- 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040005
- };
-
- // TODO(eustas): generalize.
- static final int MAX_TRANSFORMED_WORD_LENGTH = 5 + 24 + 8;
-
- private static final int MAX_DISTANCE_BITS = 24;
- private static final int MAX_LARGE_WINDOW_DISTANCE_BITS = 62;
-
- /**
- * Safe distance limit.
- *
- * Limit ((1 << 31) - 4) allows safe distance calculation without overflows,
- * given the distance alphabet size is limited to corresponding size.
- */
- private static final int MAX_ALLOWED_DISTANCE = 0x7FFFFFFC;
-
- //----------------------------------------------------------------------------
- // Prefix code LUT.
- //----------------------------------------------------------------------------
- static final int[] BLOCK_LENGTH_OFFSET = {
- 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497,
- 753, 1265, 2289, 4337, 8433, 16625
- };
-
- static final int[] BLOCK_LENGTH_N_BITS = {
- 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 24
- };
-
- static final short[] INSERT_LENGTH_N_BITS = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
- 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18
- };
-
- static final short[] COPY_LENGTH_N_BITS = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
- 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18
- };
-
- // Each command is represented with 4x16-bit values:
- // * [insertLenExtraBits, copyLenExtraBits]
- // * insertLenOffset
- // * copyLenOffset
- // * distanceContext
- static final short[] CMD_LOOKUP = new short[NUM_COMMAND_CODES * 4];
-
- static {
- unpackCommandLookupTable(CMD_LOOKUP);
- }
-
- private static int log2floor(int i) {
- int result = -1;
- int step = 16;
- while (step > 0) {
- if ((i >>> step) != 0) {
- result += step;
- i = i >>> step;
- }
- step = step >> 1;
- }
- return result + i;
- }
-
- private static int calculateDistanceAlphabetSize(int npostfix, int ndirect, int maxndistbits) {
- return NUM_DISTANCE_SHORT_CODES + ndirect + 2 * (maxndistbits << npostfix);
- }
-
- // TODO(eustas): add a correctness test for this function when
- // large-window and dictionary are implemented.
- private static int calculateDistanceAlphabetLimit(int maxDistance, int npostfix, int ndirect) {
- if (maxDistance < ndirect + (2 << npostfix)) {
- throw new IllegalArgumentException("maxDistance is too small");
- }
- final int offset = ((maxDistance - ndirect) >> npostfix) + 4;
- final int ndistbits = log2floor(offset) - 1;
- final int group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1);
- return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + NUM_DISTANCE_SHORT_CODES;
- }
-
- private static void unpackCommandLookupTable(short[] cmdLookup) {
- final short[] insertLengthOffsets = new short[24];
- final short[] copyLengthOffsets = new short[24];
- copyLengthOffsets[0] = 2;
- for (int i = 0; i < 23; ++i) {
- insertLengthOffsets[i + 1] =
- (short) (insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]));
- copyLengthOffsets[i + 1] =
- (short) (copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]));
- }
-
- for (int cmdCode = 0; cmdCode < NUM_COMMAND_CODES; ++cmdCode) {
- int rangeIdx = cmdCode >>> 6;
- /* -4 turns any regular distance code to negative. */
- int distanceContextOffset = -4;
- if (rangeIdx >= 2) {
- rangeIdx -= 2;
- distanceContextOffset = 0;
- }
- final int insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
- final int copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
- final short copyLengthOffset = copyLengthOffsets[copyCode];
- final int distanceContext =
- distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
- final int index = cmdCode * 4;
- cmdLookup[index + 0] =
- (short) (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
- cmdLookup[index + 1] = insertLengthOffsets[insertCode];
- cmdLookup[index + 2] = copyLengthOffsets[copyCode];
- cmdLookup[index + 3] = (short) distanceContext;
- }
- }
-
- /**
- * Reads brotli stream header and parses "window bits".
- *
- * @param s initialized state, before any read is performed.
- * @return -1 if header is invalid
- */
- private static int decodeWindowBits(State s) {
- /* Change the meaning of flag. Before that step it means "decoder must be capable of reading
- * "large-window" brotli stream. After this step it means that "large-window" feature
- * is actually detected. Despite the window size could be same as before (lgwin = 10..24),
- * encoded distances are allowed to be much greater, thus bigger dictinary could be used. */
- final int largeWindowEnabled = s.isLargeWindow;
- s.isLargeWindow = 0;
-
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) == 0) {
- return 16;
- }
- int n = BitReader.readFewBits(s, 3);
- if (n != 0) {
- return 17 + n;
- }
- n = BitReader.readFewBits(s, 3);
- if (n != 0) {
- if (n == 1) {
- if (largeWindowEnabled == 0) {
- /* Reserved value in regular brotli stream. */
- return -1;
- }
- s.isLargeWindow = 1;
- /* Check "reserved" bit for future (post-large-window) extensions. */
- if (BitReader.readFewBits(s, 1) == 1) {
- return -1;
- }
- n = BitReader.readFewBits(s, 6);
- if (n < MIN_LARGE_WINDOW_BITS || n > MAX_LARGE_WINDOW_BITS) {
- /* Encoded window bits value is too small or too big. */
- return -1;
- }
- return n;
- } else {
- return 8 + n;
- }
- }
- return 17;
- }
-
- /**
- * Switch decoder to "eager" mode.
- *
- * In "eager" mode decoder returns as soon as there is enough data to fill output buffer.
- *
- * @param s initialized state, before any read is performed.
- */
- static void enableEagerOutput(State s) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- s.isEager = 1;
- }
-
- static void enableLargeWindow(State s) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- s.isLargeWindow = 1;
- }
-
- // TODO(eustas): do we need byte views?
- static void attachDictionaryChunk(State s, byte[] data) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- if (s.cdNumChunks == 0) {
- s.cdChunks = new byte[16][];
- s.cdChunkOffsets = new int[16];
- s.cdBlockBits = -1;
- }
- if (s.cdNumChunks == 15) {
- throw new IllegalStateException("Too many dictionary chunks");
- }
- s.cdChunks[s.cdNumChunks] = data;
- s.cdNumChunks++;
- s.cdTotalSize += data.length;
- s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;
- }
-
- /**
- * Associate input with decoder state.
- *
- * @param s uninitialized state without associated input
- * @param input compressed data source
- */
- static void initState(State s, InputStream input) {
- if (s.runningState != UNINITIALIZED) {
- throw new IllegalStateException("State MUST be uninitialized");
- }
- /* 6 trees + 1 extra "offset" slot to simplify table decoding logic. */
- s.blockTrees = new int[7 + 3 * (HUFFMAN_TABLE_SIZE_258 + HUFFMAN_TABLE_SIZE_26)];
- s.blockTrees[0] = 7;
- s.distRbIdx = 3;
- final int maxDistanceAlphabetLimit =
- calculateDistanceAlphabetLimit(MAX_ALLOWED_DISTANCE, 3, 15 << 3);
- s.distExtraBits = new byte[maxDistanceAlphabetLimit];
- s.distOffset = new int[maxDistanceAlphabetLimit];
- s.input = input;
- BitReader.initBitReader(s);
- s.runningState = INITIALIZED;
- }
-
- static void close(State s) throws IOException {
- if (s.runningState == UNINITIALIZED) {
- throw new IllegalStateException("State MUST be initialized");
- }
- if (s.runningState == CLOSED) {
- return;
- }
- s.runningState = CLOSED;
- if (s.input != null) {
- Utils.closeInput(s.input);
- s.input = null;
- }
- }
-
- /**
- * Decodes a number in the range [0..255], by reading 1 - 11 bits.
- */
- private static int decodeVarLenUnsignedByte(State s) {
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) != 0) {
- final int n = BitReader.readFewBits(s, 3);
- if (n == 0) {
- return 1;
- } else {
- return BitReader.readFewBits(s, n) + (1 << n);
- }
- }
- return 0;
- }
-
- private static void decodeMetaBlockLength(State s) {
- BitReader.fillBitWindow(s);
- s.inputEnd = BitReader.readFewBits(s, 1);
- s.metaBlockLength = 0;
- s.isUncompressed = 0;
- s.isMetadata = 0;
- if ((s.inputEnd != 0) && BitReader.readFewBits(s, 1) != 0) {
- return;
- }
- final int sizeNibbles = BitReader.readFewBits(s, 2) + 4;
- if (sizeNibbles == 7) {
- s.isMetadata = 1;
- if (BitReader.readFewBits(s, 1) != 0) {
- throw new BrotliRuntimeException("Corrupted reserved bit");
- }
- final int sizeBytes = BitReader.readFewBits(s, 2);
- if (sizeBytes == 0) {
- return;
- }
- for (int i = 0; i < sizeBytes; i++) {
- BitReader.fillBitWindow(s);
- final int bits = BitReader.readFewBits(s, 8);
- if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
- throw new BrotliRuntimeException("Exuberant nibble");
- }
- s.metaBlockLength |= bits << (i * 8);
- }
- } else {
- for (int i = 0; i < sizeNibbles; i++) {
- BitReader.fillBitWindow(s);
- final int bits = BitReader.readFewBits(s, 4);
- if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
- throw new BrotliRuntimeException("Exuberant nibble");
- }
- s.metaBlockLength |= bits << (i * 4);
- }
- }
- s.metaBlockLength++;
- if (s.inputEnd == 0) {
- s.isUncompressed = BitReader.readFewBits(s, 1);
- }
- }
-
- /**
- * Decodes the next Huffman code from bit-stream.
- */
- private static int readSymbol(int[] tableGroup, int tableIdx, State s) {
- int offset = tableGroup[tableIdx];
- final int val = BitReader.peekBits(s);
- offset += val & HUFFMAN_TABLE_MASK;
- final int bits = tableGroup[offset] >> 16;
- final int sym = tableGroup[offset] & 0xFFFF;
- if (bits <= HUFFMAN_TABLE_BITS) {
- s.bitOffset += bits;
- return sym;
- }
- offset += sym;
- final int mask = (1 << bits) - 1;
- offset += (val & mask) >>> HUFFMAN_TABLE_BITS;
- s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS);
- return tableGroup[offset] & 0xFFFF;
- }
-
- private static int readBlockLength(int[] tableGroup, int tableIdx, State s) {
- BitReader.fillBitWindow(s);
- final int code = readSymbol(tableGroup, tableIdx, s);
- final int n = BLOCK_LENGTH_N_BITS[code];
- BitReader.fillBitWindow(s);
- return BLOCK_LENGTH_OFFSET[code] + BitReader.readBits(s, n);
- }
-
- private static void moveToFront(int[] v, int index) {
- final int value = v[index];
- for (; index > 0; index--) {
- v[index] = v[index - 1];
- }
- v[0] = value;
- }
-
- private static void inverseMoveToFrontTransform(byte[] v, int vLen) {
- final int[] mtf = new int[256];
- for (int i = 0; i < 256; i++) {
- mtf[i] = i;
- }
- for (int i = 0; i < vLen; i++) {
- final int index = v[i] & 0xFF;
- v[i] = (byte) mtf[index];
- if (index != 0) {
- moveToFront(mtf, index);
- }
- }
- }
-
- private static void readHuffmanCodeLengths(
- int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, State s) {
- int symbol = 0;
- int prevCodeLen = DEFAULT_CODE_LENGTH;
- int repeat = 0;
- int repeatCodeLen = 0;
- int space = 32768;
- final int[] table = new int[32 + 1]; /* Speculative single entry table group. */
- final int tableIdx = table.length - 1;
- Huffman.buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, CODE_LENGTH_CODES);
-
- while (symbol < numSymbols && space > 0) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int p = BitReader.peekBits(s) & 31;
- s.bitOffset += table[p] >> 16;
- final int codeLen = table[p] & 0xFFFF;
- if (codeLen < CODE_LENGTH_REPEAT_CODE) {
- repeat = 0;
- codeLengths[symbol++] = codeLen;
- if (codeLen != 0) {
- prevCodeLen = codeLen;
- space -= 32768 >> codeLen;
- }
- } else {
- final int extraBits = codeLen - 14;
- int newLen = 0;
- if (codeLen == CODE_LENGTH_REPEAT_CODE) {
- newLen = prevCodeLen;
- }
- if (repeatCodeLen != newLen) {
- repeat = 0;
- repeatCodeLen = newLen;
- }
- final int oldRepeat = repeat;
- if (repeat > 0) {
- repeat -= 2;
- repeat <<= extraBits;
- }
- BitReader.fillBitWindow(s);
- repeat += BitReader.readFewBits(s, extraBits) + 3;
- final int repeatDelta = repeat - oldRepeat;
- if (symbol + repeatDelta > numSymbols) {
- throw new BrotliRuntimeException("symbol + repeatDelta > numSymbols"); // COV_NF_LINE
- }
- for (int i = 0; i < repeatDelta; i++) {
- codeLengths[symbol++] = repeatCodeLen;
- }
- if (repeatCodeLen != 0) {
- space -= repeatDelta << (15 - repeatCodeLen);
- }
- }
- }
- if (space != 0) {
- throw new BrotliRuntimeException("Unused space"); // COV_NF_LINE
- }
- // TODO(eustas): Pass max_symbol to Huffman table builder instead?
- Utils.fillIntsWithZeroes(codeLengths, symbol, numSymbols);
- }
-
- private static void checkDupes(int[] symbols, int length) {
- for (int i = 0; i < length - 1; ++i) {
- for (int j = i + 1; j < length; ++j) {
- if (symbols[i] == symbols[j]) {
- throw new BrotliRuntimeException("Duplicate simple Huffman code symbol"); // COV_NF_LINE
- }
- }
- }
- }
-
- /**
- * Reads up to 4 symbols directly and applies predefined histograms.
- */
- private static int readSimpleHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
- int[] tableGroup, int tableIdx, State s) {
- // TODO(eustas): Avoid allocation?
- final int[] codeLengths = new int[alphabetSizeLimit];
- final int[] symbols = new int[4];
-
- final int maxBits = 1 + log2floor(alphabetSizeMax - 1);
-
- final int numSymbols = BitReader.readFewBits(s, 2) + 1;
- for (int i = 0; i < numSymbols; i++) {
- BitReader.fillBitWindow(s);
- final int symbol = BitReader.readFewBits(s, maxBits);
- if (symbol >= alphabetSizeLimit) {
- throw new BrotliRuntimeException("Can't readHuffmanCode"); // COV_NF_LINE
- }
- symbols[i] = symbol;
- }
- checkDupes(symbols, numSymbols);
-
- int histogramId = numSymbols;
- if (numSymbols == 4) {
- histogramId += BitReader.readFewBits(s, 1);
- }
-
- switch (histogramId) {
- case 1:
- codeLengths[symbols[0]] = 1;
- break;
-
- case 2:
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 1;
- break;
-
- case 3:
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 2;
- break;
-
- case 4: // uniform 4-symbol histogram
- codeLengths[symbols[0]] = 2;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 2;
- codeLengths[symbols[3]] = 2;
- break;
-
- case 5: // prioritized 4-symbol histogram
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 3;
- codeLengths[symbols[3]] = 3;
- break;
-
- default:
- break;
- }
-
- // TODO(eustas): Use specialized version?
- return Huffman.buildHuffmanTable(
- tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
- }
-
- // Decode Huffman-coded code lengths.
- private static int readComplexHuffmanCode(int alphabetSizeLimit, int skip,
- int[] tableGroup, int tableIdx, State s) {
- // TODO(eustas): Avoid allocation?
- final int[] codeLengths = new int[alphabetSizeLimit];
- final int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES];
- int space = 32;
- int numCodes = 0;
- for (int i = skip; i < CODE_LENGTH_CODES && space > 0; i++) {
- final int codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
- BitReader.fillBitWindow(s);
- final int p = BitReader.peekBits(s) & 15;
- // TODO(eustas): Demultiplex FIXED_TABLE.
- s.bitOffset += FIXED_TABLE[p] >> 16;
- final int v = FIXED_TABLE[p] & 0xFFFF;
- codeLengthCodeLengths[codeLenIdx] = v;
- if (v != 0) {
- space -= (32 >> v);
- numCodes++;
- }
- }
- if (space != 0 && numCodes != 1) {
- throw new BrotliRuntimeException("Corrupted Huffman code histogram"); // COV_NF_LINE
- }
-
- readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);
-
- return Huffman.buildHuffmanTable(
- tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
- }
-
- /**
- * Decodes Huffman table from bit-stream.
- *
- * @return number of slots used by resulting Huffman table
- */
- private static int readHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
- int[] tableGroup, int tableIdx, State s) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int simpleCodeOrSkip = BitReader.readFewBits(s, 2);
- if (simpleCodeOrSkip == 1) {
- return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
- } else {
- return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);
- }
- }
-
- private static int decodeContextMap(int contextMapSize, byte[] contextMap, State s) {
- BitReader.readMoreInput(s);
- final int numTrees = decodeVarLenUnsignedByte(s) + 1;
-
- if (numTrees == 1) {
- Utils.fillBytesWithZeroes(contextMap, 0, contextMapSize);
- return numTrees;
- }
-
- BitReader.fillBitWindow(s);
- final int useRleForZeros = BitReader.readFewBits(s, 1);
- int maxRunLengthPrefix = 0;
- if (useRleForZeros != 0) {
- maxRunLengthPrefix = BitReader.readFewBits(s, 4) + 1;
- }
- final int alphabetSize = numTrees + maxRunLengthPrefix;
- final int tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5];
- /* Speculative single entry table group. */
- final int[] table = new int[tableSize + 1];
- final int tableIdx = table.length - 1;
- readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
- for (int i = 0; i < contextMapSize; ) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int code = readSymbol(table, tableIdx, s);
- if (code == 0) {
- contextMap[i] = 0;
- i++;
- } else if (code <= maxRunLengthPrefix) {
- BitReader.fillBitWindow(s);
- int reps = (1 << code) + BitReader.readFewBits(s, code);
- while (reps != 0) {
- if (i >= contextMapSize) {
- throw new BrotliRuntimeException("Corrupted context map"); // COV_NF_LINE
- }
- contextMap[i] = 0;
- i++;
- reps--;
- }
- } else {
- contextMap[i] = (byte) (code - maxRunLengthPrefix);
- i++;
- }
- }
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) == 1) {
- inverseMoveToFrontTransform(contextMap, contextMapSize);
- }
- return numTrees;
- }
-
- private static int decodeBlockTypeAndLength(State s, int treeType, int numBlockTypes) {
- final int[] ringBuffers = s.rings;
- final int offset = 4 + treeType * 2;
- BitReader.fillBitWindow(s);
- int blockType = readSymbol(s.blockTrees, 2 * treeType, s);
- final int result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
-
- if (blockType == 1) {
- blockType = ringBuffers[offset + 1] + 1;
- } else if (blockType == 0) {
- blockType = ringBuffers[offset];
- } else {
- blockType -= 2;
- }
- if (blockType >= numBlockTypes) {
- blockType -= numBlockTypes;
- }
- ringBuffers[offset] = ringBuffers[offset + 1];
- ringBuffers[offset + 1] = blockType;
- return result;
- }
-
- private static void decodeLiteralBlockSwitch(State s) {
- s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
- final int literalBlockType = s.rings[5];
- s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS;
- s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF;
- final int contextMode = s.contextModes[literalBlockType];
- s.contextLookupOffset1 = contextMode << 9;
- s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
- }
-
- private static void decodeCommandBlockSwitch(State s) {
- s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);
- s.commandTreeIdx = s.rings[7];
- }
-
- private static void decodeDistanceBlockSwitch(State s) {
- s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);
- s.distContextMapSlice = s.rings[9] << DISTANCE_CONTEXT_BITS;
- }
-
- private static void maybeReallocateRingBuffer(State s) {
- int newSize = s.maxRingBufferSize;
- if (newSize > s.expectedTotalSize) {
- /* TODO(eustas): Handle 2GB+ cases more gracefully. */
- final int minimalNewSize = s.expectedTotalSize;
- while ((newSize >> 1) > minimalNewSize) {
- newSize >>= 1;
- }
- if ((s.inputEnd == 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
- newSize = 16384;
- }
- }
- if (newSize <= s.ringBufferSize) {
- return;
- }
- final int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH;
- final byte[] newBuffer = new byte[ringBufferSizeWithSlack];
- if (s.ringBuffer.length != 0) {
- System.arraycopy(s.ringBuffer, 0, newBuffer, 0, s.ringBufferSize);
- }
- s.ringBuffer = newBuffer;
- s.ringBufferSize = newSize;
- }
-
- private static void readNextMetablockHeader(State s) {
- if (s.inputEnd != 0) {
- s.nextRunningState = FINISHED;
- s.runningState = INIT_WRITE;
- return;
- }
- // TODO(eustas): Reset? Do we need this?
- s.literalTreeGroup = new int[0];
- s.commandTreeGroup = new int[0];
- s.distanceTreeGroup = new int[0];
-
- BitReader.readMoreInput(s);
- decodeMetaBlockLength(s);
- if ((s.metaBlockLength == 0) && (s.isMetadata == 0)) {
- return;
- }
- if ((s.isUncompressed != 0) || (s.isMetadata != 0)) {
- BitReader.jumpToByteBoundary(s);
- s.runningState = (s.isMetadata != 0) ? READ_METADATA : COPY_UNCOMPRESSED;
- } else {
- s.runningState = COMPRESSED_BLOCK_START;
- }
-
- if (s.isMetadata != 0) {
- return;
- }
- s.expectedTotalSize += s.metaBlockLength;
- if (s.expectedTotalSize > 1 << 30) {
- s.expectedTotalSize = 1 << 30;
- }
- if (s.ringBufferSize < s.maxRingBufferSize) {
- maybeReallocateRingBuffer(s);
- }
- }
-
- private static int readMetablockPartition(State s, int treeType, int numBlockTypes) {
- int offset = s.blockTrees[2 * treeType];
- if (numBlockTypes <= 1) {
- s.blockTrees[2 * treeType + 1] = offset;
- s.blockTrees[2 * treeType + 2] = offset;
- return 1 << 28;
- }
-
- final int blockTypeAlphabetSize = numBlockTypes + 2;
- offset += readHuffmanCode(
- blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
- s.blockTrees[2 * treeType + 1] = offset;
-
- final int blockLengthAlphabetSize = NUM_BLOCK_LENGTH_CODES;
- offset += readHuffmanCode(
- blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
- s.blockTrees[2 * treeType + 2] = offset;
-
- return readBlockLength(s.blockTrees, 2 * treeType + 1, s);
- }
-
- private static void calculateDistanceLut(State s, int alphabetSizeLimit) {
- final byte[] distExtraBits = s.distExtraBits;
- final int[] distOffset = s.distOffset;
- final int npostfix = s.distancePostfixBits;
- final int ndirect = s.numDirectDistanceCodes;
- final int postfix = 1 << npostfix;
- int bits = 1;
- int half = 0;
-
- /* Skip short codes. */
- int i = NUM_DISTANCE_SHORT_CODES;
-
- /* Fill direct codes. */
- for (int j = 0; j < ndirect; ++j) {
- distExtraBits[i] = 0;
- distOffset[i] = j + 1;
- ++i;
- }
-
- /* Fill regular distance codes. */
- while (i < alphabetSizeLimit) {
- final int base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
- /* Always fill the complete group. */
- for (int j = 0; j < postfix; ++j) {
- distExtraBits[i] = (byte) bits;
- distOffset[i] = base + j;
- ++i;
- }
- bits = bits + half;
- half = half ^ 1;
- }
- }
-
- private static void readMetablockHuffmanCodesAndContextMaps(State s) {
- s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.literalBlockLength = readMetablockPartition(s, 0, s.numLiteralBlockTypes);
- s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.commandBlockLength = readMetablockPartition(s, 1, s.numCommandBlockTypes);
- s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.distanceBlockLength = readMetablockPartition(s, 2, s.numDistanceBlockTypes);
-
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- s.distancePostfixBits = BitReader.readFewBits(s, 2);
- s.numDirectDistanceCodes = BitReader.readFewBits(s, 4) << s.distancePostfixBits;
- // TODO(eustas): Reuse?
- s.contextModes = new byte[s.numLiteralBlockTypes];
- for (int i = 0; i < s.numLiteralBlockTypes;) {
- /* Ensure that less than 256 bits read between readMoreInput. */
- final int limit = Math.min(i + 96, s.numLiteralBlockTypes);
- for (; i < limit; ++i) {
- BitReader.fillBitWindow(s);
- s.contextModes[i] = (byte) BitReader.readFewBits(s, 2);
- }
- BitReader.readMoreInput(s);
- }
-
- // TODO(eustas): Reuse?
- s.contextMap = new byte[s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS];
- final int numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS,
- s.contextMap, s);
- s.trivialLiteralContext = 1;
- for (int j = 0; j < s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS; j++) {
- if (s.contextMap[j] != j >> LITERAL_CONTEXT_BITS) {
- s.trivialLiteralContext = 0;
- break;
- }
- }
-
- // TODO(eustas): Reuse?
- s.distContextMap = new byte[s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS];
- final int numDistTrees = decodeContextMap(s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS,
- s.distContextMap, s);
-
- s.literalTreeGroup = decodeHuffmanTreeGroup(NUM_LITERAL_CODES, NUM_LITERAL_CODES,
- numLiteralTrees, s);
- s.commandTreeGroup = decodeHuffmanTreeGroup(NUM_COMMAND_CODES, NUM_COMMAND_CODES,
- s.numCommandBlockTypes, s);
- int distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
- s.distancePostfixBits, s.numDirectDistanceCodes, MAX_DISTANCE_BITS);
- int distanceAlphabetSizeLimit = distanceAlphabetSizeMax;
- if (s.isLargeWindow == 1) {
- distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
- s.distancePostfixBits, s.numDirectDistanceCodes, MAX_LARGE_WINDOW_DISTANCE_BITS);
- distanceAlphabetSizeLimit = calculateDistanceAlphabetLimit(
- MAX_ALLOWED_DISTANCE, s.distancePostfixBits, s.numDirectDistanceCodes);
- }
- s.distanceTreeGroup = decodeHuffmanTreeGroup(distanceAlphabetSizeMax, distanceAlphabetSizeLimit,
- numDistTrees, s);
- calculateDistanceLut(s, distanceAlphabetSizeLimit);
-
- s.contextMapSlice = 0;
- s.distContextMapSlice = 0;
- s.contextLookupOffset1 = s.contextModes[0] * 512;
- s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
- s.literalTreeIdx = 0;
- s.commandTreeIdx = 0;
-
- s.rings[4] = 1;
- s.rings[5] = 0;
- s.rings[6] = 1;
- s.rings[7] = 0;
- s.rings[8] = 1;
- s.rings[9] = 0;
- }
-
- private static void copyUncompressedData(State s) {
- final byte[] ringBuffer = s.ringBuffer;
-
- // Could happen if block ends at ring buffer end.
- if (s.metaBlockLength <= 0) {
- BitReader.reload(s);
- s.runningState = BLOCK_START;
- return;
- }
-
- final int chunkLength = Math.min(s.ringBufferSize - s.pos, s.metaBlockLength);
- BitReader.copyRawBytes(s, ringBuffer, s.pos, chunkLength);
- s.metaBlockLength -= chunkLength;
- s.pos += chunkLength;
- if (s.pos == s.ringBufferSize) {
- s.nextRunningState = COPY_UNCOMPRESSED;
- s.runningState = INIT_WRITE;
- return;
- }
-
- BitReader.reload(s);
- s.runningState = BLOCK_START;
- }
-
- private static int writeRingBuffer(State s) {
- final int toWrite = Math.min(s.outputLength - s.outputUsed,
- s.ringBufferBytesReady - s.ringBufferBytesWritten);
- // TODO(eustas): DCHECK(toWrite >= 0)
- if (toWrite != 0) {
- System.arraycopy(s.ringBuffer, s.ringBufferBytesWritten, s.output,
- s.outputOffset + s.outputUsed, toWrite);
- s.outputUsed += toWrite;
- s.ringBufferBytesWritten += toWrite;
- }
-
- if (s.outputUsed < s.outputLength) {
- return 1;
- } else {
- return 0;
- }
- }
-
- private static int[] decodeHuffmanTreeGroup(int alphabetSizeMax, int alphabetSizeLimit,
- int n, State s) {
- final int maxTableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSizeLimit + 31) >> 5];
- final int[] group = new int[n + n * maxTableSize];
- int next = n;
- for (int i = 0; i < n; ++i) {
- group[i] = next;
- next += readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, group, i, s);
- }
- return group;
- }
-
- // Returns offset in ringBuffer that should trigger WRITE when filled.
- private static int calculateFence(State s) {
- int result = s.ringBufferSize;
- if (s.isEager != 0) {
- result = Math.min(result, s.ringBufferBytesWritten + s.outputLength - s.outputUsed);
- }
- return result;
- }
-
- private static void doUseDictionary(State s, int fence) {
- if (s.distance > MAX_ALLOWED_DISTANCE) {
- throw new BrotliRuntimeException("Invalid backward reference");
- }
- final int address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
- if (address < 0) {
- initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
- s.runningState = COPY_FROM_COMPOUND_DICTIONARY;
- } else {
- // Force lazy dictionary initialization.
- final ByteBuffer dictionaryData = Dictionary.getData();
- final int wordLength = s.copyLength;
- if (wordLength > Dictionary.MAX_DICTIONARY_WORD_LENGTH) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- final int shift = Dictionary.sizeBits[wordLength];
- if (shift == 0) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- int offset = Dictionary.offsets[wordLength];
- final int mask = (1 << shift) - 1;
- final int wordIdx = address & mask;
- final int transformIdx = address >>> shift;
- offset += wordIdx * wordLength;
- final Transform.Transforms transforms = Transform.RFC_TRANSFORMS;
- if (transformIdx >= transforms.numTransforms) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- final int len = Transform.transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData,
- offset, wordLength, transforms, transformIdx);
- s.pos += len;
- s.metaBlockLength -= len;
- if (s.pos >= fence) {
- s.nextRunningState = MAIN_LOOP;
- s.runningState = INIT_WRITE;
- return;
- }
- s.runningState = MAIN_LOOP;
- }
- }
-
- private static void initializeCompoundDictionary(State s) {
- s.cdBlockMap = new byte[1 << CD_BLOCK_MAP_BITS];
- int blockBits = CD_BLOCK_MAP_BITS;
- // If this function is executed, then s.cdTotalSize > 0.
- while (((s.cdTotalSize - 1) >>> blockBits) != 0) {
- blockBits++;
- }
- blockBits -= CD_BLOCK_MAP_BITS;
- s.cdBlockBits = blockBits;
- int cursor = 0;
- int index = 0;
- while (cursor < s.cdTotalSize) {
- while (s.cdChunkOffsets[index + 1] < cursor) {
- index++;
- }
- s.cdBlockMap[cursor >>> blockBits] = (byte) index;
- cursor += 1 << blockBits;
- }
- }
-
- private static void initializeCompoundDictionaryCopy(State s, int address, int length) {
- if (s.cdBlockBits == -1) {
- initializeCompoundDictionary(s);
- }
- int index = s.cdBlockMap[address >>> s.cdBlockBits];
- while (address >= s.cdChunkOffsets[index + 1]) {
- index++;
- }
- if (s.cdTotalSize > address + length) {
- throw new BrotliRuntimeException("Invalid backward reference");
- }
- /* Update the recent distances cache */
- s.distRbIdx = (s.distRbIdx + 1) & 0x3;
- s.rings[s.distRbIdx] = s.distance;
- s.metaBlockLength -= length;
- s.cdBrIndex = index;
- s.cdBrOffset = address - s.cdChunkOffsets[index];
- s.cdBrLength = length;
- s.cdBrCopied = 0;
- }
-
- private static int copyFromCompoundDictionary(State s, int fence) {
- int pos = s.pos;
- final int origPos = pos;
- while (s.cdBrLength != s.cdBrCopied) {
- final int space = fence - pos;
- final int chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex];
- final int remChunkLength = chunkLength - s.cdBrOffset;
- int length = s.cdBrLength - s.cdBrCopied;
- if (length > remChunkLength) {
- length = remChunkLength;
- }
- if (length > space) {
- length = space;
- }
- Utils.copyBytes(
- s.ringBuffer, pos, s.cdChunks[s.cdBrIndex], s.cdBrOffset, s.cdBrOffset + length);
- pos += length;
- s.cdBrOffset += length;
- s.cdBrCopied += length;
- if (length == remChunkLength) {
- s.cdBrIndex++;
- s.cdBrOffset = 0;
- }
- if (pos >= fence) {
- break;
- }
- }
- return pos - origPos;
- }
-
- /**
- * Actual decompress implementation.
- */
- static void decompress(State s) {
- if (s.runningState == UNINITIALIZED) {
- throw new IllegalStateException("Can't decompress until initialized");
- }
- if (s.runningState == CLOSED) {
- throw new IllegalStateException("Can't decompress after close");
- }
- if (s.runningState == INITIALIZED) {
- final int windowBits = decodeWindowBits(s);
- if (windowBits == -1) { /* Reserved case for future expansion. */
- throw new BrotliRuntimeException("Invalid 'windowBits' code");
- }
- s.maxRingBufferSize = 1 << windowBits;
- s.maxBackwardDistance = s.maxRingBufferSize - 16;
- s.runningState = BLOCK_START;
- }
-
- int fence = calculateFence(s);
- int ringBufferMask = s.ringBufferSize - 1;
- byte[] ringBuffer = s.ringBuffer;
-
- while (s.runningState != FINISHED) {
- // TODO(eustas): extract cases to methods for the better readability.
- switch (s.runningState) {
- case BLOCK_START:
- if (s.metaBlockLength < 0) {
- throw new BrotliRuntimeException("Invalid metablock length");
- }
- readNextMetablockHeader(s);
- /* Ring-buffer would be reallocated here. */
- fence = calculateFence(s);
- ringBufferMask = s.ringBufferSize - 1;
- ringBuffer = s.ringBuffer;
- continue;
-
- case COMPRESSED_BLOCK_START:
- readMetablockHuffmanCodesAndContextMaps(s);
- s.runningState = MAIN_LOOP;
-
- // fall through
- case MAIN_LOOP:
- if (s.metaBlockLength <= 0) {
- s.runningState = BLOCK_START;
- continue;
- }
- BitReader.readMoreInput(s);
- if (s.commandBlockLength == 0) {
- decodeCommandBlockSwitch(s);
- }
- s.commandBlockLength--;
- BitReader.fillBitWindow(s);
- final int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
- final short insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
- final int insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
- final int copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
- s.distanceCode = CMD_LOOKUP[cmdCode + 3];
- BitReader.fillBitWindow(s);
- {
- final int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF;
- s.insertLength = insertLengthOffset + BitReader.readBits(s, insertLengthExtraBits);
- }
- BitReader.fillBitWindow(s);
- {
- final int copyLengthExtraBits = insertAndCopyExtraBits >> 8;
- s.copyLength = copyLengthOffset + BitReader.readBits(s, copyLengthExtraBits);
- }
-
- s.j = 0;
- s.runningState = INSERT_LOOP;
-
- // fall through
- case INSERT_LOOP:
- if (s.trivialLiteralContext != 0) {
- while (s.j < s.insertLength) {
- BitReader.readMoreInput(s);
- if (s.literalBlockLength == 0) {
- decodeLiteralBlockSwitch(s);
- }
- s.literalBlockLength--;
- BitReader.fillBitWindow(s);
- ringBuffer[s.pos] = (byte) readSymbol(s.literalTreeGroup, s.literalTreeIdx, s);
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = INSERT_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- } else {
- int prevByte1 = ringBuffer[(s.pos - 1) & ringBufferMask] & 0xFF;
- int prevByte2 = ringBuffer[(s.pos - 2) & ringBufferMask] & 0xFF;
- while (s.j < s.insertLength) {
- BitReader.readMoreInput(s);
- if (s.literalBlockLength == 0) {
- decodeLiteralBlockSwitch(s);
- }
- final int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1]
- | Context.LOOKUP[s.contextLookupOffset2 + prevByte2];
- final int literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
- s.literalBlockLength--;
- prevByte2 = prevByte1;
- BitReader.fillBitWindow(s);
- prevByte1 = readSymbol(s.literalTreeGroup, literalTreeIdx, s);
- ringBuffer[s.pos] = (byte) prevByte1;
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = INSERT_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- }
- if (s.runningState != INSERT_LOOP) {
- continue;
- }
- s.metaBlockLength -= s.insertLength;
- if (s.metaBlockLength <= 0) {
- s.runningState = MAIN_LOOP;
- continue;
- }
- int distanceCode = s.distanceCode;
- if (distanceCode < 0) {
- // distanceCode in untouched; assigning it 0 won't affect distance ring buffer rolling.
- s.distance = s.rings[s.distRbIdx];
- } else {
- BitReader.readMoreInput(s);
- if (s.distanceBlockLength == 0) {
- decodeDistanceBlockSwitch(s);
- }
- s.distanceBlockLength--;
- BitReader.fillBitWindow(s);
- final int distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
- distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
- if (distanceCode < NUM_DISTANCE_SHORT_CODES) {
- final int index =
- (s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode]) & 0x3;
- s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
- if (s.distance < 0) {
- throw new BrotliRuntimeException("Negative distance"); // COV_NF_LINE
- }
- } else {
- final int extraBits = s.distExtraBits[distanceCode];
- int bits;
- if (s.bitOffset + extraBits <= BitReader.BITNESS) {
- bits = BitReader.readFewBits(s, extraBits);
- } else {
- BitReader.fillBitWindow(s);
- bits = BitReader.readBits(s, extraBits);
- }
- s.distance = s.distOffset[distanceCode] + (bits << s.distancePostfixBits);
- }
- }
-
- if (s.maxDistance != s.maxBackwardDistance
- && s.pos < s.maxBackwardDistance) {
- s.maxDistance = s.pos;
- } else {
- s.maxDistance = s.maxBackwardDistance;
- }
-
- if (s.distance > s.maxDistance) {
- s.runningState = USE_DICTIONARY;
- continue;
- }
-
- if (distanceCode > 0) {
- s.distRbIdx = (s.distRbIdx + 1) & 0x3;
- s.rings[s.distRbIdx] = s.distance;
- }
-
- if (s.copyLength > s.metaBlockLength) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- s.j = 0;
- s.runningState = COPY_LOOP;
-
- // fall through
- case COPY_LOOP:
- int src = (s.pos - s.distance) & ringBufferMask;
- int dst = s.pos;
- final int copyLength = s.copyLength - s.j;
- final int srcEnd = src + copyLength;
- final int dstEnd = dst + copyLength;
- if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
- if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
- for (int k = 0; k < copyLength; k += 4) {
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- }
- } else {
- Utils.copyBytesWithin(ringBuffer, dst, src, srcEnd);
- }
- s.j += copyLength;
- s.metaBlockLength -= copyLength;
- s.pos += copyLength;
- } else {
- for (; s.j < s.copyLength;) {
- ringBuffer[s.pos] =
- ringBuffer[(s.pos - s.distance) & ringBufferMask];
- s.metaBlockLength--;
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = COPY_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- }
- if (s.runningState == COPY_LOOP) {
- s.runningState = MAIN_LOOP;
- }
- continue;
-
- case USE_DICTIONARY:
- doUseDictionary(s, fence);
- continue;
-
- case COPY_FROM_COMPOUND_DICTIONARY:
- s.pos += copyFromCompoundDictionary(s, fence);
- if (s.pos >= fence) {
- s.nextRunningState = COPY_FROM_COMPOUND_DICTIONARY;
- s.runningState = INIT_WRITE;
- return;
- }
- s.runningState = MAIN_LOOP;
- continue;
-
- case READ_METADATA:
- while (s.metaBlockLength > 0) {
- BitReader.readMoreInput(s);
- // Optimize
- BitReader.fillBitWindow(s);
- BitReader.readFewBits(s, 8);
- s.metaBlockLength--;
- }
- s.runningState = BLOCK_START;
- continue;
-
- case COPY_UNCOMPRESSED:
- copyUncompressedData(s);
- continue;
-
- case INIT_WRITE:
- s.ringBufferBytesReady = Math.min(s.pos, s.ringBufferSize);
- s.runningState = WRITE;
-
- // fall through
- case WRITE:
- if (writeRingBuffer(s) == 0) {
- // Output buffer is full.
- return;
- }
- if (s.pos >= s.maxBackwardDistance) {
- s.maxDistance = s.maxBackwardDistance;
- }
- // Wrap the ringBuffer.
- if (s.pos >= s.ringBufferSize) {
- if (s.pos > s.ringBufferSize) {
- Utils.copyBytesWithin(ringBuffer, 0, s.ringBufferSize, s.pos);
- }
- s.pos &= ringBufferMask;
- s.ringBufferBytesWritten = 0;
- }
- s.runningState = s.nextRunningState;
- continue;
-
- default:
- throw new BrotliRuntimeException("Unexpected state " + String.valueOf(s.runningState));
- }
- }
- if (s.runningState == FINISHED) {
- if (s.metaBlockLength < 0) {
- throw new BrotliRuntimeException("Invalid metablock length");
- }
- BitReader.jumpToByteBoundary(s);
- BitReader.checkHealth(s, 1);
- }
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/Decoder.java b/firka/android/app/src/main/java/org/brotli/dec/Decoder.java
deleted file mode 100644
index e33f5a9a..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/Decoder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.brotli.dec;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class Decoder {
- private static long decodeBytes(InputStream input, OutputStream output, byte[] buffer)
- throws IOException {
- long totalOut = 0;
- int readBytes;
- BrotliInputStream in = new BrotliInputStream(input);
- in.enableLargeWindow();
- try {
- while ((readBytes = in.read(buffer)) >= 0) {
- output.write(buffer, 0, readBytes);
- totalOut += readBytes;
- }
- } finally {
- in.close();
- }
- return totalOut;
- }
-
- private static void decompress(String fromPath, String toPath, byte[] buffer) throws IOException {
- long start;
- long bytesDecoded;
- long end;
- InputStream in = null;
- OutputStream out = null;
- try {
- in = new FileInputStream(fromPath);
- out = new FileOutputStream(toPath);
- start = System.nanoTime();
- bytesDecoded = decodeBytes(in, out, buffer);
- end = System.nanoTime();
- } finally {
- if (in != null) {
- in.close(); // Hopefully, does not throw exception.
- }
- if (out != null) {
- out.close();
- }
- }
-
- double timeDelta = (end - start) / 1000000000.0;
- if (timeDelta <= 0) {
- return;
- }
- double mbDecoded = bytesDecoded / (1024.0 * 1024.0);
- System.out.println(mbDecoded / timeDelta + " MiB/s");
- }
-
- public static void main(String... args) throws IOException {
- if (args.length != 2 && args.length != 3) {
- System.out.println("Usage: decoder Dictionary content is loaded from binary resource when {@link #getData()} is executed for the
- * first time. Consequently, it saves memory and CPU in case dictionary is not required.
- *
- * One possible drawback is that multiple threads that need dictionary data may be blocked (only
- * once in each classworld). To avoid this, it is enough to call {@link #getData()} proactively.
- */
-public final class Dictionary {
- static final int MIN_DICTIONARY_WORD_LENGTH = 4;
- static final int MAX_DICTIONARY_WORD_LENGTH = 31;
-
- private static ByteBuffer data = ByteBuffer.allocateDirect(0);
- static final int[] offsets = new int[32];
- static final int[] sizeBits = new int[32];
-
- private static class DataLoader {
- static final boolean OK;
-
- static {
- boolean ok = true;
- try {
- Class.forName(Dictionary.class.getPackage().getName() + ".DictionaryData");
- } catch (Throwable ex) {
- ok = false;
- }
- OK = ok;
- }
- }
-
- public static void setData(ByteBuffer newData, int[] newSizeBits) {
- if ((Utils.isDirect(newData) == 0) || (Utils.isReadOnly(newData) == 0)) {
- throw new BrotliRuntimeException("newData must be a direct read-only byte buffer");
- }
- // TODO: is that so?
- if (newSizeBits.length > MAX_DICTIONARY_WORD_LENGTH) {
- throw new BrotliRuntimeException(
- "sizeBits length must be at most " + String.valueOf(MAX_DICTIONARY_WORD_LENGTH));
- }
- for (int i = 0; i < MIN_DICTIONARY_WORD_LENGTH; ++i) {
- if (newSizeBits[i] != 0) {
- throw new BrotliRuntimeException(
- "first " + String.valueOf(MIN_DICTIONARY_WORD_LENGTH) + " must be 0");
- }
- }
- final int[] dictionaryOffsets = Dictionary.offsets;
- final int[] dictionarySizeBits = Dictionary.sizeBits;
- System.arraycopy(newSizeBits, 0, dictionarySizeBits, 0, newSizeBits.length);
- int pos = 0;
- final int limit = newData.capacity();
- for (int i = 0; i < newSizeBits.length; ++i) {
- dictionaryOffsets[i] = pos;
- final int bits = dictionarySizeBits[i];
- if (bits != 0) {
- if (bits >= 31) {
- throw new BrotliRuntimeException("newSizeBits values must be less than 31");
- }
- pos += i << bits;
- if (pos <= 0 || pos > limit) {
- throw new BrotliRuntimeException("newSizeBits is inconsistent: overflow");
- }
- }
- }
- for (int i = newSizeBits.length; i < 32; ++i) {
- dictionaryOffsets[i] = pos;
- }
- if (pos != limit) {
- throw new BrotliRuntimeException("newSizeBits is inconsistent: underflow");
- }
- Dictionary.data = newData;
- }
-
- public static ByteBuffer getData() {
- if (data.capacity() != 0) {
- return data;
- }
- if (!DataLoader.OK) {
- throw new BrotliRuntimeException("brotli dictionary is not set");
- }
- /* Might have been set when {@link DictionaryData} was loaded.*/
- return data;
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/DictionaryData.java b/firka/android/app/src/main/java/org/brotli/dec/DictionaryData.java
deleted file mode 100644
index ad96f38e..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/DictionaryData.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.nio.ByteBuffer;
-
-/**
- * Built-in dictionary data.
- *
- * When this class is loaded, it sets its data: {@link Dictionary#setData(ByteBuffer)}.
- */
-final class DictionaryData {
- private static final String DATA0 = "wjnfgltmojefofewab`h`lgfgbwbpkltlmozpjwf`jwzlsfmivpwojhfeqfftlqhwf{wzfbqlufqalgzolufelqnallhsobzojufojmfkfosklnfpjgfnlqftlqgolmdwkfnujftejmgsbdfgbzpevookfbgwfqnfb`kbqfbeqlnwqvfnbqhbaofvslmkjdkgbwfobmgmftpfufmmf{w`bpfalwkslpwvpfgnbgfkbmgkfqftkbwmbnfOjmhaoldpjyfabpfkfognbhfnbjmvpfq$*#(klogfmgptjwkMftpqfbgtfqfpjdmwbhfkbufdbnfpffm`boosbwktfoosovpnfmvejonsbqwiljmwkjpojpwdllgmffgtbzptfpwilapnjmgboploldlqj`kvpfpobpwwfbnbqnzellghjmdtjoofbpwtbqgafpwejqfSbdfhmltbtbz-smdnlufwkbmolbgdjufpfoemlwfnv`keffgnbmzql`hj`lmlm`follhkjgfgjfgKlnfqvofklpwbib{jmel`ovaobtpofppkboeplnfpv`kylmf233&lmfp`bqfWjnfqb`faovfelvqtffheb`fklsfdbufkbqgolpwtkfmsbqhhfswsbpppkjsqllnKWNOsobmWzsfglmfpbufhffseobdojmhplogejufwllhqbwfwltmivnswkvpgbqh`bqgejofefbqpwbzhjoowkbweboobvwlfufq-`lnwbohpklsulwfgffsnlgfqfpwwvqmalqmabmgefooqlpfvqo+phjmqlof`lnfb`wpbdfpnffwdlog-isdjwfnubqzefowwkfmpfmggqlsUjft`lsz2-3!?,b=pwlsfopfojfpwlvqsb`h-djesbpw`pp !2s{#plojg# -dje!#bow>!wqbmpsbqfmwjmelqnbwjlmbssoj`bwjlm!#lm`oj`h>!fpwbaojpkfgbgufqwjpjmd-smd!#bow>!fmujqlmnfmwsfqelqnbm`fbssqlsqjbwf%bns8ngbpk8jnnfgjbwfoz?,pwqlmd=?,qbwkfq#wkbmwfnsfqbwvqfgfufolsnfmw`lnsfwjwjlmsob`fklogfqujpjajojwz9`lszqjdkw!=3!#kfjdkw>!fufm#wklvdkqfsob`fnfmwgfpwjmbwjlm@lqslqbwjlm?vo#`obpp>!Bppl`jbwjlmjmgjujgvbopsfqpsf`wjufpfwWjnflvw+vqo+kwws9,,nbwkfnbwj`pnbqdjm.wls9fufmwvbooz#gfp`qjswjlm*#ml.qfsfbw`loof`wjlmp-ISD\u007Fwkvna\u007Fsbqwj`jsbwf,kfbg=?algzeolbw9ofew8?oj#`obpp>!kvmgqfgp#le\t\tKltfufq/#`lnslpjwjlm`ofbq9alwk8`llsfqbwjlmtjwkjm#wkf#obafo#elq>!alqgfq.wls9Mft#Yfbobmgqf`lnnfmgfgsklwldqbskzjmwfqfpwjmd%ow8pvs%dw8`lmwqlufqpzMfwkfqobmgpbowfqmbwjufnb{ofmdwk>!ptjwyfqobmgGfufolsnfmwfppfmwjbooz\t\tBowklvdk#?,wf{wbqfb=wkvmgfqajqgqfsqfpfmwfg%bns8mgbpk8psf`vobwjlm`lnnvmjwjfpofdjpobwjlmfof`wqlmj`p\t\n?gju#jg>!joovpwqbwfgfmdjmffqjmdwfqqjwlqjfpbvwklqjwjfpgjpwqjavwfg5!#kfjdkw>!pbmp.pfqje8`bsbaof#le#gjpbssfbqfgjmwfqb`wjufollhjmd#elqjw#tlvog#afBedkbmjpwbmtbp#`qfbwfgNbwk-eollq+pvqqlvmgjmd`bm#bopl#aflapfqubwjlmnbjmwfmbm`ffm`lvmwfqfg?k1#`obpp>!nlqf#qf`fmwjw#kbp#affmjmubpjlm#le*-dfwWjnf+*evmgbnfmwboGfpsjwf#wkf!=?gju#jg>!jmpsjqbwjlmf{bnjmbwjlmsqfsbqbwjlmf{sobmbwjlm?jmsvw#jg>!?,b=?,psbm=ufqpjlmp#lejmpwqvnfmwpafelqf#wkf##>#$kwws9,,Gfp`qjswjlmqfobwjufoz#-pvapwqjmd+fb`k#le#wkff{sfqjnfmwpjmeovfmwjbojmwfdqbwjlmnbmz#sflsofgvf#wl#wkf#`lnajmbwjlmgl#mlw#kbufNjggof#Fbpw?mlp`qjsw=?`lszqjdkw!#sfqkbsp#wkfjmpwjwvwjlmjm#Gf`fnafqbqqbmdfnfmwnlpw#ebnlvpsfqplmbojwz`qfbwjlm#leojnjwbwjlmpf{`ovpjufozplufqfjdmwz.`lmwfmw!=\t?wg#`obpp>!vmgfqdqlvmgsbqboofo#wlgl`wqjmf#lel``vsjfg#azwfqnjmloldzQfmbjppbm`fb#mvnafq#lepvsslqw#elqf{solqbwjlmqf`ldmjwjlmsqfgf`fpplq?jnd#pq`>!,?k2#`obpp>!svaoj`bwjlmnbz#bopl#afpsf`jbojyfg?,ejfogpfw=sqldqfppjufnjoojlmp#lepwbwfp#wkbwfmelq`fnfmwbqlvmg#wkf#lmf#bmlwkfq-sbqfmwMlgfbdqj`vowvqfBowfqmbwjufqfpfbq`kfqpwltbqgp#wkfNlpw#le#wkfnbmz#lwkfq#+fpsf`jbooz?wg#tjgwk>!8tjgwk9233&jmgfsfmgfmw?k0#`obpp>!#lm`kbmdf>!*-bgg@obpp+jmwfqb`wjlmLmf#le#wkf#gbvdkwfq#leb``fpplqjfpaqbm`kfp#le\u000E\t?gju#jg>!wkf#obqdfpwgf`obqbwjlmqfdvobwjlmpJmelqnbwjlmwqbmpobwjlmgl`vnfmwbqzjm#lqgfq#wl!=\t?kfbg=\t?!#kfjdkw>!2b`qlpp#wkf#lqjfmwbwjlm*8?,p`qjsw=jnsofnfmwfg`bm#af#pffmwkfqf#tbp#bgfnlmpwqbwf`lmwbjmfq!=`lmmf`wjlmpwkf#Aqjwjpktbp#tqjwwfm\"jnslqwbmw8s{8#nbqdjm.elooltfg#azbajojwz#wl#`lnsoj`bwfggvqjmd#wkf#jnnjdqbwjlmbopl#`boofg?k7#`obpp>!gjpwjm`wjlmqfsob`fg#azdlufqmnfmwpol`bwjlm#lejm#Mlufnafqtkfwkfq#wkf?,s=\t?,gju=b`rvjpjwjlm`boofg#wkf#sfqpf`vwjlmgfpjdmbwjlmxelmw.pjyf9bssfbqfg#jmjmufpwjdbwff{sfqjfm`fgnlpw#ojhfoztjgfoz#vpfggjp`vppjlmpsqfpfm`f#le#+gl`vnfmw-f{wfmpjufozJw#kbp#affmjw#glfp#mlw`lmwqbqz#wljmkbajwbmwpjnsqlufnfmwp`klobqpkjs`lmpvnswjlmjmpwqv`wjlmelq#f{bnsoflmf#lq#nlqfs{8#sbggjmdwkf#`vqqfmwb#pfqjfp#lebqf#vpvboozqlof#jm#wkfsqfujlvpoz#gfqjubwjufpfujgfm`f#lef{sfqjfm`fp`lolqp`kfnfpwbwfg#wkbw`fqwjej`bwf?,b=?,gju=\t#pfof`wfg>!kjdk#p`klloqfpslmpf#wl`lnelqwbaofbglswjlm#lewkqff#zfbqpwkf#`lvmwqzjm#Efaqvbqzpl#wkbw#wkfsflsof#tkl#sqlujgfg#az?sbqbn#mbnfbeef`wfg#azjm#wfqnp#lebssljmwnfmwJPL.;;6:.2!tbp#alqm#jmkjpwlqj`bo#qfdbqgfg#bpnfbpvqfnfmwjp#abpfg#lm#bmg#lwkfq#9#evm`wjlm+pjdmjej`bmw`fofaqbwjlmwqbmpnjwwfg,ip,irvfqz-jp#hmltm#bpwkflqfwj`bo#wbajmgf{>!jw#`lvog#af?mlp`qjsw=\tkbujmd#affm\u000E\t?kfbg=\u000E\t?#%rvlw8Wkf#`lnsjobwjlmkf#kbg#affmsqlgv`fg#azskjolplskfq`lmpwqv`wfgjmwfmgfg#wlbnlmd#lwkfq`lnsbqfg#wlwl#pbz#wkbwFmdjmffqjmdb#gjeefqfmwqfefqqfg#wlgjeefqfm`fpafojfe#wkbwsklwldqbskpjgfmwjezjmdKjpwlqz#le#Qfsvaoj`#lemf`fppbqjozsqlabajojwzwf`kmj`boozofbujmd#wkfpsf`wb`vobqeqb`wjlm#lefof`wqj`jwzkfbg#le#wkfqfpwbvqbmwpsbqwmfqpkjsfnskbpjp#lmnlpw#qf`fmwpkbqf#tjwk#pbzjmd#wkbwejoofg#tjwkgfpjdmfg#wljw#jp#lewfm!=?,jeqbnf=bp#elooltp9nfqdfg#tjwkwkqlvdk#wkf`lnnfq`jbo#sljmwfg#lvwlsslqwvmjwzujft#le#wkfqfrvjqfnfmwgjujpjlm#lesqldqbnnjmdkf#qf`fjufgpfwJmwfqubo!=?,psbm=?,jm#Mft#Zlqhbggjwjlmbo#`lnsqfppjlm\t\t?gju#jg>!jm`lqslqbwf8?,p`qjsw=?bwwb`kFufmwaf`bnf#wkf#!#wbqdfw>!\\`bqqjfg#lvwPlnf#le#wkfp`jfm`f#bmgwkf#wjnf#le@lmwbjmfq!=nbjmwbjmjmd@kqjpwlskfqNv`k#le#wkftqjwjmdp#le!#kfjdkw>!1pjyf#le#wkfufqpjlm#le#nj{wvqf#le#afwtffm#wkfF{bnsofp#lefgv`bwjlmbo`lnsfwjwjuf#lmpvanjw>!gjqf`wlq#legjpwjm`wjuf,GWG#[KWNO#qfobwjmd#wlwfmgfm`z#wlsqlujm`f#letkj`k#tlvoggfpsjwf#wkfp`jfmwjej`#ofdjpobwvqf-jmmfqKWNO#boofdbwjlmpBdqj`vowvqftbp#vpfg#jmbssqlb`k#wljmwfoojdfmwzfbqp#obwfq/pbmp.pfqjegfwfqnjmjmdSfqelqnbm`fbssfbqbm`fp/#tkj`k#jp#elvmgbwjlmpbaaqfujbwfgkjdkfq#wkbmp#eqln#wkf#jmgjujgvbo#`lnslpfg#lepvsslpfg#wl`objnp#wkbwbwwqjavwjlmelmw.pjyf92fofnfmwp#leKjpwlqj`bo#kjp#aqlwkfqbw#wkf#wjnfbmmjufqpbqzdlufqmfg#azqfobwfg#wl#vowjnbwfoz#jmmlubwjlmpjw#jp#pwjoo`bm#lmoz#afgfejmjwjlmpwlDNWPwqjmdB#mvnafq#lejnd#`obpp>!Fufmwvbooz/tbp#`kbmdfgl``vqqfg#jmmfjdkalqjmdgjpwjmdvjpktkfm#kf#tbpjmwqlgv`jmdwfqqfpwqjboNbmz#le#wkfbqdvfp#wkbwbm#Bnfqj`bm`lmrvfpw#letjgfpsqfbg#tfqf#hjoofgp`qffm#bmg#Jm#lqgfq#wlf{sf`wfg#wlgfp`fmgbmwpbqf#ol`bwfgofdjpobwjufdfmfqbwjlmp#ab`hdqlvmgnlpw#sflsofzfbqp#bewfqwkfqf#jp#mlwkf#kjdkfpweqfrvfmwoz#wkfz#gl#mlwbqdvfg#wkbwpkltfg#wkbwsqfglnjmbmwwkfloldj`boaz#wkf#wjnf`lmpjgfqjmdpklqw.ojufg?,psbm=?,b=`bm#af#vpfgufqz#ojwwoflmf#le#wkf#kbg#boqfbgzjmwfqsqfwfg`lnnvmj`bwfefbwvqfp#ledlufqmnfmw/?,mlp`qjsw=fmwfqfg#wkf!#kfjdkw>!0Jmgfsfmgfmwslsvobwjlmpobqdf.p`bof-#Bowklvdk#vpfg#jm#wkfgfpwqv`wjlmslppjajojwzpwbqwjmd#jmwtl#lq#nlqff{sqfppjlmppvalqgjmbwfobqdfq#wkbmkjpwlqz#bmg?,lswjlm=\u000E\t@lmwjmfmwbofojnjmbwjmdtjoo#mlw#afsqb`wj`f#lejm#eqlmw#lepjwf#le#wkffmpvqf#wkbwwl#`qfbwf#bnjppjppjssjslwfmwjboozlvwpwbmgjmdafwwfq#wkbmtkbw#jp#mltpjwvbwfg#jmnfwb#mbnf>!WqbgjwjlmbopvddfpwjlmpWqbmpobwjlmwkf#elqn#lebwnlpskfqj`jgfloldj`bofmwfqsqjpfp`bo`vobwjmdfbpw#le#wkfqfnmbmwp#lesovdjmpsbdf,jmgf{-sks #evm`wjlm+*-isd!#tjgwk>!`lmejdvqbwjlm-smd!#tjgwk>!?algz#`obpp>!Nbwk-qbmgln+*`lmwfnslqbqz#Vmjwfg#Pwbwfp`jq`vnpwbm`fp-bssfmg@kjog+lqdbmjybwjlmp?psbm#`obpp>!!=?jnd#pq`>!,gjpwjmdvjpkfgwklvpbmgp#le#`lnnvmj`bwjlm`ofbq!=?,gju=jmufpwjdbwjlmebuj`lm-j`l!#nbqdjm.qjdkw9abpfg#lm#wkf#Nbppb`kvpfwwpwbaof#alqgfq>jmwfqmbwjlmbobopl#hmltm#bpsqlmvm`jbwjlmab`hdqlvmg9 esbggjmd.ofew9Elq#f{bnsof/#njp`foobmflvp%ow8,nbwk%dw8spz`kloldj`bojm#sbqwj`vobqfbq`k!#wzsf>!elqn#nfwklg>!bp#lsslpfg#wlPvsqfnf#@lvqwl``bpjlmbooz#Bggjwjlmbooz/Mlqwk#Bnfqj`bs{8ab`hdqlvmglsslqwvmjwjfpFmwfqwbjmnfmw-wlOltfq@bpf+nbmveb`wvqjmdsqlefppjlmbo#`lnajmfg#tjwkElq#jmpwbm`f/`lmpjpwjmd#le!#nb{ofmdwk>!qfwvqm#ebopf8`lmp`jlvpmfppNfgjwfqqbmfbmf{wqblqgjmbqzbppbppjmbwjlmpvapfrvfmwoz#avwwlm#wzsf>!wkf#mvnafq#lewkf#lqjdjmbo#`lnsqfkfmpjufqfefqp#wl#wkf?,vo=\t?,gju=\tskjolplskj`bool`bwjlm-kqfetbp#svaojpkfgPbm#Eqbm`jp`l+evm`wjlm+*x\t?gju#jg>!nbjmplskjpwj`bwfgnbwkfnbwj`bo#,kfbg=\u000E\t?algzpvddfpwp#wkbwgl`vnfmwbwjlm`lm`fmwqbwjlmqfobwjlmpkjspnbz#kbuf#affm+elq#f{bnsof/Wkjp#bqwj`of#jm#plnf#`bpfpsbqwp#le#wkf#gfejmjwjlm#leDqfbw#Aqjwbjm#`foosbggjmd>frvjubofmw#wlsob`fklogfq>!8#elmw.pjyf9#ivpwjej`bwjlmafojfufg#wkbwpveefqfg#eqlnbwwfnswfg#wl#ofbgfq#le#wkf`qjsw!#pq`>!,+evm`wjlm+*#xbqf#bubjobaof\t\n?ojmh#qfo>!#pq`>$kwws9,,jmwfqfpwfg#jm`lmufmwjlmbo#!#bow>!!#,=?,bqf#dfmfqboozkbp#bopl#affmnlpw#slsvobq#`lqqfpslmgjmd`qfgjwfg#tjwkwzof>!alqgfq9?,b=?,psbm=?,-dje!#tjgwk>!?jeqbnf#pq`>!wbaof#`obpp>!jmojmf.aol`h8b``lqgjmd#wl#wldfwkfq#tjwkbssql{jnbwfozsbqojbnfmwbqznlqf#bmg#nlqfgjpsobz9mlmf8wqbgjwjlmboozsqfglnjmbmwoz%maps8\u007F%maps8%maps8?,psbm=#`foopsb`jmd>?jmsvw#mbnf>!lq!#`lmwfmw>!`lmwqlufqpjbosqlsfqwz>!ld9,{.pkl`htbuf.gfnlmpwqbwjlmpvqqlvmgfg#azMfufqwkfofpp/tbp#wkf#ejqpw`lmpjgfqbaof#Bowklvdk#wkf#`loobalqbwjlmpklvog#mlw#afsqlslqwjlm#le?psbm#pwzof>!hmltm#bp#wkf#pklqwoz#bewfqelq#jmpwbm`f/gfp`qjafg#bp#,kfbg=\t?algz#pwbqwjmd#tjwkjm`qfbpjmdoz#wkf#eb`w#wkbwgjp`vppjlm#lenjggof#le#wkfbm#jmgjujgvbogjeej`vow#wl#sljmw#le#ujftklnlpf{vbojwzb``fswbm`f#le?,psbm=?,gju=nbmveb`wvqfqplqjdjm#le#wkf`lnnlmoz#vpfgjnslqwbm`f#legfmlnjmbwjlmpab`hdqlvmg9# ofmdwk#le#wkfgfwfqnjmbwjlmb#pjdmjej`bmw!#alqgfq>!3!=qfulovwjlmbqzsqjm`jsofp#lejp#`lmpjgfqfgtbp#gfufolsfgJmgl.Fvqlsfbmuvomfqbaof#wlsqlslmfmwp#lebqf#plnfwjnfp`olpfq#wl#wkfMft#Zlqh#@jwz#mbnf>!pfbq`kbwwqjavwfg#wl`lvqpf#le#wkfnbwkfnbwj`jbmaz#wkf#fmg#lebw#wkf#fmg#le!#alqgfq>!3!#wf`kmloldj`bo-qfnluf@obpp+aqbm`k#le#wkffujgfm`f#wkbw\"Xfmgje^..=\u000E\tJmpwjwvwf#le#jmwl#b#pjmdofqfpsf`wjufoz-bmg#wkfqfelqfsqlsfqwjfp#lejp#ol`bwfg#jmplnf#le#tkj`kWkfqf#jp#bopl`lmwjmvfg#wl#bssfbqbm`f#le#%bns8mgbpk8#gfp`qjafp#wkf`lmpjgfqbwjlmbvwklq#le#wkfjmgfsfmgfmwozfrvjssfg#tjwkglfp#mlw#kbuf?,b=?b#kqfe>!`lmevpfg#tjwk?ojmh#kqfe>!,bw#wkf#bdf#lebssfbq#jm#wkfWkfpf#jm`ovgfqfdbqgofpp#le`lvog#af#vpfg#pwzof>%rvlw8pfufqbo#wjnfpqfsqfpfmw#wkfalgz=\t?,kwno=wklvdkw#wl#afslsvobwjlm#leslppjajojwjfpsfq`fmwbdf#leb``fpp#wl#wkfbm#bwwfnsw#wlsqlgv`wjlm#leirvfqz,irvfqzwtl#gjeefqfmwafolmd#wl#wkffpwbaojpknfmwqfsob`jmd#wkfgfp`qjswjlm!#gfwfqnjmf#wkfbubjobaof#elqB``lqgjmd#wl#tjgf#qbmdf#le\n?gju#`obpp>!nlqf#`lnnlmozlqdbmjpbwjlmpevm`wjlmbojwztbp#`lnsofwfg#%bns8ngbpk8#sbqwj`jsbwjlmwkf#`kbqb`wfqbm#bggjwjlmbobssfbqp#wl#afeb`w#wkbw#wkfbm#f{bnsof#lepjdmjej`bmwozlmnlvpflufq>!af`bvpf#wkfz#bpzm`#>#wqvf8sqlaofnp#tjwkpffnp#wl#kbufwkf#qfpvow#le#pq`>!kwws9,,ebnjojbq#tjwkslppfppjlm#leevm`wjlm#+*#xwllh#sob`f#jmbmg#plnfwjnfppvapwbmwjbooz?psbm=?,psbm=jp#lewfm#vpfgjm#bm#bwwfnswdqfbw#gfbo#leFmujqlmnfmwbopv``fppevooz#ujqwvbooz#boo13wk#`fmwvqz/sqlefppjlmbopmf`fppbqz#wl#gfwfqnjmfg#az`lnsbwjajojwzaf`bvpf#jw#jpGj`wjlmbqz#lenlgjej`bwjlmpWkf#elooltjmdnbz#qfefq#wl9@lmpfrvfmwoz/Jmwfqmbwjlmbobowklvdk#plnfwkbw#tlvog#aftlqog$p#ejqpw`obppjejfg#bpalwwln#le#wkf+sbqwj`vobqozbojdm>!ofew!#nlpw#`lnnlmozabpjp#elq#wkfelvmgbwjlm#le`lmwqjavwjlmpslsvobqjwz#le`fmwfq#le#wkfwl#qfgv`f#wkfivqjpgj`wjlmpbssql{jnbwjlm#lmnlvpflvw>!Mft#Wfpwbnfmw`loof`wjlm#le?,psbm=?,b=?,jm#wkf#Vmjwfgejon#gjqf`wlq.pwqj`w-gwg!=kbp#affm#vpfgqfwvqm#wl#wkfbowklvdk#wkjp`kbmdf#jm#wkfpfufqbo#lwkfqavw#wkfqf#bqfvmsqf`fgfmwfgjp#pjnjobq#wlfpsf`jbooz#jmtfjdkw9#alog8jp#`boofg#wkf`lnsvwbwjlmbojmgj`bwf#wkbwqfpwqj`wfg#wl\n?nfwb#mbnf>!bqf#wzsj`booz`lmeoj`w#tjwkKltfufq/#wkf#Bm#f{bnsof#le`lnsbqfg#tjwkrvbmwjwjfp#leqbwkfq#wkbm#b`lmpwfoobwjlmmf`fppbqz#elqqfslqwfg#wkbwpsf`jej`bwjlmslojwj`bo#bmg%maps8%maps8?qfefqfm`fp#wlwkf#pbnf#zfbqDlufqmnfmw#ledfmfqbwjlm#lekbuf#mlw#affmpfufqbo#zfbqp`lnnjwnfmw#wl\n\n?vo#`obpp>!ujpvbojybwjlm2:wk#`fmwvqz/sqb`wjwjlmfqpwkbw#kf#tlvogbmg#`lmwjmvfgl``vsbwjlm#lejp#gfejmfg#bp`fmwqf#le#wkfwkf#bnlvmw#le=?gju#pwzof>!frvjubofmw#legjeefqfmwjbwfaqlvdkw#balvwnbqdjm.ofew9#bvwlnbwj`boozwklvdkw#le#bpPlnf#le#wkfpf\t?gju#`obpp>!jmsvw#`obpp>!qfsob`fg#tjwkjp#lmf#le#wkffgv`bwjlm#bmgjmeovfm`fg#azqfsvwbwjlm#bp\t?nfwb#mbnf>!b``lnnlgbwjlm?,gju=\t?,gju=obqdf#sbqw#leJmpwjwvwf#elqwkf#pl.`boofg#bdbjmpw#wkf#Jm#wkjp#`bpf/tbp#bssljmwfg`objnfg#wl#afKltfufq/#wkjpGfsbqwnfmw#lewkf#qfnbjmjmdfeef`w#lm#wkfsbqwj`vobqoz#gfbo#tjwk#wkf\t?gju#pwzof>!bonlpw#botbzpbqf#`vqqfmwozf{sqfppjlm#leskjolplskz#leelq#nlqf#wkbm`jujojybwjlmplm#wkf#jpobmgpfof`wfgJmgf{`bm#qfpvow#jm!#ubovf>!!#,=wkf#pwqv`wvqf#,=?,b=?,gju=Nbmz#le#wkfpf`bvpfg#az#wkfle#wkf#Vmjwfgpsbm#`obpp>!n`bm#af#wqb`fgjp#qfobwfg#wlaf`bnf#lmf#lejp#eqfrvfmwozojujmd#jm#wkfwkflqfwj`boozElooltjmd#wkfQfulovwjlmbqzdlufqmnfmw#jmjp#gfwfqnjmfgwkf#slojwj`bojmwqlgv`fg#jmpveej`jfmw#wlgfp`qjswjlm!=pklqw#pwlqjfppfsbqbwjlm#lebp#wl#tkfwkfqhmltm#elq#jwptbp#jmjwjboozgjpsobz9aol`hjp#bm#f{bnsofwkf#sqjm`jsbo`lmpjpwp#le#bqf`ldmjyfg#bp,algz=?,kwno=b#pvapwbmwjboqf`lmpwqv`wfgkfbg#le#pwbwfqfpjpwbm`f#wlvmgfqdqbgvbwfWkfqf#bqf#wtldqbujwbwjlmbobqf#gfp`qjafgjmwfmwjlmboozpfqufg#bp#wkf`obpp>!kfbgfqlsslpjwjlm#wlevmgbnfmwboozglnjmbwfg#wkfbmg#wkf#lwkfqboojbm`f#tjwktbp#elq`fg#wlqfpsf`wjufoz/bmg#slojwj`bojm#pvsslqw#lesflsof#jm#wkf13wk#`fmwvqz-bmg#svaojpkfgolbg@kbqwafbwwl#vmgfqpwbmgnfnafq#pwbwfpfmujqlmnfmwboejqpw#kboe#le`lvmwqjfp#bmgbq`kjwf`wvqboaf#`lmpjgfqfg`kbqb`wfqjyfg`ofbqJmwfqubobvwklqjwbwjufEfgfqbwjlm#letbp#pv``ffgfgbmg#wkfqf#bqfb#`lmpfrvfm`fwkf#Sqfpjgfmwbopl#jm`ovgfgeqff#plewtbqfpv``fppjlm#legfufolsfg#wkftbp#gfpwqlzfgbtbz#eqln#wkf8\t?,p`qjsw=\t?bowklvdk#wkfzelooltfg#az#bnlqf#sltfqevoqfpvowfg#jm#bVmjufqpjwz#leKltfufq/#nbmzwkf#sqfpjgfmwKltfufq/#plnfjp#wklvdkw#wlvmwjo#wkf#fmgtbp#bmmlvm`fgbqf#jnslqwbmwbopl#jm`ovgfp=?jmsvw#wzsf>wkf#`fmwfq#le#GL#MLW#BOWFQvpfg#wl#qfefqwkfnfp, Assumes that end is an integer multiple of step.
- */
- private static void replicateValue(int[] table, int offset, int step, int end, int item) {
- do {
- end -= step;
- table[offset + end] = item;
- } while (end > 0);
- }
-
- /**
- * @param count histogram of bit lengths for the remaining symbols,
- * @param len code length of the next processed symbol.
- * @return table width of the next 2nd level table.
- */
- private static int nextTableBitSize(int[] count, int len, int rootBits) {
- int left = 1 << (len - rootBits);
- while (len < MAX_LENGTH) {
- left -= count[len];
- if (left <= 0) {
- break;
- }
- len++;
- left <<= 1;
- }
- return len - rootBits;
- }
-
- /**
- * Builds Huffman lookup table assuming code lengths are in symbol order.
- *
- * @return number of slots used by resulting Huffman table
- */
- static int buildHuffmanTable(int[] tableGroup, int tableIdx, int rootBits, int[] codeLengths,
- int codeLengthsSize) {
- final int tableOffset = tableGroup[tableIdx];
- int key; // Reversed prefix code.
- final int[] sorted = new int[codeLengthsSize]; // Symbols sorted by code length.
- // TODO(eustas): fill with zeroes?
- final int[] count = new int[MAX_LENGTH + 1]; // Number of codes of each length.
- final int[] offset = new int[MAX_LENGTH + 1]; // Offsets in sorted table for each length.
- int symbol;
-
- // Build histogram of code lengths.
- for (symbol = 0; symbol < codeLengthsSize; symbol++) {
- count[codeLengths[symbol]]++;
- }
-
- // Generate offsets into sorted symbol table by code length.
- offset[1] = 0;
- for (int len = 1; len < MAX_LENGTH; len++) {
- offset[len + 1] = offset[len] + count[len];
- }
-
- // Sort symbols by length, by symbol order within each length.
- for (symbol = 0; symbol < codeLengthsSize; symbol++) {
- if (codeLengths[symbol] != 0) {
- sorted[offset[codeLengths[symbol]]++] = symbol;
- }
- }
-
- int tableBits = rootBits;
- int tableSize = 1 << tableBits;
- int totalSize = tableSize;
-
- // Special case code with only one value.
- if (offset[MAX_LENGTH] == 1) {
- for (key = 0; key < totalSize; key++) {
- tableGroup[tableOffset + key] = sorted[0];
- }
- return totalSize;
- }
-
- // Fill in root table.
- key = 0;
- symbol = 0;
- for (int len = 1, step = 2; len <= rootBits; len++, step <<= 1) {
- for (; count[len] > 0; count[len]--) {
- replicateValue(tableGroup, tableOffset + key, step, tableSize,
- len << 16 | sorted[symbol++]);
- key = getNextKey(key, len);
- }
- }
-
- // Fill in 2nd level tables and add pointers to root table.
- final int mask = totalSize - 1;
- int low = -1;
- int currentOffset = tableOffset;
- for (int len = rootBits + 1, step = 2; len <= MAX_LENGTH; len++, step <<= 1) {
- for (; count[len] > 0; count[len]--) {
- if ((key & mask) != low) {
- currentOffset += tableSize;
- tableBits = nextTableBitSize(count, len, rootBits);
- tableSize = 1 << tableBits;
- totalSize += tableSize;
- low = key & mask;
- tableGroup[tableOffset + low] =
- (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);
- }
- replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize,
- (len - rootBits) << 16 | sorted[symbol++]);
- key = getNextKey(key, len);
- }
- }
- return totalSize;
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/State.java b/firka/android/app/src/main/java/org/brotli/dec/State.java
deleted file mode 100644
index 94db93ab..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/State.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.InputStream;
-
-final class State {
- byte[] ringBuffer;
- byte[] contextModes;
- byte[] contextMap;
- byte[] distContextMap;
- byte[] distExtraBits;
- byte[] output;
- byte[] byteBuffer; // BitReader
-
- short[] shortBuffer; // BitReader
-
- int[] intBuffer; // BitReader
- int[] rings;
- int[] blockTrees;
- int[] literalTreeGroup;
- int[] commandTreeGroup;
- int[] distanceTreeGroup;
- int[] distOffset;
-
- long accumulator64; // BitReader: pre-fetched bits.
-
- int runningState; // Default value is 0 == Decode.UNINITIALIZED
- int nextRunningState;
- int accumulator32; // BitReader: pre-fetched bits.
- int bitOffset; // BitReader: bit-reading position in accumulator.
- int halfOffset; // BitReader: offset of next item in intBuffer/shortBuffer.
- int tailBytes; // BitReader: number of bytes in unfinished half.
- int endOfStreamReached; // BitReader: input stream is finished.
- int metaBlockLength;
- int inputEnd;
- int isUncompressed;
- int isMetadata;
- int literalBlockLength;
- int numLiteralBlockTypes;
- int commandBlockLength;
- int numCommandBlockTypes;
- int distanceBlockLength;
- int numDistanceBlockTypes;
- int pos;
- int maxDistance;
- int distRbIdx;
- int trivialLiteralContext;
- int literalTreeIdx;
- int commandTreeIdx;
- int j;
- int insertLength;
- int contextMapSlice;
- int distContextMapSlice;
- int contextLookupOffset1;
- int contextLookupOffset2;
- int distanceCode;
- int numDirectDistanceCodes;
- int distancePostfixBits;
- int distance;
- int copyLength;
- int maxBackwardDistance;
- int maxRingBufferSize;
- int ringBufferSize;
- int expectedTotalSize;
- int outputOffset;
- int outputLength;
- int outputUsed;
- int ringBufferBytesWritten;
- int ringBufferBytesReady;
- int isEager;
- int isLargeWindow;
-
- // Compound dictionary
- int cdNumChunks;
- int cdTotalSize;
- int cdBrIndex;
- int cdBrOffset;
- int cdBrLength;
- int cdBrCopied;
- byte[][] cdChunks;
- int[] cdChunkOffsets;
- int cdBlockBits;
- byte[] cdBlockMap;
-
- InputStream /* @Nullable */ input; // BitReader
-
- State() {
- this.ringBuffer = new byte[0];
- this.rings = new int[10];
- this.rings[0] = 16;
- this.rings[1] = 15;
- this.rings[2] = 11;
- this.rings[3] = 4;
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/Transform.java b/firka/android/app/src/main/java/org/brotli/dec/Transform.java
deleted file mode 100644
index 6a57a9ec..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/Transform.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.nio.ByteBuffer;
-
-/**
- * Transformations on dictionary words.
- *
- * Transform descriptor is a triplet: {prefix, operator, suffix}.
- * "prefix" and "suffix" are short strings inserted before and after transformed dictionary word.
- * "operator" is applied to dictionary word itself.
- *
- * Some operators has "built-in" parameters, i.e. parameter is defined by operator ordinal. Other
- * operators have "external" parameters, supplied via additional table encoded in shared dictionary.
- *
- * Operators:
- * - IDENTITY (0): dictionary word is inserted "as is"
- * - OMIT_LAST_N (1 - 9): last N octets of dictionary word are not inserted; N == ordinal
- * - OMIT_FIRST_M (12-20): first M octets of dictionary word are not inserted; M == ordinal - 11
- * - UPPERCASE_FIRST (10): first "scalar" is XOR'ed with number 32
- * - UPPERCASE_ALL (11): all "scalars" are XOR'ed with number 32
- * - SHIFT_FIRST (21): first "scalar" is shifted by number form parameter table
- * - SHIFT_ALL (22): all "scalar" is shifted by number form parameter table
- *
- * Here "scalar" is a variable length character coding similar to UTF-8 encoding.
- * UPPERCASE_XXX / SHIFT_XXX operators were designed to change the case of UTF-8 encoded characters.
- * While UPPERCASE_XXX works well only on ASCII charset, SHIFT is much more generic and could be
- * used for most (all?) alphabets.
- */
-final class Transform {
-
- static final class Transforms {
- final int numTransforms;
- final int[] triplets;
- final byte[] prefixSuffixStorage;
- final int[] prefixSuffixHeads;
- final short[] params;
-
- Transforms(int numTransforms, int prefixSuffixLen, int prefixSuffixCount) {
- this.numTransforms = numTransforms;
- this.triplets = new int[numTransforms * 3];
- this.params = new short[numTransforms];
- this.prefixSuffixStorage = new byte[prefixSuffixLen];
- this.prefixSuffixHeads = new int[prefixSuffixCount + 1];
- }
- }
-
- static final int NUM_RFC_TRANSFORMS = 121;
- static final Transforms RFC_TRANSFORMS = new Transforms(NUM_RFC_TRANSFORMS, 167, 50);
-
- private static final int OMIT_FIRST_LAST_LIMIT = 9;
-
- private static final int IDENTITY = 0;
- private static final int OMIT_LAST_BASE = IDENTITY + 1 - 1; // there is no OMIT_LAST_0.
- private static final int UPPERCASE_FIRST = OMIT_LAST_BASE + OMIT_FIRST_LAST_LIMIT + 1;
- private static final int UPPERCASE_ALL = UPPERCASE_FIRST + 1;
- private static final int OMIT_FIRST_BASE = UPPERCASE_ALL + 1 - 1; // there is no OMIT_FIRST_0.
- private static final int SHIFT_FIRST = OMIT_FIRST_BASE + OMIT_FIRST_LAST_LIMIT + 1;
- private static final int SHIFT_ALL = SHIFT_FIRST + 1;
-
- // Bundle of 0-terminated strings.
- private static final String PREFIX_SUFFIX_SRC = "# #s #, #e #.# the #.com/#\u00C2\u00A0# of # and"
- + " # in # to #\"#\">#\n#]# for # a # that #. # with #'# from # by #. The # on # as # is #ing"
- + " #\n\t#:#ed #(# at #ly #=\"# of the #. This #,# not #er #al #='#ful #ive #less #est #ize #"
- + "ous #";
- private static final String TRANSFORMS_SRC = " !! ! , *! &! \" ! ) * * - ! # ! #!*! "
- + "+ ,$ ! - % . / # 0 1 . \" 2 3!* 4% ! # / 5 6 7 8 0 1 & $ 9 + : "
- + " ; < ' != > ?! 4 @ 4 2 & A *# ( B C& ) % ) !*# *-% A +! *. D! %' & E *6 F "
- + " G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D "
- + " Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K";
-
- private static void unpackTransforms(byte[] prefixSuffix,
- int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) {
- final int n = prefixSuffixSrc.length();
- int index = 1;
- int j = 0;
- for (int i = 0; i < n; ++i) {
- final char c = prefixSuffixSrc.charAt(i);
- if (c == 35) { // == #
- prefixSuffixHeads[index++] = j;
- } else {
- prefixSuffix[j++] = (byte) c;
- }
- }
-
- for (int i = 0; i < NUM_RFC_TRANSFORMS * 3; ++i) {
- transforms[i] = transformsSrc.charAt(i) - 32;
- }
- }
-
- static {
- unpackTransforms(RFC_TRANSFORMS.prefixSuffixStorage, RFC_TRANSFORMS.prefixSuffixHeads,
- RFC_TRANSFORMS.triplets, PREFIX_SUFFIX_SRC, TRANSFORMS_SRC);
- }
-
- static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset,
- int len, Transforms transforms, int transformIndex) {
- int offset = dstOffset;
- final int[] triplets = transforms.triplets;
- final byte[] prefixSuffixStorage = transforms.prefixSuffixStorage;
- final int[] prefixSuffixHeads = transforms.prefixSuffixHeads;
- final int transformOffset = 3 * transformIndex;
- final int prefixIdx = triplets[transformOffset];
- final int transformType = triplets[transformOffset + 1];
- final int suffixIdx = triplets[transformOffset + 2];
- int prefix = prefixSuffixHeads[prefixIdx];
- final int prefixEnd = prefixSuffixHeads[prefixIdx + 1];
- int suffix = prefixSuffixHeads[suffixIdx];
- final int suffixEnd = prefixSuffixHeads[suffixIdx + 1];
-
- int omitFirst = transformType - OMIT_FIRST_BASE;
- int omitLast = transformType - OMIT_LAST_BASE;
- if (omitFirst < 1 || omitFirst > OMIT_FIRST_LAST_LIMIT) {
- omitFirst = 0;
- }
- if (omitLast < 1 || omitLast > OMIT_FIRST_LAST_LIMIT) {
- omitLast = 0;
- }
-
- // Copy prefix.
- while (prefix != prefixEnd) {
- dst[offset++] = prefixSuffixStorage[prefix++];
- }
-
- // Copy trimmed word.
- if (omitFirst > len) {
- omitFirst = len;
- }
- srcOffset += omitFirst;
- len -= omitFirst;
- len -= omitLast;
- int i = len;
- while (i > 0) {
- dst[offset++] = src.get(srcOffset++);
- i--;
- }
-
- // Ferment.
- if (transformType == UPPERCASE_FIRST || transformType == UPPERCASE_ALL) {
- int uppercaseOffset = offset - len;
- if (transformType == UPPERCASE_FIRST) {
- len = 1;
- }
- while (len > 0) {
- final int c0 = dst[uppercaseOffset] & 0xFF;
- if (c0 < 0xC0) {
- if (c0 >= 97 && c0 <= 122) { // in [a..z] range
- dst[uppercaseOffset] ^= (byte) 32;
- }
- uppercaseOffset += 1;
- len -= 1;
- } else if (c0 < 0xE0) {
- dst[uppercaseOffset + 1] ^= (byte) 32;
- uppercaseOffset += 2;
- len -= 2;
- } else {
- dst[uppercaseOffset + 2] ^= (byte) 5;
- uppercaseOffset += 3;
- len -= 3;
- }
- }
- } else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) {
- int shiftOffset = offset - len;
- final short param = transforms.params[transformIndex];
- /* Limited sign extension: scalar < (1 << 24). */
- int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000));
- while (len > 0) {
- int step = 1;
- final int c0 = dst[shiftOffset] & 0xFF;
- if (c0 < 0x80) {
- /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
- scalar += c0;
- dst[shiftOffset] = (byte) (scalar & 0x7F);
- } else if (c0 < 0xC0) {
- /* Continuation / 10AAAAAA. */
- } else if (c0 < 0xE0) {
- /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
- if (len >= 2) {
- final byte c1 = dst[shiftOffset + 1];
- scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
- dst[shiftOffset] = (byte) (0xC0 | ((scalar >> 6) & 0x1F));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | (scalar & 0x3F));
- step = 2;
- } else {
- step = len;
- }
- } else if (c0 < 0xF0) {
- /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
- if (len >= 3) {
- final byte c1 = dst[shiftOffset + 1];
- final byte c2 = dst[shiftOffset + 2];
- scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
- dst[shiftOffset] = (byte) (0xE0 | ((scalar >> 12) & 0x0F));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
- dst[shiftOffset + 2] = (byte) ((c2 & 0xC0) | (scalar & 0x3F));
- step = 3;
- } else {
- step = len;
- }
- } else if (c0 < 0xF8) {
- /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
- if (len >= 4) {
- final byte c1 = dst[shiftOffset + 1];
- final byte c2 = dst[shiftOffset + 2];
- final byte c3 = dst[shiftOffset + 3];
- scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
- dst[shiftOffset] = (byte) (0xF0 | ((scalar >> 18) & 0x07));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));
- dst[shiftOffset + 2] = (byte) ((c2 & 0xC0) | ((scalar >> 6) & 0x3F));
- dst[shiftOffset + 3] = (byte) ((c3 & 0xC0) | (scalar & 0x3F));
- step = 4;
- } else {
- step = len;
- }
- }
- shiftOffset += step;
- len -= step;
- if (transformType == SHIFT_FIRST) {
- len = 0;
- }
- }
- }
-
- // Copy suffix.
- while (suffix != suffixEnd) {
- dst[offset++] = prefixSuffixStorage[suffix++];
- }
-
- return offset - dstOffset;
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/dec/Utils.java b/firka/android/app/src/main/java/org/brotli/dec/Utils.java
deleted file mode 100644
index cc4a9f0d..00000000
--- a/firka/android/app/src/main/java/org/brotli/dec/Utils.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-
-/**
- * A set of utility methods.
- */
-final class Utils {
-
- private static final byte[] BYTE_ZEROES = new byte[1024];
-
- private static final int[] INT_ZEROES = new int[1024];
-
- /**
- * Fills byte array with zeroes.
- *
- * Current implementation uses {@link System#arraycopy}, so it should be used for length not
- * less than 16.
- *
- * @param dest array to fill with zeroes
- * @param offset the first byte to fill
- * @param length number of bytes to change
- */
- static void fillBytesWithZeroes(byte[] dest, int start, int end) {
- int cursor = start;
- while (cursor < end) {
- int step = Math.min(cursor + 1024, end) - cursor;
- System.arraycopy(BYTE_ZEROES, 0, dest, cursor, step);
- cursor += step;
- }
- }
-
- /**
- * Fills int array with zeroes.
- *
- * Current implementation uses {@link System#arraycopy}, so it should be used for length not
- * less than 16.
- *
- * @param dest array to fill with zeroes
- * @param offset the first item to fill
- * @param length number of item to change
- */
- static void fillIntsWithZeroes(int[] dest, int start, int end) {
- int cursor = start;
- while (cursor < end) {
- int step = Math.min(cursor + 1024, end) - cursor;
- System.arraycopy(INT_ZEROES, 0, dest, cursor, step);
- cursor += step;
- }
- }
-
- static void copyBytes(byte[] dst, int target, byte[] src, int start, int end) {
- System.arraycopy(src, start, dst, target, end - start);
- }
-
- static void copyBytesWithin(byte[] bytes, int target, int start, int end) {
- System.arraycopy(bytes, start, bytes, target, end - start);
- }
-
- static int readInput(InputStream src, byte[] dst, int offset, int length) {
- try {
- return src.read(dst, offset, length);
- } catch (IOException e) {
- throw new BrotliRuntimeException("Failed to read input", e);
- }
- }
-
- static void closeInput(InputStream src) throws IOException {
- src.close();
- }
-
- static byte[] toUsAsciiBytes(String src) {
- try {
- // NB: String#getBytes(String) is present in JDK 1.1, while other variants require JDK 1.6 and
- // above.
- return src.getBytes("US-ASCII");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // cannot happen
- }
- }
-
- static ByteBuffer asReadOnlyBuffer(ByteBuffer src) {
- return src.asReadOnlyBuffer();
- }
-
- static int isReadOnly(ByteBuffer src) {
- return src.isReadOnly() ? 1 : 0;
- }
-
- static int isDirect(ByteBuffer src) {
- return src.isDirect() ? 1 : 0;
- }
-
- // Crazy pills factory: code compiled for JDK8 does not work on JRE9.
- static void flipBuffer(Buffer buffer) {
- buffer.flip();
- }
-
- static int isDebugMode() {
- boolean assertsEnabled = Boolean.parseBoolean(System.getProperty("BROTLI_ENABLE_ASSERTS"));
- return assertsEnabled ? 1 : 0;
- }
-
- // See BitReader.LOG_BITNESS
- static int getLogBintness() {
- boolean isLongExpensive = Boolean.parseBoolean(System.getProperty("BROTLI_32_BIT_CPU"));
- return isLongExpensive ? 5 : 6;
- }
-}
diff --git a/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java b/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java
deleted file mode 100644
index 51978015..00000000
--- a/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Copyright 2018 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.enc;
-
-import java.nio.ByteBuffer;
-
-/**
- * Prepared dictionary data provider.
- */
-public interface PreparedDictionary {
- ByteBuffer getData();
-}
diff --git a/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java b/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java
deleted file mode 100644
index 3813429c..00000000
--- a/firka/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Copyright 2017 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.enc;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
-
-/**
- * Java prepared (raw) dictionary producer.
- */
-public class PreparedDictionaryGenerator {
-
- private static final int MAGIC = 0xDEBCEDE0;
- private static final long HASH_MULTIPLIER = 0x1fe35a7bd3579bd3L;
-
- private static class PreparedDictionaryImpl implements PreparedDictionary {
- private final ByteBuffer data;
-
- private PreparedDictionaryImpl(ByteBuffer data) {
- this.data = data;
- }
-
- @Override
- public ByteBuffer getData() {
- return data;
- }
- }
-
- // Disallow instantiation.
- private PreparedDictionaryGenerator() { }
-
- public static PreparedDictionary generate(ByteBuffer src) {
- return generate(src, 17, 3, 40, 5);
- }
-
- public static PreparedDictionary generate(ByteBuffer src,
- int bucketBits, int slotBits, int hashBits, int blockBits) {
- ((Buffer) src).clear(); // Just in case...
- if (blockBits > 12) {
- throw new IllegalArgumentException("blockBits is too big");
- }
- if (bucketBits >= 24) {
- throw new IllegalArgumentException("bucketBits is too big");
- }
- if (bucketBits - slotBits >= 16) {
- throw new IllegalArgumentException("slotBits is too small");
- }
- int bucketLimit = 1 << blockBits;
- int numBuckets = 1 << bucketBits;
- int numSlots = 1 << slotBits;
- int slotMask = numSlots - 1;
- int hashShift = 64 - bucketBits;
- long hashMask = (~0L) >>> (64 - hashBits);
- int sourceSize = src.capacity();
- if (sourceSize < 8) {
- throw new IllegalArgumentException("src is too short");
- }
-
- /* Step 1: create "bloated" hasher. */
- short[] num = new short[numBuckets];
- int[] bucketHeads = new int[numBuckets];
- int[] nextBucket = new int[sourceSize];
-
- long accumulator = 0;
- for (int i = 0; i < 7; ++i) {
- accumulator |= (src.get(i) & 0xFFL) << (8 * i);
- }
- accumulator <<= 8;
- /* TODO(eustas): apply custom "store" order. */
- for (int i = 0; i + 7 < sourceSize; ++i) {
- accumulator = (accumulator >>> 8) | ((src.get(i + 7) & 0xFFL) << 56);
- long h = (accumulator & hashMask) * HASH_MULTIPLIER;
- int key = (int) (h >>> hashShift);
- int count = num[key];
- nextBucket[i] = (count == 0) ? -1 : bucketHeads[key];
- bucketHeads[key] = i;
- count++;
- if (count > bucketLimit) {
- count = bucketLimit;
- }
- num[key] = (short) count;
- }
-
- /* Step 2: find slot limits. */
- int[] slotLimit = new int[numSlots];
- int[] slotSize = new int[numSlots];
- int totalItems = 0;
- for (int i = 0; i < numSlots; ++i) {
- boolean overflow = false;
- slotLimit[i] = bucketLimit;
- while (true) {
- overflow = false;
- int limit = slotLimit[i];
- int count = 0;
- for (int j = i; j < numBuckets; j += numSlots) {
- int size = num[j];
- /* Last chain may span behind 64K limit; overflow happens only if
- we are about to use 0xFFFF+ as item offset. */
- if (count >= 0xFFFF) {
- overflow = true;
- break;
- }
- if (size > limit) {
- size = limit;
- }
- count += size;
- }
- if (!overflow) {
- slotSize[i] = count;
- totalItems += count;
- break;
- }
- slotLimit[i]--;
- }
- }
-
- /* Step 3: transfer data to "slim" hasher. */
- int part0 = 6 * 4;
- int part1 = numSlots * 4;
- int part2 = numBuckets * 2;
- int part3 = totalItems * 4;
- int allocSize = part0 + part1 + part2 + part3 + sourceSize;
- ByteBuffer flat = ByteBuffer.allocateDirect(allocSize);
- ByteBuffer pointer = flat.slice();
- pointer.order(ByteOrder.nativeOrder());
-
- IntBuffer struct = pointer.asIntBuffer();
- pointer.position(pointer.position() + part0);
- IntBuffer slotOffsets = pointer.asIntBuffer();
- pointer.position(pointer.position() + part1);
- ShortBuffer heads = pointer.asShortBuffer();
- pointer.position(pointer.position() + part2);
- IntBuffer items = pointer.asIntBuffer();
- pointer.position(pointer.position() + part3);
- ByteBuffer sourceCopy = pointer.slice();
-
- /* magic */ struct.put(0, MAGIC);
- /* source_offset */ struct.put(1, totalItems);
- /* source_size */ struct.put(2, sourceSize);
- /* hash_bits */ struct.put(3, hashBits);
- /* bucket_bits */ struct.put(4, bucketBits);
- /* slot_bits */ struct.put(5, slotBits);
-
- totalItems = 0;
- for (int i = 0; i < numSlots; ++i) {
- slotOffsets.put(i, totalItems);
- totalItems += slotSize[i];
- slotSize[i] = 0;
- }
-
- for (int i = 0; i < numBuckets; ++i) {
- int slot = i & slotMask;
- int count = num[i];
- if (count > slotLimit[slot]) {
- count = slotLimit[slot];
- }
- if (count == 0) {
- heads.put(i, (short) 0xFFFF);
- continue;
- }
- int cursor = slotSize[slot];
- heads.put(i, (short) cursor);
- cursor += slotOffsets.get(slot);
- slotSize[slot] += count;
- int pos = bucketHeads[i];
- for (int j = 0; j < count; j++) {
- items.put(cursor++, pos);
- pos = nextBucket[pos];
- }
- cursor--;
- items.put(cursor, items.get(cursor) | 0x80000000);
- }
-
- sourceCopy.put(src);
-
- return new PreparedDictionaryImpl(flat);
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli b/firka_wear/android/app/src/main/java/org/brotli
new file mode 120000
index 00000000..53542ea0
--- /dev/null
+++ b/firka_wear/android/app/src/main/java/org/brotli
@@ -0,0 +1 @@
+../../../../../../../firka/android/app/src/main/java/org/brotli
\ No newline at end of file
diff --git a/firka_wear/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java b/firka_wear/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java
deleted file mode 100644
index b592d2b4..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/common/SharedDictionaryType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Copyright 2018 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.common;
-
-/** POJO enum that mirrors C BrotliSharedDictionaryType. */
-public class SharedDictionaryType {
- // Disallow instantiation.
- private SharedDictionaryType() {}
-
- public static final int RAW = 0;
- public static final int SERIALIZED = 1;
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/BitReader.java b/firka_wear/android/app/src/main/java/org/brotli/dec/BitReader.java
deleted file mode 100644
index bae9452d..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/BitReader.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/* Copyright 2015 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.dec;
-
-/**
- * Bit reading helpers.
- */
-final class BitReader {
-
- // Possible values: {5, 6}. 5 corresponds to 32-bit build, 6 to 64-bit. This value is used for
- // JIT conditional compilation.
- private static final int LOG_BITNESS = Utils.getLogBintness();
-
- // Not only Java compiler prunes "if (const false)" code, but JVM as well.
- // Code under "if (DEBUG != 0)" have zero performance impact (outside unit tests).
- private static final int DEBUG = Utils.isDebugMode();
-
- static final int BITNESS = 1 << LOG_BITNESS;
-
- private static final int BYTENESS = BITNESS / 8;
- private static final int CAPACITY = 4096;
- // After encountering the end of the input stream, this amount of zero bytes will be appended.
- private static final int SLACK = 64;
- private static final int BUFFER_SIZE = CAPACITY + SLACK;
- // Don't bother to replenish the buffer while this number of bytes is available.
- private static final int SAFEGUARD = 36;
- private static final int WATERLINE = CAPACITY - SAFEGUARD;
-
- // "Half" refers to "half of native integer type", i.e. on 64-bit machines it is 32-bit type,
- // on 32-bit machines it is 16-bit.
- private static final int HALF_BITNESS = BITNESS / 2;
- private static final int HALF_SIZE = BYTENESS / 2;
- private static final int HALVES_CAPACITY = CAPACITY / HALF_SIZE;
- private static final int HALF_BUFFER_SIZE = BUFFER_SIZE / HALF_SIZE;
- private static final int HALF_WATERLINE = WATERLINE / HALF_SIZE;
-
- private static final int LOG_HALF_SIZE = LOG_BITNESS - 4;
-
- /**
- * Fills up the input buffer.
- *
- * No-op if there are at least 36 bytes present after current position.
- *
- * After encountering the end of the input stream, 64 additional zero bytes are copied to the
- * buffer.
- */
- static void readMoreInput(State s) {
- if (s.halfOffset > HALF_WATERLINE) {
- doReadMoreInput(s);
- }
- }
-
- static void doReadMoreInput(State s) {
- if (s.endOfStreamReached != 0) {
- if (halfAvailable(s) >= -2) {
- return;
- }
- throw new BrotliRuntimeException("No more input");
- }
- final int readOffset = s.halfOffset << LOG_HALF_SIZE;
- int bytesInBuffer = CAPACITY - readOffset;
- // Move unused bytes to the head of the buffer.
- Utils.copyBytesWithin(s.byteBuffer, 0, readOffset, CAPACITY);
- s.halfOffset = 0;
- while (bytesInBuffer < CAPACITY) {
- final int spaceLeft = CAPACITY - bytesInBuffer;
- final int len = Utils.readInput(s.input, s.byteBuffer, bytesInBuffer, spaceLeft);
- // EOF is -1 in Java, but 0 in C#.
- if (len <= 0) {
- s.endOfStreamReached = 1;
- s.tailBytes = bytesInBuffer;
- bytesInBuffer += HALF_SIZE - 1;
- break;
- }
- bytesInBuffer += len;
- }
- bytesToNibbles(s, bytesInBuffer);
- }
-
- static void checkHealth(State s, int endOfStream) {
- if (s.endOfStreamReached == 0) {
- return;
- }
- final int byteOffset = (s.halfOffset << LOG_HALF_SIZE) + ((s.bitOffset + 7) >> 3) - BYTENESS;
- if (byteOffset > s.tailBytes) {
- throw new BrotliRuntimeException("Read after end");
- }
- if ((endOfStream != 0) && (byteOffset != s.tailBytes)) {
- throw new BrotliRuntimeException("Unused bytes after end");
- }
- }
-
- static void assertAccumulatorHealthy(State s) {
- if (s.bitOffset > BITNESS) {
- throw new IllegalStateException("Accumulator underloaded: " + s.bitOffset);
- }
- }
-
- static void fillBitWindow(State s) {
- if (DEBUG != 0) {
- assertAccumulatorHealthy(s);
- }
- if (s.bitOffset >= HALF_BITNESS) {
- // Same as doFillBitWindow. JVM fails to inline it.
- if (BITNESS == 64) {
- s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS)
- | (s.accumulator64 >>> HALF_BITNESS);
- } else {
- s.accumulator32 = ((int) s.shortBuffer[s.halfOffset++] << HALF_BITNESS)
- | (s.accumulator32 >>> HALF_BITNESS);
- }
- s.bitOffset -= HALF_BITNESS;
- }
- }
-
- static void doFillBitWindow(State s) {
- if (DEBUG != 0) {
- assertAccumulatorHealthy(s);
- }
- if (BITNESS == 64) {
- s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS)
- | (s.accumulator64 >>> HALF_BITNESS);
- } else {
- s.accumulator32 = ((int) s.shortBuffer[s.halfOffset++] << HALF_BITNESS)
- | (s.accumulator32 >>> HALF_BITNESS);
- }
- s.bitOffset -= HALF_BITNESS;
- }
-
- static int peekBits(State s) {
- if (BITNESS == 64) {
- return (int) (s.accumulator64 >>> s.bitOffset);
- } else {
- return s.accumulator32 >>> s.bitOffset;
- }
- }
-
- /**
- * Fetches bits from accumulator.
- *
- * WARNING: accumulator MUST contain at least the specified amount of bits,
- * otherwise BitReader will become broken.
- */
- static int readFewBits(State s, int n) {
- final int val = peekBits(s) & ((1 << n) - 1);
- s.bitOffset += n;
- return val;
- }
-
- static int readBits(State s, int n) {
- if (HALF_BITNESS >= 24) {
- return readFewBits(s, n);
- } else {
- return (n <= 16) ? readFewBits(s, n) : readManyBits(s, n);
- }
- }
-
- private static int readManyBits(State s, int n) {
- final int low = readFewBits(s, 16);
- doFillBitWindow(s);
- return low | (readFewBits(s, n - 16) << 16);
- }
-
- static void initBitReader(State s) {
- s.byteBuffer = new byte[BUFFER_SIZE];
- if (BITNESS == 64) {
- s.accumulator64 = 0;
- s.intBuffer = new int[HALF_BUFFER_SIZE];
- } else {
- s.accumulator32 = 0;
- s.shortBuffer = new short[HALF_BUFFER_SIZE];
- }
- s.bitOffset = BITNESS;
- s.halfOffset = HALVES_CAPACITY;
- s.endOfStreamReached = 0;
- prepare(s);
- }
-
- private static void prepare(State s) {
- readMoreInput(s);
- checkHealth(s, 0);
- doFillBitWindow(s);
- doFillBitWindow(s);
- }
-
- static void reload(State s) {
- if (s.bitOffset == BITNESS) {
- prepare(s);
- }
- }
-
- static void jumpToByteBoundary(State s) {
- final int padding = (BITNESS - s.bitOffset) & 7;
- if (padding != 0) {
- final int paddingBits = readFewBits(s, padding);
- if (paddingBits != 0) {
- throw new BrotliRuntimeException("Corrupted padding bits");
- }
- }
- }
-
- static int halfAvailable(State s) {
- int limit = HALVES_CAPACITY;
- if (s.endOfStreamReached != 0) {
- limit = (s.tailBytes + (HALF_SIZE - 1)) >> LOG_HALF_SIZE;
- }
- return limit - s.halfOffset;
- }
-
- static void copyRawBytes(State s, byte[] data, int offset, int length) {
- if ((s.bitOffset & 7) != 0) {
- throw new BrotliRuntimeException("Unaligned copyBytes");
- }
-
- // Drain accumulator.
- while ((s.bitOffset != BITNESS) && (length != 0)) {
- data[offset++] = (byte) peekBits(s);
- s.bitOffset += 8;
- length--;
- }
- if (length == 0) {
- return;
- }
-
- // Get data from shadow buffer with "sizeof(int)" granularity.
- final int copyNibbles = Math.min(halfAvailable(s), length >> LOG_HALF_SIZE);
- if (copyNibbles > 0) {
- final int readOffset = s.halfOffset << LOG_HALF_SIZE;
- final int delta = copyNibbles << LOG_HALF_SIZE;
- System.arraycopy(s.byteBuffer, readOffset, data, offset, delta);
- offset += delta;
- length -= delta;
- s.halfOffset += copyNibbles;
- }
- if (length == 0) {
- return;
- }
-
- // Read tail bytes.
- if (halfAvailable(s) > 0) {
- // length = 1..3
- fillBitWindow(s);
- while (length != 0) {
- data[offset++] = (byte) peekBits(s);
- s.bitOffset += 8;
- length--;
- }
- checkHealth(s, 0);
- return;
- }
-
- // Now it is possible to copy bytes directly.
- while (length > 0) {
- final int len = Utils.readInput(s.input, data, offset, length);
- if (len == -1) {
- throw new BrotliRuntimeException("Unexpected end of input");
- }
- offset += len;
- length -= len;
- }
- }
-
- /**
- * Translates bytes to halves (int/short).
- */
- static void bytesToNibbles(State s, int byteLen) {
- final byte[] byteBuffer = s.byteBuffer;
- final int halfLen = byteLen >> LOG_HALF_SIZE;
- if (BITNESS == 64) {
- final int[] intBuffer = s.intBuffer;
- for (int i = 0; i < halfLen; ++i) {
- intBuffer[i] = ((byteBuffer[i * 4] & 0xFF))
- | ((byteBuffer[(i * 4) + 1] & 0xFF) << 8)
- | ((byteBuffer[(i * 4) + 2] & 0xFF) << 16)
- | ((byteBuffer[(i * 4) + 3] & 0xFF) << 24);
- }
- } else {
- final short[] shortBuffer = s.shortBuffer;
- for (int i = 0; i < halfLen; ++i) {
- shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF)
- | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));
- }
- }
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java b/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java
deleted file mode 100644
index 7bbe2f63..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliInputStream.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * {@link InputStream} decorator that decompresses brotli data.
- *
- * Not thread-safe.
- */
-public class BrotliInputStream extends InputStream {
-
- public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 256;
-
- /**
- * Value expected by InputStream contract when stream is over.
- *
- * In Java it is -1.
- * In C# it is 0 (should be patched during transpilation).
- */
- private static final int END_OF_STREAM_MARKER = -1;
-
- /**
- * Internal buffer used for efficient byte-by-byte reading.
- */
- private byte[] buffer;
-
- /**
- * Number of decoded but still unused bytes in internal buffer.
- */
- private int remainingBufferBytes;
-
- /**
- * Next unused byte offset.
- */
- private int bufferOffset;
-
- /**
- * Decoder state.
- */
- private final State state = new State();
-
- /**
- * Creates a {@link InputStream} wrapper that decompresses brotli data.
- *
- * For byte-by-byte reading ({@link #read()}) internal buffer with
- * {@link #DEFAULT_INTERNAL_BUFFER_SIZE} size is allocated and used.
- *
- * Will block the thread until first {@link BitReader#CAPACITY} bytes of data of source
- * are available.
- *
- * @param source underlying data source
- * @throws IOException in case of corrupted data or source stream problems
- */
- public BrotliInputStream(InputStream source) throws IOException {
- this(source, DEFAULT_INTERNAL_BUFFER_SIZE);
- }
-
- /**
- * Creates a {@link InputStream} wrapper that decompresses brotli data.
- *
- * For byte-by-byte reading ({@link #read()}) internal buffer of specified size is
- * allocated and used.
- *
- * Will block the thread until first {@link BitReader#CAPACITY} bytes of data of source
- * are available.
- *
- * @param source compressed data source
- * @param byteReadBufferSize size of internal buffer used in case of
- * byte-by-byte reading
- * @throws IOException in case of corrupted data or source stream problems
- */
- public BrotliInputStream(InputStream source, int byteReadBufferSize) throws IOException {
- if (byteReadBufferSize <= 0) {
- throw new IllegalArgumentException("Bad buffer size:" + byteReadBufferSize);
- } else if (source == null) {
- throw new IllegalArgumentException("source is null");
- }
- this.buffer = new byte[byteReadBufferSize];
- this.remainingBufferBytes = 0;
- this.bufferOffset = 0;
- try {
- Decode.initState(state, source);
- } catch (BrotliRuntimeException ex) {
- throw new IOException("Brotli decoder initialization failed", ex);
- }
- }
-
- public void attachDictionaryChunk(byte[] data) {
- Decode.attachDictionaryChunk(state, data);
- }
-
- public void enableEagerOutput() {
- Decode.enableEagerOutput(state);
- }
-
- public void enableLargeWindow() {
- Decode.enableLargeWindow(state);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void close() throws IOException {
- Decode.close(state);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int read() throws IOException {
- if (bufferOffset >= remainingBufferBytes) {
- remainingBufferBytes = read(buffer, 0, buffer.length);
- bufferOffset = 0;
- if (remainingBufferBytes == END_OF_STREAM_MARKER) {
- // Both Java and C# return the same value for EOF on single-byte read.
- return -1;
- }
- }
- return buffer[bufferOffset++] & 0xFF;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int read(byte[] destBuffer, int destOffset, int destLen) throws IOException {
- if (destOffset < 0) {
- throw new IllegalArgumentException("Bad offset: " + destOffset);
- } else if (destLen < 0) {
- throw new IllegalArgumentException("Bad length: " + destLen);
- } else if (destOffset + destLen > destBuffer.length) {
- throw new IllegalArgumentException(
- "Buffer overflow: " + (destOffset + destLen) + " > " + destBuffer.length);
- } else if (destLen == 0) {
- return 0;
- }
- int copyLen = Math.max(remainingBufferBytes - bufferOffset, 0);
- if (copyLen != 0) {
- copyLen = Math.min(copyLen, destLen);
- System.arraycopy(buffer, bufferOffset, destBuffer, destOffset, copyLen);
- bufferOffset += copyLen;
- destOffset += copyLen;
- destLen -= copyLen;
- if (destLen == 0) {
- return copyLen;
- }
- }
- try {
- state.output = destBuffer;
- state.outputOffset = destOffset;
- state.outputLength = destLen;
- state.outputUsed = 0;
- Decode.decompress(state);
- copyLen += state.outputUsed;
- copyLen = (copyLen > 0) ? copyLen : END_OF_STREAM_MARKER;
- return copyLen;
- } catch (BrotliRuntimeException ex) {
- throw new IOException("Brotli stream decoding failed", ex);
- }
-
- // <{[INJECTED CODE]}>
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java b/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java
deleted file mode 100644
index 18449072..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/BrotliRuntimeException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2015 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.dec;
-
-/**
- * Unchecked exception used internally.
- */
-class BrotliRuntimeException extends RuntimeException {
-
- BrotliRuntimeException(String message) {
- super(message);
- }
-
- BrotliRuntimeException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/Context.java b/firka_wear/android/app/src/main/java/org/brotli/dec/Context.java
deleted file mode 100644
index 10bf0cbc..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/Context.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2015 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.dec;
-
-/**
- * Common context lookup table for all context modes.
- */
-final class Context {
-
- static final int[] LOOKUP = new int[2048];
-
- private static final String UTF_MAP = " !! ! \"#$##%#$&'##(#)#+++++++++"
- + "+((&*'##,---,---,-----,-----,-----'###.///.///./////./////./////'# ";
- private static final String UTF_RLE = "A/* ': & : $ \u0081 @";
-
- private static void unpackLookupTable(int[] lookup, String map, String rle) {
- // LSB6, MSB6, SIGNED
- for (int i = 0; i < 256; ++i) {
- lookup[i] = i & 0x3F;
- lookup[512 + i] = i >> 2;
- lookup[1792 + i] = 2 + (i >> 6);
- }
- // UTF8
- for (int i = 0; i < 128; ++i) {
- lookup[1024 + i] = 4 * (map.charAt(i) - 32);
- }
- for (int i = 0; i < 64; ++i) {
- lookup[1152 + i] = i & 1;
- lookup[1216 + i] = 2 + (i & 1);
- }
- int offset = 1280;
- for (int k = 0; k < 19; ++k) {
- final int value = k & 3;
- final int rep = rle.charAt(k) - 32;
- for (int i = 0; i < rep; ++i) {
- lookup[offset++] = value;
- }
- }
- // SIGNED
- for (int i = 0; i < 16; ++i) {
- lookup[1792 + i] = 1;
- lookup[2032 + i] = 6;
- }
- lookup[1792] = 0;
- lookup[2047] = 7;
- for (int i = 0; i < 256; ++i) {
- lookup[1536 + i] = lookup[1792 + i] << 3;
- }
- }
-
- static {
- unpackLookupTable(LOOKUP, UTF_MAP, UTF_RLE);
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/Decode.java b/firka_wear/android/app/src/main/java/org/brotli/dec/Decode.java
deleted file mode 100644
index bf9b6817..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/Decode.java
+++ /dev/null
@@ -1,1357 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-/**
- * API for Brotli decompression.
- */
-final class Decode {
-
- static final int MIN_LARGE_WINDOW_BITS = 10;
- /* Maximum was chosen to be 30 to allow efficient decoder implementation.
- * Format allows bigger window, but Java does not support 2G+ arrays. */
- static final int MAX_LARGE_WINDOW_BITS = 30;
-
- //----------------------------------------------------------------------------
- // RunningState
- //----------------------------------------------------------------------------
- private static final int UNINITIALIZED = 0;
- private static final int INITIALIZED = 1;
- private static final int BLOCK_START = 2;
- private static final int COMPRESSED_BLOCK_START = 3;
- private static final int MAIN_LOOP = 4;
- private static final int READ_METADATA = 5;
- private static final int COPY_UNCOMPRESSED = 6;
- private static final int INSERT_LOOP = 7;
- private static final int COPY_LOOP = 8;
- private static final int USE_DICTIONARY = 9;
- private static final int FINISHED = 10;
- private static final int CLOSED = 11;
- private static final int INIT_WRITE = 12;
- private static final int WRITE = 13;
- private static final int COPY_FROM_COMPOUND_DICTIONARY = 14;
-
- private static final int DEFAULT_CODE_LENGTH = 8;
- private static final int CODE_LENGTH_REPEAT_CODE = 16;
- private static final int NUM_LITERAL_CODES = 256;
- private static final int NUM_COMMAND_CODES = 704;
- private static final int NUM_BLOCK_LENGTH_CODES = 26;
- private static final int LITERAL_CONTEXT_BITS = 6;
- private static final int DISTANCE_CONTEXT_BITS = 2;
-
- private static final int CD_BLOCK_MAP_BITS = 8;
- private static final int HUFFMAN_TABLE_BITS = 8;
- private static final int HUFFMAN_TABLE_MASK = 0xFF;
-
- /**
- * Maximum possible Huffman table size for an alphabet size of (index * 32),
- * max code length 15 and root table bits 8.
- * The biggest alphabet is "command" - 704 symbols. Though "distance" alphabet could theoretically
- * outreach that limit (for 62 extra bit distances), practically it is limited by
- * MAX_ALLOWED_DISTANCE and never gets bigger than 544 symbols.
- */
- static final int[] MAX_HUFFMAN_TABLE_SIZE = {
- 256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
- 854, 886, 920, 952, 984, 1016, 1048, 1080
- };
-
- private static final int HUFFMAN_TABLE_SIZE_26 = 396;
- private static final int HUFFMAN_TABLE_SIZE_258 = 632;
-
- private static final int CODE_LENGTH_CODES = 18;
- private static final int[] CODE_LENGTH_CODE_ORDER = {
- 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- };
-
- private static final int NUM_DISTANCE_SHORT_CODES = 16;
- private static final int[] DISTANCE_SHORT_CODE_INDEX_OFFSET = {
- 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3
- };
-
- private static final int[] DISTANCE_SHORT_CODE_VALUE_OFFSET = {
- 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
- };
-
- /**
- * Static Huffman code for the code length code lengths.
- */
- private static final int[] FIXED_TABLE = {
- 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040001,
- 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040005
- };
-
- // TODO(eustas): generalize.
- static final int MAX_TRANSFORMED_WORD_LENGTH = 5 + 24 + 8;
-
- private static final int MAX_DISTANCE_BITS = 24;
- private static final int MAX_LARGE_WINDOW_DISTANCE_BITS = 62;
-
- /**
- * Safe distance limit.
- *
- * Limit ((1 << 31) - 4) allows safe distance calculation without overflows,
- * given the distance alphabet size is limited to corresponding size.
- */
- private static final int MAX_ALLOWED_DISTANCE = 0x7FFFFFFC;
-
- //----------------------------------------------------------------------------
- // Prefix code LUT.
- //----------------------------------------------------------------------------
- static final int[] BLOCK_LENGTH_OFFSET = {
- 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497,
- 753, 1265, 2289, 4337, 8433, 16625
- };
-
- static final int[] BLOCK_LENGTH_N_BITS = {
- 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 24
- };
-
- static final short[] INSERT_LENGTH_N_BITS = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
- 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18
- };
-
- static final short[] COPY_LENGTH_N_BITS = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
- 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18
- };
-
- // Each command is represented with 4x16-bit values:
- // * [insertLenExtraBits, copyLenExtraBits]
- // * insertLenOffset
- // * copyLenOffset
- // * distanceContext
- static final short[] CMD_LOOKUP = new short[NUM_COMMAND_CODES * 4];
-
- static {
- unpackCommandLookupTable(CMD_LOOKUP);
- }
-
- private static int log2floor(int i) {
- int result = -1;
- int step = 16;
- while (step > 0) {
- if ((i >>> step) != 0) {
- result += step;
- i = i >>> step;
- }
- step = step >> 1;
- }
- return result + i;
- }
-
- private static int calculateDistanceAlphabetSize(int npostfix, int ndirect, int maxndistbits) {
- return NUM_DISTANCE_SHORT_CODES + ndirect + 2 * (maxndistbits << npostfix);
- }
-
- // TODO(eustas): add a correctness test for this function when
- // large-window and dictionary are implemented.
- private static int calculateDistanceAlphabetLimit(int maxDistance, int npostfix, int ndirect) {
- if (maxDistance < ndirect + (2 << npostfix)) {
- throw new IllegalArgumentException("maxDistance is too small");
- }
- final int offset = ((maxDistance - ndirect) >> npostfix) + 4;
- final int ndistbits = log2floor(offset) - 1;
- final int group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1);
- return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + NUM_DISTANCE_SHORT_CODES;
- }
-
- private static void unpackCommandLookupTable(short[] cmdLookup) {
- final short[] insertLengthOffsets = new short[24];
- final short[] copyLengthOffsets = new short[24];
- copyLengthOffsets[0] = 2;
- for (int i = 0; i < 23; ++i) {
- insertLengthOffsets[i + 1] =
- (short) (insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]));
- copyLengthOffsets[i + 1] =
- (short) (copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]));
- }
-
- for (int cmdCode = 0; cmdCode < NUM_COMMAND_CODES; ++cmdCode) {
- int rangeIdx = cmdCode >>> 6;
- /* -4 turns any regular distance code to negative. */
- int distanceContextOffset = -4;
- if (rangeIdx >= 2) {
- rangeIdx -= 2;
- distanceContextOffset = 0;
- }
- final int insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
- final int copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
- final short copyLengthOffset = copyLengthOffsets[copyCode];
- final int distanceContext =
- distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
- final int index = cmdCode * 4;
- cmdLookup[index + 0] =
- (short) (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
- cmdLookup[index + 1] = insertLengthOffsets[insertCode];
- cmdLookup[index + 2] = copyLengthOffsets[copyCode];
- cmdLookup[index + 3] = (short) distanceContext;
- }
- }
-
- /**
- * Reads brotli stream header and parses "window bits".
- *
- * @param s initialized state, before any read is performed.
- * @return -1 if header is invalid
- */
- private static int decodeWindowBits(State s) {
- /* Change the meaning of flag. Before that step it means "decoder must be capable of reading
- * "large-window" brotli stream. After this step it means that "large-window" feature
- * is actually detected. Despite the window size could be same as before (lgwin = 10..24),
- * encoded distances are allowed to be much greater, thus bigger dictinary could be used. */
- final int largeWindowEnabled = s.isLargeWindow;
- s.isLargeWindow = 0;
-
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) == 0) {
- return 16;
- }
- int n = BitReader.readFewBits(s, 3);
- if (n != 0) {
- return 17 + n;
- }
- n = BitReader.readFewBits(s, 3);
- if (n != 0) {
- if (n == 1) {
- if (largeWindowEnabled == 0) {
- /* Reserved value in regular brotli stream. */
- return -1;
- }
- s.isLargeWindow = 1;
- /* Check "reserved" bit for future (post-large-window) extensions. */
- if (BitReader.readFewBits(s, 1) == 1) {
- return -1;
- }
- n = BitReader.readFewBits(s, 6);
- if (n < MIN_LARGE_WINDOW_BITS || n > MAX_LARGE_WINDOW_BITS) {
- /* Encoded window bits value is too small or too big. */
- return -1;
- }
- return n;
- } else {
- return 8 + n;
- }
- }
- return 17;
- }
-
- /**
- * Switch decoder to "eager" mode.
- *
- * In "eager" mode decoder returns as soon as there is enough data to fill output buffer.
- *
- * @param s initialized state, before any read is performed.
- */
- static void enableEagerOutput(State s) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- s.isEager = 1;
- }
-
- static void enableLargeWindow(State s) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- s.isLargeWindow = 1;
- }
-
- // TODO(eustas): do we need byte views?
- static void attachDictionaryChunk(State s, byte[] data) {
- if (s.runningState != INITIALIZED) {
- throw new IllegalStateException("State MUST be freshly initialized");
- }
- if (s.cdNumChunks == 0) {
- s.cdChunks = new byte[16][];
- s.cdChunkOffsets = new int[16];
- s.cdBlockBits = -1;
- }
- if (s.cdNumChunks == 15) {
- throw new IllegalStateException("Too many dictionary chunks");
- }
- s.cdChunks[s.cdNumChunks] = data;
- s.cdNumChunks++;
- s.cdTotalSize += data.length;
- s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;
- }
-
- /**
- * Associate input with decoder state.
- *
- * @param s uninitialized state without associated input
- * @param input compressed data source
- */
- static void initState(State s, InputStream input) {
- if (s.runningState != UNINITIALIZED) {
- throw new IllegalStateException("State MUST be uninitialized");
- }
- /* 6 trees + 1 extra "offset" slot to simplify table decoding logic. */
- s.blockTrees = new int[7 + 3 * (HUFFMAN_TABLE_SIZE_258 + HUFFMAN_TABLE_SIZE_26)];
- s.blockTrees[0] = 7;
- s.distRbIdx = 3;
- final int maxDistanceAlphabetLimit =
- calculateDistanceAlphabetLimit(MAX_ALLOWED_DISTANCE, 3, 15 << 3);
- s.distExtraBits = new byte[maxDistanceAlphabetLimit];
- s.distOffset = new int[maxDistanceAlphabetLimit];
- s.input = input;
- BitReader.initBitReader(s);
- s.runningState = INITIALIZED;
- }
-
- static void close(State s) throws IOException {
- if (s.runningState == UNINITIALIZED) {
- throw new IllegalStateException("State MUST be initialized");
- }
- if (s.runningState == CLOSED) {
- return;
- }
- s.runningState = CLOSED;
- if (s.input != null) {
- Utils.closeInput(s.input);
- s.input = null;
- }
- }
-
- /**
- * Decodes a number in the range [0..255], by reading 1 - 11 bits.
- */
- private static int decodeVarLenUnsignedByte(State s) {
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) != 0) {
- final int n = BitReader.readFewBits(s, 3);
- if (n == 0) {
- return 1;
- } else {
- return BitReader.readFewBits(s, n) + (1 << n);
- }
- }
- return 0;
- }
-
- private static void decodeMetaBlockLength(State s) {
- BitReader.fillBitWindow(s);
- s.inputEnd = BitReader.readFewBits(s, 1);
- s.metaBlockLength = 0;
- s.isUncompressed = 0;
- s.isMetadata = 0;
- if ((s.inputEnd != 0) && BitReader.readFewBits(s, 1) != 0) {
- return;
- }
- final int sizeNibbles = BitReader.readFewBits(s, 2) + 4;
- if (sizeNibbles == 7) {
- s.isMetadata = 1;
- if (BitReader.readFewBits(s, 1) != 0) {
- throw new BrotliRuntimeException("Corrupted reserved bit");
- }
- final int sizeBytes = BitReader.readFewBits(s, 2);
- if (sizeBytes == 0) {
- return;
- }
- for (int i = 0; i < sizeBytes; i++) {
- BitReader.fillBitWindow(s);
- final int bits = BitReader.readFewBits(s, 8);
- if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
- throw new BrotliRuntimeException("Exuberant nibble");
- }
- s.metaBlockLength |= bits << (i * 8);
- }
- } else {
- for (int i = 0; i < sizeNibbles; i++) {
- BitReader.fillBitWindow(s);
- final int bits = BitReader.readFewBits(s, 4);
- if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
- throw new BrotliRuntimeException("Exuberant nibble");
- }
- s.metaBlockLength |= bits << (i * 4);
- }
- }
- s.metaBlockLength++;
- if (s.inputEnd == 0) {
- s.isUncompressed = BitReader.readFewBits(s, 1);
- }
- }
-
- /**
- * Decodes the next Huffman code from bit-stream.
- */
- private static int readSymbol(int[] tableGroup, int tableIdx, State s) {
- int offset = tableGroup[tableIdx];
- final int val = BitReader.peekBits(s);
- offset += val & HUFFMAN_TABLE_MASK;
- final int bits = tableGroup[offset] >> 16;
- final int sym = tableGroup[offset] & 0xFFFF;
- if (bits <= HUFFMAN_TABLE_BITS) {
- s.bitOffset += bits;
- return sym;
- }
- offset += sym;
- final int mask = (1 << bits) - 1;
- offset += (val & mask) >>> HUFFMAN_TABLE_BITS;
- s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS);
- return tableGroup[offset] & 0xFFFF;
- }
-
- private static int readBlockLength(int[] tableGroup, int tableIdx, State s) {
- BitReader.fillBitWindow(s);
- final int code = readSymbol(tableGroup, tableIdx, s);
- final int n = BLOCK_LENGTH_N_BITS[code];
- BitReader.fillBitWindow(s);
- return BLOCK_LENGTH_OFFSET[code] + BitReader.readBits(s, n);
- }
-
- private static void moveToFront(int[] v, int index) {
- final int value = v[index];
- for (; index > 0; index--) {
- v[index] = v[index - 1];
- }
- v[0] = value;
- }
-
- private static void inverseMoveToFrontTransform(byte[] v, int vLen) {
- final int[] mtf = new int[256];
- for (int i = 0; i < 256; i++) {
- mtf[i] = i;
- }
- for (int i = 0; i < vLen; i++) {
- final int index = v[i] & 0xFF;
- v[i] = (byte) mtf[index];
- if (index != 0) {
- moveToFront(mtf, index);
- }
- }
- }
-
- private static void readHuffmanCodeLengths(
- int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, State s) {
- int symbol = 0;
- int prevCodeLen = DEFAULT_CODE_LENGTH;
- int repeat = 0;
- int repeatCodeLen = 0;
- int space = 32768;
- final int[] table = new int[32 + 1]; /* Speculative single entry table group. */
- final int tableIdx = table.length - 1;
- Huffman.buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, CODE_LENGTH_CODES);
-
- while (symbol < numSymbols && space > 0) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int p = BitReader.peekBits(s) & 31;
- s.bitOffset += table[p] >> 16;
- final int codeLen = table[p] & 0xFFFF;
- if (codeLen < CODE_LENGTH_REPEAT_CODE) {
- repeat = 0;
- codeLengths[symbol++] = codeLen;
- if (codeLen != 0) {
- prevCodeLen = codeLen;
- space -= 32768 >> codeLen;
- }
- } else {
- final int extraBits = codeLen - 14;
- int newLen = 0;
- if (codeLen == CODE_LENGTH_REPEAT_CODE) {
- newLen = prevCodeLen;
- }
- if (repeatCodeLen != newLen) {
- repeat = 0;
- repeatCodeLen = newLen;
- }
- final int oldRepeat = repeat;
- if (repeat > 0) {
- repeat -= 2;
- repeat <<= extraBits;
- }
- BitReader.fillBitWindow(s);
- repeat += BitReader.readFewBits(s, extraBits) + 3;
- final int repeatDelta = repeat - oldRepeat;
- if (symbol + repeatDelta > numSymbols) {
- throw new BrotliRuntimeException("symbol + repeatDelta > numSymbols"); // COV_NF_LINE
- }
- for (int i = 0; i < repeatDelta; i++) {
- codeLengths[symbol++] = repeatCodeLen;
- }
- if (repeatCodeLen != 0) {
- space -= repeatDelta << (15 - repeatCodeLen);
- }
- }
- }
- if (space != 0) {
- throw new BrotliRuntimeException("Unused space"); // COV_NF_LINE
- }
- // TODO(eustas): Pass max_symbol to Huffman table builder instead?
- Utils.fillIntsWithZeroes(codeLengths, symbol, numSymbols);
- }
-
- private static void checkDupes(int[] symbols, int length) {
- for (int i = 0; i < length - 1; ++i) {
- for (int j = i + 1; j < length; ++j) {
- if (symbols[i] == symbols[j]) {
- throw new BrotliRuntimeException("Duplicate simple Huffman code symbol"); // COV_NF_LINE
- }
- }
- }
- }
-
- /**
- * Reads up to 4 symbols directly and applies predefined histograms.
- */
- private static int readSimpleHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
- int[] tableGroup, int tableIdx, State s) {
- // TODO(eustas): Avoid allocation?
- final int[] codeLengths = new int[alphabetSizeLimit];
- final int[] symbols = new int[4];
-
- final int maxBits = 1 + log2floor(alphabetSizeMax - 1);
-
- final int numSymbols = BitReader.readFewBits(s, 2) + 1;
- for (int i = 0; i < numSymbols; i++) {
- BitReader.fillBitWindow(s);
- final int symbol = BitReader.readFewBits(s, maxBits);
- if (symbol >= alphabetSizeLimit) {
- throw new BrotliRuntimeException("Can't readHuffmanCode"); // COV_NF_LINE
- }
- symbols[i] = symbol;
- }
- checkDupes(symbols, numSymbols);
-
- int histogramId = numSymbols;
- if (numSymbols == 4) {
- histogramId += BitReader.readFewBits(s, 1);
- }
-
- switch (histogramId) {
- case 1:
- codeLengths[symbols[0]] = 1;
- break;
-
- case 2:
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 1;
- break;
-
- case 3:
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 2;
- break;
-
- case 4: // uniform 4-symbol histogram
- codeLengths[symbols[0]] = 2;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 2;
- codeLengths[symbols[3]] = 2;
- break;
-
- case 5: // prioritized 4-symbol histogram
- codeLengths[symbols[0]] = 1;
- codeLengths[symbols[1]] = 2;
- codeLengths[symbols[2]] = 3;
- codeLengths[symbols[3]] = 3;
- break;
-
- default:
- break;
- }
-
- // TODO(eustas): Use specialized version?
- return Huffman.buildHuffmanTable(
- tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
- }
-
- // Decode Huffman-coded code lengths.
- private static int readComplexHuffmanCode(int alphabetSizeLimit, int skip,
- int[] tableGroup, int tableIdx, State s) {
- // TODO(eustas): Avoid allocation?
- final int[] codeLengths = new int[alphabetSizeLimit];
- final int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES];
- int space = 32;
- int numCodes = 0;
- for (int i = skip; i < CODE_LENGTH_CODES && space > 0; i++) {
- final int codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
- BitReader.fillBitWindow(s);
- final int p = BitReader.peekBits(s) & 15;
- // TODO(eustas): Demultiplex FIXED_TABLE.
- s.bitOffset += FIXED_TABLE[p] >> 16;
- final int v = FIXED_TABLE[p] & 0xFFFF;
- codeLengthCodeLengths[codeLenIdx] = v;
- if (v != 0) {
- space -= (32 >> v);
- numCodes++;
- }
- }
- if (space != 0 && numCodes != 1) {
- throw new BrotliRuntimeException("Corrupted Huffman code histogram"); // COV_NF_LINE
- }
-
- readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);
-
- return Huffman.buildHuffmanTable(
- tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
- }
-
- /**
- * Decodes Huffman table from bit-stream.
- *
- * @return number of slots used by resulting Huffman table
- */
- private static int readHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
- int[] tableGroup, int tableIdx, State s) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int simpleCodeOrSkip = BitReader.readFewBits(s, 2);
- if (simpleCodeOrSkip == 1) {
- return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
- } else {
- return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);
- }
- }
-
- private static int decodeContextMap(int contextMapSize, byte[] contextMap, State s) {
- BitReader.readMoreInput(s);
- final int numTrees = decodeVarLenUnsignedByte(s) + 1;
-
- if (numTrees == 1) {
- Utils.fillBytesWithZeroes(contextMap, 0, contextMapSize);
- return numTrees;
- }
-
- BitReader.fillBitWindow(s);
- final int useRleForZeros = BitReader.readFewBits(s, 1);
- int maxRunLengthPrefix = 0;
- if (useRleForZeros != 0) {
- maxRunLengthPrefix = BitReader.readFewBits(s, 4) + 1;
- }
- final int alphabetSize = numTrees + maxRunLengthPrefix;
- final int tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5];
- /* Speculative single entry table group. */
- final int[] table = new int[tableSize + 1];
- final int tableIdx = table.length - 1;
- readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
- for (int i = 0; i < contextMapSize; ) {
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- final int code = readSymbol(table, tableIdx, s);
- if (code == 0) {
- contextMap[i] = 0;
- i++;
- } else if (code <= maxRunLengthPrefix) {
- BitReader.fillBitWindow(s);
- int reps = (1 << code) + BitReader.readFewBits(s, code);
- while (reps != 0) {
- if (i >= contextMapSize) {
- throw new BrotliRuntimeException("Corrupted context map"); // COV_NF_LINE
- }
- contextMap[i] = 0;
- i++;
- reps--;
- }
- } else {
- contextMap[i] = (byte) (code - maxRunLengthPrefix);
- i++;
- }
- }
- BitReader.fillBitWindow(s);
- if (BitReader.readFewBits(s, 1) == 1) {
- inverseMoveToFrontTransform(contextMap, contextMapSize);
- }
- return numTrees;
- }
-
- private static int decodeBlockTypeAndLength(State s, int treeType, int numBlockTypes) {
- final int[] ringBuffers = s.rings;
- final int offset = 4 + treeType * 2;
- BitReader.fillBitWindow(s);
- int blockType = readSymbol(s.blockTrees, 2 * treeType, s);
- final int result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
-
- if (blockType == 1) {
- blockType = ringBuffers[offset + 1] + 1;
- } else if (blockType == 0) {
- blockType = ringBuffers[offset];
- } else {
- blockType -= 2;
- }
- if (blockType >= numBlockTypes) {
- blockType -= numBlockTypes;
- }
- ringBuffers[offset] = ringBuffers[offset + 1];
- ringBuffers[offset + 1] = blockType;
- return result;
- }
-
- private static void decodeLiteralBlockSwitch(State s) {
- s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
- final int literalBlockType = s.rings[5];
- s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS;
- s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF;
- final int contextMode = s.contextModes[literalBlockType];
- s.contextLookupOffset1 = contextMode << 9;
- s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
- }
-
- private static void decodeCommandBlockSwitch(State s) {
- s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);
- s.commandTreeIdx = s.rings[7];
- }
-
- private static void decodeDistanceBlockSwitch(State s) {
- s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);
- s.distContextMapSlice = s.rings[9] << DISTANCE_CONTEXT_BITS;
- }
-
- private static void maybeReallocateRingBuffer(State s) {
- int newSize = s.maxRingBufferSize;
- if (newSize > s.expectedTotalSize) {
- /* TODO(eustas): Handle 2GB+ cases more gracefully. */
- final int minimalNewSize = s.expectedTotalSize;
- while ((newSize >> 1) > minimalNewSize) {
- newSize >>= 1;
- }
- if ((s.inputEnd == 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
- newSize = 16384;
- }
- }
- if (newSize <= s.ringBufferSize) {
- return;
- }
- final int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH;
- final byte[] newBuffer = new byte[ringBufferSizeWithSlack];
- if (s.ringBuffer.length != 0) {
- System.arraycopy(s.ringBuffer, 0, newBuffer, 0, s.ringBufferSize);
- }
- s.ringBuffer = newBuffer;
- s.ringBufferSize = newSize;
- }
-
- private static void readNextMetablockHeader(State s) {
- if (s.inputEnd != 0) {
- s.nextRunningState = FINISHED;
- s.runningState = INIT_WRITE;
- return;
- }
- // TODO(eustas): Reset? Do we need this?
- s.literalTreeGroup = new int[0];
- s.commandTreeGroup = new int[0];
- s.distanceTreeGroup = new int[0];
-
- BitReader.readMoreInput(s);
- decodeMetaBlockLength(s);
- if ((s.metaBlockLength == 0) && (s.isMetadata == 0)) {
- return;
- }
- if ((s.isUncompressed != 0) || (s.isMetadata != 0)) {
- BitReader.jumpToByteBoundary(s);
- s.runningState = (s.isMetadata != 0) ? READ_METADATA : COPY_UNCOMPRESSED;
- } else {
- s.runningState = COMPRESSED_BLOCK_START;
- }
-
- if (s.isMetadata != 0) {
- return;
- }
- s.expectedTotalSize += s.metaBlockLength;
- if (s.expectedTotalSize > 1 << 30) {
- s.expectedTotalSize = 1 << 30;
- }
- if (s.ringBufferSize < s.maxRingBufferSize) {
- maybeReallocateRingBuffer(s);
- }
- }
-
- private static int readMetablockPartition(State s, int treeType, int numBlockTypes) {
- int offset = s.blockTrees[2 * treeType];
- if (numBlockTypes <= 1) {
- s.blockTrees[2 * treeType + 1] = offset;
- s.blockTrees[2 * treeType + 2] = offset;
- return 1 << 28;
- }
-
- final int blockTypeAlphabetSize = numBlockTypes + 2;
- offset += readHuffmanCode(
- blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
- s.blockTrees[2 * treeType + 1] = offset;
-
- final int blockLengthAlphabetSize = NUM_BLOCK_LENGTH_CODES;
- offset += readHuffmanCode(
- blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
- s.blockTrees[2 * treeType + 2] = offset;
-
- return readBlockLength(s.blockTrees, 2 * treeType + 1, s);
- }
-
- private static void calculateDistanceLut(State s, int alphabetSizeLimit) {
- final byte[] distExtraBits = s.distExtraBits;
- final int[] distOffset = s.distOffset;
- final int npostfix = s.distancePostfixBits;
- final int ndirect = s.numDirectDistanceCodes;
- final int postfix = 1 << npostfix;
- int bits = 1;
- int half = 0;
-
- /* Skip short codes. */
- int i = NUM_DISTANCE_SHORT_CODES;
-
- /* Fill direct codes. */
- for (int j = 0; j < ndirect; ++j) {
- distExtraBits[i] = 0;
- distOffset[i] = j + 1;
- ++i;
- }
-
- /* Fill regular distance codes. */
- while (i < alphabetSizeLimit) {
- final int base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
- /* Always fill the complete group. */
- for (int j = 0; j < postfix; ++j) {
- distExtraBits[i] = (byte) bits;
- distOffset[i] = base + j;
- ++i;
- }
- bits = bits + half;
- half = half ^ 1;
- }
- }
-
- private static void readMetablockHuffmanCodesAndContextMaps(State s) {
- s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.literalBlockLength = readMetablockPartition(s, 0, s.numLiteralBlockTypes);
- s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.commandBlockLength = readMetablockPartition(s, 1, s.numCommandBlockTypes);
- s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;
- s.distanceBlockLength = readMetablockPartition(s, 2, s.numDistanceBlockTypes);
-
- BitReader.readMoreInput(s);
- BitReader.fillBitWindow(s);
- s.distancePostfixBits = BitReader.readFewBits(s, 2);
- s.numDirectDistanceCodes = BitReader.readFewBits(s, 4) << s.distancePostfixBits;
- // TODO(eustas): Reuse?
- s.contextModes = new byte[s.numLiteralBlockTypes];
- for (int i = 0; i < s.numLiteralBlockTypes;) {
- /* Ensure that less than 256 bits read between readMoreInput. */
- final int limit = Math.min(i + 96, s.numLiteralBlockTypes);
- for (; i < limit; ++i) {
- BitReader.fillBitWindow(s);
- s.contextModes[i] = (byte) BitReader.readFewBits(s, 2);
- }
- BitReader.readMoreInput(s);
- }
-
- // TODO(eustas): Reuse?
- s.contextMap = new byte[s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS];
- final int numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS,
- s.contextMap, s);
- s.trivialLiteralContext = 1;
- for (int j = 0; j < s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS; j++) {
- if (s.contextMap[j] != j >> LITERAL_CONTEXT_BITS) {
- s.trivialLiteralContext = 0;
- break;
- }
- }
-
- // TODO(eustas): Reuse?
- s.distContextMap = new byte[s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS];
- final int numDistTrees = decodeContextMap(s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS,
- s.distContextMap, s);
-
- s.literalTreeGroup = decodeHuffmanTreeGroup(NUM_LITERAL_CODES, NUM_LITERAL_CODES,
- numLiteralTrees, s);
- s.commandTreeGroup = decodeHuffmanTreeGroup(NUM_COMMAND_CODES, NUM_COMMAND_CODES,
- s.numCommandBlockTypes, s);
- int distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
- s.distancePostfixBits, s.numDirectDistanceCodes, MAX_DISTANCE_BITS);
- int distanceAlphabetSizeLimit = distanceAlphabetSizeMax;
- if (s.isLargeWindow == 1) {
- distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
- s.distancePostfixBits, s.numDirectDistanceCodes, MAX_LARGE_WINDOW_DISTANCE_BITS);
- distanceAlphabetSizeLimit = calculateDistanceAlphabetLimit(
- MAX_ALLOWED_DISTANCE, s.distancePostfixBits, s.numDirectDistanceCodes);
- }
- s.distanceTreeGroup = decodeHuffmanTreeGroup(distanceAlphabetSizeMax, distanceAlphabetSizeLimit,
- numDistTrees, s);
- calculateDistanceLut(s, distanceAlphabetSizeLimit);
-
- s.contextMapSlice = 0;
- s.distContextMapSlice = 0;
- s.contextLookupOffset1 = s.contextModes[0] * 512;
- s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
- s.literalTreeIdx = 0;
- s.commandTreeIdx = 0;
-
- s.rings[4] = 1;
- s.rings[5] = 0;
- s.rings[6] = 1;
- s.rings[7] = 0;
- s.rings[8] = 1;
- s.rings[9] = 0;
- }
-
- private static void copyUncompressedData(State s) {
- final byte[] ringBuffer = s.ringBuffer;
-
- // Could happen if block ends at ring buffer end.
- if (s.metaBlockLength <= 0) {
- BitReader.reload(s);
- s.runningState = BLOCK_START;
- return;
- }
-
- final int chunkLength = Math.min(s.ringBufferSize - s.pos, s.metaBlockLength);
- BitReader.copyRawBytes(s, ringBuffer, s.pos, chunkLength);
- s.metaBlockLength -= chunkLength;
- s.pos += chunkLength;
- if (s.pos == s.ringBufferSize) {
- s.nextRunningState = COPY_UNCOMPRESSED;
- s.runningState = INIT_WRITE;
- return;
- }
-
- BitReader.reload(s);
- s.runningState = BLOCK_START;
- }
-
- private static int writeRingBuffer(State s) {
- final int toWrite = Math.min(s.outputLength - s.outputUsed,
- s.ringBufferBytesReady - s.ringBufferBytesWritten);
- // TODO(eustas): DCHECK(toWrite >= 0)
- if (toWrite != 0) {
- System.arraycopy(s.ringBuffer, s.ringBufferBytesWritten, s.output,
- s.outputOffset + s.outputUsed, toWrite);
- s.outputUsed += toWrite;
- s.ringBufferBytesWritten += toWrite;
- }
-
- if (s.outputUsed < s.outputLength) {
- return 1;
- } else {
- return 0;
- }
- }
-
- private static int[] decodeHuffmanTreeGroup(int alphabetSizeMax, int alphabetSizeLimit,
- int n, State s) {
- final int maxTableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSizeLimit + 31) >> 5];
- final int[] group = new int[n + n * maxTableSize];
- int next = n;
- for (int i = 0; i < n; ++i) {
- group[i] = next;
- next += readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, group, i, s);
- }
- return group;
- }
-
- // Returns offset in ringBuffer that should trigger WRITE when filled.
- private static int calculateFence(State s) {
- int result = s.ringBufferSize;
- if (s.isEager != 0) {
- result = Math.min(result, s.ringBufferBytesWritten + s.outputLength - s.outputUsed);
- }
- return result;
- }
-
- private static void doUseDictionary(State s, int fence) {
- if (s.distance > MAX_ALLOWED_DISTANCE) {
- throw new BrotliRuntimeException("Invalid backward reference");
- }
- final int address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
- if (address < 0) {
- initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
- s.runningState = COPY_FROM_COMPOUND_DICTIONARY;
- } else {
- // Force lazy dictionary initialization.
- final ByteBuffer dictionaryData = Dictionary.getData();
- final int wordLength = s.copyLength;
- if (wordLength > Dictionary.MAX_DICTIONARY_WORD_LENGTH) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- final int shift = Dictionary.sizeBits[wordLength];
- if (shift == 0) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- int offset = Dictionary.offsets[wordLength];
- final int mask = (1 << shift) - 1;
- final int wordIdx = address & mask;
- final int transformIdx = address >>> shift;
- offset += wordIdx * wordLength;
- final Transform.Transforms transforms = Transform.RFC_TRANSFORMS;
- if (transformIdx >= transforms.numTransforms) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- final int len = Transform.transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData,
- offset, wordLength, transforms, transformIdx);
- s.pos += len;
- s.metaBlockLength -= len;
- if (s.pos >= fence) {
- s.nextRunningState = MAIN_LOOP;
- s.runningState = INIT_WRITE;
- return;
- }
- s.runningState = MAIN_LOOP;
- }
- }
-
- private static void initializeCompoundDictionary(State s) {
- s.cdBlockMap = new byte[1 << CD_BLOCK_MAP_BITS];
- int blockBits = CD_BLOCK_MAP_BITS;
- // If this function is executed, then s.cdTotalSize > 0.
- while (((s.cdTotalSize - 1) >>> blockBits) != 0) {
- blockBits++;
- }
- blockBits -= CD_BLOCK_MAP_BITS;
- s.cdBlockBits = blockBits;
- int cursor = 0;
- int index = 0;
- while (cursor < s.cdTotalSize) {
- while (s.cdChunkOffsets[index + 1] < cursor) {
- index++;
- }
- s.cdBlockMap[cursor >>> blockBits] = (byte) index;
- cursor += 1 << blockBits;
- }
- }
-
- private static void initializeCompoundDictionaryCopy(State s, int address, int length) {
- if (s.cdBlockBits == -1) {
- initializeCompoundDictionary(s);
- }
- int index = s.cdBlockMap[address >>> s.cdBlockBits];
- while (address >= s.cdChunkOffsets[index + 1]) {
- index++;
- }
- if (s.cdTotalSize > address + length) {
- throw new BrotliRuntimeException("Invalid backward reference");
- }
- /* Update the recent distances cache */
- s.distRbIdx = (s.distRbIdx + 1) & 0x3;
- s.rings[s.distRbIdx] = s.distance;
- s.metaBlockLength -= length;
- s.cdBrIndex = index;
- s.cdBrOffset = address - s.cdChunkOffsets[index];
- s.cdBrLength = length;
- s.cdBrCopied = 0;
- }
-
- private static int copyFromCompoundDictionary(State s, int fence) {
- int pos = s.pos;
- final int origPos = pos;
- while (s.cdBrLength != s.cdBrCopied) {
- final int space = fence - pos;
- final int chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex];
- final int remChunkLength = chunkLength - s.cdBrOffset;
- int length = s.cdBrLength - s.cdBrCopied;
- if (length > remChunkLength) {
- length = remChunkLength;
- }
- if (length > space) {
- length = space;
- }
- Utils.copyBytes(
- s.ringBuffer, pos, s.cdChunks[s.cdBrIndex], s.cdBrOffset, s.cdBrOffset + length);
- pos += length;
- s.cdBrOffset += length;
- s.cdBrCopied += length;
- if (length == remChunkLength) {
- s.cdBrIndex++;
- s.cdBrOffset = 0;
- }
- if (pos >= fence) {
- break;
- }
- }
- return pos - origPos;
- }
-
- /**
- * Actual decompress implementation.
- */
- static void decompress(State s) {
- if (s.runningState == UNINITIALIZED) {
- throw new IllegalStateException("Can't decompress until initialized");
- }
- if (s.runningState == CLOSED) {
- throw new IllegalStateException("Can't decompress after close");
- }
- if (s.runningState == INITIALIZED) {
- final int windowBits = decodeWindowBits(s);
- if (windowBits == -1) { /* Reserved case for future expansion. */
- throw new BrotliRuntimeException("Invalid 'windowBits' code");
- }
- s.maxRingBufferSize = 1 << windowBits;
- s.maxBackwardDistance = s.maxRingBufferSize - 16;
- s.runningState = BLOCK_START;
- }
-
- int fence = calculateFence(s);
- int ringBufferMask = s.ringBufferSize - 1;
- byte[] ringBuffer = s.ringBuffer;
-
- while (s.runningState != FINISHED) {
- // TODO(eustas): extract cases to methods for the better readability.
- switch (s.runningState) {
- case BLOCK_START:
- if (s.metaBlockLength < 0) {
- throw new BrotliRuntimeException("Invalid metablock length");
- }
- readNextMetablockHeader(s);
- /* Ring-buffer would be reallocated here. */
- fence = calculateFence(s);
- ringBufferMask = s.ringBufferSize - 1;
- ringBuffer = s.ringBuffer;
- continue;
-
- case COMPRESSED_BLOCK_START:
- readMetablockHuffmanCodesAndContextMaps(s);
- s.runningState = MAIN_LOOP;
-
- // fall through
- case MAIN_LOOP:
- if (s.metaBlockLength <= 0) {
- s.runningState = BLOCK_START;
- continue;
- }
- BitReader.readMoreInput(s);
- if (s.commandBlockLength == 0) {
- decodeCommandBlockSwitch(s);
- }
- s.commandBlockLength--;
- BitReader.fillBitWindow(s);
- final int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
- final short insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
- final int insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
- final int copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
- s.distanceCode = CMD_LOOKUP[cmdCode + 3];
- BitReader.fillBitWindow(s);
- {
- final int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF;
- s.insertLength = insertLengthOffset + BitReader.readBits(s, insertLengthExtraBits);
- }
- BitReader.fillBitWindow(s);
- {
- final int copyLengthExtraBits = insertAndCopyExtraBits >> 8;
- s.copyLength = copyLengthOffset + BitReader.readBits(s, copyLengthExtraBits);
- }
-
- s.j = 0;
- s.runningState = INSERT_LOOP;
-
- // fall through
- case INSERT_LOOP:
- if (s.trivialLiteralContext != 0) {
- while (s.j < s.insertLength) {
- BitReader.readMoreInput(s);
- if (s.literalBlockLength == 0) {
- decodeLiteralBlockSwitch(s);
- }
- s.literalBlockLength--;
- BitReader.fillBitWindow(s);
- ringBuffer[s.pos] = (byte) readSymbol(s.literalTreeGroup, s.literalTreeIdx, s);
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = INSERT_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- } else {
- int prevByte1 = ringBuffer[(s.pos - 1) & ringBufferMask] & 0xFF;
- int prevByte2 = ringBuffer[(s.pos - 2) & ringBufferMask] & 0xFF;
- while (s.j < s.insertLength) {
- BitReader.readMoreInput(s);
- if (s.literalBlockLength == 0) {
- decodeLiteralBlockSwitch(s);
- }
- final int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1]
- | Context.LOOKUP[s.contextLookupOffset2 + prevByte2];
- final int literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
- s.literalBlockLength--;
- prevByte2 = prevByte1;
- BitReader.fillBitWindow(s);
- prevByte1 = readSymbol(s.literalTreeGroup, literalTreeIdx, s);
- ringBuffer[s.pos] = (byte) prevByte1;
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = INSERT_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- }
- if (s.runningState != INSERT_LOOP) {
- continue;
- }
- s.metaBlockLength -= s.insertLength;
- if (s.metaBlockLength <= 0) {
- s.runningState = MAIN_LOOP;
- continue;
- }
- int distanceCode = s.distanceCode;
- if (distanceCode < 0) {
- // distanceCode in untouched; assigning it 0 won't affect distance ring buffer rolling.
- s.distance = s.rings[s.distRbIdx];
- } else {
- BitReader.readMoreInput(s);
- if (s.distanceBlockLength == 0) {
- decodeDistanceBlockSwitch(s);
- }
- s.distanceBlockLength--;
- BitReader.fillBitWindow(s);
- final int distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
- distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
- if (distanceCode < NUM_DISTANCE_SHORT_CODES) {
- final int index =
- (s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode]) & 0x3;
- s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
- if (s.distance < 0) {
- throw new BrotliRuntimeException("Negative distance"); // COV_NF_LINE
- }
- } else {
- final int extraBits = s.distExtraBits[distanceCode];
- int bits;
- if (s.bitOffset + extraBits <= BitReader.BITNESS) {
- bits = BitReader.readFewBits(s, extraBits);
- } else {
- BitReader.fillBitWindow(s);
- bits = BitReader.readBits(s, extraBits);
- }
- s.distance = s.distOffset[distanceCode] + (bits << s.distancePostfixBits);
- }
- }
-
- if (s.maxDistance != s.maxBackwardDistance
- && s.pos < s.maxBackwardDistance) {
- s.maxDistance = s.pos;
- } else {
- s.maxDistance = s.maxBackwardDistance;
- }
-
- if (s.distance > s.maxDistance) {
- s.runningState = USE_DICTIONARY;
- continue;
- }
-
- if (distanceCode > 0) {
- s.distRbIdx = (s.distRbIdx + 1) & 0x3;
- s.rings[s.distRbIdx] = s.distance;
- }
-
- if (s.copyLength > s.metaBlockLength) {
- throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
- }
- s.j = 0;
- s.runningState = COPY_LOOP;
-
- // fall through
- case COPY_LOOP:
- int src = (s.pos - s.distance) & ringBufferMask;
- int dst = s.pos;
- final int copyLength = s.copyLength - s.j;
- final int srcEnd = src + copyLength;
- final int dstEnd = dst + copyLength;
- if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
- if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
- for (int k = 0; k < copyLength; k += 4) {
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- ringBuffer[dst++] = ringBuffer[src++];
- }
- } else {
- Utils.copyBytesWithin(ringBuffer, dst, src, srcEnd);
- }
- s.j += copyLength;
- s.metaBlockLength -= copyLength;
- s.pos += copyLength;
- } else {
- for (; s.j < s.copyLength;) {
- ringBuffer[s.pos] =
- ringBuffer[(s.pos - s.distance) & ringBufferMask];
- s.metaBlockLength--;
- s.pos++;
- s.j++;
- if (s.pos >= fence) {
- s.nextRunningState = COPY_LOOP;
- s.runningState = INIT_WRITE;
- break;
- }
- }
- }
- if (s.runningState == COPY_LOOP) {
- s.runningState = MAIN_LOOP;
- }
- continue;
-
- case USE_DICTIONARY:
- doUseDictionary(s, fence);
- continue;
-
- case COPY_FROM_COMPOUND_DICTIONARY:
- s.pos += copyFromCompoundDictionary(s, fence);
- if (s.pos >= fence) {
- s.nextRunningState = COPY_FROM_COMPOUND_DICTIONARY;
- s.runningState = INIT_WRITE;
- return;
- }
- s.runningState = MAIN_LOOP;
- continue;
-
- case READ_METADATA:
- while (s.metaBlockLength > 0) {
- BitReader.readMoreInput(s);
- // Optimize
- BitReader.fillBitWindow(s);
- BitReader.readFewBits(s, 8);
- s.metaBlockLength--;
- }
- s.runningState = BLOCK_START;
- continue;
-
- case COPY_UNCOMPRESSED:
- copyUncompressedData(s);
- continue;
-
- case INIT_WRITE:
- s.ringBufferBytesReady = Math.min(s.pos, s.ringBufferSize);
- s.runningState = WRITE;
-
- // fall through
- case WRITE:
- if (writeRingBuffer(s) == 0) {
- // Output buffer is full.
- return;
- }
- if (s.pos >= s.maxBackwardDistance) {
- s.maxDistance = s.maxBackwardDistance;
- }
- // Wrap the ringBuffer.
- if (s.pos >= s.ringBufferSize) {
- if (s.pos > s.ringBufferSize) {
- Utils.copyBytesWithin(ringBuffer, 0, s.ringBufferSize, s.pos);
- }
- s.pos &= ringBufferMask;
- s.ringBufferBytesWritten = 0;
- }
- s.runningState = s.nextRunningState;
- continue;
-
- default:
- throw new BrotliRuntimeException("Unexpected state " + String.valueOf(s.runningState));
- }
- }
- if (s.runningState == FINISHED) {
- if (s.metaBlockLength < 0) {
- throw new BrotliRuntimeException("Invalid metablock length");
- }
- BitReader.jumpToByteBoundary(s);
- BitReader.checkHealth(s, 1);
- }
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/Decoder.java b/firka_wear/android/app/src/main/java/org/brotli/dec/Decoder.java
deleted file mode 100644
index e33f5a9a..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/Decoder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.brotli.dec;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class Decoder {
- private static long decodeBytes(InputStream input, OutputStream output, byte[] buffer)
- throws IOException {
- long totalOut = 0;
- int readBytes;
- BrotliInputStream in = new BrotliInputStream(input);
- in.enableLargeWindow();
- try {
- while ((readBytes = in.read(buffer)) >= 0) {
- output.write(buffer, 0, readBytes);
- totalOut += readBytes;
- }
- } finally {
- in.close();
- }
- return totalOut;
- }
-
- private static void decompress(String fromPath, String toPath, byte[] buffer) throws IOException {
- long start;
- long bytesDecoded;
- long end;
- InputStream in = null;
- OutputStream out = null;
- try {
- in = new FileInputStream(fromPath);
- out = new FileOutputStream(toPath);
- start = System.nanoTime();
- bytesDecoded = decodeBytes(in, out, buffer);
- end = System.nanoTime();
- } finally {
- if (in != null) {
- in.close(); // Hopefully, does not throw exception.
- }
- if (out != null) {
- out.close();
- }
- }
-
- double timeDelta = (end - start) / 1000000000.0;
- if (timeDelta <= 0) {
- return;
- }
- double mbDecoded = bytesDecoded / (1024.0 * 1024.0);
- System.out.println(mbDecoded / timeDelta + " MiB/s");
- }
-
- public static void main(String... args) throws IOException {
- if (args.length != 2 && args.length != 3) {
- System.out.println("Usage: decoder Dictionary content is loaded from binary resource when {@link #getData()} is executed for the
- * first time. Consequently, it saves memory and CPU in case dictionary is not required.
- *
- * One possible drawback is that multiple threads that need dictionary data may be blocked (only
- * once in each classworld). To avoid this, it is enough to call {@link #getData()} proactively.
- */
-public final class Dictionary {
- static final int MIN_DICTIONARY_WORD_LENGTH = 4;
- static final int MAX_DICTIONARY_WORD_LENGTH = 31;
-
- private static ByteBuffer data = ByteBuffer.allocateDirect(0);
- static final int[] offsets = new int[32];
- static final int[] sizeBits = new int[32];
-
- private static class DataLoader {
- static final boolean OK;
-
- static {
- boolean ok = true;
- try {
- Class.forName(Dictionary.class.getPackage().getName() + ".DictionaryData");
- } catch (Throwable ex) {
- ok = false;
- }
- OK = ok;
- }
- }
-
- public static void setData(ByteBuffer newData, int[] newSizeBits) {
- if ((Utils.isDirect(newData) == 0) || (Utils.isReadOnly(newData) == 0)) {
- throw new BrotliRuntimeException("newData must be a direct read-only byte buffer");
- }
- // TODO: is that so?
- if (newSizeBits.length > MAX_DICTIONARY_WORD_LENGTH) {
- throw new BrotliRuntimeException(
- "sizeBits length must be at most " + String.valueOf(MAX_DICTIONARY_WORD_LENGTH));
- }
- for (int i = 0; i < MIN_DICTIONARY_WORD_LENGTH; ++i) {
- if (newSizeBits[i] != 0) {
- throw new BrotliRuntimeException(
- "first " + String.valueOf(MIN_DICTIONARY_WORD_LENGTH) + " must be 0");
- }
- }
- final int[] dictionaryOffsets = Dictionary.offsets;
- final int[] dictionarySizeBits = Dictionary.sizeBits;
- System.arraycopy(newSizeBits, 0, dictionarySizeBits, 0, newSizeBits.length);
- int pos = 0;
- final int limit = newData.capacity();
- for (int i = 0; i < newSizeBits.length; ++i) {
- dictionaryOffsets[i] = pos;
- final int bits = dictionarySizeBits[i];
- if (bits != 0) {
- if (bits >= 31) {
- throw new BrotliRuntimeException("newSizeBits values must be less than 31");
- }
- pos += i << bits;
- if (pos <= 0 || pos > limit) {
- throw new BrotliRuntimeException("newSizeBits is inconsistent: overflow");
- }
- }
- }
- for (int i = newSizeBits.length; i < 32; ++i) {
- dictionaryOffsets[i] = pos;
- }
- if (pos != limit) {
- throw new BrotliRuntimeException("newSizeBits is inconsistent: underflow");
- }
- Dictionary.data = newData;
- }
-
- public static ByteBuffer getData() {
- if (data.capacity() != 0) {
- return data;
- }
- if (!DataLoader.OK) {
- throw new BrotliRuntimeException("brotli dictionary is not set");
- }
- /* Might have been set when {@link DictionaryData} was loaded.*/
- return data;
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/DictionaryData.java b/firka_wear/android/app/src/main/java/org/brotli/dec/DictionaryData.java
deleted file mode 100644
index ad96f38e..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/DictionaryData.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.nio.ByteBuffer;
-
-/**
- * Built-in dictionary data.
- *
- * When this class is loaded, it sets its data: {@link Dictionary#setData(ByteBuffer)}.
- */
-final class DictionaryData {
- private static final String DATA0 = "wjnfgltmojefofewab`h`lgfgbwbpkltlmozpjwf`jwzlsfmivpwojhfeqfftlqhwf{wzfbqlufqalgzolufelqnallhsobzojufojmfkfosklnfpjgfnlqftlqgolmdwkfnujftejmgsbdfgbzpevookfbgwfqnfb`kbqfbeqlnwqvfnbqhbaofvslmkjdkgbwfobmgmftpfufmmf{w`bpfalwkslpwvpfgnbgfkbmgkfqftkbwmbnfOjmhaoldpjyfabpfkfognbhfnbjmvpfq$*#(klogfmgptjwkMftpqfbgtfqfpjdmwbhfkbufdbnfpffm`boosbwktfoosovpnfmvejonsbqwiljmwkjpojpwdllgmffgtbzptfpwilapnjmgboploldlqj`kvpfpobpwwfbnbqnzellghjmdtjoofbpwtbqgafpwejqfSbdfhmltbtbz-smdnlufwkbmolbgdjufpfoemlwfnv`keffgnbmzql`hj`lmlm`follhkjgfgjfgKlnfqvofklpwbib{jmel`ovaobtpofppkboeplnfpv`kylmf233&lmfp`bqfWjnfqb`faovfelvqtffheb`fklsfdbufkbqgolpwtkfmsbqhhfswsbpppkjsqllnKWNOsobmWzsfglmfpbufhffseobdojmhplogejufwllhqbwfwltmivnswkvpgbqh`bqgejofefbqpwbzhjoowkbweboobvwlfufq-`lnwbohpklsulwfgffsnlgfqfpwwvqmalqmabmgefooqlpfvqo+phjmqlof`lnfb`wpbdfpnffwdlog-isdjwfnubqzefowwkfmpfmggqlsUjft`lsz2-3!?,b=pwlsfopfojfpwlvqsb`h-djesbpw`pp !2s{#plojg# -dje!#bow>!wqbmpsbqfmwjmelqnbwjlmbssoj`bwjlm!#lm`oj`h>!fpwbaojpkfgbgufqwjpjmd-smd!#bow>!fmujqlmnfmwsfqelqnbm`fbssqlsqjbwf%bns8ngbpk8jnnfgjbwfoz?,pwqlmd=?,qbwkfq#wkbmwfnsfqbwvqfgfufolsnfmw`lnsfwjwjlmsob`fklogfqujpjajojwz9`lszqjdkw!=3!#kfjdkw>!fufm#wklvdkqfsob`fnfmwgfpwjmbwjlm@lqslqbwjlm?vo#`obpp>!Bppl`jbwjlmjmgjujgvbopsfqpsf`wjufpfwWjnflvw+vqo+kwws9,,nbwkfnbwj`pnbqdjm.wls9fufmwvbooz#gfp`qjswjlm*#ml.qfsfbw`loof`wjlmp-ISD\u007Fwkvna\u007Fsbqwj`jsbwf,kfbg=?algzeolbw9ofew8?oj#`obpp>!kvmgqfgp#le\t\tKltfufq/#`lnslpjwjlm`ofbq9alwk8`llsfqbwjlmtjwkjm#wkf#obafo#elq>!alqgfq.wls9Mft#Yfbobmgqf`lnnfmgfgsklwldqbskzjmwfqfpwjmd%ow8pvs%dw8`lmwqlufqpzMfwkfqobmgpbowfqmbwjufnb{ofmdwk>!ptjwyfqobmgGfufolsnfmwfppfmwjbooz\t\tBowklvdk#?,wf{wbqfb=wkvmgfqajqgqfsqfpfmwfg%bns8mgbpk8psf`vobwjlm`lnnvmjwjfpofdjpobwjlmfof`wqlmj`p\t\n?gju#jg>!joovpwqbwfgfmdjmffqjmdwfqqjwlqjfpbvwklqjwjfpgjpwqjavwfg5!#kfjdkw>!pbmp.pfqje8`bsbaof#le#gjpbssfbqfgjmwfqb`wjufollhjmd#elqjw#tlvog#afBedkbmjpwbmtbp#`qfbwfgNbwk-eollq+pvqqlvmgjmd`bm#bopl#aflapfqubwjlmnbjmwfmbm`ffm`lvmwfqfg?k1#`obpp>!nlqf#qf`fmwjw#kbp#affmjmubpjlm#le*-dfwWjnf+*evmgbnfmwboGfpsjwf#wkf!=?gju#jg>!jmpsjqbwjlmf{bnjmbwjlmsqfsbqbwjlmf{sobmbwjlm?jmsvw#jg>!?,b=?,psbm=ufqpjlmp#lejmpwqvnfmwpafelqf#wkf##>#$kwws9,,Gfp`qjswjlmqfobwjufoz#-pvapwqjmd+fb`k#le#wkff{sfqjnfmwpjmeovfmwjbojmwfdqbwjlmnbmz#sflsofgvf#wl#wkf#`lnajmbwjlmgl#mlw#kbufNjggof#Fbpw?mlp`qjsw=?`lszqjdkw!#sfqkbsp#wkfjmpwjwvwjlmjm#Gf`fnafqbqqbmdfnfmwnlpw#ebnlvpsfqplmbojwz`qfbwjlm#leojnjwbwjlmpf{`ovpjufozplufqfjdmwz.`lmwfmw!=\t?wg#`obpp>!vmgfqdqlvmgsbqboofo#wlgl`wqjmf#lel``vsjfg#azwfqnjmloldzQfmbjppbm`fb#mvnafq#lepvsslqw#elqf{solqbwjlmqf`ldmjwjlmsqfgf`fpplq?jnd#pq`>!,?k2#`obpp>!svaoj`bwjlmnbz#bopl#afpsf`jbojyfg?,ejfogpfw=sqldqfppjufnjoojlmp#lepwbwfp#wkbwfmelq`fnfmwbqlvmg#wkf#lmf#bmlwkfq-sbqfmwMlgfbdqj`vowvqfBowfqmbwjufqfpfbq`kfqpwltbqgp#wkfNlpw#le#wkfnbmz#lwkfq#+fpsf`jbooz?wg#tjgwk>!8tjgwk9233&jmgfsfmgfmw?k0#`obpp>!#lm`kbmdf>!*-bgg@obpp+jmwfqb`wjlmLmf#le#wkf#gbvdkwfq#leb``fpplqjfpaqbm`kfp#le\u000E\t?gju#jg>!wkf#obqdfpwgf`obqbwjlmqfdvobwjlmpJmelqnbwjlmwqbmpobwjlmgl`vnfmwbqzjm#lqgfq#wl!=\t?kfbg=\t?!#kfjdkw>!2b`qlpp#wkf#lqjfmwbwjlm*8?,p`qjsw=jnsofnfmwfg`bm#af#pffmwkfqf#tbp#bgfnlmpwqbwf`lmwbjmfq!=`lmmf`wjlmpwkf#Aqjwjpktbp#tqjwwfm\"jnslqwbmw8s{8#nbqdjm.elooltfg#azbajojwz#wl#`lnsoj`bwfggvqjmd#wkf#jnnjdqbwjlmbopl#`boofg?k7#`obpp>!gjpwjm`wjlmqfsob`fg#azdlufqmnfmwpol`bwjlm#lejm#Mlufnafqtkfwkfq#wkf?,s=\t?,gju=b`rvjpjwjlm`boofg#wkf#sfqpf`vwjlmgfpjdmbwjlmxelmw.pjyf9bssfbqfg#jmjmufpwjdbwff{sfqjfm`fgnlpw#ojhfoztjgfoz#vpfggjp`vppjlmpsqfpfm`f#le#+gl`vnfmw-f{wfmpjufozJw#kbp#affmjw#glfp#mlw`lmwqbqz#wljmkbajwbmwpjnsqlufnfmwp`klobqpkjs`lmpvnswjlmjmpwqv`wjlmelq#f{bnsoflmf#lq#nlqfs{8#sbggjmdwkf#`vqqfmwb#pfqjfp#lebqf#vpvboozqlof#jm#wkfsqfujlvpoz#gfqjubwjufpfujgfm`f#lef{sfqjfm`fp`lolqp`kfnfpwbwfg#wkbw`fqwjej`bwf?,b=?,gju=\t#pfof`wfg>!kjdk#p`klloqfpslmpf#wl`lnelqwbaofbglswjlm#lewkqff#zfbqpwkf#`lvmwqzjm#Efaqvbqzpl#wkbw#wkfsflsof#tkl#sqlujgfg#az?sbqbn#mbnfbeef`wfg#azjm#wfqnp#lebssljmwnfmwJPL.;;6:.2!tbp#alqm#jmkjpwlqj`bo#qfdbqgfg#bpnfbpvqfnfmwjp#abpfg#lm#bmg#lwkfq#9#evm`wjlm+pjdmjej`bmw`fofaqbwjlmwqbmpnjwwfg,ip,irvfqz-jp#hmltm#bpwkflqfwj`bo#wbajmgf{>!jw#`lvog#af?mlp`qjsw=\tkbujmd#affm\u000E\t?kfbg=\u000E\t?#%rvlw8Wkf#`lnsjobwjlmkf#kbg#affmsqlgv`fg#azskjolplskfq`lmpwqv`wfgjmwfmgfg#wlbnlmd#lwkfq`lnsbqfg#wlwl#pbz#wkbwFmdjmffqjmdb#gjeefqfmwqfefqqfg#wlgjeefqfm`fpafojfe#wkbwsklwldqbskpjgfmwjezjmdKjpwlqz#le#Qfsvaoj`#lemf`fppbqjozsqlabajojwzwf`kmj`boozofbujmd#wkfpsf`wb`vobqeqb`wjlm#lefof`wqj`jwzkfbg#le#wkfqfpwbvqbmwpsbqwmfqpkjsfnskbpjp#lmnlpw#qf`fmwpkbqf#tjwk#pbzjmd#wkbwejoofg#tjwkgfpjdmfg#wljw#jp#lewfm!=?,jeqbnf=bp#elooltp9nfqdfg#tjwkwkqlvdk#wkf`lnnfq`jbo#sljmwfg#lvwlsslqwvmjwzujft#le#wkfqfrvjqfnfmwgjujpjlm#lesqldqbnnjmdkf#qf`fjufgpfwJmwfqubo!=?,psbm=?,jm#Mft#Zlqhbggjwjlmbo#`lnsqfppjlm\t\t?gju#jg>!jm`lqslqbwf8?,p`qjsw=?bwwb`kFufmwaf`bnf#wkf#!#wbqdfw>!\\`bqqjfg#lvwPlnf#le#wkfp`jfm`f#bmgwkf#wjnf#le@lmwbjmfq!=nbjmwbjmjmd@kqjpwlskfqNv`k#le#wkftqjwjmdp#le!#kfjdkw>!1pjyf#le#wkfufqpjlm#le#nj{wvqf#le#afwtffm#wkfF{bnsofp#lefgv`bwjlmbo`lnsfwjwjuf#lmpvanjw>!gjqf`wlq#legjpwjm`wjuf,GWG#[KWNO#qfobwjmd#wlwfmgfm`z#wlsqlujm`f#letkj`k#tlvoggfpsjwf#wkfp`jfmwjej`#ofdjpobwvqf-jmmfqKWNO#boofdbwjlmpBdqj`vowvqftbp#vpfg#jmbssqlb`k#wljmwfoojdfmwzfbqp#obwfq/pbmp.pfqjegfwfqnjmjmdSfqelqnbm`fbssfbqbm`fp/#tkj`k#jp#elvmgbwjlmpbaaqfujbwfgkjdkfq#wkbmp#eqln#wkf#jmgjujgvbo#`lnslpfg#lepvsslpfg#wl`objnp#wkbwbwwqjavwjlmelmw.pjyf92fofnfmwp#leKjpwlqj`bo#kjp#aqlwkfqbw#wkf#wjnfbmmjufqpbqzdlufqmfg#azqfobwfg#wl#vowjnbwfoz#jmmlubwjlmpjw#jp#pwjoo`bm#lmoz#afgfejmjwjlmpwlDNWPwqjmdB#mvnafq#lejnd#`obpp>!Fufmwvbooz/tbp#`kbmdfgl``vqqfg#jmmfjdkalqjmdgjpwjmdvjpktkfm#kf#tbpjmwqlgv`jmdwfqqfpwqjboNbmz#le#wkfbqdvfp#wkbwbm#Bnfqj`bm`lmrvfpw#letjgfpsqfbg#tfqf#hjoofgp`qffm#bmg#Jm#lqgfq#wlf{sf`wfg#wlgfp`fmgbmwpbqf#ol`bwfgofdjpobwjufdfmfqbwjlmp#ab`hdqlvmgnlpw#sflsofzfbqp#bewfqwkfqf#jp#mlwkf#kjdkfpweqfrvfmwoz#wkfz#gl#mlwbqdvfg#wkbwpkltfg#wkbwsqfglnjmbmwwkfloldj`boaz#wkf#wjnf`lmpjgfqjmdpklqw.ojufg?,psbm=?,b=`bm#af#vpfgufqz#ojwwoflmf#le#wkf#kbg#boqfbgzjmwfqsqfwfg`lnnvmj`bwfefbwvqfp#ledlufqmnfmw/?,mlp`qjsw=fmwfqfg#wkf!#kfjdkw>!0Jmgfsfmgfmwslsvobwjlmpobqdf.p`bof-#Bowklvdk#vpfg#jm#wkfgfpwqv`wjlmslppjajojwzpwbqwjmd#jmwtl#lq#nlqff{sqfppjlmppvalqgjmbwfobqdfq#wkbmkjpwlqz#bmg?,lswjlm=\u000E\t@lmwjmfmwbofojnjmbwjmdtjoo#mlw#afsqb`wj`f#lejm#eqlmw#lepjwf#le#wkffmpvqf#wkbwwl#`qfbwf#bnjppjppjssjslwfmwjboozlvwpwbmgjmdafwwfq#wkbmtkbw#jp#mltpjwvbwfg#jmnfwb#mbnf>!WqbgjwjlmbopvddfpwjlmpWqbmpobwjlmwkf#elqn#lebwnlpskfqj`jgfloldj`bofmwfqsqjpfp`bo`vobwjmdfbpw#le#wkfqfnmbmwp#lesovdjmpsbdf,jmgf{-sks #evm`wjlm+*-isd!#tjgwk>!`lmejdvqbwjlm-smd!#tjgwk>!?algz#`obpp>!Nbwk-qbmgln+*`lmwfnslqbqz#Vmjwfg#Pwbwfp`jq`vnpwbm`fp-bssfmg@kjog+lqdbmjybwjlmp?psbm#`obpp>!!=?jnd#pq`>!,gjpwjmdvjpkfgwklvpbmgp#le#`lnnvmj`bwjlm`ofbq!=?,gju=jmufpwjdbwjlmebuj`lm-j`l!#nbqdjm.qjdkw9abpfg#lm#wkf#Nbppb`kvpfwwpwbaof#alqgfq>jmwfqmbwjlmbobopl#hmltm#bpsqlmvm`jbwjlmab`hdqlvmg9 esbggjmd.ofew9Elq#f{bnsof/#njp`foobmflvp%ow8,nbwk%dw8spz`kloldj`bojm#sbqwj`vobqfbq`k!#wzsf>!elqn#nfwklg>!bp#lsslpfg#wlPvsqfnf#@lvqwl``bpjlmbooz#Bggjwjlmbooz/Mlqwk#Bnfqj`bs{8ab`hdqlvmglsslqwvmjwjfpFmwfqwbjmnfmw-wlOltfq@bpf+nbmveb`wvqjmdsqlefppjlmbo#`lnajmfg#tjwkElq#jmpwbm`f/`lmpjpwjmd#le!#nb{ofmdwk>!qfwvqm#ebopf8`lmp`jlvpmfppNfgjwfqqbmfbmf{wqblqgjmbqzbppbppjmbwjlmpvapfrvfmwoz#avwwlm#wzsf>!wkf#mvnafq#lewkf#lqjdjmbo#`lnsqfkfmpjufqfefqp#wl#wkf?,vo=\t?,gju=\tskjolplskj`bool`bwjlm-kqfetbp#svaojpkfgPbm#Eqbm`jp`l+evm`wjlm+*x\t?gju#jg>!nbjmplskjpwj`bwfgnbwkfnbwj`bo#,kfbg=\u000E\t?algzpvddfpwp#wkbwgl`vnfmwbwjlm`lm`fmwqbwjlmqfobwjlmpkjspnbz#kbuf#affm+elq#f{bnsof/Wkjp#bqwj`of#jm#plnf#`bpfpsbqwp#le#wkf#gfejmjwjlm#leDqfbw#Aqjwbjm#`foosbggjmd>frvjubofmw#wlsob`fklogfq>!8#elmw.pjyf9#ivpwjej`bwjlmafojfufg#wkbwpveefqfg#eqlnbwwfnswfg#wl#ofbgfq#le#wkf`qjsw!#pq`>!,+evm`wjlm+*#xbqf#bubjobaof\t\n?ojmh#qfo>!#pq`>$kwws9,,jmwfqfpwfg#jm`lmufmwjlmbo#!#bow>!!#,=?,bqf#dfmfqboozkbp#bopl#affmnlpw#slsvobq#`lqqfpslmgjmd`qfgjwfg#tjwkwzof>!alqgfq9?,b=?,psbm=?,-dje!#tjgwk>!?jeqbnf#pq`>!wbaof#`obpp>!jmojmf.aol`h8b``lqgjmd#wl#wldfwkfq#tjwkbssql{jnbwfozsbqojbnfmwbqznlqf#bmg#nlqfgjpsobz9mlmf8wqbgjwjlmboozsqfglnjmbmwoz%maps8\u007F%maps8%maps8?,psbm=#`foopsb`jmd>?jmsvw#mbnf>!lq!#`lmwfmw>!`lmwqlufqpjbosqlsfqwz>!ld9,{.pkl`htbuf.gfnlmpwqbwjlmpvqqlvmgfg#azMfufqwkfofpp/tbp#wkf#ejqpw`lmpjgfqbaof#Bowklvdk#wkf#`loobalqbwjlmpklvog#mlw#afsqlslqwjlm#le?psbm#pwzof>!hmltm#bp#wkf#pklqwoz#bewfqelq#jmpwbm`f/gfp`qjafg#bp#,kfbg=\t?algz#pwbqwjmd#tjwkjm`qfbpjmdoz#wkf#eb`w#wkbwgjp`vppjlm#lenjggof#le#wkfbm#jmgjujgvbogjeej`vow#wl#sljmw#le#ujftklnlpf{vbojwzb``fswbm`f#le?,psbm=?,gju=nbmveb`wvqfqplqjdjm#le#wkf`lnnlmoz#vpfgjnslqwbm`f#legfmlnjmbwjlmpab`hdqlvmg9# ofmdwk#le#wkfgfwfqnjmbwjlmb#pjdmjej`bmw!#alqgfq>!3!=qfulovwjlmbqzsqjm`jsofp#lejp#`lmpjgfqfgtbp#gfufolsfgJmgl.Fvqlsfbmuvomfqbaof#wlsqlslmfmwp#lebqf#plnfwjnfp`olpfq#wl#wkfMft#Zlqh#@jwz#mbnf>!pfbq`kbwwqjavwfg#wl`lvqpf#le#wkfnbwkfnbwj`jbmaz#wkf#fmg#lebw#wkf#fmg#le!#alqgfq>!3!#wf`kmloldj`bo-qfnluf@obpp+aqbm`k#le#wkffujgfm`f#wkbw\"Xfmgje^..=\u000E\tJmpwjwvwf#le#jmwl#b#pjmdofqfpsf`wjufoz-bmg#wkfqfelqfsqlsfqwjfp#lejp#ol`bwfg#jmplnf#le#tkj`kWkfqf#jp#bopl`lmwjmvfg#wl#bssfbqbm`f#le#%bns8mgbpk8#gfp`qjafp#wkf`lmpjgfqbwjlmbvwklq#le#wkfjmgfsfmgfmwozfrvjssfg#tjwkglfp#mlw#kbuf?,b=?b#kqfe>!`lmevpfg#tjwk?ojmh#kqfe>!,bw#wkf#bdf#lebssfbq#jm#wkfWkfpf#jm`ovgfqfdbqgofpp#le`lvog#af#vpfg#pwzof>%rvlw8pfufqbo#wjnfpqfsqfpfmw#wkfalgz=\t?,kwno=wklvdkw#wl#afslsvobwjlm#leslppjajojwjfpsfq`fmwbdf#leb``fpp#wl#wkfbm#bwwfnsw#wlsqlgv`wjlm#leirvfqz,irvfqzwtl#gjeefqfmwafolmd#wl#wkffpwbaojpknfmwqfsob`jmd#wkfgfp`qjswjlm!#gfwfqnjmf#wkfbubjobaof#elqB``lqgjmd#wl#tjgf#qbmdf#le\n?gju#`obpp>!nlqf#`lnnlmozlqdbmjpbwjlmpevm`wjlmbojwztbp#`lnsofwfg#%bns8ngbpk8#sbqwj`jsbwjlmwkf#`kbqb`wfqbm#bggjwjlmbobssfbqp#wl#afeb`w#wkbw#wkfbm#f{bnsof#lepjdmjej`bmwozlmnlvpflufq>!af`bvpf#wkfz#bpzm`#>#wqvf8sqlaofnp#tjwkpffnp#wl#kbufwkf#qfpvow#le#pq`>!kwws9,,ebnjojbq#tjwkslppfppjlm#leevm`wjlm#+*#xwllh#sob`f#jmbmg#plnfwjnfppvapwbmwjbooz?psbm=?,psbm=jp#lewfm#vpfgjm#bm#bwwfnswdqfbw#gfbo#leFmujqlmnfmwbopv``fppevooz#ujqwvbooz#boo13wk#`fmwvqz/sqlefppjlmbopmf`fppbqz#wl#gfwfqnjmfg#az`lnsbwjajojwzaf`bvpf#jw#jpGj`wjlmbqz#lenlgjej`bwjlmpWkf#elooltjmdnbz#qfefq#wl9@lmpfrvfmwoz/Jmwfqmbwjlmbobowklvdk#plnfwkbw#tlvog#aftlqog$p#ejqpw`obppjejfg#bpalwwln#le#wkf+sbqwj`vobqozbojdm>!ofew!#nlpw#`lnnlmozabpjp#elq#wkfelvmgbwjlm#le`lmwqjavwjlmpslsvobqjwz#le`fmwfq#le#wkfwl#qfgv`f#wkfivqjpgj`wjlmpbssql{jnbwjlm#lmnlvpflvw>!Mft#Wfpwbnfmw`loof`wjlm#le?,psbm=?,b=?,jm#wkf#Vmjwfgejon#gjqf`wlq.pwqj`w-gwg!=kbp#affm#vpfgqfwvqm#wl#wkfbowklvdk#wkjp`kbmdf#jm#wkfpfufqbo#lwkfqavw#wkfqf#bqfvmsqf`fgfmwfgjp#pjnjobq#wlfpsf`jbooz#jmtfjdkw9#alog8jp#`boofg#wkf`lnsvwbwjlmbojmgj`bwf#wkbwqfpwqj`wfg#wl\n?nfwb#mbnf>!bqf#wzsj`booz`lmeoj`w#tjwkKltfufq/#wkf#Bm#f{bnsof#le`lnsbqfg#tjwkrvbmwjwjfp#leqbwkfq#wkbm#b`lmpwfoobwjlmmf`fppbqz#elqqfslqwfg#wkbwpsf`jej`bwjlmslojwj`bo#bmg%maps8%maps8?qfefqfm`fp#wlwkf#pbnf#zfbqDlufqmnfmw#ledfmfqbwjlm#lekbuf#mlw#affmpfufqbo#zfbqp`lnnjwnfmw#wl\n\n?vo#`obpp>!ujpvbojybwjlm2:wk#`fmwvqz/sqb`wjwjlmfqpwkbw#kf#tlvogbmg#`lmwjmvfgl``vsbwjlm#lejp#gfejmfg#bp`fmwqf#le#wkfwkf#bnlvmw#le=?gju#pwzof>!frvjubofmw#legjeefqfmwjbwfaqlvdkw#balvwnbqdjm.ofew9#bvwlnbwj`boozwklvdkw#le#bpPlnf#le#wkfpf\t?gju#`obpp>!jmsvw#`obpp>!qfsob`fg#tjwkjp#lmf#le#wkffgv`bwjlm#bmgjmeovfm`fg#azqfsvwbwjlm#bp\t?nfwb#mbnf>!b``lnnlgbwjlm?,gju=\t?,gju=obqdf#sbqw#leJmpwjwvwf#elqwkf#pl.`boofg#bdbjmpw#wkf#Jm#wkjp#`bpf/tbp#bssljmwfg`objnfg#wl#afKltfufq/#wkjpGfsbqwnfmw#lewkf#qfnbjmjmdfeef`w#lm#wkfsbqwj`vobqoz#gfbo#tjwk#wkf\t?gju#pwzof>!bonlpw#botbzpbqf#`vqqfmwozf{sqfppjlm#leskjolplskz#leelq#nlqf#wkbm`jujojybwjlmplm#wkf#jpobmgpfof`wfgJmgf{`bm#qfpvow#jm!#ubovf>!!#,=wkf#pwqv`wvqf#,=?,b=?,gju=Nbmz#le#wkfpf`bvpfg#az#wkfle#wkf#Vmjwfgpsbm#`obpp>!n`bm#af#wqb`fgjp#qfobwfg#wlaf`bnf#lmf#lejp#eqfrvfmwozojujmd#jm#wkfwkflqfwj`boozElooltjmd#wkfQfulovwjlmbqzdlufqmnfmw#jmjp#gfwfqnjmfgwkf#slojwj`bojmwqlgv`fg#jmpveej`jfmw#wlgfp`qjswjlm!=pklqw#pwlqjfppfsbqbwjlm#lebp#wl#tkfwkfqhmltm#elq#jwptbp#jmjwjboozgjpsobz9aol`hjp#bm#f{bnsofwkf#sqjm`jsbo`lmpjpwp#le#bqf`ldmjyfg#bp,algz=?,kwno=b#pvapwbmwjboqf`lmpwqv`wfgkfbg#le#pwbwfqfpjpwbm`f#wlvmgfqdqbgvbwfWkfqf#bqf#wtldqbujwbwjlmbobqf#gfp`qjafgjmwfmwjlmboozpfqufg#bp#wkf`obpp>!kfbgfqlsslpjwjlm#wlevmgbnfmwboozglnjmbwfg#wkfbmg#wkf#lwkfqboojbm`f#tjwktbp#elq`fg#wlqfpsf`wjufoz/bmg#slojwj`bojm#pvsslqw#lesflsof#jm#wkf13wk#`fmwvqz-bmg#svaojpkfgolbg@kbqwafbwwl#vmgfqpwbmgnfnafq#pwbwfpfmujqlmnfmwboejqpw#kboe#le`lvmwqjfp#bmgbq`kjwf`wvqboaf#`lmpjgfqfg`kbqb`wfqjyfg`ofbqJmwfqubobvwklqjwbwjufEfgfqbwjlm#letbp#pv``ffgfgbmg#wkfqf#bqfb#`lmpfrvfm`fwkf#Sqfpjgfmwbopl#jm`ovgfgeqff#plewtbqfpv``fppjlm#legfufolsfg#wkftbp#gfpwqlzfgbtbz#eqln#wkf8\t?,p`qjsw=\t?bowklvdk#wkfzelooltfg#az#bnlqf#sltfqevoqfpvowfg#jm#bVmjufqpjwz#leKltfufq/#nbmzwkf#sqfpjgfmwKltfufq/#plnfjp#wklvdkw#wlvmwjo#wkf#fmgtbp#bmmlvm`fgbqf#jnslqwbmwbopl#jm`ovgfp=?jmsvw#wzsf>wkf#`fmwfq#le#GL#MLW#BOWFQvpfg#wl#qfefqwkfnfp, Assumes that end is an integer multiple of step.
- */
- private static void replicateValue(int[] table, int offset, int step, int end, int item) {
- do {
- end -= step;
- table[offset + end] = item;
- } while (end > 0);
- }
-
- /**
- * @param count histogram of bit lengths for the remaining symbols,
- * @param len code length of the next processed symbol.
- * @return table width of the next 2nd level table.
- */
- private static int nextTableBitSize(int[] count, int len, int rootBits) {
- int left = 1 << (len - rootBits);
- while (len < MAX_LENGTH) {
- left -= count[len];
- if (left <= 0) {
- break;
- }
- len++;
- left <<= 1;
- }
- return len - rootBits;
- }
-
- /**
- * Builds Huffman lookup table assuming code lengths are in symbol order.
- *
- * @return number of slots used by resulting Huffman table
- */
- static int buildHuffmanTable(int[] tableGroup, int tableIdx, int rootBits, int[] codeLengths,
- int codeLengthsSize) {
- final int tableOffset = tableGroup[tableIdx];
- int key; // Reversed prefix code.
- final int[] sorted = new int[codeLengthsSize]; // Symbols sorted by code length.
- // TODO(eustas): fill with zeroes?
- final int[] count = new int[MAX_LENGTH + 1]; // Number of codes of each length.
- final int[] offset = new int[MAX_LENGTH + 1]; // Offsets in sorted table for each length.
- int symbol;
-
- // Build histogram of code lengths.
- for (symbol = 0; symbol < codeLengthsSize; symbol++) {
- count[codeLengths[symbol]]++;
- }
-
- // Generate offsets into sorted symbol table by code length.
- offset[1] = 0;
- for (int len = 1; len < MAX_LENGTH; len++) {
- offset[len + 1] = offset[len] + count[len];
- }
-
- // Sort symbols by length, by symbol order within each length.
- for (symbol = 0; symbol < codeLengthsSize; symbol++) {
- if (codeLengths[symbol] != 0) {
- sorted[offset[codeLengths[symbol]]++] = symbol;
- }
- }
-
- int tableBits = rootBits;
- int tableSize = 1 << tableBits;
- int totalSize = tableSize;
-
- // Special case code with only one value.
- if (offset[MAX_LENGTH] == 1) {
- for (key = 0; key < totalSize; key++) {
- tableGroup[tableOffset + key] = sorted[0];
- }
- return totalSize;
- }
-
- // Fill in root table.
- key = 0;
- symbol = 0;
- for (int len = 1, step = 2; len <= rootBits; len++, step <<= 1) {
- for (; count[len] > 0; count[len]--) {
- replicateValue(tableGroup, tableOffset + key, step, tableSize,
- len << 16 | sorted[symbol++]);
- key = getNextKey(key, len);
- }
- }
-
- // Fill in 2nd level tables and add pointers to root table.
- final int mask = totalSize - 1;
- int low = -1;
- int currentOffset = tableOffset;
- for (int len = rootBits + 1, step = 2; len <= MAX_LENGTH; len++, step <<= 1) {
- for (; count[len] > 0; count[len]--) {
- if ((key & mask) != low) {
- currentOffset += tableSize;
- tableBits = nextTableBitSize(count, len, rootBits);
- tableSize = 1 << tableBits;
- totalSize += tableSize;
- low = key & mask;
- tableGroup[tableOffset + low] =
- (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);
- }
- replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize,
- (len - rootBits) << 16 | sorted[symbol++]);
- key = getNextKey(key, len);
- }
- }
- return totalSize;
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/State.java b/firka_wear/android/app/src/main/java/org/brotli/dec/State.java
deleted file mode 100644
index 94db93ab..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/State.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.InputStream;
-
-final class State {
- byte[] ringBuffer;
- byte[] contextModes;
- byte[] contextMap;
- byte[] distContextMap;
- byte[] distExtraBits;
- byte[] output;
- byte[] byteBuffer; // BitReader
-
- short[] shortBuffer; // BitReader
-
- int[] intBuffer; // BitReader
- int[] rings;
- int[] blockTrees;
- int[] literalTreeGroup;
- int[] commandTreeGroup;
- int[] distanceTreeGroup;
- int[] distOffset;
-
- long accumulator64; // BitReader: pre-fetched bits.
-
- int runningState; // Default value is 0 == Decode.UNINITIALIZED
- int nextRunningState;
- int accumulator32; // BitReader: pre-fetched bits.
- int bitOffset; // BitReader: bit-reading position in accumulator.
- int halfOffset; // BitReader: offset of next item in intBuffer/shortBuffer.
- int tailBytes; // BitReader: number of bytes in unfinished half.
- int endOfStreamReached; // BitReader: input stream is finished.
- int metaBlockLength;
- int inputEnd;
- int isUncompressed;
- int isMetadata;
- int literalBlockLength;
- int numLiteralBlockTypes;
- int commandBlockLength;
- int numCommandBlockTypes;
- int distanceBlockLength;
- int numDistanceBlockTypes;
- int pos;
- int maxDistance;
- int distRbIdx;
- int trivialLiteralContext;
- int literalTreeIdx;
- int commandTreeIdx;
- int j;
- int insertLength;
- int contextMapSlice;
- int distContextMapSlice;
- int contextLookupOffset1;
- int contextLookupOffset2;
- int distanceCode;
- int numDirectDistanceCodes;
- int distancePostfixBits;
- int distance;
- int copyLength;
- int maxBackwardDistance;
- int maxRingBufferSize;
- int ringBufferSize;
- int expectedTotalSize;
- int outputOffset;
- int outputLength;
- int outputUsed;
- int ringBufferBytesWritten;
- int ringBufferBytesReady;
- int isEager;
- int isLargeWindow;
-
- // Compound dictionary
- int cdNumChunks;
- int cdTotalSize;
- int cdBrIndex;
- int cdBrOffset;
- int cdBrLength;
- int cdBrCopied;
- byte[][] cdChunks;
- int[] cdChunkOffsets;
- int cdBlockBits;
- byte[] cdBlockMap;
-
- InputStream /* @Nullable */ input; // BitReader
-
- State() {
- this.ringBuffer = new byte[0];
- this.rings = new int[10];
- this.rings[0] = 16;
- this.rings[1] = 15;
- this.rings[2] = 11;
- this.rings[3] = 4;
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/Transform.java b/firka_wear/android/app/src/main/java/org/brotli/dec/Transform.java
deleted file mode 100644
index 6a57a9ec..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/Transform.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.nio.ByteBuffer;
-
-/**
- * Transformations on dictionary words.
- *
- * Transform descriptor is a triplet: {prefix, operator, suffix}.
- * "prefix" and "suffix" are short strings inserted before and after transformed dictionary word.
- * "operator" is applied to dictionary word itself.
- *
- * Some operators has "built-in" parameters, i.e. parameter is defined by operator ordinal. Other
- * operators have "external" parameters, supplied via additional table encoded in shared dictionary.
- *
- * Operators:
- * - IDENTITY (0): dictionary word is inserted "as is"
- * - OMIT_LAST_N (1 - 9): last N octets of dictionary word are not inserted; N == ordinal
- * - OMIT_FIRST_M (12-20): first M octets of dictionary word are not inserted; M == ordinal - 11
- * - UPPERCASE_FIRST (10): first "scalar" is XOR'ed with number 32
- * - UPPERCASE_ALL (11): all "scalars" are XOR'ed with number 32
- * - SHIFT_FIRST (21): first "scalar" is shifted by number form parameter table
- * - SHIFT_ALL (22): all "scalar" is shifted by number form parameter table
- *
- * Here "scalar" is a variable length character coding similar to UTF-8 encoding.
- * UPPERCASE_XXX / SHIFT_XXX operators were designed to change the case of UTF-8 encoded characters.
- * While UPPERCASE_XXX works well only on ASCII charset, SHIFT is much more generic and could be
- * used for most (all?) alphabets.
- */
-final class Transform {
-
- static final class Transforms {
- final int numTransforms;
- final int[] triplets;
- final byte[] prefixSuffixStorage;
- final int[] prefixSuffixHeads;
- final short[] params;
-
- Transforms(int numTransforms, int prefixSuffixLen, int prefixSuffixCount) {
- this.numTransforms = numTransforms;
- this.triplets = new int[numTransforms * 3];
- this.params = new short[numTransforms];
- this.prefixSuffixStorage = new byte[prefixSuffixLen];
- this.prefixSuffixHeads = new int[prefixSuffixCount + 1];
- }
- }
-
- static final int NUM_RFC_TRANSFORMS = 121;
- static final Transforms RFC_TRANSFORMS = new Transforms(NUM_RFC_TRANSFORMS, 167, 50);
-
- private static final int OMIT_FIRST_LAST_LIMIT = 9;
-
- private static final int IDENTITY = 0;
- private static final int OMIT_LAST_BASE = IDENTITY + 1 - 1; // there is no OMIT_LAST_0.
- private static final int UPPERCASE_FIRST = OMIT_LAST_BASE + OMIT_FIRST_LAST_LIMIT + 1;
- private static final int UPPERCASE_ALL = UPPERCASE_FIRST + 1;
- private static final int OMIT_FIRST_BASE = UPPERCASE_ALL + 1 - 1; // there is no OMIT_FIRST_0.
- private static final int SHIFT_FIRST = OMIT_FIRST_BASE + OMIT_FIRST_LAST_LIMIT + 1;
- private static final int SHIFT_ALL = SHIFT_FIRST + 1;
-
- // Bundle of 0-terminated strings.
- private static final String PREFIX_SUFFIX_SRC = "# #s #, #e #.# the #.com/#\u00C2\u00A0# of # and"
- + " # in # to #\"#\">#\n#]# for # a # that #. # with #'# from # by #. The # on # as # is #ing"
- + " #\n\t#:#ed #(# at #ly #=\"# of the #. This #,# not #er #al #='#ful #ive #less #est #ize #"
- + "ous #";
- private static final String TRANSFORMS_SRC = " !! ! , *! &! \" ! ) * * - ! # ! #!*! "
- + "+ ,$ ! - % . / # 0 1 . \" 2 3!* 4% ! # / 5 6 7 8 0 1 & $ 9 + : "
- + " ; < ' != > ?! 4 @ 4 2 & A *# ( B C& ) % ) !*# *-% A +! *. D! %' & E *6 F "
- + " G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D "
- + " Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K";
-
- private static void unpackTransforms(byte[] prefixSuffix,
- int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) {
- final int n = prefixSuffixSrc.length();
- int index = 1;
- int j = 0;
- for (int i = 0; i < n; ++i) {
- final char c = prefixSuffixSrc.charAt(i);
- if (c == 35) { // == #
- prefixSuffixHeads[index++] = j;
- } else {
- prefixSuffix[j++] = (byte) c;
- }
- }
-
- for (int i = 0; i < NUM_RFC_TRANSFORMS * 3; ++i) {
- transforms[i] = transformsSrc.charAt(i) - 32;
- }
- }
-
- static {
- unpackTransforms(RFC_TRANSFORMS.prefixSuffixStorage, RFC_TRANSFORMS.prefixSuffixHeads,
- RFC_TRANSFORMS.triplets, PREFIX_SUFFIX_SRC, TRANSFORMS_SRC);
- }
-
- static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset,
- int len, Transforms transforms, int transformIndex) {
- int offset = dstOffset;
- final int[] triplets = transforms.triplets;
- final byte[] prefixSuffixStorage = transforms.prefixSuffixStorage;
- final int[] prefixSuffixHeads = transforms.prefixSuffixHeads;
- final int transformOffset = 3 * transformIndex;
- final int prefixIdx = triplets[transformOffset];
- final int transformType = triplets[transformOffset + 1];
- final int suffixIdx = triplets[transformOffset + 2];
- int prefix = prefixSuffixHeads[prefixIdx];
- final int prefixEnd = prefixSuffixHeads[prefixIdx + 1];
- int suffix = prefixSuffixHeads[suffixIdx];
- final int suffixEnd = prefixSuffixHeads[suffixIdx + 1];
-
- int omitFirst = transformType - OMIT_FIRST_BASE;
- int omitLast = transformType - OMIT_LAST_BASE;
- if (omitFirst < 1 || omitFirst > OMIT_FIRST_LAST_LIMIT) {
- omitFirst = 0;
- }
- if (omitLast < 1 || omitLast > OMIT_FIRST_LAST_LIMIT) {
- omitLast = 0;
- }
-
- // Copy prefix.
- while (prefix != prefixEnd) {
- dst[offset++] = prefixSuffixStorage[prefix++];
- }
-
- // Copy trimmed word.
- if (omitFirst > len) {
- omitFirst = len;
- }
- srcOffset += omitFirst;
- len -= omitFirst;
- len -= omitLast;
- int i = len;
- while (i > 0) {
- dst[offset++] = src.get(srcOffset++);
- i--;
- }
-
- // Ferment.
- if (transformType == UPPERCASE_FIRST || transformType == UPPERCASE_ALL) {
- int uppercaseOffset = offset - len;
- if (transformType == UPPERCASE_FIRST) {
- len = 1;
- }
- while (len > 0) {
- final int c0 = dst[uppercaseOffset] & 0xFF;
- if (c0 < 0xC0) {
- if (c0 >= 97 && c0 <= 122) { // in [a..z] range
- dst[uppercaseOffset] ^= (byte) 32;
- }
- uppercaseOffset += 1;
- len -= 1;
- } else if (c0 < 0xE0) {
- dst[uppercaseOffset + 1] ^= (byte) 32;
- uppercaseOffset += 2;
- len -= 2;
- } else {
- dst[uppercaseOffset + 2] ^= (byte) 5;
- uppercaseOffset += 3;
- len -= 3;
- }
- }
- } else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) {
- int shiftOffset = offset - len;
- final short param = transforms.params[transformIndex];
- /* Limited sign extension: scalar < (1 << 24). */
- int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000));
- while (len > 0) {
- int step = 1;
- final int c0 = dst[shiftOffset] & 0xFF;
- if (c0 < 0x80) {
- /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
- scalar += c0;
- dst[shiftOffset] = (byte) (scalar & 0x7F);
- } else if (c0 < 0xC0) {
- /* Continuation / 10AAAAAA. */
- } else if (c0 < 0xE0) {
- /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
- if (len >= 2) {
- final byte c1 = dst[shiftOffset + 1];
- scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
- dst[shiftOffset] = (byte) (0xC0 | ((scalar >> 6) & 0x1F));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | (scalar & 0x3F));
- step = 2;
- } else {
- step = len;
- }
- } else if (c0 < 0xF0) {
- /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
- if (len >= 3) {
- final byte c1 = dst[shiftOffset + 1];
- final byte c2 = dst[shiftOffset + 2];
- scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
- dst[shiftOffset] = (byte) (0xE0 | ((scalar >> 12) & 0x0F));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
- dst[shiftOffset + 2] = (byte) ((c2 & 0xC0) | (scalar & 0x3F));
- step = 3;
- } else {
- step = len;
- }
- } else if (c0 < 0xF8) {
- /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
- if (len >= 4) {
- final byte c1 = dst[shiftOffset + 1];
- final byte c2 = dst[shiftOffset + 2];
- final byte c3 = dst[shiftOffset + 3];
- scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
- dst[shiftOffset] = (byte) (0xF0 | ((scalar >> 18) & 0x07));
- dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));
- dst[shiftOffset + 2] = (byte) ((c2 & 0xC0) | ((scalar >> 6) & 0x3F));
- dst[shiftOffset + 3] = (byte) ((c3 & 0xC0) | (scalar & 0x3F));
- step = 4;
- } else {
- step = len;
- }
- }
- shiftOffset += step;
- len -= step;
- if (transformType == SHIFT_FIRST) {
- len = 0;
- }
- }
- }
-
- // Copy suffix.
- while (suffix != suffixEnd) {
- dst[offset++] = prefixSuffixStorage[suffix++];
- }
-
- return offset - dstOffset;
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/dec/Utils.java b/firka_wear/android/app/src/main/java/org/brotli/dec/Utils.java
deleted file mode 100644
index cc4a9f0d..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/dec/Utils.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright 2015 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.dec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-
-/**
- * A set of utility methods.
- */
-final class Utils {
-
- private static final byte[] BYTE_ZEROES = new byte[1024];
-
- private static final int[] INT_ZEROES = new int[1024];
-
- /**
- * Fills byte array with zeroes.
- *
- * Current implementation uses {@link System#arraycopy}, so it should be used for length not
- * less than 16.
- *
- * @param dest array to fill with zeroes
- * @param offset the first byte to fill
- * @param length number of bytes to change
- */
- static void fillBytesWithZeroes(byte[] dest, int start, int end) {
- int cursor = start;
- while (cursor < end) {
- int step = Math.min(cursor + 1024, end) - cursor;
- System.arraycopy(BYTE_ZEROES, 0, dest, cursor, step);
- cursor += step;
- }
- }
-
- /**
- * Fills int array with zeroes.
- *
- * Current implementation uses {@link System#arraycopy}, so it should be used for length not
- * less than 16.
- *
- * @param dest array to fill with zeroes
- * @param offset the first item to fill
- * @param length number of item to change
- */
- static void fillIntsWithZeroes(int[] dest, int start, int end) {
- int cursor = start;
- while (cursor < end) {
- int step = Math.min(cursor + 1024, end) - cursor;
- System.arraycopy(INT_ZEROES, 0, dest, cursor, step);
- cursor += step;
- }
- }
-
- static void copyBytes(byte[] dst, int target, byte[] src, int start, int end) {
- System.arraycopy(src, start, dst, target, end - start);
- }
-
- static void copyBytesWithin(byte[] bytes, int target, int start, int end) {
- System.arraycopy(bytes, start, bytes, target, end - start);
- }
-
- static int readInput(InputStream src, byte[] dst, int offset, int length) {
- try {
- return src.read(dst, offset, length);
- } catch (IOException e) {
- throw new BrotliRuntimeException("Failed to read input", e);
- }
- }
-
- static void closeInput(InputStream src) throws IOException {
- src.close();
- }
-
- static byte[] toUsAsciiBytes(String src) {
- try {
- // NB: String#getBytes(String) is present in JDK 1.1, while other variants require JDK 1.6 and
- // above.
- return src.getBytes("US-ASCII");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // cannot happen
- }
- }
-
- static ByteBuffer asReadOnlyBuffer(ByteBuffer src) {
- return src.asReadOnlyBuffer();
- }
-
- static int isReadOnly(ByteBuffer src) {
- return src.isReadOnly() ? 1 : 0;
- }
-
- static int isDirect(ByteBuffer src) {
- return src.isDirect() ? 1 : 0;
- }
-
- // Crazy pills factory: code compiled for JDK8 does not work on JRE9.
- static void flipBuffer(Buffer buffer) {
- buffer.flip();
- }
-
- static int isDebugMode() {
- boolean assertsEnabled = Boolean.parseBoolean(System.getProperty("BROTLI_ENABLE_ASSERTS"));
- return assertsEnabled ? 1 : 0;
- }
-
- // See BitReader.LOG_BITNESS
- static int getLogBintness() {
- boolean isLongExpensive = Boolean.parseBoolean(System.getProperty("BROTLI_32_BIT_CPU"));
- return isLongExpensive ? 5 : 6;
- }
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java b/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java
deleted file mode 100644
index 51978015..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionary.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Copyright 2018 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.enc;
-
-import java.nio.ByteBuffer;
-
-/**
- * Prepared dictionary data provider.
- */
-public interface PreparedDictionary {
- ByteBuffer getData();
-}
diff --git a/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java b/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java
deleted file mode 100644
index 3813429c..00000000
--- a/firka_wear/android/app/src/main/java/org/brotli/enc/PreparedDictionaryGenerator.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Copyright 2017 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.enc;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
-
-/**
- * Java prepared (raw) dictionary producer.
- */
-public class PreparedDictionaryGenerator {
-
- private static final int MAGIC = 0xDEBCEDE0;
- private static final long HASH_MULTIPLIER = 0x1fe35a7bd3579bd3L;
-
- private static class PreparedDictionaryImpl implements PreparedDictionary {
- private final ByteBuffer data;
-
- private PreparedDictionaryImpl(ByteBuffer data) {
- this.data = data;
- }
-
- @Override
- public ByteBuffer getData() {
- return data;
- }
- }
-
- // Disallow instantiation.
- private PreparedDictionaryGenerator() { }
-
- public static PreparedDictionary generate(ByteBuffer src) {
- return generate(src, 17, 3, 40, 5);
- }
-
- public static PreparedDictionary generate(ByteBuffer src,
- int bucketBits, int slotBits, int hashBits, int blockBits) {
- ((Buffer) src).clear(); // Just in case...
- if (blockBits > 12) {
- throw new IllegalArgumentException("blockBits is too big");
- }
- if (bucketBits >= 24) {
- throw new IllegalArgumentException("bucketBits is too big");
- }
- if (bucketBits - slotBits >= 16) {
- throw new IllegalArgumentException("slotBits is too small");
- }
- int bucketLimit = 1 << blockBits;
- int numBuckets = 1 << bucketBits;
- int numSlots = 1 << slotBits;
- int slotMask = numSlots - 1;
- int hashShift = 64 - bucketBits;
- long hashMask = (~0L) >>> (64 - hashBits);
- int sourceSize = src.capacity();
- if (sourceSize < 8) {
- throw new IllegalArgumentException("src is too short");
- }
-
- /* Step 1: create "bloated" hasher. */
- short[] num = new short[numBuckets];
- int[] bucketHeads = new int[numBuckets];
- int[] nextBucket = new int[sourceSize];
-
- long accumulator = 0;
- for (int i = 0; i < 7; ++i) {
- accumulator |= (src.get(i) & 0xFFL) << (8 * i);
- }
- accumulator <<= 8;
- /* TODO(eustas): apply custom "store" order. */
- for (int i = 0; i + 7 < sourceSize; ++i) {
- accumulator = (accumulator >>> 8) | ((src.get(i + 7) & 0xFFL) << 56);
- long h = (accumulator & hashMask) * HASH_MULTIPLIER;
- int key = (int) (h >>> hashShift);
- int count = num[key];
- nextBucket[i] = (count == 0) ? -1 : bucketHeads[key];
- bucketHeads[key] = i;
- count++;
- if (count > bucketLimit) {
- count = bucketLimit;
- }
- num[key] = (short) count;
- }
-
- /* Step 2: find slot limits. */
- int[] slotLimit = new int[numSlots];
- int[] slotSize = new int[numSlots];
- int totalItems = 0;
- for (int i = 0; i < numSlots; ++i) {
- boolean overflow = false;
- slotLimit[i] = bucketLimit;
- while (true) {
- overflow = false;
- int limit = slotLimit[i];
- int count = 0;
- for (int j = i; j < numBuckets; j += numSlots) {
- int size = num[j];
- /* Last chain may span behind 64K limit; overflow happens only if
- we are about to use 0xFFFF+ as item offset. */
- if (count >= 0xFFFF) {
- overflow = true;
- break;
- }
- if (size > limit) {
- size = limit;
- }
- count += size;
- }
- if (!overflow) {
- slotSize[i] = count;
- totalItems += count;
- break;
- }
- slotLimit[i]--;
- }
- }
-
- /* Step 3: transfer data to "slim" hasher. */
- int part0 = 6 * 4;
- int part1 = numSlots * 4;
- int part2 = numBuckets * 2;
- int part3 = totalItems * 4;
- int allocSize = part0 + part1 + part2 + part3 + sourceSize;
- ByteBuffer flat = ByteBuffer.allocateDirect(allocSize);
- ByteBuffer pointer = flat.slice();
- pointer.order(ByteOrder.nativeOrder());
-
- IntBuffer struct = pointer.asIntBuffer();
- pointer.position(pointer.position() + part0);
- IntBuffer slotOffsets = pointer.asIntBuffer();
- pointer.position(pointer.position() + part1);
- ShortBuffer heads = pointer.asShortBuffer();
- pointer.position(pointer.position() + part2);
- IntBuffer items = pointer.asIntBuffer();
- pointer.position(pointer.position() + part3);
- ByteBuffer sourceCopy = pointer.slice();
-
- /* magic */ struct.put(0, MAGIC);
- /* source_offset */ struct.put(1, totalItems);
- /* source_size */ struct.put(2, sourceSize);
- /* hash_bits */ struct.put(3, hashBits);
- /* bucket_bits */ struct.put(4, bucketBits);
- /* slot_bits */ struct.put(5, slotBits);
-
- totalItems = 0;
- for (int i = 0; i < numSlots; ++i) {
- slotOffsets.put(i, totalItems);
- totalItems += slotSize[i];
- slotSize[i] = 0;
- }
-
- for (int i = 0; i < numBuckets; ++i) {
- int slot = i & slotMask;
- int count = num[i];
- if (count > slotLimit[slot]) {
- count = slotLimit[slot];
- }
- if (count == 0) {
- heads.put(i, (short) 0xFFFF);
- continue;
- }
- int cursor = slotSize[slot];
- heads.put(i, (short) cursor);
- cursor += slotOffsets.get(slot);
- slotSize[slot] += count;
- int pos = bucketHeads[i];
- for (int j = 0; j < count; j++) {
- items.put(cursor++, pos);
- pos = nextBucket[pos];
- }
- cursor--;
- items.put(cursor, items.get(cursor) | 0x80000000);
- }
-
- sourceCopy.put(src);
-
- return new PreparedDictionaryImpl(flat);
- }
-}
!sbqhpnlvpfNlpw#---?,bnlmdaqbjmalgz#mlmf8abpfg`bqqzgqbewqfefqsbdf\\klnf-nfwfqgfobzgqfbnsqlufiljmw?,wq=gqvdp?\"..#bsqjojgfboboofmf{b`welqwk`lgfpoldj`Ujft#pffnpaobmhslqwp#+133pbufg\\ojmhdlbopdqbmwdqffhklnfpqjmdpqbwfg03s{8tklpfsbqpf+*8!#Aol`hojmv{ilmfpsj{fo$*8!=*8je+.ofewgbujgklqpfEl`vpqbjpfal{fpWqb`hfnfmw?,fn=abq!=-pq`>wltfqbow>!`baofkfmqz17s{8pfwvsjwbozpkbqsnjmlqwbpwftbmwpwkjp-qfpfwtkffodjqop,`pp,233&8`ovappwveeajaofulwfp#2333hlqfb~*8\u000E\tabmgprvfvf>#x~8;3s{8`hjmdx\u000E\t\n\nbkfbg`ol`hjqjpkojhf#qbwjlpwbwpElqn!zbkll*X3^8Balvwejmgp?,k2=gfavdwbphpVQO#>`foop~*+*821s{8sqjnfwfoopwvqmp3{533-isd!psbjmafb`kwb{fpnj`qlbmdfo..=?,djewppwfuf.ojmhalgz-~*8\t\nnlvmw#+2::EBR?,qldfqeqbmh@obpp1;s{8effgp?k2=?p`lwwwfpwp11s{8gqjmh*#\u007F\u007F#oftjppkboo 30:8#elq#olufgtbpwf33s{8ib9\u000Fnpjnlm?elmwqfsoznffwpvmwfq`kfbswjdkwAqbmg*#\">#gqfpp`ojspqllnplmhfznlajonbjm-Mbnf#sobwfevmmzwqffp`ln,!2-isdtnlgfsbqbnPWBQWofew#jggfm/#132*8\t~\telqn-ujqvp`kbjqwqbmptlqpwSbdfpjwjlmsbw`k?\"..\tl.`b`ejqnpwlvqp/333#bpjbmj((*xbglaf$*X3^jg>23alwk8nfmv#-1-nj-smd!hfujm`lb`k@kjogaqv`f1-isdVQO*(-isd\u007Fpvjwfpoj`fkbqqz213!#ptffwwq=\u000E\tmbnf>gjfdlsbdf#ptjpp..=\t\t eee8!=Old-`ln!wqfbwpkffw*#%%#27s{8poffsmwfmwejofgib9\u000Fojg>!`Mbnf!tlqpfpklwp.al{.gfowb\t%ow8afbqp97;Y?gbwb.qvqbo?,b=#psfmgabhfqpklsp>#!!8sks!=`wjlm20s{8aqjbmkfoolpjyf>l>&1E#iljmnbzaf?jnd#jnd!=/#eipjnd!#!*X3^NWlsAWzsf!mftozGbmph`yf`kwqbjohmltp?,k6=ebr!=yk.`m23*8\t.2!*8wzsf>aovfpwqvozgbujp-ip$8=\u000E\t?\"pwffo#zlv#k1=\u000E\telqn#ifpvp233nfmv-\u000E\t\n\u000E\ttbofpqjphpvnfmwggjmda.ojhwfb`kdje!#ufdbpgbmphffpwjpkrjspvlnjplaqfgfpgffmwqfwlglpsvfgfb/]lpfpw/Mwjfmfkbpwblwqlpsbqwfglmgfmvfulkb`fqelqnbnjpnlnfilqnvmglbrv/Ag/Abpp/_olbzvgbef`kbwlgbpwbmwlnfmlpgbwlplwqbppjwjlnv`klbklqbovdbqnbzlqfpwlpklqbpwfmfqbmwfpelwlpfpwbpsb/Apmvfubpbovgelqlpnfgjlrvjfmnfpfpslgfq`kjofpfq/Muf`fpgf`jqilp/Efpwbqufmwbdqvslkf`klfoolpwfmdlbnjdl`lpbpmjufodfmwfnjpnbbjqfpivojlwfnbpkb`jbebulqivmjlojaqfsvmwlavfmlbvwlqbaqjoavfmbwf{wlnbqylpbafqojpwbovfdl`/_nlfmfqlivfdlsfq/Vkbafqfpwlzmvm`bnvifqubolqevfqbojaqldvpwbjdvboulwlp`bplpdv/Absvfglplnlpbujplvpwfggfafmml`kfavp`bebowbfvqlppfqjfgj`kl`vqpl`obuf`bpbpof/_msobylobqdllaqbpujpwbbslzlivmwlwqbwbujpwl`qfbq`bnslkfnlp`jm`l`bqdlsjplplqgfmkb`fm/Mqfbgjp`lsfgql`fq`bsvfgbsbsfonfmlq/Vwjo`obqlilqdf`boofslmfqwbqgfmbgjfnbq`bpjdvffoobppjdol`l`kfnlwlpnbgqf`obpfqfpwlmj/]lrvfgbsbpbqabm`lkjilpujbifsbaol/Epwfujfmfqfjmlgfibqelmgl`bmbomlqwfofwqb`bvpbwlnbqnbmlpovmfpbvwlpujoobufmglsfpbqwjslpwfmdbnbq`loofubsbgqfvmjglubnlpylmbpbnalpabmgbnbqjbbavplnv`kbpvajqqjlibujujqdqbgl`kj`bboo/Ailufmgj`kbfpwbmwbofppbojqpvfolsfplpejmfpoobnbavp`l/Epwboofdbmfdqlsobybkvnlqsbdbqivmwbglaofjpobpalopbab/]lkbaobov`kb/mqfbgj`fmivdbqmlwbpuboofboo/M`bqdbglolqbabilfpw/Edvpwlnfmwfnbqjlejqnb`lpwlej`kbsobwbkldbqbqwfpofzfpbrvfonvpflabpfpsl`lpnjwbg`jfol`kj`lnjfgldbmbqpbmwlfwbsbgfafpsobzbqfgfppjfwf`lqwf`lqfbgvgbpgfpflujfilgfpfbbdvbp%rvlw8glnbjm`lnnlmpwbwvpfufmwpnbpwfqpzpwfnb`wjlmabmmfqqfnlufp`qloovsgbwfdolabonfgjvnejowfqmvnafq`kbmdfqfpvowsvaoj`p`qffm`kllpfmlqnbowqbufojppvfpplvq`fwbqdfwpsqjmdnlgvofnlajofptjw`ksklwlpalqgfqqfdjlmjwpfoepl`jbob`wjuf`lovnmqf`lqgelooltwjwof=fjwkfqofmdwkebnjozeqjfmgobzlvwbvwklq`qfbwfqfujftpvnnfqpfqufqsobzfgsobzfqf{sbmgsloj`zelqnbwglvaofsljmwppfqjfpsfqplmojujmdgfpjdmnlmwkpelq`fpvmjrvftfjdkwsflsoffmfqdzmbwvqfpfbq`kejdvqfkbujmd`vpwlnleepfwofwwfqtjmgltpvanjwqfmgfqdqlvspvsolbgkfbowknfwklgujgflpp`klloevwvqfpkbgltgfabwfubovfpLaif`wlwkfqpqjdkwpofbdvf`kqlnfpjnsofmlwj`fpkbqfgfmgjmdpfbplmqfslqwlmojmfprvbqfavwwlmjnbdfpfmbaofnlujmdobwfpwtjmwfqEqbm`fsfqjlgpwqlmdqfsfbwOlmglmgfwbjoelqnfggfnbmgpf`vqfsbppfgwlddofsob`fpgfuj`fpwbwj``jwjfppwqfbnzfooltbwwb`hpwqffweojdkwkjggfmjmel!=lsfmfgvpfevouboofz`bvpfpofbgfqpf`qfwpf`lmggbnbdfpslqwpf{`fswqbwjmdpjdmfgwkjmdpfeef`wejfogppwbwfpleej`fujpvbofgjwlqulovnfQfslqwnvpfvnnlujfpsbqfmwb``fppnlpwoznlwkfq!#jg>!nbqhfwdqlvmg`kbm`fpvqufzafelqfpznalonlnfmwpsff`knlwjlmjmpjgfnbwwfq@fmwfqlaif`wf{jpwpnjggofFvqlsfdqltwkofdb`znbmmfqfmlvdk`bqffqbmptfqlqjdjmslqwbo`ojfmwpfof`wqbmgln`olpfgwlsj`p`lnjmdebwkfqlswjlmpjnsozqbjpfgfp`bsf`klpfm`kvq`kgfejmfqfbplm`lqmfqlvwsvwnfnlqzjeqbnfsloj`fnlgfopMvnafqgvqjmdleefqppwzofphjoofgojpwfg`boofgpjoufqnbqdjmgfofwfafwwfqaqltpfojnjwpDolabopjmdoftjgdfw`fmwfqavgdfwmltqbs`qfgjw`objnpfmdjmfpbefwz`klj`fpsjqjw.pwzofpsqfbgnbhjmdmffgfgqvppjbsofbpff{wfmwP`qjswaqlhfmbooltp`kbqdfgjujgfeb`wlqnfnafq.abpfgwkflqz`lmejdbqlvmgtlqhfgkfosfg@kvq`kjnsb`wpklvogbotbzpoldl!#alwwlnojpw!=*xubq#sqfej{lqbmdfKfbgfq-svpk+`lvsofdbqgfmaqjgdfobvm`kQfujftwbhjmdujpjlmojwwofgbwjmdAvwwlmafbvwzwkfnfpelqdlwPfbq`kbm`klqbonlpwolbgfg@kbmdfqfwvqmpwqjmdqfolbgNlajofjm`lnfpvssozPlvq`flqgfqpujftfg%maps8`lvqpfBalvw#jpobmg?kwno#`llhjfmbnf>!bnbylmnlgfqmbguj`fjm?,b=9#Wkf#gjboldklvpfpAFDJM#Nf{j`lpwbqwp`fmwqfkfjdkwbggjmdJpobmgbppfwpFnsjqfP`kllofeelqwgjqf`wmfbqoznbmvboPfof`w-\t\tLmfiljmfgnfmv!=SkjojsbtbqgpkbmgofjnslqwLeej`fqfdbqgphjoopmbwjlmPslqwpgfdqfftffhoz#+f-d-afkjmggl`wlqolddfgvmjwfg?,a=?,afdjmpsobmwpbppjpwbqwjpwjppvfg033s{\u007F`bmbgbbdfm`zp`kfnfqfnbjmAqbyjopbnsofoldl!=afzlmg.p`bofb``fswpfqufgnbqjmfEllwfq`bnfqb?,k2=\t\\elqn!ofbufppwqfpp!#,=\u000E\t-dje!#lmolbgolbgfqL{elqgpjpwfqpvqujuojpwfmefnbofGfpjdmpjyf>!bssfbowf{w!=ofufopwkbmhpkjdkfqelq`fgbmjnbobmzlmfBeqj`bbdqffgqf`fmwSflsof?aq#,=tlmgfqsqj`fpwvqmfg\u007F\u007F#x~8nbjm!=jmojmfpvmgbztqbs!=ebjofg`fmpvpnjmvwfafb`lmrvlwfp263s{\u007Ffpwbwfqfnlwffnbjo!ojmhfgqjdkw8pjdmboelqnbo2-kwnopjdmvssqjm`feolbw9-smd!#elqvn-B``fppsbsfqpplvmgpf{wfmgKfjdkwpojgfqVWE.;!%bns8#Afelqf-#TjwkpwvgjlltmfqpnbmbdfsqlejwiRvfqzbmmvbosbqbnpalvdkwebnlvpdlldofolmdfqj((*#xjpqbfopbzjmdgf`jgfklnf!=kfbgfqfmpvqfaqbm`ksjf`fpaol`h8pwbwfgwls!=?qb`jmdqfpjyf..%dw8sb`jwzpf{vboavqfbv-isd!#23/333lawbjmwjwofpbnlvmw/#Jm`-`lnfgznfmv!#ozqj`pwlgbz-jmgffg`lvmwz\\oldl-EbnjozollhfgNbqhfwopf#jeSobzfqwvqhfz*8ubq#elqfpwdjujmdfqqlqpGlnbjm~fopfxjmpfqwAold?,ellwfqoldjm-ebpwfqbdfmwp?algz#23s{#3sqbdnbeqjgbzivmjlqgloobqsob`fg`lufqpsovdjm6/333#sbdf!=alpwlm-wfpw+bubwbqwfpwfg\\`lvmwelqvnpp`kfnbjmgf{/ejoofgpkbqfpqfbgfqbofqw+bssfbqPvanjwojmf!=algz!=\t)#WkfWklvdkpffjmdifqpfzMftp?,ufqjezf{sfqwjmivqztjgwk>@llhjfPWBQW#b`qlpp\\jnbdfwkqfbgmbwjufsl`hfwal{!=\tPzpwfn#Gbujg`bm`fqwbaofpsqlufgBsqjo#qfboozgqjufqjwfn!=nlqf!=albqgp`lolqp`bnsvpejqpw#\u007F\u007F#X^8nfgjb-dvjwbqejmjpktjgwk9pkltfgLwkfq#-sks!#bppvnfobzfqptjoplmpwlqfpqfojfeptfgfm@vpwlnfbpjoz#zlvq#Pwqjmd\t\tTkjowbzolq`ofbq9qfplqweqfm`kwklvdk!*#(#!?algz=avzjmdaqbmgpNfnafqmbnf!=lssjmdpf`wlq6s{8!=upsb`fslpwfqnbilq#`leeffnbqwjmnbwvqfkbssfm?,mbu=hbmpbpojmh!=Jnbdfp>ebopftkjof#kpsb`f3%bns8#\t\tJm##sltfqSlophj.`lolqilqgbmAlwwlnPwbqw#.`lvmw1-kwnomftp!=32-isdLmojmf.qjdkwnjoofqpfmjlqJPAM#33/333#dvjgfpubovf*f`wjlmqfsbjq-{no!##qjdkwp-kwno.aol`hqfdF{s9klufqtjwkjmujqdjmsklmfp?,wq=\u000Evpjmd#\t\nubq#=$*8\t\n?,wg=\t?,wq=\tabkbpbaqbpjodbofdlnbdzbqslophjpqsphj4]4C5d\bTA\nzk\u000BBl\bQ\u007F\u000BUm\u0005Gx\bSM\nmC\bTA\twQ\nd}\bW@\bTl\bTF\ti@\tcT\u000BBM\u000B|j\u0004BV\tqw\tcC\bWI\npa\tfM\n{Z\u0005{X\bTF\bVV\bVK\t\u007Fm\u0004kF\t[]\bPm\bTv\nsI\u000Bpg\t[I\bQp\u0004mx\u000B_W\n^M\npe\u000BQ}\u000BGu\nel\npe\u0004Ch\u0004BV\bTA\tSo\nzk\u000BGL\u000BxD\nd[\u0005Jz\u0005MY\bQp\u0004li\nfl\npC\u0005{B\u0005Nt\u000BwT\ti_\bTg\u0004QQ\n|p\u000BXN\bQS\u000BxD\u0004QC\bWZ\tpD\u000BVS\bTW\u0005Nt\u0004Yh\nzu\u0004Kj\u0005N}\twr\tHa\n_D\tj`\u000BQ}\u000BWp\nxZ\u0004{c\tji\tBU\nbD\u0004a|\tTn\tpV\nZd\nmC\u000BEV\u0005{X\tc}\tTo\bWl\bUd\tIQ\tcg\u000Bxs\nXW\twR\u000Bek\tc}\t]y\tJn\nrp\neg\npV\nz\\\u0005{W\npl\nz\\\nzU\tPc\t`{\bV@\nc|\bRw\ti_\bVb\nwX\tHv\u0004Su\bTF\u000B_W\u000BWs\u000BsI\u0005m\u007F\nTT\ndc\tUS\t}f\tiZ\bWz\tc}\u0004MD\tBe\tiD\u000B@@\bTl\bPv\t}t\u0004Sw\u0004M`\u000BnU\tkW\u000Bed\nqo\u000BxY\tA|\bTz\u000By`\u0004BR\u0004BM\tia\u0004XU\nyu\u0004n^\tfL\tiI\nXW\tfD\bWz\bW@\tyj\t\u007Fm\tav\tBN\u000Bb\\\tpD\bTf\nY[\tJn\bQy\t[^\u000BWc\u000Byu\u0004Dl\u0004CJ\u000BWj\u000BHR\t`V\u000BuW\tQy\np@\u000BGu\u0005pl\u0004Jm\bW[\nLP\nxC\n`m\twQ\u0005ui\u0005\u007FR\nbI\twQ\tBZ\tWV\u0004BR\npg\tcg\u0005ti\u0004CW\n_y\tRg\bQa\u000BQB\u000BWc\nYb\u0005le\ngE\u0004Su\nL[\tQ\u007F\tea\tdj\u000B]W\nb~\u0004M`\twL\bTV\bVH\nt\u007F\npl\t|b\u0005s_\bU|\bTa\u0004oQ\u0005lv\u0004Sk\u0004M`\bTv\u000BK}\nfl\tcC\u0004oQ\u0004BR\tHk\t|d\bQp\tHK\tBZ\u000BHR\bPv\u000BLx\u000BEZ\bT\u007F\bTv\tiD\u0005oD\u0005MU\u000BwB\u0004Su\u0005k`\u0004St\ntC\tPl\tKg\noi\tjY\u000BxY\u0004h}\nzk\bWZ\t\u007Fm\u000Be`\tTB\tfE\nzk\t`z\u0004Yh\nV|\tHK\tAJ\tAJ\bUL\tp\\\tql\nYc\u0004Kd\nfy\u0004Yh\t[I\u000BDg\u0004Jm\n]n\nlb\bUd\n{Z\tlu\tfs\u0004oQ\bTW\u0004Jm\u000BwB\tea\u0004Yh\u0004BC\tsb\tTn\nzU\n_y\u000BxY\tQ]\ngw\u0004mt\tO\\\ntb\bWW\bQy\tmI\tV[\ny\\\naB\u000BRb\twQ\n]Q\u0004QJ\bWg\u000BWa\bQj\ntC\bVH\nYm\u000Bxs\bVK\nel\bWI\u000BxY\u0004Cq\ntR\u000BHV\bTl\bVw\tay\bQa\bVV\t}t\tdj\nr|\tp\\\twR\n{i\nTT\t[I\ti[\tAJ\u000Bxs\u000B_W\td{\u000BQ}\tcg\tTz\tA|\tCj\u000BLm\u0005N}\u0005m\u007F\nbK\tdZ\tp\\\t`V\tsV\np@\tiD\twQ\u000BQ}\bTf\u0005ka\u0004Jm\u000B@@\bV`\tzp\n@N\u0004Sw\tiI\tcg\noi\u0004Su\bVw\u0004lo\u0004Cy\tc}\u000Bb\\\tsU\u0004BA\bWI\bTf\nxS\tVp\nd|\bTV\u000BbC\tNo\u0005Ju\nTC\t|`\n{Z\tD]\bU|\tc}\u0005lm\bTl\tBv\tPl\tc}\bQp\t\u007Fm\nLk\tkj\n@N\u0004Sb\u0004KO\tj_\tp\\\nzU\bTl\bTg\bWI\tcf\u0004XO\bWW\ndz\u0004li\tBN\nd[\bWO\u0004MD\u000BKC\tdj\tI_\bVV\ny\\\u000BLm\u0005xl\txB\tkV\u000Bb\\\u000BJW\u000BVS\tVx\u000BxD\td{\u0004MD\bTa\t|`\u000BPz\u0004R}\u000BWs\u0004BM\nsI\u0004CN\bTa\u0004Jm\npe\ti_\npV\nrh\tRd\tHv\n~A\nxR\u000BWh\u000BWk\nxS\u000BAz\u000BwX\nbI\u0004oQ\tfw\nqI\nV|\nun\u0005z\u007F\u000Bpg\td\\\u000BoA\u0005{D\ti_\u0005xB\bT\u007F\t`V\u0005qr\tTT\u0004g]\u0004CA\u000BuR\tVJ\tT`\npw\u000BRb\tI_\nCx\u0004Ro\u000BsI\u0004Cj\u0004Kh\tBv\tWV\u0004BB\u0005oD\u0005{D\nhc\u0004Km\u000B^R\tQE\n{I\np@\nc|\u0005Gt\tc}\u0004Dl\nzU\u0005qN\tsV\u0005k}\tHh\u000B|j\nqo\u0005u|\tQ]\u000Bek\u0005\u007FZ\u0004M`\u0004St\npe\tdj\bVG\u000BeE\t\u007Fm\u000BWc\u0004|I\n[W\tfL\bT\u007F\tBZ\u0004Su\u000BKa\u0004Cq\u0005Nt\u0004Y[\nqI\bTv\tfM\ti@\t}f\u0004B\\\tQy\u000BBl\bWg\u0004XD\u0005kc\u000Bx[\bVV\tQ]\t\u007Fa\tPy\u000BxD\nfI\t}f\u0005oD\tdj\tSG\u0005ls\t~D\u0004CN\n{Z\t\\v\n_D\nhc\u000Bx_\u0004C[\tAJ\nLM\tVx\u0004CI\tbj\tc^\tcF\ntC\u0004Sx\twr\u0004XA\bU\\\t|a\u000BK\\\bTV\bVj\nd|\tfs\u0004CX\ntb\bRw\tVx\tAE\tA|\bT\u007F\u0005Nt\u000BDg\tVc\bTl\u0004d@\npo\t\u007FM\tcF\npe\tiZ\tBo\bSq\nfH\u0004l`\bTx\bWf\tHE\u000BF{\tcO\tfD\nlm\u000BfZ\nlm\u000BeU\tdG\u0004BH\bTV\tSi\u0005MW\nwX\nz\\\t\\c\u0004CX\nd}\tl}\bQp\bTV\tF~\bQ\u007F\t`i\ng@\u0005nO\bUd\bTl\nL[\twQ\tji\ntC\t|J\nLU\naB\u000BxY\u0004Kj\tAJ\u0005uN\ti[\npe\u0004Sk\u000BDg\u000Bx]\bVb\bVV\nea\tkV\nqI\bTa\u0004Sk\nAO\tpD\ntb\nts\nyi\bVg\ti_\u000B_W\nLk\u0005Nt\tyj\tfM\u0004R\u007F\tiI\bTl\u000BwX\tsV\u000BMl\nyu\tAJ\bVj\u0004KO\tWV\u000BA}\u000BW\u007F\nrp\tiD\u000B|o\u0005lv\u000BsI\u0004BM\td~\tCU\bVb\u0004eV\npC\u000BwT\tj`\tc}\u000Bxs\u000Bps\u000Bvh\tWV\u000BGg\u000BAe\u000BVK\u000B]W\trg\u000BWc\u0005F`\tBr\u000Bb\\\tdZ\bQp\nqI\u0004kF\nLk\u000BAR\bWI\bTg\tbs\tdw\n{L\n_y\tiZ\bTA\tlg\bVV\bTl\tdk\n`k\ta{\ti_\u0005{A\u0005wj\twN\u000B@@\bTe\ti_\n_D\twL\nAH\u000BiK\u000Bek\n[]\tp_\tyj\bTv\tUS\t[r\n{I\nps\u0005Gt\u000BVK\npl\u0004S}\u000BWP\t|d\u0004MD\u000BHV\bT\u007F\u0004R}\u0004M`\bTV\bVH\u0005lv\u0004Ch\bW[\u0004Ke\tR{\u000B^R\tab\tBZ\tVA\tB`\nd|\nhs\u0004Ke\tBe\u0004Oi\tR{\td\\\u0005nB\bWZ\tdZ\tVJ\u0005Os\t\u007Fm\u0004uQ\u000BhZ\u0004Q@\u0004QQ\nfI\bW[\u0004B\\\u0004li\nzU\nMd\u0004M`\nxS\bVV\n\\}\u000BxD\t\u007Fm\bTp\u0004IS\nc|\tkV\u0005i~\tV{\u000BhZ\t|b\bWt\n@R\u000BoA\u000BnU\bWI\tea\tB`\tiD\tc}\tTz\u0004BR\u000BQB\u0005Nj\tCP\t[I\bTv\t`W\u0005uN\u000Bpg\u000Bpg\u000BWc\tiT\tbs\twL\tU_\tc\\\t|h\u000BKa\tNr\tfL\nq|\nzu\nz\\\tNr\bUg\t|b\u0004m`\bTv\nyd\nrp\bWf\tUX\u0004BV\nzk\nd}\twQ\t}f\u0004Ce\u000Bed\bTW\bSB\nxU\tcn\bTb\ne\u007F\ta\\\tSG\bU|\npV\nN\\\u0004Kn\u000BnU\tAt\tpD\u000B^R\u000BIr\u0004b[\tR{\tdE\u000BxD\u000BWK\u000BWA\bQL\bW@\u0004Su\bUd\nDM\tPc\u0004CA\u0004Dl\u0004oQ\tHs\u0005wi\u0004ub\n\u007Fa\bQp\u0005Ob\nLP\bTl\u0004Y[\u000BK}\tAJ\bQ\u007F\u0004n^\u000BsA\bSM\nqM\bWZ\n^W\u000Bz{\u0004S|\tfD\bVK\bTv\bPv\u0004BB\tCP\u0004dF\tid\u000Bxs\u0004mx\u000Bws\tcC\ntC\tyc\u0005M`\u000BW\u007F\nrh\bQp\u000BxD\u0004\\o\nsI\u0004_k\nzu\u0004kF\tfD\u0004Xs\u0004XO\tjp\bTv\u0004BS\u0005{B\tBr\nzQ\nbI\tc{\u0004BD\u0004BV\u0005nO\bTF\tca\u0005Jd\tfL\tPV\tI_\nlK\u0004`o\twX\npa\tgu\bP}\u0005{^\bWf\n{I\tBN\npa\u0004Kl\u000Bpg\tcn\tfL\u000Bvh\u0004Cq\bTl\u000BnU\bSq\u0004Cm\twR\bUJ\npe\nyd\nYg\u0004Cy\u000BKW\tfD\nea\u0004oQ\tj_\tBv\u0004nM\u000BID\bTa\nzA\u0005pl\n]n\bTa\tR{\tfr\n_y\bUg\u0005{X\u0005kk\u000BxD\u0004|I\u0005xl\nfy\u0004Ce\u000BwB\nLk\u000Bd]\noi\n}h\tQ]\npe\bVw\u0004Hk\u0004OQ\nzk\tAJ\npV\bPv\ny\\\tA{\u0004Oi\bSB\u0004XA\u000BeE\tjp\nq}\tiD\u0005qN\u000B^R\t\u007Fm\tiZ\tBr\bVg\noi\n\\X\tU_\nc|\u000BHV\bTf\tTn\u0004\\N\u0004\\N\nuB\u0005lv\nyu\tTd\bTf\bPL\u000B]W\tdG\nA`\nw^\ngI\npe\tdw\nz\\\u0005ia\bWZ\tcF\u0004Jm\n{Z\bWO\u0004_k\u0004Df\u0004RR\td\\\bVV\u000Bxs\u0004BN\u0005ti\u0004lm\tTd\t]y\u000BHV\tSo\u000B|j\u0004XX\tA|\u000BZ^\u000BGu\bTW\u0005M`\u0004kF\u000BhZ\u000BVK\tdG\u000BBl\tay\nxU\u0005qE\u0005nO\bVw\nqI\u0004CX\ne\u007F\tPl\bWO\u000BLm\tdL\u0005uH\u0004Cm\tdT\u0004fn\u000BwB\u0005ka\u000BnU\n@M\nyT\tHv\t\\}\u0004Kh\td~\u0004Yh\u0005k}\neR\td\\\bWI\t|b\tHK\tiD\bTW\u0005MY\npl\bQ_\twr\u000BAx\tHE\bTg\bSq\u0005vp\u000Bb\\\bWO\nOl\nsI\nfy\u000BID\t\\c\n{Z\n^~\npe\nAO\tTT\u000Bxv\u0004k_\bWO\u000B|j\u000BwB\tQy\ti@\tPl\tHa\tdZ\u0005k}\u0004ra\tUT\u000BJc\u000Bed\np@\tQN\nd|\tkj\tHk\u0004M`\noi\twr\td\\\nlq\no_\nlb\nL[\tac\u0004BB\u0004BH\u0004Cm\npl\tIQ\bVK\u000Bxs\n`e\u000BiK\npa\u0004Oi\tUS\bTp\tfD\nPG\u0005kk\u0004XA\nz\\\neg\u000BWh\twR\u0005qN\nqS\tcn\u0004lo\nxS\n^W\tBU\nt\u007F\tHE\tp\\\tfF\tfw\bVV\bW@\tak\u000BVK\u0005ls\tVJ\bVV\u000BeE\u0004\\o\nyX\nYm\u0004M`\u0005lL\nd|\nzk\tA{\u0005sE\twQ\u0004XT\nt\u007F\tPl\t]y\u000BwT\u0005{p\u0004MD\u000Bb\\\tQ]\u0004Kj\tJn\nAH\u000BRb\tBU\tHK\t\\c\nfI\u0005m\u007F\nqM\n@R\tSo\noi\u0004BT\tHv\n_y\u0004Kh\tBZ\t]i\bUJ\tV{\u0004Sr\nbI\u000BGg\ta_\bTR\nfI\nfl\t[K\tII\u0004S|\u000BuW\tiI\bWI\nqI\u000B|j\u0004BV\bVg\bWZ\u0004kF\u000Bx]\bTA\tab\tfr\ti@\tJd\tJd\u000Bps\nAO\bTa\u0005xu\tiD\nzk\t|d\t|`\bW[\tlP\tdG\bVV\u000Bw}\u000BqO\ti[\bQ\u007F\bTz\u000BVF\twN\u0005ts\tdw\bTv\neS\ngi\tNr\u0005yS\npe\bVV\bSq\n`m\tyj\tBZ\u000BWX\bSB\tc\\\nUR\t[J\tc_\u0004nM\bWQ\u000BAx\nMd\tBr\u0005ui\u000BxY\bSM\u000BWc\u000B|j\u000Bxs\t}Q\tBO\bPL\bWW\tfM\nAO\tPc\u000BeU\u0004e^\bTg\nqI\tac\bPv\tcF\u0004oQ\tQ\u007F\u000BhZ\u0005ka\nz\\\tiK\tBU\n`k\tCP\u0004S|\u0004M`\n{I\tS{\u0004_O\tBZ\u0004Zi\u0004Sk\tps\tp\\\nYu\n]s\nxC\bWt\nbD\tkV\u000BGu\u0005yS\nqA\t[r\neK\u0004M`\tdZ\u0005lL\bUg\bTl\nbD\tUS\u000Bb\\\tpV\ncc\u0004S\\\tct\t`z\bPL\u000BWs\nA`\neg\bSq\u0005uE\u0004CR\u000BDg\t`W\u000Bz{\u000BWc\u0004Sk\u0004Sk\tbW\bUg\tea\nxZ\tiI\tUX\tVJ\nqn\tS{\u000BRb\bTQ\npl\u0005Gt\u000BuW\u0005uj\npF\nqI\tfL\t[I\tia\u0004XO\nyu\u000BDg\u000Bed\tq{\u0004VG\bQ\u007F\u0005ka\tVj\tkV\txB\nd|\np@\tQN\tPc\tps\u0004]j\tkV\toU\bTp\nzU\u0005nB\u000BB]\ta{\bV@\n]n\u0004m`\tcz\tR{\u0004m`\bQa\u000BwT\bSM\u0005MY\u0005qN\tdj\u0005~s\u000BQ}\u0005MY\u000BMB\tBv\twR\bRg\u000BQ}\tql\u000BKC\nrm\u0005xu\u0004CC\u000BwB\u000Bvh\tBq\u0004Xq\npV\ti_\u0005Ob\u0005uE\nbd\nqo\u000B{i\nC~\tBL\u000BeE\u0005uH\bVj\u0004Ey\u0004Gz\u000BzR\u000B{i\tcf\n{Z\n]n\u0004XA\u000BGu\u000BnU\thS\u000BGI\nCc\tHE\bTA\tHB\u0004BH\u0004Cj\nCc\bTF\tHE\nXI\tA{\bQ\u007F\tc\\\u000BmO\u000BWX\nfH\np@\u0005MY\bTF\nlK\tBt\nzU\tTT\u0004Km\u000BwT\npV\ndt\u000ByI\tVx\tQ\u007F\tRg\tTd\nzU\bRS\nLM\twA\u0004nM\tTn\ndS\t]g\nLc\u000BwB\t}t\t[I\tCP\u0004kX\u000BFm\u000BhZ\u0005m\u007F\ti[\np@\u000BQ}\u000BW\u007F\t|d\nMO\nMd\tf_\tfD\tcJ\tHz\u000BRb\tio\tPy\u0004Y[\nxU\tct\u000B@@\tww\bPv\u0004BM\u0004FF\ntb\u0005v|\u000BKm\tBq\tBq\u0004Kh\u0004`o\nZd\u0004XU\ti]\t|`\tSt\u0004B\\\bQ\u007F\u000B_W\tTJ\nqI\t|a\tA{\u000BuP\u0004MD\tPl\nxR\tfL\u000Bws\tc{\td\\\bV`\neg\tHK\u0005kc\nd|\bVV\ny\\\u0005kc\ti]\bVG\t`V\tss\tI_\tAE\tbs\tdu\nel\tpD\u000BW\u007F\nqs\u0005lv\bSM\u0004Zi\u000BVK\u0005ia\u000BQB\tQ\u007F\n{Z\bPt\u000BKl\nlK\nhs\ndS\bVK\u0005mf\nd^\tkV\tcO\nc|\bVH\t\\]\bTv\bSq\tmI\u000BDg\tVJ\tcn\ny\\\bVg\bTv\nyX\bTF\t]]\bTp\noi\nhs\u000BeU\nBf\tdj\u0005Mr\n|p\t\\g\t]r\bVb\u0005{D\nd[\u0004XN\tfM\tO\\\u0005s_\tcf\tiZ\u0004XN\u000BWc\tqv\n`m\tU^\u0005oD\nd|\u000BGg\tdE\u000Bwf\u0004lo\u0004u}\nd|\u0005oQ\t`i\u0004Oi\u000BxD\ndZ\nCx\u0004Yw\nzk\ntb\ngw\tyj\tB`\nyX\u000Bps\ntC\u000BpP\u000Bqw\bPu\bPX\tDm\npw\u0005Nj\tss\taG\u000Bxs\bPt\noL\u0004Gz\tOk\ti@\ti]\u0004eC\tIQ\tii\tdj\u000B@J\t|d\u0005uh\bWZ\u000BeU\u000BnU\bTa\tcC\u0004g]\nzk\u0004Yh\bVK\nLU\np@\ntb\ntR\tCj\u000BNP\ti@\bP{\n\\}\n{c\nwX\tfL\bVG\tc{\t|`\tAJ\t|C\tfD\u0005ln\t|d\tbs\nqI\u0005{B\u000BAx\np@\nzk\u000BRb\u0005Os\u000BWS\u0004e^\u000BD_\tBv\u000BWd\bVb\u000Bxs\u000BeE\bRw\n]n\n|p\u000Bg|\tfw\u0005kc\bTI\u0005ka\n\\T\u0004Sp\tju\u000Bps\npe\u0005u|\u000BGr\bVe\tCU\u0004]M\u0004XU\u000BxD\bTa\tIQ\u000BWq\tCU\tam\tdj\bSo\u0004Sw\u000BnU\u0004Ch\tQ]\u0005s_\bPt\tfS\bTa\t\\}\n@O\u0004Yc\tUZ\bTx\npe\u000BnU\nzU\t|}\tiD\nz\\\bSM\u000BxD\u0004BR\nzQ\tQN\u0004]M\u0004Yh\nLP\u000BFm\u000BLX\u0005vc\u000Bql\u0005ka\tHK\bVb\ntC\nCy\bTv\nuV\u0004oQ\t`z\t[I\tB`\u000BRb\tyj\tsb\u000BWs\bTl\tkV\u000Bed\ne\u007F\u0005lL\u000BxN\t\u007Fm\nJn\tjY\u000BxD\bVb\bSq\u000Byu\twL\u000BXL\bTA\tpg\tAt\tnD\u0004XX\twR\npl\nhw\u0005yS\nps\tcO\bW[\u000B|j\u0004XN\tsV\tp\\\tBe\nb~\nAJ\n]e\u0005k`\u0005qN\tdw\tWV\tHE\u000BEV\u0005Jz\tid\tB`\tzh\u0005E]\tfD\bTg\u0005qN\bTa\tja\u0004Cv\bSM\nhc\bUe\u0005t_\tie\u0004g]\twQ\nPn\bVB\tjw\bVg\u000BbE\tBZ\u000BRH\bP{\tjp\n\\}\ta_\tcC\t|a\u000BD]\tBZ\ti[\tfD\u000BxW\no_\td\\\n_D\ntb\t\\c\tAJ\nlK\u0004oQ\u0004lo\u000BLx\u000BM@\bWZ\u0004Kn\u000Bpg\nTi\nIv\n|r\u000B@}\u0005Jz\u0005Lm\u0005Wh\u0005k}\u0005ln\u000BxD\n]s\u0004gc\u000Bps\tBr\bTW\u000BBM\u0005tZ\nBY\u0004DW\tjf\u000BSW\u0004C}\nqo\tdE\tmv\tIQ\bPP\bUb\u0005lv\u0004BC\nzQ\t[I\u000Bgl\nig\bUs\u0004BT\u000BbC\bSq\tsU\tiW\nJn\tSY\tHK\trg\npV\u000BID\u000B|j\u0004KO\t`S\t|a`vbmglfmujbqnbgqjgavp`bqjmj`jlwjfnslslqrvf`vfmwbfpwbglsvfgfmivfdlp`lmwqbfpw/Mmmlnaqfwjfmfmsfqejonbmfqbbnjdlp`jvgbg`fmwqlbvmrvfsvfgfpgfmwqlsqjnfqsqf`jlpfd/Vmavfmlpuloufqsvmwlppfnbmbkba/Abbdlpwlmvfulpvmjglp`bqolpfrvjslmj/]lpnv`klpbodvmb`lqqfljnbdfmsbqwjqbqqjabnbq/Abklnaqffnsoflufqgbg`bnajlnv`kbpevfqlmsbpbglo/Amfbsbqf`fmvfubp`vqplpfpwbabrvjfqlojaqlp`vbmwlb``fplnjdvfoubqjlp`vbwqlwjfmfpdqvslppfq/Mmfvqlsbnfgjlpeqfmwfb`fq`bgfn/Mplefqwb`l`kfpnlgfoljwbojbofwqbpbod/Vm`lnsqb`vbofpf{jpwf`vfqslpjfmglsqfmpboofdbqujbifpgjmfqlnvq`jbslgq/Msvfpwlgjbqjlsvfaolrvjfqfnbmvfosqlsjl`qjpjp`jfqwlpfdvqlnvfqwfevfmwf`fqqbqdqbmgffef`wlsbqwfpnfgjgbsqlsjbleqf`fwjfqqbf.nbjoubqjbpelqnbpevwvqllaifwlpfdvjqqjfpdlmlqnbpnjpnlp/Vmj`l`bnjmlpjwjlpqby/_mgfajglsqvfabwlofglwfm/Abifp/Vpfpsfql`l`jmblqjdfmwjfmgb`jfmwl`/Mgjykbaobqpfq/Abobwjmbevfqybfpwjoldvfqqbfmwqbq/E{jwlo/_sfybdfmgbu/Agflfujwbqsbdjmbnfwqlpibujfqsbgqfpe/M`jo`bafyb/Mqfbppbojgbfmu/Alibs/_mbavplpajfmfpwf{wlpoofubqsvfgbmevfqwf`ln/Vm`obpfpkvnbmlwfmjglajoablvmjgbgfpw/Mpfgjwbq`qfbgl
!sbqhpnlvpfNlpw#---?,bnlmdaqbjmalgz#mlmf8abpfg`bqqzgqbewqfefqsbdf\\klnf-nfwfqgfobzgqfbnsqlufiljmw?,wq=gqvdp?\"..#bsqjojgfboboofmf{b`welqwk`lgfpoldj`Ujft#pffnpaobmhslqwp#+133pbufg\\ojmhdlbopdqbmwdqffhklnfpqjmdpqbwfg03s{8tklpfsbqpf+*8!#Aol`hojmv{ilmfpsj{fo$*8!=*8je+.ofewgbujgklqpfEl`vpqbjpfal{fpWqb`hfnfmw?,fn=abq!=-pq`>wltfqbow>!`baofkfmqz17s{8pfwvsjwbozpkbqsnjmlqwbpwftbmwpwkjp-qfpfwtkffodjqop,`pp,233&8`ovappwveeajaofulwfp#2333hlqfb~*8\u000E\tabmgprvfvf>#x~8;3s{8`hjmdx\u000E\t\n\nbkfbg`ol`hjqjpkojhf#qbwjlpwbwpElqn!zbkll*X3^8Balvwejmgp?,k2=gfavdwbphpVQO#>`foop~*+*821s{8sqjnfwfoopwvqmp3{533-isd!psbjmafb`kwb{fpnj`qlbmdfo..=?,djewppwfuf.ojmhalgz-~*8\t\nnlvmw#+2::EBR?,qldfqeqbmh@obpp1;s{8effgp?k2=?p`lwwwfpwp11s{8gqjmh*#\u007F\u007F#oftjppkboo 30:8#elq#olufgtbpwf33s{8ib9\u000Fnpjnlm?elmwqfsoznffwpvmwfq`kfbswjdkwAqbmg*#\">#gqfpp`ojspqllnplmhfznlajonbjm-Mbnf#sobwfevmmzwqffp`ln,!2-isdtnlgfsbqbnPWBQWofew#jggfm/#132*8\t~\telqn-ujqvp`kbjqwqbmptlqpwSbdfpjwjlmsbw`k?\"..\tl.`b`ejqnpwlvqp/333#bpjbmj((*xbglaf$*X3^jg>23alwk8nfmv#-1-nj-smd!hfujm`lb`k@kjogaqv`f1-isdVQO*(-isd\u007Fpvjwfpoj`fkbqqz213!#ptffwwq=\u000E\tmbnf>gjfdlsbdf#ptjpp..=\t\t eee8!=Old-`ln!wqfbwpkffw*#%%#27s{8poffsmwfmwejofgib9\u000Fojg>!`Mbnf!tlqpfpklwp.al{.gfowb\t%ow8afbqp97;Y?gbwb.qvqbo?,b=#psfmgabhfqpklsp>#!!8sks!=`wjlm20s{8aqjbmkfoolpjyf>l>&1E#iljmnbzaf?jnd#jnd!=/#eipjnd!#!*X3^NWlsAWzsf!mftozGbmph`yf`kwqbjohmltp?,k6=ebr!=yk.`m23*8\t.2!*8wzsf>aovfpwqvozgbujp-ip$8=\u000E\t?\"pwffo#zlv#k1=\u000E\telqn#ifpvp233nfmv-\u000E\t\n\u000E\ttbofpqjphpvnfmwggjmda.ojhwfb`kdje!#ufdbpgbmphffpwjpkrjspvlnjplaqfgfpgffmwqfwlglpsvfgfb/]lpfpw/Mwjfmfkbpwblwqlpsbqwfglmgfmvfulkb`fqelqnbnjpnlnfilqnvmglbrv/Ag/Abpp/_olbzvgbef`kbwlgbpwbmwlnfmlpgbwlplwqbppjwjlnv`klbklqbovdbqnbzlqfpwlpklqbpwfmfqbmwfpelwlpfpwbpsb/Apmvfubpbovgelqlpnfgjlrvjfmnfpfpslgfq`kjofpfq/Muf`fpgf`jqilp/Efpwbqufmwbdqvslkf`klfoolpwfmdlbnjdl`lpbpmjufodfmwfnjpnbbjqfpivojlwfnbpkb`jbebulqivmjlojaqfsvmwlavfmlbvwlqbaqjoavfmbwf{wlnbqylpbafqojpwbovfdl`/_nlfmfqlivfdlsfq/Vkbafqfpwlzmvm`bnvifqubolqevfqbojaqldvpwbjdvboulwlp`bplpdv/Absvfglplnlpbujplvpwfggfafmml`kfavp`bebowbfvqlppfqjfgj`kl`vqpl`obuf`bpbpof/_msobylobqdllaqbpujpwbbslzlivmwlwqbwbujpwl`qfbq`bnslkfnlp`jm`l`bqdlsjplplqgfmkb`fm/Mqfbgjp`lsfgql`fq`bsvfgbsbsfonfmlq/Vwjo`obqlilqdf`boofslmfqwbqgfmbgjfnbq`bpjdvffoobppjdol`l`kfnlwlpnbgqf`obpfqfpwlmj/]lrvfgbsbpbqabm`lkjilpujbifsbaol/Epwfujfmfqfjmlgfibqelmgl`bmbomlqwfofwqb`bvpbwlnbqnbmlpovmfpbvwlpujoobufmglsfpbqwjslpwfmdbnbq`loofubsbgqfvmjglubnlpylmbpbnalpabmgbnbqjbbavplnv`kbpvajqqjlibujujqdqbgl`kj`bboo/Ailufmgj`kbfpwbmwbofppbojqpvfolsfplpejmfpoobnbavp`l/Epwboofdbmfdqlsobybkvnlqsbdbqivmwbglaofjpobpalopbab/]lkbaobov`kb/mqfbgj`fmivdbqmlwbpuboofboo/M`bqdbglolqbabilfpw/Edvpwlnfmwfnbqjlejqnb`lpwlej`kbsobwbkldbqbqwfpofzfpbrvfonvpflabpfpsl`lpnjwbg`jfol`kj`lnjfgldbmbqpbmwlfwbsbgfafpsobzbqfgfppjfwf`lqwf`lqfbgvgbpgfpflujfilgfpfbbdvbp%rvlw8glnbjm`lnnlmpwbwvpfufmwpnbpwfqpzpwfnb`wjlmabmmfqqfnlufp`qloovsgbwfdolabonfgjvnejowfqmvnafq`kbmdfqfpvowsvaoj`p`qffm`kllpfmlqnbowqbufojppvfpplvq`fwbqdfwpsqjmdnlgvofnlajofptjw`ksklwlpalqgfqqfdjlmjwpfoepl`jbob`wjuf`lovnmqf`lqgelooltwjwof=fjwkfqofmdwkebnjozeqjfmgobzlvwbvwklq`qfbwfqfujftpvnnfqpfqufqsobzfgsobzfqf{sbmgsloj`zelqnbwglvaofsljmwppfqjfpsfqplmojujmdgfpjdmnlmwkpelq`fpvmjrvftfjdkwsflsoffmfqdzmbwvqfpfbq`kejdvqfkbujmd`vpwlnleepfwofwwfqtjmgltpvanjwqfmgfqdqlvspvsolbgkfbowknfwklgujgflpp`klloevwvqfpkbgltgfabwfubovfpLaif`wlwkfqpqjdkwpofbdvf`kqlnfpjnsofmlwj`fpkbqfgfmgjmdpfbplmqfslqwlmojmfprvbqfavwwlmjnbdfpfmbaofnlujmdobwfpwtjmwfqEqbm`fsfqjlgpwqlmdqfsfbwOlmglmgfwbjoelqnfggfnbmgpf`vqfsbppfgwlddofsob`fpgfuj`fpwbwj``jwjfppwqfbnzfooltbwwb`hpwqffweojdkwkjggfmjmel!=lsfmfgvpfevouboofz`bvpfpofbgfqpf`qfwpf`lmggbnbdfpslqwpf{`fswqbwjmdpjdmfgwkjmdpfeef`wejfogppwbwfpleej`fujpvbofgjwlqulovnfQfslqwnvpfvnnlujfpsbqfmwb``fppnlpwoznlwkfq!#jg>!nbqhfwdqlvmg`kbm`fpvqufzafelqfpznalonlnfmwpsff`knlwjlmjmpjgfnbwwfq@fmwfqlaif`wf{jpwpnjggofFvqlsfdqltwkofdb`znbmmfqfmlvdk`bqffqbmptfqlqjdjmslqwbo`ojfmwpfof`wqbmgln`olpfgwlsj`p`lnjmdebwkfqlswjlmpjnsozqbjpfgfp`bsf`klpfm`kvq`kgfejmfqfbplm`lqmfqlvwsvwnfnlqzjeqbnfsloj`fnlgfopMvnafqgvqjmdleefqppwzofphjoofgojpwfg`boofgpjoufqnbqdjmgfofwfafwwfqaqltpfojnjwpDolabopjmdoftjgdfw`fmwfqavgdfwmltqbs`qfgjw`objnpfmdjmfpbefwz`klj`fpsjqjw.pwzofpsqfbgnbhjmdmffgfgqvppjbsofbpff{wfmwP`qjswaqlhfmbooltp`kbqdfgjujgfeb`wlqnfnafq.abpfgwkflqz`lmejdbqlvmgtlqhfgkfosfg@kvq`kjnsb`wpklvogbotbzpoldl!#alwwlnojpw!=*xubq#sqfej{lqbmdfKfbgfq-svpk+`lvsofdbqgfmaqjgdfobvm`kQfujftwbhjmdujpjlmojwwofgbwjmdAvwwlmafbvwzwkfnfpelqdlwPfbq`kbm`klqbonlpwolbgfg@kbmdfqfwvqmpwqjmdqfolbgNlajofjm`lnfpvssozPlvq`flqgfqpujftfg%maps8`lvqpfBalvw#jpobmg?kwno#`llhjfmbnf>!bnbylmnlgfqmbguj`fjm?,b=9#Wkf#gjboldklvpfpAFDJM#Nf{j`lpwbqwp`fmwqfkfjdkwbggjmdJpobmgbppfwpFnsjqfP`kllofeelqwgjqf`wmfbqoznbmvboPfof`w-\t\tLmfiljmfgnfmv!=SkjojsbtbqgpkbmgofjnslqwLeej`fqfdbqgphjoopmbwjlmPslqwpgfdqfftffhoz#+f-d-afkjmggl`wlqolddfgvmjwfg?,a=?,afdjmpsobmwpbppjpwbqwjpwjppvfg033s{\u007F`bmbgbbdfm`zp`kfnfqfnbjmAqbyjopbnsofoldl!=afzlmg.p`bofb``fswpfqufgnbqjmfEllwfq`bnfqb?,k2=\t\\elqn!ofbufppwqfpp!#,=\u000E\t-dje!#lmolbgolbgfqL{elqgpjpwfqpvqujuojpwfmefnbofGfpjdmpjyf>!bssfbowf{w!=ofufopwkbmhpkjdkfqelq`fgbmjnbobmzlmfBeqj`bbdqffgqf`fmwSflsof?aq#,=tlmgfqsqj`fpwvqmfg\u007F\u007F#x~8nbjm!=jmojmfpvmgbztqbs!=ebjofg`fmpvpnjmvwfafb`lmrvlwfp263s{\u007Ffpwbwfqfnlwffnbjo!ojmhfgqjdkw8pjdmboelqnbo2-kwnopjdmvssqjm`feolbw9-smd!#elqvn-B``fppsbsfqpplvmgpf{wfmgKfjdkwpojgfqVWE.;!%bns8#Afelqf-#TjwkpwvgjlltmfqpnbmbdfsqlejwiRvfqzbmmvbosbqbnpalvdkwebnlvpdlldofolmdfqj((*#xjpqbfopbzjmdgf`jgfklnf!=kfbgfqfmpvqfaqbm`ksjf`fpaol`h8pwbwfgwls!=?qb`jmdqfpjyf..%dw8sb`jwzpf{vboavqfbv-isd!#23/333lawbjmwjwofpbnlvmw/#Jm`-`lnfgznfmv!#ozqj`pwlgbz-jmgffg`lvmwz\\oldl-EbnjozollhfgNbqhfwopf#jeSobzfqwvqhfz*8ubq#elqfpwdjujmdfqqlqpGlnbjm~fopfxjmpfqwAold?,ellwfqoldjm-ebpwfqbdfmwp?algz#23s{#3sqbdnbeqjgbzivmjlqgloobqsob`fg`lufqpsovdjm6/333#sbdf!=alpwlm-wfpw+bubwbqwfpwfg\\`lvmwelqvnpp`kfnbjmgf{/ejoofgpkbqfpqfbgfqbofqw+bssfbqPvanjwojmf!=algz!=\t)#WkfWklvdkpffjmdifqpfzMftp?,ufqjezf{sfqwjmivqztjgwk>@llhjfPWBQW#b`qlpp\\jnbdfwkqfbgmbwjufsl`hfwal{!=\tPzpwfn#Gbujg`bm`fqwbaofpsqlufgBsqjo#qfboozgqjufqjwfn!=nlqf!=albqgp`lolqp`bnsvpejqpw#\u007F\u007F#X^8nfgjb-dvjwbqejmjpktjgwk9pkltfgLwkfq#-sks!#bppvnfobzfqptjoplmpwlqfpqfojfeptfgfm@vpwlnfbpjoz#zlvq#Pwqjmd\t\tTkjowbzolq`ofbq9qfplqweqfm`kwklvdk!*#(#!?algz=avzjmdaqbmgpNfnafqmbnf!=lssjmdpf`wlq6s{8!=upsb`fslpwfqnbilq#`leeffnbqwjmnbwvqfkbssfm?,mbu=hbmpbpojmh!=Jnbdfp>ebopftkjof#kpsb`f3%bns8#\t\tJm##sltfqSlophj.`lolqilqgbmAlwwlnPwbqw#.`lvmw1-kwnomftp!=32-isdLmojmf.qjdkwnjoofqpfmjlqJPAM#33/333#dvjgfpubovf*f`wjlmqfsbjq-{no!##qjdkwp-kwno.aol`hqfdF{s9klufqtjwkjmujqdjmsklmfp?,wq=\u000Evpjmd#\t\nubq#=$*8\t\n?,wg=\t?,wq=\tabkbpbaqbpjodbofdlnbdzbqslophjpqsphj4]4C5d\bTA\nzk\u000BBl\bQ\u007F\u000BUm\u0005Gx\bSM\nmC\bTA\twQ\nd}\bW@\bTl\bTF\ti@\tcT\u000BBM\u000B|j\u0004BV\tqw\tcC\bWI\npa\tfM\n{Z\u0005{X\bTF\bVV\bVK\t\u007Fm\u0004kF\t[]\bPm\bTv\nsI\u000Bpg\t[I\bQp\u0004mx\u000B_W\n^M\npe\u000BQ}\u000BGu\nel\npe\u0004Ch\u0004BV\bTA\tSo\nzk\u000BGL\u000BxD\nd[\u0005Jz\u0005MY\bQp\u0004li\nfl\npC\u0005{B\u0005Nt\u000BwT\ti_\bTg\u0004QQ\n|p\u000BXN\bQS\u000BxD\u0004QC\bWZ\tpD\u000BVS\bTW\u0005Nt\u0004Yh\nzu\u0004Kj\u0005N}\twr\tHa\n_D\tj`\u000BQ}\u000BWp\nxZ\u0004{c\tji\tBU\nbD\u0004a|\tTn\tpV\nZd\nmC\u000BEV\u0005{X\tc}\tTo\bWl\bUd\tIQ\tcg\u000Bxs\nXW\twR\u000Bek\tc}\t]y\tJn\nrp\neg\npV\nz\\\u0005{W\npl\nz\\\nzU\tPc\t`{\bV@\nc|\bRw\ti_\bVb\nwX\tHv\u0004Su\bTF\u000B_W\u000BWs\u000BsI\u0005m\u007F\nTT\ndc\tUS\t}f\tiZ\bWz\tc}\u0004MD\tBe\tiD\u000B@@\bTl\bPv\t}t\u0004Sw\u0004M`\u000BnU\tkW\u000Bed\nqo\u000BxY\tA|\bTz\u000By`\u0004BR\u0004BM\tia\u0004XU\nyu\u0004n^\tfL\tiI\nXW\tfD\bWz\bW@\tyj\t\u007Fm\tav\tBN\u000Bb\\\tpD\bTf\nY[\tJn\bQy\t[^\u000BWc\u000Byu\u0004Dl\u0004CJ\u000BWj\u000BHR\t`V\u000BuW\tQy\np@\u000BGu\u0005pl\u0004Jm\bW[\nLP\nxC\n`m\twQ\u0005ui\u0005\u007FR\nbI\twQ\tBZ\tWV\u0004BR\npg\tcg\u0005ti\u0004CW\n_y\tRg\bQa\u000BQB\u000BWc\nYb\u0005le\ngE\u0004Su\nL[\tQ\u007F\tea\tdj\u000B]W\nb~\u0004M`\twL\bTV\bVH\nt\u007F\npl\t|b\u0005s_\bU|\bTa\u0004oQ\u0005lv\u0004Sk\u0004M`\bTv\u000BK}\nfl\tcC\u0004oQ\u0004BR\tHk\t|d\bQp\tHK\tBZ\u000BHR\bPv\u000BLx\u000BEZ\bT\u007F\bTv\tiD\u0005oD\u0005MU\u000BwB\u0004Su\u0005k`\u0004St\ntC\tPl\tKg\noi\tjY\u000BxY\u0004h}\nzk\bWZ\t\u007Fm\u000Be`\tTB\tfE\nzk\t`z\u0004Yh\nV|\tHK\tAJ\tAJ\bUL\tp\\\tql\nYc\u0004Kd\nfy\u0004Yh\t[I\u000BDg\u0004Jm\n]n\nlb\bUd\n{Z\tlu\tfs\u0004oQ\bTW\u0004Jm\u000BwB\tea\u0004Yh\u0004BC\tsb\tTn\nzU\n_y\u000BxY\tQ]\ngw\u0004mt\tO\\\ntb\bWW\bQy\tmI\tV[\ny\\\naB\u000BRb\twQ\n]Q\u0004QJ\bWg\u000BWa\bQj\ntC\bVH\nYm\u000Bxs\bVK\nel\bWI\u000BxY\u0004Cq\ntR\u000BHV\bTl\bVw\tay\bQa\bVV\t}t\tdj\nr|\tp\\\twR\n{i\nTT\t[I\ti[\tAJ\u000Bxs\u000B_W\td{\u000BQ}\tcg\tTz\tA|\tCj\u000BLm\u0005N}\u0005m\u007F\nbK\tdZ\tp\\\t`V\tsV\np@\tiD\twQ\u000BQ}\bTf\u0005ka\u0004Jm\u000B@@\bV`\tzp\n@N\u0004Sw\tiI\tcg\noi\u0004Su\bVw\u0004lo\u0004Cy\tc}\u000Bb\\\tsU\u0004BA\bWI\bTf\nxS\tVp\nd|\bTV\u000BbC\tNo\u0005Ju\nTC\t|`\n{Z\tD]\bU|\tc}\u0005lm\bTl\tBv\tPl\tc}\bQp\t\u007Fm\nLk\tkj\n@N\u0004Sb\u0004KO\tj_\tp\\\nzU\bTl\bTg\bWI\tcf\u0004XO\bWW\ndz\u0004li\tBN\nd[\bWO\u0004MD\u000BKC\tdj\tI_\bVV\ny\\\u000BLm\u0005xl\txB\tkV\u000Bb\\\u000BJW\u000BVS\tVx\u000BxD\td{\u0004MD\bTa\t|`\u000BPz\u0004R}\u000BWs\u0004BM\nsI\u0004CN\bTa\u0004Jm\npe\ti_\npV\nrh\tRd\tHv\n~A\nxR\u000BWh\u000BWk\nxS\u000BAz\u000BwX\nbI\u0004oQ\tfw\nqI\nV|\nun\u0005z\u007F\u000Bpg\td\\\u000BoA\u0005{D\ti_\u0005xB\bT\u007F\t`V\u0005qr\tTT\u0004g]\u0004CA\u000BuR\tVJ\tT`\npw\u000BRb\tI_\nCx\u0004Ro\u000BsI\u0004Cj\u0004Kh\tBv\tWV\u0004BB\u0005oD\u0005{D\nhc\u0004Km\u000B^R\tQE\n{I\np@\nc|\u0005Gt\tc}\u0004Dl\nzU\u0005qN\tsV\u0005k}\tHh\u000B|j\nqo\u0005u|\tQ]\u000Bek\u0005\u007FZ\u0004M`\u0004St\npe\tdj\bVG\u000BeE\t\u007Fm\u000BWc\u0004|I\n[W\tfL\bT\u007F\tBZ\u0004Su\u000BKa\u0004Cq\u0005Nt\u0004Y[\nqI\bTv\tfM\ti@\t}f\u0004B\\\tQy\u000BBl\bWg\u0004XD\u0005kc\u000Bx[\bVV\tQ]\t\u007Fa\tPy\u000BxD\nfI\t}f\u0005oD\tdj\tSG\u0005ls\t~D\u0004CN\n{Z\t\\v\n_D\nhc\u000Bx_\u0004C[\tAJ\nLM\tVx\u0004CI\tbj\tc^\tcF\ntC\u0004Sx\twr\u0004XA\bU\\\t|a\u000BK\\\bTV\bVj\nd|\tfs\u0004CX\ntb\bRw\tVx\tAE\tA|\bT\u007F\u0005Nt\u000BDg\tVc\bTl\u0004d@\npo\t\u007FM\tcF\npe\tiZ\tBo\bSq\nfH\u0004l`\bTx\bWf\tHE\u000BF{\tcO\tfD\nlm\u000BfZ\nlm\u000BeU\tdG\u0004BH\bTV\tSi\u0005MW\nwX\nz\\\t\\c\u0004CX\nd}\tl}\bQp\bTV\tF~\bQ\u007F\t`i\ng@\u0005nO\bUd\bTl\nL[\twQ\tji\ntC\t|J\nLU\naB\u000BxY\u0004Kj\tAJ\u0005uN\ti[\npe\u0004Sk\u000BDg\u000Bx]\bVb\bVV\nea\tkV\nqI\bTa\u0004Sk\nAO\tpD\ntb\nts\nyi\bVg\ti_\u000B_W\nLk\u0005Nt\tyj\tfM\u0004R\u007F\tiI\bTl\u000BwX\tsV\u000BMl\nyu\tAJ\bVj\u0004KO\tWV\u000BA}\u000BW\u007F\nrp\tiD\u000B|o\u0005lv\u000BsI\u0004BM\td~\tCU\bVb\u0004eV\npC\u000BwT\tj`\tc}\u000Bxs\u000Bps\u000Bvh\tWV\u000BGg\u000BAe\u000BVK\u000B]W\trg\u000BWc\u0005F`\tBr\u000Bb\\\tdZ\bQp\nqI\u0004kF\nLk\u000BAR\bWI\bTg\tbs\tdw\n{L\n_y\tiZ\bTA\tlg\bVV\bTl\tdk\n`k\ta{\ti_\u0005{A\u0005wj\twN\u000B@@\bTe\ti_\n_D\twL\nAH\u000BiK\u000Bek\n[]\tp_\tyj\bTv\tUS\t[r\n{I\nps\u0005Gt\u000BVK\npl\u0004S}\u000BWP\t|d\u0004MD\u000BHV\bT\u007F\u0004R}\u0004M`\bTV\bVH\u0005lv\u0004Ch\bW[\u0004Ke\tR{\u000B^R\tab\tBZ\tVA\tB`\nd|\nhs\u0004Ke\tBe\u0004Oi\tR{\td\\\u0005nB\bWZ\tdZ\tVJ\u0005Os\t\u007Fm\u0004uQ\u000BhZ\u0004Q@\u0004QQ\nfI\bW[\u0004B\\\u0004li\nzU\nMd\u0004M`\nxS\bVV\n\\}\u000BxD\t\u007Fm\bTp\u0004IS\nc|\tkV\u0005i~\tV{\u000BhZ\t|b\bWt\n@R\u000BoA\u000BnU\bWI\tea\tB`\tiD\tc}\tTz\u0004BR\u000BQB\u0005Nj\tCP\t[I\bTv\t`W\u0005uN\u000Bpg\u000Bpg\u000BWc\tiT\tbs\twL\tU_\tc\\\t|h\u000BKa\tNr\tfL\nq|\nzu\nz\\\tNr\bUg\t|b\u0004m`\bTv\nyd\nrp\bWf\tUX\u0004BV\nzk\nd}\twQ\t}f\u0004Ce\u000Bed\bTW\bSB\nxU\tcn\bTb\ne\u007F\ta\\\tSG\bU|\npV\nN\\\u0004Kn\u000BnU\tAt\tpD\u000B^R\u000BIr\u0004b[\tR{\tdE\u000BxD\u000BWK\u000BWA\bQL\bW@\u0004Su\bUd\nDM\tPc\u0004CA\u0004Dl\u0004oQ\tHs\u0005wi\u0004ub\n\u007Fa\bQp\u0005Ob\nLP\bTl\u0004Y[\u000BK}\tAJ\bQ\u007F\u0004n^\u000BsA\bSM\nqM\bWZ\n^W\u000Bz{\u0004S|\tfD\bVK\bTv\bPv\u0004BB\tCP\u0004dF\tid\u000Bxs\u0004mx\u000Bws\tcC\ntC\tyc\u0005M`\u000BW\u007F\nrh\bQp\u000BxD\u0004\\o\nsI\u0004_k\nzu\u0004kF\tfD\u0004Xs\u0004XO\tjp\bTv\u0004BS\u0005{B\tBr\nzQ\nbI\tc{\u0004BD\u0004BV\u0005nO\bTF\tca\u0005Jd\tfL\tPV\tI_\nlK\u0004`o\twX\npa\tgu\bP}\u0005{^\bWf\n{I\tBN\npa\u0004Kl\u000Bpg\tcn\tfL\u000Bvh\u0004Cq\bTl\u000BnU\bSq\u0004Cm\twR\bUJ\npe\nyd\nYg\u0004Cy\u000BKW\tfD\nea\u0004oQ\tj_\tBv\u0004nM\u000BID\bTa\nzA\u0005pl\n]n\bTa\tR{\tfr\n_y\bUg\u0005{X\u0005kk\u000BxD\u0004|I\u0005xl\nfy\u0004Ce\u000BwB\nLk\u000Bd]\noi\n}h\tQ]\npe\bVw\u0004Hk\u0004OQ\nzk\tAJ\npV\bPv\ny\\\tA{\u0004Oi\bSB\u0004XA\u000BeE\tjp\nq}\tiD\u0005qN\u000B^R\t\u007Fm\tiZ\tBr\bVg\noi\n\\X\tU_\nc|\u000BHV\bTf\tTn\u0004\\N\u0004\\N\nuB\u0005lv\nyu\tTd\bTf\bPL\u000B]W\tdG\nA`\nw^\ngI\npe\tdw\nz\\\u0005ia\bWZ\tcF\u0004Jm\n{Z\bWO\u0004_k\u0004Df\u0004RR\td\\\bVV\u000Bxs\u0004BN\u0005ti\u0004lm\tTd\t]y\u000BHV\tSo\u000B|j\u0004XX\tA|\u000BZ^\u000BGu\bTW\u0005M`\u0004kF\u000BhZ\u000BVK\tdG\u000BBl\tay\nxU\u0005qE\u0005nO\bVw\nqI\u0004CX\ne\u007F\tPl\bWO\u000BLm\tdL\u0005uH\u0004Cm\tdT\u0004fn\u000BwB\u0005ka\u000BnU\n@M\nyT\tHv\t\\}\u0004Kh\td~\u0004Yh\u0005k}\neR\td\\\bWI\t|b\tHK\tiD\bTW\u0005MY\npl\bQ_\twr\u000BAx\tHE\bTg\bSq\u0005vp\u000Bb\\\bWO\nOl\nsI\nfy\u000BID\t\\c\n{Z\n^~\npe\nAO\tTT\u000Bxv\u0004k_\bWO\u000B|j\u000BwB\tQy\ti@\tPl\tHa\tdZ\u0005k}\u0004ra\tUT\u000BJc\u000Bed\np@\tQN\nd|\tkj\tHk\u0004M`\noi\twr\td\\\nlq\no_\nlb\nL[\tac\u0004BB\u0004BH\u0004Cm\npl\tIQ\bVK\u000Bxs\n`e\u000BiK\npa\u0004Oi\tUS\bTp\tfD\nPG\u0005kk\u0004XA\nz\\\neg\u000BWh\twR\u0005qN\nqS\tcn\u0004lo\nxS\n^W\tBU\nt\u007F\tHE\tp\\\tfF\tfw\bVV\bW@\tak\u000BVK\u0005ls\tVJ\bVV\u000BeE\u0004\\o\nyX\nYm\u0004M`\u0005lL\nd|\nzk\tA{\u0005sE\twQ\u0004XT\nt\u007F\tPl\t]y\u000BwT\u0005{p\u0004MD\u000Bb\\\tQ]\u0004Kj\tJn\nAH\u000BRb\tBU\tHK\t\\c\nfI\u0005m\u007F\nqM\n@R\tSo\noi\u0004BT\tHv\n_y\u0004Kh\tBZ\t]i\bUJ\tV{\u0004Sr\nbI\u000BGg\ta_\bTR\nfI\nfl\t[K\tII\u0004S|\u000BuW\tiI\bWI\nqI\u000B|j\u0004BV\bVg\bWZ\u0004kF\u000Bx]\bTA\tab\tfr\ti@\tJd\tJd\u000Bps\nAO\bTa\u0005xu\tiD\nzk\t|d\t|`\bW[\tlP\tdG\bVV\u000Bw}\u000BqO\ti[\bQ\u007F\bTz\u000BVF\twN\u0005ts\tdw\bTv\neS\ngi\tNr\u0005yS\npe\bVV\bSq\n`m\tyj\tBZ\u000BWX\bSB\tc\\\nUR\t[J\tc_\u0004nM\bWQ\u000BAx\nMd\tBr\u0005ui\u000BxY\bSM\u000BWc\u000B|j\u000Bxs\t}Q\tBO\bPL\bWW\tfM\nAO\tPc\u000BeU\u0004e^\bTg\nqI\tac\bPv\tcF\u0004oQ\tQ\u007F\u000BhZ\u0005ka\nz\\\tiK\tBU\n`k\tCP\u0004S|\u0004M`\n{I\tS{\u0004_O\tBZ\u0004Zi\u0004Sk\tps\tp\\\nYu\n]s\nxC\bWt\nbD\tkV\u000BGu\u0005yS\nqA\t[r\neK\u0004M`\tdZ\u0005lL\bUg\bTl\nbD\tUS\u000Bb\\\tpV\ncc\u0004S\\\tct\t`z\bPL\u000BWs\nA`\neg\bSq\u0005uE\u0004CR\u000BDg\t`W\u000Bz{\u000BWc\u0004Sk\u0004Sk\tbW\bUg\tea\nxZ\tiI\tUX\tVJ\nqn\tS{\u000BRb\bTQ\npl\u0005Gt\u000BuW\u0005uj\npF\nqI\tfL\t[I\tia\u0004XO\nyu\u000BDg\u000Bed\tq{\u0004VG\bQ\u007F\u0005ka\tVj\tkV\txB\nd|\np@\tQN\tPc\tps\u0004]j\tkV\toU\bTp\nzU\u0005nB\u000BB]\ta{\bV@\n]n\u0004m`\tcz\tR{\u0004m`\bQa\u000BwT\bSM\u0005MY\u0005qN\tdj\u0005~s\u000BQ}\u0005MY\u000BMB\tBv\twR\bRg\u000BQ}\tql\u000BKC\nrm\u0005xu\u0004CC\u000BwB\u000Bvh\tBq\u0004Xq\npV\ti_\u0005Ob\u0005uE\nbd\nqo\u000B{i\nC~\tBL\u000BeE\u0005uH\bVj\u0004Ey\u0004Gz\u000BzR\u000B{i\tcf\n{Z\n]n\u0004XA\u000BGu\u000BnU\thS\u000BGI\nCc\tHE\bTA\tHB\u0004BH\u0004Cj\nCc\bTF\tHE\nXI\tA{\bQ\u007F\tc\\\u000BmO\u000BWX\nfH\np@\u0005MY\bTF\nlK\tBt\nzU\tTT\u0004Km\u000BwT\npV\ndt\u000ByI\tVx\tQ\u007F\tRg\tTd\nzU\bRS\nLM\twA\u0004nM\tTn\ndS\t]g\nLc\u000BwB\t}t\t[I\tCP\u0004kX\u000BFm\u000BhZ\u0005m\u007F\ti[\np@\u000BQ}\u000BW\u007F\t|d\nMO\nMd\tf_\tfD\tcJ\tHz\u000BRb\tio\tPy\u0004Y[\nxU\tct\u000B@@\tww\bPv\u0004BM\u0004FF\ntb\u0005v|\u000BKm\tBq\tBq\u0004Kh\u0004`o\nZd\u0004XU\ti]\t|`\tSt\u0004B\\\bQ\u007F\u000B_W\tTJ\nqI\t|a\tA{\u000BuP\u0004MD\tPl\nxR\tfL\u000Bws\tc{\td\\\bV`\neg\tHK\u0005kc\nd|\bVV\ny\\\u0005kc\ti]\bVG\t`V\tss\tI_\tAE\tbs\tdu\nel\tpD\u000BW\u007F\nqs\u0005lv\bSM\u0004Zi\u000BVK\u0005ia\u000BQB\tQ\u007F\n{Z\bPt\u000BKl\nlK\nhs\ndS\bVK\u0005mf\nd^\tkV\tcO\nc|\bVH\t\\]\bTv\bSq\tmI\u000BDg\tVJ\tcn\ny\\\bVg\bTv\nyX\bTF\t]]\bTp\noi\nhs\u000BeU\nBf\tdj\u0005Mr\n|p\t\\g\t]r\bVb\u0005{D\nd[\u0004XN\tfM\tO\\\u0005s_\tcf\tiZ\u0004XN\u000BWc\tqv\n`m\tU^\u0005oD\nd|\u000BGg\tdE\u000Bwf\u0004lo\u0004u}\nd|\u0005oQ\t`i\u0004Oi\u000BxD\ndZ\nCx\u0004Yw\nzk\ntb\ngw\tyj\tB`\nyX\u000Bps\ntC\u000BpP\u000Bqw\bPu\bPX\tDm\npw\u0005Nj\tss\taG\u000Bxs\bPt\noL\u0004Gz\tOk\ti@\ti]\u0004eC\tIQ\tii\tdj\u000B@J\t|d\u0005uh\bWZ\u000BeU\u000BnU\bTa\tcC\u0004g]\nzk\u0004Yh\bVK\nLU\np@\ntb\ntR\tCj\u000BNP\ti@\bP{\n\\}\n{c\nwX\tfL\bVG\tc{\t|`\tAJ\t|C\tfD\u0005ln\t|d\tbs\nqI\u0005{B\u000BAx\np@\nzk\u000BRb\u0005Os\u000BWS\u0004e^\u000BD_\tBv\u000BWd\bVb\u000Bxs\u000BeE\bRw\n]n\n|p\u000Bg|\tfw\u0005kc\bTI\u0005ka\n\\T\u0004Sp\tju\u000Bps\npe\u0005u|\u000BGr\bVe\tCU\u0004]M\u0004XU\u000BxD\bTa\tIQ\u000BWq\tCU\tam\tdj\bSo\u0004Sw\u000BnU\u0004Ch\tQ]\u0005s_\bPt\tfS\bTa\t\\}\n@O\u0004Yc\tUZ\bTx\npe\u000BnU\nzU\t|}\tiD\nz\\\bSM\u000BxD\u0004BR\nzQ\tQN\u0004]M\u0004Yh\nLP\u000BFm\u000BLX\u0005vc\u000Bql\u0005ka\tHK\bVb\ntC\nCy\bTv\nuV\u0004oQ\t`z\t[I\tB`\u000BRb\tyj\tsb\u000BWs\bTl\tkV\u000Bed\ne\u007F\u0005lL\u000BxN\t\u007Fm\nJn\tjY\u000BxD\bVb\bSq\u000Byu\twL\u000BXL\bTA\tpg\tAt\tnD\u0004XX\twR\npl\nhw\u0005yS\nps\tcO\bW[\u000B|j\u0004XN\tsV\tp\\\tBe\nb~\nAJ\n]e\u0005k`\u0005qN\tdw\tWV\tHE\u000BEV\u0005Jz\tid\tB`\tzh\u0005E]\tfD\bTg\u0005qN\bTa\tja\u0004Cv\bSM\nhc\bUe\u0005t_\tie\u0004g]\twQ\nPn\bVB\tjw\bVg\u000BbE\tBZ\u000BRH\bP{\tjp\n\\}\ta_\tcC\t|a\u000BD]\tBZ\ti[\tfD\u000BxW\no_\td\\\n_D\ntb\t\\c\tAJ\nlK\u0004oQ\u0004lo\u000BLx\u000BM@\bWZ\u0004Kn\u000Bpg\nTi\nIv\n|r\u000B@}\u0005Jz\u0005Lm\u0005Wh\u0005k}\u0005ln\u000BxD\n]s\u0004gc\u000Bps\tBr\bTW\u000BBM\u0005tZ\nBY\u0004DW\tjf\u000BSW\u0004C}\nqo\tdE\tmv\tIQ\bPP\bUb\u0005lv\u0004BC\nzQ\t[I\u000Bgl\nig\bUs\u0004BT\u000BbC\bSq\tsU\tiW\nJn\tSY\tHK\trg\npV\u000BID\u000B|j\u0004KO\t`S\t|a`vbmglfmujbqnbgqjgavp`bqjmj`jlwjfnslslqrvf`vfmwbfpwbglsvfgfmivfdlp`lmwqbfpw/Mmmlnaqfwjfmfmsfqejonbmfqbbnjdlp`jvgbg`fmwqlbvmrvfsvfgfpgfmwqlsqjnfqsqf`jlpfd/Vmavfmlpuloufqsvmwlppfnbmbkba/Abbdlpwlmvfulpvmjglp`bqolpfrvjslmj/]lpnv`klpbodvmb`lqqfljnbdfmsbqwjqbqqjabnbq/Abklnaqffnsoflufqgbg`bnajlnv`kbpevfqlmsbpbglo/Amfbsbqf`fmvfubp`vqplpfpwbabrvjfqlojaqlp`vbmwlb``fplnjdvfoubqjlp`vbwqlwjfmfpdqvslppfq/Mmfvqlsbnfgjlpeqfmwfb`fq`bgfn/Mplefqwb`l`kfpnlgfoljwbojbofwqbpbod/Vm`lnsqb`vbofpf{jpwf`vfqslpjfmglsqfmpboofdbqujbifpgjmfqlnvq`jbslgq/Msvfpwlgjbqjlsvfaolrvjfqfnbmvfosqlsjl`qjpjp`jfqwlpfdvqlnvfqwfevfmwf`fqqbqdqbmgffef`wlsbqwfpnfgjgbsqlsjbleqf`fwjfqqbf.nbjoubqjbpelqnbpevwvqllaifwlpfdvjqqjfpdlmlqnbpnjpnlp/Vmj`l`bnjmlpjwjlpqby/_mgfajglsqvfabwlofglwfm/Abifp/Vpfpsfql`l`jmblqjdfmwjfmgb`jfmwl`/Mgjykbaobqpfq/Abobwjmbevfqybfpwjoldvfqqbfmwqbq/E{jwlo/_sfybdfmgbu/Agflfujwbqsbdjmbnfwqlpibujfqsbgqfpe/M`jo`bafyb/Mqfbppbojgbfmu/Alibs/_mbavplpajfmfpwf{wlpoofubqsvfgbmevfqwf`ln/Vm`obpfpkvnbmlwfmjglajoablvmjgbgfpw/Mpfgjwbq`qfbgl