tinflate: Support either stream or inplace uncompress mode.

If tinf_uncompress_dyn_init() called with NULL dictionary, inplace mode will
be active. Output will still be produced in chunks of .destSize, but any
data written to .dest pointer should remain there (and the pointer itself
should not be touched after initialization).
This commit is contained in:
Paul Sokolovsky 2016-08-03 01:49:52 +03:00
parent 9daa35b843
commit dd802431ad
2 changed files with 19 additions and 7 deletions

View file

@ -73,7 +73,10 @@ typedef struct TINF_DATA {
} TINF_DATA;
#define TINF_PUT(d, c) \
{ *d->dest++ = c; d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; }
{ \
*d->dest++ = c; \
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
}
/* low-level API */

View file

@ -349,16 +349,25 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
dist = tinf_decode_symbol(d, dt);
/* possibly get more bits from distance code */
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
d->lzOff = d->dict_idx - offs;
if (d->lzOff < 0) {
d->lzOff += d->dict_size;
if (d->dict_ring) {
d->lzOff = d->dict_idx - offs;
if (d->lzOff < 0) {
d->lzOff += d->dict_size;
}
} else {
d->lzOff = -offs;
}
}
/* copy next byte from dict substring */
TINF_PUT(d, d->dict_ring[d->lzOff]);
if (++d->lzOff == d->dict_size) {
d->lzOff = 0;
if (d->dict_ring) {
TINF_PUT(d, d->dict_ring[d->lzOff]);
if (++d->lzOff == d->dict_size) {
d->lzOff = 0;
}
} else {
d->dest[0] = d->dest[d->lzOff];
d->dest++;
}
d->curlen--;
return TINF_OK;