Home | History | Annotate | Download | only in zlib
      1 /* example.c -- usage example of the zlib compression library
      2  * Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
      3  * For conditions of distribution and use, see copyright notice in zlib.h
      4  */
      5 
      6 /* @(#) $Id$ */
      7 
      8 #include "zlib.h"
      9 #include <stdio.h>
     10 
     11 #ifdef STDC
     12 #  include <string.h>
     13 #  include <stdlib.h>
     14 #endif
     15 
     16 #if defined(VMS) || defined(RISCOS)
     17 #  define TESTFILE "foo-gz"
     18 #else
     19 #  define TESTFILE "foo.gz"
     20 #endif
     21 
     22 #define CHECK_ERR(err, msg) { \
     23     if (err != Z_OK) { \
     24         fprintf(stderr, "%s error: %d\n", msg, err); \
     25         exit(1); \
     26     } \
     27 }
     28 
     29 z_const char hello[] = "hello, hello!";
     30 /* "hello world" would be more standard, but the repeated "hello"
     31  * stresses the compression code better, sorry...
     32  */
     33 
     34 const char dictionary[] = "hello";
     35 uLong dictId; /* Adler32 value of the dictionary */
     36 
     37 void test_deflate       OF((Byte *compr, uLong comprLen));
     38 void test_inflate       OF((Byte *compr, uLong comprLen,
     39                             Byte *uncompr, uLong uncomprLen));
     40 void test_large_deflate OF((Byte *compr, uLong comprLen,
     41                             Byte *uncompr, uLong uncomprLen));
     42 void test_large_inflate OF((Byte *compr, uLong comprLen,
     43                             Byte *uncompr, uLong uncomprLen));
     44 void test_flush         OF((Byte *compr, uLong *comprLen));
     45 void test_sync          OF((Byte *compr, uLong comprLen,
     46                             Byte *uncompr, uLong uncomprLen));
     47 void test_dict_deflate  OF((Byte *compr, uLong comprLen));
     48 void test_dict_inflate  OF((Byte *compr, uLong comprLen,
     49                             Byte *uncompr, uLong uncomprLen));
     50 int  main               OF((int argc, char *argv[]));
     51 
     52 
     53 #ifdef Z_SOLO
     54 
     55 void *myalloc OF((void *, unsigned, unsigned));
     56 void myfree OF((void *, void *));
     57 
     58 void *myalloc(q, n, m)
     59     void *q;
     60     unsigned n, m;
     61 {
     62     q = Z_NULL;
     63     return calloc(n, m);
     64 }
     65 
     66 void myfree(void *q, void *p)
     67 {
     68     q = Z_NULL;
     69     free(p);
     70 }
     71 
     72 static alloc_func zalloc = myalloc;
     73 static free_func zfree = myfree;
     74 
     75 #else /* !Z_SOLO */
     76 
     77 static alloc_func zalloc = (alloc_func)0;
     78 static free_func zfree = (free_func)0;
     79 
     80 void test_compress      OF((Byte *compr, uLong comprLen,
     81                             Byte *uncompr, uLong uncomprLen));
     82 void test_gzio          OF((const char *fname,
     83                             Byte *uncompr, uLong uncomprLen));
     84 
     85 /* ===========================================================================
     86  * Test compress() and uncompress()
     87  */
     88 void test_compress(compr, comprLen, uncompr, uncomprLen)
     89     Byte *compr, *uncompr;
     90     uLong comprLen, uncomprLen;
     91 {
     92     int err;
     93     uLong len = (uLong)strlen(hello)+1;
     94 
     95     err = compress(compr, &comprLen, (const Bytef*)hello, len);
     96     CHECK_ERR(err, "compress");
     97 
     98     strcpy((char*)uncompr, "garbage");
     99 
    100     err = uncompress(uncompr, &uncomprLen, compr, comprLen);
    101     CHECK_ERR(err, "uncompress");
    102 
    103     if (strcmp((char*)uncompr, hello)) {
    104         fprintf(stderr, "bad uncompress\n");
    105         exit(1);
    106     } else {
    107         printf("uncompress(): %s\n", (char *)uncompr);
    108     }
    109 }
    110 
    111 /* ===========================================================================
    112  * Test read/write of .gz files
    113  */
    114 void test_gzio(fname, uncompr, uncomprLen)
    115     const char *fname; /* compressed file name */
    116     Byte *uncompr;
    117     uLong uncomprLen;
    118 {
    119 #ifdef NO_GZCOMPRESS
    120     fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
    121 #else
    122     int err;
    123     int len = (int)strlen(hello)+1;
    124     gzFile file;
    125     z_off_t pos;
    126 
    127     file = gzopen(fname, "wb");
    128     if (file == NULL) {
    129         fprintf(stderr, "gzopen error\n");
    130         exit(1);
    131     }
    132     gzputc(file, 'h');
    133     if (gzputs(file, "ello") != 4) {
    134         fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
    135         exit(1);
    136     }
    137     if (gzprintf(file, ", %s!", "hello") != 8) {
    138         fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
    139         exit(1);
    140     }
    141     gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
    142     gzclose(file);
    143 
    144     file = gzopen(fname, "rb");
    145     if (file == NULL) {
    146         fprintf(stderr, "gzopen error\n");
    147         exit(1);
    148     }
    149     strcpy((char*)uncompr, "garbage");
    150 
    151     if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
    152         fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
    153         exit(1);
    154     }
    155     if (strcmp((char*)uncompr, hello)) {
    156         fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
    157         exit(1);
    158     } else {
    159         printf("gzread(): %s\n", (char*)uncompr);
    160     }
    161 
    162     pos = gzseek(file, -8L, SEEK_CUR);
    163     if (pos != 6 || gztell(file) != pos) {
    164         fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
    165                 (long)pos, (long)gztell(file));
    166         exit(1);
    167     }
    168 
    169     if (gzgetc(file) != ' ') {
    170         fprintf(stderr, "gzgetc error\n");
    171         exit(1);
    172     }
    173 
    174     if (gzungetc(' ', file) != ' ') {
    175         fprintf(stderr, "gzungetc error\n");
    176         exit(1);
    177     }
    178 
    179     gzgets(file, (char*)uncompr, (int)uncomprLen);
    180     if (strlen((char*)uncompr) != 7) { /* " hello!" */
    181         fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
    182         exit(1);
    183     }
    184     if (strcmp((char*)uncompr, hello + 6)) {
    185         fprintf(stderr, "bad gzgets after gzseek\n");
    186         exit(1);
    187     } else {
    188         printf("gzgets() after gzseek: %s\n", (char*)uncompr);
    189     }
    190 
    191     gzclose(file);
    192 #endif
    193 }
    194 
    195 #endif /* Z_SOLO */
    196 
    197 /* ===========================================================================
    198  * Test deflate() with small buffers
    199  */
    200 void test_deflate(compr, comprLen)
    201     Byte *compr;
    202     uLong comprLen;
    203 {
    204     z_stream c_stream; /* compression stream */
    205     int err;
    206     uLong len = (uLong)strlen(hello)+1;
    207 
    208     c_stream.zalloc = zalloc;
    209     c_stream.zfree = zfree;
    210     c_stream.opaque = (voidpf)0;
    211 
    212     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
    213     CHECK_ERR(err, "deflateInit");
    214 
    215     c_stream.next_in  = (z_const unsigned char *)hello;
    216     c_stream.next_out = compr;
    217 
    218     while (c_stream.total_in != len && c_stream.total_out < comprLen) {
    219         c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
    220         err = deflate(&c_stream, Z_NO_FLUSH);
    221         CHECK_ERR(err, "deflate");
    222     }
    223     /* Finish the stream, still forcing small buffers: */
    224     for (;;) {
    225         c_stream.avail_out = 1;
    226         err = deflate(&c_stream, Z_FINISH);
    227         if (err == Z_STREAM_END) break;
    228         CHECK_ERR(err, "deflate");
    229     }
    230 
    231     err = deflateEnd(&c_stream);
    232     CHECK_ERR(err, "deflateEnd");
    233 }
    234 
    235 /* ===========================================================================
    236  * Test inflate() with small buffers
    237  */
    238 void test_inflate(compr, comprLen, uncompr, uncomprLen)
    239     Byte *compr, *uncompr;
    240     uLong comprLen, uncomprLen;
    241 {
    242     int err;
    243     z_stream d_stream; /* decompression stream */
    244 
    245     strcpy((char*)uncompr, "garbage");
    246 
    247     d_stream.zalloc = zalloc;
    248     d_stream.zfree = zfree;
    249     d_stream.opaque = (voidpf)0;
    250 
    251     d_stream.next_in  = compr;
    252     d_stream.avail_in = 0;
    253     d_stream.next_out = uncompr;
    254 
    255     err = inflateInit(&d_stream);
    256     CHECK_ERR(err, "inflateInit");
    257 
    258     while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
    259         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
    260         err = inflate(&d_stream, Z_NO_FLUSH);
    261         if (err == Z_STREAM_END) break;
    262         CHECK_ERR(err, "inflate");
    263     }
    264 
    265     err = inflateEnd(&d_stream);
    266     CHECK_ERR(err, "inflateEnd");
    267 
    268     if (strcmp((char*)uncompr, hello)) {
    269         fprintf(stderr, "bad inflate\n");
    270         exit(1);
    271     } else {
    272         printf("inflate(): %s\n", (char *)uncompr);
    273     }
    274 }
    275 
    276 /* ===========================================================================
    277  * Test deflate() with large buffers and dynamic change of compression level
    278  */
    279 void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
    280     Byte *compr, *uncompr;
    281     uLong comprLen, uncomprLen;
    282 {
    283     z_stream c_stream; /* compression stream */
    284     int err;
    285 
    286     c_stream.zalloc = zalloc;
    287     c_stream.zfree = zfree;
    288     c_stream.opaque = (voidpf)0;
    289 
    290     err = deflateInit(&c_stream, Z_BEST_SPEED);
    291     CHECK_ERR(err, "deflateInit");
    292 
    293     c_stream.next_out = compr;
    294     c_stream.avail_out = (uInt)comprLen;
    295 
    296     /* At this point, uncompr is still mostly zeroes, so it should compress
    297      * very well:
    298      */
    299     c_stream.next_in = uncompr;
    300     c_stream.avail_in = (uInt)uncomprLen;
    301     err = deflate(&c_stream, Z_NO_FLUSH);
    302     CHECK_ERR(err, "deflate");
    303     if (c_stream.avail_in != 0) {
    304         fprintf(stderr, "deflate not greedy\n");
    305         exit(1);
    306     }
    307 
    308     /* Feed in already compressed data and switch to no compression: */
    309     deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
    310     c_stream.next_in = compr;
    311     c_stream.avail_in = (uInt)comprLen/2;
    312     err = deflate(&c_stream, Z_NO_FLUSH);
    313     CHECK_ERR(err, "deflate");
    314 
    315     /* Switch back to compressing mode: */
    316     deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
    317     c_stream.next_in = uncompr;
    318     c_stream.avail_in = (uInt)uncomprLen;
    319     err = deflate(&c_stream, Z_NO_FLUSH);
    320     CHECK_ERR(err, "deflate");
    321 
    322     err = deflate(&c_stream, Z_FINISH);
    323     if (err != Z_STREAM_END) {
    324         fprintf(stderr, "deflate should report Z_STREAM_END\n");
    325         exit(1);
    326     }
    327     err = deflateEnd(&c_stream);
    328     CHECK_ERR(err, "deflateEnd");
    329 }
    330 
    331 /* ===========================================================================
    332  * Test inflate() with large buffers
    333  */
    334 void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
    335     Byte *compr, *uncompr;
    336     uLong comprLen, uncomprLen;
    337 {
    338     int err;
    339     z_stream d_stream; /* decompression stream */
    340 
    341     strcpy((char*)uncompr, "garbage");
    342 
    343     d_stream.zalloc = zalloc;
    344     d_stream.zfree = zfree;
    345     d_stream.opaque = (voidpf)0;
    346 
    347     d_stream.next_in  = compr;
    348     d_stream.avail_in = (uInt)comprLen;
    349 
    350     err = inflateInit(&d_stream);
    351     CHECK_ERR(err, "inflateInit");
    352 
    353     for (;;) {
    354         d_stream.next_out = uncompr;            /* discard the output */
    355         d_stream.avail_out = (uInt)uncomprLen;
    356         err = inflate(&d_stream, Z_NO_FLUSH);
    357         if (err == Z_STREAM_END) break;
    358         CHECK_ERR(err, "large inflate");
    359     }
    360 
    361     err = inflateEnd(&d_stream);
    362     CHECK_ERR(err, "inflateEnd");
    363 
    364     if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
    365         fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
    366         exit(1);
    367     } else {
    368         printf("large_inflate(): OK\n");
    369     }
    370 }
    371 
    372 /* ===========================================================================
    373  * Test deflate() with full flush
    374  */
    375 void test_flush(compr, comprLen)
    376     Byte *compr;
    377     uLong *comprLen;
    378 {
    379     z_stream c_stream; /* compression stream */
    380     int err;
    381     uInt len = (uInt)strlen(hello)+1;
    382 
    383     c_stream.zalloc = zalloc;
    384     c_stream.zfree = zfree;
    385     c_stream.opaque = (voidpf)0;
    386 
    387     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
    388     CHECK_ERR(err, "deflateInit");
    389 
    390     c_stream.next_in  = (z_const unsigned char *)hello;
    391     c_stream.next_out = compr;
    392     c_stream.avail_in = 3;
    393     c_stream.avail_out = (uInt)*comprLen;
    394     err = deflate(&c_stream, Z_FULL_FLUSH);
    395     CHECK_ERR(err, "deflate");
    396 
    397     compr[3]++; /* force an error in first compressed block */
    398     c_stream.avail_in = len - 3;
    399 
    400     err = deflate(&c_stream, Z_FINISH);
    401     if (err != Z_STREAM_END) {
    402         CHECK_ERR(err, "deflate");
    403     }
    404     err = deflateEnd(&c_stream);
    405     CHECK_ERR(err, "deflateEnd");
    406 
    407     *comprLen = c_stream.total_out;
    408 }
    409 
    410 /* ===========================================================================
    411  * Test inflateSync()
    412  */
    413 void test_sync(compr, comprLen, uncompr, uncomprLen)
    414     Byte *compr, *uncompr;
    415     uLong comprLen, uncomprLen;
    416 {
    417     int err;
    418     z_stream d_stream; /* decompression stream */
    419 
    420     strcpy((char*)uncompr, "garbage");
    421 
    422     d_stream.zalloc = zalloc;
    423     d_stream.zfree = zfree;
    424     d_stream.opaque = (voidpf)0;
    425 
    426     d_stream.next_in  = compr;
    427     d_stream.avail_in = 2; /* just read the zlib header */
    428 
    429     err = inflateInit(&d_stream);
    430     CHECK_ERR(err, "inflateInit");
    431 
    432     d_stream.next_out = uncompr;
    433     d_stream.avail_out = (uInt)uncomprLen;
    434 
    435     inflate(&d_stream, Z_NO_FLUSH);
    436     CHECK_ERR(err, "inflate");
    437 
    438     d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
    439     err = inflateSync(&d_stream);           /* but skip the damaged part */
    440     CHECK_ERR(err, "inflateSync");
    441 
    442     err = inflate(&d_stream, Z_FINISH);
    443     if (err != Z_DATA_ERROR) {
    444         fprintf(stderr, "inflate should report DATA_ERROR\n");
    445         /* Because of incorrect adler32 */
    446         exit(1);
    447     }
    448     err = inflateEnd(&d_stream);
    449     CHECK_ERR(err, "inflateEnd");
    450 
    451     printf("after inflateSync(): hel%s\n", (char *)uncompr);
    452 }
    453 
    454 /* ===========================================================================
    455  * Test deflate() with preset dictionary
    456  */
    457 void test_dict_deflate(compr, comprLen)
    458     Byte *compr;
    459     uLong comprLen;
    460 {
    461     z_stream c_stream; /* compression stream */
    462     int err;
    463 
    464     c_stream.zalloc = zalloc;
    465     c_stream.zfree = zfree;
    466     c_stream.opaque = (voidpf)0;
    467 
    468     err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
    469     CHECK_ERR(err, "deflateInit");
    470 
    471     err = deflateSetDictionary(&c_stream,
    472                 (const Bytef*)dictionary, (int)sizeof(dictionary));
    473     CHECK_ERR(err, "deflateSetDictionary");
    474 
    475     dictId = c_stream.adler;
    476     c_stream.next_out = compr;
    477     c_stream.avail_out = (uInt)comprLen;
    478 
    479     c_stream.next_in = (z_const unsigned char *)hello;
    480     c_stream.avail_in = (uInt)strlen(hello)+1;
    481 
    482     err = deflate(&c_stream, Z_FINISH);
    483     if (err != Z_STREAM_END) {
    484         fprintf(stderr, "deflate should report Z_STREAM_END\n");
    485         exit(1);
    486     }
    487     err = deflateEnd(&c_stream);
    488     CHECK_ERR(err, "deflateEnd");
    489 }
    490 
    491 /* ===========================================================================
    492  * Test inflate() with a preset dictionary
    493  */
    494 void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
    495     Byte *compr, *uncompr;
    496     uLong comprLen, uncomprLen;
    497 {
    498     int err;
    499     z_stream d_stream; /* decompression stream */
    500 
    501     strcpy((char*)uncompr, "garbage");
    502 
    503     d_stream.zalloc = zalloc;
    504     d_stream.zfree = zfree;
    505     d_stream.opaque = (voidpf)0;
    506 
    507     d_stream.next_in  = compr;
    508     d_stream.avail_in = (uInt)comprLen;
    509 
    510     err = inflateInit(&d_stream);
    511     CHECK_ERR(err, "inflateInit");
    512 
    513     d_stream.next_out = uncompr;
    514     d_stream.avail_out = (uInt)uncomprLen;
    515 
    516     for (;;) {
    517         err = inflate(&d_stream, Z_NO_FLUSH);
    518         if (err == Z_STREAM_END) break;
    519         if (err == Z_NEED_DICT) {
    520             if (d_stream.adler != dictId) {
    521                 fprintf(stderr, "unexpected dictionary");
    522                 exit(1);
    523             }
    524             err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
    525                                        (int)sizeof(dictionary));
    526         }
    527         CHECK_ERR(err, "inflate with dict");
    528     }
    529 
    530     err = inflateEnd(&d_stream);
    531     CHECK_ERR(err, "inflateEnd");
    532 
    533     if (strcmp((char*)uncompr, hello)) {
    534         fprintf(stderr, "bad inflate with dict\n");
    535         exit(1);
    536     } else {
    537         printf("inflate with dictionary: %s\n", (char *)uncompr);
    538     }
    539 }
    540 
    541 /* ===========================================================================
    542  * Usage:  example [output.gz  [input.gz]]
    543  */
    544 
    545 int main(argc, argv)
    546     int argc;
    547     char *argv[];
    548 {
    549     Byte *compr, *uncompr;
    550     uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
    551     uLong uncomprLen = comprLen;
    552     static const char* myVersion = ZLIB_VERSION;
    553 
    554     if (zlibVersion()[0] != myVersion[0]) {
    555         fprintf(stderr, "incompatible zlib version\n");
    556         exit(1);
    557 
    558     } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
    559         fprintf(stderr, "warning: different zlib version\n");
    560     }
    561 
    562     printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
    563             ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
    564 
    565     compr    = (Byte*)calloc((uInt)comprLen, 1);
    566     uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
    567     /* compr and uncompr are cleared to avoid reading uninitialized
    568      * data and to ensure that uncompr compresses well.
    569      */
    570     if (compr == Z_NULL || uncompr == Z_NULL) {
    571         printf("out of memory\n");
    572         exit(1);
    573     }
    574 
    575 #ifdef Z_SOLO
    576     argc = strlen(argv[0]);
    577 #else
    578     test_compress(compr, comprLen, uncompr, uncomprLen);
    579 
    580     test_gzio((argc > 1 ? argv[1] : TESTFILE),
    581               uncompr, uncomprLen);
    582 #endif
    583 
    584     test_deflate(compr, comprLen);
    585     test_inflate(compr, comprLen, uncompr, uncomprLen);
    586 
    587     test_large_deflate(compr, comprLen, uncompr, uncomprLen);
    588     test_large_inflate(compr, comprLen, uncompr, uncomprLen);
    589 
    590     test_flush(compr, &comprLen);
    591     test_sync(compr, comprLen, uncompr, uncomprLen);
    592     comprLen = uncomprLen;
    593 
    594     test_dict_deflate(compr, comprLen);
    595     test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
    596 
    597     free(compr);
    598     free(uncompr);
    599 
    600     return 0;
    601 }
    602