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