brotli 0.2.0 → 0.4.0

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.
Files changed (111) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +34 -0
  3. data/.github/workflows/publish.yml +34 -0
  4. data/Gemfile +6 -2
  5. data/Rakefile +18 -6
  6. data/bin/before_install.sh +9 -0
  7. data/brotli.gemspec +7 -13
  8. data/ext/brotli/brotli.c +209 -11
  9. data/ext/brotli/buffer.c +1 -7
  10. data/ext/brotli/buffer.h +1 -1
  11. data/ext/brotli/extconf.rb +45 -26
  12. data/lib/brotli/version.rb +1 -1
  13. data/smoke.sh +1 -1
  14. data/test/brotli_test.rb +104 -0
  15. data/test/brotli_writer_test.rb +36 -0
  16. data/test/test_helper.rb +8 -0
  17. data/vendor/brotli/c/common/constants.c +15 -0
  18. data/vendor/brotli/c/common/constants.h +149 -6
  19. data/vendor/brotli/c/{dec/context.h → common/context.c} +91 -186
  20. data/vendor/brotli/c/common/context.h +113 -0
  21. data/vendor/brotli/c/common/dictionary.bin +0 -0
  22. data/vendor/brotli/c/common/dictionary.bin.br +0 -0
  23. data/vendor/brotli/c/common/dictionary.c +11 -2
  24. data/vendor/brotli/c/common/dictionary.h +4 -4
  25. data/vendor/brotli/c/common/platform.c +22 -0
  26. data/vendor/brotli/c/common/platform.h +594 -0
  27. data/vendor/brotli/c/common/transform.c +291 -0
  28. data/vendor/brotli/c/common/transform.h +85 -0
  29. data/vendor/brotli/c/common/version.h +8 -1
  30. data/vendor/brotli/c/dec/bit_reader.c +29 -1
  31. data/vendor/brotli/c/dec/bit_reader.h +91 -100
  32. data/vendor/brotli/c/dec/decode.c +665 -437
  33. data/vendor/brotli/c/dec/huffman.c +65 -84
  34. data/vendor/brotli/c/dec/huffman.h +67 -14
  35. data/vendor/brotli/c/dec/prefix.h +1 -20
  36. data/vendor/brotli/c/dec/state.c +32 -45
  37. data/vendor/brotli/c/dec/state.h +173 -55
  38. data/vendor/brotli/c/enc/backward_references.c +27 -16
  39. data/vendor/brotli/c/enc/backward_references.h +7 -7
  40. data/vendor/brotli/c/enc/backward_references_hq.c +155 -116
  41. data/vendor/brotli/c/enc/backward_references_hq.h +22 -23
  42. data/vendor/brotli/c/enc/backward_references_inc.h +32 -22
  43. data/vendor/brotli/c/enc/bit_cost.c +1 -1
  44. data/vendor/brotli/c/enc/bit_cost.h +5 -5
  45. data/vendor/brotli/c/enc/block_encoder_inc.h +7 -6
  46. data/vendor/brotli/c/enc/block_splitter.c +5 -6
  47. data/vendor/brotli/c/enc/block_splitter.h +1 -1
  48. data/vendor/brotli/c/enc/block_splitter_inc.h +26 -17
  49. data/vendor/brotli/c/enc/brotli_bit_stream.c +107 -123
  50. data/vendor/brotli/c/enc/brotli_bit_stream.h +19 -38
  51. data/vendor/brotli/c/enc/cluster.c +1 -1
  52. data/vendor/brotli/c/enc/cluster.h +1 -1
  53. data/vendor/brotli/c/enc/cluster_inc.h +6 -3
  54. data/vendor/brotli/c/enc/command.c +28 -0
  55. data/vendor/brotli/c/enc/command.h +52 -42
  56. data/vendor/brotli/c/enc/compress_fragment.c +21 -22
  57. data/vendor/brotli/c/enc/compress_fragment.h +1 -1
  58. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +102 -69
  59. data/vendor/brotli/c/enc/compress_fragment_two_pass.h +1 -1
  60. data/vendor/brotli/c/enc/dictionary_hash.c +1827 -1101
  61. data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
  62. data/vendor/brotli/c/enc/encode.c +358 -195
  63. data/vendor/brotli/c/enc/encoder_dict.c +33 -0
  64. data/vendor/brotli/c/enc/encoder_dict.h +43 -0
  65. data/vendor/brotli/c/enc/entropy_encode.c +16 -14
  66. data/vendor/brotli/c/enc/entropy_encode.h +7 -7
  67. data/vendor/brotli/c/enc/entropy_encode_static.h +3 -3
  68. data/vendor/brotli/c/enc/fast_log.c +105 -0
  69. data/vendor/brotli/c/enc/fast_log.h +20 -99
  70. data/vendor/brotli/c/enc/find_match_length.h +5 -6
  71. data/vendor/brotli/c/enc/hash.h +145 -103
  72. data/vendor/brotli/c/enc/hash_composite_inc.h +125 -0
  73. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +93 -53
  74. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +54 -53
  75. data/vendor/brotli/c/enc/hash_longest_match_inc.h +58 -54
  76. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +95 -63
  77. data/vendor/brotli/c/enc/hash_rolling_inc.h +212 -0
  78. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +46 -43
  79. data/vendor/brotli/c/enc/histogram.c +9 -6
  80. data/vendor/brotli/c/enc/histogram.h +6 -3
  81. data/vendor/brotli/c/enc/histogram_inc.h +1 -1
  82. data/vendor/brotli/c/enc/literal_cost.c +5 -5
  83. data/vendor/brotli/c/enc/literal_cost.h +2 -2
  84. data/vendor/brotli/c/enc/memory.c +5 -16
  85. data/vendor/brotli/c/enc/memory.h +52 -1
  86. data/vendor/brotli/c/enc/metablock.c +171 -36
  87. data/vendor/brotli/c/enc/metablock.h +13 -8
  88. data/vendor/brotli/c/enc/metablock_inc.h +2 -2
  89. data/vendor/brotli/c/enc/params.h +46 -0
  90. data/vendor/brotli/c/enc/prefix.h +3 -4
  91. data/vendor/brotli/c/enc/quality.h +29 -24
  92. data/vendor/brotli/c/enc/ringbuffer.h +19 -12
  93. data/vendor/brotli/c/enc/static_dict.c +49 -45
  94. data/vendor/brotli/c/enc/static_dict.h +4 -3
  95. data/vendor/brotli/c/enc/static_dict_lut.h +1 -1
  96. data/vendor/brotli/c/enc/utf8_util.c +21 -21
  97. data/vendor/brotli/c/enc/utf8_util.h +1 -1
  98. data/vendor/brotli/c/enc/write_bits.h +35 -38
  99. data/vendor/brotli/c/include/brotli/decode.h +13 -8
  100. data/vendor/brotli/c/include/brotli/encode.h +54 -8
  101. data/vendor/brotli/c/include/brotli/port.h +225 -83
  102. data/vendor/brotli/c/include/brotli/types.h +0 -7
  103. metadata +28 -87
  104. data/.travis.yml +0 -30
  105. data/spec/brotli_spec.rb +0 -88
  106. data/spec/inflate_spec.rb +0 -75
  107. data/spec/spec_helper.rb +0 -4
  108. data/vendor/brotli/c/dec/port.h +0 -168
  109. data/vendor/brotli/c/dec/transform.h +0 -300
  110. data/vendor/brotli/c/enc/context.h +0 -184
  111. data/vendor/brotli/c/enc/port.h +0 -184
