chd 0.1.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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +30 -0
  3. data/chd.gemspec +29 -0
  4. data/ext/chd.c +1008 -0
  5. data/ext/extconf.rb +60 -0
  6. data/lib/chd/cd.rb +272 -0
  7. data/lib/chd/metadata.rb +196 -0
  8. data/lib/chd/version.rb +4 -0
  9. data/lib/chd.rb +21 -0
  10. data/libchdr/CMakeLists.txt +104 -0
  11. data/libchdr/LICENSE.txt +24 -0
  12. data/libchdr/README.md +7 -0
  13. data/libchdr/deps/lzma-19.00/CMakeLists.txt +33 -0
  14. data/libchdr/deps/lzma-19.00/LICENSE +3 -0
  15. data/libchdr/deps/lzma-19.00/include/7zTypes.h +375 -0
  16. data/libchdr/deps/lzma-19.00/include/Alloc.h +51 -0
  17. data/libchdr/deps/lzma-19.00/include/Bra.h +64 -0
  18. data/libchdr/deps/lzma-19.00/include/Compiler.h +33 -0
  19. data/libchdr/deps/lzma-19.00/include/CpuArch.h +336 -0
  20. data/libchdr/deps/lzma-19.00/include/Delta.h +19 -0
  21. data/libchdr/deps/lzma-19.00/include/LzFind.h +121 -0
  22. data/libchdr/deps/lzma-19.00/include/LzHash.h +57 -0
  23. data/libchdr/deps/lzma-19.00/include/Lzma86.h +111 -0
  24. data/libchdr/deps/lzma-19.00/include/LzmaDec.h +234 -0
  25. data/libchdr/deps/lzma-19.00/include/LzmaEnc.h +76 -0
  26. data/libchdr/deps/lzma-19.00/include/LzmaLib.h +131 -0
  27. data/libchdr/deps/lzma-19.00/include/Precomp.h +10 -0
  28. data/libchdr/deps/lzma-19.00/include/Sort.h +18 -0
  29. data/libchdr/deps/lzma-19.00/lzma-history.txt +446 -0
  30. data/libchdr/deps/lzma-19.00/lzma.txt +328 -0
  31. data/libchdr/deps/lzma-19.00/lzma.vcxproj +543 -0
  32. data/libchdr/deps/lzma-19.00/lzma.vcxproj.filters +17 -0
  33. data/libchdr/deps/lzma-19.00/src/Alloc.c +455 -0
  34. data/libchdr/deps/lzma-19.00/src/Bra86.c +82 -0
  35. data/libchdr/deps/lzma-19.00/src/BraIA64.c +53 -0
  36. data/libchdr/deps/lzma-19.00/src/CpuArch.c +218 -0
  37. data/libchdr/deps/lzma-19.00/src/Delta.c +64 -0
  38. data/libchdr/deps/lzma-19.00/src/LzFind.c +1127 -0
  39. data/libchdr/deps/lzma-19.00/src/Lzma86Dec.c +54 -0
  40. data/libchdr/deps/lzma-19.00/src/LzmaDec.c +1185 -0
  41. data/libchdr/deps/lzma-19.00/src/LzmaEnc.c +1330 -0
  42. data/libchdr/deps/lzma-19.00/src/Sort.c +141 -0
  43. data/libchdr/deps/zlib-1.2.11/CMakeLists.txt +29 -0
  44. data/libchdr/deps/zlib-1.2.11/ChangeLog +1515 -0
  45. data/libchdr/deps/zlib-1.2.11/FAQ +368 -0
  46. data/libchdr/deps/zlib-1.2.11/INDEX +68 -0
  47. data/libchdr/deps/zlib-1.2.11/Makefile +5 -0
  48. data/libchdr/deps/zlib-1.2.11/Makefile.in +410 -0
  49. data/libchdr/deps/zlib-1.2.11/README +115 -0
  50. data/libchdr/deps/zlib-1.2.11/adler32.c +186 -0
  51. data/libchdr/deps/zlib-1.2.11/compress.c +86 -0
  52. data/libchdr/deps/zlib-1.2.11/configure +921 -0
  53. data/libchdr/deps/zlib-1.2.11/crc32.c +442 -0
  54. data/libchdr/deps/zlib-1.2.11/crc32.h +441 -0
  55. data/libchdr/deps/zlib-1.2.11/deflate.c +2163 -0
  56. data/libchdr/deps/zlib-1.2.11/deflate.h +349 -0
  57. data/libchdr/deps/zlib-1.2.11/doc/algorithm.txt +209 -0
  58. data/libchdr/deps/zlib-1.2.11/doc/rfc1950.txt +619 -0
  59. data/libchdr/deps/zlib-1.2.11/doc/rfc1951.txt +955 -0
  60. data/libchdr/deps/zlib-1.2.11/doc/rfc1952.txt +675 -0
  61. data/libchdr/deps/zlib-1.2.11/doc/txtvsbin.txt +107 -0
  62. data/libchdr/deps/zlib-1.2.11/gzclose.c +25 -0
  63. data/libchdr/deps/zlib-1.2.11/gzguts.h +218 -0
  64. data/libchdr/deps/zlib-1.2.11/gzlib.c +637 -0
  65. data/libchdr/deps/zlib-1.2.11/gzread.c +654 -0
  66. data/libchdr/deps/zlib-1.2.11/gzwrite.c +665 -0
  67. data/libchdr/deps/zlib-1.2.11/infback.c +640 -0
  68. data/libchdr/deps/zlib-1.2.11/inffast.c +323 -0
  69. data/libchdr/deps/zlib-1.2.11/inffast.h +11 -0
  70. data/libchdr/deps/zlib-1.2.11/inffixed.h +94 -0
  71. data/libchdr/deps/zlib-1.2.11/inflate.c +1561 -0
  72. data/libchdr/deps/zlib-1.2.11/inflate.h +125 -0
  73. data/libchdr/deps/zlib-1.2.11/inftrees.c +304 -0
  74. data/libchdr/deps/zlib-1.2.11/inftrees.h +62 -0
  75. data/libchdr/deps/zlib-1.2.11/make_vms.com +867 -0
  76. data/libchdr/deps/zlib-1.2.11/treebuild.xml +116 -0
  77. data/libchdr/deps/zlib-1.2.11/trees.c +1203 -0
  78. data/libchdr/deps/zlib-1.2.11/trees.h +128 -0
  79. data/libchdr/deps/zlib-1.2.11/uncompr.c +93 -0
  80. data/libchdr/deps/zlib-1.2.11/zconf.h +534 -0
  81. data/libchdr/deps/zlib-1.2.11/zconf.h.cmakein +536 -0
  82. data/libchdr/deps/zlib-1.2.11/zconf.h.in +534 -0
  83. data/libchdr/deps/zlib-1.2.11/zlib.3 +149 -0
  84. data/libchdr/deps/zlib-1.2.11/zlib.3.pdf +0 -0
  85. data/libchdr/deps/zlib-1.2.11/zlib.h +1912 -0
  86. data/libchdr/deps/zlib-1.2.11/zlib.map +94 -0
  87. data/libchdr/deps/zlib-1.2.11/zlib.pc.cmakein +13 -0
  88. data/libchdr/deps/zlib-1.2.11/zlib.pc.in +13 -0
  89. data/libchdr/deps/zlib-1.2.11/zlib2ansi +152 -0
  90. data/libchdr/deps/zlib-1.2.11/zutil.c +325 -0
  91. data/libchdr/deps/zlib-1.2.11/zutil.h +271 -0
  92. data/libchdr/include/dr_libs/dr_flac.h +12280 -0
  93. data/libchdr/include/libchdr/bitstream.h +43 -0
  94. data/libchdr/include/libchdr/cdrom.h +110 -0
  95. data/libchdr/include/libchdr/chd.h +427 -0
  96. data/libchdr/include/libchdr/chdconfig.h +10 -0
  97. data/libchdr/include/libchdr/coretypes.h +60 -0
  98. data/libchdr/include/libchdr/flac.h +50 -0
  99. data/libchdr/include/libchdr/huffman.h +90 -0
  100. data/libchdr/pkg-config.pc.in +10 -0
  101. data/libchdr/src/libchdr_bitstream.c +125 -0
  102. data/libchdr/src/libchdr_cdrom.c +415 -0
  103. data/libchdr/src/libchdr_chd.c +2744 -0
  104. data/libchdr/src/libchdr_flac.c +302 -0
  105. data/libchdr/src/libchdr_huffman.c +545 -0
  106. data/libchdr/src/link.T +5 -0
  107. data/libchdr/tests/CMakeLists.txt +2 -0
  108. data/libchdr/tests/benchmark.c +52 -0
  109. metadata +183 -0
