File Coverage

Bzip2.xs
Criterion Covered Total %
statement 212 290 73.1
branch 129 240 53.7
condition n/a
subroutine n/a
pod n/a
total 341 530 64.3


line stmt bran cond sub pod time code
1             /* Filename: Bzip2.xs
2             * Author : Paul Marquess,
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 51312           deRef(SV * sv, const char * string)
250             #else
251             deRef(sv, string)
252             SV * sv ;
253             char * string;
254             #endif
255             {
256             dTHX;
257 51312 100         SvGETMAGIC(sv);
    50          
258              
259 51312 50         if (SvROK(sv)) {
260 0           sv = SvRV(sv) ;
261 0 0         SvGETMAGIC(sv);
    0          
262 0 0         switch(SvTYPE(sv)) {
263             case SVt_PVAV:
264             case SVt_PVHV:
265             case SVt_PVCV:
266 0           croak("%s: buffer parameter is not a SCALAR reference", string);
267             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 51312 50         if (!SvOK(sv))
    0          
    0          
275 0           sv = sv_2mortal(newSVpv("", 0));
276              
277 51312           return sv ;
278             }
279              
280             static SV*
281             #ifdef CAN_PROTOTYPE
282 51334           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 51334           bool wipe = 0 ;
291             STRLEN na;
292              
293 51334 100         SvGETMAGIC(sv);
    50          
294 51334 100         wipe = ! SvOK(sv) ;
    50          
    50          
295              
296 51334 100         if (SvROK(sv)) {
297 18           sv = SvRV(sv) ;
298 18 50         SvGETMAGIC(sv);
    0          
299 18 50         wipe = ! SvOK(sv) ;
    0          
    0          
300              
301 18 50         switch(SvTYPE(sv)) {
302             case SVt_PVAV:
303             case SVt_PVHV:
304             case SVt_PVCV:
305 0           croak("%s: buffer parameter is not a SCALAR reference", string);
306             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 51334 50         if (SvREADONLY(sv) && PL_curcop != &PL_compiling)
    0          
314 0           croak("%s: buffer parameter is read-only", string);
315              
316 51334 100         SvUPGRADE(sv, SVt_PV);
317              
318 51334 100         if (wipe)
319 30           sv_setpv(sv, "") ;
320             else
321 51304 100         (void)SvPVbyte_force(sv, na) ;
322              
323 51334           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           int flags = 0 ;
377 21 100         if (appendOut)
378 14           flags |= FLAG_APPEND_OUTPUT;
379 21           PostInitStream(s, appendOut ? FLAG_APPEND_OUTPUT :0) ;
380             }
381             }
382             else
383 0           err = BZ_MEM_ERROR ;
384              
385             {
386 21           SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s);
387 21 50         XPUSHs(obj);
388             }
389             if(0)
390             {
391             SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ;
392             XPUSHs(obj);
393             }
394 21 50         if (GIMME_V == G_ARRAY) {
    100          
395 13           SV * sv = sv_2mortal(newSViv(err)) ;
396 13 50         setDUALstatus(sv, err);
397 13 50         XPUSHs(sv) ;
398             }
399             }
400              
401             MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2
402              
403             void
404             new(className, appendOut=1 , consume=1, small=0, verbosity=0, limitOutput=0)
405             const char* className
406             int appendOut
407             int consume
408             int small
409             int verbosity
410             int limitOutput
411             PPCODE:
412             {
413 30           int err = BZ_OK ;
414             inflateStream s ;
415             #if 0
416             if (trace)
417             warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
418             windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
419             #endif
420 30 50         if ((s = InitStream() )) {
421              
422 30           err = BZ2_bzDecompressInit (&(s->stream), verbosity, small);
423 30 50         if (err != BZ_OK) {
424 0           Safefree(s) ;
425 0           s = NULL ;
426             }
427 30 50         if (s) {
428 30           int flags = 0;
429 30 100         if (appendOut)
430 23           flags |= FLAG_APPEND_OUTPUT;
431 30 100         if (consume)
432 16           flags |= FLAG_CONSUME_INPUT;
433 30 100         if (limitOutput)
434 7           flags |= (FLAG_LIMIT_OUTPUT|FLAG_CONSUME_INPUT);
435 30           PostInitStream(s, flags) ;
436             }
437             }
438             else
439 0           err = BZ_MEM_ERROR ;
440              
441             {
442 30           SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s);
443 30 50         XPUSHs(obj);
444             }
445             if (0)
446             {
447             SV* obj = sv_2mortal(newSViv(PTR2IV(s))) ;
448             XPUSHs(obj);
449             }
450 30 50         if (GIMME_V == G_ARRAY) {
    100          
451 19           SV * sv = sv_2mortal(newSViv(err)) ;
452 19 50         setDUALstatus(sv, err);
453 19 50         XPUSHs(sv) ;
454             }
455             }
456              
457              
458              
459             MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2
460              
461             void
462             DispStream(s, message=NULL)
463             Compress::Raw::Bzip2 s
464             const char * message
465              
466             DualType
467             bzdeflate (s, buf, output)
468             Compress::Raw::Bzip2 s
469             SV * buf
470             SV * output
471             uInt cur_length = NO_INIT
472             uInt increment = NO_INIT
473             int RETVAL = 0;
474             uInt bufinc = NO_INIT
475             STRLEN origlen = NO_INIT
476             CODE:
477 205           bufinc = s->bufsize;
478              
479             /* If the input buffer is a reference, dereference it */
480 205           buf = deRef(buf, "deflate") ;
481              
482             /* initialise the input buffer */
483             #ifdef UTF8_AVAILABLE
484 205 50         if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
    0          
    0          
