brotli 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/ext/brotli/brotli.cc +114 -24
  3. data/ext/brotli/brotli.h +0 -1
  4. data/ext/brotli/extconf.rb +30 -23
  5. data/lib/brotli/version.rb +1 -1
  6. data/vendor/brotli/LICENSE +1 -1
  7. data/vendor/brotli/dec/Makefile +1 -1
  8. data/vendor/brotli/dec/bit_reader.c +3 -3
  9. data/vendor/brotli/dec/bit_reader.h +25 -27
  10. data/vendor/brotli/dec/context.h +4 -4
  11. data/vendor/brotli/dec/decode.c +410 -486
  12. data/vendor/brotli/dec/decode.h +101 -105
  13. data/vendor/brotli/dec/dictionary.c +1 -1
  14. data/vendor/brotli/dec/dictionary.h +7 -8
  15. data/vendor/brotli/dec/huffman.c +103 -105
  16. data/vendor/brotli/dec/huffman.h +18 -18
  17. data/vendor/brotli/dec/port.h +52 -40
  18. data/vendor/brotli/dec/prefix.h +2 -0
  19. data/vendor/brotli/dec/state.c +13 -19
  20. data/vendor/brotli/dec/state.h +25 -39
  21. data/vendor/brotli/dec/transform.h +38 -44
  22. data/vendor/brotli/dec/types.h +2 -2
  23. data/vendor/brotli/enc/Makefile +1 -1
  24. data/vendor/brotli/enc/backward_references.cc +455 -359
  25. data/vendor/brotli/enc/backward_references.h +79 -3
  26. data/vendor/brotli/enc/bit_cost.h +54 -32
  27. data/vendor/brotli/enc/block_splitter.cc +285 -193
  28. data/vendor/brotli/enc/block_splitter.h +4 -12
  29. data/vendor/brotli/enc/brotli_bit_stream.cc +623 -324
  30. data/vendor/brotli/enc/brotli_bit_stream.h +76 -37
  31. data/vendor/brotli/enc/cluster.h +161 -120
  32. data/vendor/brotli/enc/command.h +60 -37
  33. data/vendor/brotli/enc/compress_fragment.cc +701 -0
  34. data/vendor/brotli/enc/compress_fragment.h +47 -0
  35. data/vendor/brotli/enc/compress_fragment_two_pass.cc +524 -0
  36. data/vendor/brotli/enc/compress_fragment_two_pass.h +40 -0
  37. data/vendor/brotli/enc/compressor.h +15 -0
  38. data/vendor/brotli/enc/context.h +1 -1
  39. data/vendor/brotli/enc/dictionary.h +2 -2
  40. data/vendor/brotli/enc/encode.cc +819 -286
  41. data/vendor/brotli/enc/encode.h +38 -15
  42. data/vendor/brotli/enc/encode_parallel.cc +40 -42
  43. data/vendor/brotli/enc/entropy_encode.cc +144 -147
  44. data/vendor/brotli/enc/entropy_encode.h +32 -8
  45. data/vendor/brotli/enc/entropy_encode_static.h +572 -0
  46. data/vendor/brotli/enc/fast_log.h +7 -40
  47. data/vendor/brotli/enc/find_match_length.h +9 -9
  48. data/vendor/brotli/enc/hash.h +462 -154
  49. data/vendor/brotli/enc/histogram.cc +6 -6
  50. data/vendor/brotli/enc/histogram.h +13 -13
  51. data/vendor/brotli/enc/literal_cost.cc +45 -45
  52. data/vendor/brotli/enc/metablock.cc +92 -89
  53. data/vendor/brotli/enc/metablock.h +12 -12
  54. data/vendor/brotli/enc/port.h +7 -16
  55. data/vendor/brotli/enc/prefix.h +23 -22
  56. data/vendor/brotli/enc/ringbuffer.h +75 -29
  57. data/vendor/brotli/enc/static_dict.cc +56 -48
  58. data/vendor/brotli/enc/static_dict.h +5 -5
  59. data/vendor/brotli/enc/streams.cc +1 -1
  60. data/vendor/brotli/enc/streams.h +5 -5
  61. data/vendor/brotli/enc/transform.h +40 -35
  62. data/vendor/brotli/enc/types.h +2 -0
  63. data/vendor/brotli/enc/utf8_util.cc +3 -2
  64. data/vendor/brotli/enc/write_bits.h +6 -6
  65. metadata +9 -5
  66. data/vendor/brotli/dec/streams.c +0 -102
  67. data/vendor/brotli/dec/streams.h +0 -95
