xref: /aosp_15_r20/external/zstd/zlibWrapper/examples/example_original.c (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
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$ */
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 
myalloc(q,n,m)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 
myfree(void * q,void * p)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  */
test_compress(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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  */
test_gzio(const char * fname,Byte * uncompr,uLong uncomprLen)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  */
test_deflate(Byte * compr,uLong comprLen)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  */
test_inflate(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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  */
test_large_deflate(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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  */
test_large_inflate(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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  */
test_flush(Byte * compr,uLong comprLen)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  */
test_sync(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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  */
test_dict_deflate(Byte * compr,uLong comprLen)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  */
test_dict_inflate(Byte * compr,uLong comprLen,Byte * uncompr,uLong uncomprLen)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 
main(int argc,char * argv[])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