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