@@ -9,16 +9,15 @@
9
9
  #ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_
10
10
  #define BROTLI_ENC_FIND_MATCH_LENGTH_H_
11
11
 
12
+ #include "../common/platform.h"
12
13
  #include <brotli/types.h>
13
- #include "./port.h"
14
14
 
15
15
  #if defined(__cplusplus) || defined(c_plusplus)
16
16
  extern "C" {
17
17
  #endif
18
18
 
19
19
  /* Separate implementation for little-endian 64-bit targets, for speed. */
20
- #if defined(__GNUC__) && defined(_LP64) && defined(BROTLI_LITTLE_ENDIAN)
21
-
20
+ #if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN
22
21
  static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
23
22
  const uint8_t* s2,
24
23
  size_t limit) {
@@ -32,7 +31,7 @@ static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
32
31
  } else {
33
32
  uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^
34
33
  BROTLI_UNALIGNED_LOAD64LE(s1 + matched);
35
- size_t matching_bits = (size_t)__builtin_ctzll(x);
34
+ size_t matching_bits = (size_t)BROTLI_TZCNT64(x);
36
35
  matched += matching_bits >> 3;
37
36
  return matched;
38
37
  }
@@ -60,8 +59,8 @@ static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
60
59
  the first non-matching bit and use that to calculate the total
