diff options
Diffstat (limited to 'rbutil/rbutilqt/mspack/qtmd.c')
-rw-r--r-- | rbutil/rbutilqt/mspack/qtmd.c | 235 |
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 */ |
168 | static void qtmd_init_model(struct qtmd_model *model, | 168 | static 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 | ||
186 | struct qtmd_stream *qtmd_init(struct mspack_system *system, | 186 | struct 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]; |