485 0           croak("Wide character in " COMPRESS_CLASS "::bzdeflate input parameter");
486             #endif
487 205 100         s->stream.next_in = (char*)SvPV_nomg(buf, origlen) ;
488 205           s->stream.avail_in = (unsigned int) origlen;
489              
490             /* and retrieve the output buffer */
491 205           output = deRef_l(output, "deflate") ;
492             #ifdef UTF8_AVAILABLE
493 205 50         if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
    0          
    0          
494 0           croak("Wide character in " COMPRESS_CLASS "::bzdeflate output parameter");
495             #endif
496              
497 205 100         if((s->flags & FLAG_APPEND_OUTPUT) == FLAG_APPEND_OUTPUT) {
498 129 100         SvOOK_off(output);
499             } else {
500 76           SvCUR_set(output, 0);
501             }
502 205           cur_length = SvCUR(output) ;
503 205           s->stream.next_out = (char*) SvPVX(output) + cur_length;
504 205           increment = SvLEN(output) - cur_length;
505 205           s->stream.avail_out = increment;
506 410 100         while (s->stream.avail_in != 0) {
507              
508 205 50         if (s->stream.avail_out == 0) {
509             /* out of space in the output buffer so make it bigger */
510 0           s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
511 0           cur_length += increment ;
512 0           s->stream.next_out += cur_length ;
513 0           increment = bufinc ;
514 0           s->stream.avail_out = increment;
515 0           bufinc *= 2 ;
516             }
517              
518 205           RETVAL = BZ2_bzCompress(&(s->stream), BZ_RUN);
519 205 50         if (RETVAL != BZ_RUN_OK)
520 0           break;
521             }
522              
523 205           s->compressedBytes += cur_length + increment - s->stream.avail_out ;
524 205           s->uncompressedBytes += origlen - s->stream.avail_in ;
525              
526 205           s->last_error = RETVAL ;
527 205 50         if (RETVAL == BZ_RUN_OK) {
528 205           SvPOK_only(output);
529 205           SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
530 205 100         SvSETMAGIC(output);
531             }
532             OUTPUT:
533             RETVAL
534              
535              
536             void
537             DESTROY(s)
538             Compress::Raw::Bzip2 s
539             CODE:
540 21           BZ2_bzCompressEnd(&s->stream) ;
541 21           Safefree(s) ;
542              
543              
544             DualType
545             bzclose(s, output)
546             Compress::Raw::Bzip2 s
547             SV * output
548             uInt cur_length = NO_INIT
549             uInt increment = NO_INIT
550             uInt bufinc = NO_INIT
551             CODE:
552 21           bufinc = s->bufsize;
553              
554 21           s->stream.avail_in = 0; /* should be zero already anyway */
555              
556             /* retrieve the output buffer */
557 21           output = deRef_l(output, "close") ;
558             #ifdef UTF8_AVAILABLE
559 21 50         if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
    0          
    0          
