1 /* Filename: Zlib.xs 2 * Author : Paul Marquess, <pmqs@cpan.org> 3 * Created : 22nd January 1996 4 * Version : 2.000 5 * 6 * Copyright (c) 1995-2010 Paul Marquess. All rights reserved. 7 * This program is free software; you can redistribute it and/or 8 * modify it under the same terms as Perl itself. 9 * 10 */ 11 12 /* Parts of this code are based on the files gzio.c and gzappend.c from 13 * the standard zlib source distribution. Below are the copyright statements 14 * from each. 15 */ 16 17 /* gzio.c -- IO on .gz files 18 * Copyright (C) 1995 Jean-loup Gailly. 19 * For conditions of distribution and use, see copyright notice in zlib.h 20 */ 21 22 /* gzappend -- command to append to a gzip file 23 24 Copyright (C) 2003 Mark Adler, all rights reserved 25 version 1.1, 4 Nov 2003 26 */ 27 28 29 30 #include "EXTERN.h" 31 #include "perl.h" 32 #include "XSUB.h" 33 34 #include <zlib.h> 35 36 /* zlib prior to 1.06 doesn't know about z_off_t */ 37 #ifndef z_off_t 38 # define z_off_t long 39 #endif 40 41 #if ! defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200 42 # define NEED_DUMMY_BYTE_AT_END 43 #endif 44 45 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1210 46 # define MAGIC_APPEND 47 #endif 48 49 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221 50 # define AT_LEAST_ZLIB_1_2_2_1 51 #endif 52 53 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1222 54 # define AT_LEAST_ZLIB_1_2_2_2 55 #endif 56 57 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223 58 # define AT_LEAST_ZLIB_1_2_2_3 59 #endif 60 61 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230 62 # define AT_LEAST_ZLIB_1_2_3 63 #endif 64 65 #ifdef USE_PPPORT_H 66 # define NEED_sv_2pvbyte 67 # define NEED_sv_2pv_nolen 68 # include "ppport.h" 69 #endif 70 71 #if PERL_REVISION == 5 && PERL_VERSION == 9 72 /* For Andreas */ 73 # define sv_pvbyte_force(sv,lp) sv_pvbyten_force(sv,lp) 74 #endif 75 76 #if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) 77 78 # ifdef SvPVbyte_force 79 # undef SvPVbyte_force 80 # endif 81 82 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp) 83 84 #endif 85 86 #ifndef SvPVbyte_nolen 87 # define SvPVbyte_nolen SvPV_nolen 88 #endif 89 90 91 92 #if 0 93 # ifndef SvPVbyte_nolen 94 # define SvPVbyte_nolen SvPV_nolen 95 # endif 96 97 # ifndef SvPVbyte_force 98 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp) 99 # endif 100 #endif 101 102 #if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) 103 # define UTF8_AVAILABLE 104 #endif 105 106 typedef int DualType ; 107 typedef int int_undef ; 108 109 typedef struct di_stream { 110 int flags ; 111 #define FLAG_APPEND 1 112 #define FLAG_CRC32 2 113 #define FLAG_ADLER32 4 114 #define FLAG_CONSUME_INPUT 8 115 #define FLAG_LIMIT_OUTPUT 16 116 uLong crc32 ; 117 uLong adler32 ; 118 z_stream stream; 119 uLong bufsize; 120 SV * dictionary ; 121 uLong dict_adler ; 122 int last_error ; 123 bool zip_mode ; 124 #define SETP_BYTE 125 #ifdef SETP_BYTE 126 bool deflateParams_out_valid ; 127 Bytef deflateParams_out_byte; 128 #else 129 #define deflateParams_BUFFER_SIZE 0x4000 130 uLong deflateParams_out_length; 131 Bytef* deflateParams_out_buffer; 132 #endif 133 int Level; 134 int Method; 135 int WindowBits; 136 int MemLevel; 137 int Strategy; 138 uLong bytesInflated ; 139 uLong compressedBytes ; 140 uLong uncompressedBytes ; 141 #ifdef MAGIC_APPEND 142 143 #define WINDOW_SIZE 32768U 144 145 bool matchedEndBlock; 146 Bytef* window ; 147 int window_lastbit, window_left, window_full; 148 unsigned window_have; 149 off_t window_lastoff, window_end; 150 off_t window_endOffset; 151 152 uLong lastBlockOffset ; 153 unsigned char window_lastByte ; 154 155 156 #endif 157 } di_stream; 158 159 typedef di_stream * deflateStream ; 160 typedef di_stream * Compress__Raw__Zlib__deflateStream ; 161 typedef di_stream * inflateStream ; 162 typedef di_stream * Compress__Raw__Zlib__inflateStream ; 163 typedef di_stream * Compress__Raw__Zlib__inflateScanStream ; 164 165 #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \ 166 Zero(to,1,typ)) 167 168 /* Figure out the Operating System */ 169 #ifdef MSDOS 170 # define OS_CODE 0x00 171 #endif 172 173 #if defined(AMIGA) || defined(AMIGAOS) 174 # define OS_CODE 0x01 175 #endif 176 177 #if defined(VAXC) || defined(VMS) 178 # define OS_CODE 0x02 179 #endif 180 181 #if 0 /* VM/CMS */ 182 # define OS_CODE 0x04 183 #endif 184 185 #if defined(ATARI) || defined(atarist) 186 # define OS_CODE 0x05 187 #endif 188 189 #ifdef OS2 190 # define OS_CODE 0x06 191 #endif 192 193 #if defined(MACOS) || defined(TARGET_OS_MAC) 194 # define OS_CODE 0x07 195 #endif 196 197 #if 0 /* Z-System */ 198 # define OS_CODE 0x08 199 #endif 200 201 #if 0 /* CP/M */ 202 # define OS_CODE 0x09 203 #endif 204 205 #ifdef TOPS20 206 # define OS_CODE 0x0a 207 #endif 208 209 #ifdef WIN32 /* Window 95 & Windows NT */ 210 # define OS_CODE 0x0b 211 #endif 212 213 #if 0 /* QDOS */ 214 # define OS_CODE 0x0c 215 #endif 216 217 #if 0 /* Acorn RISCOS */ 218 # define OS_CODE 0x0d 219 #endif 220 221 #if 0 /* ??? */ 222 # define OS_CODE 0x0e 223 #endif 224 225 #ifdef __50SERIES /* Prime/PRIMOS */ 226 # define OS_CODE 0x0F 227 #endif 228 229 /* Default to UNIX */ 230 #ifndef OS_CODE 231 # define OS_CODE 0x03 /* assume Unix */ 232 #endif 233 234 #ifndef GZIP_OS_CODE 235 # define GZIP_OS_CODE OS_CODE 236 #endif 237 238 #define adlerInitial adler32(0L, Z_NULL, 0) 239 #define crcInitial crc32(0L, Z_NULL, 0) 240 241 /* static const char * const my_z_errmsg[] = { */ 242 static const char my_z_errmsg[][32] = { 243 "need dictionary", /* Z_NEED_DICT 2 */ 244 "stream end", /* Z_STREAM_END 1 */ 245 "", /* Z_OK 0 */ 246 "file error", /* Z_ERRNO (-1) */ 247 "stream error", /* Z_STREAM_ERROR (-2) */ 248 "data error", /* Z_DATA_ERROR (-3) */ 249 "insufficient memory", /* Z_MEM_ERROR (-4) */ 250 "buffer error", /* Z_BUF_ERROR (-5) */ 251 "incompatible version",/* Z_VERSION_ERROR(-6) */ 252 ""}; 253 254 #define setDUALstatus(var, err) \ 255 sv_setnv(var, (double)err) ; \ 256 sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \ 257 SvNOK_on(var); 258 259 260 #if defined(__SYMBIAN32__) 261 # define NO_WRITEABLE_DATA 262 #endif 263 264 #define TRACE_DEFAULT 0 265 266 #ifdef NO_WRITEABLE_DATA 267 # define trace TRACE_DEFAULT 268 #else 269 static int trace = TRACE_DEFAULT ; 270 #endif 271 272 /* Dodge PerlIO hiding of these functions. */ 273 #undef printf 274 275 static char * 276 #ifdef CAN_PROTOTYPE 277 GetErrorString(int error_no) 278 #else 279 GetErrorString(error_no) 280 int error_no ; 281 #endif 282 { 283 dTHX; 284 char * errstr ; 285 286 if (error_no == Z_ERRNO) { 287 errstr = Strerror(errno) ; 288 } 289 else 290 /* errstr = gzerror(fil, &error_no) ; */ 291 errstr = (char*) my_z_errmsg[2 - error_no]; 292 293 return errstr ; 294 } 295 296 297 #ifdef MAGIC_APPEND 298 299 /* 300 The following two functions are taken almost directly from 301 examples/gzappend.c. Only cosmetic changes have been made to conform to 302 the coding style of the rest of the code in this file. 303 */ 304 305 306 /* return the greatest common divisor of a and b using Euclid's algorithm, 307 modified to be fast when one argument much greater than the other, and 308 coded to avoid unnecessary swapping */ 309 static unsigned 310 #ifdef CAN_PROTOTYPE 311 gcd(unsigned a, unsigned b) 312 #else 313 gcd(a, b) 314 unsigned a; 315 unsigned b; 316 #endif 317 { 318 unsigned c; 319 320 while (a && b) 321 if (a > b) { 322 c = b; 323 while (a - c >= c) 324 c <<= 1; 325 a -= c; 326 } 327 else { 328 c = a; 329 while (b - c >= c) 330 c <<= 1; 331 b -= c; 332 } 333 return a + b; 334 } 335 336 /* rotate list[0..len-1] left by rot positions, in place */ 337 static void 338 #ifdef CAN_PROTOTYPE 339 rotate(unsigned char *list, unsigned len, unsigned rot) 340 #else 341 rotate(list, len, rot) 342 unsigned char *list; 343 unsigned len ; 344 unsigned rot; 345 #endif 346 { 347 unsigned char tmp; 348 unsigned cycles; 349 unsigned char *start, *last, *to, *from; 350 351 /* normalize rot and handle degenerate cases */ 352 if (len < 2) return; 353 if (rot >= len) rot %= len; 354 if (rot == 0) return; 355 356 /* pointer to last entry in list */ 357 last = list + (len - 1); 358 359 /* do simple left shift by one */ 360 if (rot == 1) { 361 tmp = *list; 362 memcpy(list, list + 1, len - 1); 363 *last = tmp; 364 return; 365 } 366 367 /* do simple right shift by one */ 368 if (rot == len - 1) { 369 tmp = *last; 370 memmove(list + 1, list, len - 1); 371 *list = tmp; 372 return; 373 } 374 375 /* otherwise do rotate as a set of cycles in place */ 376 cycles = gcd(len, rot); /* number of cycles */ 377 do { 378 start = from = list + cycles; /* start index is arbitrary */ 379 tmp = *from; /* save entry to be overwritten */ 380 for (;;) { 381 to = from; /* next step in cycle */ 382 from += rot; /* go right rot positions */ 383 if (from > last) from -= len; /* (pointer better not wrap) */ 384 if (from == start) break; /* all but one shifted */ 385 *to = *from; /* shift left */ 386 } 387 *to = tmp; /* complete the circle */ 388 } while (--cycles); 389 } 390 391 #endif /* MAGIC_APPEND */ 392 393 static void 394 #ifdef CAN_PROTOTYPE 395 DispHex(void * ptr, int length) 396 #else 397 DispHex(ptr, length) 398 void * ptr; 399 int length; 400 #endif 401 { 402 char * p = (char*)ptr; 403 int i; 404 for (i = 0; i < length; ++i) { 405 printf(" %02x", 0xFF & *(p+i)); 406 } 407 } 408 409 410 static void 411 #ifdef CAN_PROTOTYPE 412 DispStream(di_stream * s, char * message) 413 #else 414 DispStream(s, message) 415 di_stream * s; 416 char * message; 417 #endif 418 { 419 420 #if 0 421 if (! trace) 422 return ; 423 #endif 424 425 #define EnDis(f) (s->flags & f ? "Enabled" : "Disabled") 426 427 printf("DispStream 0x%p", s) ; 428 if (message) 429 printf("- %s \n", message) ; 430 printf("\n") ; 431 432 if (!s) { 433 printf(" stream pointer is NULL\n"); 434 } 435 else { 436 printf(" stream 0x%p\n", &(s->stream)); 437 printf(" zalloc 0x%p\n", s->stream.zalloc); 438 printf(" zfree 0x%p\n", s->stream.zfree); 439 printf(" opaque 0x%p\n", s->stream.opaque); 440 if (s->stream.msg) 441 printf(" msg %s\n", s->stream.msg); 442 else 443 printf(" msg \n"); 444 printf(" next_in 0x%p", s->stream.next_in); 445 if (s->stream.next_in){ 446 printf(" =>"); 447 DispHex(s->stream.next_in, 4); 448 } 449 printf("\n"); 450 451 printf(" next_out 0x%p", s->stream.next_out); 452 if (s->stream.next_out){ 453 printf(" =>"); 454 DispHex(s->stream.next_out, 4); 455 } 456 printf("\n"); 457 458 printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in); 459 printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out); 460 printf(" total_in %ld\n", s->stream.total_in); 461 printf(" total_out %ld\n", s->stream.total_out); 462 printf(" adler %ld\n", s->stream.adler ); 463 printf(" bufsize %ld\n", s->bufsize); 464 printf(" dictionary 0x%p\n", s->dictionary); 465 printf(" dict_adler 0x%ld\n",s->dict_adler); 466 printf(" zip_mode %d\n", s->zip_mode); 467 printf(" crc32 0x%x\n", (unsigned)s->crc32); 468 printf(" adler32 0x%x\n", (unsigned)s->adler32); 469 printf(" flags 0x%x\n", s->flags); 470 printf(" APPEND %s\n", EnDis(FLAG_APPEND)); 471 printf(" CRC32 %s\n", EnDis(FLAG_CRC32)); 472 printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32)); 473 printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT)); 474 printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT)); 475 476 477 #ifdef MAGIC_APPEND 478 printf(" window 0x%p\n", s->window); 479 #endif 480 printf("\n"); 481 482 } 483 } 484 485 static di_stream * 486 #ifdef CAN_PROTOTYPE 487 InitStream(void) 488 #else 489 InitStream() 490 #endif 491 { 492 di_stream *s ; 493 494 ZMALLOC(s, di_stream) ; 495 496 return s ; 497 498 } 499 500 static void 501 #ifdef CAN_PROTOTYPE 502 PostInitStream(di_stream * s, int flags, int bufsize, int windowBits) 503 #else 504 PostInitStream(s, flags, bufsize, windowBits) 505 di_stream *s ; 506 int flags ; 507 int bufsize ; 508 int windowBits ; 509 #endif 510 { 511 s->bufsize = bufsize ; 512 s->compressedBytes = 513 s->uncompressedBytes = 514 s->last_error = 0 ; 515 s->flags = flags ; 516 s->zip_mode = (windowBits < 0) ; 517 if (flags & FLAG_CRC32) 518 s->crc32 = crcInitial ; 519 if (flags & FLAG_ADLER32) 520 s->adler32 = adlerInitial ; 521 } 522 523 524 static SV* 525 #ifdef CAN_PROTOTYPE 526 deRef(SV * sv, const char * string) 527 #else 528 deRef(sv, string) 529 SV * sv ; 530 char * string; 531 #endif 532 { 533 dTHX; 534 SvGETMAGIC(sv); 535 536 if (SvROK(sv)) { 537 sv = SvRV(sv) ; 538 SvGETMAGIC(sv); 539 switch(SvTYPE(sv)) { 540 case SVt_PVAV: 541 case SVt_PVHV: 542 case SVt_PVCV: 543 croak("%s: buffer parameter is not a SCALAR reference", string); 544 default: 545 break; 546 } 547 if (SvROK(sv)) 548 croak("%s: buffer parameter is a reference to a reference", string) ; 549 } 550 551 if (!SvOK(sv)) { 552 sv = newSVpv("", 0); 553 } 554 555 return sv ; 556 } 557 558 static SV* 559 #ifdef CAN_PROTOTYPE 560 deRef_l(SV * sv, const char * string) 561 #else 562 deRef_l(sv, string) 563 SV * sv ; 564 char * string ; 565 #endif 566 { 567 dTHX; 568 bool wipe = 0 ; 569 570 SvGETMAGIC(sv); 571 wipe = ! SvOK(sv) ; 572 573 if (SvROK(sv)) { 574 sv = SvRV(sv) ; 575 SvGETMAGIC(sv); 576 wipe = ! SvOK(sv) ; 577 578 switch(SvTYPE(sv)) { 579 case SVt_PVAV: 580 case SVt_PVHV: 581 case SVt_PVCV: 582 croak("%s: buffer parameter is not a SCALAR reference", string); 583 default: 584 break; 585 } 586 if (SvROK(sv)) 587 croak("%s: buffer parameter is a reference to a reference", string) ; 588 } 589 590 if (SvREADONLY(sv) && PL_curcop != &PL_compiling) 591 croak("%s: buffer parameter is read-only", string); 592 593 SvUPGRADE(sv, SVt_PV); 594 595 if (wipe) 596 SvCUR_set(sv, 0); 597 598 SvOOK_off(sv); 599 SvPOK_only(sv); 600 601 return sv ; 602 } 603 604 605 #include "constants.h" 606 607 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_ 608 609 REQUIRE: 1.924 610 PROTOTYPES: DISABLE 611 612 INCLUDE: constants.xs 613 614 BOOT: 615 /* Check this version of zlib is == 1 */ 616 if (zlibVersion()[0] != '1') 617 croak("Compress::Raw::Zlib needs zlib version 1.x\n") ; 618 619 { 620 /* Create the $os_code scalar */ 621 SV * os_code_sv = perl_get_sv("Compress::Raw::Zlib::gzip_os_code", GV_ADDMULTI) ; 622 sv_setiv(os_code_sv, GZIP_OS_CODE) ; 623 } 624 625 626 #define Zip_zlib_version() (const char*)zlib_version 627 const char* 628 Zip_zlib_version() 629 630 unsigned 631 ZLIB_VERNUM() 632 CODE: 633 #ifdef ZLIB_VERNUM 634 RETVAL = ZLIB_VERNUM ; 635 #else 636 /* 1.1.4 => 0x1140 */ 637 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ; 638 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ; 639 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ; 640 #endif 641 OUTPUT: 642 RETVAL 643 644 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_ 645 646 #define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len) 647 648 uLong 649 Zip_adler32(buf, adler=adlerInitial) 650 uLong adler = NO_INIT 651 STRLEN len = NO_INIT 652 Bytef * buf = NO_INIT 653 SV * sv = ST(0) ; 654 INIT: 655 /* If the buffer is a reference, dereference it */ 656 sv = deRef(sv, "adler32") ; 657 #ifdef UTF8_AVAILABLE 658 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1)) 659 croak("Wide character in Compress::Raw::Zlib::adler32"); 660 #endif 661 buf = (Byte*)SvPVbyte(sv, len) ; 662 663 if (items < 2) 664 adler = adlerInitial; 665 else if (SvOK(ST(1))) 666 adler = SvUV(ST(1)) ; 667 else 668 adler = adlerInitial; 669 OUTPUT: 670 RETVAL 671 672 #define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len) 673 674 uLong 675 Zip_crc32(buf, crc=crcInitial) 676 uLong crc = NO_INIT 677 STRLEN len = NO_INIT 678 Bytef * buf = NO_INIT 679 SV * sv = ST(0) ; 680 INIT: 681 /* If the buffer is a reference, dereference it */ 682 sv = deRef(sv, "crc32") ; 683 #ifdef UTF8_AVAILABLE 684 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1)) 685 croak("Wide character in Compress::Raw::Zlib::crc32"); 686 #endif 687 buf = (Byte*)SvPVbyte(sv, len) ; 688 689 if (items < 2) 690 crc = crcInitial; 691 else if (SvOK(ST(1))) 692 crc = SvUV(ST(1)) ; 693 else 694 crc = crcInitial; 695 696 697 uLong 698 crc32_combine(crc1, crc2, len2) 699 uLong crc1 700 uLong crc2 701 z_off_t len2 702 CODE: 703 #ifndef AT_LEAST_ZLIB_1_2_2_1 704 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */ 705 croak("crc32_combine needs zlib 1.2.3 or better"); 706 #else 707 RETVAL = crc32_combine(crc1, crc2, len2); 708 #endif 709 OUTPUT: 710 RETVAL 711 712 713 uLong 714 adler32_combine(adler1, adler2, len2) 715 uLong adler1 716 uLong adler2 717 z_off_t len2 718 CODE: 719 #ifndef AT_LEAST_ZLIB_1_2_2_1 720 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */ 721 croak("adler32_combine needs zlib 1.2.3 or better"); 722 #else 723 RETVAL = adler32_combine(adler1, adler2, len2); 724 #endif 725 OUTPUT: 726 RETVAL 727 728 729 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib 730 731 void 732 _deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary) 733 int flags 734 int level 735 int method 736 int windowBits 737 int memLevel 738 int strategy 739 uLong bufsize 740 SV* dictionary 741 PPCODE: 742 int err ; 743 deflateStream s ; 744 745 if (trace) 746 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld dictionary=%p)\n", 747 level, method, windowBits, memLevel, strategy, bufsize, dictionary) ; 748 if ((s = InitStream() )) { 749 750 s->Level = level; 751 s->Method = method; 752 s->WindowBits = windowBits; 753 s->MemLevel = memLevel; 754 s->Strategy = strategy; 755 756 err = deflateInit2(&(s->stream), level, 757 method, windowBits, memLevel, strategy); 758 759 /* Check if a dictionary has been specified */ 760 761 if (err == Z_OK && SvCUR(dictionary)) { 762 #ifdef UTF8_AVAILABLE 763 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1)) 764 croak("Wide character in Compress::Raw::Zlib::Deflate::new dicrionary parameter"); 765 #endif 766 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary), 767 SvCUR(dictionary)) ; 768 s->dict_adler = s->stream.adler ; 769 } 770 771 if (err != Z_OK) { 772 Safefree(s) ; 773 s = NULL ; 774 } 775 else 776 PostInitStream(s, flags, bufsize, windowBits) ; 777 778 } 779 else 780 err = Z_MEM_ERROR ; 781 782 { 783 SV* obj = sv_setref_pv(sv_newmortal(), 784 "Compress::Raw::Zlib::deflateStream", (void*)s); 785 XPUSHs(obj); 786 } 787 if (GIMME == G_ARRAY) { 788 SV * sv = sv_2mortal(newSViv(err)) ; 789 setDUALstatus(sv, err); 790 XPUSHs(sv) ; 791 } 792 793 void 794 _inflateInit(flags, windowBits, bufsize, dictionary) 795 int flags 796 int windowBits 797 uLong bufsize 798 SV * dictionary 799 ALIAS: 800 _inflateScanInit = 1 801 PPCODE: 802 803 int err = Z_OK ; 804 inflateStream s ; 805 #ifndef MAGIC_APPEND 806 if (ix == 1) 807 croak("inflateScanInit needs zlib 1.2.1 or better"); 808 #endif 809 if (trace) 810 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n", 811 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ; 812 if ((s = InitStream() )) { 813 814 s->WindowBits = windowBits; 815 816 err = inflateInit2(&(s->stream), windowBits); 817 if (err != Z_OK) { 818 Safefree(s) ; 819 s = NULL ; 820 } 821 else if (SvCUR(dictionary)) { 822 #ifdef AT_LEAST_ZLIB_1_2_2_1 823 /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */ 824 if (s->WindowBits < 0) { 825 err = inflateSetDictionary(&(s->stream), 826 (const Bytef*)SvPVbyte_nolen(dictionary), 827 SvCUR(dictionary)); 828 if (err != Z_OK) { 829 Safefree(s) ; 830 s = NULL ; 831 } 832 } 833 else 834 #endif 835 /* Dictionary specified - take a copy for use in inflate */ 836 s->dictionary = newSVsv(dictionary) ; 837 } 838 if (s) { 839 PostInitStream(s, flags, bufsize, windowBits) ; 840 #ifdef MAGIC_APPEND 841 if (ix == 1) 842 { 843 s->window = (unsigned char *)safemalloc(WINDOW_SIZE); 844 } 845 #endif 846 } 847 } 848 else 849 err = Z_MEM_ERROR ; 850 851 { 852 SV* obj = sv_setref_pv(sv_newmortal(), 853 ix == 1 854 ? "Compress::Raw::Zlib::inflateScanStream" 855 : "Compress::Raw::Zlib::inflateStream", 856 (void*)s); 857 XPUSHs(obj); 858 } 859 if (GIMME == G_ARRAY) { 860 SV * sv = sv_2mortal(newSViv(err)) ; 861 setDUALstatus(sv, err); 862 XPUSHs(sv) ; 863 } 864 865 866 867 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream 868 869 void 870 DispStream(s, message=NULL) 871 Compress::Raw::Zlib::deflateStream s 872 char * message 873 874 DualType 875 deflateReset(s) 876 Compress::Raw::Zlib::deflateStream s 877 CODE: 878 RETVAL = deflateReset(&(s->stream)) ; 879 if (RETVAL == Z_OK) { 880 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; 881 } 882 OUTPUT: 883 RETVAL 884 885 DualType 886 deflate (s, buf, output) 887 Compress::Raw::Zlib::deflateStream s 888 SV * buf 889 SV * output 890 uInt cur_length = NO_INIT 891 uInt increment = NO_INIT 892 uInt prefix = NO_INIT 893 int RETVAL = 0; 894 uLong bufinc = NO_INIT 895 CODE: 896 bufinc = s->bufsize; 897 898 /* If the input buffer is a reference, dereference it */ 899 buf = deRef(buf, "deflate") ; 900 901 /* initialise the input buffer */ 902 #ifdef UTF8_AVAILABLE 903 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 904 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter"); 905 #endif 906 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ; 907 s->stream.avail_in = SvCUR(buf) ; 908 909 if (s->flags & FLAG_CRC32) 910 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ; 911 912 if (s->flags & FLAG_ADLER32) 913 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ; 914 915 /* and retrieve the output buffer */ 916 output = deRef_l(output, "deflate") ; 917 #ifdef UTF8_AVAILABLE 918 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 919 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate output parameter"); 920 #endif 921 922 if((s->flags & FLAG_APPEND) != FLAG_APPEND) { 923 SvCUR_set(output, 0); 924 /* sv_setpvn(output, "", 0); */ 925 } 926 prefix = cur_length = SvCUR(output) ; 927 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; 928 increment = SvLEN(output) - cur_length; 929 s->stream.avail_out = increment; 930 #ifdef SETP_BYTE 931 /* Check for saved output from deflateParams */ 932 if (s->deflateParams_out_valid) { 933 *(s->stream.next_out) = s->deflateParams_out_byte; 934 ++ s->stream.next_out; 935 -- s->stream.avail_out ; 936 s->deflateParams_out_valid = FALSE; 937 } 938 #else 939 /* Check for saved output from deflateParams */ 940 if (s->deflateParams_out_length) { 941 uLong plen = s->deflateParams_out_length ; 942 /* printf("Copy %d bytes saved data\n", plen);*/ 943 if (s->stream.avail_out < plen) { 944 /*printf("GROW from %d to %d\n", s->stream.avail_out, 945 SvLEN(output) + plen - s->stream.avail_out); */ 946 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ; 947 } 948 949 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ; 950 cur_length = cur_length + plen; 951 SvCUR_set(output, cur_length); 952 s->stream.next_out += plen ; 953 s->stream.avail_out = SvLEN(output) - cur_length ; 954 increment = s->stream.avail_out; 955 s->deflateParams_out_length = 0; 956 } 957 #endif 958 while (s->stream.avail_in != 0) { 959 960 if (s->stream.avail_out == 0) { 961 /* out of space in the output buffer so make it bigger */ 962 Sv_Grow(output, SvLEN(output) + bufinc) ; 963 cur_length += increment ; 964 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; 965 increment = bufinc ; 966 s->stream.avail_out = increment; 967 bufinc *= 2 ; 968 } 969 970 RETVAL = deflate(&(s->stream), Z_NO_FLUSH); 971 if (RETVAL != Z_OK) 972 break; 973 } 974 975 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ; 976 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ; 977 978 s->last_error = RETVAL ; 979 if (RETVAL == Z_OK) { 980 SvPOK_only(output); 981 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; 982 SvSETMAGIC(output); 983 } 984 OUTPUT: 985 RETVAL 986 987 988 void 989 DESTROY(s) 990 Compress::Raw::Zlib::deflateStream s 991 CODE: 992 deflateEnd(&s->stream) ; 993 if (s->dictionary) 994 SvREFCNT_dec(s->dictionary) ; 995 #ifndef SETP_BYTE 996 if (s->deflateParams_out_buffer) 997 Safefree(s->deflateParams_out_buffer); 998 #endif 999 Safefree(s) ; 1000 1001 1002 DualType 1003 flush(s, output, f=Z_FINISH) 1004 Compress::Raw::Zlib::deflateStream s 1005 SV * output 1006 int f 1007 uInt cur_length = NO_INIT 1008 uInt increment = NO_INIT 1009 uInt prefix = NO_INIT 1010 uLong bufinc = NO_INIT 1011 CODE: 1012 bufinc = s->bufsize; 1013 1014 s->stream.avail_in = 0; /* should be zero already anyway */ 1015 1016 /* retrieve the output buffer */ 1017 output = deRef_l(output, "flush") ; 1018 #ifdef UTF8_AVAILABLE 1019 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 1020 croak("Wide character in Compress::Raw::Zlib::Deflate::flush input parameter"); 1021 #endif 1022 if(! s->flags & FLAG_APPEND) { 1023 SvCUR_set(output, 0); 1024 /* sv_setpvn(output, "", 0); */ 1025 } 1026 prefix = cur_length = SvCUR(output) ; 1027 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; 1028 increment = SvLEN(output) - cur_length; 1029 s->stream.avail_out = increment; 1030 #ifdef SETP_BYTE 1031 /* Check for saved output from deflateParams */ 1032 if (s->deflateParams_out_valid) { 1033 *(s->stream.next_out) = s->deflateParams_out_byte; 1034 ++ s->stream.next_out; 1035 -- s->stream.avail_out ; 1036 s->deflateParams_out_valid = FALSE; 1037 } 1038 #else 1039 /* Check for saved output from deflateParams */ 1040 if (s->deflateParams_out_length) { 1041 uLong plen = s->deflateParams_out_length ; 1042 /* printf("Copy %d bytes saved data\n", plen); */ 1043 if (s->stream.avail_out < plen) { 1044 /* printf("GROW from %d to %d\n", s->stream.avail_out, 1045 SvLEN(output) + plen - s->stream.avail_out); */ 1046 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ; 1047 } 1048 1049 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ; 1050 cur_length = cur_length + plen; 1051 SvCUR_set(output, cur_length); 1052 s->stream.next_out += plen ; 1053 s->stream.avail_out = SvLEN(output) - cur_length ; 1054 increment = s->stream.avail_out; 1055 s->deflateParams_out_length = 0; 1056 } 1057 #endif 1058 1059 for (;;) { 1060 if (s->stream.avail_out == 0) { 1061 /* consumed all the available output, so extend it */ 1062 Sv_Grow(output, SvLEN(output) + bufinc) ; 1063 cur_length += increment ; 1064 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; 1065 increment = bufinc ; 1066 s->stream.avail_out = increment; 1067 bufinc *= 2 ; 1068 } 1069 RETVAL = deflate(&(s->stream), f); 1070 1071 /* deflate has finished flushing only when it hasn't used up 1072 * all the available space in the output buffer: 1073 */ 1074 if (s->stream.avail_out != 0 || RETVAL != Z_OK ) 1075 break; 1076 } 1077 1078 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ; 1079 s->last_error = RETVAL ; 1080 1081 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ; 1082 1083 if (RETVAL == Z_OK) { 1084 SvPOK_only(output); 1085 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; 1086 SvSETMAGIC(output); 1087 } 1088 OUTPUT: 1089 RETVAL 1090 1091 1092 DualType 1093 _deflateParams(s, flags, level, strategy, bufsize) 1094 Compress::Raw::Zlib::deflateStream s 1095 int flags 1096 int level 1097 int strategy 1098 uLong bufsize 1099 CODE: 1100 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize); 1101 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */ 1102 if (flags & 1) 1103 s->Level = level ; 1104 if (flags & 2) 1105 s->Strategy = strategy ; 1106 if (flags & 4) { 1107 s->bufsize = bufsize; 1108 } 1109 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/ 1110 #ifdef SETP_BYTE 1111 s->stream.avail_in = 0; 1112 s->stream.next_out = &(s->deflateParams_out_byte) ; 1113 s->stream.avail_out = 1; 1114 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy); 1115 s->deflateParams_out_valid = 1116 (RETVAL == Z_OK && s->stream.avail_out == 0) ; 1117 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */ 1118 #else 1119 /* printf("Level %d Strategy %d, Prev Len %d\n", 1120 s->Level, s->Strategy, s->deflateParams_out_length); */ 1121 s->stream.avail_in = 0; 1122 if (s->deflateParams_out_buffer == NULL) 1123 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE); 1124 s->stream.next_out = s->deflateParams_out_buffer ; 1125 s->stream.avail_out = deflateParams_BUFFER_SIZE; 1126 1127 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy); 1128 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out; 1129 /* printf("RETVAL %d, length out %d, avail %d\n", 1130 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */ 1131 #endif 1132 OUTPUT: 1133 RETVAL 1134 1135 1136 int 1137 get_Level(s) 1138 Compress::Raw::Zlib::deflateStream s 1139 CODE: 1140 RETVAL = s->Level ; 1141 OUTPUT: 1142 RETVAL 1143 1144 int 1145 get_Strategy(s) 1146 Compress::Raw::Zlib::deflateStream s 1147 CODE: 1148 RETVAL = s->Strategy ; 1149 OUTPUT: 1150 RETVAL 1151 1152 1153 uLong 1154 get_Bufsize(s) 1155 Compress::Raw::Zlib::deflateStream s 1156 CODE: 1157 RETVAL = s->bufsize ; 1158 OUTPUT: 1159 RETVAL 1160 1161 1162 int 1163 status(s) 1164 Compress::Raw::Zlib::deflateStream s 1165 CODE: 1166 RETVAL = s->last_error ; 1167 OUTPUT: 1168 RETVAL 1169 1170 uLong 1171 crc32(s) 1172 Compress::Raw::Zlib::deflateStream s 1173 CODE: 1174 RETVAL = s->crc32 ; 1175 OUTPUT: 1176 RETVAL 1177 1178 uLong 1179 dict_adler(s) 1180 Compress::Raw::Zlib::deflateStream s 1181 CODE: 1182 RETVAL = s->dict_adler ; 1183 OUTPUT: 1184 RETVAL 1185 1186 uLong 1187 adler32(s) 1188 Compress::Raw::Zlib::deflateStream s 1189 CODE: 1190 RETVAL = s->adler32 ; 1191 OUTPUT: 1192 RETVAL 1193 1194 uLong 1195 compressedBytes(s) 1196 Compress::Raw::Zlib::deflateStream s 1197 CODE: 1198 RETVAL = s->compressedBytes; 1199 OUTPUT: 1200 RETVAL 1201 1202 uLong 1203 uncompressedBytes(s) 1204 Compress::Raw::Zlib::deflateStream s 1205 CODE: 1206 RETVAL = s->uncompressedBytes; 1207 OUTPUT: 1208 RETVAL 1209 1210 uLong 1211 total_in(s) 1212 Compress::Raw::Zlib::deflateStream s 1213 CODE: 1214 RETVAL = s->stream.total_in ; 1215 OUTPUT: 1216 RETVAL 1217 1218 uLong 1219 total_out(s) 1220 Compress::Raw::Zlib::deflateStream s 1221 CODE: 1222 RETVAL = s->stream.total_out ; 1223 OUTPUT: 1224 RETVAL 1225 1226 char* 1227 msg(s) 1228 Compress::Raw::Zlib::deflateStream s 1229 CODE: 1230 RETVAL = s->stream.msg; 1231 OUTPUT: 1232 RETVAL 1233 1234 int 1235 deflateTune(s, good_length, max_lazy, nice_length, max_chain) 1236 Compress::Raw::Zlib::deflateStream s 1237 int good_length 1238 int max_lazy 1239 int nice_length 1240 int max_chain 1241 CODE: 1242 #ifndef AT_LEAST_ZLIB_1_2_2_3 1243 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */ 1244 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */ 1245 croak("deflateTune needs zlib 1.2.2.3 or better"); 1246 #else 1247 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain); 1248 #endif 1249 OUTPUT: 1250 RETVAL 1251 1252 1253 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream 1254 1255 void 1256 DispStream(s, message=NULL) 1257 Compress::Raw::Zlib::inflateStream s 1258 char * message 1259 1260 DualType 1261 inflateReset(s) 1262 Compress::Raw::Zlib::inflateStream s 1263 CODE: 1264 RETVAL = inflateReset(&(s->stream)) ; 1265 if (RETVAL == Z_OK) { 1266 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; 1267 } 1268 OUTPUT: 1269 RETVAL 1270 1271 DualType 1272 inflate (s, buf, output, eof=FALSE) 1273 Compress::Raw::Zlib::inflateStream s 1274 SV * buf 1275 SV * output 1276 bool eof 1277 uInt cur_length = 0; 1278 uInt prefix_length = 0; 1279 int increment = 0; 1280 STRLEN stmp = NO_INIT 1281 uLong bufinc = NO_INIT 1282 PREINIT: 1283 #ifdef UTF8_AVAILABLE 1284 bool out_utf8 = FALSE; 1285 #endif 1286 CODE: 1287 bufinc = s->bufsize; 1288 /* If the buffer is a reference, dereference it */ 1289 buf = deRef(buf, "inflate") ; 1290 1291 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf)) 1292 croak("Compress::Raw::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified"); 1293 #ifdef UTF8_AVAILABLE 1294 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 1295 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate input parameter"); 1296 #endif 1297 1298 /* initialise the input buffer */ 1299 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ; 1300 s->stream.avail_in = SvCUR(buf) ; 1301 1302 /* and retrieve the output buffer */ 1303 output = deRef_l(output, "inflate") ; 1304 #ifdef UTF8_AVAILABLE 1305 if (DO_UTF8(output)) 1306 out_utf8 = TRUE ; 1307 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 1308 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate output parameter"); 1309 #endif 1310 if((s->flags & FLAG_APPEND) != FLAG_APPEND) { 1311 SvCUR_set(output, 0); 1312 } 1313 1314 /* Assume no output buffer - the code below will update if there is any available */ 1315 s->stream.avail_out = 0; 1316 1317 1318 if (SvLEN(output)) { 1319 prefix_length = cur_length = SvCUR(output) ; 1320 1321 if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) 1322 { 1323 Sv_Grow(output, bufinc + cur_length + 1) ; 1324 } 1325 1326 /* Only setup the stream output pointers if there is spare 1327 capacity in the outout SV 1328 */ 1329 if (SvLEN(output) > cur_length + 1) 1330 { 1331 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; 1332 increment = SvLEN(output) - cur_length - 1; 1333 s->stream.avail_out = increment; 1334 } 1335 } 1336 1337 1338 s->bytesInflated = 0; 1339 1340 RETVAL = Z_OK; 1341 1342 while (RETVAL == Z_OK) { 1343 if (s->stream.avail_out == 0) { 1344 /* out of space in the output buffer so make it bigger */ 1345 Sv_Grow(output, SvLEN(output) + bufinc +1) ; 1346 cur_length += increment ; 1347 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; 1348 increment = bufinc ; 1349 s->stream.avail_out = increment; 1350 bufinc *= 2 ; 1351 } 1352 1353 /* printf("INFLATE Availl In %d, Out %d\n", s->stream.avail_in, 1354 s->stream.avail_out); 1355 DispStream(s, "BEFORE"); 1356 Perl_sv_dump(output); */ 1357 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH); 1358 /* printf("INFLATE returned %d %s, avail in %d, out %d\n", RETVAL, 1359 GetErrorString(RETVAL), s->stream.avail_in, s->stream.avail_out); */ 1360 1361 1362 if (RETVAL == Z_NEED_DICT && s->dictionary) { 1363 s->dict_adler = s->stream.adler ; 1364 RETVAL = inflateSetDictionary(&(s->stream), 1365 (const Bytef*)SvPVbyte_nolen(s->dictionary), 1366 SvCUR(s->dictionary)); 1367 if (RETVAL == Z_OK) 1368 continue; 1369 } 1370 1371 if (s->flags & FLAG_LIMIT_OUTPUT && 1372 (RETVAL == Z_OK || RETVAL == Z_BUF_ERROR )) 1373 break; 1374 1375 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR || 1376 RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END ) 1377 break ; 1378 1379 if (RETVAL == Z_BUF_ERROR) { 1380 if (s->stream.avail_out == 0) 1381 continue ; 1382 if (s->stream.avail_in == 0) { 1383 RETVAL = Z_OK ; 1384 break ; 1385 } 1386 } 1387 } 1388 #ifdef NEED_DUMMY_BYTE_AT_END 1389 if (eof && RETVAL == Z_OK && s->flags & FLAG_LIMIT_OUTPUT == 0) { 1390 Bytef* nextIn = s->stream.next_in; 1391 uInt availIn = s->stream.avail_in; 1392 s->stream.next_in = (Bytef*) " "; 1393 s->stream.avail_in = 1; 1394 if (s->stream.avail_out == 0) { 1395 /* out of space in the output buffer so make it bigger */ 1396 Sv_Grow(output, SvLEN(output) + bufinc) ; 1397 cur_length += increment ; 1398 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; 1399 increment = bufinc ; 1400 s->stream.avail_out = increment; 1401 bufinc *= 2 ; 1402 } 1403 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH); 1404 s->stream.next_in = nextIn ; 1405 s->stream.avail_in = availIn ; 1406 } 1407 #endif 1408 1409 s->last_error = RETVAL ; 1410 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_BUF_ERROR || RETVAL == Z_DATA_ERROR) { 1411 unsigned in ; 1412 1413 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; 1414 s->uncompressedBytes += s->bytesInflated ; 1415 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; 1416 1417 SvPOK_only(output); 1418 SvCUR_set(output, prefix_length + s->bytesInflated) ; 1419 *SvEND(output) = '\0'; 1420 #ifdef UTF8_AVAILABLE 1421 if (out_utf8) 1422 sv_utf8_upgrade(output); 1423 #endif 1424 SvSETMAGIC(output); 1425 1426 if (s->flags & FLAG_CRC32 ) 1427 s->crc32 = crc32(s->crc32, 1428 (const Bytef*)SvPVbyte_nolen(output)+prefix_length, 1429 SvCUR(output)-prefix_length) ; 1430 1431 if (s->flags & FLAG_ADLER32) 1432 s->adler32 = adler32(s->adler32, 1433 (const Bytef*)SvPVbyte_nolen(output)+prefix_length, 1434 SvCUR(output)-prefix_length) ; 1435 1436 /* fix the input buffer */ 1437 if (s->flags & FLAG_CONSUME_INPUT || s->flags & FLAG_LIMIT_OUTPUT) { 1438 in = s->stream.avail_in ; 1439 SvCUR_set(buf, in) ; 1440 if (in) 1441 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; 1442 *SvEND(buf) = '\0'; 1443 SvSETMAGIC(buf); 1444 } 1445 1446 } 1447 OUTPUT: 1448 RETVAL 1449 1450 uLong 1451 inflateCount(s) 1452 Compress::Raw::Zlib::inflateStream s 1453 CODE: 1454 RETVAL = s->bytesInflated; 1455 OUTPUT: 1456 RETVAL 1457 1458 uLong 1459 compressedBytes(s) 1460 Compress::Raw::Zlib::inflateStream s 1461 CODE: 1462 RETVAL = s->compressedBytes; 1463 OUTPUT: 1464 RETVAL 1465 1466 uLong 1467 uncompressedBytes(s) 1468 Compress::Raw::Zlib::inflateStream s 1469 CODE: 1470 RETVAL = s->uncompressedBytes; 1471 OUTPUT: 1472 RETVAL 1473 1474 1475 DualType 1476 inflateSync (s, buf) 1477 Compress::Raw::Zlib::inflateStream s 1478 SV * buf 1479 CODE: 1480 1481 /* If the buffer is a reference, dereference it */ 1482 buf = deRef(buf, "inflateSync") ; 1483 #ifdef UTF8_AVAILABLE 1484 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 1485 croak("Wide character in Compress::Raw::Zlib::Inflate::inflateSync"); 1486 #endif 1487 1488 /* initialise the input buffer */ 1489 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ; 1490 s->stream.avail_in = SvCUR(buf) ; 1491 1492 /* inflateSync doesn't create any output */ 1493 s->stream.next_out = (Bytef*) NULL; 1494 s->stream.avail_out = 0; 1495 1496 RETVAL = inflateSync(&(s->stream)); 1497 s->last_error = RETVAL ; 1498 1499 /* fix the input buffer */ 1500 { 1501 unsigned in = s->stream.avail_in ; 1502 SvCUR_set(buf, in) ; 1503 if (in) 1504 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; 1505 *SvEND(buf) = '\0'; 1506 SvSETMAGIC(buf); 1507 } 1508 OUTPUT: 1509 RETVAL 1510 1511 void 1512 DESTROY(s) 1513 Compress::Raw::Zlib::inflateStream s 1514 CODE: 1515 inflateEnd(&s->stream) ; 1516 if (s->dictionary) 1517 SvREFCNT_dec(s->dictionary) ; 1518 #ifndef SETP_BYTE 1519 if (s->deflateParams_out_buffer) 1520 Safefree(s->deflateParams_out_buffer); 1521 #endif 1522 #ifdef MAGIC_APPEND 1523 if (s->window) 1524 Safefree(s->window); 1525 #endif 1526 Safefree(s) ; 1527 1528 1529 uLong 1530 status(s) 1531 Compress::Raw::Zlib::inflateStream s 1532 CODE: 1533 RETVAL = s->last_error ; 1534 OUTPUT: 1535 RETVAL 1536 1537 uLong 1538 crc32(s) 1539 Compress::Raw::Zlib::inflateStream s 1540 CODE: 1541 RETVAL = s->crc32 ; 1542 OUTPUT: 1543 RETVAL 1544 1545 uLong 1546 dict_adler(s) 1547 Compress::Raw::Zlib::inflateStream s 1548 CODE: 1549 RETVAL = s->dict_adler ; 1550 OUTPUT: 1551 RETVAL 1552 1553 uLong 1554 total_in(s) 1555 Compress::Raw::Zlib::inflateStream s 1556 CODE: 1557 RETVAL = s->stream.total_in ; 1558 OUTPUT: 1559 RETVAL 1560 1561 uLong 1562 adler32(s) 1563 Compress::Raw::Zlib::inflateStream s 1564 CODE: 1565 RETVAL = s->adler32 ; 1566 OUTPUT: 1567 RETVAL 1568 1569 uLong 1570 total_out(s) 1571 Compress::Raw::Zlib::inflateStream s 1572 CODE: 1573 RETVAL = s->stream.total_out ; 1574 OUTPUT: 1575 RETVAL 1576 1577 char* 1578 msg(s) 1579 Compress::Raw::Zlib::inflateStream s 1580 CODE: 1581 RETVAL = s->stream.msg; 1582 OUTPUT: 1583 RETVAL 1584 1585 1586 uLong 1587 get_Bufsize(s) 1588 Compress::Raw::Zlib::inflateStream s 1589 CODE: 1590 RETVAL = s->bufsize ; 1591 OUTPUT: 1592 RETVAL 1593 1594 bool 1595 set_Append(s, mode) 1596 Compress::Raw::Zlib::inflateStream s 1597 bool mode 1598 CODE: 1599 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND); 1600 if (mode) 1601 s->flags |= FLAG_APPEND ; 1602 else 1603 s->flags &= ~FLAG_APPEND ; 1604 OUTPUT: 1605 RETVAL 1606 1607 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream 1608 1609 void 1610 DESTROY(s) 1611 Compress::Raw::Zlib::inflateScanStream s 1612 CODE: 1613 inflateEnd(&s->stream) ; 1614 if (s->dictionary) 1615 SvREFCNT_dec(s->dictionary) ; 1616 #ifndef SETP_BYTE 1617 if (s->deflateParams_out_buffer) 1618 Safefree(s->deflateParams_out_buffer); 1619 #endif 1620 #ifdef MAGIC_APPEND 1621 if (s->window) 1622 Safefree(s->window); 1623 #endif 1624 Safefree(s) ; 1625 1626 void 1627 DispStream(s, message=NULL) 1628 Compress::Raw::Zlib::inflateScanStream s 1629 char * message 1630 1631 DualType 1632 inflateReset(s) 1633 Compress::Raw::Zlib::inflateScanStream s 1634 CODE: 1635 RETVAL = inflateReset(&(s->stream)) ; 1636 if (RETVAL == Z_OK) { 1637 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; 1638 } 1639 OUTPUT: 1640 RETVAL 1641 1642 DualType 1643 scan(s, buf, out=NULL, eof=FALSE) 1644 Compress::Raw::Zlib::inflateScanStream s 1645 SV * buf 1646 SV * out 1647 bool eof 1648 bool eof_mode = FALSE; 1649 int start_len = NO_INIT 1650 STRLEN stmp = NO_INIT 1651 CODE: 1652 /* If the input buffer is a reference, dereference it */ 1653 #ifndef MAGIC_APPEND 1654 buf = buf; 1655 croak("scan needs zlib 1.2.1 or better"); 1656 #else 1657 buf = deRef(buf, "inflateScan") ; 1658 #ifdef UTF8_AVAILABLE 1659 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 1660 croak("Wide character in Compress::Raw::Zlib::InflateScan::scan input parameter"); 1661 #endif 1662 /* initialise the input buffer */ 1663 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ; 1664 s->stream.avail_in = SvCUR(buf) ; 1665 start_len = s->stream.avail_in ; 1666 s->bytesInflated = 0 ; 1667 do 1668 { 1669 if (s->stream.avail_in == 0) { 1670 RETVAL = Z_OK ; 1671 break ; 1672 } 1673 1674 /* set up output to next available section of sliding window */ 1675 s->stream.avail_out = WINDOW_SIZE - s->window_have; 1676 s->stream.next_out = s->window + s->window_have; 1677 1678 /* DispStream(s, "before inflate\n"); */ 1679 1680 /* inflate and check for errors */ 1681 RETVAL = inflate(&(s->stream), Z_BLOCK); 1682 1683 if (start_len > 1 && ! eof_mode) 1684 s->window_lastByte = *(s->stream.next_in - 1 ) ; 1685 1686 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR || 1687 RETVAL == Z_DATA_ERROR ) 1688 break ; 1689 1690 if (s->flags & FLAG_CRC32 ) 1691 s->crc32 = crc32(s->crc32, s->window + s->window_have, 1692 WINDOW_SIZE - s->window_have - s->stream.avail_out); 1693 1694 if (s->flags & FLAG_ADLER32) 1695 s->adler32 = adler32(s->adler32, s->window + s->window_have, 1696 WINDOW_SIZE - s->window_have - s->stream.avail_out); 1697 1698 s->uncompressedBytes = 1699 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out; 1700 1701 if (s->stream.avail_out) 1702 s->window_have = WINDOW_SIZE - s->stream.avail_out; 1703 else { 1704 s->window_have = 0; 1705 s->window_full = 1; 1706 } 1707 1708 /* process end of block */ 1709 if (s->stream.data_type & 128) { 1710 if (s->stream.data_type & 64) { 1711 s->window_left = s->stream.data_type & 0x1f; 1712 } 1713 else { 1714 s->window_lastbit = s->stream.data_type & 0x1f; 1715 s->lastBlockOffset = s->stream.total_in; 1716 } 1717 } 1718 1719 } while (RETVAL != Z_STREAM_END); 1720 1721 s->last_error = RETVAL ; 1722 s->window_lastoff = s->stream.total_in ; 1723 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; 1724 1725 if (RETVAL == Z_STREAM_END) 1726 { 1727 s->matchedEndBlock = 1 ; 1728 1729 /* save the location of the end of the compressed data */ 1730 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ; 1731 s->window_endOffset = s->stream.total_in ; 1732 if (s->window_left) 1733 { 1734 -- s->window_endOffset ; 1735 } 1736 1737 /* if window wrapped, build dictionary from window by rotating */ 1738 if (s->window_full) { 1739 rotate(s->window, WINDOW_SIZE, s->window_have); 1740 s->window_have = WINDOW_SIZE; 1741 } 1742 1743 /* if (s->flags & FLAG_CONSUME_INPUT) { */ 1744 if (1) { 1745 unsigned in = s->stream.avail_in ; 1746 SvCUR_set(buf, in) ; 1747 if (in) 1748 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; 1749 *SvEND(buf) = '\0'; 1750 SvSETMAGIC(buf); 1751 } 1752 } 1753 #endif 1754 OUTPUT: 1755 RETVAL 1756 1757 1758 uLong 1759 getEndOffset(s) 1760 Compress::Raw::Zlib::inflateScanStream s 1761 CODE: 1762 #ifndef MAGIC_APPEND 1763 croak("getEndOffset needs zlib 1.2.1 or better"); 1764 #else 1765 RETVAL = s->window_endOffset; 1766 #endif 1767 OUTPUT: 1768 RETVAL 1769 1770 uLong 1771 inflateCount(s) 1772 Compress::Raw::Zlib::inflateScanStream s 1773 CODE: 1774 #ifndef MAGIC_APPEND 1775 croak("inflateCount needs zlib 1.2.1 or better"); 1776 #else 1777 RETVAL = s->bytesInflated; 1778 #endif 1779 OUTPUT: 1780 RETVAL 1781 1782 uLong 1783 compressedBytes(s) 1784 Compress::Raw::Zlib::inflateScanStream s 1785 CODE: 1786 RETVAL = s->compressedBytes; 1787 OUTPUT: 1788 RETVAL 1789 1790 uLong 1791 uncompressedBytes(s) 1792 Compress::Raw::Zlib::inflateScanStream s 1793 CODE: 1794 RETVAL = s->uncompressedBytes; 1795 OUTPUT: 1796 RETVAL 1797 1798 1799 uLong 1800 getLastBlockOffset(s) 1801 Compress::Raw::Zlib::inflateScanStream s 1802 CODE: 1803 #ifndef MAGIC_APPEND 1804 croak("getLastBlockOffset needs zlib 1.2.1 or better"); 1805 #else 1806 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0); 1807 #endif 1808 OUTPUT: 1809 RETVAL 1810 1811 uLong 1812 getLastBufferOffset(s) 1813 Compress::Raw::Zlib::inflateScanStream s 1814 CODE: 1815 #ifndef MAGIC_APPEND 1816 croak("getLastBufferOffset needs zlib 1.2.1 or better"); 1817 #else 1818 RETVAL = s->window_lastoff; 1819 #endif 1820 OUTPUT: 1821 RETVAL 1822 1823 void 1824 resetLastBlockByte(s, byte) 1825 Compress::Raw::Zlib::inflateScanStream s 1826 unsigned char* byte 1827 CODE: 1828 #ifndef MAGIC_APPEND 1829 croak("resetLastBlockByte needs zlib 1.2.1 or better"); 1830 #else 1831 if (byte != NULL) 1832 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7)); 1833 #endif 1834 1835 1836 void 1837 _createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize) 1838 Compress::Raw::Zlib::inflateScanStream inf_s 1839 int flags 1840 int level 1841 int method 1842 int windowBits 1843 int memLevel 1844 int strategy 1845 uLong bufsize 1846 PPCODE: 1847 { 1848 #ifndef MAGIC_APPEND 1849 flags = flags; 1850 level = level ; 1851 method = method; 1852 windowBits = windowBits; 1853 memLevel = memLevel; 1854 strategy = strategy; 1855 bufsize= bufsize; 1856 croak("_createDeflateStream needs zlib 1.2.1 or better"); 1857 #else 1858 int err ; 1859 deflateStream s ; 1860 1861 if (trace) 1862 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n", 1863 level, method, windowBits, memLevel, strategy, bufsize) ; 1864 if ((s = InitStream() )) { 1865 1866 s->Level = level; 1867 s->Method = method; 1868 s->WindowBits = windowBits; 1869 s->MemLevel = memLevel; 1870 s->Strategy = strategy; 1871 1872 err = deflateInit2(&(s->stream), level, 1873 method, windowBits, memLevel, strategy); 1874 1875 if (err == Z_OK) { 1876 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have); 1877 s->dict_adler = s->stream.adler ; 1878 } 1879 1880 if (err != Z_OK) { 1881 Safefree(s) ; 1882 s = NULL ; 1883 } 1884 else { 1885 PostInitStream(s, flags, bufsize, windowBits) ; 1886 s->crc32 = inf_s->crc32; 1887 s->adler32 = inf_s->adler32; 1888 s->stream.adler = inf_s->stream.adler ; 1889 /* s->stream.total_out = inf_s->bytesInflated ; */ 1890 s->stream.total_in = inf_s->stream.total_out ; 1891 if (inf_s->window_left) { 1892 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */ 1893 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte); 1894 } 1895 } 1896 } 1897 else 1898 err = Z_MEM_ERROR ; 1899 1900 XPUSHs(sv_setref_pv(sv_newmortal(), 1901 "Compress::Raw::Zlib::deflateStream", (void*)s)); 1902 if (GIMME == G_ARRAY) { 1903 SV * sv = sv_2mortal(newSViv(err)) ; 1904 setDUALstatus(sv, err); 1905 XPUSHs(sv) ; 1906 } 1907 #endif 1908 } 1909 1910 DualType 1911 status(s) 1912 Compress::Raw::Zlib::inflateScanStream s 1913 CODE: 1914 RETVAL = s->last_error ; 1915 OUTPUT: 1916 RETVAL 1917 1918 uLong 1919 crc32(s) 1920 Compress::Raw::Zlib::inflateScanStream s 1921 CODE: 1922 RETVAL = s->crc32 ; 1923 OUTPUT: 1924 RETVAL 1925 1926 1927 uLong 1928 adler32(s) 1929 Compress::Raw::Zlib::inflateScanStream s 1930 CODE: 1931 RETVAL = s->adler32 ; 1932 OUTPUT: 1933 RETVAL 1934 1935