chd 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }