brotli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +1 -0
- data/Rakefile +6 -1
- data/brotli.gemspec +1 -1
- data/docs/Brotli.html +485 -0
- data/docs/Brotli/Error.html +124 -0
- data/docs/_index.html +122 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +127 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +127 -0
- data/docs/js/app.js +292 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +67 -0
- data/docs/top-level-namespace.html +110 -0
- data/ext/brotli/brotli.c +20 -0
- data/lib/brotli/version.rb +1 -1
- data/vendor/brotli/c/common/constants.h +13 -6
- data/vendor/brotli/c/{dec → common}/context.h +182 -172
- data/vendor/brotli/c/common/dictionary.bin +0 -0
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
- data/vendor/brotli/c/common/dictionary.c +1 -1
- data/vendor/brotli/c/common/dictionary.h +4 -4
- data/vendor/brotli/c/common/platform.h +509 -0
- data/vendor/brotli/c/common/transform.c +235 -0
- data/vendor/brotli/c/common/transform.h +80 -0
- data/vendor/brotli/c/common/version.h +8 -1
- data/vendor/brotli/c/dec/bit_reader.c +1 -1
- data/vendor/brotli/c/dec/bit_reader.h +35 -86
- data/vendor/brotli/c/dec/decode.c +322 -205
- data/vendor/brotli/c/dec/huffman.c +35 -37
- data/vendor/brotli/c/dec/huffman.h +13 -9
- data/vendor/brotli/c/dec/prefix.h +3 -4
- data/vendor/brotli/c/dec/state.c +26 -34
- data/vendor/brotli/c/dec/state.h +34 -23
- data/vendor/brotli/c/enc/backward_references.c +25 -15
- data/vendor/brotli/c/enc/backward_references.h +5 -6
- data/vendor/brotli/c/enc/backward_references_hq.c +94 -68
- data/vendor/brotli/c/enc/backward_references_hq.h +22 -25
- data/vendor/brotli/c/enc/backward_references_inc.h +10 -10
- data/vendor/brotli/c/enc/bit_cost.c +1 -1
- data/vendor/brotli/c/enc/bit_cost.h +5 -5
- data/vendor/brotli/c/enc/block_encoder_inc.h +7 -6
- data/vendor/brotli/c/enc/block_splitter.c +2 -3
- data/vendor/brotli/c/enc/block_splitter.h +1 -1
- data/vendor/brotli/c/enc/block_splitter_inc.h +11 -11
- data/vendor/brotli/c/enc/brotli_bit_stream.c +102 -101
- data/vendor/brotli/c/enc/brotli_bit_stream.h +19 -38
- data/vendor/brotli/c/enc/cluster.c +1 -1
- data/vendor/brotli/c/enc/cluster.h +1 -1
- data/vendor/brotli/c/enc/command.h +40 -30
- data/vendor/brotli/c/enc/compress_fragment.c +21 -22
- data/vendor/brotli/c/enc/compress_fragment.h +1 -1
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +101 -68
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +1 -1
- data/vendor/brotli/c/enc/dictionary_hash.c +1 -1
- data/vendor/brotli/c/enc/encode.c +262 -162
- data/vendor/brotli/c/enc/encoder_dict.c +32 -0
- data/vendor/brotli/c/enc/encoder_dict.h +41 -0
- data/vendor/brotli/c/enc/entropy_encode.c +14 -14
- data/vendor/brotli/c/enc/entropy_encode.h +5 -5
- data/vendor/brotli/c/enc/entropy_encode_static.h +3 -3
- data/vendor/brotli/c/enc/fast_log.h +4 -2
- data/vendor/brotli/c/enc/find_match_length.h +3 -3
- data/vendor/brotli/c/enc/hash.h +75 -24
- data/vendor/brotli/c/enc/hash_composite_inc.h +133 -0
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +9 -8
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +8 -8
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +8 -8
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +10 -9
- data/vendor/brotli/c/enc/hash_rolling_inc.h +215 -0
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +9 -8
- data/vendor/brotli/c/enc/histogram.c +9 -6
- data/vendor/brotli/c/enc/histogram.h +6 -3
- data/vendor/brotli/c/enc/histogram_inc.h +1 -1
- data/vendor/brotli/c/enc/literal_cost.c +5 -5
- data/vendor/brotli/c/enc/literal_cost.h +2 -2
- data/vendor/brotli/c/enc/memory.c +5 -16
- data/vendor/brotli/c/enc/memory.h +40 -1
- data/vendor/brotli/c/enc/metablock.c +163 -25
- data/vendor/brotli/c/enc/metablock.h +13 -8
- data/vendor/brotli/c/enc/metablock_inc.h +1 -1
- data/vendor/brotli/c/enc/params.h +44 -0
- data/vendor/brotli/c/enc/prefix.h +3 -4
- data/vendor/brotli/c/enc/quality.h +29 -24
- data/vendor/brotli/c/enc/ringbuffer.h +15 -11
- data/vendor/brotli/c/enc/static_dict.c +49 -45
- data/vendor/brotli/c/enc/static_dict.h +4 -3
- data/vendor/brotli/c/enc/static_dict_lut.h +1 -1
- data/vendor/brotli/c/enc/utf8_util.c +20 -20
- data/vendor/brotli/c/enc/utf8_util.h +1 -1
- data/vendor/brotli/c/enc/write_bits.h +16 -21
- data/vendor/brotli/c/include/brotli/decode.h +13 -8
- data/vendor/brotli/c/include/brotli/encode.h +33 -8
- data/vendor/brotli/c/include/brotli/port.h +211 -83
- data/vendor/brotli/c/include/brotli/types.h +0 -7
- metadata +33 -12
- data/vendor/brotli/c/dec/port.h +0 -168
- data/vendor/brotli/c/dec/transform.h +0 -300
- data/vendor/brotli/c/enc/context.h +0 -184
- data/vendor/brotli/c/enc/port.h +0 -184
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
#include <brotli/decode.h>
|
|
8
8
|
|
|
9
|
-
#
|
|
9
|
+
#if defined(__ARM_NEON__)
|
|
10
10
|
#include <arm_neon.h>
|
|
11
11
|
#endif
|
|
12
12
|
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
#include <string.h> /* memcpy, memset */
|
|
15
15
|
|
|
16
16
|
#include "../common/constants.h"
|
|
17
|
+
#include "../common/context.h"
|
|
17
18
|
#include "../common/dictionary.h"
|
|
19
|
+
#include "../common/platform.h"
|
|
20
|
+
#include "../common/transform.h"
|
|
18
21
|
#include "../common/version.h"
|
|
19
22
|
#include "./bit_reader.h"
|
|
20
|
-
#include "./context.h"
|
|
21
23
|
#include "./huffman.h"
|
|
22
|
-
#include "./port.h"
|
|
23
24
|
#include "./prefix.h"
|
|
24
25
|
#include "./state.h"
|
|
25
|
-
#include "./transform.h"
|
|
26
26
|
|
|
27
27
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
28
28
|
extern "C" {
|
|
@@ -37,7 +37,7 @@ extern "C" {
|
|
|
37
37
|
(unsigned long)(idx), (unsigned long)array_name[idx]))
|
|
38
38
|
|
|
39
39
|
#define HUFFMAN_TABLE_BITS 8U
|
|
40
|
-
#define HUFFMAN_TABLE_MASK
|
|
40
|
+
#define HUFFMAN_TABLE_MASK 0xFF
|
|
41
41
|
|
|
42
42
|
/* We need the slack region for the following reasons:
|
|
43
43
|
- doing up to two 16-byte copies for fast backward copying
|
|
@@ -59,11 +59,16 @@ static const uint8_t kCodeLengthPrefixValue[16] = {
|
|
|
59
59
|
|
|
60
60
|
BROTLI_BOOL BrotliDecoderSetParameter(
|
|
61
61
|
BrotliDecoderState* state, BrotliDecoderParameter p, uint32_t value) {
|
|
62
|
+
if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
|
|
62
63
|
switch (p) {
|
|
63
64
|
case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:
|
|
64
65
|
state->canny_ringbuffer_allocation = !!value ? 0 : 1;
|
|
65
66
|
return BROTLI_TRUE;
|
|
66
67
|
|
|
68
|
+
case BROTLI_DECODER_PARAM_LARGE_WINDOW:
|
|
69
|
+
state->large_window = TO_BROTLI_BOOL(!!value);
|
|
70
|
+
return BROTLI_TRUE;
|
|
71
|
+
|
|
67
72
|
default: return BROTLI_FALSE;
|
|
68
73
|
}
|
|
69
74
|
}
|
|
@@ -80,8 +85,15 @@ BrotliDecoderState* BrotliDecoderCreateInstance(
|
|
|
80
85
|
BROTLI_DUMP();
|
|
81
86
|
return 0;
|
|
82
87
|
}
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) {
|
|
89
|
+
BROTLI_DUMP();
|
|
90
|
+
if (!alloc_func && !free_func) {
|
|
91
|
+
free(state);
|
|
92
|
+
} else if (alloc_func && free_func) {
|
|
93
|
+
free_func(opaque, state);
|
|
94
|
+
}
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
85
97
|
return state;
|
|
86
98
|
}
|
|
87
99
|
|
|
@@ -97,39 +109,61 @@ void BrotliDecoderDestroyInstance(BrotliDecoderState* state) {
|
|
|
97
109
|
}
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
/* Saves error code and converts it to BrotliDecoderResult */
|
|
112
|
+
/* Saves error code and converts it to BrotliDecoderResult. */
|
|
101
113
|
static BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(
|
|
102
114
|
BrotliDecoderState* s, BrotliDecoderErrorCode e) {
|
|
103
115
|
s->error_code = (int)e;
|
|
104
116
|
switch (e) {
|
|
105
117
|
case BROTLI_DECODER_SUCCESS:
|
|
106
118
|
return BROTLI_DECODER_RESULT_SUCCESS;
|
|
119
|
+
|
|
107
120
|
case BROTLI_DECODER_NEEDS_MORE_INPUT:
|
|
108
121
|
return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
|
|
122
|
+
|
|
109
123
|
case BROTLI_DECODER_NEEDS_MORE_OUTPUT:
|
|
110
124
|
return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
|
|
125
|
+
|
|
111
126
|
default:
|
|
112
127
|
return BROTLI_DECODER_RESULT_ERROR;
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
130
|
|
|
116
|
-
/* Decodes
|
|
117
|
-
Precondition: bit-reader accumulator has at least
|
|
118
|
-
static
|
|
131
|
+
/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli".
|
|
132
|
+
Precondition: bit-reader accumulator has at least 8 bits. */
|
|
133
|
+
static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,
|
|
134
|
+
BrotliBitReader* br) {
|
|
119
135
|
uint32_t n;
|
|
136
|
+
BROTLI_BOOL large_window = s->large_window;
|
|
137
|
+
s->large_window = BROTLI_FALSE;
|
|
120
138
|
BrotliTakeBits(br, 1, &n);
|
|
121
139
|
if (n == 0) {
|
|
122
|
-
|
|
140
|
+
s->window_bits = 16;
|
|
141
|
+
return BROTLI_DECODER_SUCCESS;
|
|
123
142
|
}
|
|
124
143
|
BrotliTakeBits(br, 3, &n);
|
|
125
144
|
if (n != 0) {
|
|
126
|
-
|
|
145
|
+
s->window_bits = 17 + n;
|
|
146
|
+
return BROTLI_DECODER_SUCCESS;
|
|
127
147
|
}
|
|
128
148
|
BrotliTakeBits(br, 3, &n);
|
|
149
|
+
if (n == 1) {
|
|
150
|
+
if (large_window) {
|
|
151
|
+
BrotliTakeBits(br, 1, &n);
|
|
152
|
+
if (n == 1) {
|
|
153
|
+
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
|
|
154
|
+
}
|
|
155
|
+
s->large_window = BROTLI_TRUE;
|
|
156
|
+
return BROTLI_DECODER_SUCCESS;
|
|
157
|
+
} else {
|
|
158
|
+
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
129
161
|
if (n != 0) {
|
|
130
|
-
|
|
162
|
+
s->window_bits = 8 + n;
|
|
163
|
+
return BROTLI_DECODER_SUCCESS;
|
|
131
164
|
}
|
|
132
|
-
|
|
165
|
+
s->window_bits = 17;
|
|
166
|
+
return BROTLI_DECODER_SUCCESS;
|
|
133
167
|
}
|
|
134
168
|
|
|
135
169
|
static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
|
|
@@ -155,7 +189,7 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(
|
|
|
155
189
|
*value = 0;
|
|
156
190
|
return BROTLI_DECODER_SUCCESS;
|
|
157
191
|
}
|
|
158
|
-
|
|
192
|
+
/* Fall through. */
|
|
159
193
|
|
|
160
194
|
case BROTLI_STATE_DECODE_UINT8_SHORT:
|
|
161
195
|
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {
|
|
@@ -169,7 +203,7 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(
|
|
|
169
203
|
}
|
|
170
204
|
/* Use output value as a temporary storage. It MUST be persisted. */
|
|
171
205
|
*value = bits;
|
|
172
|
-
|
|
206
|
+
/* Fall through. */
|
|
173
207
|
|
|
174
208
|
case BROTLI_STATE_DECODE_UINT8_LONG:
|
|
175
209
|
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {
|
|
@@ -206,7 +240,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
206
240
|
break;
|
|
207
241
|
}
|
|
208
242
|
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;
|
|
209
|
-
|
|
243
|
+
/* Fall through. */
|
|
210
244
|
|
|
211
245
|
case BROTLI_STATE_METABLOCK_HEADER_EMPTY:
|
|
212
246
|
if (!BrotliSafeReadBits(br, 1, &bits)) {
|
|
@@ -217,7 +251,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
217
251
|
return BROTLI_DECODER_SUCCESS;
|
|
218
252
|
}
|
|
219
253
|
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
|
|
220
|
-
|
|
254
|
+
/* Fall through. */
|
|
221
255
|
|
|
222
256
|
case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:
|
|
223
257
|
if (!BrotliSafeReadBits(br, 2, &bits)) {
|
|
@@ -231,7 +265,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
231
265
|
break;
|
|
232
266
|
}
|
|
233
267
|
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;
|
|
234
|
-
|
|
268
|
+
/* Fall through. */
|
|
235
269
|
|
|
236
270
|
case BROTLI_STATE_METABLOCK_HEADER_SIZE:
|
|
237
271
|
i = s->loop_counter;
|
|
@@ -247,7 +281,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
247
281
|
}
|
|
248
282
|
s->substate_metablock_header =
|
|
249
283
|
BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
|
|
250
|
-
|
|
284
|
+
/* Fall through. */
|
|
251
285
|
|
|
252
286
|
case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:
|
|
253
287
|
if (!s->is_last_metablock) {
|
|
@@ -268,7 +302,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
268
302
|
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED);
|
|
269
303
|
}
|
|
270
304
|
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;
|
|
271
|
-
|
|
305
|
+
/* Fall through. */
|
|
272
306
|
|
|
273
307
|
case BROTLI_STATE_METABLOCK_HEADER_BYTES:
|
|
274
308
|
if (!BrotliSafeReadBits(br, 2, &bits)) {
|
|
@@ -280,7 +314,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|
|
280
314
|
}
|
|
281
315
|
s->size_nibbles = (uint8_t)bits;
|
|
282
316
|
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;
|
|
283
|
-
|
|
317
|
+
/* Fall through. */
|
|
284
318
|
|
|
285
319
|
case BROTLI_STATE_METABLOCK_HEADER_METADATA:
|
|
286
320
|
i = s->loop_counter;
|
|
@@ -342,7 +376,7 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
|
|
|
342
376
|
*result = table->value;
|
|
343
377
|
return BROTLI_TRUE;
|
|
344
378
|
}
|
|
345
|
-
return BROTLI_FALSE;
|
|
379
|
+
return BROTLI_FALSE; /* No valid bits at all. */
|
|
346
380
|
}
|
|
347
381
|
val = (uint32_t)BrotliGetBitsUnmasked(br);
|
|
348
382
|
table += val & HUFFMAN_TABLE_MASK;
|
|
@@ -352,11 +386,11 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
|
|
|
352
386
|
*result = table->value;
|
|
353
387
|
return BROTLI_TRUE;
|
|
354
388
|
} else {
|
|
355
|
-
return BROTLI_FALSE;
|
|
389
|
+
return BROTLI_FALSE; /* Not enough bits for the first level. */
|
|
356
390
|
}
|
|
357
391
|
}
|
|
358
392
|
if (available_bits <= HUFFMAN_TABLE_BITS) {
|
|
359
|
-
return BROTLI_FALSE;
|
|
393
|
+
return BROTLI_FALSE; /* Not enough bits to move to the second level. */
|
|
360
394
|
}
|
|
361
395
|
|
|
362
396
|
/* Speculatively drop HUFFMAN_TABLE_BITS. */
|
|
@@ -364,7 +398,7 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
|
|
|
364
398
|
available_bits -= HUFFMAN_TABLE_BITS;
|
|
365
399
|
table += table->value + val;
|
|
366
400
|
if (available_bits < table->bits) {
|
|
367
|
-
return BROTLI_FALSE;
|
|
401
|
+
return BROTLI_FALSE; /* Not enough bits for the second level. */
|
|
368
402
|
}
|
|
369
403
|
|
|
370
404
|
BrotliDropBits(br, HUFFMAN_TABLE_BITS + table->bits);
|
|
@@ -428,12 +462,11 @@ static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) {
|
|
|
428
462
|
}
|
|
429
463
|
|
|
430
464
|
/* Reads (s->symbol + 1) symbols.
|
|
431
|
-
Totally 1..4 symbols are read, 1..
|
|
432
|
-
The list of symbols MUST NOT contain duplicates.
|
|
433
|
-
*/
|
|
465
|
+
Totally 1..4 symbols are read, 1..11 bits each.
|
|
466
|
+
The list of symbols MUST NOT contain duplicates. */
|
|
434
467
|
static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
|
|
435
|
-
uint32_t alphabet_size, BrotliDecoderState* s) {
|
|
436
|
-
/* max_bits == 1..
|
|
468
|
+
uint32_t alphabet_size, uint32_t max_symbol, BrotliDecoderState* s) {
|
|
469
|
+
/* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
|
|
437
470
|
BrotliBitReader* br = &s->br;
|
|
438
471
|
uint32_t max_bits = Log2Floor(alphabet_size - 1);
|
|
439
472
|
uint32_t i = s->sub_loop_counter;
|
|
@@ -445,7 +478,7 @@ static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
|
|
|
445
478
|
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
|
|
446
479
|
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
447
480
|
}
|
|
448
|
-
if (v >=
|
|
481
|
+
if (v >= max_symbol) {
|
|
449
482
|
return
|
|
450
483
|
BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
|
|
451
484
|
}
|
|
@@ -471,20 +504,20 @@ static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
|
|
|
471
504
|
B) remember code length (if it is not 0)
|
|
472
505
|
C) extend corresponding index-chain
|
|
473
506
|
D) reduce the Huffman space
|
|
474
|
-
E) update the histogram
|
|
475
|
-
*/
|
|
507
|
+
E) update the histogram */
|
|
476
508
|
static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len,
|
|
477
509
|
uint32_t* symbol, uint32_t* repeat, uint32_t* space,
|
|
478
510
|
uint32_t* prev_code_len, uint16_t* symbol_lists,
|
|
479
511
|
uint16_t* code_length_histo, int* next_symbol) {
|
|
480
512
|
*repeat = 0;
|
|
481
|
-
if (code_len != 0) {
|
|
513
|
+
if (code_len != 0) { /* code_len == 1..15 */
|
|
482
514
|
symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);
|
|
483
515
|
next_symbol[code_len] = (int)(*symbol);
|
|
484
516
|
*prev_code_len = code_len;
|
|
485
517
|
*space -= 32768U >> code_len;
|
|
486
518
|
code_length_histo[code_len]++;
|
|
487
|
-
BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n",
|
|
519
|
+
BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n",
|
|
520
|
+
(int)*symbol, (int)code_len));
|
|
488
521
|
}
|
|
489
522
|
(*symbol)++;
|
|
490
523
|
}
|
|
@@ -498,8 +531,7 @@ static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len,
|
|
|
498
531
|
D) For each symbol do the same operations as in ProcessSingleCodeLength
|
|
499
532
|
|
|
500
533
|
PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or
|
|
501
|
-
code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH
|
|
502
|
-
*/
|
|
534
|
+
code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */
|
|
503
535
|
static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len,
|
|
504
536
|
uint32_t repeat_delta, uint32_t alphabet_size, uint32_t* symbol,
|
|
505
537
|
uint32_t* repeat, uint32_t* space, uint32_t* prev_code_len,
|
|
@@ -530,7 +562,7 @@ static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len,
|
|
|
530
562
|
return;
|
|
531
563
|
}
|
|
532
564
|
BROTLI_LOG(("[ReadHuffmanCode] code_length[%d..%d] = %d\n",
|
|
533
|
-
|
|
565
|
+
(int)*symbol, (int)(*symbol + repeat_delta - 1), (int)*repeat_code_len));
|
|
534
566
|
if (*repeat_code_len != 0) {
|
|
535
567
|
unsigned last = *symbol + repeat_delta;
|
|
536
568
|
int next = next_symbol[*repeat_code_len];
|
|
@@ -576,12 +608,12 @@ static BrotliDecoderErrorCode ReadSymbolCodeLengths(
|
|
|
576
608
|
BrotliFillBitWindow16(br);
|
|
577
609
|
p += BrotliGetBitsUnmasked(br) &
|
|
578
610
|
BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
|
|
579
|
-
BrotliDropBits(br, p->bits); /* Use 1..5 bits */
|
|
611
|
+
BrotliDropBits(br, p->bits); /* Use 1..5 bits. */
|
|
580
612
|
code_len = p->value; /* code_len == 0..17 */
|
|
581
613
|
if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
|
|
582
614
|
ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
|
|
583
615
|
&prev_code_len, symbol_lists, code_length_histo, next_symbol);
|
|
584
|
-
} else {
|
|
616
|
+
} else { /* code_len == 16..17, extra_bits == 2..3 */
|
|
585
617
|
uint32_t extra_bits =
|
|
586
618
|
(code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3;
|
|
587
619
|
uint32_t repeat_delta =
|
|
@@ -616,13 +648,13 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
|
|
|
616
648
|
get_byte = BROTLI_TRUE;
|
|
617
649
|
continue;
|
|
618
650
|
}
|
|
619
|
-
code_len = p->value;
|
|
651
|
+
code_len = p->value; /* code_len == 0..17 */
|
|
620
652
|
if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
|
|
621
653
|
BrotliDropBits(br, p->bits);
|
|
622
654
|
ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space,
|
|
623
655
|
&s->prev_code_len, s->symbol_lists, s->code_length_histo,
|
|
624
656
|
s->next_symbol);
|
|
625
|
-
} else {
|
|
657
|
+
} else { /* code_len == 16..17, extra_bits == 2..3 */
|
|
626
658
|
uint32_t extra_bits = code_len - 14U;
|
|
627
659
|
uint32_t repeat_delta = (bits >> p->bits) & BitMask(extra_bits);
|
|
628
660
|
if (available_bits < p->bits + extra_bits) {
|
|
@@ -674,7 +706,7 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
|
|
|
674
706
|
++num_codes;
|
|
675
707
|
++s->code_length_histo[v];
|
|
676
708
|
if (space - 1U >= 32U) {
|
|
677
|
-
/* space is 0 or wrapped around */
|
|
709
|
+
/* space is 0 or wrapped around. */
|
|
678
710
|
break;
|
|
679
711
|
}
|
|
680
712
|
}
|
|
@@ -689,22 +721,22 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
|
|
|
689
721
|
There are 2 scenarios:
|
|
690
722
|
A) Huffman code contains only few symbols (1..4). Those symbols are read
|
|
691
723
|
directly; their code lengths are defined by the number of symbols.
|
|
692
|
-
For this scenario 4 -
|
|
724
|
+
For this scenario 4 - 49 bits will be read.
|
|
693
725
|
|
|
694
726
|
B) 2-phase decoding:
|
|
695
727
|
B.1) Small Huffman table is decoded; it is specified with code lengths
|
|
696
728
|
encoded with predefined entropy code. 32 - 74 bits are used.
|
|
697
729
|
B.2) Decoded table is used to decode code lengths of symbols in resulting
|
|
698
|
-
Huffman table. In worst case 3520 bits are read.
|
|
699
|
-
*/
|
|
730
|
+
Huffman table. In worst case 3520 bits are read. */
|
|
700
731
|
static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|
732
|
+
uint32_t max_symbol,
|
|
701
733
|
HuffmanCode* table,
|
|
702
734
|
uint32_t* opt_table_size,
|
|
703
735
|
BrotliDecoderState* s) {
|
|
704
736
|
BrotliBitReader* br = &s->br;
|
|
705
737
|
/* Unnecessary masking, but might be good for safety. */
|
|
706
|
-
alphabet_size &=
|
|
707
|
-
/* State machine */
|
|
738
|
+
alphabet_size &= 0x7FF;
|
|
739
|
+
/* State machine. */
|
|
708
740
|
for (;;) {
|
|
709
741
|
switch (s->substate_huffman) {
|
|
710
742
|
case BROTLI_STATE_HUFFMAN_NONE:
|
|
@@ -717,7 +749,7 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|
|
717
749
|
0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
|
|
718
750
|
if (s->sub_loop_counter != 1) {
|
|
719
751
|
s->space = 32;
|
|
720
|
-
s->repeat = 0;
|
|
752
|
+
s->repeat = 0; /* num_codes */
|
|
721
753
|
memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo[0]) *
|
|
722
754
|
(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));
|
|
723
755
|
memset(&s->code_length_code_lengths[0], 0,
|
|
@@ -725,24 +757,26 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|
|
725
757
|
s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
|
|
726
758
|
continue;
|
|
727
759
|
}
|
|
728
|
-
|
|
760
|
+
/* Fall through. */
|
|
729
761
|
|
|
730
762
|
case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
|
|
731
763
|
/* Read symbols, codes & code lengths directly. */
|
|
732
|
-
if (!BrotliSafeReadBits(br, 2, &s->symbol)) {
|
|
764
|
+
if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */
|
|
733
765
|
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
|
|
734
766
|
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
735
767
|
}
|
|
736
768
|
s->sub_loop_counter = 0;
|
|
737
|
-
|
|
769
|
+
/* Fall through. */
|
|
770
|
+
|
|
738
771
|
case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
|
|
739
772
|
BrotliDecoderErrorCode result =
|
|
740
|
-
ReadSimpleHuffmanSymbols(alphabet_size, s);
|
|
773
|
+
ReadSimpleHuffmanSymbols(alphabet_size, max_symbol, s);
|
|
741
774
|
if (result != BROTLI_DECODER_SUCCESS) {
|
|
742
775
|
return result;
|
|
743
776
|
}
|
|
744
|
-
/* No break, transit to the next state. */
|
|
745
777
|
}
|
|
778
|
+
/* Fall through. */
|
|
779
|
+
|
|
746
780
|
case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
|
|
747
781
|
uint32_t table_size;
|
|
748
782
|
if (s->symbol == 3) {
|
|
@@ -785,20 +819,21 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|
|
785
819
|
s->repeat_code_len = 0;
|
|
786
820
|
s->space = 32768;
|
|
787
821
|
s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
|
|
788
|
-
/* No break, transit to the next state. */
|
|
789
822
|
}
|
|
823
|
+
/* Fall through. */
|
|
824
|
+
|
|
790
825
|
case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
|
|
791
826
|
uint32_t table_size;
|
|
792
|
-
BrotliDecoderErrorCode result = ReadSymbolCodeLengths(
|
|
827
|
+
BrotliDecoderErrorCode result = ReadSymbolCodeLengths(max_symbol, s);
|
|
793
828
|
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
|
|
794
|
-
result = SafeReadSymbolCodeLengths(
|
|
829
|
+
result = SafeReadSymbolCodeLengths(max_symbol, s);
|
|
795
830
|
}
|
|
796
831
|
if (result != BROTLI_DECODER_SUCCESS) {
|
|
797
832
|
return result;
|
|
798
833
|
}
|
|
799
834
|
|
|
800
835
|
if (s->space != 0) {
|
|
801
|
-
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", s->space));
|
|
836
|
+
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)s->space));
|
|
802
837
|
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
|
|
803
838
|
}
|
|
804
839
|
table_size = BrotliBuildHuffmanTable(
|
|
@@ -823,7 +858,7 @@ static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table,
|
|
|
823
858
|
uint32_t code;
|
|
824
859
|
uint32_t nbits;
|
|
825
860
|
code = ReadSymbol(table, br);
|
|
826
|
-
nbits = kBlockLengthPrefixCode[code].nbits;
|
|
861
|
+
nbits = kBlockLengthPrefixCode[code].nbits; /* nbits == 2..24 */
|
|
827
862
|
return kBlockLengthPrefixCode[code].offset + BrotliReadBits(br, nbits);
|
|
828
863
|
}
|
|
829
864
|
|
|
@@ -842,7 +877,7 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
|
|
|
842
877
|
}
|
|
843
878
|
{
|
|
844
879
|
uint32_t bits;
|
|
845
|
-
uint32_t nbits = kBlockLengthPrefixCode[index].nbits;
|
|
880
|
+
uint32_t nbits = kBlockLengthPrefixCode[index].nbits; /* nbits == 2..24 */
|
|
846
881
|
if (!BrotliSafeReadBits(br, nbits, &bits)) {
|
|
847
882
|
s->block_length_index = index;
|
|
848
883
|
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
|
|
@@ -867,8 +902,7 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
|
|
|
867
902
|
of Y values, and reinitialize only first elements in L.
|
|
868
903
|
|
|
869
904
|
Most of input values are 0 and 1. To reduce number of branches, we replace
|
|
870
|
-
inner for loop with do-while.
|
|
871
|
-
*/
|
|
905
|
+
inner for loop with do-while. */
|
|
872
906
|
static BROTLI_NOINLINE void InverseMoveToFrontTransform(
|
|
873
907
|
uint8_t* v, uint32_t v_len, BrotliDecoderState* state) {
|
|
874
908
|
/* Reinitialize elements that could have been changed. */
|
|
@@ -884,7 +918,7 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(
|
|
|
884
918
|
/* Initialize list using 4 consequent values pattern. */
|
|
885
919
|
mtf[0] = pattern;
|
|
886
920
|
do {
|
|
887
|
-
pattern += 0x04040404;
|
|
921
|
+
pattern += 0x04040404; /* Advance all 4 values by 4. */
|
|
888
922
|
mtf[i] = pattern;
|
|
889
923
|
i++;
|
|
890
924
|
} while (i <= upper_bound);
|
|
@@ -917,7 +951,8 @@ static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
|
|
|
917
951
|
while (s->htree_index < group->num_htrees) {
|
|
918
952
|
uint32_t table_size;
|
|
919
953
|
BrotliDecoderErrorCode result =
|
|
920
|
-
ReadHuffmanCode(group->alphabet_size,
|
|
954
|
+
ReadHuffmanCode(group->alphabet_size, group->max_symbol,
|
|
955
|
+
s->next, &table_size, s);
|
|
921
956
|
if (result != BROTLI_DECODER_SUCCESS) return result;
|
|
922
957
|
group->htrees[s->htree_index] = s->next;
|
|
923
958
|
s->next += table_size;
|
|
@@ -934,8 +969,7 @@ static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
|
|
|
934
969
|
2) Decode Huffman table using ReadHuffmanCode function.
|
|
935
970
|
This table will be used for reading context map items.
|
|
936
971
|
3) Read context map items; "0" values could be run-length encoded.
|
|
937
|
-
4) Optionally, apply InverseMoveToFront transform to the resulting map.
|
|
938
|
-
*/
|
|
972
|
+
4) Optionally, apply InverseMoveToFront transform to the resulting map. */
|
|
939
973
|
static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
940
974
|
uint32_t* num_htrees,
|
|
941
975
|
uint8_t** context_map_arg,
|
|
@@ -953,7 +987,8 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
|
953
987
|
s->context_index = 0;
|
|
954
988
|
BROTLI_LOG_UINT(context_map_size);
|
|
955
989
|
BROTLI_LOG_UINT(*num_htrees);
|
|
956
|
-
*context_map_arg =
|
|
990
|
+
*context_map_arg =
|
|
991
|
+
(uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size);
|
|
957
992
|
if (*context_map_arg == 0) {
|
|
958
993
|
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);
|
|
959
994
|
}
|
|
@@ -962,7 +997,8 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
|
962
997
|
return BROTLI_DECODER_SUCCESS;
|
|
963
998
|
}
|
|
964
999
|
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
|
|
965
|
-
|
|
1000
|
+
/* Fall through. */
|
|
1001
|
+
|
|
966
1002
|
case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
|
|
967
1003
|
uint32_t bits;
|
|
968
1004
|
/* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
|
|
@@ -979,15 +1015,19 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
|
979
1015
|
}
|
|
980
1016
|
BROTLI_LOG_UINT(s->max_run_length_prefix);
|
|
981
1017
|
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
|
|
982
|
-
/* No break, continue to next state. */
|
|
983
1018
|
}
|
|
984
|
-
|
|
985
|
-
|
|
1019
|
+
/* Fall through. */
|
|
1020
|
+
|
|
1021
|
+
case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {
|
|
1022
|
+
uint32_t alphabet_size = *num_htrees + s->max_run_length_prefix;
|
|
1023
|
+
result = ReadHuffmanCode(alphabet_size, alphabet_size,
|
|
986
1024
|
s->context_map_table, NULL, s);
|
|
987
1025
|
if (result != BROTLI_DECODER_SUCCESS) return result;
|
|
988
1026
|
s->code = 0xFFFF;
|
|
989
1027
|
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
|
|
990
|
-
|
|
1028
|
+
}
|
|
1029
|
+
/* Fall through. */
|
|
1030
|
+
|
|
991
1031
|
case BROTLI_STATE_CONTEXT_MAP_DECODE: {
|
|
992
1032
|
uint32_t context_index = s->context_index;
|
|
993
1033
|
uint32_t max_run_length_prefix = s->max_run_length_prefix;
|
|
@@ -1034,8 +1074,9 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
|
1034
1074
|
} while (--reps);
|
|
1035
1075
|
}
|
|
1036
1076
|
}
|
|
1037
|
-
/* No break, continue to next state. */
|
|
1038
1077
|
}
|
|
1078
|
+
/* Fall through. */
|
|
1079
|
+
|
|
1039
1080
|
case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
|
|
1040
1081
|
uint32_t bits;
|
|
1041
1082
|
if (!BrotliSafeReadBits(br, 1, &bits)) {
|
|
@@ -1048,6 +1089,7 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|
|
1048
1089
|
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
|
|
1049
1090
|
return BROTLI_DECODER_SUCCESS;
|
|
1050
1091
|
}
|
|
1092
|
+
|
|
1051
1093
|
default:
|
|
1052
1094
|
return
|
|
1053
1095
|
BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);
|
|
@@ -1066,8 +1108,11 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
|
|
|
1066
1108
|
BrotliBitReader* br = &s->br;
|
|
1067
1109
|
uint32_t* ringbuffer = &s->block_type_rb[tree_type * 2];
|
|
1068
1110
|
uint32_t block_type;
|
|
1111
|
+
if (max_block_type <= 1) {
|
|
1112
|
+
return BROTLI_FALSE;
|
|
1113
|
+
}
|
|
1069
1114
|
|
|
1070
|
-
/* Read 0..15 + 3..39 bits */
|
|
1115
|
+
/* Read 0..15 + 3..39 bits. */
|
|
1071
1116
|
if (!safe) {
|
|
1072
1117
|
block_type = ReadSymbol(type_tree, br);
|
|
1073
1118
|
s->block_length[tree_type] = ReadBlockLength(len_tree, br);
|
|
@@ -1124,9 +1169,8 @@ static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {
|
|
|
1124
1169
|
trivial = s->trivial_literal_contexts[block_type >> 5];
|
|
1125
1170
|
s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;
|
|
1126
1171
|
s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];
|
|
1127
|
-
context_mode = s->context_modes[block_type];
|
|
1128
|
-
s->
|
|
1129
|
-
s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]];
|
|
1172
|
+
context_mode = s->context_modes[block_type] & 3;
|
|
1173
|
+
s->context_lookup = BROTLI_CONTEXT_LUT(context_mode);
|
|
1130
1174
|
}
|
|
1131
1175
|
|
|
1132
1176
|
/* Decodes the block type and updates the state for literal context.
|
|
@@ -1163,6 +1207,7 @@ static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
|
|
|
1163
1207
|
static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
|
|
1164
1208
|
DecodeCommandBlockSwitchInternal(0, s);
|
|
1165
1209
|
}
|
|
1210
|
+
|
|
1166
1211
|
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
|
|
1167
1212
|
BrotliDecoderState* s) {
|
|
1168
1213
|
return DecodeCommandBlockSwitchInternal(1, s);
|
|
@@ -1199,8 +1244,7 @@ static size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {
|
|
|
1199
1244
|
|
|
1200
1245
|
/* Dumps output.
|
|
1201
1246
|
Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push
|
|
1202
|
-
and either ring-buffer is as big as window size, or |force| is true.
|
|
1203
|
-
*/
|
|
1247
|
+
and either ring-buffer is as big as window size, or |force| is true. */
|
|
1204
1248
|
static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(
|
|
1205
1249
|
BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,
|
|
1206
1250
|
size_t* total_out, BROTLI_BOOL force) {
|
|
@@ -1259,8 +1303,7 @@ static void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {
|
|
|
1259
1303
|
this function is called.
|
|
1260
1304
|
|
|
1261
1305
|
Last two bytes of ring-buffer are initialized to 0, so context calculation
|
|
1262
|
-
could be done uniformly for the first two and all other positions.
|
|
1263
|
-
*/
|
|
1306
|
+
could be done uniformly for the first two and all other positions. */
|
|
1264
1307
|
static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
|
|
1265
1308
|
BrotliDecoderState* s) {
|
|
1266
1309
|
uint8_t* old_ringbuffer = s->ringbuffer;
|
|
@@ -1268,8 +1311,8 @@ static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
|
|
|
1268
1311
|
return BROTLI_TRUE;
|
|
1269
1312
|
}
|
|
1270
1313
|
|
|
1271
|
-
s->ringbuffer = (uint8_t*)
|
|
1272
|
-
kRingBufferWriteAheadSlack);
|
|
1314
|
+
s->ringbuffer = (uint8_t*)BROTLI_DECODER_ALLOC(s,
|
|
1315
|
+
(size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack);
|
|
1273
1316
|
if (s->ringbuffer == 0) {
|
|
1274
1317
|
/* Restore previous value. */
|
|
1275
1318
|
s->ringbuffer = old_ringbuffer;
|
|
@@ -1280,7 +1323,7 @@ static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
|
|
|
1280
1323
|
|
|
1281
1324
|
if (!!old_ringbuffer) {
|
|
1282
1325
|
memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);
|
|
1283
|
-
|
|
1326
|
+
BROTLI_DECODER_FREE(s, old_ringbuffer);
|
|
1284
1327
|
}
|
|
1285
1328
|
|
|
1286
1329
|
s->ringbuffer_size = s->new_ringbuffer_size;
|
|
@@ -1320,8 +1363,9 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
|
|
|
1320
1363
|
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
1321
1364
|
}
|
|
1322
1365
|
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;
|
|
1323
|
-
/* No break, continue to next state */
|
|
1324
1366
|
}
|
|
1367
|
+
/* Fall through. */
|
|
1368
|
+
|
|
1325
1369
|
case BROTLI_STATE_UNCOMPRESSED_WRITE: {
|
|
1326
1370
|
BrotliDecoderErrorCode result;
|
|
1327
1371
|
result = WriteRingBuffer(
|
|
@@ -1345,8 +1389,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
|
|
|
1345
1389
|
If we know the data size is small, do not allocate more ring buffer
|
|
1346
1390
|
size than needed to reduce memory usage.
|
|
1347
1391
|
|
|
1348
|
-
When this method is called, metablock size and flags MUST be decoded.
|
|
1349
|
-
*/
|
|
1392
|
+
When this method is called, metablock size and flags MUST be decoded. */
|
|
1350
1393
|
static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(
|
|
1351
1394
|
BrotliDecoderState* s) {
|
|
1352
1395
|
int window_size = 1 << s->window_bits;
|
|
@@ -1377,7 +1420,7 @@ static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(
|
|
|
1377
1420
|
if (!!s->canny_ringbuffer_allocation) {
|
|
1378
1421
|
/* Reduce ring buffer size to save memory when server is unscrupulous.
|
|
1379
1422
|
In worst case memory usage might be 1.5x bigger for a short period of
|
|
1380
|
-
ring buffer reallocation
|
|
1423
|
+
ring buffer reallocation. */
|
|
1381
1424
|
while ((new_ringbuffer_size >> 1) >= min_size) {
|
|
1382
1425
|
new_ringbuffer_size >>= 1;
|
|
1383
1426
|
}
|
|
@@ -1397,7 +1440,7 @@ static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {
|
|
|
1397
1440
|
s->loop_counter = i;
|
|
1398
1441
|
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
1399
1442
|
}
|
|
1400
|
-
s->context_modes[i] = (uint8_t)
|
|
1443
|
+
s->context_modes[i] = (uint8_t)bits;
|
|
1401
1444
|
BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);
|
|
1402
1445
|
i++;
|
|
1403
1446
|
}
|
|
@@ -1412,12 +1455,12 @@ static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
|
|
|
1412
1455
|
s->distance_context = 1;
|
|
1413
1456
|
} else {
|
|
1414
1457
|
int distance_code = s->distance_code << 1;
|
|
1415
|
-
/* kDistanceShortCodeIndexOffset has 2-bit values from LSB:
|
|
1416
|
-
|
|
1417
|
-
const uint32_t kDistanceShortCodeIndexOffset =
|
|
1418
|
-
/* kDistanceShortCodeValueOffset has 2-bit values from LSB:
|
|
1419
|
-
|
|
1420
|
-
const uint32_t kDistanceShortCodeValueOffset =
|
|
1458
|
+
/* kDistanceShortCodeIndexOffset has 2-bit values from LSB:
|
|
1459
|
+
3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */
|
|
1460
|
+
const uint32_t kDistanceShortCodeIndexOffset = 0xAAAFFF1B;
|
|
1461
|
+
/* kDistanceShortCodeValueOffset has 2-bit values from LSB:
|
|
1462
|
+
-0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */
|
|
1463
|
+
const uint32_t kDistanceShortCodeValueOffset = 0xFA5FA500;
|
|
1421
1464
|
int v = (s->dist_rb_idx +
|
|
1422
1465
|
(int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3;
|
|
1423
1466
|
s->distance_code = s->dist_rb[v];
|
|
@@ -1427,9 +1470,9 @@ static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
|
|
|
1427
1470
|
} else {
|
|
1428
1471
|
s->distance_code -= v;
|
|
1429
1472
|
if (s->distance_code <= 0) {
|
|
1430
|
-
/* A huge distance will cause a BROTLI_FAILURE() soon.
|
|
1431
|
-
|
|
1432
|
-
s->distance_code =
|
|
1473
|
+
/* A huge distance will cause a BROTLI_FAILURE() soon.
|
|
1474
|
+
This is a little faster than failing here. */
|
|
1475
|
+
s->distance_code = 0x7FFFFFFF;
|
|
1433
1476
|
}
|
|
1434
1477
|
}
|
|
1435
1478
|
}
|
|
@@ -1445,7 +1488,7 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBits(
|
|
|
1445
1488
|
}
|
|
1446
1489
|
}
|
|
1447
1490
|
|
|
1448
|
-
/* Precondition: s->distance_code < 0 */
|
|
1491
|
+
/* Precondition: s->distance_code < 0. */
|
|
1449
1492
|
static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
|
|
1450
1493
|
int safe, BrotliDecoderState* s, BrotliBitReader* br) {
|
|
1451
1494
|
int distval;
|
|
@@ -1461,10 +1504,10 @@ static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
|
|
|
1461
1504
|
}
|
|
1462
1505
|
s->distance_code = (int)code;
|
|
1463
1506
|
}
|
|
1464
|
-
/* Convert the distance code to the actual distance by possibly
|
|
1465
|
-
|
|
1507
|
+
/* Convert the distance code to the actual distance by possibly
|
|
1508
|
+
looking up past distances from the s->ringbuffer. */
|
|
1466
1509
|
s->distance_context = 0;
|
|
1467
|
-
if ((s->distance_code & ~
|
|
1510
|
+
if ((s->distance_code & ~0xF) == 0) {
|
|
1468
1511
|
TakeDistanceFromRingBuffer(s);
|
|
1469
1512
|
--s->block_length[2];
|
|
1470
1513
|
return BROTLI_TRUE;
|
|
@@ -1480,14 +1523,14 @@ static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
|
|
|
1480
1523
|
s->distance_code = (int)s->num_direct_distance_codes + offset +
|
|
1481
1524
|
(int)BrotliReadBits(br, nbits);
|
|
1482
1525
|
} else {
|
|
1483
|
-
/* This branch also works well when s->distance_postfix_bits == 0 */
|
|
1526
|
+
/* This branch also works well when s->distance_postfix_bits == 0. */
|
|
1484
1527
|
uint32_t bits;
|
|
1485
1528
|
postfix = distval & s->distance_postfix_mask;
|
|
1486
1529
|
distval >>= s->distance_postfix_bits;
|
|
1487
1530
|
nbits = ((uint32_t)distval >> 1) + 1;
|
|
1488
1531
|
if (safe) {
|
|
1489
1532
|
if (!SafeReadBits(br, nbits, &bits)) {
|
|
1490
|
-
s->distance_code = -1;
|
|
1533
|
+
s->distance_code = -1; /* Restore precondition. */
|
|
1491
1534
|
BrotliBitReaderRestoreState(br, &memento);
|
|
1492
1535
|
return BROTLI_FALSE;
|
|
1493
1536
|
}
|
|
@@ -1614,7 +1657,7 @@ CommandBegin:
|
|
|
1614
1657
|
if (safe) {
|
|
1615
1658
|
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
|
1616
1659
|
}
|
|
1617
|
-
if (!CheckInputAmount(safe, br, 28)) {
|
|
1660
|
+
if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */
|
|
1618
1661
|
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
|
1619
1662
|
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
1620
1663
|
goto saveStateAndReturn;
|
|
@@ -1623,7 +1666,7 @@ CommandBegin:
|
|
|
1623
1666
|
BROTLI_SAFE(DecodeCommandBlockSwitch(s));
|
|
1624
1667
|
goto CommandBegin;
|
|
1625
1668
|
}
|
|
1626
|
-
/* Read the insert/copy length in the command */
|
|
1669
|
+
/* Read the insert/copy length in the command. */
|
|
1627
1670
|
BROTLI_SAFE(ReadCommand(s, br, &i));
|
|
1628
1671
|
BROTLI_LOG(("[ProcessCommandsInternal] pos = %d insert = %d copy = %d\n",
|
|
1629
1672
|
pos, i, s->copy_length));
|
|
@@ -1636,13 +1679,13 @@ CommandInner:
|
|
|
1636
1679
|
if (safe) {
|
|
1637
1680
|
s->state = BROTLI_STATE_COMMAND_INNER;
|
|
1638
1681
|
}
|
|
1639
|
-
/* Read the literals in the command */
|
|
1682
|
+
/* Read the literals in the command. */
|
|
1640
1683
|
if (s->trivial_literal_context) {
|
|
1641
1684
|
uint32_t bits;
|
|
1642
1685
|
uint32_t value;
|
|
1643
1686
|
PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
|
|
1644
1687
|
do {
|
|
1645
|
-
if (!CheckInputAmount(safe, br, 28)) {
|
|
1688
|
+
if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
|
|
1646
1689
|
s->state = BROTLI_STATE_COMMAND_INNER;
|
|
1647
1690
|
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
1648
1691
|
goto saveStateAndReturn;
|
|
@@ -1678,7 +1721,7 @@ CommandInner:
|
|
|
1678
1721
|
do {
|
|
1679
1722
|
const HuffmanCode* hc;
|
|
1680
1723
|
uint8_t context;
|
|
1681
|
-
if (!CheckInputAmount(safe, br, 28)) {
|
|
1724
|
+
if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
|
|
1682
1725
|
s->state = BROTLI_STATE_COMMAND_INNER;
|
|
1683
1726
|
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
1684
1727
|
goto saveStateAndReturn;
|
|
@@ -1687,7 +1730,7 @@ CommandInner:
|
|
|
1687
1730
|
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
|
|
1688
1731
|
if (s->trivial_literal_context) goto CommandInner;
|
|
1689
1732
|
}
|
|
1690
|
-
context =
|
|
1733
|
+
context = BROTLI_CONTEXT(p1, p2, s->context_lookup);
|
|
1691
1734
|
BROTLI_LOG_UINT(context);
|
|
1692
1735
|
hc = s->literal_hgroup.htrees[s->context_map_slice[context]];
|
|
1693
1736
|
p2 = p1;
|
|
@@ -1743,32 +1786,44 @@ CommandPostDecodeLiterals:
|
|
|
1743
1786
|
}
|
|
1744
1787
|
i = s->copy_length;
|
|
1745
1788
|
/* Apply copy of LZ77 back-reference, or static dictionary reference if
|
|
1746
|
-
|
|
1789
|
+
the distance is larger than the max LZ77 distance */
|
|
1747
1790
|
if (s->distance_code > s->max_distance) {
|
|
1748
|
-
|
|
1791
|
+
/* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.
|
|
1792
|
+
With this choice, no signed overflow can occur after decoding
|
|
1793
|
+
a special distance code (e.g., after adding 3 to the last distance). */
|
|
1794
|
+
if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) {
|
|
1795
|
+
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
|
|
1796
|
+
"len: %d bytes left: %d\n",
|
|
1797
|
+
pos, s->distance_code, i, s->meta_block_remaining_len));
|
|
1798
|
+
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
|
|
1799
|
+
}
|
|
1749
1800
|
if (i >= BROTLI_MIN_DICTIONARY_WORD_LENGTH &&
|
|
1750
1801
|
i <= BROTLI_MAX_DICTIONARY_WORD_LENGTH) {
|
|
1802
|
+
int address = s->distance_code - s->max_distance - 1;
|
|
1803
|
+
const BrotliDictionary* words = s->dictionary;
|
|
1804
|
+
const BrotliTransforms* transforms = s->transforms;
|
|
1751
1805
|
int offset = (int)s->dictionary->offsets_by_length[i];
|
|
1752
1806
|
uint32_t shift = s->dictionary->size_bits_by_length[i];
|
|
1807
|
+
|
|
1753
1808
|
int mask = (int)BitMask(shift);
|
|
1754
1809
|
int word_idx = address & mask;
|
|
1755
1810
|
int transform_idx = address >> shift;
|
|
1756
1811
|
/* Compensate double distance-ring-buffer roll. */
|
|
1757
1812
|
s->dist_rb_idx += s->distance_context;
|
|
1758
1813
|
offset += word_idx * i;
|
|
1759
|
-
if (BROTLI_PREDICT_FALSE(!
|
|
1814
|
+
if (BROTLI_PREDICT_FALSE(!words->data)) {
|
|
1760
1815
|
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);
|
|
1761
1816
|
}
|
|
1762
|
-
if (transform_idx <
|
|
1763
|
-
const uint8_t* word = &
|
|
1817
|
+
if (transform_idx < (int)transforms->num_transforms) {
|
|
1818
|
+
const uint8_t* word = &words->data[offset];
|
|
1764
1819
|
int len = i;
|
|
1765
|
-
if (transform_idx == 0) {
|
|
1820
|
+
if (transform_idx == transforms->cutOffTransforms[0]) {
|
|
1766
1821
|
memcpy(&s->ringbuffer[pos], word, (size_t)len);
|
|
1767
1822
|
BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s]\n",
|
|
1768
1823
|
len, word));
|
|
1769
1824
|
} else {
|
|
1770
|
-
len =
|
|
1771
|
-
|
|
1825
|
+
len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len,
|
|
1826
|
+
transforms, transform_idx);
|
|
1772
1827
|
BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s],"
|
|
1773
1828
|
" transform_idx = %d, transformed: [%.*s]\n",
|
|
1774
1829
|
i, word, transform_idx, len, &s->ringbuffer[pos]));
|
|
@@ -1776,7 +1831,6 @@ CommandPostDecodeLiterals:
|
|
|
1776
1831
|
pos += len;
|
|
1777
1832
|
s->meta_block_remaining_len -= len;
|
|
1778
1833
|
if (pos >= s->ringbuffer_size) {
|
|
1779
|
-
/*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/
|
|
1780
1834
|
s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
|
|
1781
1835
|
goto saveStateAndReturn;
|
|
1782
1836
|
}
|
|
@@ -1798,14 +1852,13 @@ CommandPostDecodeLiterals:
|
|
|
1798
1852
|
uint8_t* copy_src = &s->ringbuffer[src_start];
|
|
1799
1853
|
int dst_end = pos + i;
|
|
1800
1854
|
int src_end = src_start + i;
|
|
1801
|
-
/*
|
|
1855
|
+
/* Update the recent distances cache. */
|
|
1802
1856
|
s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
|
|
1803
1857
|
++s->dist_rb_idx;
|
|
1804
1858
|
s->meta_block_remaining_len -= i;
|
|
1805
1859
|
/* There are 32+ bytes of slack in the ring-buffer allocation.
|
|
1806
1860
|
Also, we have 16 short codes, that make these 16 bytes irrelevant
|
|
1807
|
-
in the ring-buffer. Let's copy over them as a first guess.
|
|
1808
|
-
*/
|
|
1861
|
+
in the ring-buffer. Let's copy over them as a first guess. */
|
|
1809
1862
|
memmove16(copy_dst, copy_src);
|
|
1810
1863
|
if (src_end > pos && dst_end > src_start) {
|
|
1811
1864
|
/* Regions intersect. */
|
|
@@ -1828,7 +1881,7 @@ CommandPostDecodeLiterals:
|
|
|
1828
1881
|
}
|
|
1829
1882
|
BROTLI_LOG_UINT(s->meta_block_remaining_len);
|
|
1830
1883
|
if (s->meta_block_remaining_len <= 0) {
|
|
1831
|
-
/* Next metablock, if any */
|
|
1884
|
+
/* Next metablock, if any. */
|
|
1832
1885
|
s->state = BROTLI_STATE_METABLOCK_DONE;
|
|
1833
1886
|
goto saveStateAndReturn;
|
|
1834
1887
|
} else {
|
|
@@ -1848,7 +1901,7 @@ CommandPostWrapCopy:
|
|
|
1848
1901
|
}
|
|
1849
1902
|
}
|
|
1850
1903
|
if (s->meta_block_remaining_len <= 0) {
|
|
1851
|
-
/* Next metablock, if any */
|
|
1904
|
+
/* Next metablock, if any. */
|
|
1852
1905
|
s->state = BROTLI_STATE_METABLOCK_DONE;
|
|
1853
1906
|
goto saveStateAndReturn;
|
|
1854
1907
|
} else {
|
|
@@ -1873,6 +1926,21 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
|
|
|
1873
1926
|
return ProcessCommandsInternal(1, s);
|
|
1874
1927
|
}
|
|
1875
1928
|
|
|
1929
|
+
/* Returns the maximum number of distance symbols which can only represent
|
|
1930
|
+
distances not exceeding BROTLI_MAX_ALLOWED_DISTANCE. */
|
|
1931
|
+
static uint32_t BrotliMaxDistanceSymbol(uint32_t ndirect, uint32_t npostfix) {
|
|
1932
|
+
static const uint32_t bound[BROTLI_MAX_NPOSTFIX + 1] = {0, 4, 12, 28};
|
|
1933
|
+
static const uint32_t diff[BROTLI_MAX_NPOSTFIX + 1] = {73, 126, 228, 424};
|
|
1934
|
+
uint32_t postfix = 1U << npostfix;
|
|
1935
|
+
if (ndirect < bound[npostfix]) {
|
|
1936
|
+
return ndirect + diff[npostfix] + postfix;
|
|
1937
|
+
} else if (ndirect > bound[npostfix] + postfix) {
|
|
1938
|
+
return ndirect + diff[npostfix];
|
|
1939
|
+
} else {
|
|
1940
|
+
return bound[npostfix] + diff[npostfix] + postfix;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1876
1944
|
BrotliDecoderResult BrotliDecoderDecompress(
|
|
1877
1945
|
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
|
|
1878
1946
|
uint8_t* decoded_buffer) {
|
|
@@ -1883,7 +1951,9 @@ BrotliDecoderResult BrotliDecoderDecompress(
|
|
|
1883
1951
|
const uint8_t* next_in = encoded_buffer;
|
|
1884
1952
|
size_t available_out = *decoded_size;
|
|
1885
1953
|
uint8_t* next_out = decoded_buffer;
|
|
1886
|
-
BrotliDecoderStateInit(&s)
|
|
1954
|
+
if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {
|
|
1955
|
+
return BROTLI_DECODER_RESULT_ERROR;
|
|
1956
|
+
}
|
|
1887
1957
|
result = BrotliDecoderDecompressStream(
|
|
1888
1958
|
&s, &available_in, &next_in, &available_out, &next_out, &total_out);
|
|
1889
1959
|
*decoded_size = total_out;
|
|
@@ -1895,22 +1965,25 @@ BrotliDecoderResult BrotliDecoderDecompress(
|
|
|
1895
1965
|
}
|
|
1896
1966
|
|
|
1897
1967
|
/* Invariant: input stream is never overconsumed:
|
|
1898
|
-
|
|
1968
|
+
- invalid input implies that the whole stream is invalid -> any amount of
|
|
1899
1969
|
input could be read and discarded
|
|
1900
|
-
|
|
1970
|
+
- when result is "needs more input", then at least one more byte is REQUIRED
|
|
1901
1971
|
to complete decoding; all input data MUST be consumed by decoder, so
|
|
1902
1972
|
client could swap the input buffer
|
|
1903
|
-
|
|
1973
|
+
- when result is "needs more output" decoder MUST ensure that it doesn't
|
|
1904
1974
|
hold more than 7 bits in bit reader; this saves client from swapping input
|
|
1905
1975
|
buffer ahead of time
|
|
1906
|
-
|
|
1907
|
-
buffer; this is possible because the invariant is
|
|
1908
|
-
*/
|
|
1976
|
+
- when result is "success" decoder MUST return all unused data back to input
|
|
1977
|
+
buffer; this is possible because the invariant is held on enter */
|
|
1909
1978
|
BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
1910
1979
|
BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,
|
|
1911
1980
|
size_t* available_out, uint8_t** next_out, size_t* total_out) {
|
|
1912
1981
|
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
|
|
1913
1982
|
BrotliBitReader* br = &s->br;
|
|
1983
|
+
/* Ensure that |total_out| is set, even if no data will ever be pushed out. */
|
|
1984
|
+
if (total_out) {
|
|
1985
|
+
*total_out = s->partial_pos_out;
|
|
1986
|
+
}
|
|
1914
1987
|
/* Do not try to process further in a case of unrecoverable error. */
|
|
1915
1988
|
if ((int)s->error_code < 0) {
|
|
1916
1989
|
return BROTLI_DECODER_RESULT_ERROR;
|
|
@@ -1920,7 +1993,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
1920
1993
|
s, BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));
|
|
1921
1994
|
}
|
|
1922
1995
|
if (!*available_out) next_out = 0;
|
|
1923
|
-
if (s->buffer_length == 0) {
|
|
1996
|
+
if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */
|
|
1924
1997
|
br->avail_in = *available_in;
|
|
1925
1998
|
br->next_in = *next_in;
|
|
1926
1999
|
} else {
|
|
@@ -1932,9 +2005,10 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
1932
2005
|
}
|
|
1933
2006
|
/* State machine */
|
|
1934
2007
|
for (;;) {
|
|
1935
|
-
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2008
|
+
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2009
|
+
/* Error, needs more input/output. */
|
|
1936
2010
|
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
|
|
1937
|
-
if (s->ringbuffer != 0) {
|
|
2011
|
+
if (s->ringbuffer != 0) { /* Pro-actively push output. */
|
|
1938
2012
|
BrotliDecoderErrorCode intermediate_result = WriteRingBuffer(s,
|
|
1939
2013
|
available_out, next_out, total_out, BROTLI_TRUE);
|
|
1940
2014
|
/* WriteRingBuffer checks s->meta_block_remaining_len validity. */
|
|
@@ -1943,9 +2017,10 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
1943
2017
|
break;
|
|
1944
2018
|
}
|
|
1945
2019
|
}
|
|
1946
|
-
if (s->buffer_length != 0) {
|
|
1947
|
-
if (br->avail_in == 0) {
|
|
1948
|
-
/*
|
|
2020
|
+
if (s->buffer_length != 0) { /* Used with internal buffer. */
|
|
2021
|
+
if (br->avail_in == 0) {
|
|
2022
|
+
/* Successfully finished read transaction.
|
|
2023
|
+
Accumulator contains less than 8 bits, because internal buffer
|
|
1949
2024
|
is expanded byte-by-byte until it is enough to complete read. */
|
|
1950
2025
|
s->buffer_length = 0;
|
|
1951
2026
|
/* Switch to input stream and restart. */
|
|
@@ -1965,9 +2040,9 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
1965
2040
|
/* Retry with more data in buffer. */
|
|
1966
2041
|
continue;
|
|
1967
2042
|
}
|
|
1968
|
-
/* Can't finish reading and no more input
|
|
2043
|
+
/* Can't finish reading and no more input. */
|
|
1969
2044
|
break;
|
|
1970
|
-
} else {
|
|
2045
|
+
} else { /* Input stream doesn't contain enough input. */
|
|
1971
2046
|
/* Copy tail to internal buffer and return. */
|
|
1972
2047
|
*next_in = br->next_in;
|
|
1973
2048
|
*available_in = br->avail_in;
|
|
@@ -1986,7 +2061,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
1986
2061
|
|
|
1987
2062
|
if (s->buffer_length != 0) {
|
|
1988
2063
|
/* Just consumed the buffered input and produced some output. Otherwise
|
|
1989
|
-
it would result in "needs more input". Reset internal buffer
|
|
2064
|
+
it would result in "needs more input". Reset internal buffer. */
|
|
1990
2065
|
s->buffer_length = 0;
|
|
1991
2066
|
} else {
|
|
1992
2067
|
/* Using input stream in last iteration. When decoder switches to input
|
|
@@ -2006,18 +2081,37 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2006
2081
|
break;
|
|
2007
2082
|
}
|
|
2008
2083
|
/* Decode window size. */
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2084
|
+
result = DecodeWindowBits(s, br); /* Reads 1..8 bits. */
|
|
2085
|
+
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2086
|
+
break;
|
|
2087
|
+
}
|
|
2088
|
+
if (s->large_window) {
|
|
2089
|
+
s->state = BROTLI_STATE_LARGE_WINDOW_BITS;
|
|
2090
|
+
break;
|
|
2091
|
+
}
|
|
2092
|
+
s->state = BROTLI_STATE_INITIALIZE;
|
|
2093
|
+
break;
|
|
2094
|
+
|
|
2095
|
+
case BROTLI_STATE_LARGE_WINDOW_BITS:
|
|
2096
|
+
if (!BrotliSafeReadBits(br, 6, &s->window_bits)) {
|
|
2097
|
+
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
|
2098
|
+
break;
|
|
2099
|
+
}
|
|
2100
|
+
if (s->window_bits < BROTLI_LARGE_MIN_WBITS ||
|
|
2101
|
+
s->window_bits > BROTLI_LARGE_MAX_WBITS) {
|
|
2013
2102
|
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
|
|
2014
2103
|
break;
|
|
2015
2104
|
}
|
|
2105
|
+
s->state = BROTLI_STATE_INITIALIZE;
|
|
2106
|
+
/* Fall through. */
|
|
2107
|
+
|
|
2108
|
+
case BROTLI_STATE_INITIALIZE:
|
|
2109
|
+
BROTLI_LOG_UINT(s->window_bits);
|
|
2016
2110
|
/* Maximum distance, see section 9.1. of the spec. */
|
|
2017
2111
|
s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP;
|
|
2018
2112
|
|
|
2019
2113
|
/* Allocate memory for both block_type_trees and block_len_trees. */
|
|
2020
|
-
s->block_type_trees = (HuffmanCode*)
|
|
2114
|
+
s->block_type_trees = (HuffmanCode*)BROTLI_DECODER_ALLOC(s,
|
|
2021
2115
|
sizeof(HuffmanCode) * 3 *
|
|
2022
2116
|
(BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));
|
|
2023
2117
|
if (s->block_type_trees == 0) {
|
|
@@ -2028,14 +2122,16 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2028
2122
|
s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258;
|
|
2029
2123
|
|
|
2030
2124
|
s->state = BROTLI_STATE_METABLOCK_BEGIN;
|
|
2031
|
-
|
|
2125
|
+
/* Fall through. */
|
|
2126
|
+
|
|
2032
2127
|
case BROTLI_STATE_METABLOCK_BEGIN:
|
|
2033
2128
|
BrotliDecoderStateMetablockBegin(s);
|
|
2034
2129
|
BROTLI_LOG_UINT(s->pos);
|
|
2035
2130
|
s->state = BROTLI_STATE_METABLOCK_HEADER;
|
|
2036
|
-
|
|
2131
|
+
/* Fall through. */
|
|
2132
|
+
|
|
2037
2133
|
case BROTLI_STATE_METABLOCK_HEADER:
|
|
2038
|
-
result = DecodeMetaBlockLength(s, br);
|
|
2134
|
+
result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */
|
|
2039
2135
|
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2040
2136
|
break;
|
|
2041
2137
|
}
|
|
@@ -2065,6 +2161,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2065
2161
|
s->loop_counter = 0;
|
|
2066
2162
|
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
|
|
2067
2163
|
break;
|
|
2164
|
+
|
|
2068
2165
|
case BROTLI_STATE_UNCOMPRESSED: {
|
|
2069
2166
|
result = CopyUncompressedBlockToOutput(
|
|
2070
2167
|
available_out, next_out, total_out, s);
|
|
@@ -2074,6 +2171,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2074
2171
|
s->state = BROTLI_STATE_METABLOCK_DONE;
|
|
2075
2172
|
break;
|
|
2076
2173
|
}
|
|
2174
|
+
|
|
2077
2175
|
case BROTLI_STATE_METADATA:
|
|
2078
2176
|
for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
|
|
2079
2177
|
uint32_t bits;
|
|
@@ -2087,6 +2185,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2087
2185
|
s->state = BROTLI_STATE_METABLOCK_DONE;
|
|
2088
2186
|
}
|
|
2089
2187
|
break;
|
|
2188
|
+
|
|
2090
2189
|
case BROTLI_STATE_HUFFMAN_CODE_0:
|
|
2091
2190
|
if (s->loop_counter >= 3) {
|
|
2092
2191
|
s->state = BROTLI_STATE_METABLOCK_HEADER_2;
|
|
@@ -2104,23 +2203,28 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2104
2203
|
break;
|
|
2105
2204
|
}
|
|
2106
2205
|
s->state = BROTLI_STATE_HUFFMAN_CODE_1;
|
|
2107
|
-
|
|
2206
|
+
/* Fall through. */
|
|
2207
|
+
|
|
2108
2208
|
case BROTLI_STATE_HUFFMAN_CODE_1: {
|
|
2209
|
+
uint32_t alphabet_size = s->num_block_types[s->loop_counter] + 2;
|
|
2109
2210
|
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;
|
|
2110
|
-
result = ReadHuffmanCode(
|
|
2211
|
+
result = ReadHuffmanCode(alphabet_size, alphabet_size,
|
|
2111
2212
|
&s->block_type_trees[tree_offset], NULL, s);
|
|
2112
2213
|
if (result != BROTLI_DECODER_SUCCESS) break;
|
|
2113
2214
|
s->state = BROTLI_STATE_HUFFMAN_CODE_2;
|
|
2114
|
-
/* No break, continue to next state */
|
|
2115
2215
|
}
|
|
2216
|
+
/* Fall through. */
|
|
2217
|
+
|
|
2116
2218
|
case BROTLI_STATE_HUFFMAN_CODE_2: {
|
|
2219
|
+
uint32_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS;
|
|
2117
2220
|
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
|
|
2118
|
-
result = ReadHuffmanCode(
|
|
2221
|
+
result = ReadHuffmanCode(alphabet_size, alphabet_size,
|
|
2119
2222
|
&s->block_len_trees[tree_offset], NULL, s);
|
|
2120
2223
|
if (result != BROTLI_DECODER_SUCCESS) break;
|
|
2121
2224
|
s->state = BROTLI_STATE_HUFFMAN_CODE_3;
|
|
2122
|
-
/* No break, continue to next state */
|
|
2123
2225
|
}
|
|
2226
|
+
/* Fall through. */
|
|
2227
|
+
|
|
2124
2228
|
case BROTLI_STATE_HUFFMAN_CODE_3: {
|
|
2125
2229
|
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
|
|
2126
2230
|
if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],
|
|
@@ -2133,6 +2237,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2133
2237
|
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
|
|
2134
2238
|
break;
|
|
2135
2239
|
}
|
|
2240
|
+
|
|
2136
2241
|
case BROTLI_STATE_METABLOCK_HEADER_2: {
|
|
2137
2242
|
uint32_t bits;
|
|
2138
2243
|
if (!BrotliSafeReadBits(br, 6, &bits)) {
|
|
@@ -2147,22 +2252,24 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2147
2252
|
BROTLI_LOG_UINT(s->distance_postfix_bits);
|
|
2148
2253
|
s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits);
|
|
2149
2254
|
s->context_modes =
|
|
2150
|
-
(uint8_t*)
|
|
2255
|
+
(uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);
|
|
2151
2256
|
if (s->context_modes == 0) {
|
|
2152
2257
|
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);
|
|
2153
2258
|
break;
|
|
2154
2259
|
}
|
|
2155
2260
|
s->loop_counter = 0;
|
|
2156
2261
|
s->state = BROTLI_STATE_CONTEXT_MODES;
|
|
2157
|
-
/* No break, continue to next state */
|
|
2158
2262
|
}
|
|
2263
|
+
/* Fall through. */
|
|
2264
|
+
|
|
2159
2265
|
case BROTLI_STATE_CONTEXT_MODES:
|
|
2160
2266
|
result = ReadContextModes(s);
|
|
2161
2267
|
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2162
2268
|
break;
|
|
2163
2269
|
}
|
|
2164
2270
|
s->state = BROTLI_STATE_CONTEXT_MAP_1;
|
|
2165
|
-
|
|
2271
|
+
/* Fall through. */
|
|
2272
|
+
|
|
2166
2273
|
case BROTLI_STATE_CONTEXT_MAP_1:
|
|
2167
2274
|
result = DecodeContextMap(
|
|
2168
2275
|
s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS,
|
|
@@ -2172,54 +2279,54 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2172
2279
|
}
|
|
2173
2280
|
DetectTrivialLiteralBlockTypes(s);
|
|
2174
2281
|
s->state = BROTLI_STATE_CONTEXT_MAP_2;
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2282
|
+
/* Fall through. */
|
|
2283
|
+
|
|
2284
|
+
case BROTLI_STATE_CONTEXT_MAP_2: {
|
|
2285
|
+
uint32_t num_direct_codes =
|
|
2286
|
+
s->num_direct_distance_codes - BROTLI_NUM_DISTANCE_SHORT_CODES;
|
|
2287
|
+
uint32_t num_distance_codes = BROTLI_DISTANCE_ALPHABET_SIZE(
|
|
2288
|
+
s->distance_postfix_bits, num_direct_codes,
|
|
2289
|
+
(s->large_window ? BROTLI_LARGE_MAX_DISTANCE_BITS :
|
|
2290
|
+
BROTLI_MAX_DISTANCE_BITS));
|
|
2291
|
+
uint32_t max_distance_symbol = (s->large_window ?
|
|
2292
|
+
BrotliMaxDistanceSymbol(
|
|
2293
|
+
num_direct_codes, s->distance_postfix_bits) :
|
|
2294
|
+
num_distance_codes);
|
|
2295
|
+
BROTLI_BOOL allocation_success = BROTLI_TRUE;
|
|
2296
|
+
result = DecodeContextMap(
|
|
2297
|
+
s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
|
|
2298
|
+
&s->num_dist_htrees, &s->dist_context_map, s);
|
|
2299
|
+
if (result != BROTLI_DECODER_SUCCESS) {
|
|
2300
|
+
break;
|
|
2301
|
+
}
|
|
2302
|
+
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
|
|
2303
|
+
s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS,
|
|
2304
|
+
BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees);
|
|
2305
|
+
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
|
|
2306
|
+
s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,
|
|
2307
|
+
BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);
|
|
2308
|
+
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
|
|
2309
|
+
s, &s->distance_hgroup, num_distance_codes,
|
|
2310
|
+
max_distance_symbol, s->num_dist_htrees);
|
|
2311
|
+
if (!allocation_success) {
|
|
2312
|
+
return SaveErrorCode(s,
|
|
2313
|
+
BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
|
|
2200
2314
|
}
|
|
2201
2315
|
s->loop_counter = 0;
|
|
2202
2316
|
s->state = BROTLI_STATE_TREE_GROUP;
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
break;
|
|
2217
|
-
default:
|
|
2218
|
-
return SaveErrorCode(s, BROTLI_FAILURE(
|
|
2219
|
-
BROTLI_DECODER_ERROR_UNREACHABLE));
|
|
2220
|
-
}
|
|
2221
|
-
result = HuffmanTreeGroupDecode(hgroup, s);
|
|
2222
|
-
}
|
|
2317
|
+
}
|
|
2318
|
+
/* Fall through. */
|
|
2319
|
+
|
|
2320
|
+
case BROTLI_STATE_TREE_GROUP: {
|
|
2321
|
+
HuffmanTreeGroup* hgroup = NULL;
|
|
2322
|
+
switch (s->loop_counter) {
|
|
2323
|
+
case 0: hgroup = &s->literal_hgroup; break;
|
|
2324
|
+
case 1: hgroup = &s->insert_copy_hgroup; break;
|
|
2325
|
+
case 2: hgroup = &s->distance_hgroup; break;
|
|
2326
|
+
default: return SaveErrorCode(s, BROTLI_FAILURE(
|
|
2327
|
+
BROTLI_DECODER_ERROR_UNREACHABLE));
|
|
2328
|
+
}
|
|
2329
|
+
result = HuffmanTreeGroupDecode(hgroup, s);
|
|
2223
2330
|
if (result != BROTLI_DECODER_SUCCESS) break;
|
|
2224
2331
|
s->loop_counter++;
|
|
2225
2332
|
if (s->loop_counter >= 3) {
|
|
@@ -2233,17 +2340,25 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2233
2340
|
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
|
2234
2341
|
}
|
|
2235
2342
|
break;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2236
2345
|
case BROTLI_STATE_COMMAND_BEGIN:
|
|
2346
|
+
/* Fall through. */
|
|
2237
2347
|
case BROTLI_STATE_COMMAND_INNER:
|
|
2348
|
+
/* Fall through. */
|
|
2238
2349
|
case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:
|
|
2350
|
+
/* Fall through. */
|
|
2239
2351
|
case BROTLI_STATE_COMMAND_POST_WRAP_COPY:
|
|
2240
2352
|
result = ProcessCommands(s);
|
|
2241
2353
|
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
|
|
2242
2354
|
result = SafeProcessCommands(s);
|
|
2243
2355
|
}
|
|
2244
2356
|
break;
|
|
2357
|
+
|
|
2245
2358
|
case BROTLI_STATE_COMMAND_INNER_WRITE:
|
|
2359
|
+
/* Fall through. */
|
|
2246
2360
|
case BROTLI_STATE_COMMAND_POST_WRITE_1:
|
|
2361
|
+
/* Fall through. */
|
|
2247
2362
|
case BROTLI_STATE_COMMAND_POST_WRITE_2:
|
|
2248
2363
|
result = WriteRingBuffer(
|
|
2249
2364
|
s, available_out, next_out, total_out, BROTLI_FALSE);
|
|
@@ -2256,7 +2371,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2256
2371
|
}
|
|
2257
2372
|
if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {
|
|
2258
2373
|
if (s->meta_block_remaining_len == 0) {
|
|
2259
|
-
/* Next metablock, if any */
|
|
2374
|
+
/* Next metablock, if any. */
|
|
2260
2375
|
s->state = BROTLI_STATE_METABLOCK_DONE;
|
|
2261
2376
|
} else {
|
|
2262
2377
|
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
|
@@ -2276,6 +2391,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2276
2391
|
s->state = BROTLI_STATE_COMMAND_INNER;
|
|
2277
2392
|
}
|
|
2278
2393
|
break;
|
|
2394
|
+
|
|
2279
2395
|
case BROTLI_STATE_METABLOCK_DONE:
|
|
2280
2396
|
if (s->meta_block_remaining_len < 0) {
|
|
2281
2397
|
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);
|
|
@@ -2296,7 +2412,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|
|
2296
2412
|
*next_in = br->next_in;
|
|
2297
2413
|
}
|
|
2298
2414
|
s->state = BROTLI_STATE_DONE;
|
|
2299
|
-
|
|
2415
|
+
/* Fall through. */
|
|
2416
|
+
|
|
2300
2417
|
case BROTLI_STATE_DONE:
|
|
2301
2418
|
if (s->ringbuffer != 0) {
|
|
2302
2419
|
result = WriteRingBuffer(
|