@@ -10,7 +10,6 @@
10
10
 
11
11
  #include <algorithm>
12
12
  #include <limits>
13
- #include <vector>
14
13
  #include <cstdlib>
15
14
 
16
15
  #include "./histogram.h"
@@ -19,24 +18,6 @@
19
18
 
20
19
  namespace brotli {
21
20
 
22
- namespace {
23
-
24
- struct HuffmanTree {
25
- HuffmanTree(int count, int16_t left, int16_t right)
26
- : total_count_(count),
27
- index_left_(left),
28
- index_right_or_value_(right) {
29
- }
30
- int total_count_;
31
- int16_t index_left_;
32
- int16_t index_right_or_value_;
33
- };
34
-
35
- // Sort the root nodes, least popular first.
36
- bool SortHuffmanTree(const HuffmanTree &v0, const HuffmanTree &v1) {
37
- return v0.total_count_ < v1.total_count_;
38
- }
39
-
40
21
  void SetDepth(const HuffmanTree &p,
41
22
  HuffmanTree *pool,
42
23
  uint8_t *depth,
@@ -50,7 +31,14 @@ void SetDepth(const HuffmanTree &p,
50
31
  }
51
32
  }
52
33
 
53
- } // namespace
34
+ // Sort the root nodes, least popular first.
35
+ static inline bool SortHuffmanTree(const HuffmanTree& v0,
36
+ const HuffmanTree& v1) {
37
+ if (v0.total_count_ != v1.total_count_) {
38
+ return v0.total_count_ < v1.total_count_;
39
+ }
40
+ return v0.index_right_or_value_ > v1.index_right_or_value_;
41
+ }
54
42
 
55
43
  // This function will create a Huffman tree.
56
44
  //
@@ -67,32 +55,31 @@ void SetDepth(const HuffmanTree &p,
67
55
  // we are not planning to use this with extremely long blocks.
68
56
  //
69
57
  // See http://en.wikipedia.org/wiki/Huffman_coding
70
- void CreateHuffmanTree(const int *data,
71
- const int length,
58
+ void CreateHuffmanTree(const uint32_t *data,
59
+ const size_t length,
72
60
  const int tree_limit,
61
+ HuffmanTree* tree,
73
62
  uint8_t *depth) {
74
63
  // For block sizes below 64 kB, we never need to do a second iteration
75
64
  // of this loop. Probably all of our block sizes will be smaller than
76
65
  // that, so this loop is mostly of academic interest. If we actually
77
66
  // would need this, we would be better off with the Katajainen algorithm.
78
- for (int count_limit = 1; ; count_limit *= 2) {
79
- std::vector<HuffmanTree> tree;
80
- tree.reserve(2 * length + 1);
81
-
82
- for (int i = length - 1; i >= 0; --i) {
67
+ for (uint32_t count_limit = 1; ; count_limit *= 2) {
68
+ size_t n = 0;
69
+ for (size_t i = length; i != 0;) {
70
+ --i;
83
71
  if (data[i]) {
84
- const int count = std::max(data[i], count_limit);
85
- tree.push_back(HuffmanTree(count, -1, static_cast<int16_t>(i)));
72
+ const uint32_t count = std::max(data[i], count_limit);
73
+ tree[n++] = HuffmanTree(count, -1, static_cast<int16_t>(i));
86
74
  }
87
75
  }
88
76
 
89
- const int n = static_cast<int>(tree.size());
90
77
  if (n == 1) {
91
78
  depth[tree[0].index_right_or_value_] = 1; // Only one element.
92
79
  break;
93
80
  }
94
81
 
95
- std::stable_sort(tree.begin(), tree.end(), SortHuffmanTree);
82
+ std::sort(tree, tree + n, SortHuffmanTree);
96
83
 
97
84
  // The nodes are:
98
85
  // [0, n): the sorted leaf nodes that we start with.
@@ -101,14 +88,14 @@ void CreateHuffmanTree(const int *data,
101
88
  // (n+1). These are naturally in ascending order.
102
89
  // [2n]: we add a sentinel at the end as well.
103
90
  // There will be (2n+1) elements at the end.
104
- const HuffmanTree sentinel(std::numeric_limits<int>::max(), -1, -1);
105
- tree.push_back(sentinel);
106
- tree.push_back(sentinel);
107
-
108
- int i = 0; // Points to the next leaf node.
109
- int j = n + 1; // Points to the next non-leaf node.
110
- for (int k = n - 1; k > 0; --k) {
111
- int left, right;
91
+ const HuffmanTree sentinel(std::numeric_limits<uint32_t>::max(), -1, -1);
92
+ tree[n] = sentinel;
93
+ tree[n + 1] = sentinel;
94
+
95
+ size_t i = 0; // Points to the next leaf node.
96
+ size_t j = n + 1; // Points to the next non-leaf node.
97
+ for (size_t k = n - 1; k != 0; --k) {
98
+ size_t left, right;
112
99
  if (tree[i].total_count_ <= tree[j].total_count_) {
113
100
  left = i;
114
101
  ++i;
@@ -125,16 +112,15 @@ void CreateHuffmanTree(const int *data,
125
112
  }
126
113
 
127
114
  // The sentinel node becomes the parent node.
128
- int j_end = static_cast<int>(tree.size()) - 1;
115
+ size_t j_end = 2 * n - k;
129
116
  tree[j_end].total_count_ =
130
117
  tree[left].total_count_ + tree[right].total_count_;
131
118
  tree[j_end].index_left_ = static_cast<int16_t>(left);
132
119
  tree[j_end].index_right_or_value_ = static_cast<int16_t>(right);
133
120
 
134
121
  // Add back the last sentinel node.
135
- tree.push_back(sentinel);
122
+ tree[j_end + 1] = sentinel;
136
123
  }
137
- BROTLI_DCHECK(tree.size() == 2 * n + 1);
138
124
  SetDepth(tree[2 * n - 1], &tree[0], depth, 0);
139
125
 
140
126
  // We need to pack the Huffman tree in tree_limit bits.
@@ -146,108 +132,123 @@ void CreateHuffmanTree(const int *data,
146
132
  }
147
133
  }
148
134
 
149
- void Reverse(std::vector<uint8_t>* v, int start, int end) {
135
+ static void Reverse(uint8_t* v, size_t start, size_t end) {
150
136
  --end;
151
137
  while (start < end) {
152
- uint8_t tmp = (*v)[start];
153
- (*v)[start] = (*v)[end];
154
- (*v)[end] = tmp;
138
+ uint8_t tmp = v[start];
139
+ v[start] = v[end];
140
+ v[end] = tmp;
155
141
  ++start;
156
142
  --end;
157
143
  }
158
144
  }
159
145
 
160
- void WriteHuffmanTreeRepetitions(
146
+ static void WriteHuffmanTreeRepetitions(
161
147
  const uint8_t previous_value,
162
148
  const uint8_t value,
163
- int repetitions,
164
- std::vector<uint8_t> *tree,
165
- std::vector<uint8_t> *extra_bits_data) {
149
+ size_t repetitions,
150
+ size_t* tree_size,
151
+ uint8_t* tree,
152
+ uint8_t* extra_bits_data) {
153
+ assert(repetitions > 0);
166
154
  if (previous_value != value) {
167
- tree->push_back(value);
168
- extra_bits_data->push_back(0);
155
+ tree[*tree_size] = value;
156
+ extra_bits_data[*tree_size] = 0;
157
+ ++(*tree_size);
169
158
  --repetitions;
170
159
  }
171
160
  if (repetitions == 7) {
172
- tree->push_back(value);
173
- extra_bits_data->push_back(0);
161
+ tree[*tree_size] = value;
162
+ extra_bits_data[*tree_size] = 0;
163
+ ++(*tree_size);
174
164
  --repetitions;
175
165
  }
176
166
  if (repetitions < 3) {
177
- for (int i = 0; i < repetitions; ++i) {
178
- tree->push_back(value);
179
- extra_bits_data->push_back(0);
167
+ for (size_t i = 0; i < repetitions; ++i) {
168
+ tree[*tree_size] = value;
169
+ extra_bits_data[*tree_size] = 0;
170
+ ++(*tree_size);
180
171
  }
181
172
  } else {
182
173
  repetitions -= 3;
183
- int start = static_cast<int>(tree->size());
184
- while (repetitions >= 0) {
185
- tree->push_back(16);
186
- extra_bits_data->push_back(repetitions & 0x3);
174
+ size_t start = *tree_size;
175
+ while (true) {
176
+ tree[*tree_size] = 16;
177
+ extra_bits_data[*tree_size] = repetitions & 0x3;
178
+ ++(*tree_size);
187
179
  repetitions >>= 2;
180
+ if (repetitions == 0) {
181
+ break;
182
+ }
188
183
  --repetitions;
189
184
  }
190
- Reverse(tree, start, static_cast<int>(tree->size()));
191
- Reverse(extra_bits_data, start, static_cast<int>(tree->size()));
185
+ Reverse(tree, start, *tree_size);
186
+ Reverse(extra_bits_data, start, *tree_size);
192
187
  }
193
188
  }
194
189
 
195
- void WriteHuffmanTreeRepetitionsZeros(
196
- int repetitions,
197
- std::vector<uint8_t> *tree,
198
- std::vector<uint8_t> *extra_bits_data) {
190
+ static void WriteHuffmanTreeRepetitionsZeros(
191
+ size_t repetitions,
192
+ size_t* tree_size,
193
+ uint8_t* tree,
194
+ uint8_t* extra_bits_data) {
199
195
  if (repetitions == 11) {
200
- tree->push_back(0);
201
- extra_bits_data->push_back(0);
196
+ tree[*tree_size] = 0;
197
+ extra_bits_data[*tree_size] = 0;
198
+ ++(*tree_size);
202
199
  --repetitions;
203
200
  }
204
201
  if (repetitions < 3) {
205
- for (int i = 0; i < repetitions; ++i) {
206
- tree->push_back(0);
207
- extra_bits_data->push_back(0);
202
+ for (size_t i = 0; i < repetitions; ++i) {
203
+ tree[*tree_size] = 0;
204
+ extra_bits_data[*tree_size] = 0;
205
+ ++(*tree_size);
208
206
  }
209
207
  } else {
210
208
  repetitions -= 3;
211
- int start = static_cast<int>(tree->size());
212
- while (repetitions >= 0) {
213
- tree->push_back(17);
214
- extra_bits_data->push_back(repetitions & 0x7);
209
+ size_t start = *tree_size;
210
+ while (true) {
211
+ tree[*tree_size] = 17;
212
+ extra_bits_data[*tree_size] = repetitions & 0x7;
213
+ ++(*tree_size);
215
214
  repetitions >>= 3;
215
+ if (repetitions == 0) {
216
+ break;
217
+ }
216
218
  --repetitions;
217
219
  }
218
- Reverse(tree, start, static_cast<int>(tree->size()));
219
- Reverse(extra_bits_data, start, static_cast<int>(tree->size()));
220
+ Reverse(tree, start, *tree_size);
221
+ Reverse(extra_bits_data, start, *tree_size);
220
222
  }
221
223
  }
222
224
 
223
- int OptimizeHuffmanCountsForRle(int length, int* counts) {
224
- int nonzero_count = 0;
225
- int stride;
226
- int limit;
227
- int sum;
228
- uint8_t* good_for_rle;
225
+ void OptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,
226
+ uint8_t* good_for_rle) {
227
+ size_t nonzero_count = 0;
228
+ size_t stride;
229
+ size_t limit;
230
+ size_t sum;
231
+ const size_t streak_limit = 1240;
229
232
  // Let's make the Huffman code more compatible with rle encoding.
230
- int i;
233
+ size_t i;
231
234
  for (i = 0; i < length; i++) {
232
235
  if (counts[i]) {
233
236
  ++nonzero_count;
234
237
  }
235
238
  }
236
239
  if (nonzero_count < 16) {
237
- return 1;
240
+ return;
238
241
  }
239
- for (; length >= 0; --length) {
240
- if (length == 0) {
241
- return 1; // All zeros.
242
- }
243
- if (counts[length - 1] != 0) {
244
- // Now counts[0..length - 1] does not have trailing zeros.
245
- break;
246
- }
242
+ while (length != 0 && counts[length - 1] == 0) {
243
+ --length;
244
+ }
245
+ if (length == 0) {
246
+ return; // All zeros.
247
247
  }
248
+ // Now counts[0..length - 1] does not have trailing zeros.
248
249
  {
249
- int nonzeros = 0;
250
- int smallest_nonzero = 1 << 30;
250
+ size_t nonzeros = 0;
251
+ uint32_t smallest_nonzero = 1 << 30;
251
252
  for (i = 0; i < length; ++i) {
252
253
  if (counts[i] != 0) {
253
254
  ++nonzeros;
@@ -258,9 +259,9 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
258
259
  }
259
260
  if (nonzeros < 5) {
260
261
  // Small histogram will model it well.
261
- return 1;
262
+ return;
262
263
  }
263
- int zeros = length - nonzeros;
264
+ size_t zeros = length - nonzeros;
264
265
  if (smallest_nonzero < 4) {
265
266
  if (zeros < 6) {
266
267
  for (i = 1; i < length - 1; ++i) {
@@ -271,54 +272,50 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
271
272
  }
272
273
  }
273
274
  if (nonzeros < 28) {
274
- return 1;
275
+ return;
275
276
  }
276
277
  }
277
278
  // 2) Let's mark all population counts that already can be encoded
278
279
  // with an rle code.
279
- good_for_rle = (uint8_t*)calloc(length, 1);
280
- if (good_for_rle == NULL) {
281
- return 0;
282
- }
280
+ memset(good_for_rle, 0, length);
283
281
  {
284
282
  // Let's not spoil any of the existing good rle codes.
285
283
  // Mark any seq of 0's that is longer as 5 as a good_for_rle.
286
284
  // Mark any seq of non-0's that is longer as 7 as a good_for_rle.
287
- int symbol = counts[0];
288
- int stride = 0;
289
- for (i = 0; i < length + 1; ++i) {
285
+ uint32_t symbol = counts[0];
286
+ size_t step = 0;
287
+ for (i = 0; i <= length; ++i) {
290
288
  if (i == length || counts[i] != symbol) {
291
- if ((symbol == 0 && stride >= 5) ||
292
- (symbol != 0 && stride >= 7)) {
293
- int k;
294
- for (k = 0; k < stride; ++k) {
289
+ if ((symbol == 0 && step >= 5) ||
290
+ (symbol != 0 && step >= 7)) {
291
+ size_t k;
292
+ for (k = 0; k < step; ++k) {
295
293
  good_for_rle[i - k - 1] = 1;
296
294
  }
297
295
  }
298
- stride = 1;
296
+ step = 1;
299
297
  if (i != length) {
300
298
  symbol = counts[i];
301
299
  }
302
300
  } else {
303
- ++stride;
301
+ ++step;
304
302
  }
305
303
  }
306
304
  }
307
305
  // 3) Let's replace those population counts that lead to more rle codes.
308
306
  // Math here is in 24.8 fixed point representation.
309
- const int streak_limit = 1240;
310
307
  stride = 0;
311
308
  limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420;
312
309
  sum = 0;
313
- for (i = 0; i < length + 1; ++i) {
310
+ for (i = 0; i <= length; ++i) {
314
311
  if (i == length || good_for_rle[i] ||
315
312
  (i != 0 && good_for_rle[i - 1]) ||
316
- abs(256 * counts[i] - limit) >= streak_limit) {
313
+ (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) {
317
314
  if (stride >= 4 || (stride >= 3 && sum == 0)) {
318
- int k;
315
+ size_t k;
319
316
  // The stride must end, collapse what we have, if we have enough (4).
320
- int count = (sum + stride / 2) / stride;
321
- if (count < 1) {
317
+ size_t count = (sum + stride / 2) / stride;
318
+ if (count == 0) {
322
319
  count = 1;
323
320
  }
324
321
  if (sum == 0) {
@@ -328,7 +325,7 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
328
325
  for (k = 0; k < stride; ++k) {
329
326
  // We don't want to change value at counts[i],
330
327
  // that is already belonging to the next stride. Thus - 1.
331
- counts[i - k - 1] = count;
328
+ counts[i - k - 1] = static_cast<uint32_t>(count);
332
329
  }
333
330
  }
334
331
  stride = 0;
@@ -354,21 +351,19 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
354
351
  }
355
352
  }
356
353
  }
357
- free(good_for_rle);
358
- return 1;
359
354
  }
360
355
 
361
- static void DecideOverRleUse(const uint8_t* depth, const int length,
356
+ static void DecideOverRleUse(const uint8_t* depth, const size_t length,
362
357
  bool *use_rle_for_non_zero,
363
358
  bool *use_rle_for_zero) {
364
- int total_reps_zero = 0;
365
- int total_reps_non_zero = 0;
366
- int count_reps_zero = 0;
367
- int count_reps_non_zero = 0;
368
- for (int i = 0; i < length;) {
369
- const int value = depth[i];
370
- int reps = 1;
371
- for (int k = i + 1; k < length && depth[k] == value; ++k) {
359
+ size_t total_reps_zero = 0;
360
+ size_t total_reps_non_zero = 0;
361
+ size_t count_reps_zero = 1;
362
+ size_t count_reps_non_zero = 1;
363
+ for (size_t i = 0; i < length;) {
364
+ const uint8_t value = depth[i];
365
+ size_t reps = 1;
366
+ for (size_t k = i + 1; k < length && depth[k] == value; ++k) {
372
367
  ++reps;
373
368
  }
374
369
  if (reps >= 3 && value == 0) {
@@ -381,21 +376,20 @@ static void DecideOverRleUse(const uint8_t* depth, const int length,
381
376
  }
382
377
  i += reps;
383
378
  }
384
- total_reps_non_zero -= count_reps_non_zero * 2;
385
- total_reps_zero -= count_reps_zero * 2;
386
- *use_rle_for_non_zero = total_reps_non_zero > 2;
387
- *use_rle_for_zero = total_reps_zero > 2;
379
+ *use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero * 2;
380
+ *use_rle_for_zero = total_reps_zero > count_reps_zero * 2;
388
381
  }
389
382
 
390
383
  void WriteHuffmanTree(const uint8_t* depth,
391
- uint32_t length,
392
- std::vector<uint8_t> *tree,
393
- std::vector<uint8_t> *extra_bits_data) {
384
+ size_t length,
385
+ size_t* tree_size,
386
+ uint8_t* tree,
387
+ uint8_t* extra_bits_data) {
394
388
  uint8_t previous_value = 8;
395
389
 
396
390
  // Throw away trailing zeros.
397
- uint32_t new_length = length;
398
- for (uint32_t i = 0; i < length; ++i) {
391
+ size_t new_length = length;
392
+ for (size_t i = 0; i < length; ++i) {
399
393
  if (depth[length - i - 1] == 0) {
400
394
  --new_length;
401
395
  } else {
@@ -414,20 +408,21 @@ void WriteHuffmanTree(const uint8_t* depth,
414
408
  }
415
409
 
416
410
  // Actual rle coding.
417
- for (uint32_t i = 0; i < new_length;) {
411
+ for (size_t i = 0; i < new_length;) {
418
412
  const uint8_t value = depth[i];
419
- int reps = 1;
413
+ size_t reps = 1;
420
414
  if ((value != 0 && use_rle_for_non_zero) ||
421
415
  (value == 0 && use_rle_for_zero)) {
422
- for (uint32_t k = i + 1; k < new_length && depth[k] == value; ++k) {
416
+ for (size_t k = i + 1; k < new_length && depth[k] == value; ++k) {
423
417
  ++reps;
424
418
  }
425
419
  }
426
420
  if (value == 0) {
427
- WriteHuffmanTreeRepetitionsZeros(reps, tree, extra_bits_data);
421
+ WriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data);
428
422
  } else {
429
423
  WriteHuffmanTreeRepetitions(previous_value,
430
- value, reps, tree, extra_bits_data);
424
+ value, reps, tree_size,
425
+ tree, extra_bits_data);
431
426
  previous_value = value;
432
427
  }
433
428
  i += reps;
@@ -453,13 +448,15 @@ uint16_t ReverseBits(int num_bits, uint16_t bits) {
453
448
 
454
449
  } // namespace
455
450
 
456
- void ConvertBitDepthsToSymbols(const uint8_t *depth, int len, uint16_t *bits) {
451
+ void ConvertBitDepthsToSymbols(const uint8_t *depth,
452
+ size_t len,
453
+ uint16_t *bits) {
457
454
  // In Brotli, all bit depths are [1..15]
458
455
  // 0 bit depth means that the symbol does not exist.
459
456
  const int kMaxBits = 16; // 0..15 are values for bits
460
457
  uint16_t bl_count[kMaxBits] = { 0 };
461
458
  {
462
- for (int i = 0; i < len; ++i) {
459
+ for (size_t i = 0; i < len; ++i) {
463
460
  ++bl_count[depth[i]];
464
461
  }
465
462
  bl_count[0] = 0;
@@ -473,7 +470,7 @@ void ConvertBitDepthsToSymbols(const uint8_t *depth, int len, uint16_t *bits) {
473
470
  next_code[bits] = static_cast<uint16_t>(code);
474
471
  }
475
472
  }
476
- for (int i = 0; i < len; ++i) {
473
+ for (size_t i = 0; i < len; ++i) {
477
474
  if (depth[i]) {
478
475
  bits[i] = ReverseBits(depth[i], next_code[depth[i]]++);
479
476
  }
@@ -10,13 +10,28 @@
10
10
  #define BROTLI_ENC_ENTROPY_ENCODE_H_
11
11
 
12
12
  #include <string.h>
13
- #include <vector>
14
13
  #include "./histogram.h"
15
14
  #include "./prefix.h"
16
15
  #include "./types.h"
17
16
 
18
17
  namespace brotli {
19
18
 
19
+ // A node of a Huffman tree.
20
+ struct HuffmanTree {
21
+ HuffmanTree() {}
22
+ HuffmanTree(uint32_t count, int16_t left, int16_t right)
23
+ : total_count_(count),
24
+ index_left_(left),
25
+ index_right_or_value_(right) {
26
+ }
27
+ uint32_t total_count_;
28
+ int16_t index_left_;
29
+ int16_t index_right_or_value_;
30
+ };
31
+
32
+ void SetDepth(const HuffmanTree &p, HuffmanTree *pool,
33
+ uint8_t *depth, uint8_t level);
34
+
20
35
  // This function will create a Huffman tree.
21
36
  //
22
37
  // The (data,length) contains the population counts.
@@ -25,10 +40,14 @@ namespace brotli {
25
40
  // The depth contains the tree, i.e., how many bits are used for
26
41
  // the symbol.
27
42
  //
43
+ // The actual Huffman tree is constructed in the tree[] array, which has to
44
+ // be at least 2 * length + 1 long.
45
+ //
28
46
  // See http://en.wikipedia.org/wiki/Huffman_coding
29
- void CreateHuffmanTree(const int *data,
30
- const int length,
47
+ void CreateHuffmanTree(const uint32_t *data,
48
+ const size_t length,
31
49
  const int tree_limit,
50
+ HuffmanTree* tree,
32
51
  uint8_t *depth);
33
52
 
34
53
  // Change the population counts in a way that the consequent
@@ -37,18 +56,23 @@ void CreateHuffmanTree(const int *data,
37
56
  //
38
57
  // length contains the size of the histogram.
39
58
  // counts contains the population counts.
40
- int OptimizeHuffmanCountsForRle(int length, int* counts);
59
+ // good_for_rle is a buffer of at least length size
60
+ void OptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,
61
+ uint8_t* good_for_rle);
41
62
 
42
63
  // Write a Huffman tree from bit depths into the bitstream representation
43
64
  // of a Huffman tree. The generated Huffman tree is to be compressed once
44
65
  // more using a Huffman tree
45
66
  void WriteHuffmanTree(const uint8_t* depth,
46
- uint32_t num,
47
- std::vector<uint8_t> *tree,
48
- std::vector<uint8_t> *extra_bits_data);
67
+ size_t num,
68
+ size_t* tree_size,
69
+ uint8_t* tree,
70
+ uint8_t* extra_bits_data);
49
71
 
50
72
  // Get the actual bit values for a tree of bit depths.
51
- void ConvertBitDepthsToSymbols(const uint8_t *depth, int len, uint16_t *bits);
73
+ void ConvertBitDepthsToSymbols(const uint8_t *depth,
74
+ size_t len,
75
+ uint16_t *bits);
52
76
 
53
77
  template<int kSize>
54
78
  struct EntropyCode {