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