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