xref: /freebsd/sys/contrib/zstd/zlibWrapper/examples/example.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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       OF((Byte *compr, uLong comprLen));
60 void test_inflate       OF((Byte *compr, uLong comprLen,
61                             Byte *uncompr, uLong uncomprLen));
62 void test_large_deflate OF((Byte *compr, uLong comprLen,
63                             Byte *uncompr, uLong uncomprLen));
64 void test_large_inflate OF((Byte *compr, uLong comprLen,
65                             Byte *uncompr, uLong uncomprLen));
66 void test_flush         OF((Byte *compr, uLong *comprLen));
67 void test_sync          OF((Byte *compr, uLong comprLen,
68                             Byte *uncompr, uLong uncomprLen));
69 void test_dict_deflate  OF((Byte *compr, uLong comprLen));
70 void test_dict_inflate  OF((Byte *compr, uLong comprLen,
71                             Byte *uncompr, uLong uncomprLen));
72 int  main               OF((int argc, char *argv[]));
73 
74 
75 #ifdef Z_SOLO
76 
77 void *myalloc OF((void *, unsigned, unsigned));
78 void myfree OF((void *, void *));
79 
80 void *myalloc(q, n, m)
81     void *q;
82     unsigned n, m;
83 {
84     void *buf = calloc(n, m);
85     q = Z_NULL;
86   /*  printf("myalloc %p n=%d m=%d\n", buf, n, m); */
87     return buf;
88 }
89 
90 void myfree(void *q, void *p)
91 {
92   /*  printf("myfree %p\n", p); */
93     q = Z_NULL;
94     free(p);
95 }
96 
97 static alloc_func zalloc = myalloc;
98 static free_func zfree = myfree;
99 
100 #else /* !Z_SOLO */
101 
102 static alloc_func zalloc = (alloc_func)0;
103 static free_func zfree = (free_func)0;
104 
105 void test_compress      OF((Byte *compr, uLong comprLen,
106                             Byte *uncompr, uLong uncomprLen));
107 void test_gzio          OF((const char *fname,
108                             Byte *uncompr, uLong uncomprLen));
109 
110 /* ===========================================================================
111  * Test compress() and uncompress()
112  */
113 void test_compress(compr, comprLen, uncompr, uncomprLen)
114     Byte *compr, *uncompr;
115     uLong comprLen, uncomprLen;
116 {
117     int err;
118     uLong len = (uLong)strlen(hello)+1;
119 
120     err = compress(compr, &comprLen, (const Bytef*)hello, len);
121     CHECK_ERR(err, "compress");
122 
123     strcpy((char*)uncompr, "garbage");
124 
125     err = uncompress(uncompr, &uncomprLen, compr, comprLen);
126     CHECK_ERR(err, "uncompress");
127 
128     if (strcmp((char*)uncompr, hello)) {
129         fprintf(stderr, "bad uncompress\n");
130         exit(1);
131     } else {
132         printf("uncompress(): %s\n", (char *)uncompr);
133     }
134 }
135 
136 /* ===========================================================================
137  * Test read/write of .gz files
138  */
139 void test_gzio(fname, uncompr, uncomprLen)
140     const char *fname; /* compressed file name */
141     Byte *uncompr;
142     uLong uncomprLen;
143 {
144 #ifdef NO_GZCOMPRESS
145     fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
146 #else
147     int err;
148     int len = (int)strlen(hello)+1;
149     gzFile file;
150     z_off_t pos;
151 
152     file = gzopen(fname, "wb");
153     if (file == NULL) {
154         fprintf(stderr, "gzopen error\n");
155         exit(1);
156     }
157     gzputc(file, 'h');
158     if (gzputs(file, "ello") != 4) {
159         fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
160         exit(1);
161     }
162     if (gzprintf(file, ", %s! I said hello, hello!", "hello") != 8+21) {
163         fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
164         exit(1);
165     }
166     gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
167     gzclose(file);
168 
169     file = gzopen(fname, "rb");
170     if (file == NULL) {
171         fprintf(stderr, "gzopen error\n");
172         exit(1);
173     }
174     strcpy((char*)uncompr, "garbage");
175 
176     if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
177         fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
178         exit(1);
179     }
180     if (strcmp((char*)uncompr, hello)) {
181         fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
182         exit(1);
183     } else {
184         printf("gzread(): %s\n", (char*)uncompr);
185     }
186 
187     pos = gzseek(file, -8L, SEEK_CUR);
188     if (pos != 6+21 || gztell(file) != pos) {
189         fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
190                 (long)pos, (long)gztell(file));
191         exit(1);
192     }
193 
194     if (gzgetc(file) != ' ') {
195         fprintf(stderr, "gzgetc error\n");
196         exit(1);
197     }
198 
199     if (gzungetc(' ', file) != ' ') {
200         fprintf(stderr, "gzungetc error\n");
201         exit(1);
202     }
203 
204     gzgets(file, (char*)uncompr, (int)uncomprLen);
205     if (strlen((char*)uncompr) != 7) { /* " hello!" */
206         fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
207         exit(1);
208     }
209     if (strcmp((char*)uncompr, hello + 6+21)) {
210         fprintf(stderr, "bad gzgets after gzseek\n");
211         exit(1);
212     } else {
213         printf("gzgets() after gzseek: %s\n", (char*)uncompr);
214     }
215 
216     gzclose(file);
217 #endif
218 }
219 
220 #endif /* Z_SOLO */
221 
222 /* ===========================================================================
223  * Test deflate() with small buffers
224  */
225 void test_deflate(compr, comprLen)
226     Byte *compr;
227     uLong comprLen;
228 {
229     z_stream c_stream; /* compression stream */
230     int err;
231     uLong len = (uLong)strlen(hello)+1;
232 
233     c_stream.zalloc = zalloc;
234     c_stream.zfree = zfree;
235     c_stream.opaque = (voidpf)0;
236 
237     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
238     CHECK_ERR(err, "deflateInit");
239 
240     c_stream.next_in  = (z_const unsigned char *)hello;
241     c_stream.next_out = compr;
242 
243     while (c_stream.total_in != len && c_stream.total_out < comprLen) {
244         c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
245         err = deflate(&c_stream, Z_NO_FLUSH);
246         CHECK_ERR(err, "deflate");
247     }
248     /* Finish the stream, still forcing small buffers: */
249     for (;;) {
250         c_stream.avail_out = 1;
251         err = deflate(&c_stream, Z_FINISH);
252         if (err == Z_STREAM_END) break;
253         CHECK_ERR(err, "deflate");
254     }
255 
256     err = deflateEnd(&c_stream);
257     CHECK_ERR(err, "deflateEnd");
258 }
259 
260 /* ===========================================================================
261  * Test inflate() with small buffers
262  */
263 void test_inflate(compr, comprLen, uncompr, uncomprLen)
264     Byte *compr, *uncompr;
265     uLong comprLen, uncomprLen;
266 {
267     int err;
268     z_stream d_stream; /* decompression stream */
269 
270     strcpy((char*)uncompr, "garbage");
271 
272     d_stream.zalloc = zalloc;
273     d_stream.zfree = zfree;
274     d_stream.opaque = (voidpf)0;
275 
276     d_stream.next_in  = compr;
277     d_stream.avail_in = 0;
278     d_stream.next_out = uncompr;
279 
280     err = inflateInit(&d_stream);
281     CHECK_ERR(err, "inflateInit");
282 
283     while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
284         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
285         err = inflate(&d_stream, Z_NO_FLUSH);
286         if (err == Z_STREAM_END) break;
287         CHECK_ERR(err, "inflate");
288     }
289 
290     err = inflateEnd(&d_stream);
291     CHECK_ERR(err, "inflateEnd");
292 
293     if (strcmp((char*)uncompr, hello)) {
294         fprintf(stderr, "bad inflate\n");
295         exit(1);
296     } else {
297         printf("inflate(): %s\n", (char *)uncompr);
298     }
299 }
300 
301 /* ===========================================================================
302  * Test deflate() with large buffers and dynamic change of compression level
303  */
304 void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
305     Byte *compr, *uncompr;
306     uLong comprLen, uncomprLen;
307 {
308     z_stream c_stream; /* compression stream */
309     int err;
310 
311     c_stream.zalloc = zalloc;
312     c_stream.zfree = zfree;
313     c_stream.opaque = (voidpf)0;
314 
315     err = deflateInit(&c_stream, Z_BEST_SPEED);
316     CHECK_ERR(err, "deflateInit");
317 
318     c_stream.next_out = compr;
319     c_stream.avail_out = (uInt)comprLen;
320 
321     /* At this point, uncompr is still mostly zeroes, so it should compress
322      * very well:
323      */
324     c_stream.next_in = uncompr;
325     c_stream.avail_in = (uInt)uncomprLen;
326     err = deflate(&c_stream, Z_NO_FLUSH);
327     CHECK_ERR(err, "deflate");
328     if (c_stream.avail_in != 0) {
329         fprintf(stderr, "deflate not greedy\n");
330         exit(1);
331     }
332 
333     /* Feed in already compressed data and switch to no compression: */
334     deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
335     c_stream.next_in = compr;
336     c_stream.avail_in = (uInt)comprLen/2;
337     err = deflate(&c_stream, Z_NO_FLUSH);
338     CHECK_ERR(err, "deflate");
339 
340     /* Switch back to compressing mode: */
341     deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
342     c_stream.next_in = uncompr;
343     c_stream.avail_in = (uInt)uncomprLen;
344     err = deflate(&c_stream, Z_NO_FLUSH);
345     CHECK_ERR(err, "deflate");
346 
347     err = deflate(&c_stream, Z_FINISH);
348     if (err != Z_STREAM_END) {
349         fprintf(stderr, "deflate should report Z_STREAM_END\n");
350         exit(1);
351     }
352     err = deflateEnd(&c_stream);
353     CHECK_ERR(err, "deflateEnd");
354 }
355 
356 /* ===========================================================================
357  * Test inflate() with large buffers
358  */
359 void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
360     Byte *compr, *uncompr;
361     uLong comprLen, uncomprLen;
362 {
363     int err;
364     z_stream d_stream; /* decompression stream */
365 
366     strcpy((char*)uncompr, "garbage");
367 
368     d_stream.zalloc = zalloc;
369     d_stream.zfree = zfree;
370     d_stream.opaque = (voidpf)0;
371 
372     d_stream.next_in  = compr;
373     d_stream.avail_in = (uInt)comprLen;
374 
375     err = inflateInit(&d_stream);
376     CHECK_ERR(err, "inflateInit");
377 
378     for (;;) {
379         d_stream.next_out = uncompr;            /* discard the output */
380         d_stream.avail_out = (uInt)uncomprLen;
381         err = inflate(&d_stream, Z_NO_FLUSH);
382         if (err == Z_STREAM_END) break;
383         CHECK_ERR(err, "large inflate");
384     }
385 
386     err = inflateEnd(&d_stream);
387     CHECK_ERR(err, "inflateEnd");
388 
389     if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
390         fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
391         exit(1);
392     } else {
393         printf("large_inflate(): OK\n");
394     }
395 }
396 
397 /* ===========================================================================
398  * Test deflate() with full flush
399  */
400 void test_flush(compr, comprLen)
401     Byte *compr;
402     uLong *comprLen;
403 {
404     z_stream c_stream; /* compression stream */
405     int err;
406     uInt len = (uInt)strlen(hello)+1;
407 
408     c_stream.zalloc = zalloc;
409     c_stream.zfree = zfree;
410     c_stream.opaque = (voidpf)0;
411 
412     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
413     CHECK_ERR(err, "deflateInit");
414 
415     c_stream.next_in  = (z_const unsigned char *)hello;
416     c_stream.next_out = compr;
417     c_stream.avail_in = 3;
418     c_stream.avail_out = (uInt)*comprLen;
419     err = deflate(&c_stream, Z_FULL_FLUSH);
420     CHECK_ERR(err, "deflate");
421 
422     compr[3]++; /* force an error in first compressed block */
423     c_stream.avail_in = len - 3;
424 
425     err = deflate(&c_stream, Z_FINISH);
426     if (err != Z_STREAM_END) {
427         CHECK_ERR(err, "deflate");
428     }
429     err = deflateEnd(&c_stream);
430     CHECK_ERR(err, "deflateEnd");
431 
432     *comprLen = c_stream.total_out;
433 }
434 
435 /* ===========================================================================
436  * Test inflateSync()
437  */
438 void test_sync(compr, comprLen, uncompr, uncomprLen)
439     Byte *compr, *uncompr;
440     uLong comprLen, uncomprLen;
441 {
442     int err;
443     z_stream d_stream; /* decompression stream */
444 
445     strcpy((char*)uncompr, "garbage");
446 
447     d_stream.zalloc = zalloc;
448     d_stream.zfree = zfree;
449     d_stream.opaque = (voidpf)0;
450 
451     d_stream.next_in  = compr;
452     d_stream.avail_in = 2; /* just read the zlib header */
453 
454     err = inflateInit(&d_stream);
455     CHECK_ERR(err, "inflateInit");
456 
457     d_stream.next_out = uncompr;
458     d_stream.avail_out = (uInt)uncomprLen;
459 
460     inflate(&d_stream, Z_NO_FLUSH);
461     CHECK_ERR(err, "inflate");
462 
463     d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
464     err = inflateSync(&d_stream);           /* but skip the damaged part */
465     CHECK_ERR(err, "inflateSync");
466 
467     err = inflate(&d_stream, Z_FINISH);
468     if (err != Z_DATA_ERROR) {
469         fprintf(stderr, "inflate should report DATA_ERROR\n");
470         /* Because of incorrect adler32 */
471         exit(1);
472     }
473     err = inflateEnd(&d_stream);
474     CHECK_ERR(err, "inflateEnd");
475 
476     printf("after inflateSync(): hel%s\n", (char *)uncompr);
477 }
478 
479 /* ===========================================================================
480  * Test deflate() with preset dictionary
481  */
482 void test_dict_deflate(compr, comprLen)
483     Byte *compr;
484     uLong comprLen;
485 {
486     z_stream c_stream; /* compression stream */
487     int err;
488 
489     c_stream.zalloc = zalloc;
490     c_stream.zfree = zfree;
491     c_stream.opaque = (voidpf)0;
492 
493     err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
494     CHECK_ERR(err, "deflateInit");
495 
496     err = deflateSetDictionary(&c_stream,
497                 (const Bytef*)dictionary, (int)sizeof(dictionary));
498     CHECK_ERR(err, "deflateSetDictionary");
499 
500     dictId = c_stream.adler;
501     c_stream.next_out = compr;
502     c_stream.avail_out = (uInt)comprLen;
503 
504     c_stream.next_in = (z_const unsigned char *)hello;
505     c_stream.avail_in = (uInt)strlen(hello)+1;
506 
507     err = deflate(&c_stream, Z_FINISH);
508     if (err != Z_STREAM_END) {
509         fprintf(stderr, "deflate should report Z_STREAM_END\n");
510         exit(1);
511     }
512     err = deflateEnd(&c_stream);
513     CHECK_ERR(err, "deflateEnd");
514 }
515 
516 /* ===========================================================================
517  * Test inflate() with a preset dictionary
518  */
519 void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
520     Byte *compr, *uncompr;
521     uLong comprLen, uncomprLen;
522 {
523     int err;
524     z_stream d_stream; /* decompression stream */
525 
526     strcpy((char*)uncompr, "garbage");
527 
528     d_stream.zalloc = zalloc;
529     d_stream.zfree = zfree;
530     d_stream.opaque = (voidpf)0;
531 
532     d_stream.next_in  = compr;
533     d_stream.avail_in = (uInt)comprLen;
534 
535     err = inflateInit(&d_stream);
536     CHECK_ERR(err, "inflateInit");
537 
538     d_stream.next_out = uncompr;
539     d_stream.avail_out = (uInt)uncomprLen;
540 
541     for (;;) {
542         err = inflate(&d_stream, Z_NO_FLUSH);
543         if (err == Z_STREAM_END) break;
544         if (err == Z_NEED_DICT) {
545             if (d_stream.adler != dictId) {
546                 fprintf(stderr, "unexpected dictionary");
547                 exit(1);
548             }
549             err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
550                                        (int)sizeof(dictionary));
551         }
552         CHECK_ERR(err, "inflate with dict");
553     }
554 
555     err = inflateEnd(&d_stream);
556     CHECK_ERR(err, "inflateEnd");
557 
558     if (strcmp((char*)uncompr, hello)) {
559         fprintf(stderr, "bad inflate with dict\n");
560         exit(1);
561     } else {
562         printf("inflate with dictionary: %s\n", (char *)uncompr);
563     }
564 }
565 
566 /* ===========================================================================
567  * Usage:  example [output.gz  [input.gz]]
568  */
569 
570 int main(argc, argv)
571     int argc;
572     char *argv[];
573 {
574     Byte *compr, *uncompr;
575     uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
576     uLong uncomprLen = comprLen;
577     static const char* myVersion = ZLIB_VERSION;
578 
579     if (zlibVersion()[0] != myVersion[0]) {
580         fprintf(stderr, "incompatible zlib version\n");
581         exit(1);
582 
583     } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
584         fprintf(stderr, "warning: different zlib version\n");
585     }
586 
587     printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
588             ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
589     if (ZWRAP_isUsingZSTDcompression()) printf("zstd version %s\n", zstdVersion());
590 
591     compr    = (Byte*)calloc((uInt)comprLen, 1);
592     uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
593     /* compr and uncompr are cleared to avoid reading uninitialized
594      * data and to ensure that uncompr compresses well.
595      */
596     if (compr == Z_NULL || uncompr == Z_NULL) {
597         printf("out of memory\n");
598         exit(1);
599     }
600 
601 #ifdef Z_SOLO
602     argc = strlen(argv[0]);
603 #else
604     test_compress(compr, comprLen, uncompr, uncomprLen);
605 
606     test_gzio((argc > 1 ? argv[1] : TESTFILE),
607           uncompr, uncomprLen);
608 #endif
609 
610     test_deflate(compr, comprLen);
611     test_inflate(compr, comprLen, uncompr, uncomprLen);
612 
613     test_large_deflate(compr, comprLen, uncompr, uncomprLen);
614     test_large_inflate(compr, comprLen, uncompr, uncomprLen);
615 
616     if (!ZWRAP_isUsingZSTDcompression()) {
617         test_flush(compr, &comprLen);
618         test_sync(compr, comprLen, uncompr, uncomprLen);
619     }
620     comprLen = uncomprLen;
621 
622     test_dict_deflate(compr, comprLen);
623     test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
624 
625     free(compr);
626     free(uncompr);
627 
628     return 0;
629 }
630