Verbose CLI + start pulling "Shared-Brotli" (#722)

* Verbose CLI + start pulling "Shared-Brotli"

 * vesbose CLI output; fix #666
 * pull `SHIFT` transforms; currently this is semantically dead code;
   later it will be used by "Shared-Brotli"
This commit is contained in:
Eugene Kliuchnikov 2018-10-24 16:06:09 +02:00 committed by GitHub
parent d6d98957ca
commit d0ffe60b87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 848 additions and 88 deletions

View File

@ -166,6 +166,7 @@ static BrotliTransforms kBrotliTransforms = {
kPrefixSuffixMap, kPrefixSuffixMap,
sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])), sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])),
kTransformsData, kTransformsData,
NULL, /* no extra parameters */
{0, 12, 27, 23, 42, 63, 56, 48, 59, 64} {0, 12, 27, 23, 42, 63, 56, 48, 59, 64}
}; };
@ -190,6 +191,48 @@ static int ToUpperCase(uint8_t* p) {
return 3; return 3;
} }
static int Shift(uint8_t* word, int word_len, uint16_t parameter) {
/* Limited sign extension: scalar < (1 << 24). */
uint32_t scalar =
(parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u));
if (word[0] < 0x80) {
/* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
scalar += (uint32_t)word[0];
word[0] = (uint8_t)(scalar & 0x7Fu);
return 1;
} else if (word[0] < 0xC0) {
/* Continuation / 10AAAAAA. */
return 1;
} else if (word[0] < 0xE0) {
/* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
if (word_len < 2) return 1;
scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u));
word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F));
word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F));
return 2;
} else if (word[0] < 0xF0) {
/* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
if (word_len < 3) return word_len;
scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) |
((word[0] & 0x0Fu) << 12u));
word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F));
word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F));
word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F));
return 3;
} else if (word[0] < 0xF8) {
/* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
if (word_len < 4) return word_len;
scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) |
((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u));
word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07));
word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F));
word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F));
word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F));
return 4;
}
return 1;
}
int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len, int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,
const BrotliTransforms* transforms, int transform_idx) { const BrotliTransforms* transforms, int transform_idx) {
int idx = 0; int idx = 0;
@ -221,6 +264,19 @@ int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,
uppercase += step; uppercase += step;
len -= step; len -= step;
} }
} else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) {
uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]
+ (transforms->params[transform_idx * 2 + 1] << 8u));
Shift(&dst[idx - len], len, param);
} else if (t == BROTLI_TRANSFORM_SHIFT_ALL) {
uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]
+ (transforms->params[transform_idx * 2 + 1] << 8u));
uint8_t* shift = &dst[idx - len];
while (len > 0) {
int step = Shift(shift, len, param);
shift += step;
len -= step;
}
} }
} }
{ {

View File

@ -37,6 +37,8 @@ enum BrotliWordTransformType {
BROTLI_TRANSFORM_OMIT_FIRST_7 = 18, BROTLI_TRANSFORM_OMIT_FIRST_7 = 18,
BROTLI_TRANSFORM_OMIT_FIRST_8 = 19, BROTLI_TRANSFORM_OMIT_FIRST_8 = 19,
BROTLI_TRANSFORM_OMIT_FIRST_9 = 20, BROTLI_TRANSFORM_OMIT_FIRST_9 = 20,
BROTLI_TRANSFORM_SHIFT_FIRST = 21,
BROTLI_TRANSFORM_SHIFT_ALL = 22,
BROTLI_NUM_TRANSFORM_TYPES /* Counts transforms, not a transform itself. */ BROTLI_NUM_TRANSFORM_TYPES /* Counts transforms, not a transform itself. */
}; };
@ -50,6 +52,9 @@ typedef struct BrotliTransforms {
uint32_t num_transforms; uint32_t num_transforms;
/* Each entry is a [prefix_id, transform, suffix_id] triplet. */ /* Each entry is a [prefix_id, transform, suffix_id] triplet. */
const uint8_t* transforms; const uint8_t* transforms;
/* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL,
must be NULL if and only if no such transforms are present. */
const uint8_t* params;
/* Indices of transforms like ["", BROTLI_TRANSFORM_OMIT_LAST_#, ""]. /* Indices of transforms like ["", BROTLI_TRANSFORM_OMIT_LAST_#, ""].
0-th element corresponds to ["", BROTLI_TRANSFORM_IDENTITY, ""]. 0-th element corresponds to ["", BROTLI_TRANSFORM_IDENTITY, ""].
-1, if cut-off transform does not exist. */ -1, if cut-off transform does not exist. */

View File

@ -25,9 +25,9 @@ extern "C" {
initially the total amount of commands output by previous initially the total amount of commands output by previous
CreateBackwardReferences calls, and must be incremented by the amount written CreateBackwardReferences calls, and must be incremented by the amount written
by this call. */ by this call. */
BROTLI_INTERNAL void BrotliCreateBackwardReferences( BROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes,
size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
size_t ringbuffer_mask, const BrotliEncoderParams* params, const BrotliEncoderParams* params,
HasherHandle hasher, int* dist_cache, size_t* last_insert_len, HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
Command* commands, size_t* num_commands, size_t* num_literals); Command* commands, size_t* num_commands, size_t* num_literals);

View File

@ -419,8 +419,8 @@ static size_t UpdateNodes(
size_t k; size_t k;
size_t gap = 0; size_t gap = 0;
EvaluateNode(block_start, pos, max_backward_limit, gap, starting_dist_cache, EvaluateNode(block_start, pos, max_backward_limit, gap,
model, queue, nodes); starting_dist_cache, model, queue, nodes);
{ {
const PosData* posdata = StartPosQueueAt(queue, 0); const PosData* posdata = StartPosQueueAt(queue, 0);
@ -587,9 +587,10 @@ void BrotliZopfliCreateCommands(const size_t num_bytes,
{ {
size_t distance = ZopfliNodeCopyDistance(next); size_t distance = ZopfliNodeCopyDistance(next);
size_t len_code = ZopfliNodeLengthCode(next); size_t len_code = ZopfliNodeLengthCode(next);
size_t max_distance = size_t max_distance = BROTLI_MIN(size_t,
BROTLI_MIN(size_t, block_start + pos, max_backward_limit); block_start + pos, max_backward_limit);
BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > max_distance + gap); BROTLI_BOOL is_dictionary =
TO_BROTLI_BOOL(distance > max_distance + gap);
size_t dist_code = ZopfliNodeDistanceCode(next); size_t dist_code = ZopfliNodeDistanceCode(next);
InitCommand(&commands[i], &params->dist, insert_length, InitCommand(&commands[i], &params->dist, insert_length,
copy_length, (int)len_code - (int)copy_length, dist_code); copy_length, (int)len_code - (int)copy_length, dist_code);

View File

@ -23,14 +23,16 @@ extern "C" {
#endif #endif
BROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m, BROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m,
size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t num_bytes,
size_t ringbuffer_mask, const BrotliEncoderParams* params, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
const BrotliEncoderParams* params,
HasherHandle hasher, int* dist_cache, size_t* last_insert_len, HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
Command* commands, size_t* num_commands, size_t* num_literals); Command* commands, size_t* num_commands, size_t* num_literals);
BROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, BROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,
size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t num_bytes,
size_t ringbuffer_mask, const BrotliEncoderParams* params, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
const BrotliEncoderParams* params,
HasherHandle hasher, int* dist_cache, size_t* last_insert_len, HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
Command* commands, size_t* num_commands, size_t* num_literals); Command* commands, size_t* num_commands, size_t* num_literals);

View File

@ -60,7 +60,8 @@ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
FN(FindLongestMatch)(hasher, FN(FindLongestMatch)(hasher,
&params->dictionary, &params->dictionary,
ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,
max_distance, gap, params->dist.max_distance, &sr2); max_distance, gap, params->dist.max_distance,
&sr2);
if (sr2.score >= sr.score + cost_diff_lazy) { if (sr2.score >= sr.score + cost_diff_lazy) {
/* Ok, let's just write one byte for now and start a match from the /* Ok, let's just write one byte for now and start a match from the
next byte. */ next byte. */
@ -76,7 +77,8 @@ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
} }
apply_random_heuristics = apply_random_heuristics =
position + 2 * sr.len + random_heuristics_window_size; position + 2 * sr.len + random_heuristics_window_size;
max_distance = BROTLI_MIN(size_t, position, max_backward_limit); max_distance = BROTLI_MIN(size_t,
position, max_backward_limit);
{ {
/* The first 16 codes are special short-codes, /* The first 16 codes are special short-codes,
and the minimum offset is 1. */ and the minimum offset is 1. */

View File

@ -114,8 +114,6 @@ typedef struct BrotliEncoderStateStruct {
BROTLI_BOOL is_initialized_; BROTLI_BOOL is_initialized_;
} BrotliEncoderStateStruct; } BrotliEncoderStateStruct;
static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s);
static size_t InputBlockSize(BrotliEncoderState* s) { static size_t InputBlockSize(BrotliEncoderState* s) {
return (size_t)1 << s->params.lgblock; return (size_t)1 << s->params.lgblock;
} }

View File

@ -24,7 +24,6 @@ void BrotliInitEncoderDictionary(BrotliEncoderDictionary* dict) {
dict->cutoffTransformsCount = kCutoffTransformsCount; dict->cutoffTransformsCount = kCutoffTransformsCount;
dict->cutoffTransforms = kCutoffTransforms; dict->cutoffTransforms = kCutoffTransforms;
} }
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)

View File

@ -86,10 +86,10 @@ typedef struct {
/* Parameters */ /* Parameters */
int quality; int quality;
int lgwin; int lgwin;
int verbosity;
BROTLI_BOOL force_overwrite; BROTLI_BOOL force_overwrite;
BROTLI_BOOL junk_source; BROTLI_BOOL junk_source;
BROTLI_BOOL copy_stat; BROTLI_BOOL copy_stat;
BROTLI_BOOL verbose;
BROTLI_BOOL write_to_stdout; BROTLI_BOOL write_to_stdout;
BROTLI_BOOL test_integrity; BROTLI_BOOL test_integrity;
BROTLI_BOOL decompress; BROTLI_BOOL decompress;
@ -121,6 +121,12 @@ typedef struct {
const uint8_t* next_in; const uint8_t* next_in;
size_t available_out; size_t available_out;
uint8_t* next_out; uint8_t* next_out;
/* Reporting */
/* size_t would be large enough,
until 4GiB+ files are compressed / decompressed on 32-bit CPUs. */
size_t total_in;
size_t total_out;
} Context; } Context;
/* Parse up to 5 decimal digits. */ /* Parse up to 5 decimal digits. */
@ -279,11 +285,11 @@ static Command ParseParams(Context* params) {
command = COMMAND_TEST_INTEGRITY; command = COMMAND_TEST_INTEGRITY;
continue; continue;
} else if (c == 'v') { } else if (c == 'v') {
if (params->verbose) { if (params->verbosity > 0) {
fprintf(stderr, "argument --verbose / -v already set\n"); fprintf(stderr, "argument --verbose / -v already set\n");
return COMMAND_INVALID; return COMMAND_INVALID;
} }
params->verbose = BROTLI_TRUE; params->verbosity = 1;
continue; continue;
} else if (c == 'V') { } else if (c == 'V') {
/* Don't parse further. */ /* Don't parse further. */
@ -415,11 +421,11 @@ static Command ParseParams(Context* params) {
command_set = BROTLI_TRUE; command_set = BROTLI_TRUE;
command = COMMAND_TEST_INTEGRITY; command = COMMAND_TEST_INTEGRITY;
} else if (strcmp("verbose", arg) == 0) { } else if (strcmp("verbose", arg) == 0) {
if (params->verbose) { if (params->verbosity > 0) {
fprintf(stderr, "argument --verbose / -v already set\n"); fprintf(stderr, "argument --verbose / -v already set\n");
return COMMAND_INVALID; return COMMAND_INVALID;
} }
params->verbose = BROTLI_TRUE; params->verbosity = 1;
} else if (strcmp("version", arg) == 0) { } else if (strcmp("version", arg) == 0) {
/* Don't parse further. */ /* Don't parse further. */
return COMMAND_VERSION; return COMMAND_VERSION;
@ -787,6 +793,8 @@ static void InitializeBuffers(Context* context) {
context->next_in = NULL; context->next_in = NULL;
context->available_out = kFileBufferSize; context->available_out = kFileBufferSize;
context->next_out = context->output; context->next_out = context->output;
context->total_in = 0;
context->total_out = 0;
} }
static BROTLI_BOOL HasMoreInput(Context* context) { static BROTLI_BOOL HasMoreInput(Context* context) {
@ -796,6 +804,7 @@ static BROTLI_BOOL HasMoreInput(Context* context) {
static BROTLI_BOOL ProvideInput(Context* context) { static BROTLI_BOOL ProvideInput(Context* context) {
context->available_in = context->available_in =
fread(context->input, 1, kFileBufferSize, context->fin); fread(context->input, 1, kFileBufferSize, context->fin);
context->total_in += context->available_in;
context->next_in = context->input; context->next_in = context->input;
if (ferror(context->fin)) { if (ferror(context->fin)) {
fprintf(stderr, "failed to read input [%s]: %s\n", fprintf(stderr, "failed to read input [%s]: %s\n",
@ -808,6 +817,7 @@ static BROTLI_BOOL ProvideInput(Context* context) {
/* Internal: should be used only in Provide-/Flush-Output. */ /* Internal: should be used only in Provide-/Flush-Output. */
static BROTLI_BOOL WriteOutput(Context* context) { static BROTLI_BOOL WriteOutput(Context* context) {
size_t out_size = (size_t)(context->next_out - context->output); size_t out_size = (size_t)(context->next_out - context->output);
context->total_out += out_size;
if (out_size == 0) return BROTLI_TRUE; if (out_size == 0) return BROTLI_TRUE;
if (context->test_integrity) return BROTLI_TRUE; if (context->test_integrity) return BROTLI_TRUE;
@ -833,6 +843,25 @@ static BROTLI_BOOL FlushOutput(Context* context) {
return BROTLI_TRUE; return BROTLI_TRUE;
} }
static void PrintBytes(size_t value) {
if (value < 1024) {
fprintf(stderr, "%d B", (int)value);
} else if (value < 1048576) {
fprintf(stderr, "%0.3f KiB", (double)value / 1024.0);
} else if (value < 1073741824) {
fprintf(stderr, "%0.3f MiB", (double)value / 1048576.0);
} else {
fprintf(stderr, "%0.3f GiB", (double)value / 1073741824.0);
}
}
static void PrintFileProcessingProgress(Context* context) {
fprintf(stderr, "[%s]: ", PrintablePath(context->current_input_path));
PrintBytes(context->total_in);
fprintf(stderr, " -> ");
PrintBytes(context->total_out);
}
static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) { static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) {
BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
InitializeBuffers(context); InitializeBuffers(context);
@ -853,6 +882,11 @@ static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) {
PrintablePath(context->current_input_path)); PrintablePath(context->current_input_path));
return BROTLI_FALSE; return BROTLI_FALSE;
} }
if (context->verbosity > 0) {
fprintf(stderr, "Decompressed ");
PrintFileProcessingProgress(context);
fprintf(stderr, "\n");
}
return BROTLI_TRUE; return BROTLI_TRUE;
} else { } else {
fprintf(stderr, "corrupt input [%s]\n", fprintf(stderr, "corrupt input [%s]\n",
@ -915,7 +949,13 @@ static BROTLI_BOOL CompressFile(Context* context, BrotliEncoderState* s) {
} }
if (BrotliEncoderIsFinished(s)) { if (BrotliEncoderIsFinished(s)) {
return FlushOutput(context); if (!FlushOutput(context)) return BROTLI_FALSE;
if (context->verbosity > 0) {
fprintf(stderr, "Compressed ");
PrintFileProcessingProgress(context);
fprintf(stderr, "\n");
}
return BROTLI_TRUE;
} }
} }
} }
@ -979,11 +1019,11 @@ int main(int argc, char** argv) {
context.quality = 11; context.quality = 11;
context.lgwin = -1; context.lgwin = -1;
context.verbosity = 0;
context.force_overwrite = BROTLI_FALSE; context.force_overwrite = BROTLI_FALSE;
context.junk_source = BROTLI_FALSE; context.junk_source = BROTLI_FALSE;
context.copy_stat = BROTLI_TRUE; context.copy_stat = BROTLI_TRUE;
context.test_integrity = BROTLI_FALSE; context.test_integrity = BROTLI_FALSE;
context.verbose = BROTLI_FALSE;
context.write_to_stdout = BROTLI_FALSE; context.write_to_stdout = BROTLI_FALSE;
context.decompress = BROTLI_FALSE; context.decompress = BROTLI_FALSE;
context.large_window = BROTLI_FALSE; context.large_window = BROTLI_FALSE;

View File

@ -85,7 +85,17 @@ public class BrotliInputStream extends InputStream {
} }
public void setEager(boolean eager) { public void setEager(boolean eager) {
state.isEager = eager ? 1 : 0; boolean isEager = (state.isEager != 0);
if (eager == isEager) {
/* Shortcut for no-op change. */
return;
}
if (eager) {
Decode.setEager(state);
} else {
/* Once decoder is "eager", there is no way back. */
throw new IllegalStateException("Brotli decoder has been already switched to eager mode");
}
} }
/** /**

View File

@ -18,18 +18,19 @@ final class Decode {
// RunningState // RunningState
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
private static final int UNINITIALIZED = 0; private static final int UNINITIALIZED = 0;
private static final int BLOCK_START = 1; private static final int INITIALIZED = 1;
private static final int COMPRESSED_BLOCK_START = 2; private static final int BLOCK_START = 2;
private static final int MAIN_LOOP = 3; private static final int COMPRESSED_BLOCK_START = 3;
private static final int READ_METADATA = 4; private static final int MAIN_LOOP = 4;
private static final int COPY_UNCOMPRESSED = 5; private static final int READ_METADATA = 5;
private static final int INSERT_LOOP = 6; private static final int COPY_UNCOMPRESSED = 6;
private static final int COPY_LOOP = 7; private static final int INSERT_LOOP = 7;
private static final int TRANSFORM = 8; private static final int COPY_LOOP = 8;
private static final int FINISHED = 9; private static final int TRANSFORM = 9;
private static final int CLOSED = 10; private static final int FINISHED = 10;
private static final int INIT_WRITE = 11; private static final int CLOSED = 11;
private static final int WRITE = 12; private static final int INIT_WRITE = 12;
private static final int WRITE = 13;
private static final int DEFAULT_CODE_LENGTH = 8; private static final int DEFAULT_CODE_LENGTH = 8;
private static final int CODE_LENGTH_REPEAT_CODE = 16; private static final int CODE_LENGTH_REPEAT_CODE = 16;
@ -139,6 +140,20 @@ final class Decode {
return 17; 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 setEager(State s) {
if (s.runningState != INITIALIZED) {
throw new IllegalStateException("State MUST be freshly initialized");
}
s.isEager = 1;
}
/** /**
* Associate input with decoder state. * Associate input with decoder state.
* *
@ -152,13 +167,7 @@ final class Decode {
s.blockTrees = new int[6 * HUFFMAN_TABLE_SIZE]; s.blockTrees = new int[6 * HUFFMAN_TABLE_SIZE];
s.input = input; s.input = input;
BitReader.initBitReader(s); BitReader.initBitReader(s);
int windowBits = decodeWindowBits(s); s.runningState = INITIALIZED;
if (windowBits == 9) { /* Reserved case for future expansion. */
throw new BrotliRuntimeException("Invalid 'windowBits' code");
}
s.maxRingBufferSize = 1 << windowBits;
s.maxBackwardDistance = s.maxRingBufferSize - 16;
s.runningState = BLOCK_START;
} }
static void close(State s) throws IOException { static void close(State s) throws IOException {
@ -727,6 +736,16 @@ final class Decode {
if (s.runningState == CLOSED) { if (s.runningState == CLOSED) {
throw new IllegalStateException("Can't decompress after close"); throw new IllegalStateException("Can't decompress after close");
} }
if (s.runningState == INITIALIZED) {
int windowBits = decodeWindowBits(s);
if (windowBits == 9) { /* 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 fence = calculateFence(s);
int ringBufferMask = s.ringBufferSize - 1; int ringBufferMask = s.ringBufferSize - 1;
byte[] ringBuffer = s.ringBuffer; byte[] ringBuffer = s.ringBuffer;
@ -935,9 +954,9 @@ final class Decode {
int wordIdx = wordId & mask; int wordIdx = wordId & mask;
int transformIdx = wordId >>> shift; int transformIdx = wordId >>> shift;
offset += wordIdx * s.copyLength; offset += wordIdx * s.copyLength;
if (transformIdx < Transform.NUM_TRANSFORMS) { if (transformIdx < Transform.NUM_RFC_TRANSFORMS) {
int len = Transform.transformDictionaryWord(ringBuffer, s.pos, int len = Transform.transformDictionaryWord(ringBuffer, s.pos, Dictionary.getData(),
Dictionary.getData(), offset, s.copyLength, transformIdx); offset, s.copyLength, Transform.RFC_TRANSFORMS, transformIdx);
s.pos += len; s.pos += len;
s.metaBlockLength -= len; s.metaBlockLength -= len;
if (s.pos >= fence) { if (s.pos >= fence) {

View File

@ -64,6 +64,474 @@ public class SynthTest {
/* GENERATED CODE START */ /* GENERATED CODE START */
@Test
public void testAllTransforms10() {
byte[] compressed = {
(byte) 0x1b, (byte) 0xfc, (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x80,
(byte) 0xe3, (byte) 0xb4, (byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x5b,
(byte) 0x26, (byte) 0x31, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0xe0, (byte) 0x4e,
(byte) 0x1b, (byte) 0x13, (byte) 0x7c, (byte) 0x84, (byte) 0x26, (byte) 0xf8, (byte) 0x04,
(byte) 0x10, (byte) 0x4c, (byte) 0xf0, (byte) 0x89, (byte) 0x38, (byte) 0x30, (byte) 0xc1,
(byte) 0x27, (byte) 0x4e, (byte) 0xc1, (byte) 0x04, (byte) 0x9f, (byte) 0x64, (byte) 0x06,
(byte) 0x26, (byte) 0xf8, (byte) 0x24, (byte) 0x3f, (byte) 0x34, (byte) 0xc1, (byte) 0x27,
(byte) 0x7d, (byte) 0x82, (byte) 0x09, (byte) 0x3e, (byte) 0xe9, (byte) 0x16, (byte) 0x4d,
(byte) 0xf0, (byte) 0xc9, (byte) 0xd2, (byte) 0xc0, (byte) 0x04, (byte) 0x9f, (byte) 0x0c,
(byte) 0x8f, (byte) 0x4c, (byte) 0xf0, (byte) 0xc9, (byte) 0x06, (byte) 0xd1, (byte) 0x04,
(byte) 0x9f, (byte) 0x6c, (byte) 0x92, (byte) 0x4d, (byte) 0xf0, (byte) 0xc9, (byte) 0x39,
(byte) 0xc1, (byte) 0x04, (byte) 0x9f, (byte) 0xdc, (byte) 0x94, (byte) 0x4c, (byte) 0xf0,
(byte) 0xc9, (byte) 0x69, (byte) 0xd1, (byte) 0x04, (byte) 0x9f, (byte) 0x3c, (byte) 0x98,
(byte) 0x4d, (byte) 0xf0, (byte) 0x29, (byte) 0x9c, (byte) 0x81, (byte) 0x09, (byte) 0x3e,
(byte) 0x45, (byte) 0x37, (byte) 0x31, (byte) 0xc1, (byte) 0xa7, (byte) 0x60, (byte) 0x47,
(byte) 0x26, (byte) 0xf8, (byte) 0x14, (byte) 0xfa, (byte) 0xcc, (byte) 0x04, (byte) 0x9f,
(byte) 0xc2, (byte) 0x20, (byte) 0x9a, (byte) 0xe0, (byte) 0x53, (byte) 0x48, (byte) 0x54,
(byte) 0x13, (byte) 0x7c, (byte) 0x8a, (byte) 0x8f, (byte) 0x6c, (byte) 0x82, (byte) 0x4f,
(byte) 0xb1, (byte) 0xd2, (byte) 0x4d, (byte) 0xf0, (byte) 0x29, (byte) 0x67, (byte) 0x82,
(byte) 0x09, (byte) 0x3e, (byte) 0xe5, (byte) 0x4f, (byte) 0x31, (byte) 0xc1, (byte) 0xa7,
(byte) 0x7c, (byte) 0x4a, (byte) 0x26, (byte) 0xf8, (byte) 0x94, (byte) 0x57, (byte) 0xcd,
(byte) 0x04, (byte) 0x9f, (byte) 0x12, (byte) 0x2c, (byte) 0x9a, (byte) 0xe0, (byte) 0x53,
(byte) 0xba, (byte) 0x55, (byte) 0x13, (byte) 0x7c, (byte) 0xca, (byte) 0xbf, (byte) 0x6c,
(byte) 0x82, (byte) 0x4f, (byte) 0xb9, (byte) 0xd8, (byte) 0x4d, (byte) 0xf0, (byte) 0xa9,
(byte) 0x30, (byte) 0x03, (byte) 0x13, (byte) 0x7c, (byte) 0x2a, (byte) 0xd2, (byte) 0xc2,
(byte) 0x04, (byte) 0x9f, (byte) 0x4a, (byte) 0x36, (byte) 0x31, (byte) 0xc1, (byte) 0xa7,
(byte) 0xca, (byte) 0x6d, (byte) 0x4c, (byte) 0xf0, (byte) 0xa9, (byte) 0x94, (byte) 0x23,
(byte) 0x13, (byte) 0x7c, (byte) 0x2a, (byte) 0xeb, (byte) 0xca, (byte) 0x04, (byte) 0x9f,
(byte) 0xea, (byte) 0x3c, (byte) 0x33, (byte) 0xc1, (byte) 0xa7, (byte) 0xb2, (byte) 0xef,
(byte) 0x4c, (byte) 0xf0, (byte) 0xa9, (byte) 0xf8, (byte) 0x43, (byte) 0x13, (byte) 0x7c,
(byte) 0xaa, (byte) 0x00, (byte) 0xd3, (byte) 0x04, (byte) 0x9f, (byte) 0x2a, (byte) 0x42,
(byte) 0x35, (byte) 0xc1, (byte) 0xa7, (byte) 0xc2, (byte) 0x70, (byte) 0x4d, (byte) 0xf0,
(byte) 0xa9, (byte) 0x52, (byte) 0x64, (byte) 0x13, (byte) 0x7c, (byte) 0x2a, (byte) 0x1a,
(byte) 0xdb, (byte) 0x04, (byte) 0x9f, (byte) 0x6a, (byte) 0x48, (byte) 0x37, (byte) 0xc1,
(byte) 0xa7, (byte) 0x92, (byte) 0xf2, (byte) 0x4d, (byte) 0xf0, (byte) 0xa9, (byte) 0xc3,
(byte) 0x04, (byte) 0x13, (byte) 0x7c, (byte) 0xea, (byte) 0x32, (byte) 0xc3, (byte) 0x04,
(byte) 0x9f, (byte) 0x7a, (byte) 0x4e, (byte) 0x31, (byte) 0xc1, (byte) 0xa7, (byte) 0x06,
(byte) 0x74, (byte) 0x4c, (byte) 0xf0, (byte) 0xa9, (byte) 0x19, (byte) 0x25, (byte) 0x13,
(byte) 0x7c, (byte) 0x6a, (byte) 0x4d, (byte) 0xcb, (byte) 0x04, (byte) 0x9f, (byte) 0x1a,
(byte) 0x55, (byte) 0x33, (byte) 0xc1, (byte) 0xa7, (byte) 0x56, (byte) 0xf5, (byte) 0x4c,
(byte) 0xf0, (byte) 0xa9, (byte) 0x5d, (byte) 0x45, (byte) 0x13, (byte) 0x7c, (byte) 0xea,
(byte) 0x59, (byte) 0xd3, (byte) 0x04, (byte) 0x9f, (byte) 0xfa, (byte) 0x57, (byte) 0x35,
(byte) 0xc1, (byte) 0xa7, (byte) 0x66, (byte) 0x76, (byte) 0x4d, (byte) 0xf0, (byte) 0xa9,
(byte) 0x9f, (byte) 0x65, (byte) 0x13, (byte) 0x7c, (byte) 0x6a, (byte) 0x6f, (byte) 0xdb,
(byte) 0x04, (byte) 0x9f, (byte) 0x9a, (byte) 0x5d, (byte) 0x37, (byte) 0xc1, (byte) 0xa7,
(byte) 0x06, (byte) 0xf8, (byte) 0x4d, (byte) 0xf0, (byte) 0x69, (byte) 0x0c, (byte) 0x06,
(byte) 0x26, (byte) 0xf8, (byte) 0x34, (byte) 0x08, (byte) 0x07, (byte) 0x13, (byte) 0x7c,
(byte) 0x1a, (byte) 0x8b, (byte) 0x85, (byte) 0x09, (byte) 0x3e, (byte) 0x8d, (byte) 0xc8,
(byte) 0xc3, (byte) 0x04, (byte) 0x9f, (byte) 0xe6, (byte) 0x65, (byte) 0x62, (byte) 0x82,
(byte) 0x4f, (byte) 0xb3, (byte) 0x73, (byte) 0x31, (byte) 0xc1, (byte) 0xa7, (byte) 0x41,
(byte) 0xda, (byte) 0x98, (byte) 0xe0, (byte) 0xd3, (byte) 0x54, (byte) 0x7d, (byte) 0x4c,
(byte) 0xf0, (byte) 0x69, (byte) 0xc4, (byte) 0x46, (byte) 0x26, (byte) 0xf8, (byte) 0x34,
(byte) 0x72, (byte) 0x27, (byte) 0x13, (byte) 0x7c, (byte) 0x1a, (byte) 0xc5, (byte) 0x95,
(byte) 0x09, (byte) 0x3e, (byte) 0x8d, (byte) 0xe5, (byte) 0xcb, (byte) 0x04, (byte) 0x9f,
(byte) 0x06, (byte) 0x75, (byte) 0x66, (byte) 0x82, (byte) 0x4f, (byte) 0x43, (byte) 0x7b,
(byte) 0x33, (byte) 0xc1, (byte) 0xa7, (byte) 0x09, (byte) 0xde, (byte) 0x99, (byte) 0xe0,
(byte) 0xd3, (byte) 0x34, (byte) 0xff, (byte) 0x4c, (byte) 0xf0, (byte) 0x69, (byte) 0xb2,
(byte) 0x87, (byte) 0x26, (byte) 0xf8, (byte) 0x34, (byte) 0xe9, (byte) 0x47, (byte) 0x13,
(byte) 0x7c, (byte) 0x9a, (byte) 0xfb, (byte) 0xa5, (byte) 0x09, (byte) 0x3e, (byte) 0x4d,
(byte) 0x01, (byte) 0xd4, (byte) 0x04, (byte) 0x9f, (byte) 0x46, (byte) 0x82, (byte) 0x6a,
(byte) 0x82, (byte) 0x4f, (byte) 0x03, (byte) 0x82, (byte) 0x35, (byte) 0xc1, (byte) 0xa7,
(byte) 0x61, (byte) 0xe1, (byte) 0x9a, (byte) 0xe0, (byte) 0xd3, (byte) 0xe4, (byte) 0x80,
(byte) 0x4d, (byte) 0xf0, (byte) 0x69, (byte) 0x8a, (byte) 0xc8, (byte) 0x26, (byte) 0xf8,
(byte) 0x34, (byte) 0x52, (byte) 0x68, (byte) 0x13, (byte) 0x7c, (byte) 0x9a, (byte) 0x2f,
(byte) 0xb6, (byte) 0x09, (byte) 0x3e, (byte) 0x8d, (byte) 0x1b, (byte) 0xdc, (byte) 0x04,
(byte) 0x9f, (byte) 0x86, (byte) 0x8f, (byte) 0x6e, (byte) 0x82, (byte) 0x4f, (byte) 0xb3,
(byte) 0x88, (byte) 0x37, (byte) 0xc1, (byte) 0xa7, (byte) 0xd9, (byte) 0xe4, (byte) 0x9b,
(byte) 0xe0, (byte) 0xd3, (byte) 0x9e, (byte) 0x02, (byte) 0x4c, (byte) 0xf0, (byte) 0x69,
(byte) 0x6d, (byte) 0x09, (byte) 0x26, (byte) 0xf8, (byte) 0xb4, (byte) 0xc3, (byte) 0x08,
(byte) 0x13, (byte) 0x7c, (byte) 0x5a, (byte) 0x68, (byte) 0x86, (byte) 0x09, (byte) 0x3e,
(byte) 0xad, (byte) 0x37, (byte) 0xc4, (byte) 0x04, (byte) 0x9f, (byte) 0x56, (byte) 0x9d,
(byte) 0x62, (byte) 0x82, (byte) 0x4f, (byte) 0x9b, (byte) 0x8f, (byte) 0x31, (byte) 0xc1,
(byte) 0xa7, (byte) 0x2d, (byte) 0xe8, (byte) 0x98, (byte) 0xe0, (byte) 0xd3, (byte) 0x4a,
(byte) 0x84, (byte) 0x4c, (byte) 0xf0, (byte) 0x69, (byte) 0x3f, (byte) 0x4a, (byte) 0x26,
(byte) 0xf8, (byte) 0xb4, (byte) 0x2c, (byte) 0x29, (byte) 0x13, (byte) 0x7c, (byte) 0xda,
(byte) 0x9c, (byte) 0x96, (byte) 0x09, (byte) 0x3e, (byte) 0x2d, (byte) 0x52, (byte) 0xcc,
(byte) 0x04, (byte) 0x9f, (byte) 0xb6, (byte) 0xaa, (byte) 0x66, (byte) 0x82, (byte) 0x4f,
(byte) 0x2b, (byte) 0x96, (byte) 0x33, (byte) 0xc1, (byte) 0xa7, (byte) 0x7d, (byte) 0xeb,
(byte) 0x99, (byte) 0xe0, (byte) 0xd3, (byte) 0xf6, (byte) 0x05, (byte) 0x4d, (byte) 0xf0,
(byte) 0x69, (byte) 0x17, (byte) 0x8b, (byte) 0x26, (byte) 0xf8, (byte) 0xb4, (byte) 0x97,
(byte) 0x49, (byte) 0x13, (byte) 0x7c, (byte) 0xda, (byte) 0xd1, (byte) 0xa6, (byte) 0x09,
(byte) 0x3e, (byte) 0x2d, (byte) 0x6c, (byte) 0xd4, (byte) 0x04, (byte) 0x9f, (byte) 0xb6,
(byte) 0xb7, (byte) 0x6a, (byte) 0x82, (byte) 0x4f, (byte) 0xab, (byte) 0x9c, (byte) 0x35,
(byte) 0xc1, (byte) 0xa7, (byte) 0xc5, (byte) 0xee, (byte) 0x9a, (byte) 0xe0, (byte) 0xd3,
(byte) 0x9a, (byte) 0x87, (byte) 0x4d, (byte) 0xf0, (byte) 0x69, (byte) 0xe9, (byte) 0xcb
};
checkSynth(
/*
* // The stream consists of word "time" with all possible transforms.
* main_header
* metablock_header_easy: 1533, 1
* command_easy: 10, "|", 2 // = 0 << 10 + 1 + 1
* command_easy: 10, "|", 1037 // = 1 << 10 + 1 + 12
* command_easy: 10, "|", 2073 // = 2 << 10 + 1 + 24
* command_easy: 10, "|", 3110 // = 3 << 10 + 1 + 37
* command_easy: 10, "|", 4144 // = 4 << 10 + 1 + 47
* command_easy: 10, "|", 5180 // = 5 << 10 + 1 + 59
* command_easy: 10, "|", 6220 // = 6 << 10 + 1 + 75
* command_easy: 10, "|", 7256 // = 7 << 10 + 1 + 87
* command_easy: 10, "|", 8294 // = 8 << 10 + 1 + 101
* command_easy: 10, "|", 9333 // = 9 << 10 + 1 + 116
* command_easy: 10, "|", 10368 // = 10 << 10 + 1 + 127
* command_easy: 10, "|", 11408 // = 11 << 10 + 1 + 143
* command_easy: 10, "|", 12441 // = 12 << 10 + 1 + 152
* command_easy: 10, "|", 13475 // = 13 << 10 + 1 + 162
* command_easy: 10, "|", 14513 // = 14 << 10 + 1 + 176
* command_easy: 10, "|", 15550 // = 15 << 10 + 1 + 189
* command_easy: 10, "|", 16587 // = 16 << 10 + 1 + 202
* command_easy: 10, "|", 17626 // = 17 << 10 + 1 + 217
* command_easy: 10, "|", 18665 // = 18 << 10 + 1 + 232
* command_easy: 10, "|", 19703 // = 19 << 10 + 1 + 246
* command_easy: 10, "|", 20739 // = 20 << 10 + 1 + 258
* command_easy: 10, "|", 21775 // = 21 << 10 + 1 + 270
* command_easy: 10, "|", 22812 // = 22 << 10 + 1 + 283
* command_easy: 10, "|", 23848 // = 23 << 10 + 1 + 295
* command_easy: 10, "|", 24880 // = 24 << 10 + 1 + 303
* command_easy: 10, "|", 25916 // = 25 << 10 + 1 + 315
* command_easy: 10, "|", 26956 // = 26 << 10 + 1 + 331
* command_easy: 10, "|", 27988 // = 27 << 10 + 1 + 339
* command_easy: 10, "|", 29021 // = 28 << 10 + 1 + 348
* command_easy: 10, "|", 30059 // = 29 << 10 + 1 + 362
* command_easy: 10, "|", 31100 // = 30 << 10 + 1 + 379
* command_easy: 10, "|", 32136 // = 31 << 10 + 1 + 391
* command_easy: 10, "|", 33173 // = 32 << 10 + 1 + 404
* command_easy: 10, "|", 34209 // = 33 << 10 + 1 + 416
* command_easy: 10, "|", 35247 // = 34 << 10 + 1 + 430
* command_easy: 10, "|", 36278 // = 35 << 10 + 1 + 437
* command_easy: 10, "|", 37319 // = 36 << 10 + 1 + 454
* command_easy: 10, "|", 38355 // = 37 << 10 + 1 + 466
* command_easy: 10, "|", 39396 // = 38 << 10 + 1 + 483
* command_easy: 10, "|", 40435 // = 39 << 10 + 1 + 498
* command_easy: 10, "|", 41465 // = 40 << 10 + 1 + 504
* command_easy: 10, "|", 42494 // = 41 << 10 + 1 + 509
* command_easy: 10, "|", 43534 // = 42 << 10 + 1 + 525
* command_easy: 10, "|", 44565 // = 43 << 10 + 1 + 532
* command_easy: 10, "|", 45606 // = 44 << 10 + 1 + 549
* command_easy: 10, "|", 46641 // = 45 << 10 + 1 + 560
* command_easy: 10, "|", 47680 // = 46 << 10 + 1 + 575
* command_easy: 10, "|", 48719 // = 47 << 10 + 1 + 590
* command_easy: 10, "|", 49758 // = 48 << 10 + 1 + 605
* command_easy: 10, "|", 50786 // = 49 << 10 + 1 + 609
* command_easy: 10, "|", 51824 // = 50 << 10 + 1 + 623
* command_easy: 10, "|", 52861 // = 51 << 10 + 1 + 636
* command_easy: 10, "|", 53897 // = 52 << 10 + 1 + 648
* command_easy: 10, "|", 54935 // = 53 << 10 + 1 + 662
* command_easy: 10, "|", 55973 // = 54 << 10 + 1 + 676
* command_easy: 10, "|", 56999 // = 55 << 10 + 1 + 678
* command_easy: 10, "|", 58027 // = 56 << 10 + 1 + 682
* command_easy: 10, "|", 59056 // = 57 << 10 + 1 + 687
* command_easy: 10, "|", 60092 // = 58 << 10 + 1 + 699
* command_easy: 10, "|", 61129 // = 59 << 10 + 1 + 712
* command_easy: 10, "|", 62156 // = 60 << 10 + 1 + 715
* command_easy: 10, "|", 63195 // = 61 << 10 + 1 + 730
* command_easy: 10, "|", 64233 // = 62 << 10 + 1 + 744
* command_easy: 10, "|", 65277 // = 63 << 10 + 1 + 764
* command_easy: 10, "|", 66307 // = 64 << 10 + 1 + 770
* command_easy: 10, "|", 67333 // = 65 << 10 + 1 + 772
* command_easy: 10, "|", 68371 // = 66 << 10 + 1 + 786
* command_easy: 10, "|", 69407 // = 67 << 10 + 1 + 798
* command_easy: 10, "|", 70444 // = 68 << 10 + 1 + 811
* command_easy: 10, "|", 71480 // = 69 << 10 + 1 + 823
* command_easy: 10, "|", 72517 // = 70 << 10 + 1 + 836
* command_easy: 10, "|", 73554 // = 71 << 10 + 1 + 849
* command_easy: 10, "|", 74591 // = 72 << 10 + 1 + 862
* command_easy: 10, "|", 75631 // = 73 << 10 + 1 + 878
* command_easy: 10, "|", 76679 // = 74 << 10 + 1 + 902
* command_easy: 10, "|", 77715 // = 75 << 10 + 1 + 914
* command_easy: 10, "|", 78757 // = 76 << 10 + 1 + 932
* command_easy: 10, "|", 79793 // = 77 << 10 + 1 + 944
* command_easy: 10, "|", 80830 // = 78 << 10 + 1 + 957
* command_easy: 10, "|", 81866 // = 79 << 10 + 1 + 969
* command_easy: 10, "|", 82902 // = 80 << 10 + 1 + 981
* command_easy: 10, "|", 83942 // = 81 << 10 + 1 + 997
* command_easy: 10, "|", 84980 // = 82 << 10 + 1 + 1011
* command_easy: 10, "|", 86018 // = 83 << 10 + 1 + 1025
* command_easy: 10, "|", 87055 // = 84 << 10 + 1 + 1038
* command_easy: 10, "|", 88093 // = 85 << 10 + 1 + 1052
* command_easy: 10, "|", 89129 // = 86 << 10 + 1 + 1064
* command_easy: 10, "|", 90166 // = 87 << 10 + 1 + 1077
* command_easy: 10, "|", 91202 // = 88 << 10 + 1 + 1089
* command_easy: 10, "|", 92239 // = 89 << 10 + 1 + 1102
* command_easy: 10, "|", 93276 // = 90 << 10 + 1 + 1115
* command_easy: 10, "|", 94315 // = 91 << 10 + 1 + 1130
* command_easy: 10, "|", 95353 // = 92 << 10 + 1 + 1144
* command_easy: 10, "|", 96392 // = 93 << 10 + 1 + 1159
* command_easy: 10, "|", 97432 // = 94 << 10 + 1 + 1175
* command_easy: 10, "|", 98468 // = 95 << 10 + 1 + 1187
* command_easy: 10, "|", 99507 // = 96 << 10 + 1 + 1202
* command_easy: 10, "|", 100544 // = 97 << 10 + 1 + 1215
* command_easy: 10, "|", 101581 // = 98 << 10 + 1 + 1228
* command_easy: 10, "|", 102619 // = 99 << 10 + 1 + 1242
* command_easy: 10, "|", 103655 // = 100 << 10 + 1 + 1254
* command_easy: 10, "|", 104694 // = 101 << 10 + 1 + 1269
* command_easy: 10, "|", 105730 // = 102 << 10 + 1 + 1281
* command_easy: 10, "|", 106767 // = 103 << 10 + 1 + 1294
* command_easy: 10, "|", 107804 // = 104 << 10 + 1 + 1307
* command_easy: 10, "|", 108841 // = 105 << 10 + 1 + 1320
* command_easy: 10, "|", 109878 // = 106 << 10 + 1 + 1333
* command_easy: 10, "|", 110917 // = 107 << 10 + 1 + 1348
* command_easy: 10, "|", 111954 // = 108 << 10 + 1 + 1361
* command_easy: 10, "|", 112991 // = 109 << 10 + 1 + 1374
* command_easy: 10, "|", 114028 // = 110 << 10 + 1 + 1387
* command_easy: 10, "|", 115066 // = 111 << 10 + 1 + 1401
* command_easy: 10, "|", 116104 // = 112 << 10 + 1 + 1415
* command_easy: 10, "|", 117140 // = 113 << 10 + 1 + 1427
* command_easy: 10, "|", 118176 // = 114 << 10 + 1 + 1439
* command_easy: 10, "|", 119213 // = 115 << 10 + 1 + 1452
* command_easy: 10, "|", 120250 // = 116 << 10 + 1 + 1465
* command_easy: 10, "|", 121287 // = 117 << 10 + 1 + 1478
* command_easy: 10, "|", 122325 // = 118 << 10 + 1 + 1492
* command_easy: 10, "|", 123363 // = 119 << 10 + 1 + 1506
* command_easy: 10, "|", 124401 // = 120 << 10 + 1 + 1520
*/
compressed,
true,
"|categories|categories | categories |ategories|Categories |categories the | categories|s cat"
+ "egories |categories of |Categories|categories and |tegories|categorie|, categories |catego"
+ "ries, | Categories |categories in |categories to |e categories |categories\"|categories.|c"
+ "ategories\">|categories\n|categor|categories]|categories for |egories|categori|categories "
+ "a |categories that | Categories|categories. |.categories| categories, |gories|categories w"
+ "ith |categories'|categories from |categories by |ories|ries| the categories|catego|categor"
+ "ies. The |CATEGORIES|categories on |categories as |categories is |cat|categorieing |catego"
+ "ries\n\t|categories:| categories. |categoriesed |s|ies|cate|categories(|Categories, |ca|ca"
+ "tegories at |categoriesly | the categories of |categ|c| Categories, |Categories\"|.categor"
+ "ies(|CATEGORIES |Categories\">|categories=\"| categories.|.com/categories| the categories "
+ "of the |Categories'|categories. This |categories,|.categories |Categories(|Categories.|cat"
+ "egories not | categories=\"|categorieser | CATEGORIES |categoriesal | CATEGORIES|categorie"
+ "s='|CATEGORIES\"|Categories. | categories(|categoriesful | Categories. |categoriesive |cat"
+ "egoriesless |CATEGORIES'|categoriesest | Categories.|CATEGORIES\">| categories='|Categorie"
+ "s,|categoriesize |CATEGORIES.|\302\240categories| categories,|Categories=\"|CATEGORIES="
+ "\"|categoriesous |CATEGORIES, |Categories='| Categories,| CATEGORIES=\"| CATEGORIES, |CATE"
+ "GORIES,|CATEGORIES(|CATEGORIES. | CATEGORIES.|CATEGORIES='| CATEGORIES. | Categories=\"| C"
+ "ATEGORIES='| Categories='"
);
}
@Test
public void testAllTransforms4() {
byte[] compressed = {
(byte) 0x1b, (byte) 0x40, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x80,
(byte) 0xe3, (byte) 0xb4, (byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x5b,
(byte) 0x26, (byte) 0x31, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0xe0, (byte) 0x4e,
(byte) 0x1b, (byte) 0x51, (byte) 0x3e, (byte) 0x42, (byte) 0x51, (byte) 0x3e, (byte) 0x81,
(byte) 0x02, (byte) 0x51, (byte) 0x3e, (byte) 0x11, (byte) 0x04, (byte) 0xa2, (byte) 0x7c,
(byte) 0xe2, (byte) 0x0b, (byte) 0x44, (byte) 0xf9, (byte) 0x24, (byte) 0x1b, (byte) 0x10,
(byte) 0xe5, (byte) 0x93, (byte) 0x84, (byte) 0x50, (byte) 0x94, (byte) 0x4f, (byte) 0xba,
(byte) 0x02, (byte) 0x51, (byte) 0x3e, (byte) 0x69, (byte) 0x0c, (byte) 0x45, (byte) 0xf9,
(byte) 0x64, (byte) 0x39, (byte) 0x20, (byte) 0xca, (byte) 0x27, (byte) 0x13, (byte) 0x22,
(byte) 0x51, (byte) 0x3e, (byte) 0xd9, (byte) 0x11, (byte) 0x8a, (byte) 0xf2, (byte) 0xc9,
(byte) 0xa2, (byte) 0x58, (byte) 0x94, (byte) 0x4f, (byte) 0x4e, (byte) 0x05, (byte) 0xa2,
(byte) 0x7c, (byte) 0x72, (byte) 0x2c, (byte) 0x12, (byte) 0xe5, (byte) 0x93, (byte) 0x83,
(byte) 0xa1, (byte) 0x28, (byte) 0x9f, (byte) 0xfc, (byte) 0x8c, (byte) 0x45, (byte) 0xf9,
(byte) 0x14, (byte) 0x6e, (byte) 0x40, (byte) 0x94, (byte) 0x4f, (byte) 0x71, (byte) 0x47,
(byte) 0x44, (byte) 0xf9, (byte) 0x14, (byte) 0x80, (byte) 0x48, (byte) 0x94, (byte) 0x4f,
(byte) 0x81, (byte) 0xc8, (byte) 0x44, (byte) 0xf9, (byte) 0x14, (byte) 0x8e, (byte) 0x50,
(byte) 0x94, (byte) 0x4f, (byte) 0x41, (byte) 0x49, (byte) 0x45, (byte) 0xf9, (byte) 0x14,
(byte) 0x9b, (byte) 0x58, (byte) 0x94, (byte) 0x4f, (byte) 0x11, (byte) 0xca, (byte) 0x45,
(byte) 0xf9, (byte) 0x94, (byte) 0xa3, (byte) 0x40, (byte) 0x94, (byte) 0x4f, (byte) 0x99,
(byte) 0x4a, (byte) 0x44, (byte) 0xf9, (byte) 0x94, (byte) 0xb3, (byte) 0x48, (byte) 0x94,
(byte) 0x4f, (byte) 0x59, (byte) 0xcb, (byte) 0x44, (byte) 0xf9, (byte) 0x94, (byte) 0xb8,
(byte) 0x50, (byte) 0x94, (byte) 0x4f, (byte) 0x09, (byte) 0x4c, (byte) 0x45, (byte) 0xf9,
(byte) 0x94, (byte) 0xcb, (byte) 0x58, (byte) 0x94, (byte) 0x4f, (byte) 0x19, (byte) 0xcd,
(byte) 0x45, (byte) 0xf9, (byte) 0x54, (byte) 0xd8, (byte) 0x80, (byte) 0x28, (byte) 0x9f,
(byte) 0xca, (byte) 0x9b, (byte) 0x10, (byte) 0xe5, (byte) 0x53, (byte) 0x99, (byte) 0x23,
(byte) 0xa2, (byte) 0x7c, (byte) 0xaa, (byte) 0x73, (byte) 0x46, (byte) 0x94, (byte) 0x4f,
(byte) 0x25, (byte) 0x0f, (byte) 0x89, (byte) 0xf2, (byte) 0xa9, (byte) 0xf0, (byte) 0x29,
(byte) 0x51, (byte) 0x3e, (byte) 0xd5, (byte) 0x40, (byte) 0x26, (byte) 0xca, (byte) 0xa7,
(byte) 0x62, (byte) 0xe8, (byte) 0x44, (byte) 0xf9, (byte) 0x54, (byte) 0x0d, (byte) 0xa1,
(byte) 0x28, (byte) 0x9f, (byte) 0xca, (byte) 0xa1, (byte) 0x14, (byte) 0xe5, (byte) 0x53,
(byte) 0x61, (byte) 0xa4, (byte) 0xa2, (byte) 0x7c, (byte) 0xaa, (byte) 0x8c, (byte) 0x56,
(byte) 0x94, (byte) 0x4f, (byte) 0x45, (byte) 0x12, (byte) 0x8b, (byte) 0xf2, (byte) 0xa9,
(byte) 0x52, (byte) 0x6a, (byte) 0x51, (byte) 0x3e, (byte) 0x95, (byte) 0x4c, (byte) 0x2e,
(byte) 0xca, (byte) 0xa7, (byte) 0xda, (byte) 0xe9, (byte) 0x45, (byte) 0xf9, (byte) 0xd4,
(byte) 0x44, (byte) 0x81, (byte) 0x28, (byte) 0x9f, (byte) 0xba, (byte) 0xa8, (byte) 0x10,
(byte) 0xe5, (byte) 0x53, (byte) 0x37, (byte) 0x25, (byte) 0xa2, (byte) 0x7c, (byte) 0x6a,
(byte) 0xaa, (byte) 0x46, (byte) 0x94, (byte) 0x4f, (byte) 0xad, (byte) 0x15, (byte) 0x89,
(byte) 0xf2, (byte) 0xa9, (byte) 0xc5, (byte) 0x2a, (byte) 0x51, (byte) 0x3e, (byte) 0xb5,
(byte) 0x5a, (byte) 0x26, (byte) 0xca, (byte) 0xa7, (byte) 0x5e, (byte) 0xeb, (byte) 0x44,
(byte) 0xf9, (byte) 0xd4, (byte) 0x6c, (byte) 0xa1, (byte) 0x28, (byte) 0x9f, (byte) 0xba,
(byte) 0xad, (byte) 0x14, (byte) 0xe5, (byte) 0x53, (byte) 0xcf, (byte) 0xa5, (byte) 0xa2,
(byte) 0x7c, (byte) 0x6a, (byte) 0xbd, (byte) 0x56, (byte) 0x94, (byte) 0x4f, (byte) 0xbd,
(byte) 0x17, (byte) 0x8b, (byte) 0xf2, (byte) 0xa9, (byte) 0x09, (byte) 0x6b, (byte) 0x51,
(byte) 0x3e, (byte) 0x35, (byte) 0x63, (byte) 0x2e, (byte) 0xca, (byte) 0xa7, (byte) 0xd6,
(byte) 0xec, (byte) 0x45, (byte) 0xf9, (byte) 0x34, (byte) 0x9b, (byte) 0x01, (byte) 0x51,
(byte) 0x3e, (byte) 0x0d, (byte) 0x67, (byte) 0x41, (byte) 0x94, (byte) 0x4f, (byte) 0x43,
(byte) 0x9a, (byte) 0x10, (byte) 0xe5, (byte) 0xd3, (byte) 0xa8, (byte) 0x36, (byte) 0x44,
(byte) 0xf9, (byte) 0x34, (byte) 0xb1, (byte) 0x11, (byte) 0x51, (byte) 0x3e, (byte) 0xcd,
(byte) 0x6d, (byte) 0x45, (byte) 0x94, (byte) 0x4f, (byte) 0xe3, (byte) 0x9b, (byte) 0x11,
(byte) 0xe5, (byte) 0xd3, (byte) 0x14, (byte) 0x77, (byte) 0x44, (byte) 0xf9, (byte) 0x34,
(byte) 0xcc, (byte) 0x21, (byte) 0x51, (byte) 0x3e, (byte) 0x8d, (byte) 0x75, (byte) 0x49,
(byte) 0x94, (byte) 0x4f, (byte) 0x83, (byte) 0x9e, (byte) 0x12, (byte) 0xe5, (byte) 0xd3,
(byte) 0xb8, (byte) 0xb7, (byte) 0x44, (byte) 0xf9, (byte) 0x34, (byte) 0xfa, (byte) 0x31,
(byte) 0x51, (byte) 0x3e, (byte) 0x0d, (byte) 0x80, (byte) 0x4d, (byte) 0x94, (byte) 0x4f,
(byte) 0x73, (byte) 0xa0, (byte) 0x13, (byte) 0xe5, (byte) 0xd3, (byte) 0x34, (byte) 0xf8,
(byte) 0x44, (byte) 0xf9, (byte) 0x34, (byte) 0x13, (byte) 0x42, (byte) 0x51, (byte) 0x3e,
(byte) 0x4d, (byte) 0x87, (byte) 0x51, (byte) 0x94, (byte) 0x4f, (byte) 0x53, (byte) 0xa2,
(byte) 0x14, (byte) 0xe5, (byte) 0xd3, (byte) 0xb4, (byte) 0x38, (byte) 0x45, (byte) 0xf9,
(byte) 0x34, (byte) 0x34, (byte) 0x52, (byte) 0x51, (byte) 0x3e, (byte) 0x0d, (byte) 0x8f,
(byte) 0x55, (byte) 0x94, (byte) 0x4f, (byte) 0x23, (byte) 0xa4, (byte) 0x15, (byte) 0xe5,
(byte) 0xd3, (byte) 0x24, (byte) 0x79, (byte) 0x45, (byte) 0xf9, (byte) 0x34, (byte) 0x4f,
(byte) 0x62, (byte) 0x51, (byte) 0x3e, (byte) 0x8d, (byte) 0x95, (byte) 0x59, (byte) 0x94,
(byte) 0x4f, (byte) 0xd3, (byte) 0xa5, (byte) 0x16, (byte) 0xe5, (byte) 0xd3, (byte) 0x98,
(byte) 0xb9, (byte) 0x45, (byte) 0xf9, (byte) 0x34, (byte) 0x6e, (byte) 0x72, (byte) 0x51,
(byte) 0x3e, (byte) 0xcd, (byte) 0x9d, (byte) 0x5d, (byte) 0x94, (byte) 0x4f, (byte) 0x13,
(byte) 0xa8, (byte) 0x17, (byte) 0xe5, (byte) 0xd3, (byte) 0x1c, (byte) 0xfa, (byte) 0x45,
(byte) 0xf9, (byte) 0xb4, (byte) 0x90, (byte) 0x02, (byte) 0x51, (byte) 0x3e, (byte) 0xed,
(byte) 0xa5, (byte) 0x41, (byte) 0x94, (byte) 0x4f, (byte) 0xeb, (byte) 0xa9, (byte) 0x10,
(byte) 0xe5, (byte) 0xd3, (byte) 0x9a, (byte) 0x3a, (byte) 0x44, (byte) 0xf9, (byte) 0xb4,
(byte) 0xac, (byte) 0x12, (byte) 0x51, (byte) 0x3e, (byte) 0x6d, (byte) 0xad, (byte) 0x45,
(byte) 0x94, (byte) 0x4f, (byte) 0xbb, (byte) 0xab, (byte) 0x11, (byte) 0xe5, (byte) 0xd3,
(byte) 0x0a, (byte) 0x7b, (byte) 0x44, (byte) 0xf9, (byte) 0xb4, (byte) 0xc9, (byte) 0x22,
(byte) 0x51, (byte) 0x3e, (byte) 0x2d, (byte) 0xb4, (byte) 0x49, (byte) 0x94, (byte) 0x4f,
(byte) 0x7b, (byte) 0xad, (byte) 0x12, (byte) 0xe5, (byte) 0xd3, (byte) 0x82, (byte) 0xbb,
(byte) 0x44, (byte) 0xf9, (byte) 0xb4, (byte) 0xe7, (byte) 0x32, (byte) 0x51, (byte) 0x3e,
(byte) 0xad, (byte) 0xbb, (byte) 0x4d, (byte) 0x94, (byte) 0x4f, (byte) 0x5b, (byte) 0xaf,
(byte) 0x13, (byte) 0xe5, (byte) 0xd3, (byte) 0xf6, (byte) 0xfb, (byte) 0x44, (byte) 0xf9,
(byte) 0xb4, (byte) 0x05, (byte) 0x43, (byte) 0x51, (byte) 0x3e, (byte) 0xed, (byte) 0xc2,
(byte) 0x51, (byte) 0x94, (byte) 0x4f, (byte) 0x1b, (byte) 0xb1, (byte) 0x14, (byte) 0xe5,
(byte) 0xd3, (byte) 0x62, (byte) 0x3c, (byte) 0x45, (byte) 0xf9, (byte) 0xb4, (byte) 0x1f,
(byte) 0x53, (byte) 0x51, (byte) 0x3e, (byte) 0xad, (byte) 0xc9, (byte) 0x55, (byte) 0x94,
(byte) 0x4f, (byte) 0xeb, (byte) 0xb2, (byte) 0x15, (byte) 0xe5, (byte) 0xd3, (byte) 0xda,
(byte) 0x7c, (byte) 0x45, (byte) 0xf9, (byte) 0xb4, (byte) 0x3e, (byte) 0x63
};
checkSynth(
/*
* // The stream consists of word "time" with all possible transforms.
* main_header
* metablock_header_easy: 833, 1
* command_easy: 4, "|", 2 // = 0 << 10 + 1 + 1
* command_easy: 4, "|", 1031 // = 1 << 10 + 1 + 6
* command_easy: 4, "|", 2061 // = 2 << 10 + 1 + 12
* command_easy: 4, "|", 3092 // = 3 << 10 + 1 + 19
* command_easy: 4, "|", 4120 // = 4 << 10 + 1 + 23
* command_easy: 4, "|", 5150 // = 5 << 10 + 1 + 29
* command_easy: 4, "|", 6184 // = 6 << 10 + 1 + 39
* command_easy: 4, "|", 7214 // = 7 << 10 + 1 + 45
* command_easy: 4, "|", 8246 // = 8 << 10 + 1 + 53
* command_easy: 4, "|", 9279 // = 9 << 10 + 1 + 62
* command_easy: 4, "|", 10308 // = 10 << 10 + 1 + 67
* command_easy: 4, "|", 11342 // = 11 << 10 + 1 + 77
* command_easy: 4, "|", 12369 // = 12 << 10 + 1 + 80
* command_easy: 4, "|", 13397 // = 13 << 10 + 1 + 84
* command_easy: 4, "|", 14429 // = 14 << 10 + 1 + 92
* command_easy: 4, "|", 15460 // = 15 << 10 + 1 + 99
* command_easy: 4, "|", 16491 // = 16 << 10 + 1 + 106
* command_easy: 4, "|", 17524 // = 17 << 10 + 1 + 115
* command_easy: 4, "|", 18557 // = 18 << 10 + 1 + 124
* command_easy: 4, "|", 19589 // = 19 << 10 + 1 + 132
* command_easy: 4, "|", 20619 // = 20 << 10 + 1 + 138
* command_easy: 4, "|", 21649 // = 21 << 10 + 1 + 144
* command_easy: 4, "|", 22680 // = 22 << 10 + 1 + 151
* command_easy: 4, "|", 23710 // = 23 << 10 + 1 + 157
* command_easy: 4, "|", 24736 // = 24 << 10 + 1 + 159
* command_easy: 4, "|", 25766 // = 25 << 10 + 1 + 165
* command_easy: 4, "|", 26800 // = 26 << 10 + 1 + 175
* command_easy: 4, "|", 27826 // = 27 << 10 + 1 + 177
* command_easy: 4, "|", 28853 // = 28 << 10 + 1 + 180
* command_easy: 4, "|", 29885 // = 29 << 10 + 1 + 188
* command_easy: 4, "|", 30920 // = 30 << 10 + 1 + 199
* command_easy: 4, "|", 31950 // = 31 << 10 + 1 + 205
* command_easy: 4, "|", 32981 // = 32 << 10 + 1 + 212
* command_easy: 4, "|", 34011 // = 33 << 10 + 1 + 218
* command_easy: 4, "|", 35043 // = 34 << 10 + 1 + 226
* command_easy: 4, "|", 36068 // = 35 << 10 + 1 + 227
* command_easy: 4, "|", 37103 // = 36 << 10 + 1 + 238
* command_easy: 4, "|", 38133 // = 37 << 10 + 1 + 244
* command_easy: 4, "|", 39168 // = 38 << 10 + 1 + 255
* command_easy: 4, "|", 40201 // = 39 << 10 + 1 + 264
* command_easy: 4, "|", 41226 // = 40 << 10 + 1 + 265
* command_easy: 4, "|", 42251 // = 41 << 10 + 1 + 266
* command_easy: 4, "|", 43285 // = 42 << 10 + 1 + 276
* command_easy: 4, "|", 44310 // = 43 << 10 + 1 + 277
* command_easy: 4, "|", 45345 // = 44 << 10 + 1 + 288
* command_easy: 4, "|", 46374 // = 45 << 10 + 1 + 293
* command_easy: 4, "|", 47407 // = 46 << 10 + 1 + 302
* command_easy: 4, "|", 48440 // = 47 << 10 + 1 + 311
* command_easy: 4, "|", 49473 // = 48 << 10 + 1 + 320
* command_easy: 4, "|", 50498 // = 49 << 10 + 1 + 321
* command_easy: 4, "|", 51530 // = 50 << 10 + 1 + 329
* command_easy: 4, "|", 52561 // = 51 << 10 + 1 + 336
* command_easy: 4, "|", 53591 // = 52 << 10 + 1 + 342
* command_easy: 4, "|", 54623 // = 53 << 10 + 1 + 350
* command_easy: 4, "|", 55655 // = 54 << 10 + 1 + 358
* command_easy: 4, "|", 56680 // = 55 << 10 + 1 + 359
* command_easy: 4, "|", 57705 // = 56 << 10 + 1 + 360
* command_easy: 4, "|", 58730 // = 57 << 10 + 1 + 361
* command_easy: 4, "|", 59760 // = 58 << 10 + 1 + 367
* command_easy: 4, "|", 60791 // = 59 << 10 + 1 + 374
* command_easy: 4, "|", 61816 // = 60 << 10 + 1 + 375
* command_easy: 4, "|", 62849 // = 61 << 10 + 1 + 384
* command_easy: 4, "|", 63881 // = 62 << 10 + 1 + 392
* command_easy: 4, "|", 64919 // = 63 << 10 + 1 + 406
* command_easy: 4, "|", 65944 // = 64 << 10 + 1 + 407
* command_easy: 4, "|", 66969 // = 65 << 10 + 1 + 408
* command_easy: 4, "|", 68001 // = 66 << 10 + 1 + 416
* command_easy: 4, "|", 69031 // = 67 << 10 + 1 + 422
* command_easy: 4, "|", 70062 // = 68 << 10 + 1 + 429
* command_easy: 4, "|", 71092 // = 69 << 10 + 1 + 435
* command_easy: 4, "|", 72123 // = 70 << 10 + 1 + 442
* command_easy: 4, "|", 73154 // = 71 << 10 + 1 + 449
* command_easy: 4, "|", 74185 // = 72 << 10 + 1 + 456
* command_easy: 4, "|", 75219 // = 73 << 10 + 1 + 466
* command_easy: 4, "|", 76261 // = 74 << 10 + 1 + 484
* command_easy: 4, "|", 77291 // = 75 << 10 + 1 + 490
* command_easy: 4, "|", 78327 // = 76 << 10 + 1 + 502
* command_easy: 4, "|", 79357 // = 77 << 10 + 1 + 508
* command_easy: 4, "|", 80388 // = 78 << 10 + 1 + 515
* command_easy: 4, "|", 81418 // = 79 << 10 + 1 + 521
* command_easy: 4, "|", 82448 // = 80 << 10 + 1 + 527
* command_easy: 4, "|", 83482 // = 81 << 10 + 1 + 537
* command_easy: 4, "|", 84514 // = 82 << 10 + 1 + 545
* command_easy: 4, "|", 85546 // = 83 << 10 + 1 + 553
* command_easy: 4, "|", 86577 // = 84 << 10 + 1 + 560
* command_easy: 4, "|", 87609 // = 85 << 10 + 1 + 568
* command_easy: 4, "|", 88639 // = 86 << 10 + 1 + 574
* command_easy: 4, "|", 89670 // = 87 << 10 + 1 + 581
* command_easy: 4, "|", 90700 // = 88 << 10 + 1 + 587
* command_easy: 4, "|", 91731 // = 89 << 10 + 1 + 594
* command_easy: 4, "|", 92762 // = 90 << 10 + 1 + 601
* command_easy: 4, "|", 93795 // = 91 << 10 + 1 + 610
* command_easy: 4, "|", 94827 // = 92 << 10 + 1 + 618
* command_easy: 4, "|", 95860 // = 93 << 10 + 1 + 627
* command_easy: 4, "|", 96894 // = 94 << 10 + 1 + 637
* command_easy: 4, "|", 97924 // = 95 << 10 + 1 + 643
* command_easy: 4, "|", 98957 // = 96 << 10 + 1 + 652
* command_easy: 4, "|", 99988 // = 97 << 10 + 1 + 659
* command_easy: 4, "|", 101019 // = 98 << 10 + 1 + 666
* command_easy: 4, "|", 102051 // = 99 << 10 + 1 + 674
* command_easy: 4, "|", 103081 // = 100 << 10 + 1 + 680
* command_easy: 4, "|", 104114 // = 101 << 10 + 1 + 689
* command_easy: 4, "|", 105144 // = 102 << 10 + 1 + 695
* command_easy: 4, "|", 106175 // = 103 << 10 + 1 + 702
* command_easy: 4, "|", 107206 // = 104 << 10 + 1 + 709
* command_easy: 4, "|", 108237 // = 105 << 10 + 1 + 716
* command_easy: 4, "|", 109268 // = 106 << 10 + 1 + 723
* command_easy: 4, "|", 110301 // = 107 << 10 + 1 + 732
* command_easy: 4, "|", 111332 // = 108 << 10 + 1 + 739
* command_easy: 4, "|", 112363 // = 109 << 10 + 1 + 746
* command_easy: 4, "|", 113394 // = 110 << 10 + 1 + 753
* command_easy: 4, "|", 114426 // = 111 << 10 + 1 + 761
* command_easy: 4, "|", 115458 // = 112 << 10 + 1 + 769
* command_easy: 4, "|", 116488 // = 113 << 10 + 1 + 775
* command_easy: 4, "|", 117518 // = 114 << 10 + 1 + 781
* command_easy: 4, "|", 118549 // = 115 << 10 + 1 + 788
* command_easy: 4, "|", 119580 // = 116 << 10 + 1 + 795
* command_easy: 4, "|", 120611 // = 117 << 10 + 1 + 802
* command_easy: 4, "|", 121643 // = 118 << 10 + 1 + 810
* command_easy: 4, "|", 122675 // = 119 << 10 + 1 + 818
* command_easy: 4, "|", 123707 // = 120 << 10 + 1 + 826
*/
compressed,
true,
"|time|time | time |ime|Time |time the | time|s time |time of |Time|time and |me|tim|, time |"
+ "time, | Time |time in |time to |e time |time\"|time.|time\">|time\n|t|time]|time for |e|ti"
+ "|time a |time that | Time|time. |.time| time, ||time with |time'|time from |time by ||| th"
+ "e time||time. The |TIME|time on |time as |time is ||timing |time\n\t|time:| time. |timeed "
+ "||||time(|Time, ||time at |timely | the time of ||| Time, |Time\"|.time(|TIME |Time\">|tim"
+ "e=\"| time.|.com/time| the time of the |Time'|time. This |time,|.time |Time(|Time.|time no"
+ "t | time=\"|timeer | TIME |timeal | TIME|time='|TIME\"|Time. | time(|timeful | Time. |time"
+ "ive |timeless |TIME'|timeest | Time.|TIME\">| time='|Time,|timeize |TIME.|\302\240time| ti"
+ "me,|Time=\"|TIME=\"|timeous |TIME, |Time='| Time,| TIME=\"| TIME, |TIME,|TIME(|TIME. | TIM"
+ "E.|TIME='| TIME. | Time=\"| TIME='| Time='"
);
}
@Test @Test
public void testBaseDictWord() { public void testBaseDictWord() {
byte[] compressed = { byte[] compressed = {
@ -446,6 +914,28 @@ public class SynthTest {
); );
} }
@Test
public void testCopyTooLong() {
byte[] compressed = {
(byte) 0xa1, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x1c, (byte) 0xa7, (byte) 0x6d, (byte) 0x00, (byte) 0x00, (byte) 0x38, (byte) 0xd8,
(byte) 0x32, (byte) 0x89, (byte) 0x01, (byte) 0x12, (byte) 0x00, (byte) 0x00, (byte) 0x77,
(byte) 0xda, (byte) 0x34, (byte) 0xab, (byte) 0xdb, (byte) 0x50, (byte) 0x00
};
checkSynth(
/*
* // Has a copy length that goes over the end of the meta-block,
* // with a ringbuffer wrap.
* main_header: 10
* metablock_header_easy: 2, 1
* command_easy: 1024, "a", 1
*/
compressed,
false,
""
);
}
@Test @Test
public void testCustomHuffmanCode() { public void testCustomHuffmanCode() {
byte[] compressed = { byte[] compressed = {
@ -2199,6 +2689,23 @@ public class SynthTest {
); );
} }
/* DISABLED: Java decoder does not tolerate extra input after the brotli stream.
@Test
public void testSimplePrefixPlusExtraData() {
byte[] compressed = {
(byte) 0x1b, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0xa0, (byte) 0xc3, (byte) 0xc4,
(byte) 0xc6, (byte) 0xc8, (byte) 0x02, (byte) 0x00, (byte) 0x70, (byte) 0xb0, (byte) 0x65,
(byte) 0x12, (byte) 0x03, (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xee, (byte) 0xb4,
(byte) 0x51, (byte) 0xa0, (byte) 0x1d, (byte) 0x55, (byte) 0xaa
};
checkSynth(
compressed,
true,
"abcd"
);
}
*/
@Test @Test
public void testTooManySymbolsRepeated() { public void testTooManySymbolsRepeated() {
byte[] compressed = { byte[] compressed = {
@ -2246,7 +2753,7 @@ public class SynthTest {
* main_header * main_header
* metablock_header_easy: 9, 1 * metablock_header_easy: 9, 1
* command_inscopy_easy: 0, 4 * command_inscopy_easy: 0, 4
* command_dist_easy: 5121 * command_dist_easy: 5121 // 5 << 10 + 1
*/ */
compressed, compressed,
true, true,
@ -2270,7 +2777,7 @@ public class SynthTest {
* main_header * main_header
* metablock_header_easy: 4, 1 * metablock_header_easy: 4, 1
* command_inscopy_easy: 0, 4 * command_inscopy_easy: 0, 4
* command_dist_easy: 5121 * command_dist_easy: 5121 // 5 << 10 + 1
*/ */
compressed, compressed,
false, false,

View File

@ -10,13 +10,58 @@ import java.nio.ByteBuffer;
/** /**
* Transformations on dictionary words. * 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 { final class Transform {
static final int NUM_TRANSFORMS = 121; static final class Transforms {
private static final int[] TRANSFORMS = new int[NUM_TRANSFORMS * 3]; final int numTransforms;
private static final byte[] PREFIX_SUFFIX = new byte[217]; final int[] triplets;
private static final int[] PREFIX_SUFFIX_HEADS = new int[51]; 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. // Bundle of 0-terminated strings.
private static final String PREFIX_SUFFIX_SRC = "# #s #, #e #.# the #.com/#\u00C2\u00A0# of # and" private static final String PREFIX_SUFFIX_SRC = "# #s #, #e #.# the #.com/#\u00C2\u00A0# of # and"
@ -29,71 +74,87 @@ final class Transform {
+ " G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D " + " 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"; + " Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K";
private static void unpackTransforms(byte[] prefixSuffix, int[] prefixSuffixHeads, private static void unpackTransforms(byte[] prefixSuffix,
int[] transforms, String prefixSuffixSrc, String transformsSrc) { int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) {
int n = prefixSuffixSrc.length(); int n = prefixSuffixSrc.length();
int index = 1; int index = 1;
int j = 0;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
char c = prefixSuffixSrc.charAt(i); char c = prefixSuffixSrc.charAt(i);
prefixSuffix[i] = (byte) c;
if (c == 35) { // == # if (c == 35) { // == #
prefixSuffixHeads[index++] = i + 1; prefixSuffixHeads[index++] = j;
prefixSuffix[i] = 0; } else {
prefixSuffix[j++] = (byte) c;
} }
} }
for (int i = 0; i < NUM_TRANSFORMS * 3; ++i) { for (int i = 0; i < NUM_RFC_TRANSFORMS * 3; ++i) {
transforms[i] = transformsSrc.charAt(i) - 32; transforms[i] = transformsSrc.charAt(i) - 32;
} }
} }
static { static {
unpackTransforms(PREFIX_SUFFIX, PREFIX_SUFFIX_HEADS, TRANSFORMS, PREFIX_SUFFIX_SRC, unpackTransforms(RFC_TRANSFORMS.prefixSuffixStorage, RFC_TRANSFORMS.prefixSuffixHeads,
TRANSFORMS_SRC); RFC_TRANSFORMS.triplets, PREFIX_SUFFIX_SRC, TRANSFORMS_SRC);
} }
static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer data, int wordOffset, static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset,
int len, int transformIndex) { int len, Transforms transforms, int transformIndex) {
int offset = dstOffset; int offset = dstOffset;
int[] triplets = transforms.triplets;
byte[] prefixSuffixStorage = transforms.prefixSuffixStorage;
int[] prefixSuffixHeads = transforms.prefixSuffixHeads;
int transformOffset = 3 * transformIndex; int transformOffset = 3 * transformIndex;
int transformPrefix = PREFIX_SUFFIX_HEADS[TRANSFORMS[transformOffset]]; int prefixIdx = triplets[transformOffset];
int transformType = TRANSFORMS[transformOffset + 1]; int transformType = triplets[transformOffset + 1];
int transformSuffix = PREFIX_SUFFIX_HEADS[TRANSFORMS[transformOffset + 2]]; int suffixIdx = triplets[transformOffset + 2];
int prefix = prefixSuffixHeads[prefixIdx];
int prefixEnd = prefixSuffixHeads[prefixIdx + 1];
int suffix = prefixSuffixHeads[suffixIdx];
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. // Copy prefix.
while (PREFIX_SUFFIX[transformPrefix] != 0) { while (prefix != prefixEnd) {
dst[offset++] = PREFIX_SUFFIX[transformPrefix++]; dst[offset++] = prefixSuffixStorage[prefix++];
} }
// Copy trimmed word. // Copy trimmed word.
int omitFirst = transformType >= 12 ? (transformType - 11) : 0;
if (omitFirst > len) { if (omitFirst > len) {
omitFirst = len; omitFirst = len;
} }
wordOffset += omitFirst; srcOffset += omitFirst;
len -= omitFirst; len -= omitFirst;
len -= transformType <= 9 ? transformType : 0; // Omit last. len -= omitLast;
int i = len; int i = len;
while (i > 0) { while (i > 0) {
dst[offset++] = data.get(wordOffset++); dst[offset++] = src.get(srcOffset++);
i--; i--;
} }
// Ferment. // Ferment.
if (transformType == 11 || transformType == 10) { if (transformType == UPPERCASE_FIRST || transformType == UPPERCASE_ALL) {
int uppercaseOffset = offset - len; int uppercaseOffset = offset - len;
if (transformType == 10) { if (transformType == UPPERCASE_FIRST) {
len = 1; len = 1;
} }
while (len > 0) { while (len > 0) {
int tmp = dst[uppercaseOffset] & 0xFF; int c0 = dst[uppercaseOffset] & 0xFF;
if (tmp < 0xc0) { if (c0 < 0xC0) {
if (tmp >= 97 && tmp <= 122) { // in [a..z] range if (c0 >= 97 && c0 <= 122) { // in [a..z] range
dst[uppercaseOffset] ^= (byte) 32; dst[uppercaseOffset] ^= (byte) 32;
} }
uppercaseOffset += 1; uppercaseOffset += 1;
len -= 1; len -= 1;
} else if (tmp < 0xe0) { } else if (c0 < 0xE0) {
dst[uppercaseOffset + 1] ^= (byte) 32; dst[uppercaseOffset + 1] ^= (byte) 32;
uppercaseOffset += 2; uppercaseOffset += 2;
len -= 2; len -= 2;
@ -103,11 +164,71 @@ final class Transform {
len -= 3; len -= 3;
} }
} }
} else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) {
int shiftOffset = offset - len;
short param = transforms.params[transformIndex];
/* Limited sign extension: scalar < (1 << 24). */
int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000));
while (len > 0) {
int step = 1;
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) {
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) {
byte c1 = dst[shiftOffset + 1];
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) {
byte c1 = dst[shiftOffset + 1];
byte c2 = dst[shiftOffset + 2];
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. // Copy suffix.
while (PREFIX_SUFFIX[transformSuffix] != 0) { while (suffix != suffixEnd) {
dst[offset++] = PREFIX_SUFFIX[transformSuffix++]; dst[offset++] = prefixSuffixStorage[suffix++];
} }
return offset - dstOffset; return offset - dstOffset;

View File

@ -36,8 +36,8 @@ public class TransformTest {
public void testTrimAll() { public void testTrimAll() {
byte[] output = new byte[0]; byte[] output = new byte[0];
byte[] input = {119, 111, 114, 100}; // "word" byte[] input = {119, 111, 114, 100}; // "word"
Transform.transformDictionaryWord( Transform.transformDictionaryWord(output, 0,
output, 0, ByteBuffer.wrap(input), 0, input.length, 39); ByteBuffer.wrap(input), 0, input.length, Transform.RFC_TRANSFORMS, 39);
byte[] expectedOutput = new byte[0]; byte[] expectedOutput = new byte[0];
assertArrayEquals(expectedOutput, output); assertArrayEquals(expectedOutput, output);
} }
@ -46,8 +46,8 @@ public class TransformTest {
public void testCapitalize() { public void testCapitalize() {
byte[] output = new byte[6]; byte[] output = new byte[6];
byte[] input = {113, -61, -90, -32, -92, -86}; // "qæप" byte[] input = {113, -61, -90, -32, -92, -86}; // "qæप"
Transform.transformDictionaryWord( Transform.transformDictionaryWord(output, 0,
output, 0, ByteBuffer.wrap(input), 0, input.length, 44); ByteBuffer.wrap(input), 0, input.length, Transform.RFC_TRANSFORMS, 44);
byte[] expectedOutput = {81, -61, -122, -32, -92, -81}; // "QÆय" byte[] expectedOutput = {81, -61, -122, -32, -92, -81}; // "QÆय"
assertArrayEquals(expectedOutput, output); assertArrayEquals(expectedOutput, output);
} }
@ -60,9 +60,9 @@ public class TransformTest {
byte[] testWord = {111, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102}; byte[] testWord = {111, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
byte[] output = new byte[2259]; byte[] output = new byte[2259];
int offset = 0; int offset = 0;
for (int i = 0; i < Transform.NUM_TRANSFORMS; ++i) { for (int i = 0; i < Transform.NUM_RFC_TRANSFORMS; ++i) {
offset += Transform.transformDictionaryWord( offset += Transform.transformDictionaryWord(output, offset,
output, offset, ByteBuffer.wrap(testWord), 0, testWord.length, i); ByteBuffer.wrap(testWord), 0, testWord.length, Transform.RFC_TRANSFORMS, i);
output[offset++] = -1; output[offset++] = -1;
} }
assertEquals(output.length, offset); assertEquals(output.length, offset);