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:
parent
dd802431ad
commit
fbf79b5188
3 changed files with 64 additions and 35 deletions
|
|
@ -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 -- */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue