diff --git a/examples/tgunzip/tgunzip.c b/examples/tgunzip/tgunzip.c index 0841b1e..52d05e2 100644 --- a/examples/tgunzip/tgunzip.c +++ b/examples/tgunzip/tgunzip.c @@ -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 -- */ diff --git a/src/tinf.h b/src/tinf.h index 82a6874..27fb681 100644 --- a/src/tinf.h +++ b/src/tinf.h @@ -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); diff --git a/src/tinfgzip.c b/src/tinfgzip.c index 1a16795..c13dbac 100644 --- a/src/tinfgzip.c +++ b/src/tinfgzip.c @@ -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; }