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