61
60
  length of the match. */
62
61
  while (s2_ptr <= s2_limit - 4 &&
63
- BROTLI_UNALIGNED_LOAD32(s2_ptr) ==
64
- BROTLI_UNALIGNED_LOAD32(s1 + matched)) {
62
+ BrotliUnalignedRead32(s2_ptr) ==
63
+ BrotliUnalignedRead32(s1 + matched)) {
65
64
  s2_ptr += 4;
66
65
  matched += 4;
67
66
  }
@@ -14,11 +14,12 @@
14
14
 
15
15
  #include "../common/constants.h"
16
16
  #include "../common/dictionary.h"
17
+ #include "../common/platform.h"
17
18
  #include <brotli/types.h>
19
+ #include "./encoder_dict.h"
18
20
  #include "./fast_log.h"
19
21
  #include "./find_match_length.h"
20
22
  #include "./memory.h"
21
- #include "./port.h"
22
23
  #include "./quality.h"
23
24
  #include "./static_dict.h"
24
25
 
@@ -26,32 +27,19 @@
26
27
  extern "C" {
27
28
  #endif
28
29
 
29
- /* Pointer to hasher data.
30
- *
31
- * Excluding initialization and destruction, hasher can be passed as
32
- * HasherHandle by value.
33
- *
34
- * Typically hasher data consists of 3 sections:
35
- * * HasherCommon structure
36
- * * private structured hasher data, depending on hasher type
37
- * * private dynamic hasher data, depending on hasher type and parameters
38
- */
39
- typedef uint8_t* HasherHandle;
40
-
41
30
  typedef struct {
31
+ /* Dynamically allocated area; first member for quickest access. */
32
+ void* extra;
33
+
34
+ size_t dict_num_lookups;
35
+ size_t dict_num_matches;
36
+
42
37
  BrotliHasherParams params;
43
38
 
44
39
  /* False if hasher needs to be "prepared" before use. */
45
40
  BROTLI_BOOL is_prepared_;
46
-
47
- size_t dict_num_lookups;
48
- size_t dict_num_matches;
49
41
  } HasherCommon;
50
42
 
51
- static BROTLI_INLINE HasherCommon* GetHasherCommon(HasherHandle handle) {
52
- return (HasherCommon*)handle;
53
- }
54
-
55
43
  #define score_t size_t
56
44
 
57
45
  static const uint32_t kCutoffTransformsCount = 10;
@@ -73,13 +61,13 @@ typedef struct HasherSearchResult {
73
61
  * There is no effort to ensure that it is a prime, the oddity is enough
74
62
  for this use.
75
63
  * The number has been tuned heuristically against compression benchmarks. */
76
- static const uint32_t kHashMul32 = 0x1e35a7bd;
77
- static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1e35a7bd, 0x1e35a7bd);
64
+ static const uint32_t kHashMul32 = 0x1E35A7BD;
65
+ static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1E35A7BD, 0x1E35A7BD);
78
66
  static const uint64_t kHashMul64Long =
