Upgrade to Compress::Zlib 1.38
[p5sagit/p5-mst-13.2.git] / ext / Compress / Zlib / Zlib.xs
CommitLineData
f4c6fd49 1/* Filename: Zlib.xs
2 * Author : Paul Marquess, <pmqs@cpan.org>
3 * Created : 30 January 2005
76e6f389 4 * Version : 1.38
f4c6fd49 5 *
6 * Copyright (c) 1995-2005 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/* Part of this code is based on the file gzio.c */
13
14/* gzio.c -- IO on .gz files
15 * Copyright (C) 1995 Jean-loup Gailly.
16 * For conditions of distribution and use, see copyright notice in zlib.h
17 */
18
19
20
21#include "EXTERN.h"
22#include "perl.h"
23#include "XSUB.h"
24
25#include <zlib.h>
26
27#ifndef PERL_VERSION
28#include "patchlevel.h"
29#define PERL_REVISION 5
30#define PERL_VERSION PATCHLEVEL
31#define PERL_SUBVERSION SUBVERSION
32#endif
33
34#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
35
36# define PL_sv_undef sv_undef
37# define PL_na na
38# define PL_curcop curcop
39# define PL_compiling compiling
40
41#endif
42
43#ifndef newSVuv
44# define newSVuv newSViv
45#endif
46
76e6f389 47#ifndef dTHX
48# define dTHX
49#endif
50
f4c6fd49 51typedef struct di_stream {
52 z_stream stream;
53 uLong bufsize;
54 uLong bufinc;
55 SV * dictionary ;
56 uLong dict_adler ;
57 bool deflateParams_out_valid ;
58 Bytef deflateParams_out_byte;
59 int Level;
60 int Method;
61 int WindowBits;
62 int MemLevel;
63 int Strategy;
64} di_stream;
65
66typedef di_stream * deflateStream ;
67typedef di_stream * Compress__Zlib__deflateStream ;
68typedef di_stream * inflateStream ;
69typedef di_stream * Compress__Zlib__inflateStream ;
70
71/* typedef gzFile Compress__Zlib__gzFile ; */
72typedef struct gzType {
73 gzFile gz ;
74 SV * buffer ;
75 uLong offset ;
76 bool closed ;
77} gzType ;
78
79typedef gzType* Compress__Zlib__gzFile ;
80
81
82
83#define GZERRNO "Compress::Zlib::gzerrno"
84
85#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
86 Zero(to,1,typ))
87
88#define adlerInitial adler32(0L, Z_NULL, 0)
89#define crcInitial crc32(0L, Z_NULL, 0)
90
91#if 1
c042ae3a 92static const char * const my_z_errmsg[] = {
f4c6fd49 93 "need dictionary", /* Z_NEED_DICT 2 */
94 "stream end", /* Z_STREAM_END 1 */
95 "", /* Z_OK 0 */
96 "file error", /* Z_ERRNO (-1) */
97 "stream error", /* Z_STREAM_ERROR (-2) */
98 "data error", /* Z_DATA_ERROR (-3) */
99 "insufficient memory", /* Z_MEM_ERROR (-4) */
100 "buffer error", /* Z_BUF_ERROR (-5) */
101 "incompatible version",/* Z_VERSION_ERROR(-6) */
102 ""};
103#endif
104
c042ae3a 105#if defined(__SYMBIAN32__)
106# define NO_WRITEABLE_DATA
107#endif
108
109#define TRACE_DEFAULT 0
110
111#ifdef NO_WRITEABLE_DATA
112#define trace TRACE_DEFAULT
113#else
114static int trace = TRACE_DEFAULT ;
115#endif
f4c6fd49 116
c042ae3a 117/* Dodge PerlIO hiding of these functions. */
118#undef printf
f4c6fd49 119
120static void
121#ifdef CAN_PROTOTYPE
122SetGzErrorNo(int error_no)
123#else
124SetGzErrorNo(error_no)
125int error_no ;
126#endif
127{
c042ae3a 128 dTHX;
f4c6fd49 129 char * errstr ;
130 SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ;
131
132 if (error_no == Z_ERRNO) {
133 error_no = errno ;
134 errstr = Strerror(errno) ;
135 }
136 else
137 /* errstr = gzerror(fil, &error_no) ; */
138 errstr = (char*) my_z_errmsg[2 - error_no];
139
140 if (SvIV(gzerror_sv) != error_no) {
141 sv_setiv(gzerror_sv, error_no) ;
142 sv_setpv(gzerror_sv, errstr) ;
143 SvIOK_on(gzerror_sv) ;
144 }
145
146}
147
148static void
149#ifdef CAN_PROTOTYPE
150SetGzError(gzFile file)
151#else
152SetGzError(file)
153gzFile file ;
154#endif
155{
156 int error_no ;
157
158 (void)gzerror(file, &error_no) ;
159 SetGzErrorNo(error_no) ;
160}
161
162static void
163#ifdef CAN_PROTOTYPE
164DispHex(void * ptr, int length)
165#else
166DispHex(ptr, length)
167 void * ptr;
168 int length;
169#endif
170{
171 char * p = (char*)ptr;
172 int i;
173 for (i = 0; i < length; ++i) {
174 printf(" %02x", 0xFF & *(p+i));
175 }
176}
177
178
179static void
180#ifdef CAN_PROTOTYPE
181DispStream(di_stream * s, char * message)
182#else
183DispStream(s, message)
184 di_stream * s;
185 char * message;
186#endif
187{
188
189#if 0
190 if (! trace)
191 return ;
192#endif
193
194 printf("DispStream 0x%p - %s \n", s, message) ;
195
196 if (!s) {
197 printf(" stream pointer is NULL\n");
198 }
199 else {
200 printf(" stream 0x%p\n", &(s->stream));
201 printf(" zalloc 0x%p\n", s->stream.zalloc);
202 printf(" zfree 0x%p\n", s->stream.zfree);
203 printf(" opaque 0x%p\n", s->stream.opaque);
204 if (s->stream.msg)
205 printf(" msg %s\n", s->stream.msg);
206 else
207 printf(" msg \n");
208 printf(" next_in 0x%p", s->stream.next_in);
209 if (s->stream.next_in) {
210 printf(" =>");
211 DispHex(s->stream.next_in, 4);
212 }
213 printf("\n");
214
215 printf(" next_out 0x%p", s->stream.next_out);
216 if (s->stream.next_out){
217 printf(" =>");
218 DispHex(s->stream.next_out, 4);
219 }
220 printf("\n");
221
222 printf(" avail_in %ld\n", s->stream.avail_in);
223 printf(" avail_out %ld\n", s->stream.avail_out);
224 printf(" total_in %ld\n", s->stream.total_in);
225 printf(" total_out %ld\n", s->stream.total_out);
226 printf(" adler 0x%lx\n", s->stream.adler);
227 printf(" reserved 0x%lx\n", s->stream.reserved);
228 printf(" bufsize %ld\n", s->bufsize);
229 printf(" dictionary 0x%p\n", s->dictionary);
230 printf(" dict_adler 0x%ld\n", s->dict_adler);
231 printf("\n");
232
233 }
234}
235
236
237static di_stream *
238#ifdef CAN_PROTOTYPE
239InitStream(uLong bufsize)
240#else
241InitStream(bufsize)
242 uLong bufsize ;
243#endif
244{
245 di_stream *s ;
246
247 ZMALLOC(s, di_stream) ;
248
249 if (s) {
250 s->bufsize = bufsize ;
251 s->bufinc = bufsize ;
252 }
253
254 return s ;
255
256}
257
258#define SIZE 4096
259
260static int
261#ifdef CAN_PROTOTYPE
262gzreadline(Compress__Zlib__gzFile file, SV * output)
263#else
264gzreadline(file, output)
265 Compress__Zlib__gzFile file ;
266 SV * output ;
267#endif
268{
c042ae3a 269 dTHX;
f4c6fd49 270 SV * store = file->buffer ;
271 char *nl = "\n";
272 char *p;
273 char *out_ptr = SvPVX(store) ;
274 int n;
275
276 while (1) {
277
278 /* anything left from last time */
279 if ((n = SvCUR(store))) {
280
281 out_ptr = SvPVX(store) + file->offset ;
282 if ((p = ninstr(out_ptr, out_ptr + n - 1, nl, nl))) {
283 /* if (rschar != 0777 && */
284 /* p = ninstr(out_ptr, out_ptr + n - 1, rs, rs+rslen-1)) { */
285
286 sv_catpvn(output, out_ptr, p - out_ptr + 1);
287
288 file->offset += (p - out_ptr + 1) ;
289 n = n - (p - out_ptr + 1);
290 SvCUR_set(store, n) ;
291 return SvCUR(output);
292 }
293 else /* no EOL, so append the complete buffer */
294 sv_catpvn(output, out_ptr, n);
295
296 }
297
298
299 SvCUR_set(store, 0) ;
300 file->offset = 0 ;
301 out_ptr = SvPVX(store) ;
302
303 n = gzread(file->gz, out_ptr, SIZE) ;
304
305 if (n <= 0)
306 /* Either EOF or an error */
307 /* so return what we have so far else signal eof */
308 return (SvCUR(output)>0) ? SvCUR(output) : n ;
309
310 SvCUR_set(store, n) ;
311 }
312}
313
314static SV*
315#ifdef CAN_PROTOTYPE
316deRef(SV * sv, char * string)
317#else
318deRef(sv, string)
319SV * sv ;
320char * string;
321#endif
322{
c042ae3a 323 dTHX;
f4c6fd49 324 if (SvROK(sv)) {
325 sv = SvRV(sv) ;
326 switch(SvTYPE(sv)) {
327 case SVt_PVAV:
328 case SVt_PVHV:
329 case SVt_PVCV:
330 croak("%s: buffer parameter is not a SCALAR reference", string);
331 }
332 if (SvROK(sv))
333 croak("%s: buffer parameter is a reference to a reference", string) ;
334 }
335
336 if (!SvOK(sv)) {
337 sv = newSVpv("", 0);
338 }
339 return sv ;
340}
341
342#include "constants.h"
343
344MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
345
346REQUIRE: 1.924
347PROTOTYPES: DISABLE
348
349INCLUDE: constants.xs
350
351BOOT:
352 /* Check this version of zlib is == 1 */
353 if (zlibVersion()[0] != '1')
354 croak("Compress::Zlib needs zlib version 1.x\n") ;
355
356 {
357 /* Create the $gzerror scalar */
358 SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ;
359 sv_setiv(gzerror_sv, 0) ;
360 sv_setpv(gzerror_sv, "") ;
361 SvIOK_on(gzerror_sv) ;
362 }
363
364
365#define Zip_zlib_version() (char*)zlib_version
366char*
367Zip_zlib_version()
368
06edba15 369unsigned
370ZLIB_VERNUM()
371 CODE:
372#ifdef ZLIB_VERNUM
373 RETVAL = ZLIB_VERNUM ;
374#else
375 /* 1.1.4 => 0x1140 */
376 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
377 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
378 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
379#endif
380 OUTPUT:
381 RETVAL
382
383
f4c6fd49 384
385void
386DispStream(s, message=NULL)
387 Compress::Zlib::inflateStream s
388 char * message
389
390Compress::Zlib::gzFile
391gzopen_(path, mode)
392 char * path
393 char * mode
394 CODE:
395 gzFile gz ;
396 gz = gzopen(path, mode) ;
397 if (gz) {
398 ZMALLOC(RETVAL, gzType) ;
399 RETVAL->buffer = newSV(SIZE) ;
400 SvPOK_only(RETVAL->buffer) ;
401 SvCUR_set(RETVAL->buffer, 0) ;
402 RETVAL->offset = 0 ;
403 RETVAL->gz = gz ;
404 RETVAL->closed = FALSE ;
405 SetGzErrorNo(0) ;
406 }
407 else {
408 RETVAL = NULL ;
409 SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
410 }
411 OUTPUT:
412 RETVAL
413
414
415Compress::Zlib::gzFile
416gzdopen_(fh, mode, offset)
417 int fh
418 char * mode
419 long offset
420 CODE:
421 gzFile gz ;
422 if (offset != -1)
423 lseek(fh, offset, 0) ;
424 gz = gzdopen(fh, mode) ;
425 if (gz) {
426 ZMALLOC(RETVAL, gzType) ;
427 RETVAL->buffer = newSV(SIZE) ;
428 SvPOK_only(RETVAL->buffer) ;
429 SvCUR_set(RETVAL->buffer, 0) ;
430 RETVAL->offset = 0 ;
431 RETVAL->gz = gz ;
432 RETVAL->closed = FALSE ;
433 SetGzErrorNo(0) ;
434 }
435 else {
436 RETVAL = NULL ;
437 SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
438 }
439 OUTPUT:
440 RETVAL
441
442
443MODULE = Compress::Zlib PACKAGE = Compress::Zlib::gzFile PREFIX = Zip_
444
445#define Zip_gzread(file, buf, len) gzread(file->gz, bufp, len)
446
447int
448Zip_gzread(file, buf, len=4096)
449 Compress::Zlib::gzFile file
450 unsigned len
451 SV * buf
452 voidp bufp = NO_INIT
453 uLong bufsize = 0 ;
454 int RETVAL = 0 ;
455 CODE:
456 if (SvREADONLY(buf) && PL_curcop != &PL_compiling)
457 croak("gzread: buffer parameter is read-only");
f2e5e569 458 SvUPGRADE(buf, SVt_PV);
f4c6fd49 459 SvPOK_only(buf);
460 SvCUR_set(buf, 0);
461 /* any left over from gzreadline ? */
462 if ((bufsize = SvCUR(file->buffer)) > 0) {
463 uLong movesize ;
464
465 if (bufsize < len) {
466 movesize = bufsize ;
467 len -= movesize ;
468 }
469 else {
470 movesize = len ;
471 len = 0 ;
472 }
473 RETVAL = movesize ;
474
475 sv_catpvn(buf, SvPVX(file->buffer) + file->offset, movesize);
476
477 file->offset += movesize ;
478 SvCUR_set(file->buffer, bufsize - movesize) ;
479 }
480
481 if (len) {
482 bufp = (Byte*)SvGROW(buf, bufsize+len+1);
483 RETVAL = gzread(file->gz, ((Bytef*)bufp)+bufsize, len) ;
484 SetGzError(file->gz) ;
485 if (RETVAL >= 0) {
486 RETVAL += bufsize ;
487 SvCUR_set(buf, RETVAL) ;
488 *SvEND(buf) = '\0';
489 }
490 }
491 OUTPUT:
492 RETVAL
493 buf
494
495int
496gzreadline(file, buf)
497 Compress::Zlib::gzFile file
498 SV * buf
499 int RETVAL = 0;
500 CODE:
501 if (SvREADONLY(buf) && PL_curcop != &PL_compiling)
502 croak("gzreadline: buffer parameter is read-only");
f2e5e569 503 SvUPGRADE(buf, SVt_PV);
f4c6fd49 504 SvPOK_only(buf);
505 /* sv_setpvn(buf, "", SIZE) ; */
506 SvGROW(buf, SIZE) ;
507 SvCUR_set(buf, 0);
508 RETVAL = gzreadline(file, buf) ;
509 SetGzError(file->gz) ;
510 OUTPUT:
511 RETVAL
512 buf
513 CLEANUP:
514 if (RETVAL >= 0) {
515 /* SvCUR(buf) = RETVAL; */
516 /* Don't need to explicitly terminate with '\0', because
517 sv_catpvn aready has */
518 }
519
520#define Zip_gzwrite(file, buf) gzwrite(file->gz, buf, (unsigned)len)
521int
522Zip_gzwrite(file, buf)
523 Compress::Zlib::gzFile file
524 STRLEN len = NO_INIT
525 voidp buf = (voidp)SvPV(ST(1), len) ;
526 CLEANUP:
527 SetGzError(file->gz) ;
528
529#define Zip_gzflush(file, flush) gzflush(file->gz, flush)
530int
531Zip_gzflush(file, flush)
532 Compress::Zlib::gzFile file
533 int flush
534 CLEANUP:
535 SetGzError(file->gz) ;
536
06edba15 537#define Zip_gzclose(file) file->closed ? 0 : gzclose(file->gz)
f4c6fd49 538int
539Zip_gzclose(file)
540 Compress::Zlib::gzFile file
541 CLEANUP:
542 file->closed = TRUE ;
543 SetGzErrorNo(RETVAL) ;
544
545
546#define Zip_gzeof(file) gzeof(file->gz)
547int
548Zip_gzeof(file)
549 Compress::Zlib::gzFile file
550 CODE:
551#ifdef OLD_ZLIB
552 croak("gzeof needs zlib 1.0.6 or better") ;
553#else
554 RETVAL = gzeof(file->gz);
555#endif
556 OUTPUT:
557 RETVAL
558
559
560#define Zip_gzsetparams(file,l,s) gzsetparams(file->gz,l,s)
561int
562Zip_gzsetparams(file, level, strategy)
563 Compress::Zlib::gzFile file
564 int level
565 int strategy
566 CODE:
567#ifdef OLD_ZLIB
568 croak("gzsetparams needs zlib 1.0.6 or better") ;
569#else
570 RETVAL = gzsetparams(file->gz, level, strategy);
571#endif
572 OUTPUT:
573 RETVAL
574
575void
576DESTROY(file)
577 Compress::Zlib::gzFile file
578 CODE:
579 if (! file->closed)
580 Zip_gzclose(file) ;
581 SvREFCNT_dec(file->buffer) ;
582 safefree((char*)file) ;
583
584#define Zip_gzerror(file) (char*)gzerror(file->gz, &errnum)
585
586char *
587Zip_gzerror(file)
588 Compress::Zlib::gzFile file
589 int errnum = NO_INIT
590 CLEANUP:
591 sv_setiv(ST(0), errnum) ;
592 SvPOK_on(ST(0)) ;
593
594
595
596MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
597
598
599#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
600
601uLong
602Zip_adler32(buf, adler=adlerInitial)
603 uLong adler = NO_INIT
604 STRLEN len = NO_INIT
605 Bytef * buf = NO_INIT
606 SV * sv = ST(0) ;
607 INIT:
608 /* If the buffer is a reference, dereference it */
609 sv = deRef(sv, "adler32") ;
610 buf = (Byte*)SvPV(sv, len) ;
611
612 if (items < 2)
613 adler = adlerInitial;
614 else if (SvOK(ST(1)))
615 adler = SvUV(ST(1)) ;
616 else
617 adler = adlerInitial;
618
619#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
620
621uLong
622Zip_crc32(buf, crc=crcInitial)
623 uLong crc = NO_INIT
624 STRLEN len = NO_INIT
625 Bytef * buf = NO_INIT
626 SV * sv = ST(0) ;
627 INIT:
628 /* If the buffer is a reference, dereference it */
629 sv = deRef(sv, "crc32") ;
630 buf = (Byte*)SvPV(sv, len) ;
631
632 if (items < 2)
633 crc = crcInitial;
634 else if (SvOK(ST(1)))
635 crc = SvUV(ST(1)) ;
636 else
637 crc = crcInitial;
638
639MODULE = Compress::Zlib PACKAGE = Compress::Zlib
640
641void
642_deflateInit(level, method, windowBits, memLevel, strategy, bufsize, dictionary)
643 int level
644 int method
645 int windowBits
646 int memLevel
647 int strategy
648 uLong bufsize
649 SV * dictionary
650 PPCODE:
651
652 int err ;
653 deflateStream s ;
654
655 if (trace)
656 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%d\n",
657 level, method, windowBits, memLevel, strategy, bufsize) ;
658 if ((s = InitStream(bufsize)) ) {
659
660 s->Level = level;
661 s->Method = method;
662 s->WindowBits = windowBits;
663 s->MemLevel = memLevel;
664 s->Strategy = strategy;
665
666 err = deflateInit2(&(s->stream), level,
667 method, windowBits, memLevel, strategy);
668
669 /* Check if a dictionary has been specified */
670 if (err == Z_OK && SvCUR(dictionary)) {
671 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVX(dictionary),
672 SvCUR(dictionary)) ;
673 s->dict_adler = s->stream.adler ;
674 }
675
676 if (err != Z_OK) {
677 Safefree(s) ;
678 s = NULL ;
679 }
680
681 }
682 else
683 err = Z_MEM_ERROR ;
684
685 XPUSHs(sv_setref_pv(sv_newmortal(),
686 "Compress::Zlib::deflateStream", (void*)s));
687 if (GIMME == G_ARRAY)
688 XPUSHs(sv_2mortal(newSViv(err))) ;
689
690void
691_inflateInit(windowBits, bufsize, dictionary)
692 int windowBits
693 uLong bufsize
694 SV * dictionary
695 PPCODE:
696
697 int err = Z_OK ;
698 inflateStream s ;
699
700 if (trace)
701 warn("in _inflateInit(windowBits=%d, bufsize=%d, dictionary=%d\n",
702 windowBits, bufsize, SvCUR(dictionary)) ;
703 if ((s = InitStream(bufsize)) ) {
704
705 s->WindowBits = windowBits;
706
707 err = inflateInit2(&(s->stream), windowBits);
708
709 if (err != Z_OK) {
710 Safefree(s) ;
711 s = NULL ;
712 }
713 else if (SvCUR(dictionary)) {
714 /* Dictionary specified - take a copy for use in inflate */
715 s->dictionary = newSVsv(dictionary) ;
716 }
717 }
718 else
719 err = Z_MEM_ERROR ;
720
721 XPUSHs(sv_setref_pv(sv_newmortal(),
722 "Compress::Zlib::inflateStream", (void*)s));
723 if (GIMME == G_ARRAY)
724 XPUSHs(sv_2mortal(newSViv(err))) ;
725
726
727
728MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
729
730void
731DispStream(s, message=NULL)
732 Compress::Zlib::deflateStream s
733 char * message
734
735void
736deflate (s, buf)
737 Compress::Zlib::deflateStream s
738 SV * buf
739 uLong outsize = NO_INIT
740 SV * output = NO_INIT
741 int err = 0;
742 PPCODE:
743
744 /* If the buffer is a reference, dereference it */
745 buf = deRef(buf, "deflate") ;
746
747 /* initialise the input buffer */
748 s->stream.next_in = (Bytef*)SvPV(buf, *(STRLEN*)&s->stream.avail_in) ;
749 /* s->stream.next_in = (Bytef*)SvPVX(buf); */
750 s->stream.avail_in = SvCUR(buf) ;
751
752 /* and the output buffer */
753 /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
754 output = sv_2mortal(newSV(s->bufinc)) ;
755 SvPOK_only(output) ;
756 SvCUR_set(output, 0) ;
757 outsize = s->bufinc ;
758 s->stream.next_out = (Bytef*) SvPVX(output) ;
759 s->stream.avail_out = outsize;
760
761 /* Check for saved output from deflateParams */
762 if (s->deflateParams_out_valid) {
763 *(s->stream.next_out) = s->deflateParams_out_byte;
764 ++ s->stream.next_out;
765 -- s->stream.avail_out ;
766 s->deflateParams_out_valid = FALSE;
767 }
768
769 while (s->stream.avail_in != 0) {
770
771 if (s->stream.avail_out == 0) {
772 s->bufinc *= 2 ;
773 SvGROW(output, outsize + s->bufinc) ;
774 s->stream.next_out = (Bytef*) SvPVX(output) + outsize ;
775 outsize += s->bufinc ;
776 s->stream.avail_out = s->bufinc ;
777 }
778 err = deflate(&(s->stream), Z_NO_FLUSH);
779 if (err != Z_OK)
780 break;
781 }
782
783 if (err == Z_OK) {
784 SvPOK_only(output);
785 SvCUR_set(output, outsize - s->stream.avail_out) ;
786 }
787 else
788 output = &PL_sv_undef ;
789 XPUSHs(output) ;
790 if (GIMME == G_ARRAY)
791 XPUSHs(sv_2mortal(newSViv(err))) ;
792
793
794
795void
796flush(s, f=Z_FINISH)
797 Compress::Zlib::deflateStream s
798 int f
799 uLong outsize = NO_INIT
800 SV * output = NO_INIT
801 int err = Z_OK ;
802 PPCODE:
803
804 s->stream.avail_in = 0; /* should be zero already anyway */
805
806 /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
807 output = sv_2mortal(newSV(s->bufinc)) ;
808 SvPOK_only(output) ;
809 SvCUR_set(output, 0) ;
810 outsize = s->bufinc ;
811 s->stream.next_out = (Bytef*) SvPVX(output) ;
812 s->stream.avail_out = outsize;
813
814 /* Check for saved output from deflateParams */
815 if (s->deflateParams_out_valid) {
816 *(s->stream.next_out) = s->deflateParams_out_byte;
817 ++ s->stream.next_out;
818 -- s->stream.avail_out ;
819 s->deflateParams_out_valid = FALSE;
820 }
821
822 for (;;) {
823 if (s->stream.avail_out == 0) {
824 /* consumed all the available output, so extend it */
825 s->bufinc *= 2 ;
826 SvGROW(output, outsize + s->bufinc) ;
827 s->stream.next_out = (Bytef*)SvPVX(output) + outsize ;
828 outsize += s->bufinc ;
829 s->stream.avail_out = s->bufinc ;
830 }
831 err = deflate(&(s->stream), f);
832
833 /* deflate has finished flushing only when it hasn't used up
834 * all the available space in the output buffer:
835 */
836 if (s->stream.avail_out != 0 || err != Z_OK )
837 break;
838 }
839
840 err = (err == Z_STREAM_END ? Z_OK : err) ;
841
842 if (err == Z_OK) {
843 SvPOK_only(output);
844 SvCUR_set(output, outsize - s->stream.avail_out) ;
845 }
846 else
847 output = &PL_sv_undef ;
848 XPUSHs(output) ;
849 if (GIMME == G_ARRAY)
850 XPUSHs(sv_2mortal(newSViv(err))) ;
851
852int
853_deflateParams(s, flags, level, strategy, bufsize)
854 Compress::Zlib::deflateStream s
855 int flags
856 int level
857 int strategy
858 uLong bufsize
859 CODE:
860 if (flags & 1)
861 s->Level = level ;
862 if (flags & 2)
863 s->Strategy = strategy ;
864 if (bufsize) {
865 s->bufsize = bufsize;
866 s->bufinc = bufsize;
867 }
868 s->stream.avail_in = 0;
869 s->stream.next_out = &(s->deflateParams_out_byte) ;
870 s->stream.avail_out = 1;
871 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
872 s->deflateParams_out_valid =
873 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
874 OUTPUT:
875 RETVAL
876
877
878int
879get_Level(s)
880 Compress::Zlib::deflateStream s
881 CODE:
882 RETVAL = s->Level ;
883 OUTPUT:
884 RETVAL
885
886int
887get_Strategy(s)
888 Compress::Zlib::deflateStream s
889 CODE:
890 RETVAL = s->Strategy ;
891 OUTPUT:
892 RETVAL
893
894void
895DESTROY(s)
896 Compress::Zlib::deflateStream s
897 CODE:
898 deflateEnd(&s->stream) ;
899 if (s->dictionary)
900 SvREFCNT_dec(s->dictionary) ;
901 Safefree(s) ;
902
903
904uLong
905dict_adler(s)
906 Compress::Zlib::deflateStream s
907 CODE:
908 RETVAL = s->dict_adler ;
909 OUTPUT:
910 RETVAL
911
912uLong
913total_in(s)
914 Compress::Zlib::deflateStream s
915 CODE:
916 RETVAL = s->stream.total_in ;
917 OUTPUT:
918 RETVAL
919
920uLong
921total_out(s)
922 Compress::Zlib::deflateStream s
923 CODE:
924 RETVAL = s->stream.total_out ;
925 OUTPUT:
926 RETVAL
927
928char*
929msg(s)
930 Compress::Zlib::deflateStream s
931 CODE:
932 RETVAL = s->stream.msg;
933 OUTPUT:
934 RETVAL
935
936
937MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
938
939void
940DispStream(s, message=NULL)
941 Compress::Zlib::inflateStream s
942 char * message
943
944void
945inflate (s, buf)
946 Compress::Zlib::inflateStream s
947 SV * buf
948 uLong outsize = NO_INIT
949 SV * output = NO_INIT
950 int err = Z_OK ;
951 ALIAS:
952 __unc_inflate = 1
953 PPCODE:
954
955 /* If the buffer is a reference, dereference it */
956 buf = deRef(buf, "inflate") ;
957
958 /* initialise the input buffer */
959 s->stream.next_in = (Bytef*)SvPVX(buf) ;
960 s->stream.avail_in = SvCUR(buf) ;
961
962 /* and the output buffer */
963 output = sv_2mortal(newSV(s->bufinc+1)) ;
964 SvPOK_only(output) ;
965 SvCUR_set(output, 0) ;
966 outsize = s->bufinc ;
967 s->stream.next_out = (Bytef*) SvPVX(output) ;
968 s->stream.avail_out = outsize;
969
970 while (1) {
971
972 if (s->stream.avail_out == 0) {
973 s->bufinc *= 2 ;
974 SvGROW(output, outsize + s->bufinc+1) ;
975 s->stream.next_out = (Bytef*) SvPVX(output) + outsize ;
976 outsize += s->bufinc ;
977 s->stream.avail_out = s->bufinc ;
978 }
979
980 err = inflate(&(s->stream), Z_SYNC_FLUSH);
981 if (err == Z_BUF_ERROR) {
982 if (s->stream.avail_out == 0)
983 continue ;
984 if (s->stream.avail_in == 0) {
985 err = Z_OK ;
986 break ;
987 }
988 }
989
990 if (err == Z_NEED_DICT && s->dictionary) {
991 s->dict_adler = s->stream.adler ;
992 err = inflateSetDictionary(&(s->stream),
993 (const Bytef*)SvPVX(s->dictionary),
994 SvCUR(s->dictionary));
995 }
996
997 if (err != Z_OK)
998 break;
999 }
1000
1001 if (err == Z_OK || err == Z_STREAM_END || err == Z_DATA_ERROR) {
1002 unsigned in ;
1003
1004 SvPOK_only(output);
1005 SvCUR_set(output, outsize - s->stream.avail_out) ;
1006 *SvEND(output) = '\0';
1007
1008 /* fix the input buffer */
1009 if (ix == 0) {
1010 in = s->stream.avail_in ;
1011 SvCUR_set(buf, in) ;
1012 if (in)
1013 Move(s->stream.next_in, SvPVX(buf), in, char) ;
1014 *SvEND(buf) = '\0';
1015 SvSETMAGIC(buf);
1016 }
1017 }
1018 else
1019 output = &PL_sv_undef ;
1020 XPUSHs(output) ;
1021 if (GIMME == G_ARRAY)
1022 XPUSHs(sv_2mortal(newSViv(err))) ;
1023
1024int
1025inflateSync (s, buf)
1026 Compress::Zlib::inflateStream s
1027 SV * buf
1028 CODE:
1029
1030 /* If the buffer is a reference, dereference it */
1031 buf = deRef(buf, "inflateSync") ;
1032
1033 /* initialise the input buffer */
1034 s->stream.next_in = (Bytef*)SvPVX(buf) ;
1035 s->stream.avail_in = SvCUR(buf) ;
1036
1037 /* inflateSync doesn't create any output */
1038 s->stream.next_out = (Bytef*) NULL;
1039 s->stream.avail_out = 0;
1040
1041 RETVAL = inflateSync(&(s->stream));
1042 {
1043 /* fix the input buffer */
1044 unsigned in = s->stream.avail_in ;
1045
1046 SvCUR_set(buf, in) ;
1047 if (in)
1048 Move(s->stream.next_in, SvPVX(buf), in, char) ;
1049 *SvEND(buf) = '\0';
1050 SvSETMAGIC(buf);
1051 }
1052 OUTPUT:
1053 RETVAL
1054
1055void
1056DESTROY(s)
1057 Compress::Zlib::inflateStream s
1058 CODE:
1059 inflateEnd(&s->stream) ;
1060 if (s->dictionary)
1061 SvREFCNT_dec(s->dictionary) ;
1062 Safefree(s) ;
1063
1064
1065uLong
1066dict_adler(s)
1067 Compress::Zlib::inflateStream s
1068 CODE:
1069 RETVAL = s->dict_adler ;
1070 OUTPUT:
1071 RETVAL
1072
1073uLong
1074total_in(s)
1075 Compress::Zlib::inflateStream s
1076 CODE:
1077 RETVAL = s->stream.total_in ;
1078 OUTPUT:
1079 RETVAL
1080
1081uLong
1082total_out(s)
1083 Compress::Zlib::inflateStream s
1084 CODE:
1085 RETVAL = s->stream.total_out ;
1086 OUTPUT:
1087 RETVAL
1088
1089char*
1090msg(s)
1091 Compress::Zlib::inflateStream s
1092 CODE:
1093 RETVAL = s->stream.msg;
1094 OUTPUT:
1095 RETVAL
1096
1097