560 0           croak("Wide character in " COMPRESS_CLASS "::bzclose input parameter");
561             #endif
562 21 100         if((s->flags & FLAG_APPEND_OUTPUT) == FLAG_APPEND_OUTPUT) {
563 14 100         SvOOK_off(output);
564             } else {
565 7           SvCUR_set(output, 0);
566             }
567 21           cur_length = SvCUR(output) ;
568 21           s->stream.next_out = (char*) SvPVX(output) + cur_length;
569 21           increment = SvLEN(output) - cur_length;
570 21           s->stream.avail_out = increment;
571              
572             for (;;) {
573 39 100         if (s->stream.avail_out == 0) {
574             /* consumed all the available output, so extend it */
575 18           s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
576 18           cur_length += increment ;
577 18           s->stream.next_out += cur_length ;
578 18           increment = bufinc ;
579 18           s->stream.avail_out = increment;
580 18           bufinc *= 2 ;
581             }
582 39           RETVAL = BZ2_bzCompress(&(s->stream), BZ_FINISH);
583              
584             /* deflate has finished flushing only when it hasn't used up
585             * all the available space in the output buffer:
586             */
587             /* if (s->stream.avail_out != 0 || RETVAL < 0 ) */
588 39 100         if (RETVAL == BZ_STREAM_END || RETVAL < 0 )
    50          
589             break;
590 18           }
591              
592             /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */
593 21           s->last_error = RETVAL ;
594              
595 21           s->compressedBytes += cur_length + increment - s->stream.avail_out ;
596              
597 21 50         if (RETVAL == BZ_STREAM_END) {
598 21           SvPOK_only(output);
599 21           SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
600 21 100         SvSETMAGIC(output);
601             }
602             OUTPUT:
603             RETVAL
604              
605              
606             DualType
607             bzflush(s, output)
608             Compress::Raw::Bzip2 s
609             SV * output
610             uInt cur_length = NO_INIT
611             uInt increment = NO_INIT
612             uInt bufinc = NO_INIT
613             CODE:
614 2           bufinc = s->bufsize;
615              
616 2           s->stream.avail_in = 0; /* should be zero already anyway */
617              
618             /* retrieve the output buffer */
619 2           output = deRef_l(output, "close") ;
620             #ifdef UTF8_AVAILABLE
621 2 50         if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
    0          
    0          
