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