tinfgzip: Rewrite in terms of (new) tinf_uncompress_dyn().

tinf_gzip_uncompress() is gone, and replaced with 2 functions to parse
gzip header/trailer. The core decompression routine is tinf_uncompress_dyn,
and client code is expected to call it itself.
This commit is contained in:
Paul Sokolovsky 2016-08-03 02:03:00 +03:00
parent dd802431ad
commit fbf79b5188
3 changed files with 64 additions and 35 deletions

View file

@ -46,7 +46,8 @@ int main(int argc, char *argv[])
{
FILE *fin, *fout;
unsigned int len, dlen, outlen;
unsigned char *source, *dest;
const unsigned char *source;
unsigned char *dest;
int res;
printf("tgunzip - example from the tiny inflate library (www.ibsensoftware.com)\n\n");
@ -80,7 +81,7 @@ int main(int argc, char *argv[])
if (source == NULL) exit_error("memory");
if (fread(source, 1, len, fin) != len) exit_error("read");
if (fread((unsigned char*)source, 1, len, fin) != len) exit_error("read");
fclose(fin);
@ -99,11 +100,42 @@ int main(int argc, char *argv[])
outlen = dlen;
res = tinf_gzip_uncompress(dest, &outlen, source, len);
TINF_DATA d;
TINF_GZIP_INFO gz;
if ((res != TINF_OK) || (outlen != dlen)) exit_error("inflate");
res = tinf_gzip_parse_header(&gz, &source, 0);
if (res != TINF_OK) {
printf("Error parsing header: %d\n", res);
exit(1);
}
printf("decompressed %u bytes\n", outlen);
// tinf_uncompress_dyn_init(&d, malloc(32768), 32768);
tinf_uncompress_dyn_init(&d, NULL, 0);
d.source = source;
d.dest = dest;
/* decompress byte by byte; can be any other length */
d.destSize = 1;
do {
res = tinf_uncompress_dyn(&d);
} while (res == TINF_OK);
if (res != TINF_DONE) {
printf("Error during decompression: %d\n", res);
}
printf("decompressed %lu bytes\n", d.dest - dest);
res = tinf_gzip_parse_trailer(&gz, &d.source, 0);
if (d.dest - dest != gz.dlen) {
printf("Invalid decompressed length: %lu vs %u\n", d.dest - dest, gz.dlen);
}
if (tinf_crc32(dest, gz.dlen) != gz.crc32) {
printf("Invalid decompressed crc32\n");
}
/* -- write output -- */

View file

@ -99,8 +99,13 @@ void TINFCC tinf_init(void);
int TINFCC tinf_uncompress(TINF_DATA *d, void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
int TINFCC tinf_gzip_uncompress(TINF_DATA *d, void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
typedef struct TINF_GZIP_INFO {
unsigned int dlen;
unsigned int crc32;
} TINF_GZIP_INFO;
int tinf_gzip_parse_header(TINF_GZIP_INFO *gz, const unsigned char **source, unsigned int sourceLen);
int tinf_gzip_parse_trailer(TINF_GZIP_INFO *gz, const unsigned char **source, unsigned int sourceLen);
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);

View file

@ -39,14 +39,10 @@
#define FNAME 8
#define FCOMMENT 16
int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
int tinf_gzip_parse_header(TINF_GZIP_INFO *gz, const unsigned char **source, unsigned int sourceLen)
{
unsigned char *src = (unsigned char *)source;
unsigned char *dst = (unsigned char *)dest;
unsigned char *start;
unsigned int dlen, crc32;
int res;
const unsigned char *src = *source;
const unsigned char *start;
unsigned char flg;
/* -- check format -- */
@ -94,31 +90,27 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
start += 2;
}
/* -- get decompressed length -- */
*source = start;
return TINF_OK;
}
dlen = src[sourceLen - 1];
dlen = 256*dlen + src[sourceLen - 2];
dlen = 256*dlen + src[sourceLen - 3];
dlen = 256*dlen + src[sourceLen - 4];
int tinf_gzip_parse_trailer(TINF_GZIP_INFO *gz, const unsigned char **source, unsigned int sourceLen) {
unsigned int dlen, crc32;
const unsigned char *src = *source;
dlen = src[7];
dlen = 256*dlen + src[6];
dlen = 256*dlen + src[5];
dlen = 256*dlen + src[4];
/* -- get crc32 of decompressed data -- */
crc32 = src[sourceLen - 5];
crc32 = 256*crc32 + src[sourceLen - 6];
crc32 = 256*crc32 + src[sourceLen - 7];
crc32 = 256*crc32 + src[sourceLen - 8];
/* -- decompress data -- */
res = tinf_uncompress(dst, destLen, start, src + sourceLen - start - 8);
if (res != TINF_OK) return TINF_DATA_ERROR;
if (*destLen != dlen) return TINF_DATA_ERROR;
/* -- check CRC32 checksum -- */
if (crc32 != tinf_crc32(dst, dlen)) return TINF_DATA_ERROR;
crc32 = src[3];
crc32 = 256*crc32 + src[2];
crc32 = 256*crc32 + src[1];
crc32 = 256*crc32 + src[0];
gz->dlen = dlen;
gz->crc32 = crc32;
return TINF_OK;
}