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