622 0           croak("Wide character in " COMPRESS_CLASS "::bzflush input parameter");
623             #endif
624 2 50         if((s->flags & FLAG_APPEND_OUTPUT) == FLAG_APPEND_OUTPUT) {
625 0 0         SvOOK_off(output);
626             } else {
627 2           SvCUR_set(output, 0);
628             }
629 2           cur_length = SvCUR(output) ;
630 2           s->stream.next_out = (char*) SvPVX(output) + cur_length;
631 2           increment = SvLEN(output) - cur_length;
632 2           s->stream.avail_out = increment;
633              
634             for (;;) {
635 4 100         if (s->stream.avail_out == 0) {
636             /* consumed all the available output, so extend it */
637 2           s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
638 2           cur_length += increment ;
639 2           s->stream.next_out += cur_length ;
640 2           increment = bufinc ;
641 2           s->stream.avail_out = increment;
642 2           bufinc *= 2 ;
643             }
644 4           RETVAL = BZ2_bzCompress(&(s->stream), BZ_FLUSH);
645              
646 4 100         if (RETVAL == BZ_RUN_OK || RETVAL < 0)
    50          
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 2           }
655              
656             /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */
657 2           s->last_error = RETVAL ;
658              
659 2           s->compressedBytes += cur_length + increment - s->stream.avail_out ;
660              
661 2 50         if (RETVAL == BZ_RUN_OK) {
662 2           SvPOK_only(output);
663 2           SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
664 2 50         SvSETMAGIC(output);
665             }
666             OUTPUT:
667             RETVAL
668              
669             uLong
670             total_in_lo32(s)
671             Compress::Raw::Bzip2 s
672             CODE:
673 0           RETVAL = s->stream.total_in_lo32 ;
674             OUTPUT:
675             RETVAL
676              
677             uLong
678             total_out_lo32(s)
679             Compress::Raw::Bzip2 s
680             CODE:
681 0           RETVAL = s->stream.total_out_lo32 ;
682             OUTPUT:
683             RETVAL
684              
685             uLong
686             compressedBytes(s)
687             Compress::Raw::Bzip2 s
688             CODE:
689 4           RETVAL = s->compressedBytes;
690             OUTPUT:
691             RETVAL
692              
693             uLong
694             uncompressedBytes(s)
695             Compress::Raw::Bzip2 s
696             CODE:
697 4           RETVAL = s->uncompressedBytes;
698             OUTPUT:
699             RETVAL
700              
701              
702             MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2
703              
704             void
705             DispStream(s, message=NULL)
706             Compress::Raw::Bunzip2 s
707             const char * message
708              
709             DualType
710             bzinflate (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             uInt bufinc = NO_INIT
718             STRLEN na = NO_INIT ;
719             STRLEN origlen = NO_INIT
720             PREINIT:
721             #ifdef UTF8_AVAILABLE
722 51107           bool out_utf8 = FALSE;
723             #endif
724             CODE:
725 51107           bufinc = s->bufsize;
726             /* If the buffer is a reference, dereference it */
727 51107           buf = deRef(buf, "bzinflate") ;
728              
729 51107 100         if (s->flags & FLAG_CONSUME_INPUT) {
730 93 100         if (SvREADONLY(buf))
731 1           croak(UNCOMPRESS_CLASS "::bzinflate input parameter cannot be read-only when ConsumeInput is specified");
732 92 100         SvPV_force(buf, na);
733             }
734             #ifdef UTF8_AVAILABLE
735 51106 50         if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
    0          
    0          
736 0           croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate input parameter");
737             #endif
738              
739             /* initialise the input buffer */
740 51106 100         s->stream.next_in = (char*)SvPV_nomg(buf, origlen) ;
741 51106           s->stream.avail_in = (unsigned int) origlen;
742              
743             /* and retrieve the output buffer */
744 51106           output = deRef_l(output, "bzinflate") ;
745             #ifdef UTF8_AVAILABLE
746 51106 50         if (DO_UTF8(output))
    0          
747 0           out_utf8 = TRUE ;
748 51106 50         if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
    0          
    0          
749 0           croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate output parameter");
750             #endif
751 51106 100         if((s->flags & FLAG_APPEND_OUTPUT) == FLAG_APPEND_OUTPUT) {
752 51035 100         SvOOK_off(output);
753             } else {
754 71           SvCUR_set(output, 0);
755             }
756              
757             /* Assume no output buffer - the code below will update if there is any available */
758 51106           s->stream.avail_out = 0;
759              
760 51106 50         if (SvLEN(output)) {
761 51106           prefix_length = cur_length = SvCUR(output) ;
762              
763 51106 100         if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc)
    50          
764             {
765 20           Sv_Grow(output, bufinc + cur_length + 1) ;
766             }
767              
768             /* Only setup the stream output pointers if there is spare
769             capacity in the outout SV
770             */
771 51106 50         if (SvLEN(output) > cur_length + 1)
772             {
773 51106           s->stream.next_out = (char*) SvPVX(output) + cur_length;
774 51106           increment = SvLEN(output) - cur_length - 1;
775 51106           s->stream.avail_out = increment;
776             }
777             }
778              
779 51106           s->bytesInflated = 0;
780              
781 51106           RETVAL = BZ_OK;
782              
783             while (1) {
784              
785 51127 100         if (s->stream.avail_out == 0) {
786             /* out of space in the output buffer so make it bigger */
787 21           s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc + 1) ;
788 21           cur_length += increment ;
789 21           s->stream.next_out += cur_length ;
790 21           increment = bufinc ;
791 21           s->stream.avail_out = increment;
792 21           bufinc *= 2 ;
793             }
794              
795             /* DispStream(s, "pre"); */
796 51127           RETVAL = BZ2_bzDecompress (&(s->stream));
797              
798             /*
799             printf("Status %d\n", RETVAL);
800             DispStream(s, "apres");
801             */
802 51127 100         if (RETVAL != BZ_OK || s->flags & FLAG_LIMIT_OUTPUT)
    100          
