/* given a data stream and a tree, decode a symbol */ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) { int sum = 0, cur = 0, len = 0; /* get more bits while code value is above sum */ do { cur = 2*cur + tinf_getbit(d); if (++len == TINF_ARRAY_SIZE(t->table)) { return TINF_DATA_ERROR; } sum += t->table[len]; cur -= t->table[len]; } while (cur >= 0); sum += cur; if (sum < 0 || sum >= (int)(TINF_ARRAY_SIZE(t->trans))) { return TINF_DATA_ERROR; } return t->trans[sum]; }
/* inflate next byte of compressed stream */ int uzlib_uncompress(TINF_DATA *d) { do { int res; /* start a new block */ if (d->btype == -1) { next_blk: /* read final block flag */ d->bfinal = tinf_getbit(d); /* read block type (2 bits) */ d->btype = tinf_read_bits(d, 2, 0); //printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal); if (d->btype == 1) { /* build fixed huffman trees */ tinf_build_fixed_trees(&d->ltree, &d->dtree); } else if (d->btype == 2) { /* decode trees from stream */ res = tinf_decode_trees(d, &d->ltree, &d->dtree); if (res != TINF_OK) { return res; } } } /* process current block */ switch (d->btype) { case 0: /* decompress uncompressed block */ res = tinf_inflate_uncompressed_block(d); break; case 1: case 2: /* decompress block with fixed/dynamic huffman trees */ /* trees were decoded previously, so it's the same routine for both */ res = tinf_inflate_block_data(d, &d->ltree, &d->dtree); break; default: return TINF_DATA_ERROR; } if (res == TINF_DONE && !d->bfinal) { /* the block has ended (without producing more data), but we can't return without data, so start procesing next block */ goto next_blk; } if (res != TINF_OK) { return res; } } while (--d->destSize); return TINF_OK; }
/* inflate stream from source to dest */ int tinf_uncompress(void *dest, unsigned int *destLen, const void *source, unsigned int sourceLen) { TINF_DATA d; int bfinal; d.source = (const unsigned char *)source; d.bitcount = 0; d.dest = (unsigned char *)dest; d.destLen = destLen; *destLen = 0; do { unsigned int btype; int res; /* read final block flag */ bfinal = tinf_getbit(&d); /* read block type (2 bits) */ btype = tinf_read_bits(&d, 2, 0); /* decompress block */ switch (btype) { case 0: /* decompress uncompressed block */ res = tinf_inflate_uncompressed_block(&d); break; case 1: /* decompress block with fixed huffman trees */ res = tinf_inflate_fixed_block(&d,&tbl); break; case 2: /* decompress block with dynamic huffman trees */ res = tinf_inflate_dynamic_block(&d,&tbl); break; default: return TINF_DATA_ERROR; } if (res != TINF_OK) return TINF_DATA_ERROR; if (d.source > (unsigned char *)source + sourceLen) return TINF_DATA_ERROR; } while (!bfinal); return TINF_OK; }
/* inflate stream from source to dest */ int tinf_uncompress(void *dest, unsigned int *destLen, const void *source, unsigned int sourceLen, const unsigned int swapped_btype[3]) { TINF_DATA d; int bfinal; /* initialise data */ d.source = (const unsigned char *)source; d.bitcount = 0; d.dest = (unsigned char *)dest; d.destLen = destLen; d.sourceLen = 0; d.sourceSize = sourceLen; d.destSize = *destLen; *destLen = 0; do { unsigned int btype; int res; /* read final block flag */ bfinal = tinf_getbit(&d); /* read block type (2 bits) */ btype = tinf_read_bits(&d, 2, 0); /* decompress block */ if(btype == swapped_btype[0]) { /* decompress uncompressed block */ res = tinf_inflate_uncompressed_block(&d); } else if(btype == swapped_btype[1]) { /* decompress block with fixed huffman trees */ res = tinf_inflate_fixed_block(&d); } else if(btype == swapped_btype[2]) { /* decompress block with dynamic huffman trees */ res = tinf_inflate_dynamic_block(&d); } else { return TINF_DATA_ERROR; } if (res != TINF_OK) return TINF_DATA_ERROR; } while (!bfinal); return TINF_OK; }
/* inflate stream from source to dest */ int tinf_uncompress(void *dest, unsigned int *destLen, const void *source, unsigned int sourceLen) { TINF_DATA d; int bfinal; /* initialise data */ d.source = (const unsigned char *)source; d.bitcount = 0; d.dest = (unsigned char *)dest; d.destLen = destLen; *destLen = 0; do { unsigned int btype; int res; /* read block type (2 bits) */ btype = tinf_read_bits(&d, 3, 0); /* read final block flag */ bfinal = tinf_getbit(&d); /* decompress block */ switch (btype) { case 7: /* decompress uncompressed block */ res = tinf_inflate_uncompressed_block(&d); break; case 5: /* decompress block with fixed huffman trees */ res = tinf_inflate_fixed_block(&d); break; case 6: /* decompress block with dynamic huffman trees */ res = tinf_inflate_dynamic_block(&d); break; default: return -1; } if (res != TINF_OK) return -1; } while (!bfinal); return ((char*)d.source - (char *)source); }
/* read a num bit value from a stream and add base */ static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base) { unsigned int val = 0; /* read num bits */ if (num) { unsigned int limit = 1 << (num); unsigned int mask; for (mask = 1; mask < limit; mask *= 2) if (tinf_getbit(d)) val += mask; } return val + base; }
/* given a data stream and a tree, decode a symbol */ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) { int sum = 0, cur = 0, len = 0; /* get more bits while code value is above sum */ do { cur = 2*cur + tinf_getbit(d); ++len; sum += t->table[len]; cur -= t->table[len]; } while (cur >= 0); return t->trans[sum + cur]; }