From dd802431adb13a0c7bd5ae23bd1df58f2551d7c2 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 3 Aug 2016 01:49:52 +0300 Subject: [PATCH] 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). --- src/tinf.h | 5 ++++- src/tinflate.c | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/tinf.h b/src/tinf.h index e42c8f2..82a6874 100644 --- a/src/tinf.h +++ b/src/tinf.h @@ -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 */ diff --git a/src/tinflate.c b/src/tinflate.c index 11e05be..d7efdc0 100644 --- a/src/tinflate.c +++ b/src/tinflate.c @@ -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;