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