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