1 /* Filename: Bzip2.xs 2 * Author : Paul Marquess, <pmqs@cpan.org> 3 * Created : 5th October 2005 4 * Version : 2.000 5 * 6 * Copyright (c) 2005-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 13 #include "EXTERN.h" 14 #include "perl.h" 15 #include "XSUB.h" 16 17 #include "bzlib.h" 18 19 #ifdef USE_PPPORT_H 20 # define NEED_sv_2pv_nolen 21 # include "ppport.h" 22 #endif 23 24 #if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) 25 26 # ifdef SvPVbyte_force 27 # undef SvPVbyte_force 28 # endif 29 30 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp) 31 32 #endif 33 34 #ifndef SvPVbyte_nolen 35 # define SvPVbyte_nolen SvPV_nolen 36 #endif 37 38 39 #if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) 40 # define UTF8_AVAILABLE 41 #endif 42 43 typedef int DualType ; 44 typedef int int_undef ; 45 46 typedef unsigned long uLong; 47 typedef unsigned int uInt; 48 49 typedef struct di_stream { 50 int flags ; 51 #define FLAG_APPEND_OUTPUT 1 52 #define FLAG_CONSUME_INPUT 8 53 #define FLAG_LIMIT_OUTPUT 16 54 bz_stream stream; 55 uInt bufsize; 56 int last_error ; 57 uLong bytesInflated ; 58 uLong compressedBytes ; 59 uLong uncompressedBytes ; 60 61 } di_stream; 62 63 typedef di_stream * deflateStream ; 64 typedef di_stream * Compress__Raw__Bzip2 ; 65 66 typedef di_stream * inflateStream ; 67 typedef di_stream * Compress__Raw__Bunzip2 ; 68 69 #define COMPRESS_CLASS "Compress::Raw::Bzip2" 70 #define UNCOMPRESS_CLASS "Compress::Raw::Bunzip2" 71 72 #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \ 73 Zero(to,1,typ)) 74 75 76 /* static const char * const my_z_errmsg[] = { */ 77 static const char my_z_errmsg[][32] = { 78 "End of Stream", /* BZ_STREAM_END 4 */ 79 "Finish OK", /* BZ_FINISH_OK 3 */ 80 "Flush OK", /* BZ_FLUSH_OK 2 */ 81 "Run OK", /* BZ_RUN_OK 1 */ 82 "", /* BZ_OK 0 */ 83 "Sequence Error", /* BZ_SEQUENCE_ERROR (-1) */ 84 "Param Error", /* BZ_PARAM_ERROR (-2) */ 85 "Memory Error", /* BZ_MEM_ERROR (-3) */ 86 "Data Error", /* BZ_DATA_ERROR (-4) */ 87 "Magic Error", /* BZ_DATA_ERROR_MAGIC (-5) */ 88 "IO Error", /* BZ_IO_ERROR (-6) */ 89 "Unexpected EOF", /* BZ_UNEXPECTED_EOF (-7) */ 90 "Output Buffer Full", /* BZ_OUTBUFF_FULL (-8) */ 91 "Config Error", /* BZ_CONFIG_ERROR (-9) */ 92 ""}; 93 94 #define setDUALstatus(var, err) \ 95 sv_setnv(var, (double)err) ; \ 96 sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \ 97 SvNOK_on(var); 98 99 100 #if defined(__SYMBIAN32__) 101 # define NO_WRITEABLE_DATA 102 #endif 103 104 #define TRACE_DEFAULT 0 105 106 #ifdef NO_WRITEABLE_DATA 107 # define trace TRACE_DEFAULT 108 #else 109 static int trace = TRACE_DEFAULT ; 110 #endif 111 112 /* Dodge PerlIO hiding of these functions. */ 113 #undef printf 114 115 #if 1 116 #define getInnerObject(x) (*av_fetch((AV*)SvRV(x), 0, FALSE)) 117 #else 118 #define getInnerObject(x) ((SV*)SvRV(sv)) 119 #endif 120 121 #ifdef BZ_NO_STDIO 122 void bz_internal_error(int errorcode) 123 { 124 croak("bz_internal_error %d\n", errorcode); 125 } 126 #endif 127 128 static char * 129 #ifdef CAN_PROTOTYPE 130 GetErrorString(int error_no) 131 #else 132 GetErrorString(error_no) 133 int error_no ; 134 #endif 135 { 136 dTHX; 137 char * errstr ; 138 139 #if 0 140 if (error_no == BZ_ERRNO) { 141 errstr = Strerror(errno) ; 142 } 143 else 144 #endif 145 errstr = (char*) my_z_errmsg[4 - error_no]; 146 147 return errstr ; 148 } 149 150 static void 151 #ifdef CAN_PROTOTYPE 152 DispHex(void * ptr, int length) 153 #else 154 DispHex(ptr, length) 155 void * ptr; 156 int length; 157 #endif 158 { 159 char * p = (char*)ptr; 160 int i; 161 for (i = 0; i < length; ++i) { 162 printf(" %02x", 0xFF & *(p+i)); 163 } 164 } 165 166 167 static void 168 #ifdef CAN_PROTOTYPE 169 DispStream(di_stream * s, char * message) 170 #else 171 DispStream(s, message) 172 di_stream * s; 173 char * message; 174 #endif 175 { 176 177 #if 0 178 if (! trace) 179 return ; 180 #endif 181 182 #define EnDis(f) (s->flags & f ? "Enabled" : "Disabled") 183 184 printf("DispStream 0x%p", s) ; 185 if (message) 186 printf(" - %s \n", message) ; 187 printf("\n") ; 188 189 if (!s) { 190 printf(" stream pointer is NULL\n"); 191 } 192 else { 193 printf(" stream 0x%p\n", &(s->stream)); 194 printf(" opaque 0x%p\n", s->stream.opaque); 195 printf(" state 0x%p\n", s->stream.state ); 196 printf(" next_in 0x%p", s->stream.next_in); 197 if (s->stream.next_in){ 198 printf(" =>"); 199 DispHex(s->stream.next_in, 4); 200 } 201 printf("\n"); 202 203 printf(" next_out 0x%p", s->stream.next_out); 204 if (s->stream.next_out){ 205 printf(" =>"); 206 DispHex(s->stream.next_out, 4); 207 } 208 printf("\n"); 209 210 printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in); 211 printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out); 212 printf(" bufsize %lu\n", (unsigned long)s->bufsize); 213 printf(" total_in_lo32 %u\n", s->stream.total_in_lo32); 214 printf(" total_in_hi32 %u\n", s->stream.total_in_hi32); 215 printf(" total_out_lo32 %u\n", s->stream.total_out_lo32); 216 printf(" total_out_hi32 %u\n", s->stream.total_out_hi32); 217 printf(" flags 0x%x\n", s->flags); 218 printf(" APPEND %s\n", EnDis(FLAG_APPEND_OUTPUT)); 219 printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT)); 220 printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT)); 221 222 printf("\n"); 223 224 } 225 } 226 227 static di_stream * 228 #ifdef CAN_PROTOTYPE 229 InitStream(void) 230 #else 231 InitStream() 232 #endif 233 { 234 di_stream *s ; 235 236 ZMALLOC(s, di_stream) ; 237 238 return s ; 239 240 } 241 242 static void 243 #ifdef CAN_PROTOTYPE 244 PostInitStream(di_stream * s, int flags) 245 #else 246 PostInitStream(s, flags) 247 di_stream *s ; 248 int flags ; 249 #endif 250 { 251 s->bufsize = 1024 * 16 ; 252 s->last_error = 0 ; 253 s->flags = flags ; 254 } 255 256 257 static SV* 258 #ifdef CAN_PROTOTYPE 259 deRef(SV * sv, const char * string) 260 #else 261 deRef(sv, string) 262 SV * sv ; 263 char * string; 264 #endif 265 { 266 dTHX; 267 SvGETMAGIC(sv); 268 269 if (SvROK(sv)) { 270 sv = SvRV(sv) ; 271 SvGETMAGIC(sv); 272 switch(SvTYPE(sv)) { 273 case SVt_PVAV: 274 case SVt_PVHV: 275 case SVt_PVCV: 276 croak("%s: buffer parameter is not a SCALAR reference", string); 277 default: 278 break; 279 } 280 if (SvROK(sv)) 281 croak("%s: buffer parameter is a reference to a reference", string) ; 282 } 283 284 if (!SvOK(sv)) { 285 sv = newSVpv("", 0); 286 } 287 288 return sv ; 289 } 290 291 static SV* 292 #ifdef CAN_PROTOTYPE 293 deRef_l(SV * sv, const char * string) 294 #else 295 deRef_l(sv, string) 296 SV * sv ; 297 char * string ; 298 #endif 299 { 300 dTHX; 301 bool wipe = 0 ; 302 303 SvGETMAGIC(sv); 304 wipe = ! SvOK(sv) ; 305 306 if (SvROK(sv)) { 307 sv = SvRV(sv) ; 308 SvGETMAGIC(sv); 309 wipe = ! SvOK(sv) ; 310 311 switch(SvTYPE(sv)) { 312 case SVt_PVAV: 313 case SVt_PVHV: 314 case SVt_PVCV: 315 croak("%s: buffer parameter is not a SCALAR reference", string); 316 default: 317 break; 318 } 319 if (SvROK(sv)) 320 croak("%s: buffer parameter is a reference to a reference", string) ; 321 } 322 323 if (SvREADONLY(sv) && PL_curcop != &PL_compiling) 324 croak("%s: buffer parameter is read-only", string); 325 326 SvUPGRADE(sv, SVt_PV); 327 328 if (wipe) 329 SvCUR_set(sv, 0); 330 331 SvOOK_off(sv); 332 SvPOK_only(sv); 333 334 return sv ; 335 } 336 337 338 #include "constants.h" 339 340 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_ 341 342 REQUIRE: 1.924 343 PROTOTYPES: DISABLE 344 345 INCLUDE: constants.xs 346 347 BOOT: 348 #ifndef NO_WRITEABLE_DATA 349 trace = TRACE_DEFAULT ; 350 #endif 351 /* Check this version of bzip2 is == 1 */ 352 if (BZ2_bzlibVersion()[0] != '1') 353 croak(COMPRESS_CLASS " needs bzip2 version 1.x, you have %s\n", BZ2_bzlibVersion()) ; 354 355 356 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 357 358 #define bzlibversion() BZ2_bzlibVersion() 359 const char * 360 bzlibversion() 361 362 void 363 new(className, appendOut=1, blockSize100k=1, workfactor=0, verbosity=0) 364 const char * className 365 int appendOut 366 int blockSize100k 367 int workfactor 368 int verbosity 369 PPCODE: 370 { 371 int err ; 372 deflateStream s ; 373 #if 0 374 /* if (trace) */ 375 warn("in Compress::Raw::Bzip2::_new(items=%d,appendOut=%d, blockSize100k=%d, workfactor=%d, verbosity=%d\n", 376 items, appendOut, blockSize100k, workfactor, verbosity); 377 #endif 378 if ((s = InitStream() )) { 379 380 err = BZ2_bzCompressInit ( &(s->stream), 381 blockSize100k, 382 verbosity, 383 workfactor ); 384 385 if (err != BZ_OK) { 386 Safefree(s) ; 387 s = NULL ; 388 } 389 else { 390 int flags = 0 ; 391 if (appendOut) 392 flags |= FLAG_APPEND_OUTPUT; 393 PostInitStream(s, appendOut ? FLAG_APPEND_OUTPUT :0) ; 394 } 395 } 396 else 397 err = BZ_MEM_ERROR ; 398 399 { 400 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s); 401 XPUSHs(obj); 402 } 403 if(0) 404 { 405 SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ; 406 XPUSHs(obj); 407 } 408 if (GIMME == G_ARRAY) { 409 SV * sv = sv_2mortal(newSViv(err)) ; 410 setDUALstatus(sv, err); 411 XPUSHs(sv) ; 412 } 413 } 414 415 MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2 416 417 void 418 new(className, appendOut=1 , consume=1, small=0, verbosity=0, limitOutput=0) 419 const char* className 420 int appendOut 421 int consume 422 int small 423 int verbosity 424 int limitOutput 425 PPCODE: 426 { 427 int err = BZ_OK ; 428 inflateStream s ; 429 #if 0 430 if (trace) 431 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n", 432 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ; 433 #endif 434 if ((s = InitStream() )) { 435 436 err = BZ2_bzDecompressInit (&(s->stream), verbosity, small); 437 if (err != BZ_OK) { 438 Safefree(s) ; 439 s = NULL ; 440 } 441 if (s) { 442 int flags = 0; 443 if (appendOut) 444 flags |= FLAG_APPEND_OUTPUT; 445 if (consume) 446 flags |= FLAG_CONSUME_INPUT; 447 if (limitOutput) 448 flags |= (FLAG_LIMIT_OUTPUT|FLAG_CONSUME_INPUT); 449 PostInitStream(s, flags) ; 450 } 451 } 452 else 453 err = BZ_MEM_ERROR ; 454 455 { 456 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s); 457 XPUSHs(obj); 458 } 459 if (0) 460 { 461 SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ; 462 XPUSHs(obj); 463 } 464 if (GIMME == G_ARRAY) { 465 SV * sv = sv_2mortal(newSViv(err)) ; 466 setDUALstatus(sv, err); 467 XPUSHs(sv) ; 468 } 469 } 470 471 472 473 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 474 475 void 476 DispStream(s, message=NULL) 477 Compress::Raw::Bzip2 s 478 char * message 479 480 DualType 481 bzdeflate (s, buf, output) 482 Compress::Raw::Bzip2 s 483 SV * buf 484 SV * output 485 uInt cur_length = NO_INIT 486 uInt increment = NO_INIT 487 int RETVAL = 0; 488 uInt bufinc = NO_INIT 489 CODE: 490 bufinc = s->bufsize; 491 492 /* If the input buffer is a reference, dereference it */ 493 buf = deRef(buf, "deflate") ; 494 495 /* initialise the input buffer */ 496 #ifdef UTF8_AVAILABLE 497 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 498 croak("Wide character in " COMPRESS_CLASS "::bzdeflate input parameter"); 499 #endif 500 s->stream.next_in = (char*)SvPVbyte_nolen(buf) ; 501 s->stream.avail_in = SvCUR(buf) ; 502 503 /* and retrieve the output buffer */ 504 output = deRef_l(output, "deflate") ; 505 #ifdef UTF8_AVAILABLE 506 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 507 croak("Wide character in " COMPRESS_CLASS "::bzdeflate output parameter"); 508 #endif 509 510 if((s->flags & FLAG_APPEND_OUTPUT) != FLAG_APPEND_OUTPUT) { 511 SvCUR_set(output, 0); 512 /* sv_setpvn(output, "", 0); */ 513 } 514 cur_length = SvCUR(output) ; 515 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length; 516 increment = SvLEN(output) - cur_length; 517 s->stream.avail_out = increment; 518 while (s->stream.avail_in != 0) { 519 520 if (s->stream.avail_out == 0) { 521 /* out of space in the output buffer so make it bigger */ 522 Sv_Grow(output, SvLEN(output) + bufinc) ; 523 cur_length += increment ; 524 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length ; 525 increment = bufinc ; 526 s->stream.avail_out = increment; 527 bufinc *= 2 ; 528 } 529 530 RETVAL = BZ2_bzCompress(&(s->stream), BZ_RUN); 531 if (RETVAL != BZ_RUN_OK) 532 break; 533 } 534 535 s->compressedBytes += cur_length + increment - s->stream.avail_out ; 536 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ; 537 538 s->last_error = RETVAL ; 539 if (RETVAL == BZ_RUN_OK) { 540 SvPOK_only(output); 541 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; 542 SvSETMAGIC(output); 543 } 544 OUTPUT: 545 RETVAL 546 547 548 void 549 DESTROY(s) 550 Compress::Raw::Bzip2 s 551 CODE: 552 BZ2_bzCompressEnd(&s->stream) ; 553 Safefree(s) ; 554 555 556 DualType 557 bzclose(s, output) 558 Compress::Raw::Bzip2 s 559 SV * output 560 uInt cur_length = NO_INIT 561 uInt increment = NO_INIT 562 uInt bufinc = NO_INIT 563 CODE: 564 bufinc = s->bufsize; 565 566 s->stream.avail_in = 0; /* should be zero already anyway */ 567 568 /* retrieve the output buffer */ 569 output = deRef_l(output, "close") ; 570 #ifdef UTF8_AVAILABLE 571 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 572 croak("Wide character in " COMPRESS_CLASS "::bzclose input parameter"); 573 #endif 574 if(! s->flags & FLAG_APPEND_OUTPUT) { 575 SvCUR_set(output, 0); 576 /* sv_setpvn(output, "", 0); */ 577 } 578 cur_length = SvCUR(output) ; 579 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length; 580 increment = SvLEN(output) - cur_length; 581 s->stream.avail_out = increment; 582 583 for (;;) { 584 if (s->stream.avail_out == 0) { 585 /* consumed all the available output, so extend it */ 586 Sv_Grow(output, SvLEN(output) + bufinc) ; 587 cur_length += increment ; 588 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length ; 589 increment = bufinc ; 590 s->stream.avail_out = increment; 591 bufinc *= 2 ; 592 } 593 RETVAL = BZ2_bzCompress(&(s->stream), BZ_FINISH); 594 595 /* deflate has finished flushing only when it hasn't used up 596 * all the available space in the output buffer: 597 */ 598 /* if (s->stream.avail_out != 0 || RETVAL < 0 ) */ 599 if (RETVAL == BZ_STREAM_END || RETVAL < 0 ) 600 break; 601 } 602 603 /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */ 604 s->last_error = RETVAL ; 605 606 s->compressedBytes += cur_length + increment - s->stream.avail_out ; 607 608 if (RETVAL == BZ_STREAM_END) { 609 SvPOK_only(output); 610 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; 611 SvSETMAGIC(output); 612 } 613 OUTPUT: 614 RETVAL 615 616 617 DualType 618 bzflush(s, output) 619 Compress::Raw::Bzip2 s 620 SV * output 621 uInt cur_length = NO_INIT 622 uInt increment = NO_INIT 623 uInt bufinc = NO_INIT 624 CODE: 625 bufinc = s->bufsize; 626 627 s->stream.avail_in = 0; /* should be zero already anyway */ 628 629 /* retrieve the output buffer */ 630 output = deRef_l(output, "close") ; 631 #ifdef UTF8_AVAILABLE 632 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 633 croak("Wide character in " COMPRESS_CLASS "::bzflush input parameter"); 634 #endif 635 if(! s->flags & FLAG_APPEND_OUTPUT) { 636 SvCUR_set(output, 0); 637 /* sv_setpvn(output, "", 0); */ 638 } 639 cur_length = SvCUR(output) ; 640 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length; 641 increment = SvLEN(output) - cur_length; 642 s->stream.avail_out = increment; 643 644 for (;;) { 645 if (s->stream.avail_out == 0) { 646 /* consumed all the available output, so extend it */ 647 Sv_Grow(output, SvLEN(output) + bufinc) ; 648 cur_length += increment ; 649 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length ; 650 increment = bufinc ; 651 s->stream.avail_out = increment; 652 bufinc *= 2 ; 653 } 654 RETVAL = BZ2_bzCompress(&(s->stream), BZ_FLUSH); 655 656 if (RETVAL == BZ_RUN_OK || RETVAL < 0) 657 break; 658 659 /* deflate has finished flushing only when it hasn't used up 660 * all the available space in the output buffer: 661 */ 662 /* RETVAL == if (s->stream.avail_out != 0 || RETVAL < 0 ) 663 break; */ 664 } 665 666 /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */ 667 s->last_error = RETVAL ; 668 669 s->compressedBytes += cur_length + increment - s->stream.avail_out ; 670 671 if (RETVAL == BZ_RUN_OK) { 672 SvPOK_only(output); 673 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; 674 SvSETMAGIC(output); 675 } 676 OUTPUT: 677 RETVAL 678 679 uLong 680 total_in_lo32(s) 681 Compress::Raw::Bzip2 s 682 CODE: 683 RETVAL = s->stream.total_in_lo32 ; 684 OUTPUT: 685 RETVAL 686 687 uLong 688 total_out_lo32(s) 689 Compress::Raw::Bzip2 s 690 CODE: 691 RETVAL = s->stream.total_out_lo32 ; 692 OUTPUT: 693 RETVAL 694 695 uLong 696 compressedBytes(s) 697 Compress::Raw::Bzip2 s 698 CODE: 699 RETVAL = s->compressedBytes; 700 OUTPUT: 701 RETVAL 702 703 uLong 704 uncompressedBytes(s) 705 Compress::Raw::Bzip2 s 706 CODE: 707 RETVAL = s->uncompressedBytes; 708 OUTPUT: 709 RETVAL 710 711 712 MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2 713 714 void 715 DispStream(s, message=NULL) 716 Compress::Raw::Bunzip2 s 717 char * message 718 719 DualType 720 bzinflate (s, buf, output) 721 Compress::Raw::Bunzip2 s 722 SV * buf 723 SV * output 724 uInt cur_length = 0; 725 uInt prefix_length = 0; 726 uInt increment = 0; 727 STRLEN stmp = NO_INIT 728 uInt bufinc = NO_INIT 729 PREINIT: 730 #ifdef UTF8_AVAILABLE 731 bool out_utf8 = FALSE; 732 #endif 733 CODE: 734 bufinc = s->bufsize; 735 /* If the buffer is a reference, dereference it */ 736 buf = deRef(buf, "bzinflate") ; 737 738 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf)) 739 croak(UNCOMPRESS_CLASS "::bzinflate input parameter cannot be read-only when ConsumeInput is specified"); 740 #ifdef UTF8_AVAILABLE 741 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 742 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate input parameter"); 743 #endif 744 745 /* initialise the input buffer */ 746 s->stream.next_in = (char*)SvPVbyte_force(buf, stmp) ; 747 s->stream.avail_in = SvCUR(buf); 748 749 /* and retrieve the output buffer */ 750 output = deRef_l(output, "bzinflate") ; 751 #ifdef UTF8_AVAILABLE 752 if (DO_UTF8(output)) 753 out_utf8 = TRUE ; 754 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 755 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate output parameter"); 756 #endif 757 if((s->flags & FLAG_APPEND_OUTPUT) != FLAG_APPEND_OUTPUT) { 758 SvCUR_set(output, 0); 759 } 760 761 /* Assume no output buffer - the code below will update if there is any available */ 762 s->stream.avail_out = 0; 763 764 if (SvLEN(output)) { 765 prefix_length = cur_length = SvCUR(output) ; 766 767 if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) 768 { 769 Sv_Grow(output, bufinc + cur_length + 1) ; 770 } 771 772 /* Only setup the stream output pointers if there is spare 773 capacity in the outout SV 774 */ 775 if (SvLEN(output) > cur_length + 1) 776 { 777 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length; 778 increment = SvLEN(output) - cur_length - 1; 779 s->stream.avail_out = increment; 780 } 781 } 782 783 s->bytesInflated = 0; 784 785 RETVAL = BZ_OK; 786 787 while (1) { 788 789 if (s->stream.avail_out == 0) { 790 /* out of space in the output buffer so make it bigger */ 791 Sv_Grow(output, SvLEN(output) + bufinc + 1) ; 792 cur_length += increment ; 793 s->stream.next_out = (char*) SvPVbyte_nolen(output) + cur_length ; 794 increment = bufinc ; 795 s->stream.avail_out = increment; 796 bufinc *= 2 ; 797 } 798 799 /* DispStream(s, "pre"); */ 800 RETVAL = BZ2_bzDecompress (&(s->stream)); 801 802 /* DispStream(s, "apres"); */ 803 if (RETVAL != BZ_OK || s->flags & FLAG_LIMIT_OUTPUT) 804 break ; 805 806 if (s->stream.avail_out == 0) 807 continue ; 808 809 if (s->stream.avail_in == 0) { 810 RETVAL = BZ_OK ; 811 break ; 812 } 813 814 } 815 816 s->last_error = RETVAL ; 817 if (RETVAL == BZ_OK || RETVAL == BZ_STREAM_END) { 818 unsigned in ; 819 820 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; 821 s->uncompressedBytes += s->bytesInflated ; 822 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; 823 824 SvPOK_only(output); 825 SvCUR_set(output, prefix_length + s->bytesInflated) ; 826 *SvEND(output) = '\0'; 827 #ifdef UTF8_AVAILABLE 828 if (out_utf8) 829 sv_utf8_upgrade(output); 830 #endif 831 SvSETMAGIC(output); 832 833 /* fix the input buffer */ 834 if (s->flags & FLAG_CONSUME_INPUT) { 835 in = s->stream.avail_in ; 836 SvCUR_set(buf, in) ; 837 if (in) 838 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; 839 *SvEND(buf) = '\0'; 840 SvSETMAGIC(buf); 841 } 842 } 843 OUTPUT: 844 RETVAL 845 846 uLong 847 inflateCount(s) 848 Compress::Raw::Bunzip2 s 849 CODE: 850 RETVAL = s->bytesInflated; 851 OUTPUT: 852 RETVAL 853 854 855 void 856 DESTROY(s) 857 Compress::Raw::Bunzip2 s 858 CODE: 859 BZ2_bzDecompressEnd(&s->stream) ; 860 Safefree(s) ; 861 862 863 uLong 864 status(s) 865 Compress::Raw::Bunzip2 s 866 CODE: 867 RETVAL = s->last_error ; 868 OUTPUT: 869 RETVAL 870 871 uLong 872 total_in_lo32(s) 873 Compress::Raw::Bunzip2 s 874 CODE: 875 RETVAL = s->stream.total_in_lo32 ; 876 OUTPUT: 877 RETVAL 878 879 uLong 880 total_out_lo32(s) 881 Compress::Raw::Bunzip2 s 882 CODE: 883 RETVAL = s->stream.total_out_lo32 ; 884 OUTPUT: 885 RETVAL 886 887 uLong 888 compressedBytes(s) 889 Compress::Raw::Bunzip2 s 890 CODE: 891 RETVAL = s->compressedBytes; 892 OUTPUT: 893 RETVAL 894 895 uLong 896 uncompressedBytes(s) 897 Compress::Raw::Bunzip2 s 898 CODE: 899 RETVAL = s->uncompressedBytes; 900 OUTPUT: 901 RETVAL 902 903 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_ 904