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 #define PERL_NO_GET_CONTEXT 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, const char * message) 170 #else 171 DispStream(s, message) 172 di_stream * s; 173 const 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 = sv_2mortal(newSVpv("", 0)); 286 287 return sv ; 288 } 289 290 static SV* 291 #ifdef CAN_PROTOTYPE 292 deRef_l(SV * sv, const char * string) 293 #else 294 deRef_l(sv, string) 295 SV * sv ; 296 char * string ; 297 #endif 298 { 299 dTHX; 300 bool wipe = 0 ; 301 STRLEN na; 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 sv_setpv(sv, "") ; 330 else 331 (void)SvPVbyte_force(sv, na) ; 332 333 return sv ; 334 } 335 336 337 #include "constants.h" 338 339 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_ 340 341 REQUIRE: 1.924 342 PROTOTYPES: DISABLE 343 344 INCLUDE: constants.xs 345 346 BOOT: 347 #ifndef NO_WRITEABLE_DATA 348 trace = TRACE_DEFAULT ; 349 #endif 350 /* Check this version of bzip2 is == 1 */ 351 if (BZ2_bzlibVersion()[0] != '1') 352 croak(COMPRESS_CLASS " needs bzip2 version 1.x, you have %s\n", BZ2_bzlibVersion()) ; 353 354 355 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 356 357 #define bzlibversion() BZ2_bzlibVersion() 358 const char * 359 bzlibversion() 360 361 void 362 new(className, appendOut=1, blockSize100k=1, workfactor=0, verbosity=0) 363 const char * className 364 int appendOut 365 int blockSize100k 366 int workfactor 367 int verbosity 368 PPCODE: 369 { 370 int err ; 371 deflateStream s ; 372 #if 0 373 /* if (trace) */ 374 warn("in Compress::Raw::Bzip2::_new(items=%d,appendOut=%d, blockSize100k=%d, workfactor=%d, verbosity=%d\n", 375 items, appendOut, blockSize100k, workfactor, verbosity); 376 #endif 377 if ((s = InitStream() )) { 378 379 err = BZ2_bzCompressInit ( &(s->stream), 380 blockSize100k, 381 verbosity, 382 workfactor ); 383 384 if (err != BZ_OK) { 385 Safefree(s) ; 386 s = NULL ; 387 } 388 else { 389 int flags = 0 ; 390 if (appendOut) 391 flags |= FLAG_APPEND_OUTPUT; 392 PostInitStream(s, appendOut ? FLAG_APPEND_OUTPUT :0) ; 393 } 394 } 395 else 396 err = BZ_MEM_ERROR ; 397 398 { 399 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s); 400 XPUSHs(obj); 401 } 402 if(0) 403 { 404 SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ; 405 XPUSHs(obj); 406 } 407 if (GIMME == G_ARRAY) { 408 SV * sv = sv_2mortal(newSViv(err)) ; 409 setDUALstatus(sv, err); 410 XPUSHs(sv) ; 411 } 412 } 413 414 MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2 415 416 void 417 new(className, appendOut=1 , consume=1, small=0, verbosity=0, limitOutput=0) 418 const char* className 419 int appendOut 420 int consume 421 int small 422 int verbosity 423 int limitOutput 424 PPCODE: 425 { 426 int err = BZ_OK ; 427 inflateStream s ; 428 #if 0 429 if (trace) 430 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n", 431 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ; 432 #endif 433 if ((s = InitStream() )) { 434 435 err = BZ2_bzDecompressInit (&(s->stream), verbosity, small); 436 if (err != BZ_OK) { 437 Safefree(s) ; 438 s = NULL ; 439 } 440 if (s) { 441 int flags = 0; 442 if (appendOut) 443 flags |= FLAG_APPEND_OUTPUT; 444 if (consume) 445 flags |= FLAG_CONSUME_INPUT; 446 if (limitOutput) 447 flags |= (FLAG_LIMIT_OUTPUT|FLAG_CONSUME_INPUT); 448 PostInitStream(s, flags) ; 449 } 450 } 451 else 452 err = BZ_MEM_ERROR ; 453 454 { 455 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s); 456 XPUSHs(obj); 457 } 458 if (0) 459 { 460 SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ; 461 XPUSHs(obj); 462 } 463 if (GIMME == G_ARRAY) { 464 SV * sv = sv_2mortal(newSViv(err)) ; 465 setDUALstatus(sv, err); 466 XPUSHs(sv) ; 467 } 468 } 469 470 471 472 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 473 474 void 475 DispStream(s, message=NULL) 476 Compress::Raw::Bzip2 s 477 const char * message 478 479 DualType 480 bzdeflate (s, buf, output) 481 Compress::Raw::Bzip2 s 482 SV * buf 483 SV * output 484 uInt cur_length = NO_INIT 485 uInt increment = NO_INIT 486 int RETVAL = 0; 487 uInt bufinc = NO_INIT 488 STRLEN origlen = 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*)SvPV_nomg(buf, origlen) ; 501 s->stream.avail_in = origlen; 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*) SvPVX(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 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ; 523 cur_length += increment ; 524 s->stream.next_out += 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 += origlen - 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*) SvPVX(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 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ; 587 cur_length += increment ; 588 s->stream.next_out += 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*) SvPVX(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 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ; 648 cur_length += increment ; 649 s->stream.next_out += 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 const 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 uInt bufinc = NO_INIT 728 STRLEN na = NO_INIT ; 729 STRLEN origlen = NO_INIT 730 PREINIT: 731 #ifdef UTF8_AVAILABLE 732 bool out_utf8 = FALSE; 733 #endif 734 CODE: 735 bufinc = s->bufsize; 736 /* If the buffer is a reference, dereference it */ 737 buf = deRef(buf, "bzinflate") ; 738 739 if (s->flags & FLAG_CONSUME_INPUT) { 740 if (SvREADONLY(buf)) 741 croak(UNCOMPRESS_CLASS "::bzinflate input parameter cannot be read-only when ConsumeInput is specified"); 742 SvPV_force(buf, na); 743 } 744 #ifdef UTF8_AVAILABLE 745 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) 746 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate input parameter"); 747 #endif 748 749 /* initialise the input buffer */ 750 s->stream.next_in = (char*)SvPV_nomg(buf, origlen) ; 751 s->stream.avail_in = origlen; 752 753 /* and retrieve the output buffer */ 754 output = deRef_l(output, "bzinflate") ; 755 #ifdef UTF8_AVAILABLE 756 if (DO_UTF8(output)) 757 out_utf8 = TRUE ; 758 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) 759 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate output parameter"); 760 #endif 761 if((s->flags & FLAG_APPEND_OUTPUT) != FLAG_APPEND_OUTPUT) { 762 SvCUR_set(output, 0); 763 } 764 765 /* Assume no output buffer - the code below will update if there is any available */ 766 s->stream.avail_out = 0; 767 768 if (SvLEN(output)) { 769 prefix_length = cur_length = SvCUR(output) ; 770 771 if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) 772 { 773 Sv_Grow(output, bufinc + cur_length + 1) ; 774 } 775 776 /* Only setup the stream output pointers if there is spare 777 capacity in the outout SV 778 */ 779 if (SvLEN(output) > cur_length + 1) 780 { 781 s->stream.next_out = (char*) SvPVX(output) + cur_length; 782 increment = SvLEN(output) - cur_length - 1; 783 s->stream.avail_out = increment; 784 } 785 } 786 787 s->bytesInflated = 0; 788 789 RETVAL = BZ_OK; 790 791 while (1) { 792 793 if (s->stream.avail_out == 0) { 794 /* out of space in the output buffer so make it bigger */ 795 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc + 1) ; 796 cur_length += increment ; 797 s->stream.next_out += cur_length ; 798 increment = bufinc ; 799 s->stream.avail_out = increment; 800 bufinc *= 2 ; 801 } 802 803 /* DispStream(s, "pre"); */ 804 RETVAL = BZ2_bzDecompress (&(s->stream)); 805 806 /* 807 printf("Status %d\n", RETVAL); 808 DispStream(s, "apres"); 809 */ 810 if (RETVAL != BZ_OK || s->flags & FLAG_LIMIT_OUTPUT) 811 break ; 812 813 if (s->stream.avail_out == 0) 814 continue ; 815 816 if (s->stream.avail_in == 0) { 817 RETVAL = BZ_OK ; 818 break ; 819 } 820 821 } 822 823 s->last_error = RETVAL ; 824 if (RETVAL == BZ_OK || RETVAL == BZ_STREAM_END) { 825 unsigned in ; 826 827 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; 828 s->uncompressedBytes += s->bytesInflated ; 829 s->compressedBytes += origlen - s->stream.avail_in ; 830 831 SvPOK_only(output); 832 SvCUR_set(output, prefix_length + s->bytesInflated) ; 833 *SvEND(output) = '\0'; 834 #ifdef UTF8_AVAILABLE 835 if (out_utf8) 836 sv_utf8_upgrade(output); 837 #endif 838 SvSETMAGIC(output); 839 840 /* fix the input buffer */ 841 if (s->flags & FLAG_CONSUME_INPUT) { 842 in = s->stream.avail_in ; 843 SvCUR_set(buf, in) ; 844 if (in) 845 Move(s->stream.next_in, SvPVX(buf), in, char) ; 846 *SvEND(buf) = '\0'; 847 SvSETMAGIC(buf); 848 } 849 } 850 OUTPUT: 851 RETVAL 852 853 uLong 854 inflateCount(s) 855 Compress::Raw::Bunzip2 s 856 CODE: 857 RETVAL = s->bytesInflated; 858 OUTPUT: 859 RETVAL 860 861 862 void 863 DESTROY(s) 864 Compress::Raw::Bunzip2 s 865 CODE: 866 BZ2_bzDecompressEnd(&s->stream) ; 867 Safefree(s) ; 868 869 870 uLong 871 status(s) 872 Compress::Raw::Bunzip2 s 873 CODE: 874 RETVAL = s->last_error ; 875 OUTPUT: 876 RETVAL 877 878 uLong 879 total_in_lo32(s) 880 Compress::Raw::Bunzip2 s 881 CODE: 882 RETVAL = s->stream.total_in_lo32 ; 883 OUTPUT: 884 RETVAL 885 886 uLong 887 total_out_lo32(s) 888 Compress::Raw::Bunzip2 s 889 CODE: 890 RETVAL = s->stream.total_out_lo32 ; 891 OUTPUT: 892 RETVAL 893 894 uLong 895 compressedBytes(s) 896 Compress::Raw::Bunzip2 s 897 CODE: 898 RETVAL = s->compressedBytes; 899 OUTPUT: 900 RETVAL 901 902 uLong 903 uncompressedBytes(s) 904 Compress::Raw::Bunzip2 s 905 CODE: 906 RETVAL = s->uncompressedBytes; 907 OUTPUT: 908 RETVAL 909 910 MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_ 911