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