This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Digest-SHA to CPAN version 5.74
[perl5.git] / cpan / Compress-Raw-Bzip2 / Bzip2.xs
CommitLineData
bdb7fd9f
RGS
1/* Filename: Bzip2.xs
2 * Author : Paul Marquess, <pmqs@cpan.org>
3 * Created : 5th October 2005
4 * Version : 2.000
5 *
9b5fd1d4 6 * Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
bdb7fd9f
RGS
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
14c0f22a 12#define PERL_NO_GET_CONTEXT
bdb7fd9f
RGS
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
ea6efd2c 53#define FLAG_LIMIT_OUTPUT 16
bdb7fd9f
RGS
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
63typedef di_stream * deflateStream ;
64typedef di_stream * Compress__Raw__Bzip2 ;
65
66typedef di_stream * inflateStream ;
67typedef 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[] = { */
77static 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
122void bz_internal_error(int errorcode)
123{
124 croak("bz_internal_error %d\n", errorcode);
125}
126#endif
127
128static char *
129#ifdef CAN_PROTOTYPE
130GetErrorString(int error_no)
131#else
132GetErrorString(error_no)
133int 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
150static void
151#ifdef CAN_PROTOTYPE
152DispHex(void * ptr, int length)
153#else
154DispHex(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
167static void
168#ifdef CAN_PROTOTYPE
169DispStream(di_stream * s, char * message)
170#else
171DispStream(s, message)
172 di_stream * s;
173 char * message;
174#endif
175{
176
177#if 0
178 if (! trace)
179 return ;
180#endif
181
182#define EnDis(f) (s->flags & f ? "Enabled" : "Disabled")
183
184 printf("DispStream 0x%p", s) ;
185 if (message)
ea6efd2c 186 printf(" - %s \n", message) ;
bdb7fd9f
RGS
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);
ea6efd2c 195 printf(" state 0x%p\n", s->stream.state );
bdb7fd9f
RGS
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);
ea6efd2c
MB
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);
bdb7fd9f
RGS
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));
ea6efd2c 220 printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT));
bdb7fd9f
RGS
221
222 printf("\n");
223
224 }
225}
226
227static di_stream *
228#ifdef CAN_PROTOTYPE
229InitStream(void)
230#else
231InitStream()
232#endif
233{
234 di_stream *s ;
235
236 ZMALLOC(s, di_stream) ;
237
238 return s ;
239
240}
241
242static void
243#ifdef CAN_PROTOTYPE
244PostInitStream(di_stream * s, int flags)
245#else
246PostInitStream(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
257static SV*
258#ifdef CAN_PROTOTYPE
259deRef(SV * sv, const char * string)
260#else
261deRef(sv, string)
262SV * sv ;
263char * 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);
776304fb
PM
277 default:
278 break;
bdb7fd9f
RGS
279 }
280 if (SvROK(sv))
281 croak("%s: buffer parameter is a reference to a reference", string) ;
282 }
283
4bac9ae4
CS
284 if (!SvOK(sv))
285 sv = sv_2mortal(newSVpv("", 0));
bdb7fd9f
RGS
286
287 return sv ;
288}
289
290static SV*
291#ifdef CAN_PROTOTYPE
292deRef_l(SV * sv, const char * string)
293#else
294deRef_l(sv, string)
295SV * sv ;
296char * string ;
297#endif
298{
299 dTHX;
300 bool wipe = 0 ;
4bac9ae4 301 STRLEN na;
bdb7fd9f
RGS
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);
776304fb
PM
316 default:
317 break;
bdb7fd9f
RGS
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
9d90bd60
PM
326 SvUPGRADE(sv, SVt_PV);
327
bdb7fd9f 328 if (wipe)
9d90bd60 329 sv_setpv(sv, "") ;
4bac9ae4
CS
330 else
331 (void)SvPVbyte_force(sv, na) ;
9d90bd60 332
bdb7fd9f
RGS
333 return sv ;
334}
335
336
337#include "constants.h"
338
339MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_
340
341REQUIRE: 1.924
342PROTOTYPES: DISABLE
343
344INCLUDE: constants.xs
345
346BOOT:
c14f59c3
PM
347#ifndef NO_WRITEABLE_DATA
348 trace = TRACE_DEFAULT ;
349#endif
bdb7fd9f
RGS
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
355MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2
356
357#define bzlibversion() BZ2_bzlibVersion()
358const char *
359bzlibversion()
360
361void
c14f59c3
PM
362new(className, appendOut=1, blockSize100k=1, workfactor=0, verbosity=0)
363 const char * className
bdb7fd9f
RGS
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 {
c14f59c3 399 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s);
bdb7fd9f
RGS
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
414MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2
415
416void
ea6efd2c 417new(className, appendOut=1 , consume=1, small=0, verbosity=0, limitOutput=0)
c14f59c3 418 const char* className
bdb7fd9f
RGS
419 int appendOut
420 int consume
421 int small
422 int verbosity
ea6efd2c 423 int limitOutput
bdb7fd9f
RGS
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;
ea6efd2c
MB
446 if (limitOutput)
447 flags |= (FLAG_LIMIT_OUTPUT|FLAG_CONSUME_INPUT);
bdb7fd9f
RGS
448 PostInitStream(s, flags) ;
449 }
450 }
451 else
452 err = BZ_MEM_ERROR ;
453
454 {
c14f59c3 455 SV* obj = sv_setref_pv(sv_newmortal(), className, (void*)s);
bdb7fd9f
RGS
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
472MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2
473
474void
475DispStream(s, message=NULL)
476 Compress::Raw::Bzip2 s
477 char * message
478
479DualType
480bzdeflate (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 CODE:
489 bufinc = s->bufsize;
490
491 /* If the input buffer is a reference, dereference it */
492 buf = deRef(buf, "deflate") ;
493
494 /* initialise the input buffer */
495#ifdef UTF8_AVAILABLE
496 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
497 croak("Wide character in " COMPRESS_CLASS "::bzdeflate input parameter");
9d90bd60 498#endif
14c0f22a 499 s->stream.next_in = (char*)SvPV_nomg_nolen(buf) ;
9d90bd60 500 s->stream.avail_in = SvCUR(buf) ;
bdb7fd9f
RGS
501
502 /* and retrieve the output buffer */
503 output = deRef_l(output, "deflate") ;
504#ifdef UTF8_AVAILABLE
505 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
506 croak("Wide character in " COMPRESS_CLASS "::bzdeflate output parameter");
507#endif
9d90bd60
PM
508
509 if((s->flags & FLAG_APPEND_OUTPUT) != FLAG_APPEND_OUTPUT) {
bdb7fd9f 510 SvCUR_set(output, 0);
9d90bd60
PM
511 /* sv_setpvn(output, "", 0); */
512 }
bdb7fd9f 513 cur_length = SvCUR(output) ;
9d90bd60 514 s->stream.next_out = (char*) SvPVX(output) + cur_length;
bdb7fd9f
RGS
515 increment = SvLEN(output) - cur_length;
516 s->stream.avail_out = increment;
517 while (s->stream.avail_in != 0) {
518
519 if (s->stream.avail_out == 0) {
520 /* out of space in the output buffer so make it bigger */
9d90bd60 521 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
bdb7fd9f 522 cur_length += increment ;
9d90bd60 523 s->stream.next_out += cur_length ;
bdb7fd9f
RGS
524 increment = bufinc ;
525 s->stream.avail_out = increment;
526 bufinc *= 2 ;
527 }
528
529 RETVAL = BZ2_bzCompress(&(s->stream), BZ_RUN);
530 if (RETVAL != BZ_RUN_OK)
531 break;
532 }
533
534 s->compressedBytes += cur_length + increment - s->stream.avail_out ;
535 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ;
536
537 s->last_error = RETVAL ;
538 if (RETVAL == BZ_RUN_OK) {
539 SvPOK_only(output);
540 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
541 SvSETMAGIC(output);
542 }
543 OUTPUT:
544 RETVAL
545
546
547void
548DESTROY(s)
549 Compress::Raw::Bzip2 s
550 CODE:
551 BZ2_bzCompressEnd(&s->stream) ;
552 Safefree(s) ;
553
554
555DualType
556bzclose(s, output)
557 Compress::Raw::Bzip2 s
558 SV * output
559 uInt cur_length = NO_INIT
560 uInt increment = NO_INIT
561 uInt bufinc = NO_INIT
562 CODE:
563 bufinc = s->bufsize;
564
565 s->stream.avail_in = 0; /* should be zero already anyway */
566
567 /* retrieve the output buffer */
568 output = deRef_l(output, "close") ;
569#ifdef UTF8_AVAILABLE
570 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
571 croak("Wide character in " COMPRESS_CLASS "::bzclose input parameter");
572#endif
9d90bd60 573 if(! s->flags & FLAG_APPEND_OUTPUT) {
bdb7fd9f 574 SvCUR_set(output, 0);
9d90bd60
PM
575 /* sv_setpvn(output, "", 0); */
576 }
bdb7fd9f 577 cur_length = SvCUR(output) ;
9d90bd60 578 s->stream.next_out = (char*) SvPVX(output) + cur_length;
bdb7fd9f
RGS
579 increment = SvLEN(output) - cur_length;
580 s->stream.avail_out = increment;
581
582 for (;;) {
583 if (s->stream.avail_out == 0) {
584 /* consumed all the available output, so extend it */
9d90bd60 585 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
bdb7fd9f 586 cur_length += increment ;
9d90bd60 587 s->stream.next_out += cur_length ;
bdb7fd9f
RGS
588 increment = bufinc ;
589 s->stream.avail_out = increment;
590 bufinc *= 2 ;
591 }
592 RETVAL = BZ2_bzCompress(&(s->stream), BZ_FINISH);
593
594 /* deflate has finished flushing only when it hasn't used up
595 * all the available space in the output buffer:
596 */
597 /* if (s->stream.avail_out != 0 || RETVAL < 0 ) */
598 if (RETVAL == BZ_STREAM_END || RETVAL < 0 )
599 break;
600 }
601
602 /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */
603 s->last_error = RETVAL ;
604
605 s->compressedBytes += cur_length + increment - s->stream.avail_out ;
606
607 if (RETVAL == BZ_STREAM_END) {
608 SvPOK_only(output);
609 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
610 SvSETMAGIC(output);
611 }
612 OUTPUT:
613 RETVAL
614
615
616DualType
617bzflush(s, output)
618 Compress::Raw::Bzip2 s
619 SV * output
620 uInt cur_length = NO_INIT
621 uInt increment = NO_INIT
622 uInt bufinc = NO_INIT
623 CODE:
624 bufinc = s->bufsize;
625
626 s->stream.avail_in = 0; /* should be zero already anyway */
627
628 /* retrieve the output buffer */
629 output = deRef_l(output, "close") ;
630#ifdef UTF8_AVAILABLE
631 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
632 croak("Wide character in " COMPRESS_CLASS "::bzflush input parameter");
633#endif
9d90bd60 634 if(! s->flags & FLAG_APPEND_OUTPUT) {
bdb7fd9f 635 SvCUR_set(output, 0);
9d90bd60
PM
636 /* sv_setpvn(output, "", 0); */
637 }
bdb7fd9f 638 cur_length = SvCUR(output) ;
9d90bd60 639 s->stream.next_out = (char*) SvPVX(output) + cur_length;
bdb7fd9f
RGS
640 increment = SvLEN(output) - cur_length;
641 s->stream.avail_out = increment;
642
643 for (;;) {
644 if (s->stream.avail_out == 0) {
645 /* consumed all the available output, so extend it */
9d90bd60 646 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc) ;
bdb7fd9f 647 cur_length += increment ;
9d90bd60 648 s->stream.next_out += cur_length ;
bdb7fd9f
RGS
649 increment = bufinc ;
650 s->stream.avail_out = increment;
651 bufinc *= 2 ;
652 }
653 RETVAL = BZ2_bzCompress(&(s->stream), BZ_FLUSH);
654
655 if (RETVAL == BZ_RUN_OK || RETVAL < 0)
656 break;
657
658 /* deflate has finished flushing only when it hasn't used up
659 * all the available space in the output buffer:
660 */
661 /* RETVAL == if (s->stream.avail_out != 0 || RETVAL < 0 )
662 break; */
663 }
664
665 /* RETVAL = (RETVAL == BZ_STREAM_END ? BZ_OK : RETVAL) ; */
666 s->last_error = RETVAL ;
667
668 s->compressedBytes += cur_length + increment - s->stream.avail_out ;
669
670 if (RETVAL == BZ_RUN_OK) {
671 SvPOK_only(output);
672 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
673 SvSETMAGIC(output);
674 }
675 OUTPUT:
676 RETVAL
677
678uLong
679total_in_lo32(s)
680 Compress::Raw::Bzip2 s
681 CODE:
682 RETVAL = s->stream.total_in_lo32 ;
683 OUTPUT:
684 RETVAL
685
686uLong
687total_out_lo32(s)
688 Compress::Raw::Bzip2 s
689 CODE:
690 RETVAL = s->stream.total_out_lo32 ;
691 OUTPUT:
692 RETVAL
693
694uLong
695compressedBytes(s)
696 Compress::Raw::Bzip2 s
697 CODE:
698 RETVAL = s->compressedBytes;
699 OUTPUT:
700 RETVAL
701
702uLong
703uncompressedBytes(s)
704 Compress::Raw::Bzip2 s
705 CODE:
706 RETVAL = s->uncompressedBytes;
707 OUTPUT:
708 RETVAL
709
710
711MODULE = Compress::Raw::Bunzip2 PACKAGE = Compress::Raw::Bunzip2
712
713void
714DispStream(s, message=NULL)
715 Compress::Raw::Bunzip2 s
716 char * message
717
718DualType
719bzinflate (s, buf, output)
720 Compress::Raw::Bunzip2 s
721 SV * buf
722 SV * output
723 uInt cur_length = 0;
724 uInt prefix_length = 0;
725 uInt increment = 0;
bdb7fd9f
RGS
726 uInt bufinc = NO_INIT
727 PREINIT:
728#ifdef UTF8_AVAILABLE
729 bool out_utf8 = FALSE;
730#endif
731 CODE:
732 bufinc = s->bufsize;
733 /* If the buffer is a reference, dereference it */
ea6efd2c 734 buf = deRef(buf, "bzinflate") ;
bdb7fd9f
RGS
735
736 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
737 croak(UNCOMPRESS_CLASS "::bzinflate input parameter cannot be read-only when ConsumeInput is specified");
738#ifdef UTF8_AVAILABLE
739 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
740 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate input parameter");
741#endif
742
743 /* initialise the input buffer */
14c0f22a 744 s->stream.next_in = (char*)SvPV_nomg_nolen(buf) ;
9d90bd60 745 s->stream.avail_in = SvCUR(buf);
bdb7fd9f
RGS
746
747 /* and retrieve the output buffer */
ea6efd2c 748 output = deRef_l(output, "bzinflate") ;
bdb7fd9f
RGS
749#ifdef UTF8_AVAILABLE
750 if (DO_UTF8(output))
751 out_utf8 = TRUE ;
752 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
753 croak("Wide character in " UNCOMPRESS_CLASS "::bzinflate output parameter");
754#endif
755 if((s->flags & FLAG_APPEND_OUTPUT) != FLAG_APPEND_OUTPUT) {
756 SvCUR_set(output, 0);
757 }
80b215cb 758
ea6efd2c
MB
759 /* Assume no output buffer - the code below will update if there is any available */
760 s->stream.avail_out = 0;
761
762 if (SvLEN(output)) {
763 prefix_length = cur_length = SvCUR(output) ;
764
765 if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc)
766 {
767 Sv_Grow(output, bufinc + cur_length + 1) ;
768 }
769
770 /* Only setup the stream output pointers if there is spare
771 capacity in the outout SV
772 */
773 if (SvLEN(output) > cur_length + 1)
774 {
9d90bd60 775 s->stream.next_out = (char*) SvPVX(output) + cur_length;
ea6efd2c
MB
776 increment = SvLEN(output) - cur_length - 1;
777 s->stream.avail_out = increment;
778 }
779 }
780
781 s->bytesInflated = 0;
782
783 RETVAL = BZ_OK;
bdb7fd9f
RGS
784
785 while (1) {
786
787 if (s->stream.avail_out == 0) {
788 /* out of space in the output buffer so make it bigger */
9d90bd60 789 s->stream.next_out = Sv_Grow(output, SvLEN(output) + bufinc + 1) ;
bdb7fd9f 790 cur_length += increment ;
9d90bd60 791 s->stream.next_out += cur_length ;
bdb7fd9f
RGS
792 increment = bufinc ;
793 s->stream.avail_out = increment;
794 bufinc *= 2 ;
795 }
796
dcfdccf9 797 /* DispStream(s, "pre"); */
bdb7fd9f
RGS
798 RETVAL = BZ2_bzDecompress (&(s->stream));
799
9d90bd60
PM
800 /*
801 printf("Status %d\n", RETVAL);
802 DispStream(s, "apres");
803 */
ea6efd2c 804 if (RETVAL != BZ_OK || s->flags & FLAG_LIMIT_OUTPUT)
bdb7fd9f
RGS
805 break ;
806
807 if (s->stream.avail_out == 0)
808 continue ;
809
810 if (s->stream.avail_in == 0) {
811 RETVAL = BZ_OK ;
812 break ;
813 }
814
815 }
816
817 s->last_error = RETVAL ;
818 if (RETVAL == BZ_OK || RETVAL == BZ_STREAM_END) {
819 unsigned in ;
820
821 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
822 s->uncompressedBytes += s->bytesInflated ;
823 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
824
825 SvPOK_only(output);
826 SvCUR_set(output, prefix_length + s->bytesInflated) ;
9d90bd60 827 *SvEND(output) = '\0';
bdb7fd9f
RGS
828#ifdef UTF8_AVAILABLE
829 if (out_utf8)
9d90bd60 830 sv_utf8_upgrade(output);
bdb7fd9f 831#endif
9d90bd60 832 SvSETMAGIC(output);
bdb7fd9f
RGS
833
834 /* fix the input buffer */
835 if (s->flags & FLAG_CONSUME_INPUT) {
836 in = s->stream.avail_in ;
837 SvCUR_set(buf, in) ;
838 if (in)
4bac9ae4 839 Move(s->stream.next_in, SvPVX(buf), in, char) ;
9d90bd60
PM
840 *SvEND(buf) = '\0';
841 SvSETMAGIC(buf);
bdb7fd9f
RGS
842 }
843 }
844 OUTPUT:
845 RETVAL
846
847uLong
848inflateCount(s)
849 Compress::Raw::Bunzip2 s
850 CODE:
851 RETVAL = s->bytesInflated;
852 OUTPUT:
853 RETVAL
854
855
856void
857DESTROY(s)
858 Compress::Raw::Bunzip2 s
859 CODE:
860 BZ2_bzDecompressEnd(&s->stream) ;
861 Safefree(s) ;
862
863
864uLong
865status(s)
866 Compress::Raw::Bunzip2 s
867 CODE:
868 RETVAL = s->last_error ;
869 OUTPUT:
870 RETVAL
871
872uLong
873total_in_lo32(s)
874 Compress::Raw::Bunzip2 s
875 CODE:
876 RETVAL = s->stream.total_in_lo32 ;
877 OUTPUT:
878 RETVAL
879
880uLong
881total_out_lo32(s)
882 Compress::Raw::Bunzip2 s
883 CODE:
884 RETVAL = s->stream.total_out_lo32 ;
885 OUTPUT:
886 RETVAL
887
888uLong
889compressedBytes(s)
890 Compress::Raw::Bunzip2 s
891 CODE:
892 RETVAL = s->compressedBytes;
893 OUTPUT:
894 RETVAL
895
896uLong
897uncompressedBytes(s)
898 Compress::Raw::Bunzip2 s
899 CODE:
900 RETVAL = s->uncompressedBytes;
901 OUTPUT:
902 RETVAL
903
904MODULE = Compress::Raw::Bzip2 PACKAGE = Compress::Raw::Bzip2 PREFIX = Zip_