File Coverage

Bzip2.xs
Criterion Covered Total %
statement 207 288 71.8
branch 121 232 52.1
condition n/a
subroutine n/a
pod n/a
total 328 520 63.0


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