summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/mspack/qtmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/rbutilqt/mspack/qtmd.c')
-rw-r--r--rbutil/rbutilqt/mspack/qtmd.c235
1 files changed, 118 insertions, 117 deletions
diff --git a/rbutil/rbutilqt/mspack/qtmd.c b/rbutil/rbutilqt/mspack/qtmd.c
index 0fb20da167..58e4787b7f 100644
--- a/rbutil/rbutilqt/mspack/qtmd.c
+++ b/rbutil/rbutilqt/mspack/qtmd.c
@@ -27,11 +27,11 @@
27#define BITS_TYPE struct qtmd_stream 27#define BITS_TYPE struct qtmd_stream
28#define BITS_VAR qtm 28#define BITS_VAR qtm
29#define BITS_ORDER_MSB 29#define BITS_ORDER_MSB
30#define READ_BYTES do { \ 30#define READ_BYTES do { \
31 unsigned char b0, b1; \ 31 unsigned char b0, b1; \
32 READ_IF_NEEDED; b0 = *i_ptr++; \ 32 READ_IF_NEEDED; b0 = *i_ptr++; \
33 READ_IF_NEEDED; b1 = *i_ptr++; \ 33 READ_IF_NEEDED; b1 = *i_ptr++; \
34 INJECT_BITS((b0 << 8) | b1, 16); \ 34 INJECT_BITS((b0 << 8) | b1, 16); \
35} while (0) 35} while (0)
36#include "readbits.h" 36#include "readbits.h"
37 37
@@ -115,7 +115,7 @@ static const unsigned char length_extra[27] = {
115 else break; \ 115 else break; \
116 } \ 116 } \
117 L <<= 1; H = (H << 1) | 1; \ 117 L <<= 1; H = (H << 1) | 1; \
118 ENSURE_BITS(1); \ 118 ENSURE_BITS(1); \
119 C = (C << 1) | PEEK_BITS(1); \ 119 C = (C << 1) | PEEK_BITS(1); \
120 REMOVE_BITS(1); \ 120 REMOVE_BITS(1); \
121 } \ 121 } \
@@ -130,7 +130,7 @@ static void qtmd_update_model(struct qtmd_model *model) {
130 /* -1, not -2; the 0 entry saves this */ 130 /* -1, not -2; the 0 entry saves this */
131 model->syms[i].cumfreq >>= 1; 131 model->syms[i].cumfreq >>= 1;
132 if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) { 132 if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
133 model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1; 133 model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
134 } 134 }
135 } 135 }
136 } 136 }
@@ -149,11 +149,11 @@ static void qtmd_update_model(struct qtmd_model *model) {
149 * characteristics */ 149 * characteristics */
150 for (i = 0; i < model->entries - 1; i++) { 150 for (i = 0; i < model->entries - 1; i++) {
151 for (j = i + 1; j < model->entries; j++) { 151 for (j = i + 1; j < model->entries; j++) {
152 if (model->syms[i].cumfreq < model->syms[j].cumfreq) { 152 if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
153 tmp = model->syms[i]; 153 tmp = model->syms[i];
154 model->syms[i] = model->syms[j]; 154 model->syms[i] = model->syms[j];
155 model->syms[j] = tmp; 155 model->syms[j] = tmp;
156 } 156 }
157 } 157 }
158 } 158 }
159 159
@@ -166,7 +166,7 @@ static void qtmd_update_model(struct qtmd_model *model) {
166 166
167/* Initialises a model to decode symbols from [start] to [start]+[len]-1 */ 167/* Initialises a model to decode symbols from [start] to [start]+[len]-1 */
168static void qtmd_init_model(struct qtmd_model *model, 168static void qtmd_init_model(struct qtmd_model *model,
169 struct qtmd_modelsym *syms, int start, int len) 169 struct qtmd_modelsym *syms, int start, int len)
170{ 170{
171 int i; 171 int i;
172 172
@@ -184,9 +184,9 @@ static void qtmd_init_model(struct qtmd_model *model,
184/*-------- main Quantum code --------*/ 184/*-------- main Quantum code --------*/
185 185
186struct qtmd_stream *qtmd_init(struct mspack_system *system, 186struct qtmd_stream *qtmd_init(struct mspack_system *system,
187 struct mspack_file *input, 187 struct mspack_file *input,
188 struct mspack_file *output, 188 struct mspack_file *output,
189 int window_bits, int input_buffer_size) 189 int window_bits, int input_buffer_size)
190{ 190{
191 unsigned int window_size = 1 << window_bits; 191 unsigned int window_size = 1 << window_bits;
192 struct qtmd_stream *qtm; 192 struct qtmd_stream *qtm;
@@ -197,6 +197,7 @@ struct qtmd_stream *qtmd_init(struct mspack_system *system,
197 /* Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */ 197 /* Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
198 if (window_bits < 10 || window_bits > 21) return NULL; 198 if (window_bits < 10 || window_bits > 21) return NULL;
199 199
200 /* round up input buffer size to multiple of two */
200 input_buffer_size = (input_buffer_size + 1) & -2; 201 input_buffer_size = (input_buffer_size + 1) & -2;
201 if (input_buffer_size < 2) return NULL; 202 if (input_buffer_size < 2) return NULL;
202 203
@@ -307,113 +308,113 @@ int qtmd_decompress(struct qtmd_stream *qtm, off_t out_bytes) {
307 while (window_posn < frame_end) { 308 while (window_posn < frame_end) {
308 GET_SYMBOL(qtm->model7, selector); 309 GET_SYMBOL(qtm->model7, selector);
309 if (selector < 4) { 310 if (selector < 4) {
310 /* literal byte */ 311 /* literal byte */
311 struct qtmd_model *mdl = (selector == 0) ? &qtm->model0 : 312 struct qtmd_model *mdl = (selector == 0) ? &qtm->model0 :
312 ((selector == 1) ? &qtm->model1 : 313 ((selector == 1) ? &qtm->model1 :
313 ((selector == 2) ? &qtm->model2 : 314 ((selector == 2) ? &qtm->model2 :
314 &qtm->model3)); 315 &qtm->model3));
315 GET_SYMBOL((*mdl), sym); 316 GET_SYMBOL((*mdl), sym);
316 window[window_posn++] = sym; 317 window[window_posn++] = sym;
317 frame_todo--; 318 frame_todo--;
318 } 319 }
319 else { 320 else {
320 /* match repeated string */ 321 /* match repeated string */
321 switch (selector) { 322 switch (selector) {
322 case 4: /* selector 4 = fixed length match (3 bytes) */ 323 case 4: /* selector 4 = fixed length match (3 bytes) */
323 GET_SYMBOL(qtm->model4, sym); 324 GET_SYMBOL(qtm->model4, sym);
324 READ_MANY_BITS(extra, extra_bits[sym]); 325 READ_MANY_BITS(extra, extra_bits[sym]);
325 match_offset = position_base[sym] + extra + 1; 326 match_offset = position_base[sym] + extra + 1;
326 match_length = 3; 327 match_length = 3;
327 break; 328 break;
328 329
329 case 5: /* selector 5 = fixed length match (4 bytes) */ 330 case 5: /* selector 5 = fixed length match (4 bytes) */
330 GET_SYMBOL(qtm->model5, sym); 331 GET_SYMBOL(qtm->model5, sym);
331 READ_MANY_BITS(extra, extra_bits[sym]); 332 READ_MANY_BITS(extra, extra_bits[sym]);
332 match_offset = position_base[sym] + extra + 1; 333 match_offset = position_base[sym] + extra + 1;
333 match_length = 4; 334 match_length = 4;
334 break; 335 break;
335 336
336 case 6: /* selector 6 = variable length match */ 337 case 6: /* selector 6 = variable length match */
337 GET_SYMBOL(qtm->model6len, sym); 338 GET_SYMBOL(qtm->model6len, sym);
338 READ_MANY_BITS(extra, length_extra[sym]); 339 READ_MANY_BITS(extra, length_extra[sym]);
339 match_length = length_base[sym] + extra + 5; 340 match_length = length_base[sym] + extra + 5;
340 341
341 GET_SYMBOL(qtm->model6, sym); 342 GET_SYMBOL(qtm->model6, sym);
342 READ_MANY_BITS(extra, extra_bits[sym]); 343 READ_MANY_BITS(extra, extra_bits[sym]);
343 match_offset = position_base[sym] + extra + 1; 344 match_offset = position_base[sym] + extra + 1;
344 break; 345 break;
345 346
346 default: 347 default:
347 /* should be impossible, model7 can only return 0-6 */ 348 /* should be impossible, model7 can only return 0-6 */
348 D(("got %d from selector", selector)) 349 D(("got %d from selector", selector))
349 return qtm->error = MSPACK_ERR_DECRUNCH; 350 return qtm->error = MSPACK_ERR_DECRUNCH;
350 } 351 }
351 352
352 rundest = &window[window_posn]; 353 rundest = &window[window_posn];
353 frame_todo -= match_length; 354 frame_todo -= match_length;
354 355
355 /* does match destination wrap the window? This situation is possible 356 /* does match destination wrap the window? This situation is possible
356 * where the window size is less than the 32k frame size, but matches 357 * where the window size is less than the 32k frame size, but matches
357 * must not go beyond a frame boundary */ 358 * must not go beyond a frame boundary */
358 if ((window_posn + match_length) > qtm->window_size) { 359 if ((window_posn + match_length) > qtm->window_size) {
359 /* copy first part of match, before window end */ 360 /* copy first part of match, before window end */
360 i = qtm->window_size - window_posn; 361 i = qtm->window_size - window_posn;
361 j = window_posn - match_offset; 362 j = window_posn - match_offset;
362 while (i--) *rundest++ = window[j++ & (qtm->window_size - 1)]; 363 while (i--) *rundest++ = window[j++ & (qtm->window_size - 1)];
363 364
364 /* flush currently stored data */ 365 /* flush currently stored data */
365 i = (&window[qtm->window_size] - qtm->o_ptr); 366 i = (&window[qtm->window_size] - qtm->o_ptr);
366 367
367 /* this should not happen, but if it does then this code 368 /* this should not happen, but if it does then this code
368 * can't handle the situation (can't flush up to the end of 369 * can't handle the situation (can't flush up to the end of
369 * the window, but can't break out either because we haven't 370 * the window, but can't break out either because we haven't
370 * finished writing the match). bail out in this case */ 371 * finished writing the match). bail out in this case */
371 if (i > out_bytes) { 372 if (i > out_bytes) {
372 D(("during window-wrap match; %d bytes to flush but only need %d", 373 D(("during window-wrap match; %d bytes to flush but only need %d",
373 i, (int) out_bytes)) 374 i, (int) out_bytes))
374 return qtm->error = MSPACK_ERR_DECRUNCH; 375 return qtm->error = MSPACK_ERR_DECRUNCH;
375 } 376 }
376 if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) { 377 if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) {
377 return qtm->error = MSPACK_ERR_WRITE; 378 return qtm->error = MSPACK_ERR_WRITE;
378 } 379 }
379 out_bytes -= i; 380 out_bytes -= i;
380 qtm->o_ptr = &window[0]; 381 qtm->o_ptr = &window[0];
381 qtm->o_end = &window[0]; 382 qtm->o_end = &window[0];
382 383
383 /* copy second part of match, after window wrap */ 384 /* copy second part of match, after window wrap */
384 rundest = &window[0]; 385 rundest = &window[0];
385 i = match_length - (qtm->window_size - window_posn); 386 i = match_length - (qtm->window_size - window_posn);
386 while (i--) *rundest++ = window[j++ & (qtm->window_size - 1)]; 387 while (i--) *rundest++ = window[j++ & (qtm->window_size - 1)];
387 window_posn = window_posn + match_length - qtm->window_size; 388 window_posn = window_posn + match_length - qtm->window_size;
388 389
389 break; /* because "window_posn < frame_end" has now failed */ 390 break; /* because "window_posn < frame_end" has now failed */
390 } 391 }
391 else { 392 else {
392 /* normal match - output won't wrap window or frame end */ 393 /* normal match - output won't wrap window or frame end */
393 i = match_length; 394 i = match_length;
394 395
395 /* does match _offset_ wrap the window? */ 396 /* does match _offset_ wrap the window? */
396 if (match_offset > window_posn) { 397 if (match_offset > window_posn) {
397 /* j = length from match offset to end of window */ 398 /* j = length from match offset to end of window */
398 j = match_offset - window_posn; 399 j = match_offset - window_posn;
399 if (j > (int) qtm->window_size) { 400 if (j > (int) qtm->window_size) {
400 D(("match offset beyond window boundaries")) 401 D(("match offset beyond window boundaries"))
401 return qtm->error = MSPACK_ERR_DECRUNCH; 402 return qtm->error = MSPACK_ERR_DECRUNCH;
402 } 403 }
403 runsrc = &window[qtm->window_size - j]; 404 runsrc = &window[qtm->window_size - j];
404 if (j < i) { 405 if (j < i) {
405 /* if match goes over the window edge, do two copy runs */ 406 /* if match goes over the window edge, do two copy runs */
406 i -= j; while (j-- > 0) *rundest++ = *runsrc++; 407 i -= j; while (j-- > 0) *rundest++ = *runsrc++;
407 runsrc = window; 408 runsrc = window;
408 } 409 }
409 while (i-- > 0) *rundest++ = *runsrc++; 410 while (i-- > 0) *rundest++ = *runsrc++;
410 } 411 }
411 else { 412 else {
412 runsrc = rundest - match_offset; 413 runsrc = rundest - match_offset;
413 while (i-- > 0) *rundest++ = *runsrc++; 414 while (i-- > 0) *rundest++ = *runsrc++;
414 } 415 }
415 window_posn += match_length; 416 window_posn += match_length;
416 } 417 }
417 } /* if (window_posn+match_length > frame_end) */ 418 } /* if (window_posn+match_length > frame_end) */
418 } /* while (window_posn < frame_end) */ 419 } /* while (window_posn < frame_end) */
419 420
@@ -448,7 +449,7 @@ int qtmd_decompress(struct qtmd_stream *qtm, off_t out_bytes) {
448 /* break out if we have more than enough to finish this request */ 449 /* break out if we have more than enough to finish this request */
449 if (i >= out_bytes) break; 450 if (i >= out_bytes) break;
450 if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) { 451 if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) {
451 return qtm->error = MSPACK_ERR_WRITE; 452 return qtm->error = MSPACK_ERR_WRITE;
452 } 453 }
453 out_bytes -= i; 454 out_bytes -= i;
454 qtm->o_ptr = &window[0]; 455 qtm->o_ptr = &window[0];