Back to index

lightning-sunbird  0.9+nobinonly
example.c
Go to the documentation of this file.
00001 /* example.c -- usage example of the zlib compression library
00002  * Copyright (C) 1995-2004 Jean-loup Gailly.
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 /* @(#) $Id: example.c,v 1.5 2005/07/20 20:32:42 wtchang%redhat.com Exp $ */
00007 
00008 #include <stdio.h>
00009 #include "zlib.h"
00010 
00011 #ifdef STDC
00012 #  include <string.h>
00013 #  include <stdlib.h>
00014 #endif
00015 
00016 #if defined(VMS) || defined(RISCOS)
00017 #  define TESTFILE "foo-gz"
00018 #else
00019 #  define TESTFILE "foo.gz"
00020 #endif
00021 
00022 #define CHECK_ERR(err, msg) { \
00023     if (err != Z_OK) { \
00024         fprintf(stderr, "%s error: %d\n", msg, err); \
00025         exit(1); \
00026     } \
00027 }
00028 
00029 const char hello[] = "hello, hello!";
00030 /* "hello world" would be more standard, but the repeated "hello"
00031  * stresses the compression code better, sorry...
00032  */
00033 
00034 const char dictionary[] = "hello";
00035 uLong dictId; /* Adler32 value of the dictionary */
00036 
00037 void test_compress      OF((Byte *compr, uLong comprLen,
00038                             Byte *uncompr, uLong uncomprLen));
00039 void test_gzio          OF((const char *fname,
00040                             Byte *uncompr, uLong uncomprLen));
00041 void test_deflate       OF((Byte *compr, uLong comprLen));
00042 void test_inflate       OF((Byte *compr, uLong comprLen,
00043                             Byte *uncompr, uLong uncomprLen));
00044 void test_large_deflate OF((Byte *compr, uLong comprLen,
00045                             Byte *uncompr, uLong uncomprLen));
00046 void test_large_inflate OF((Byte *compr, uLong comprLen,
00047                             Byte *uncompr, uLong uncomprLen));
00048 void test_flush         OF((Byte *compr, uLong *comprLen));
00049 void test_sync          OF((Byte *compr, uLong comprLen,
00050                             Byte *uncompr, uLong uncomprLen));
00051 void test_dict_deflate  OF((Byte *compr, uLong comprLen));
00052 void test_dict_inflate  OF((Byte *compr, uLong comprLen,
00053                             Byte *uncompr, uLong uncomprLen));
00054 int  main               OF((int argc, char *argv[]));
00055 
00056 /* ===========================================================================
00057  * Test compress() and uncompress()
00058  */
00059 void test_compress(compr, comprLen, uncompr, uncomprLen)
00060     Byte *compr, *uncompr;
00061     uLong comprLen, uncomprLen;
00062 {
00063     int err;
00064     uLong len = (uLong)strlen(hello)+1;
00065 
00066     err = compress(compr, &comprLen, (const Bytef*)hello, len);
00067     CHECK_ERR(err, "compress");
00068 
00069     strcpy((char*)uncompr, "garbage");
00070 
00071     err = uncompress(uncompr, &uncomprLen, compr, comprLen);
00072     CHECK_ERR(err, "uncompress");
00073 
00074     if (strcmp((char*)uncompr, hello)) {
00075         fprintf(stderr, "bad uncompress\n");
00076         exit(1);
00077     } else {
00078         printf("uncompress(): %s\n", (char *)uncompr);
00079     }
00080 }
00081 
00082 /* ===========================================================================
00083  * Test read/write of .gz files
00084  */
00085 void test_gzio(fname, uncompr, uncomprLen)
00086     const char *fname; /* compressed file name */
00087     Byte *uncompr;
00088     uLong uncomprLen;
00089 {
00090 #ifdef NO_GZCOMPRESS
00091     fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
00092 #else
00093     int err;
00094     int len = (int)strlen(hello)+1;
00095     gzFile file;
00096     z_off_t pos;
00097 
00098     file = gzopen(fname, "wb");
00099     if (file == NULL) {
00100         fprintf(stderr, "gzopen error\n");
00101         exit(1);
00102     }
00103     gzputc(file, 'h');
00104     if (gzputs(file, "ello") != 4) {
00105         fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
00106         exit(1);
00107     }
00108     if (gzprintf(file, ", %s!", "hello") != 8) {
00109         fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
00110         exit(1);
00111     }
00112     gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
00113     gzclose(file);
00114 
00115     file = gzopen(fname, "rb");
00116     if (file == NULL) {
00117         fprintf(stderr, "gzopen error\n");
00118         exit(1);
00119     }
00120     strcpy((char*)uncompr, "garbage");
00121 
00122     if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
00123         fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
00124         exit(1);
00125     }
00126     if (strcmp((char*)uncompr, hello)) {
00127         fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
00128         exit(1);
00129     } else {
00130         printf("gzread(): %s\n", (char*)uncompr);
00131     }
00132 
00133     pos = gzseek(file, -8L, SEEK_CUR);
00134     if (pos != 6 || gztell(file) != pos) {
00135         fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
00136                 (long)pos, (long)gztell(file));
00137         exit(1);
00138     }
00139 
00140     if (gzgetc(file) != ' ') {
00141         fprintf(stderr, "gzgetc error\n");
00142         exit(1);
00143     }
00144 
00145     if (gzungetc(' ', file) != ' ') {
00146         fprintf(stderr, "gzungetc error\n");
00147         exit(1);
00148     }
00149 
00150     gzgets(file, (char*)uncompr, (int)uncomprLen);
00151     if (strlen((char*)uncompr) != 7) { /* " hello!" */
00152         fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
00153         exit(1);
00154     }
00155     if (strcmp((char*)uncompr, hello + 6)) {
00156         fprintf(stderr, "bad gzgets after gzseek\n");
00157         exit(1);
00158     } else {
00159         printf("gzgets() after gzseek: %s\n", (char*)uncompr);
00160     }
00161 
00162     gzclose(file);
00163 #endif
00164 }
00165 
00166 /* ===========================================================================
00167  * Test deflate() with small buffers
00168  */
00169 void test_deflate(compr, comprLen)
00170     Byte *compr;
00171     uLong comprLen;
00172 {
00173     z_stream c_stream; /* compression stream */
00174     int err;
00175     uLong len = (uLong)strlen(hello)+1;
00176 
00177     c_stream.zalloc = (alloc_func)0;
00178     c_stream.zfree = (free_func)0;
00179     c_stream.opaque = (voidpf)0;
00180 
00181     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
00182     CHECK_ERR(err, "deflateInit");
00183 
00184     c_stream.next_in  = (Bytef*)hello;
00185     c_stream.next_out = compr;
00186 
00187     while (c_stream.total_in != len && c_stream.total_out < comprLen) {
00188         c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
00189         err = deflate(&c_stream, Z_NO_FLUSH);
00190         CHECK_ERR(err, "deflate");
00191     }
00192     /* Finish the stream, still forcing small buffers: */
00193     for (;;) {
00194         c_stream.avail_out = 1;
00195         err = deflate(&c_stream, Z_FINISH);
00196         if (err == Z_STREAM_END) break;
00197         CHECK_ERR(err, "deflate");
00198     }
00199 
00200     err = deflateEnd(&c_stream);
00201     CHECK_ERR(err, "deflateEnd");
00202 }
00203 
00204 /* ===========================================================================
00205  * Test inflate() with small buffers
00206  */
00207 void test_inflate(compr, comprLen, uncompr, uncomprLen)
00208     Byte *compr, *uncompr;
00209     uLong comprLen, uncomprLen;
00210 {
00211     int err;
00212     z_stream d_stream; /* decompression stream */
00213 
00214     strcpy((char*)uncompr, "garbage");
00215 
00216     d_stream.zalloc = (alloc_func)0;
00217     d_stream.zfree = (free_func)0;
00218     d_stream.opaque = (voidpf)0;
00219 
00220     d_stream.next_in  = compr;
00221     d_stream.avail_in = 0;
00222     d_stream.next_out = uncompr;
00223 
00224     err = inflateInit(&d_stream);
00225     CHECK_ERR(err, "inflateInit");
00226 
00227     while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
00228         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
00229         err = inflate(&d_stream, Z_NO_FLUSH);
00230         if (err == Z_STREAM_END) break;
00231         CHECK_ERR(err, "inflate");
00232     }
00233 
00234     err = inflateEnd(&d_stream);
00235     CHECK_ERR(err, "inflateEnd");
00236 
00237     if (strcmp((char*)uncompr, hello)) {
00238         fprintf(stderr, "bad inflate\n");
00239         exit(1);
00240     } else {
00241         printf("inflate(): %s\n", (char *)uncompr);
00242     }
00243 }
00244 
00245 /* ===========================================================================
00246  * Test deflate() with large buffers and dynamic change of compression level
00247  */
00248 void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
00249     Byte *compr, *uncompr;
00250     uLong comprLen, uncomprLen;
00251 {
00252     z_stream c_stream; /* compression stream */
00253     int err;
00254 
00255     c_stream.zalloc = (alloc_func)0;
00256     c_stream.zfree = (free_func)0;
00257     c_stream.opaque = (voidpf)0;
00258 
00259     err = deflateInit(&c_stream, Z_BEST_SPEED);
00260     CHECK_ERR(err, "deflateInit");
00261 
00262     c_stream.next_out = compr;
00263     c_stream.avail_out = (uInt)comprLen;
00264 
00265     /* At this point, uncompr is still mostly zeroes, so it should compress
00266      * very well:
00267      */
00268     c_stream.next_in = uncompr;
00269     c_stream.avail_in = (uInt)uncomprLen;
00270     err = deflate(&c_stream, Z_NO_FLUSH);
00271     CHECK_ERR(err, "deflate");
00272     if (c_stream.avail_in != 0) {
00273         fprintf(stderr, "deflate not greedy\n");
00274         exit(1);
00275     }
00276 
00277     /* Feed in already compressed data and switch to no compression: */
00278     deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
00279     c_stream.next_in = compr;
00280     c_stream.avail_in = (uInt)comprLen/2;
00281     err = deflate(&c_stream, Z_NO_FLUSH);
00282     CHECK_ERR(err, "deflate");
00283 
00284     /* Switch back to compressing mode: */
00285     deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
00286     c_stream.next_in = uncompr;
00287     c_stream.avail_in = (uInt)uncomprLen;
00288     err = deflate(&c_stream, Z_NO_FLUSH);
00289     CHECK_ERR(err, "deflate");
00290 
00291     err = deflate(&c_stream, Z_FINISH);
00292     if (err != Z_STREAM_END) {
00293         fprintf(stderr, "deflate should report Z_STREAM_END\n");
00294         exit(1);
00295     }
00296     err = deflateEnd(&c_stream);
00297     CHECK_ERR(err, "deflateEnd");
00298 }
00299 
00300 /* ===========================================================================
00301  * Test inflate() with large buffers
00302  */
00303 void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
00304     Byte *compr, *uncompr;
00305     uLong comprLen, uncomprLen;
00306 {
00307     int err;
00308     z_stream d_stream; /* decompression stream */
00309 
00310     strcpy((char*)uncompr, "garbage");
00311 
00312     d_stream.zalloc = (alloc_func)0;
00313     d_stream.zfree = (free_func)0;
00314     d_stream.opaque = (voidpf)0;
00315 
00316     d_stream.next_in  = compr;
00317     d_stream.avail_in = (uInt)comprLen;
00318 
00319     err = inflateInit(&d_stream);
00320     CHECK_ERR(err, "inflateInit");
00321 
00322     for (;;) {
00323         d_stream.next_out = uncompr;            /* discard the output */
00324         d_stream.avail_out = (uInt)uncomprLen;
00325         err = inflate(&d_stream, Z_NO_FLUSH);
00326         if (err == Z_STREAM_END) break;
00327         CHECK_ERR(err, "large inflate");
00328     }
00329 
00330     err = inflateEnd(&d_stream);
00331     CHECK_ERR(err, "inflateEnd");
00332 
00333     if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
00334         fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
00335         exit(1);
00336     } else {
00337         printf("large_inflate(): OK\n");
00338     }
00339 }
00340 
00341 /* ===========================================================================
00342  * Test deflate() with full flush
00343  */
00344 void test_flush(compr, comprLen)
00345     Byte *compr;
00346     uLong *comprLen;
00347 {
00348     z_stream c_stream; /* compression stream */
00349     int err;
00350     uInt len = (uInt)strlen(hello)+1;
00351 
00352     c_stream.zalloc = (alloc_func)0;
00353     c_stream.zfree = (free_func)0;
00354     c_stream.opaque = (voidpf)0;
00355 
00356     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
00357     CHECK_ERR(err, "deflateInit");
00358 
00359     c_stream.next_in  = (Bytef*)hello;
00360     c_stream.next_out = compr;
00361     c_stream.avail_in = 3;
00362     c_stream.avail_out = (uInt)*comprLen;
00363     err = deflate(&c_stream, Z_FULL_FLUSH);
00364     CHECK_ERR(err, "deflate");
00365 
00366     compr[3]++; /* force an error in first compressed block */
00367     c_stream.avail_in = len - 3;
00368 
00369     err = deflate(&c_stream, Z_FINISH);
00370     if (err != Z_STREAM_END) {
00371         CHECK_ERR(err, "deflate");
00372     }
00373     err = deflateEnd(&c_stream);
00374     CHECK_ERR(err, "deflateEnd");
00375 
00376     *comprLen = c_stream.total_out;
00377 }
00378 
00379 /* ===========================================================================
00380  * Test inflateSync()
00381  */
00382 void test_sync(compr, comprLen, uncompr, uncomprLen)
00383     Byte *compr, *uncompr;
00384     uLong comprLen, uncomprLen;
00385 {
00386     int err;
00387     z_stream d_stream; /* decompression stream */
00388 
00389     strcpy((char*)uncompr, "garbage");
00390 
00391     d_stream.zalloc = (alloc_func)0;
00392     d_stream.zfree = (free_func)0;
00393     d_stream.opaque = (voidpf)0;
00394 
00395     d_stream.next_in  = compr;
00396     d_stream.avail_in = 2; /* just read the zlib header */
00397 
00398     err = inflateInit(&d_stream);
00399     CHECK_ERR(err, "inflateInit");
00400 
00401     d_stream.next_out = uncompr;
00402     d_stream.avail_out = (uInt)uncomprLen;
00403 
00404     inflate(&d_stream, Z_NO_FLUSH);
00405     CHECK_ERR(err, "inflate");
00406 
00407     d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
00408     err = inflateSync(&d_stream);           /* but skip the damaged part */
00409     CHECK_ERR(err, "inflateSync");
00410 
00411     err = inflate(&d_stream, Z_FINISH);
00412     if (err != Z_DATA_ERROR) {
00413         fprintf(stderr, "inflate should report DATA_ERROR\n");
00414         /* Because of incorrect adler32 */
00415         exit(1);
00416     }
00417     err = inflateEnd(&d_stream);
00418     CHECK_ERR(err, "inflateEnd");
00419 
00420     printf("after inflateSync(): hel%s\n", (char *)uncompr);
00421 }
00422 
00423 /* ===========================================================================
00424  * Test deflate() with preset dictionary
00425  */
00426 void test_dict_deflate(compr, comprLen)
00427     Byte *compr;
00428     uLong comprLen;
00429 {
00430     z_stream c_stream; /* compression stream */
00431     int err;
00432 
00433     c_stream.zalloc = (alloc_func)0;
00434     c_stream.zfree = (free_func)0;
00435     c_stream.opaque = (voidpf)0;
00436 
00437     err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
00438     CHECK_ERR(err, "deflateInit");
00439 
00440     err = deflateSetDictionary(&c_stream,
00441                                (const Bytef*)dictionary, sizeof(dictionary));
00442     CHECK_ERR(err, "deflateSetDictionary");
00443 
00444     dictId = c_stream.adler;
00445     c_stream.next_out = compr;
00446     c_stream.avail_out = (uInt)comprLen;
00447 
00448     c_stream.next_in = (Bytef*)hello;
00449     c_stream.avail_in = (uInt)strlen(hello)+1;
00450 
00451     err = deflate(&c_stream, Z_FINISH);
00452     if (err != Z_STREAM_END) {
00453         fprintf(stderr, "deflate should report Z_STREAM_END\n");
00454         exit(1);
00455     }
00456     err = deflateEnd(&c_stream);
00457     CHECK_ERR(err, "deflateEnd");
00458 }
00459 
00460 /* ===========================================================================
00461  * Test inflate() with a preset dictionary
00462  */
00463 void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
00464     Byte *compr, *uncompr;
00465     uLong comprLen, uncomprLen;
00466 {
00467     int err;
00468     z_stream d_stream; /* decompression stream */
00469 
00470     strcpy((char*)uncompr, "garbage");
00471 
00472     d_stream.zalloc = (alloc_func)0;
00473     d_stream.zfree = (free_func)0;
00474     d_stream.opaque = (voidpf)0;
00475 
00476     d_stream.next_in  = compr;
00477     d_stream.avail_in = (uInt)comprLen;
00478 
00479     err = inflateInit(&d_stream);
00480     CHECK_ERR(err, "inflateInit");
00481 
00482     d_stream.next_out = uncompr;
00483     d_stream.avail_out = (uInt)uncomprLen;
00484 
00485     for (;;) {
00486         err = inflate(&d_stream, Z_NO_FLUSH);
00487         if (err == Z_STREAM_END) break;
00488         if (err == Z_NEED_DICT) {
00489             if (d_stream.adler != dictId) {
00490                 fprintf(stderr, "unexpected dictionary");
00491                 exit(1);
00492             }
00493             err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
00494                                        sizeof(dictionary));
00495         }
00496         CHECK_ERR(err, "inflate with dict");
00497     }
00498 
00499     err = inflateEnd(&d_stream);
00500     CHECK_ERR(err, "inflateEnd");
00501 
00502     if (strcmp((char*)uncompr, hello)) {
00503         fprintf(stderr, "bad inflate with dict\n");
00504         exit(1);
00505     } else {
00506         printf("inflate with dictionary: %s\n", (char *)uncompr);
00507     }
00508 }
00509 
00510 /* ===========================================================================
00511  * Usage:  example [output.gz  [input.gz]]
00512  */
00513 
00514 int main(argc, argv)
00515     int argc;
00516     char *argv[];
00517 {
00518     Byte *compr, *uncompr;
00519     uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
00520     uLong uncomprLen = comprLen;
00521     static const char* myVersion = ZLIB_VERSION;
00522 
00523     if (zlibVersion()[0] != myVersion[0]) {
00524         fprintf(stderr, "incompatible zlib version\n");
00525         exit(1);
00526 
00527     } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
00528         fprintf(stderr, "warning: different zlib version\n");
00529     }
00530 
00531     printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
00532             ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
00533 
00534     compr    = (Byte*)calloc((uInt)comprLen, 1);
00535     uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
00536     /* compr and uncompr are cleared to avoid reading uninitialized
00537      * data and to ensure that uncompr compresses well.
00538      */
00539     if (compr == Z_NULL || uncompr == Z_NULL) {
00540         printf("out of memory\n");
00541         exit(1);
00542     }
00543     test_compress(compr, comprLen, uncompr, uncomprLen);
00544 
00545     test_gzio((argc > 1 ? argv[1] : TESTFILE),
00546               uncompr, uncomprLen);
00547 
00548     test_deflate(compr, comprLen);
00549     test_inflate(compr, comprLen, uncompr, uncomprLen);
00550 
00551     test_large_deflate(compr, comprLen, uncompr, uncomprLen);
00552     test_large_inflate(compr, comprLen, uncompr, uncomprLen);
00553 
00554     test_flush(compr, &comprLen);
00555     test_sync(compr, comprLen, uncompr, uncomprLen);
00556     comprLen = uncomprLen;
00557 
00558     test_dict_deflate(compr, comprLen);
00559     test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
00560 
00561     free(compr);
00562     free(uncompr);
00563 
00564     return 0;
00565 }