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