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: example.c,v 1.1.1.1 2024/10/27 22:44:15 christos Exp $ */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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