79
- BROTLI_MAKE_UINT64_T(0x1fe35a7bU, 0xd3579bd3U);
67
+ BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
80
68
 
81
69
  static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
82
- uint32_t h = BROTLI_UNALIGNED_LOAD32(data) * kHashMul32;
70
+ uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
83
71
  /* The higher bits contain more mixture from the multiplication,
84
72
  so we take our results from there. */
85
73
  return h >> (32 - 14);
@@ -146,34 +134,31 @@ static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
146
134
  }
147
135
 
148
136
  static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
149
- const BrotliDictionary* dictionary, size_t item, const uint8_t* data,
150
- size_t max_length, size_t max_backward, HasherSearchResult* out) {
151
- size_t len;
152
- size_t dist;
137
+ const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,
138
+ const uint8_t* data, size_t max_length, size_t max_backward,
139
+ size_t max_distance, HasherSearchResult* out) {
153
140
  size_t offset;
154
141
  size_t matchlen;
155
142
  size_t backward;
156
143
  score_t score;
157
- len = item & 0x1F;
158
- dist = item >> 5;
159
- offset = dictionary->offsets_by_length[len] + len * dist;
144
+ offset = dictionary->words->offsets_by_length[len] + len * word_idx;
160
145
  if (len > max_length) {
161
146
  return BROTLI_FALSE;
162
147
  }
163
148
 
164
149
  matchlen =
165
- FindMatchLengthWithLimit(data, &dictionary->data[offset], len);
166
- if (matchlen + kCutoffTransformsCount <= len || matchlen == 0) {
150
+ FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);
151
+ if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {
167
152
  return BROTLI_FALSE;
168
153
  }
169
154
  {
170
155
  size_t cut = len - matchlen;
171
- size_t transform_id =
172
- (cut << 2) + (size_t)((kCutoffTransforms >> (cut * 6)) & 0x3F);
173
- backward = max_backward + dist + 1 +
174
- (transform_id << dictionary->size_bits_by_length[len]);
156
+ size_t transform_id = (cut << 2) +
157
+ (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);
158
+ backward = max_backward + 1 + word_idx +
159
+ (transform_id << dictionary->words->size_bits_by_length[len]);
175
160
  }
176
- if (backward >= BROTLI_MAX_DISTANCE) {
161
+ if (backward > max_distance) {
177
162
  return BROTLI_FALSE;
178
163
  }
179
164
  score = BackwardReferenceScore(matchlen, backward);
@@ -188,24 +173,25 @@ static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
188
173
  }
189
174
 
190
175
  static BROTLI_INLINE void SearchInStaticDictionary(
191
- const BrotliDictionary* dictionary, const uint16_t* dictionary_hash,
192
- HasherHandle handle, const uint8_t* data, size_t max_length,
193
- size_t max_backward, HasherSearchResult* out, BROTLI_BOOL shallow) {
176
+ const BrotliEncoderDictionary* dictionary,
177
+ HasherCommon* common, const uint8_t* data, size_t max_length,
178
+ size_t max_backward, size_t max_distance,
179
+ HasherSearchResult* out, BROTLI_BOOL shallow) {
194
180
  size_t key;
195
181
  size_t i;
196
- HasherCommon* self = GetHasherCommon(handle);
197
- if (self->dict_num_matches < (self->dict_num_lookups >> 7)) {
182
+ if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {
198
183
  return;
199
184
  }
200
185
  key = Hash14(data) << 1;
201
186
  for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
202
- size_t item = dictionary_hash[key];
203
- self->dict_num_lookups++;
204
- if (item != 0) {
187
+ common->dict_num_lookups++;
188
+ if (dictionary->hash_table_lengths[key] != 0) {
205
189
  BROTLI_BOOL item_matches = TestStaticDictionaryItem(
206
- dictionary, item, data, max_length, max_backward, out);
190
+ dictionary, dictionary->hash_table_lengths[key],
191
+ dictionary->hash_table_words[key], data,
192
+ max_length, max_backward, max_distance, out);
207
193
  if (item_matches) {
208
- self->dict_num_matches++;
194
+ common->dict_num_matches++;
209
195
  }
210
196
  }
211
197
  }
@@ -254,37 +240,37 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
254
240
  /* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
255
241
  #define MAX_NUM_MATCHES_H10 128
256
242
 
257
- /* For BUCKET_SWEEP == 1, enabling the dictionary lookup makes compression
243
+ /* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression
258
244
  a little faster (0.5% - 1%) and it compresses 0.15% better on small text
259
245
  and HTML inputs. */
260
246
 
261
247
  #define HASHER() H2
262
248
  #define BUCKET_BITS 16
263
- #define BUCKET_SWEEP 1
249
+ #define BUCKET_SWEEP_BITS 0
264
250
  #define HASH_LEN 5
265
251
  #define USE_DICTIONARY 1
266
252
  #include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
267
- #undef BUCKET_SWEEP
253
+ #undef BUCKET_SWEEP_BITS
268
254
  #undef USE_DICTIONARY
269
255
  #undef HASHER
270
256
 
271
257
  #define HASHER() H3
272
- #define BUCKET_SWEEP 2
258
+ #define BUCKET_SWEEP_BITS 1
273
259
  #define USE_DICTIONARY 0
274
260
  #include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
275
261
  #undef USE_DICTIONARY
276
- #undef BUCKET_SWEEP
262
+ #undef BUCKET_SWEEP_BITS
277
263
  #undef BUCKET_BITS
278
264
  #undef HASHER
279
265
 
280
266
  #define HASHER() H4
281
267
  #define BUCKET_BITS 17
282
- #define BUCKET_SWEEP 4
268
+ #define BUCKET_SWEEP_BITS 2
283
269
  #define USE_DICTIONARY 1
284
270
  #include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
285
271
  #undef USE_DICTIONARY
286
272
  #undef HASH_LEN
287
- #undef BUCKET_SWEEP
273
+ #undef BUCKET_SWEEP_BITS
288
274
  #undef BUCKET_BITS
289
275
  #undef HASHER
290
276
 
@@ -328,110 +314,166 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
328
314
 
329
315
  #define HASHER() H54
330
316
  #define BUCKET_BITS 20
331
- #define BUCKET_SWEEP 4
317
+ #define BUCKET_SWEEP_BITS 2
332
318
  #define HASH_LEN 7
333
319
  #define USE_DICTIONARY 0
334
320
  #include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
335
321
  #undef USE_DICTIONARY
336
322
  #undef HASH_LEN
337
- #undef BUCKET_SWEEP
323
+ #undef BUCKET_SWEEP_BITS
338
324
  #undef BUCKET_BITS
339
325
  #undef HASHER
340
326
 
327
+ /* fast large window hashers */
328
+
329
+ #define HASHER() HROLLING_FAST
330
+ #define CHUNKLEN 32
331
+ #define JUMP 4
332
+ #define NUMBUCKETS 16777216
333
+ #define MASK ((NUMBUCKETS * 64) - 1)
334
+ #include "./hash_rolling_inc.h" /* NOLINT(build/include) */
335
+ #undef JUMP
336
+ #undef HASHER
337
+
338
+
339
+ #define HASHER() HROLLING
340
+ #define JUMP 1
341
+ #include "./hash_rolling_inc.h" /* NOLINT(build/include) */
342
+ #undef MASK
343
+ #undef NUMBUCKETS
344
+ #undef JUMP
345
+ #undef CHUNKLEN
346
+ #undef HASHER
347
+
348
+ #define HASHER() H35
349
+ #define HASHER_A H3
350
+ #define HASHER_B HROLLING_FAST
351
+ #include "./hash_composite_inc.h" /* NOLINT(build/include) */
352
+ #undef HASHER_A
353
+ #undef HASHER_B
354
+ #undef HASHER
355
+
356
+ #define HASHER() H55
357
+ #define HASHER_A H54
358
+ #define HASHER_B HROLLING_FAST
359
+ #include "./hash_composite_inc.h" /* NOLINT(build/include) */
360
+ #undef HASHER_A
361
+ #undef HASHER_B
362
+ #undef HASHER
363
+
364
+ #define HASHER() H65
365
+ #define HASHER_A H6
366
+ #define HASHER_B HROLLING
367
+ #include "./hash_composite_inc.h" /* NOLINT(build/include) */
368
+ #undef HASHER_A
369
+ #undef HASHER_B
370
+ #undef HASHER
371
+
341
372
  #undef FN
342
373
  #undef CAT
343
374
  #undef EXPAND_CAT
344
375
 
345
- #define FOR_GENERIC_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
376
+ #define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
377
+ #define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
378
+ #define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
346
379
  #define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
347
380
 
348
- static BROTLI_INLINE void DestroyHasher(
349
- MemoryManager* m, HasherHandle* handle) {
350
- if (*handle == NULL) return;
351
- BROTLI_FREE(m, *handle);
381
+ typedef struct {
382
+ HasherCommon common;
383
+
384
+ union {
385
+ #define MEMBER_(N) \
386
+ H ## N _H ## N;
387
+ FOR_ALL_HASHERS(MEMBER_)
388
+ #undef MEMBER_
389
+ } privat;
390
+ } Hasher;
391
+
392
+ /* MUST be invoked before any other method. */
393
+ static BROTLI_INLINE void HasherInit(Hasher* hasher) {
394
+ hasher->common.extra = NULL;
395
+ }
396
+
397
+ static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
398
+ if (hasher->common.extra == NULL) return;
399
+ BROTLI_FREE(m, hasher->common.extra);
352
400
  }
353
401
 
354
- static BROTLI_INLINE void HasherReset(HasherHandle handle) {
355
- if (handle == NULL) return;
356
- GetHasherCommon(handle)->is_prepared_ = BROTLI_FALSE;
402
+ static BROTLI_INLINE void HasherReset(Hasher* hasher) {
403
+ hasher->common.is_prepared_ = BROTLI_FALSE;
357
404
  }
358
405
 
359
406
  static BROTLI_INLINE size_t HasherSize(const BrotliEncoderParams* params,
360
407
  BROTLI_BOOL one_shot, const size_t input_size) {
361
- size_t result = sizeof(HasherCommon);
362
408
  switch (params->hasher.type) {
363
- #define SIZE_(N) \
364
- case N: \
365
- result += HashMemAllocInBytesH ## N(params, one_shot, input_size); \
366
- break;
409
+ #define SIZE_(N) \
410
+ case N: \
411
+ return HashMemAllocInBytesH ## N(params, one_shot, input_size);
367
412
  FOR_ALL_HASHERS(SIZE_)
368
413
  #undef SIZE_
369
414
  default:
370
415
  break;
371
416
  }
372
- return result;
417
+ return 0; /* Default case. */
373
418
  }
374
419
 
375
- static BROTLI_INLINE void HasherSetup(MemoryManager* m, HasherHandle* handle,
420
+ static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,
376
421
  BrotliEncoderParams* params, const uint8_t* data, size_t position,
377
422
  size_t input_size, BROTLI_BOOL is_last) {
378
- HasherHandle self = NULL;
379
- HasherCommon* common = NULL;
380
423
  BROTLI_BOOL one_shot = (position == 0 && is_last);
381
- if (*handle == NULL) {
424
+ if (hasher->common.extra == NULL) {
382
425
  size_t alloc_size;
383
426
  ChooseHasher(params, &params->hasher);
384
427
  alloc_size = HasherSize(params, one_shot, input_size);
385
- self = BROTLI_ALLOC(m, uint8_t, alloc_size);
386
- if (BROTLI_IS_OOM(m)) return;
387
- *handle = self;
388
- common = GetHasherCommon(self);
389
- common->params = params->hasher;
390
- switch (common->params.type) {
391
- #define INITIALIZE_(N) \
392
- case N: \
393
- InitializeH ## N(*handle, params); \
428
+ hasher->common.extra = BROTLI_ALLOC(m, uint8_t, alloc_size);
429
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra)) return;
430
+ hasher->common.params = params->hasher;
431
+ switch (hasher->common.params.type) {
432
+ #define INITIALIZE_(N) \
433
+ case N: \
434
+ InitializeH ## N(&hasher->common, \
435
+ &hasher->privat._H ## N, params); \
394
436
  break;
395
437
  FOR_ALL_HASHERS(INITIALIZE_);
396
438
  #undef INITIALIZE_
397
439
  default:
398
440
  break;
399
441
  }
400
- HasherReset(*handle);
442
+ HasherReset(hasher);
401
443
  }
402
444
 
403
- self = *handle;
404
- common = GetHasherCommon(self);
405
- if (!common->is_prepared_) {
406
- switch (common->params.type) {
407
- #define PREPARE_(N) \
408
- case N: \
409
- PrepareH ## N(self, one_shot, input_size, data); \
445
+ if (!hasher->common.is_prepared_) {
446
+ switch (hasher->common.params.type) {
447
+ #define PREPARE_(N) \
448
+ case N: \
449
+ PrepareH ## N( \
450
+ &hasher->privat._H ## N, \
451
+ one_shot, input_size, data); \
410
452
  break;
411
453
  FOR_ALL_HASHERS(PREPARE_)
412
454
  #undef PREPARE_
413
455
  default: break;
414
456
  }
415
457
  if (position == 0) {
416
- common->dict_num_lookups = 0;
417
- common->dict_num_matches = 0;
458
+ hasher->common.dict_num_lookups = 0;
459
+ hasher->common.dict_num_matches = 0;
418
460
  }
419
- common->is_prepared_ = BROTLI_TRUE;
461
+ hasher->common.is_prepared_ = BROTLI_TRUE;
420
462
  }
421
463
  }
422
464
 
423
465
  static BROTLI_INLINE void InitOrStitchToPreviousBlock(
424
- MemoryManager* m, HasherHandle* handle, const uint8_t* data, size_t mask,
466
+ MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,
425
467
  BrotliEncoderParams* params, size_t position, size_t input_size,
426
468
  BROTLI_BOOL is_last) {
427
- HasherHandle self;
428
- HasherSetup(m, handle, params, data, position, input_size, is_last);
469
+ HasherSetup(m, hasher, params, data, position, input_size, is_last);
429
470
  if (BROTLI_IS_OOM(m)) return;
430
- self = *handle;
431
- switch (GetHasherCommon(self)->params.type) {
432
- #define INIT_(N) \
433
- case N: \
434
- StitchToPreviousBlockH ## N(self, input_size, position, data, mask); \
471
+ switch (hasher->common.params.type) {
472
+ #define INIT_(N) \
473
+ case N: \
474
+ StitchToPreviousBlockH ## N( \
475
+ &hasher->privat._H ## N, \
476
+ input_size, position, data, mask); \
435
477
  break;
436
478
  FOR_ALL_HASHERS(INIT_)
437
479
  #undef INIT_
@@ -0,0 +1,125 @@
1
+ /* NOLINT(build/header_guard) */
2
+ /* Copyright 2018 Google Inc. All Rights Reserved.
3
+
4
+ Distributed under MIT license.
5
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6
+ */
7
+
8
+ /* template parameters: FN, HASHER_A, HASHER_B */
9
+
10
+ /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A
11
+ and HASHER_B. */
12
+
13
+ #define HashComposite HASHER()
14
+
15
+ #define FN_A(X) EXPAND_CAT(X, HASHER_A)
16
+ #define FN_B(X) EXPAND_CAT(X, HASHER_B)
17
+
18
+ static BROTLI_INLINE size_t FN(HashTypeLength)(void) {
19
+ size_t a = FN_A(HashTypeLength)();
20
+ size_t b = FN_B(HashTypeLength)();
21
+ return a > b ? a : b;
22
+ }
23
+
24
+ static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
25
+ size_t a = FN_A(StoreLookahead)();
26
+ size_t b = FN_B(StoreLookahead)();
27
+ return a > b ? a : b;
28
+ }
29
+
30
+ typedef struct HashComposite {
31
+ HASHER_A ha;
32
+ HASHER_B hb;
33
+ HasherCommon hb_common;
34
+
35
+ /* Shortcuts. */
36
+ void* extra;
37
+ HasherCommon* common;
38
+
39
+ BROTLI_BOOL fresh;
40
+ const BrotliEncoderParams* params;
41
+ } HashComposite;
42
+
43
+ static void FN(Initialize)(HasherCommon* common,
44
+ HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {
45
+ self->common = common;
46
+ self->extra = common->extra;
47
+
48
+ self->hb_common = *self->common;
49
+ self->fresh = BROTLI_TRUE;
50
+ self->params = params;
51
+ /* TODO: Initialize of the hashers is defered to Prepare (and params
52
+ remembered here) because we don't get the one_shot and input_size params
53
+ here that are needed to know the memory size of them. Instead provide
54
+ those params to all hashers FN(Initialize) */
55
+ }
56
+
57
+ static void FN(Prepare)(
58
+ HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
59
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
60
+ if (self->fresh) {
61
+ self->fresh = BROTLI_FALSE;
62
+ self->hb_common.extra = (uint8_t*)self->extra +
63
+ FN_A(HashMemAllocInBytes)(self->params, one_shot, input_size);
64
+
65
+ FN_A(Initialize)(self->common, &self->ha, self->params);
66
+ FN_B(Initialize)(&self->hb_common, &self->hb, self->params);
67
+ }
68
+ FN_A(Prepare)(&self->ha, one_shot, input_size, data);
69
+ FN_B(Prepare)(&self->hb, one_shot, input_size, data);
70
+ }
71
+
72
+ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
73
+ const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
74
+ size_t input_size) {
75
+ return FN_A(HashMemAllocInBytes)(params, one_shot, input_size) +
76
+ FN_B(HashMemAllocInBytes)(params, one_shot, input_size);
77
+ }
78
+
79
+ static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,
80
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
81
+ FN_A(Store)(&self->ha, data, mask, ix);
82
+ FN_B(Store)(&self->hb, data, mask, ix);
83
+ }
84
+
85
+ static BROTLI_INLINE void FN(StoreRange)(
86
+ HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
87
+ const size_t mask, const size_t ix_start,
88
+ const size_t ix_end) {
89
+ FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);
90
+ FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);
91
+ }
92
+
93
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
94
+ HashComposite* BROTLI_RESTRICT self,
95
+ size_t num_bytes, size_t position, const uint8_t* ringbuffer,
96
+ size_t ring_buffer_mask) {
97
+ FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,
98
+ ringbuffer, ring_buffer_mask);
99
+ FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,
100
+ ringbuffer, ring_buffer_mask);
101
+ }
102
+
103
+ static BROTLI_INLINE void FN(PrepareDistanceCache)(
104
+ HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {
105
+ FN_A(PrepareDistanceCache)(&self->ha, distance_cache);
106
+ FN_B(PrepareDistanceCache)(&self->hb, distance_cache);
107
+ }
108
+
109
+ static BROTLI_INLINE void FN(FindLongestMatch)(
110
+ HashComposite* BROTLI_RESTRICT self,
111
+ const BrotliEncoderDictionary* dictionary,
112
+ const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
113
+ const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
114
+ const size_t max_length, const size_t max_backward,
115
+ const size_t dictionary_distance, const size_t max_distance,
116
+ HasherSearchResult* BROTLI_RESTRICT out) {
117
+ FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,
118
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
119
+ max_distance, out);
120
+ FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,
121
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
122
+ max_distance, out);
123
+ }
124
+
125
+ #undef HashComposite