803             break ;
804              
805 51085 100         if (s->stream.avail_out == 0)
806 21           continue ;
807              
808 51064 50         if (s->stream.avail_in == 0) {
809 51064           RETVAL = BZ_OK ;
810 51064           break ;
811             }
812              
813 21           }
814              
815 51106           s->last_error = RETVAL ;
816 51106 100         if (RETVAL == BZ_OK || RETVAL == BZ_STREAM_END) {
    50          
817             unsigned in ;
818              
819 51106           s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
820 51106           s->uncompressedBytes += s->bytesInflated ;
821 51106           s->compressedBytes += origlen - s->stream.avail_in ;
822              
823 51106           SvPOK_only(output);
824 51106           SvCUR_set(output, prefix_length + s->bytesInflated) ;
825 51106           *SvEND(output) = '\0';
826             #ifdef UTF8_AVAILABLE
827 51106 50         if (out_utf8)
828 0           sv_utf8_upgrade(output);
829             #endif
830 51106 100         SvSETMAGIC(output);
831              
832             /* fix the input buffer */
833 51106 100         if (s->flags & FLAG_CONSUME_INPUT) {
834 92           in = s->stream.avail_in ;
835 92           SvCUR_set(buf, in) ;
836 92 100         if (in)
837 17           Move(s->stream.next_in, SvPVX(buf), in, char) ;
838 92           *SvEND(buf) = '\0';
839 92 100         SvSETMAGIC(buf);
840             }
841             }
842             OUTPUT:
843             RETVAL
844              
845             uLong
846             inflateCount(s)
847             Compress::Raw::Bunzip2 s
848             CODE:
849 0           RETVAL = s->bytesInflated;
850             OUTPUT:
851             RETVAL
852              
853              
854             void
855             DESTROY(s)
856             Compress::Raw::Bunzip2 s
857             CODE:
858 30           BZ2_bzDecompressEnd(&s->stream) ;
859 30           Safefree(s) ;
860              
861              
862             uLong
863             status(s)
864             Compress::Raw::Bunzip2 s
865             CODE:
866 0           RETVAL = s->last_error ;
867             OUTPUT:
868             RETVAL
869              
870             uLong
871             total_in_lo32(s)
872             Compress::Raw::Bunzip2 s
873             CODE:
874 12           RETVAL = s->stream.total_in_lo32 ;
875             OUTPUT:
876             RETVAL
877              
878             uLong
879             total_out_lo32(s)
880             Compress::Raw::Bunzip2 s
881             CODE:
882 18           RETVAL = s->stream.total_out_lo32 ;
883             OUTPUT:
884             RETVAL
885              
886             uLong
887             compressedBytes(s)
888             Compress::Raw::Bunzip2 s
889             CODE:
890 4           RETVAL = s->compressedBytes;
891             OUTPUT:
892             RETVAL
893              
894             uLong
895             uncompressedBytes(s)
896             Compress::Raw::Bunzip2 s
897             CODE:
898 4           RETVAL = s->uncompressedBytes;
899             OUTPUT:
900             RETVAL
901              
902             MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_