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