@@ -0,0 +1,545 @@
1
+ /* license:BSD-3-Clause
2
+ * copyright-holders:Aaron Giles
3
+ ****************************************************************************
4
+
5
+ huffman.c
6
+
7
+ Static Huffman compression and decompression helpers.
8
+
9
+ ****************************************************************************
10
+
11
+ Maximum codelength is officially (alphabetsize - 1). This would be 255 bits
12
+ (since we use 1 byte values). However, it is also dependent upon the number
13
+ of samples used, as follows:
14
+
15
+ 2 bits -> 3..4 samples
16
+ 3 bits -> 5..7 samples
17
+ 4 bits -> 8..12 samples
18
+ 5 bits -> 13..20 samples
19
+ 6 bits -> 21..33 samples
20
+ 7 bits -> 34..54 samples
21
+ 8 bits -> 55..88 samples
22
+ 9 bits -> 89..143 samples
23
+ 10 bits -> 144..232 samples
24
+ 11 bits -> 233..376 samples
25
+ 12 bits -> 377..609 samples
26
+ 13 bits -> 610..986 samples
27
+ 14 bits -> 987..1596 samples
28
+ 15 bits -> 1597..2583 samples
29
+ 16 bits -> 2584..4180 samples -> note that a 4k data size guarantees codelength <= 16 bits
30
+ 17 bits -> 4181..6764 samples
31
+ 18 bits -> 6765..10945 samples
32
+ 19 bits -> 10946..17710 samples
33
+ 20 bits -> 17711..28656 samples
34
+ 21 bits -> 28657..46367 samples
35
+ 22 bits -> 46368..75024 samples
36
+ 23 bits -> 75025..121392 samples
37
+ 24 bits -> 121393..196417 samples
38
+ 25 bits -> 196418..317810 samples
39
+ 26 bits -> 317811..514228 samples
40
+ 27 bits -> 514229..832039 samples
41
+ 28 bits -> 832040..1346268 samples
42
+ 29 bits -> 1346269..2178308 samples
43
+ 30 bits -> 2178309..3524577 samples
44
+ 31 bits -> 3524578..5702886 samples
45
+ 32 bits -> 5702887..9227464 samples
46
+
47
+ Looking at it differently, here is where powers of 2 fall into these buckets:
48
+
49
+ 256 samples -> 11 bits max
50
+ 512 samples -> 12 bits max
51
+ 1k samples -> 14 bits max
52
+ 2k samples -> 15 bits max
53
+ 4k samples -> 16 bits max
54
+ 8k samples -> 18 bits max
55
+ 16k samples -> 19 bits max
56
+ 32k samples -> 21 bits max
57
+ 64k samples -> 22 bits max
58
+ 128k samples -> 24 bits max
59
+ 256k samples -> 25 bits max
60
+ 512k samples -> 27 bits max
61
+ 1M samples -> 28 bits max
62
+ 2M samples -> 29 bits max
63
+ 4M samples -> 31 bits max
64
+ 8M samples -> 32 bits max
65
+
66
+ ****************************************************************************
67
+
68
+ Delta-RLE encoding works as follows:
69
+
70
+ Starting value is assumed to be 0. All data is encoded as a delta
71
+ from the previous value, such that final[i] = final[i - 1] + delta.
72
+ Long runs of 0s are RLE-encoded as follows:
73
+
74
+ 0x100 = repeat count of 8
75
+ 0x101 = repeat count of 9
76
+ 0x102 = repeat count of 10
77
+ 0x103 = repeat count of 11
78
+ 0x104 = repeat count of 12
79
+ 0x105 = repeat count of 13
80
+ 0x106 = repeat count of 14
81
+ 0x107 = repeat count of 15
82
+ 0x108 = repeat count of 16
83
+ 0x109 = repeat count of 32
84
+ 0x10a = repeat count of 64
85
+ 0x10b = repeat count of 128
86
+ 0x10c = repeat count of 256
87
+ 0x10d = repeat count of 512
88
+ 0x10e = repeat count of 1024
89
+ 0x10f = repeat count of 2048
90
+
91
+ Note that repeat counts are reset at the end of a row, so if a 0 run
92
+ extends to the end of a row, a large repeat count may be used.
93
+
94
+ The reason for starting the run counts at 8 is that 0 is expected to
95
+ be the most common symbol, and is typically encoded in 1 or 2 bits.
96
+
97
+ ***************************************************************************/
98
+
99
+ #include <stdlib.h>
100
+ #include <stdio.h>
101
+ #include <string.h>
102
+
103
+ #include <libchdr/huffman.h>
104
+
105
+ #define MAX(x,y) ((x) > (y) ? (x) : (y))
106
+
107
+ /***************************************************************************
108
+ * MACROS
109
+ ***************************************************************************
110
+ */
111
+
112
+ #define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
113
+
114
+ /***************************************************************************
115
+ * IMPLEMENTATION
116
+ ***************************************************************************
117
+ */
118
+
119
+ /*-------------------------------------------------
120
+ * huffman_context_base - create an encoding/
121
+ * decoding context
122
+ *-------------------------------------------------
123
+ */
124
+
125
+ struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
126
+ {
127
+ struct huffman_decoder* decoder = NULL;
128
+
129
+ /* limit to 24 bits */
130
+ if (maxbits > 24)
131
+ return NULL;
132
+
133
+ decoder = (struct huffman_decoder*)malloc(sizeof(struct huffman_decoder));
134
+ decoder->numcodes = numcodes;
135
+ decoder->maxbits = maxbits;
136
+ decoder->lookup = (lookup_value*)malloc(sizeof(lookup_value) * (1 << maxbits));
137
+ decoder->huffnode = (struct node_t*)malloc(sizeof(struct node_t) * numcodes);
138
+ decoder->datahisto = NULL;
139
+ decoder->prevdata = 0;
140
+ decoder->rleremaining = 0;
141
+ return decoder;
142
+ }
143
+
144
+ void delete_huffman_decoder(struct huffman_decoder* decoder)
145
+ {
146
+ if (decoder != NULL)
147
+ {
148
+ if (decoder->lookup != NULL)
149
+ free(decoder->lookup);
150
+ if (decoder->huffnode != NULL)
151
+ free(decoder->huffnode);
152
+ free(decoder);
153
+ }
154
+ }
155
+
156
+ /*-------------------------------------------------
157
+ * decode_one - decode a single code from the
158
+ * huffman stream
159
+ *-------------------------------------------------
160
+ */
161
+
162
+ uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf)
163
+ {
164
+ /* peek ahead to get maxbits worth of data */
165
+ uint32_t bits = bitstream_peek(bitbuf, decoder->maxbits);
166
+
167
+ /* look it up, then remove the actual number of bits for this code */
168
+ lookup_value lookup = decoder->lookup[bits];
169
+ bitstream_remove(bitbuf, lookup & 0x1f);
170
+
171
+ /* return the value */
172
+ return lookup >> 5;
173
+ }
174
+
175
+ /*-------------------------------------------------
176
+ * import_tree_rle - import an RLE-encoded
177
+ * huffman tree from a source data stream
178
+ *-------------------------------------------------
179
+ */
180
+
181
+ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
182
+ {
183
+ int numbits;
184
+ uint32_t curnode;
185
+ enum huffman_error error;
186
+
187
+ /* bits per entry depends on the maxbits */
188
+ if (decoder->maxbits >= 16)
189
+ numbits = 5;
190
+ else if (decoder->maxbits >= 8)
191
+ numbits = 4;
192
+ else
193
+ numbits = 3;
194
+
195
+ /* loop until we read all the nodes */
196
+ for (curnode = 0; curnode < decoder->numcodes; )
197
+ {
198
+ /* a non-one value is just raw */
199
+ int nodebits = bitstream_read(bitbuf, numbits);
200
+ if (nodebits != 1)
201
+ decoder->huffnode[curnode++].numbits = nodebits;
202
+
203
+ /* a one value is an escape code */
204
+ else
205
+ {
206
+ /* a double 1 is just a single 1 */
207
+ nodebits = bitstream_read(bitbuf, numbits);
208
+ if (nodebits == 1)
209
+ decoder->huffnode[curnode++].numbits = nodebits;
210
+
211
+ /* otherwise, we need one for value for the repeat count */
212
+ else
213
+ {
214
+ int repcount = bitstream_read(bitbuf, numbits) + 3;
215
+ while (repcount--)
216
+ decoder->huffnode[curnode++].numbits = nodebits;
217
+ }
218
+ }
219
+ }
220
+
221
+ /* make sure we ended up with the right number */
222
+ if (curnode != decoder->numcodes)
223
+ return HUFFERR_INVALID_DATA;
224
+
225
+ /* assign canonical codes for all nodes based on their code lengths */
226
+ error = huffman_assign_canonical_codes(decoder);
227
+ if (error != HUFFERR_NONE)
228
+ return error;
229
+
230
+ /* build the lookup table */
231
+ huffman_build_lookup_table(decoder);
232
+
233
+ /* determine final input length and report errors */
234
+ return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
235
+ }
236
+
237
+
238
+ /*-------------------------------------------------
239
+ * import_tree_huffman - import a huffman-encoded
240
+ * huffman tree from a source data stream
241
+ *-------------------------------------------------
242
+ */
243
+
244
+ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
245
+ {
246
+ int start;
247
+ int last = 0;
248
+ int count = 0;
249
+ int index;
250
+ uint32_t curcode;
251
+ uint8_t rlefullbits = 0;
252
+ uint32_t temp;
253
+ enum huffman_error error;
254
+ /* start by parsing the lengths for the small tree */
255
+ struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
256
+ smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
257
+ start = bitstream_read(bitbuf, 3) + 1;
258
+ for (index = 1; index < 24; index++)
259
+ {
260
+ if (index < start || count == 7)
261
+ smallhuff->huffnode[index].numbits = 0;
262
+ else
263
+ {
264
+ count = bitstream_read(bitbuf, 3);
265
+ smallhuff->huffnode[index].numbits = (count == 7) ? 0 : count;
266
+ }
267
+ }
268
+
269
+ /* then regenerate the tree */
270
+ error = huffman_assign_canonical_codes(smallhuff);
271
+ if (error != HUFFERR_NONE)
272
+ return error;
273
+ huffman_build_lookup_table(smallhuff);
274
+
275
+ /* determine the maximum length of an RLE count */
276
+ temp = decoder->numcodes - 9;
277
+ while (temp != 0)
278
+ temp >>= 1, rlefullbits++;
279
+
280
+ /* now process the rest of the data */
281
+ for (curcode = 0; curcode < decoder->numcodes; )
282
+ {
283
+ int value = huffman_decode_one(smallhuff, bitbuf);
284
+ if (value != 0)
285
+ decoder->huffnode[curcode++].numbits = last = value - 1;
286
+ else
287
+ {
288
+ int count = bitstream_read(bitbuf, 3) + 2;
289
+ if (count == 7+2)
290
+ count += bitstream_read(bitbuf, rlefullbits);
291
+ for ( ; count != 0 && curcode < decoder->numcodes; count--)
292
+ decoder->huffnode[curcode++].numbits = last;
293
+ }
294
+ }
295
+
296
+ /* make sure we ended up with the right number */
297
+ if (curcode != decoder->numcodes)
298
+ return HUFFERR_INVALID_DATA;
299
+
300
+ /* assign canonical codes for all nodes based on their code lengths */
301
+ error = huffman_assign_canonical_codes(decoder);
302
+ if (error != HUFFERR_NONE)
303
+ return error;
304
+
305
+ /* build the lookup table */
306
+ huffman_build_lookup_table(decoder);
307
+
308
+ /* determine final input length and report errors */
309
+ return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
310
+ }
311
+
312
+ /*-------------------------------------------------
313
+ * compute_tree_from_histo - common backend for
314
+ * computing a tree based on the data histogram
315
+ *-------------------------------------------------
316
+ */
317
+
318
+ enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
319
+ {
320
+ uint32_t i;
321
+ uint32_t lowerweight;
322
+ uint32_t upperweight;
323
+ /* compute the number of data items in the histogram */
324
+ uint32_t sdatacount = 0;
325
+ for (i = 0; i < decoder->numcodes; i++)
326
+ sdatacount += decoder->datahisto[i];
327
+
328
+ /* binary search to achieve the optimum encoding */
329
+ lowerweight = 0;
330
+ upperweight = sdatacount * 2;
331
+ while (1)
332
+ {
333
+ /* build a tree using the current weight */
334
+ uint32_t curweight = (upperweight + lowerweight) / 2;
335
+ int curmaxbits = huffman_build_tree(decoder, sdatacount, curweight);
336
+
337
+ /* apply binary search here */
338
+ if (curmaxbits <= decoder->maxbits)
339
+ {
340
+ lowerweight = curweight;
341
+
342
+ /* early out if it worked with the raw weights, or if we're done searching */
343
+ if (curweight == sdatacount || (upperweight - lowerweight) <= 1)
344
+ break;
345
+ }
346
+ else
347
+ upperweight = curweight;
348
+ }
349
+
350
+ /* assign canonical codes for all nodes based on their code lengths */
351
+ return huffman_assign_canonical_codes(decoder);
352
+ }
353
+
354
+ /***************************************************************************
355
+ * INTERNAL FUNCTIONS
356
+ ***************************************************************************
357
+ */
358
+
359
+ /*-------------------------------------------------
360
+ * tree_node_compare - compare two tree nodes
361
+ * by weight
362
+ *-------------------------------------------------
363
+ */
364
+
365
+ static int huffman_tree_node_compare(const void *item1, const void *item2)
366
+ {
367
+ const struct node_t *node1 = *(const struct node_t **)item1;
368
+ const struct node_t *node2 = *(const struct node_t **)item2;
369
+ if (node2->weight != node1->weight)
370
+ return node2->weight - node1->weight;
371
+ if (node2->bits - node1->bits == 0)
372
+ fprintf(stderr, "identical node sort keys, should not happen!\n");
373
+ return (int)node1->bits - (int)node2->bits;
374
+ }
375
+
376
+ /*-------------------------------------------------
377
+ * build_tree - build a huffman tree based on the
378
+ * data distribution
379
+ *-------------------------------------------------
380
+ */
381
+
382
+ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
383
+ {
384
+ uint32_t curcode;
385
+ int nextalloc;
386
+ int listitems = 0;
387
+ int maxbits = 0;
388
+ /* make a list of all non-zero nodes */
389
+ struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
390
+ memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
391
+ for (curcode = 0; curcode < decoder->numcodes; curcode++)
392
+ if (decoder->datahisto[curcode] != 0)
393
+ {
394
+ list[listitems++] = &decoder->huffnode[curcode];
395
+ decoder->huffnode[curcode].count = decoder->datahisto[curcode];
396
+ decoder->huffnode[curcode].bits = curcode;
397
+
398
+ /* scale the weight by the current effective length, ensuring we don't go to 0 */
399
+ decoder->huffnode[curcode].weight = ((uint64_t)decoder->datahisto[curcode]) * ((uint64_t)totalweight) / ((uint64_t)totaldata);
400
+ if (decoder->huffnode[curcode].weight == 0)
401
+ decoder->huffnode[curcode].weight = 1;
402
+ }
403
+
404
+ #if 0
405
+ fprintf(stderr, "Pre-sort:\n");
406
+ for (int i = 0; i < listitems; i++) {
407
+ fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
408
+ }
409
+ #endif
410
+
411
+ /* sort the list by weight, largest weight first */
412
+ qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
413
+
414
+ #if 0
415
+ fprintf(stderr, "Post-sort:\n");
416
+ for (int i = 0; i < listitems; i++) {
417
+ fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
418
+ }
419
+ fprintf(stderr, "===================\n");
420
+ #endif
421
+
422
+ /* now build the tree */
423
+ nextalloc = decoder->numcodes;
424
+ while (listitems > 1)
425
+ {
426
+ int curitem;
427
+ /* remove lowest two items */
428
+ struct node_t* node1 = &(*list[--listitems]);
429
+ struct node_t* node0 = &(*list[--listitems]);
430
+
431
+ /* create new node */
432
+ struct node_t* newnode = &decoder->huffnode[nextalloc++];
433
+ newnode->parent = NULL;
434
+ node0->parent = node1->parent = newnode;
435
+ newnode->weight = node0->weight + node1->weight;
436
+
437
+ /* insert into list at appropriate location */
438
+ for (curitem = 0; curitem < listitems; curitem++)
439
+ if (newnode->weight > list[curitem]->weight)
440
+ {
441
+ memmove(&list[curitem+1], &list[curitem], (listitems - curitem) * sizeof(list[0]));
442
+ break;
443
+ }
444
+ list[curitem] = newnode;
445
+ listitems++;
446
+ }
447
+
448
+ /* compute the number of bits in each code, and fill in another histogram */
449
+ for (curcode = 0; curcode < decoder->numcodes; curcode++)
450
+ {
451
+ struct node_t *curnode;
452
+ struct node_t* node = &decoder->huffnode[curcode];
453
+ node->numbits = 0;
454
+ node->bits = 0;
455
+
456
+ /* if we have a non-zero weight, compute the number of bits */
457
+ if (node->weight > 0)
458
+ {
459
+ /* determine the number of bits for this node */
460
+ for (curnode = node; curnode->parent != NULL; curnode = curnode->parent)
461
+ node->numbits++;
462
+ if (node->numbits == 0)
463
+ node->numbits = 1;
464
+
465
+ /* keep track of the max */
466
+ maxbits = MAX(maxbits, ((int)node->numbits));
467
+ }
468
+ }
469
+ return maxbits;
470
+ }
471
+
472
+ /*-------------------------------------------------
473
+ * assign_canonical_codes - assign canonical codes
474
+ * to all the nodes based on the number of bits
475
+ * in each
476
+ *-------------------------------------------------
477
+ */
478
+
479
+ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
480
+ {
481
+ uint32_t curcode;
482
+ int codelen;
483
+ uint32_t curstart = 0;
484
+ /* build up a histogram of bit lengths */
485
+ uint32_t bithisto[33] = { 0 };
486
+ for (curcode = 0; curcode < decoder->numcodes; curcode++)
487
+ {
488
+ struct node_t* node = &decoder->huffnode[curcode];
489
+ if (node->numbits > decoder->maxbits)
490
+ return HUFFERR_INTERNAL_INCONSISTENCY;
491
+ if (node->numbits <= 32)
492
+ bithisto[node->numbits]++;
493
+ }
494
+
495
+ /* for each code length, determine the starting code number */
496
+ for (codelen = 32; codelen > 0; codelen--)
497
+ {
498
+ uint32_t nextstart = (curstart + bithisto[codelen]) >> 1;
499
+ if (codelen != 1 && nextstart * 2 != (curstart + bithisto[codelen]))
500
+ return HUFFERR_INTERNAL_INCONSISTENCY;
501
+ bithisto[codelen] = curstart;
502
+ curstart = nextstart;
503
+ }
504
+
505
+ /* now assign canonical codes */
506
+ for (curcode = 0; curcode < decoder->numcodes; curcode++)
507
+ {
508
+ struct node_t* node = &decoder->huffnode[curcode];
509
+ if (node->numbits > 0)
510
+ node->bits = bithisto[node->numbits]++;
511
+ }
512
+ return HUFFERR_NONE;
513
+ }
514
+
515
+ /*-------------------------------------------------
516
+ * build_lookup_table - build a lookup table for
517
+ * fast decoding
518
+ *-------------------------------------------------
519
+ */
520
+
521
+ void huffman_build_lookup_table(struct huffman_decoder* decoder)
522
+ {
523
+ uint32_t curcode;
524
+ /* iterate over all codes */
525
+ for (curcode = 0; curcode < decoder->numcodes; curcode++)
526
+ {
527
+ /* process all nodes which have non-zero bits */
528
+ struct node_t* node = &decoder->huffnode[curcode];
529
+ if (node->numbits > 0)
530
+ {
531
+ int shift;
532
+ lookup_value *dest;
533
+ lookup_value *destend;
534
+ /* set up the entry */
535
+ lookup_value value = MAKE_LOOKUP(curcode, node->numbits);
536
+
537
+ /* fill all matching entries */
538
+ shift = decoder->maxbits - node->numbits;
539
+ dest = &decoder->lookup[node->bits << shift];
540
+ destend = &decoder->lookup[((node->bits + 1) << shift) - 1];
541
+ while (dest <= destend)
542
+ *dest++ = value;
543
+ }
544
+ }
545
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ global: chd_*;
3
+ local: *;
4
+ };
5
+
@@ -0,0 +1,2 @@
1
+ add_executable(chdr-benchmark benchmark.c)
2
+ target_link_libraries(chdr-benchmark PRIVATE chdr-static)
@@ -0,0 +1,52 @@
1
+ #include <libchdr/chd.h>
2
+ #include <stdlib.h>
3
+ #include <stdio.h>
4
+ #include <time.h>
5
+
6
+ int main(int argc, char** argv)
7
+ {
8
+ chd_error err;
9
+ chd_file* file;
10
+ const chd_header* header;
11
+ void* buffer;
12
+ unsigned int i;
13
+ unsigned int totalbytes;
14
+ clock_t start, end;
15
+ double time_taken;
16
+
17
+ printf("\nlibchdr benchmark tool....");
18
+
19
+ /* Recording the starting clock tick.*/
20
+ start = clock();
21
+
22
+ /* Sequential read all hunks */
23
+ err = chd_open(argv[1], CHD_OPEN_READ, NULL, &file);
24
+ if (err)
25
+ {
26
+ printf("\nchd_open() error: %s", chd_error_string(err));
27
+ return 0;
28
+ }
29
+ header = chd_get_header(file);
30
+ totalbytes = header->hunkbytes * header->totalhunks;
31
+ buffer = malloc(header->hunkbytes);
32
+ for (i = 0 ; i < header->totalhunks ; i++)
33
+ {
34
+ err = chd_read(file, i, buffer);
35
+ if (err)
36
+ printf("\nchd_read() error: %s", chd_error_string(err));
37
+ }
38
+ free(buffer);
39
+ chd_close(file);
40
+
41
+ /* Recording the end clock tick. */
42
+ end = clock();
43
+
44
+ /* Calculating total time taken by the program. */
45
+ time_taken = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);
46
+
47
+ /* Print results */
48
+ printf("\nRead %d bytes in %lf seconds", totalbytes, time_taken);
49
+ printf("\nRate is %lf MB/s", (((double)totalbytes)/(1024*1024)) / time_taken);
50
+ printf("\n\n");
51
+ return 0;
52
+ }