Compress::Zlib should not ask under Cygwin in CORE
[p5sagit/p5-mst-13.2.git] / ext / Compress / Zlib / Zlib.xs
CommitLineData
f4c6fd49 1/* Filename: Zlib.xs
2 * Author : Paul Marquess, <pmqs@cpan.org>
642e522c 3 * Created : 22nd January 1996
4 * Version : 2.000
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
642e522c 12/* Parts of this code are based on the files gzio.c and gzappend.c from
13 * the standard zlib source distribution. Below are the copyright statements
14 * from each.
15 */
f4c6fd49 16
17/* gzio.c -- IO on .gz files
18 * Copyright (C) 1995 Jean-loup Gailly.
19 * For conditions of distribution and use, see copyright notice in zlib.h
20 */
21
642e522c 22/* gzappend -- command to append to a gzip file
23
24 Copyright (C) 2003 Mark Adler, all rights reserved
25 version 1.1, 4 Nov 2003
26*/
27
f4c6fd49 28
29
30#include "EXTERN.h"
31#include "perl.h"
32#include "XSUB.h"
33
34#include <zlib.h>
35
642e522c 36
37#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1210
38# define MAGIC_APPEND
39#endif
40
41#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221
42# define AT_LEAST_ZLIB_1_2_2_1
43#endif
44
45#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223
46# define AT_LEAST_ZLIB_1_2_2_3
47#endif
48
49#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
50# define AT_LEAST_ZLIB_1_2_3
51#endif
52
53#if 0
54
55# include "ppport.h"
56
57#else
58
59/* zlib prior to 1.06 doesn't know about z_off_t */
60#ifndef z_off_t
61# define z_off_t long
62#endif
63
64# ifndef PERL_VERSION
65# include "patchlevel.h"
66# define PERL_REVISION 5
67# define PERL_VERSION PATCHLEVEL
68# define PERL_SUBVERSION SUBVERSION
69# endif
70
71# if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
72
73# define PL_sv_undef sv_undef
74# define PL_na na
75# define PL_curcop curcop
76# define PL_compiling compiling
77
78# endif
79
80# ifndef newSVuv
81# define newSVuv newSViv
82# endif
83
84#endif
85
86
87#if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
88# define UTF8_AVAILABLE
89#endif
90
91#if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
92
93# ifdef SvPVbyte_force
94# undef SvPVbyte_force
95# endif
96
97# define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
98
f4c6fd49 99#endif
100
642e522c 101#ifndef SvPVbyte_nolen
102# define SvPVbyte_nolen SvPV_nolen
103#endif
104
105#ifndef SvPVbyte
106# define SvPVbyte SvPV
107#endif
108
109#ifndef dTHX
110# define dTHX
111#endif
112
113#ifndef SvPV_nolen
114
115#define sv_2pv_nolen(a) my_sv_2pv_nolen(a)
116
117static char *
118my_sv_2pv_nolen(register SV *sv)
119{
120 STRLEN n_a;
121 return sv_2pv(sv, &n_a);
122}
123
124
125/* SvPV_nolen depends on sv_2pv_nolen */
126#define SvPV_nolen(sv) \
127 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
128 ? SvPVX(sv) : sv_2pv_nolen(sv))
f4c6fd49 129
f4c6fd49 130
131#endif
132
642e522c 133#ifndef SvGETMAGIC
134# define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
f4c6fd49 135#endif
136
642e522c 137typedef int DualType ;
138typedef int int_undef ;
139
f4c6fd49 140typedef struct di_stream {
642e522c 141 int flags ;
142#define FLAG_APPEND 1
143#define FLAG_CRC32 2
144#define FLAG_ADLER32 4
145#define FLAG_CONSUME_INPUT 8
146 uLong crc32 ;
147 uLong adler32 ;
f4c6fd49 148 z_stream stream;
642e522c 149 uLong bufsize;
150 uLong bufinc;
f4c6fd49 151 SV * dictionary ;
152 uLong dict_adler ;
642e522c 153 int last_error ;
154 bool zip_mode ;
155#define SETP_BYTE
156#ifdef SETP_BYTE
f4c6fd49 157 bool deflateParams_out_valid ;
158 Bytef deflateParams_out_byte;
642e522c 159#else
160#define deflateParams_BUFFER_SIZE 0x4000
161 uLong deflateParams_out_length;
162 Bytef* deflateParams_out_buffer;
163#endif
f4c6fd49 164 int Level;
165 int Method;
166 int WindowBits;
167 int MemLevel;
168 int Strategy;
642e522c 169 uLong bytesInflated ;
170#ifdef MAGIC_APPEND
171
172#define WINDOW_SIZE 32768U
173
174 bool matchedEndBlock;
175 Bytef* window ;
176 int window_lastbit, window_left, window_full;
177 unsigned window_have;
178 off_t window_lastoff, window_end;
179 off_t window_endOffset;
180
181 uLong lastBlockOffset ;
182 unsigned char window_lastByte ;
183
184
185#endif
f4c6fd49 186} di_stream;
187
188typedef di_stream * deflateStream ;
189typedef di_stream * Compress__Zlib__deflateStream ;
190typedef di_stream * inflateStream ;
191typedef di_stream * Compress__Zlib__inflateStream ;
642e522c 192typedef di_stream * Compress__Zlib__inflateScanStream ;
193
194#define GZERRNO "Compress::Zlib::gzerrno"
f4c6fd49 195
642e522c 196#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
197 Zero(to,1,typ))
198
199/* Figure out the Operating System */
200#ifdef MSDOS
201# define OS_CODE 0x00
202#endif
f4c6fd49 203
642e522c 204#if defined(AMIGA) || defined(AMIGAOS)
205# define OS_CODE 0x01
206#endif
207
208#if defined(VAXC) || defined(VMS)
209# define OS_CODE 0x02
210#endif
f4c6fd49 211
642e522c 212#if 0 /* VM/CMS */
213# define OS_CODE 0x04
214#endif
215
216#if defined(ATARI) || defined(atarist)
217# define OS_CODE 0x05
218#endif
219
220#ifdef OS2
221# define OS_CODE 0x06
222#endif
223
224#if defined(MACOS) || defined(TARGET_OS_MAC)
225# define OS_CODE 0x07
226#endif
f4c6fd49 227
642e522c 228#if 0 /* Z-System */
229# define OS_CODE 0x08
230#endif
231
232#if 0 /* CP/M */
233# define OS_CODE 0x09
234#endif
235
236#ifdef TOPS20
237# define OS_CODE 0x0a
238#endif
f4c6fd49 239
642e522c 240#ifdef WIN32 /* Window 95 & Windows NT */
241# define OS_CODE 0x0b
242#endif
243
244#if 0 /* QDOS */
245# define OS_CODE 0x0c
246#endif
247
248#if 0 /* Acorn RISCOS */
249# define OS_CODE 0x0d
250#endif
251
252#if 0 /* ??? */
253# define OS_CODE 0x0e
254#endif
255
256#ifdef __50SERIES /* Prime/PRIMOS */
257# define OS_CODE 0x0F
258#endif
259
260/* Default to UNIX */
261#ifndef OS_CODE
262# define OS_CODE 0x03 /* assume Unix */
263#endif
f4c6fd49 264
642e522c 265#ifndef GZIP_OS_CODE
266# define GZIP_OS_CODE OS_CODE
267#endif
f4c6fd49 268
269#define adlerInitial adler32(0L, Z_NULL, 0)
270#define crcInitial crc32(0L, Z_NULL, 0)
271
642e522c 272
c042ae3a 273static const char * const my_z_errmsg[] = {
f4c6fd49 274 "need dictionary", /* Z_NEED_DICT 2 */
275 "stream end", /* Z_STREAM_END 1 */
276 "", /* Z_OK 0 */
277 "file error", /* Z_ERRNO (-1) */
278 "stream error", /* Z_STREAM_ERROR (-2) */
279 "data error", /* Z_DATA_ERROR (-3) */
280 "insufficient memory", /* Z_MEM_ERROR (-4) */
281 "buffer error", /* Z_BUF_ERROR (-5) */
282 "incompatible version",/* Z_VERSION_ERROR(-6) */
283 ""};
f4c6fd49 284
642e522c 285#define setDUALstatus(var, err) \
286 sv_setnv(var, (double)err) ; \
287 sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \
288 SvNOK_on(var);
289
290
c042ae3a 291#if defined(__SYMBIAN32__)
292# define NO_WRITEABLE_DATA
293#endif
294
295#define TRACE_DEFAULT 0
296
297#ifdef NO_WRITEABLE_DATA
642e522c 298# define trace TRACE_DEFAULT
c042ae3a 299#else
642e522c 300 static int trace = TRACE_DEFAULT ;
c042ae3a 301#endif
f4c6fd49 302
c042ae3a 303/* Dodge PerlIO hiding of these functions. */
304#undef printf
f4c6fd49 305
642e522c 306static char *
307#ifdef CAN_PROTOTYPE
308GetErrorString(int error_no)
309#else
310GetErrorString(error_no)
311int error_no ;
312#endif
313{
314 dTHX;
315 char * errstr ;
316
317 if (error_no == Z_ERRNO) {
318 errstr = Strerror(errno) ;
319 }
320 else
321 /* errstr = gzerror(fil, &error_no) ; */
322 errstr = (char*) my_z_errmsg[2 - error_no];
323
324 return errstr ;
325}
326
327#if 0
f4c6fd49 328static void
329#ifdef CAN_PROTOTYPE
330SetGzErrorNo(int error_no)
331#else
332SetGzErrorNo(error_no)
333int error_no ;
334#endif
335{
336 char * errstr ;
337 SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ;
338
339 if (error_no == Z_ERRNO) {
340 error_no = errno ;
341 errstr = Strerror(errno) ;
342 }
343 else
344 /* errstr = gzerror(fil, &error_no) ; */
345 errstr = (char*) my_z_errmsg[2 - error_no];
346
347 if (SvIV(gzerror_sv) != error_no) {
348 sv_setiv(gzerror_sv, error_no) ;
349 sv_setpv(gzerror_sv, errstr) ;
350 SvIOK_on(gzerror_sv) ;
351 }
352
353}
354
642e522c 355
f4c6fd49 356static void
357#ifdef CAN_PROTOTYPE
358SetGzError(gzFile file)
359#else
360SetGzError(file)
361gzFile file ;
362#endif
363{
364 int error_no ;
365
366 (void)gzerror(file, &error_no) ;
367 SetGzErrorNo(error_no) ;
368}
369
642e522c 370#endif
371
372#ifdef MAGIC_APPEND
373
374/*
375 The following two functions are taken almost directly from
376 examples/gzappend.c. Only cosmetic changes have been made to conform to
377 the coding style of the rest of the code in this file.
378*/
379
380
381/* return the greatest common divisor of a and b using Euclid's algorithm,
382 modified to be fast when one argument much greater than the other, and
383 coded to avoid unnecessary swapping */
384static unsigned
385#ifdef CAN_PROTOTYPE
386gcd(unsigned a, unsigned b)
387#else
388gcd(a, b)
389 unsigned a;
390 unsigned b;
391#endif
392{
393 unsigned c;
394
395 while (a && b)
396 if (a > b) {
397 c = b;
398 while (a - c >= c)
399 c <<= 1;
400 a -= c;
401 }
402 else {
403 c = a;
404 while (b - c >= c)
405 c <<= 1;
406 b -= c;
407 }
408 return a + b;
409}
410
411/* rotate list[0..len-1] left by rot positions, in place */
412static void
413#ifdef CAN_PROTOTYPE
414rotate(unsigned char *list, unsigned len, unsigned rot)
415#else
416rotate(list, len, rot)
417 unsigned char *list;
418 unsigned len ;
419 unsigned rot;
420#endif
421{
422 unsigned char tmp;
423 unsigned cycles;
424 unsigned char *start, *last, *to, *from;
425
426 /* normalize rot and handle degenerate cases */
427 if (len < 2) return;
428 if (rot >= len) rot %= len;
429 if (rot == 0) return;
430
431 /* pointer to last entry in list */
432 last = list + (len - 1);
433
434 /* do simple left shift by one */
435 if (rot == 1) {
436 tmp = *list;
437 memcpy(list, list + 1, len - 1);
438 *last = tmp;
439 return;
440 }
441
442 /* do simple right shift by one */
443 if (rot == len - 1) {
444 tmp = *last;
445 memmove(list + 1, list, len - 1);
446 *list = tmp;
447 return;
448 }
449
450 /* otherwise do rotate as a set of cycles in place */
451 cycles = gcd(len, rot); /* number of cycles */
452 do {
453 start = from = list + cycles; /* start index is arbitrary */
454 tmp = *from; /* save entry to be overwritten */
455 for (;;) {
456 to = from; /* next step in cycle */
457 from += rot; /* go right rot positions */
458 if (from > last) from -= len; /* (pointer better not wrap) */
459 if (from == start) break; /* all but one shifted */
460 *to = *from; /* shift left */
461 }
462 *to = tmp; /* complete the circle */
463 } while (--cycles);
464}
465
466#endif /* MAGIC_APPEND */
467
f4c6fd49 468static void
469#ifdef CAN_PROTOTYPE
470DispHex(void * ptr, int length)
471#else
472DispHex(ptr, length)
473 void * ptr;
474 int length;
475#endif
476{
477 char * p = (char*)ptr;
478 int i;
479 for (i = 0; i < length; ++i) {
480 printf(" %02x", 0xFF & *(p+i));
481 }
482}
483
484
485static void
486#ifdef CAN_PROTOTYPE
487DispStream(di_stream * s, char * message)
488#else
489DispStream(s, message)
490 di_stream * s;
491 char * message;
492#endif
493{
494
495#if 0
496 if (! trace)
497 return ;
498#endif
499
642e522c 500#define EnDis(f) (s->flags & f ? "Enabled" : "Disabled")
501
502 printf("DispStream 0x%p", s) ;
503 if (message)
504 printf("- %s \n", message) ;
505 printf("\n") ;
f4c6fd49 506
507 if (!s) {
642e522c 508 printf(" stream pointer is NULL\n");
f4c6fd49 509 }
510 else {
642e522c 511 printf(" stream 0x%p\n", &(s->stream));
512 printf(" zalloc 0x%p\n", s->stream.zalloc);
513 printf(" zfree 0x%p\n", s->stream.zfree);
514 printf(" opaque 0x%p\n", s->stream.opaque);
515 if (s->stream.msg)
516 printf(" msg %s\n", s->stream.msg);
517 else
518 printf(" msg \n");
519 printf(" next_in 0x%p", s->stream.next_in);
520 if (s->stream.next_in){
521 printf(" =>");
f4c6fd49 522 DispHex(s->stream.next_in, 4);
642e522c 523 }
f4c6fd49 524 printf("\n");
525
642e522c 526 printf(" next_out 0x%p", s->stream.next_out);
527 if (s->stream.next_out){
528 printf(" =>");
f4c6fd49 529 DispHex(s->stream.next_out, 4);
642e522c 530 }
f4c6fd49 531 printf("\n");
532
642e522c 533 printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in);
534 printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out);
535 printf(" total_in %ld\n", s->stream.total_in);
536 printf(" total_out %ld\n", s->stream.total_out);
537 printf(" adler %ld\n", s->stream.adler );
538 printf(" bufsize %ld\n", s->bufsize);
539 printf(" dictionary 0x%p\n", s->dictionary);
540 printf(" dict_adler 0x%ld\n",s->dict_adler);
541 printf(" zip_mode %d\n", s->zip_mode);
542 printf(" crc32 0x%x\n", (unsigned)s->crc32);
543 printf(" adler32 0x%x\n", (unsigned)s->adler32);
544 printf(" flags 0x%x\n", s->flags);
545 printf(" APPEND %s\n", EnDis(FLAG_APPEND));
546 printf(" CRC32 %s\n", EnDis(FLAG_CRC32));
547 printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32));
548 printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT));
549
550#ifdef MAGIC_APPEND
551 printf(" window 0x%p\n", s->window);
552#endif
553 printf("\n");
f4c6fd49 554
555 }
556}
557
f4c6fd49 558static di_stream *
559#ifdef CAN_PROTOTYPE
642e522c 560InitStream(void)
f4c6fd49 561#else
642e522c 562InitStream()
f4c6fd49 563#endif
564{
565 di_stream *s ;
566
567 ZMALLOC(s, di_stream) ;
568
f4c6fd49 569 return s ;
570
571}
572
642e522c 573static void
f4c6fd49 574#ifdef CAN_PROTOTYPE
642e522c 575PostInitStream(di_stream * s, int flags, int bufsize, int windowBits)
f4c6fd49 576#else
642e522c 577PostInitStream(s, flags, bufsize, windowBits)
578 di_stream *s ;
579 int flags ;
580 int bufsize ;
581 int windowBits ;
f4c6fd49 582#endif
583{
642e522c 584 s->bufsize = bufsize ;
585 s->bufinc = bufsize ;
586 s->last_error = 0 ;
587 s->flags = flags ;
588 s->zip_mode = (windowBits < 0) ;
589 if (flags & FLAG_CRC32)
590 s->crc32 = crcInitial ;
591 if (flags & FLAG_ADLER32)
592 s->adler32 = adlerInitial ;
f4c6fd49 593}
594
642e522c 595
f4c6fd49 596static SV*
597#ifdef CAN_PROTOTYPE
598deRef(SV * sv, char * string)
599#else
600deRef(sv, string)
601SV * sv ;
602char * string;
603#endif
604{
c042ae3a 605 dTHX;
642e522c 606 SvGETMAGIC(sv);
607
f4c6fd49 608 if (SvROK(sv)) {
642e522c 609 sv = SvRV(sv) ;
610 SvGETMAGIC(sv);
611 switch(SvTYPE(sv)) {
f4c6fd49 612 case SVt_PVAV:
613 case SVt_PVHV:
614 case SVt_PVCV:
615 croak("%s: buffer parameter is not a SCALAR reference", string);
642e522c 616 }
617 if (SvROK(sv))
618 croak("%s: buffer parameter is a reference to a reference", string) ;
f4c6fd49 619 }
620
621 if (!SvOK(sv)) {
622 sv = newSVpv("", 0);
642e522c 623 }
624
625 return sv ;
626}
627
628static SV*
629#ifdef CAN_PROTOTYPE
630deRef_l(SV * sv, char * string)
631#else
632deRef_l(sv, string)
633SV * sv ;
634char * string ;
635#endif
636{
637 bool wipe = 0 ;
638
639 SvGETMAGIC(sv);
640 wipe = ! SvOK(sv) ;
641
642 if (SvROK(sv)) {
643 sv = SvRV(sv) ;
644 SvGETMAGIC(sv);
645 wipe = ! SvOK(sv) ;
646
647 switch(SvTYPE(sv)) {
648 case SVt_PVAV:
649 case SVt_PVHV:
650 case SVt_PVCV:
651 croak("%s: buffer parameter is not a SCALAR reference", string);
652 }
653 if (SvROK(sv))
654 croak("%s: buffer parameter is a reference to a reference", string) ;
655 }
656
657 if (SvREADONLY(sv) && PL_curcop != &PL_compiling)
658 croak("%s: buffer parameter is read-only", string);
659
660 SvUPGRADE(sv, SVt_PV);
661
662 if (wipe)
663 SvCUR_set(sv, 0);
664
665 SvOOK_off(sv);
666 SvPOK_only(sv);
667
f4c6fd49 668 return sv ;
669}
670
642e522c 671
f4c6fd49 672#include "constants.h"
673
642e522c 674MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
f4c6fd49 675
676REQUIRE: 1.924
677PROTOTYPES: DISABLE
678
679INCLUDE: constants.xs
680
681BOOT:
682 /* Check this version of zlib is == 1 */
683 if (zlibVersion()[0] != '1')
684 croak("Compress::Zlib needs zlib version 1.x\n") ;
685
686 {
642e522c 687 /* Create the $os_code scalar */
688 SV * os_code_sv = perl_get_sv("Compress::Zlib::gzip_os_code", GV_ADDMULTI) ;
689 sv_setiv(os_code_sv, GZIP_OS_CODE) ;
690 }
691
692 {
f4c6fd49 693 /* Create the $gzerror scalar */
694 SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ;
695 sv_setiv(gzerror_sv, 0) ;
696 sv_setpv(gzerror_sv, "") ;
697 SvIOK_on(gzerror_sv) ;
698 }
699
700
642e522c 701int
702_readonly_ref(sv)
703 SV* sv
704 CODE:
705 if (SvROK(sv))
706 RETVAL = SvREADONLY(SvRV(sv)) ;
707 else
708 RETVAL = SvREADONLY(sv) ;
709 OUTPUT:
710 RETVAL
711
712void
713_dualvar(num,str)
714 SV * num
715 SV * str
716PROTOTYPE: $$
717CODE:
718{
719 STRLEN len;
720 char *ptr = SvPVbyte(str,len);
721 ST(0) = sv_newmortal();
722 SvUPGRADE(ST(0),SVt_PVNV);
723 sv_setpvn(ST(0),ptr,len);
724 if(SvNOK(num) || SvPOK(num) || SvMAGICAL(num)) {
5e701d2b 725 SvNV_set(ST(0), SvNV(num));
642e522c 726 SvNOK_on(ST(0));
727 }
728#ifdef SVf_IVisUVXXXX
729 else if (SvUOK(num)) {
730 SvUVX(ST(0)) = SvUV(num);
731 SvIOK_on(ST(0));
732 SvIsUV_on(ST(0));
733 }
734#endif
735 else {
5e701d2b 736 SvIV_set(ST(0), SvIV(num));
642e522c 737 SvIOK_on(ST(0));
738 }
739 XSRETURN(1);
740}
741
742
f4c6fd49 743#define Zip_zlib_version() (char*)zlib_version
744char*
745Zip_zlib_version()
746
06edba15 747unsigned
748ZLIB_VERNUM()
749 CODE:
750#ifdef ZLIB_VERNUM
751 RETVAL = ZLIB_VERNUM ;
752#else
753 /* 1.1.4 => 0x1140 */
754 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
755 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
756 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
757#endif
758 OUTPUT:
759 RETVAL
760
642e522c 761MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
f4c6fd49 762
642e522c 763#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
f4c6fd49 764
642e522c 765uLong
766Zip_adler32(buf, adler=adlerInitial)
767 uLong adler = NO_INIT
768 STRLEN len = NO_INIT
769 Bytef * buf = NO_INIT
770 SV * sv = ST(0) ;
771 INIT:
772 /* If the buffer is a reference, dereference it */
773 sv = deRef(sv, "adler32") ;
774#ifdef UTF8_AVAILABLE
775 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
776 croak("Wide character in Compress::Zlib::adler32");
777#endif
778 buf = (Byte*)SvPVbyte(sv, len) ;
f4c6fd49 779
642e522c 780 if (items < 2)
781 adler = adlerInitial;
782 else if (SvOK(ST(1)))
783 adler = SvUV(ST(1)) ;
784 else
785 adler = adlerInitial;
786
787#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
f4c6fd49 788
642e522c 789uLong
790Zip_crc32(buf, crc=crcInitial)
791 uLong crc = NO_INIT
792 STRLEN len = NO_INIT
793 Bytef * buf = NO_INIT
794 SV * sv = ST(0) ;
795 INIT:
796 /* If the buffer is a reference, dereference it */
797 sv = deRef(sv, "crc32") ;
798#ifdef UTF8_AVAILABLE
799 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
800 croak("Wide character in Compress::Zlib::crc32");
801#endif
802 buf = (Byte*)SvPVbyte(sv, len) ;
f4c6fd49 803
642e522c 804 if (items < 2)
805 crc = crcInitial;
806 else if (SvOK(ST(1)))
807 crc = SvUV(ST(1)) ;
808 else
809 crc = crcInitial;
f4c6fd49 810
811
642e522c 812uLong
813crc32_combine(crc1, crc2, len2)
814 uLong crc1
815 uLong crc2
816 z_off_t len2
f4c6fd49 817 CODE:
642e522c 818#ifndef AT_LEAST_ZLIB_1_2_2_1
819 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
820 croak("crc32_combine needs zlib 1.2.3 or better");
f4c6fd49 821#else
642e522c 822 RETVAL = crc32_combine(crc1, crc2, len2);
f4c6fd49 823#endif
642e522c 824 OUTPUT:
825 RETVAL
f4c6fd49 826
827
642e522c 828uLong
829adler32_combine(adler1, adler2, len2)
830 uLong adler1
831 uLong adler2
832 z_off_t len2
f4c6fd49 833 CODE:
642e522c 834#ifndef AT_LEAST_ZLIB_1_2_2_1
835 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
836 croak("adler32_combine needs zlib 1.2.3 or better");
f4c6fd49 837#else
642e522c 838 RETVAL = adler32_combine(adler1, adler2, len2);
f4c6fd49 839#endif
642e522c 840 OUTPUT:
841 RETVAL
f4c6fd49 842
f4c6fd49 843
844MODULE = Compress::Zlib PACKAGE = Compress::Zlib
845
846void
642e522c 847_deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
848 int flags
f4c6fd49 849 int level
850 int method
851 int windowBits
852 int memLevel
853 int strategy
854 uLong bufsize
642e522c 855 SV* dictionary
f4c6fd49 856 PPCODE:
f4c6fd49 857 int err ;
858 deflateStream s ;
859
860 if (trace)
642e522c 861 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld\n",
f4c6fd49 862 level, method, windowBits, memLevel, strategy, bufsize) ;
642e522c 863 if ((s = InitStream() )) {
f4c6fd49 864
865 s->Level = level;
866 s->Method = method;
867 s->WindowBits = windowBits;
868 s->MemLevel = memLevel;
869 s->Strategy = strategy;
870
871 err = deflateInit2(&(s->stream), level,
872 method, windowBits, memLevel, strategy);
873
874 /* Check if a dictionary has been specified */
642e522c 875
f4c6fd49 876 if (err == Z_OK && SvCUR(dictionary)) {
642e522c 877#ifdef UTF8_AVAILABLE
878 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
879 croak("Wide character in Compress::Zlib::Deflate::new dicrionary parameter");
880#endif
881 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
f4c6fd49 882 SvCUR(dictionary)) ;
883 s->dict_adler = s->stream.adler ;
884 }
885
886 if (err != Z_OK) {
887 Safefree(s) ;
888 s = NULL ;
889 }
642e522c 890 else
891 PostInitStream(s, flags, bufsize, windowBits) ;
f4c6fd49 892
893 }
894 else
895 err = Z_MEM_ERROR ;
896
897 XPUSHs(sv_setref_pv(sv_newmortal(),
898 "Compress::Zlib::deflateStream", (void*)s));
642e522c 899 if (GIMME == G_ARRAY) {
900 SV * sv = sv_2mortal(newSViv(err)) ;
901 setDUALstatus(sv, err);
902 XPUSHs(sv) ;
903 }
f4c6fd49 904
905void
642e522c 906_inflateInit(flags, windowBits, bufsize, dictionary)
907 int flags
f4c6fd49 908 int windowBits
909 uLong bufsize
910 SV * dictionary
642e522c 911 ALIAS:
912 _inflateScanInit = 1
f4c6fd49 913 PPCODE:
914
915 int err = Z_OK ;
916 inflateStream s ;
642e522c 917#ifndef MAGIC_APPEND
918 if (ix == 1)
919 croak("inflateScanInit needs zlib 1.2.1 or better");
920#endif
f4c6fd49 921 if (trace)
642e522c 922 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
923 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
924 if ((s = InitStream() )) {
f4c6fd49 925
926 s->WindowBits = windowBits;
927
928 err = inflateInit2(&(s->stream), windowBits);
f4c6fd49 929 if (err != Z_OK) {
930 Safefree(s) ;
931 s = NULL ;
932 }
933 else if (SvCUR(dictionary)) {
934 /* Dictionary specified - take a copy for use in inflate */
935 s->dictionary = newSVsv(dictionary) ;
936 }
642e522c 937 if (s) {
938 PostInitStream(s, flags, bufsize, windowBits) ;
939#ifdef MAGIC_APPEND
940 if (ix == 1)
941 {
942 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
943 }
944#endif
945 }
f4c6fd49 946 }
947 else
948 err = Z_MEM_ERROR ;
949
950 XPUSHs(sv_setref_pv(sv_newmortal(),
642e522c 951 ix == 1
952 ? "Compress::Zlib::inflateScanStream"
953 : "Compress::Zlib::inflateStream",
954 (void*)s));
955 if (GIMME == G_ARRAY) {
956 SV * sv = sv_2mortal(newSViv(err)) ;
957 setDUALstatus(sv, err);
958 XPUSHs(sv) ;
959 }
f4c6fd49 960
961
962
963MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
964
965void
966DispStream(s, message=NULL)
642e522c 967 Compress::Zlib::deflateStream s
968 char * message
969
970DualType
971deflateReset(s)
972 Compress::Zlib::deflateStream s
973 CODE:
974 RETVAL = deflateReset(&(s->stream)) ;
975 if (RETVAL == Z_OK) {
976 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
977 }
978 OUTPUT:
979 RETVAL
f4c6fd49 980
642e522c 981DualType
982deflate (s, buf, output)
f4c6fd49 983 Compress::Zlib::deflateStream s
984 SV * buf
642e522c 985 SV * output
986 uInt cur_length = NO_INIT
987 uInt increment = NO_INIT
988 int RETVAL = 0;
989 CODE:
990
991 /* If the input buffer is a reference, dereference it */
f4c6fd49 992 buf = deRef(buf, "deflate") ;
993
994 /* initialise the input buffer */
642e522c 995#ifdef UTF8_AVAILABLE
996 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
997 croak("Wide character in Compress::Zlib::Deflate::deflate input parameter");
998#endif
d967198d 999 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1000 s->stream.avail_in = SvCUR(buf) ;
642e522c 1001
1002 if (s->flags & FLAG_CRC32)
1003 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
1004
1005 if (s->flags & FLAG_ADLER32)
1006 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
1007
1008 /* and retrieve the output buffer */
1009 output = deRef_l(output, "deflate") ;
1010#ifdef UTF8_AVAILABLE
1011 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1012 croak("Wide character in Compress::Zlib::Deflate::deflate output parameter");
1013#endif
1014
1015 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1016 SvCUR_set(output, 0);
1017 /* sv_setpvn(output, "", 0); */
1018 }
1019 cur_length = SvCUR(output) ;
1020 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1021 increment = SvLEN(output) - cur_length;
1022 s->stream.avail_out = increment;
1023#ifdef SETP_BYTE
f4c6fd49 1024 /* Check for saved output from deflateParams */
1025 if (s->deflateParams_out_valid) {
1026 *(s->stream.next_out) = s->deflateParams_out_byte;
1027 ++ s->stream.next_out;
1028 -- s->stream.avail_out ;
1029 s->deflateParams_out_valid = FALSE;
1030 }
642e522c 1031#else
1032 /* Check for saved output from deflateParams */
1033 if (s->deflateParams_out_length) {
1034 uLong plen = s->deflateParams_out_length ;
1035 /* printf("Copy %d bytes saved data\n", plen);*/
1036 if (s->stream.avail_out < plen) {
1037 /*printf("GROW from %d to %d\n", s->stream.avail_out,
1038 SvLEN(output) + plen - s->stream.avail_out); */
1039 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1040 }
1041
1042 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1043 cur_length = cur_length + plen;
1044 SvCUR_set(output, cur_length);
1045 s->stream.next_out += plen ;
1046 s->stream.avail_out = SvLEN(output) - cur_length ;
1047 increment = s->stream.avail_out;
1048 s->deflateParams_out_length = 0;
1049 }
1050#endif
f4c6fd49 1051 while (s->stream.avail_in != 0) {
1052
1053 if (s->stream.avail_out == 0) {
642e522c 1054 /* out of space in the output buffer so make it bigger */
f4c6fd49 1055 s->bufinc *= 2 ;
642e522c 1056 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1057 cur_length += increment ;
1058 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1059 increment = s->bufinc ;
1060 s->stream.avail_out = increment;
f4c6fd49 1061 }
642e522c 1062
1063 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
1064 if (RETVAL != Z_OK)
f4c6fd49 1065 break;
1066 }
1067
642e522c 1068 s->last_error = RETVAL ;
1069 if (RETVAL == Z_OK) {
f4c6fd49 1070 SvPOK_only(output);
642e522c 1071 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
f4c6fd49 1072 }
642e522c 1073 OUTPUT:
1074 RETVAL
1075 output
f4c6fd49 1076
1077
f4c6fd49 1078void
642e522c 1079DESTROY(s)
f4c6fd49 1080 Compress::Zlib::deflateStream s
642e522c 1081 CODE:
1082 deflateEnd(&s->stream) ;
1083 if (s->dictionary)
1084 SvREFCNT_dec(s->dictionary) ;
1085#ifndef SETP_BYTE
1086 if (s->deflateParams_out_buffer)
1087 Safefree(s->deflateParams_out_buffer);
1088#endif
1089 Safefree(s) ;
1090
1091
1092DualType
1093flush(s, output, f=Z_FINISH)
1094 Compress::Zlib::deflateStream s
1095 SV * output
1096 int f
1097 uInt cur_length = NO_INIT
1098 uInt increment = NO_INIT
1099 CODE:
f4c6fd49 1100
1101 s->stream.avail_in = 0; /* should be zero already anyway */
1102
642e522c 1103 /* retrieve the output buffer */
1104 output = deRef_l(output, "flush") ;
1105#ifdef UTF8_AVAILABLE
1106 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1107 croak("Wide character in Compress::Zlib::Deflate::flush input parameter");
1108#endif
1109 if(! s->flags & FLAG_APPEND) {
1110 SvCUR_set(output, 0);
1111 /* sv_setpvn(output, "", 0); */
1112 }
1113 cur_length = SvCUR(output) ;
1114 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1115 increment = SvLEN(output) - cur_length;
1116 s->stream.avail_out = increment;
1117#ifdef SETP_BYTE
f4c6fd49 1118 /* Check for saved output from deflateParams */
1119 if (s->deflateParams_out_valid) {
1120 *(s->stream.next_out) = s->deflateParams_out_byte;
1121 ++ s->stream.next_out;
1122 -- s->stream.avail_out ;
1123 s->deflateParams_out_valid = FALSE;
1124 }
642e522c 1125#else
1126 /* Check for saved output from deflateParams */
1127 if (s->deflateParams_out_length) {
1128 uLong plen = s->deflateParams_out_length ;
1129 /* printf("Copy %d bytes saved data\n", plen); */
1130 if (s->stream.avail_out < plen) {
1131 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1132 SvLEN(output) + plen - s->stream.avail_out); */
1133 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1134 }
1135
1136 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1137 cur_length = cur_length + plen;
1138 SvCUR_set(output, cur_length);
1139 s->stream.next_out += plen ;
1140 s->stream.avail_out = SvLEN(output) - cur_length ;
1141 increment = s->stream.avail_out;
1142 s->deflateParams_out_length = 0;
1143 }
1144#endif
f4c6fd49 1145
1146 for (;;) {
1147 if (s->stream.avail_out == 0) {
1148 /* consumed all the available output, so extend it */
1149 s->bufinc *= 2 ;
642e522c 1150 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1151 cur_length += increment ;
1152 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1153 increment = s->bufinc ;
1154 s->stream.avail_out = increment;
f4c6fd49 1155 }
642e522c 1156 RETVAL = deflate(&(s->stream), f);
f4c6fd49 1157
1158 /* deflate has finished flushing only when it hasn't used up
1159 * all the available space in the output buffer:
1160 */
642e522c 1161 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
f4c6fd49 1162 break;
1163 }
1164
642e522c 1165 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1166 s->last_error = RETVAL ;
f4c6fd49 1167
642e522c 1168 if (RETVAL == Z_OK) {
f4c6fd49 1169 SvPOK_only(output);
642e522c 1170 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
f4c6fd49 1171 }
642e522c 1172 OUTPUT:
1173 RETVAL
1174 output
f4c6fd49 1175
642e522c 1176
1177DualType
f4c6fd49 1178_deflateParams(s, flags, level, strategy, bufsize)
1179 Compress::Zlib::deflateStream s
1180 int flags
1181 int level
1182 int strategy
1183 uLong bufsize
1184 CODE:
642e522c 1185 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1186 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
f4c6fd49 1187 if (flags & 1)
1188 s->Level = level ;
1189 if (flags & 2)
1190 s->Strategy = strategy ;
642e522c 1191 if (flags & 4) {
f4c6fd49 1192 s->bufsize = bufsize;
1193 s->bufinc = bufsize;
1194 }
642e522c 1195 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1196#ifdef SETP_BYTE
f4c6fd49 1197 s->stream.avail_in = 0;
1198 s->stream.next_out = &(s->deflateParams_out_byte) ;
1199 s->stream.avail_out = 1;
1200 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1201 s->deflateParams_out_valid =
1202 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
642e522c 1203 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1204#else
1205 /* printf("Level %d Strategy %d, Prev Len %d\n",
1206 s->Level, s->Strategy, s->deflateParams_out_length); */
1207 s->stream.avail_in = 0;
1208 if (s->deflateParams_out_buffer == NULL)
1209 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1210 s->stream.next_out = s->deflateParams_out_buffer ;
1211 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1212
1213 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1214 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1215 /* printf("RETVAL %d, length out %d, avail %d\n",
1216 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1217#endif
f4c6fd49 1218 OUTPUT:
1219 RETVAL
1220
1221
1222int
1223get_Level(s)
1224 Compress::Zlib::deflateStream s
1225 CODE:
1226 RETVAL = s->Level ;
1227 OUTPUT:
1228 RETVAL
1229
1230int
1231get_Strategy(s)
1232 Compress::Zlib::deflateStream s
1233 CODE:
1234 RETVAL = s->Strategy ;
1235 OUTPUT:
1236 RETVAL
1237
642e522c 1238
1239uLong
1240get_Bufsize(s)
1241 Compress::Zlib::deflateStream s
1242 CODE:
1243 RETVAL = s->bufsize ;
1244 OUTPUT:
1245 RETVAL
f4c6fd49 1246
1247
642e522c 1248int
1249status(s)
1250 Compress::Zlib::deflateStream s
1251 CODE:
1252 RETVAL = s->last_error ;
1253 OUTPUT:
1254 RETVAL
1255
1256uLong
1257crc32(s)
1258 Compress::Zlib::deflateStream s
1259 CODE:
1260 RETVAL = s->crc32 ;
1261 OUTPUT:
1262 RETVAL
1263
f4c6fd49 1264uLong
1265dict_adler(s)
1266 Compress::Zlib::deflateStream s
1267 CODE:
1268 RETVAL = s->dict_adler ;
1269 OUTPUT:
1270 RETVAL
1271
1272uLong
642e522c 1273adler32(s)
1274 Compress::Zlib::deflateStream s
1275 CODE:
1276 RETVAL = s->adler32 ;
1277 OUTPUT:
1278 RETVAL
1279
1280uLong
f4c6fd49 1281total_in(s)
1282 Compress::Zlib::deflateStream s
1283 CODE:
642e522c 1284 RETVAL = s->stream.total_in ;
f4c6fd49 1285 OUTPUT:
1286 RETVAL
1287
1288uLong
1289total_out(s)
1290 Compress::Zlib::deflateStream s
1291 CODE:
642e522c 1292 RETVAL = s->stream.total_out ;
f4c6fd49 1293 OUTPUT:
1294 RETVAL
1295
1296char*
1297msg(s)
1298 Compress::Zlib::deflateStream s
1299 CODE:
642e522c 1300 RETVAL = s->stream.msg;
f4c6fd49 1301 OUTPUT:
1302 RETVAL
1303
642e522c 1304int
1305deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1306 Compress::Zlib::deflateStream s
1307 int good_length
1308 int max_lazy
1309 int nice_length
1310 int max_chain
1311 CODE:
1312#ifndef AT_LEAST_ZLIB_1_2_2_3
1313 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1314 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1315 croak("deflateTune needs zlib 1.2.2.3 or better");
1316#else
1317 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1318#endif
1319 OUTPUT:
1320 RETVAL
1321
f4c6fd49 1322
1323MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
1324
1325void
1326DispStream(s, message=NULL)
642e522c 1327 Compress::Zlib::inflateStream s
1328 char * message
f4c6fd49 1329
642e522c 1330DualType
1331inflateReset(s)
1332 Compress::Zlib::inflateStream s
1333 CODE:
1334 RETVAL = inflateReset(&(s->stream)) ;
1335 if (RETVAL == Z_OK) {
1336 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1337 }
1338 OUTPUT:
1339 RETVAL
1340
1341DualType
1342inflate (s, buf, output)
f4c6fd49 1343 Compress::Zlib::inflateStream s
1344 SV * buf
642e522c 1345 SV * output
1346 uInt cur_length = NO_INIT
1347 uInt prefix_length = NO_INIT
1348 uInt increment = NO_INIT
d967198d 1349 STRLEN stmp = NO_INIT
642e522c 1350 PREINIT:
1351#ifdef UTF8_AVAILABLE
1352 bool out_utf8 = FALSE;
1353#endif
1354 CODE:
f4c6fd49 1355 /* If the buffer is a reference, dereference it */
1356 buf = deRef(buf, "inflate") ;
642e522c 1357
1358 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
1359 croak("Compress::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified");
1360#ifdef UTF8_AVAILABLE
1361 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1362 croak("Wide character in Compress::Zlib::Inflate::inflate input parameter");
1363#endif
f4c6fd49 1364
1365 /* initialise the input buffer */
d967198d 1366 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1367 s->stream.avail_in = SvCUR(buf) ;
f4c6fd49 1368
642e522c 1369 /* and retrieve the output buffer */
1370 output = deRef_l(output, "inflate") ;
1371#ifdef UTF8_AVAILABLE
1372 if (DO_UTF8(output))
1373 out_utf8 = TRUE ;
1374 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1375 croak("Wide character in Compress::Zlib::Inflate::inflate output parameter");
1376#endif
1377 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1378 SvCUR_set(output, 0);
1379 }
1380 prefix_length = cur_length = SvCUR(output) ;
1381 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1382 increment = SvLEN(output) - cur_length;
1383 s->stream.avail_out = increment;
1384 s->bytesInflated = 0;
1385
f4c6fd49 1386 while (1) {
1387
1388 if (s->stream.avail_out == 0) {
642e522c 1389 /* out of space in the output buffer so make it bigger */
f4c6fd49 1390 s->bufinc *= 2 ;
642e522c 1391 Sv_Grow(output, SvLEN(output) + s->bufinc + 1) ;
1392 cur_length += increment ;
1393 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1394 increment = s->bufinc ;
1395 s->stream.avail_out = increment;
f4c6fd49 1396 }
1397
642e522c 1398 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
f4c6fd49 1399
642e522c 1400
1401 if (RETVAL == Z_BUF_ERROR) {
1402 if (s->stream.avail_out == 0)
1403 continue ;
1404 if (s->stream.avail_in == 0) {
1405 RETVAL = Z_OK ;
1406 break ;
1407 }
1408 }
1409
1410 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1411 s->dict_adler = s->stream.adler ;
1412 RETVAL = inflateSetDictionary(&(s->stream),
1413 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1414 SvCUR(s->dictionary));
1415 }
1416
1417 if (RETVAL != Z_OK)
f4c6fd49 1418 break;
1419 }
1420
642e522c 1421 s->last_error = RETVAL ;
1422 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) {
f4c6fd49 1423 unsigned in ;
642e522c 1424
1425 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
f4c6fd49 1426 SvPOK_only(output);
642e522c 1427 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1428 *SvEND(output) = '\0';
1429#ifdef UTF8_AVAILABLE
1430 if (out_utf8)
1431 sv_utf8_upgrade(output);
1432#endif
1433
1434 if (s->flags & FLAG_CRC32 )
1435 s->crc32 = crc32(s->crc32,
1436 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1437 SvCUR(output)-prefix_length) ;
1438
1439 if (s->flags & FLAG_ADLER32)
1440 s->adler32 = adler32(s->adler32,
1441 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1442 SvCUR(output)-prefix_length) ;
1443
1444 /* fix the input buffer */
1445 if (s->flags & FLAG_CONSUME_INPUT) {
1446 in = s->stream.avail_in ;
1447 SvCUR_set(buf, in) ;
1448 if (in)
1449 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
f4c6fd49 1450 *SvEND(buf) = '\0';
1451 SvSETMAGIC(buf);
1452 }
1453 }
642e522c 1454 OUTPUT:
1455 RETVAL
1456 buf
1457 output
f4c6fd49 1458
642e522c 1459uLong
1460inflateCount(s)
1461 Compress::Zlib::inflateStream s
1462 CODE:
1463 RETVAL = s->bytesInflated;
1464 OUTPUT:
1465 RETVAL
1466
1467
1468DualType
f4c6fd49 1469inflateSync (s, buf)
1470 Compress::Zlib::inflateStream s
1471 SV * buf
1472 CODE:
1473
1474 /* If the buffer is a reference, dereference it */
1475 buf = deRef(buf, "inflateSync") ;
642e522c 1476#ifdef UTF8_AVAILABLE
1477 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1478 croak("Wide character in Compress::Zlib::Inflate::inflateSync");
1479#endif
f4c6fd49 1480
1481 /* initialise the input buffer */
642e522c 1482 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
f4c6fd49 1483 s->stream.avail_in = SvCUR(buf) ;
1484
1485 /* inflateSync doesn't create any output */
1486 s->stream.next_out = (Bytef*) NULL;
1487 s->stream.avail_out = 0;
1488
1489 RETVAL = inflateSync(&(s->stream));
642e522c 1490 s->last_error = RETVAL ;
1491
1492 /* fix the input buffer */
f4c6fd49 1493 {
f4c6fd49 1494 unsigned in = s->stream.avail_in ;
f4c6fd49 1495 SvCUR_set(buf, in) ;
1496 if (in)
642e522c 1497 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
f4c6fd49 1498 *SvEND(buf) = '\0';
1499 SvSETMAGIC(buf);
1500 }
1501 OUTPUT:
1502 RETVAL
642e522c 1503 buf
f4c6fd49 1504
1505void
1506DESTROY(s)
1507 Compress::Zlib::inflateStream s
1508 CODE:
1509 inflateEnd(&s->stream) ;
1510 if (s->dictionary)
1511 SvREFCNT_dec(s->dictionary) ;
642e522c 1512#ifndef SETP_BYTE
1513 if (s->deflateParams_out_buffer)
1514 Safefree(s->deflateParams_out_buffer);
1515#endif
1516#ifdef MAGIC_APPEND
1517 if (s->window)
1518 Safefree(s->window);
1519#endif
f4c6fd49 1520 Safefree(s) ;
1521
1522
1523uLong
642e522c 1524status(s)
1525 Compress::Zlib::inflateStream s
1526 CODE:
1527 RETVAL = s->last_error ;
1528 OUTPUT:
1529 RETVAL
1530
1531uLong
1532crc32(s)
1533 Compress::Zlib::inflateStream s
1534 CODE:
1535 RETVAL = s->crc32 ;
1536 OUTPUT:
1537 RETVAL
1538
1539uLong
f4c6fd49 1540dict_adler(s)
1541 Compress::Zlib::inflateStream s
1542 CODE:
1543 RETVAL = s->dict_adler ;
1544 OUTPUT:
1545 RETVAL
1546
1547uLong
1548total_in(s)
1549 Compress::Zlib::inflateStream s
1550 CODE:
642e522c 1551 RETVAL = s->stream.total_in ;
1552 OUTPUT:
1553 RETVAL
1554
1555uLong
1556adler32(s)
1557 Compress::Zlib::inflateStream s
1558 CODE:
1559 RETVAL = s->adler32 ;
f4c6fd49 1560 OUTPUT:
1561 RETVAL
1562
1563uLong
1564total_out(s)
1565 Compress::Zlib::inflateStream s
1566 CODE:
642e522c 1567 RETVAL = s->stream.total_out ;
f4c6fd49 1568 OUTPUT:
1569 RETVAL
1570
1571char*
1572msg(s)
1573 Compress::Zlib::inflateStream s
1574 CODE:
642e522c 1575 RETVAL = s->stream.msg;
f4c6fd49 1576 OUTPUT:
1577 RETVAL
1578
1579
642e522c 1580uLong
1581get_Bufsize(s)
1582 Compress::Zlib::inflateStream s
1583 CODE:
1584 RETVAL = s->bufsize ;
1585 OUTPUT:
1586 RETVAL
1587
1588bool
1589set_Append(s, mode)
1590 Compress::Zlib::inflateStream s
1591 bool mode
1592 CODE:
1593 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1594 if (mode)
1595 s->flags |= FLAG_APPEND ;
1596 else
1597 s->flags &= ~FLAG_APPEND ;
1598 OUTPUT:
1599 RETVAL
1600
1601MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateScanStream
1602
1603void
1604DESTROY(s)
1605 Compress::Zlib::inflateScanStream s
1606 CODE:
1607 inflateEnd(&s->stream) ;
1608 if (s->dictionary)
1609 SvREFCNT_dec(s->dictionary) ;
1610#ifndef SETP_BYTE
1611 if (s->deflateParams_out_buffer)
1612 Safefree(s->deflateParams_out_buffer);
1613#endif
1614#ifdef MAGIC_APPEND
1615 if (s->window)
1616 Safefree(s->window);
1617#endif
1618 Safefree(s) ;
1619
1620void
1621DispStream(s, message=NULL)
1622 Compress::Zlib::inflateScanStream s
1623 char * message
1624
1625DualType
1626scan(s, buf, out=NULL)
1627 Compress::Zlib::inflateScanStream s
1628 SV * buf
1629 SV * out
1630 int start_len = NO_INIT
d967198d 1631 STRLEN stmp = NO_INIT
642e522c 1632 ALIAS:
1633 inflate = 1
1634 CODE:
1635 /* If the input buffer is a reference, dereference it */
1636 ix = ix ; /* warning suppression */
1637#ifndef MAGIC_APPEND
1638 buf = buf;
1639 croak("scan needs zlib 1.2.1 or better");
1640#else
1641 buf = deRef(buf, "inflateScan") ;
1642#ifdef UTF8_AVAILABLE
1643 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1644 croak("Wide character in Compress::Zlib::InflateScan::scan input parameter");
1645#endif
1646
1647 /* initialise the input buffer */
d967198d 1648 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1649 s->stream.avail_in = SvCUR(buf) ;
642e522c 1650 start_len = s->stream.avail_in ;
1651 s->bytesInflated = 0 ;
1652 do
1653 {
1654 if (s->stream.avail_in == 0) {
1655 RETVAL = Z_OK ;
1656 break ;
1657 }
1658
1659 /* set up output to next available section of sliding window */
1660 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1661 s->stream.next_out = s->window + s->window_have;
1662
1663 /* DispStream(s, "before inflate\n"); */
1664
1665 /* inflate and check for errors */
1666 RETVAL = inflate(&(s->stream), Z_BLOCK);
1667
1668
1669 if (start_len > 1)
1670 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1671
1672 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1673 RETVAL == Z_DATA_ERROR )
1674 break ;
1675
1676 if (s->flags & FLAG_CRC32 )
1677 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1678 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1679
1680 if (s->flags & FLAG_ADLER32)
1681 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1682 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1683
1684 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1685
1686 if (s->stream.avail_out)
1687 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1688 else {
1689 s->window_have = 0;
1690 s->window_full = 1;
1691 }
1692
1693 /* process end of block */
1694 if (s->stream.data_type & 128) {
1695 if (s->stream.data_type & 64) {
1696 s->window_left = s->stream.data_type & 0x1f;
1697 }
1698 else {
1699 s->window_lastbit = s->stream.data_type & 0x1f;
1700 s->lastBlockOffset = s->stream.total_in;
1701 }
1702 }
1703
1704 } while (RETVAL != Z_STREAM_END);
1705
1706 s->last_error = RETVAL ;
1707 s->window_lastoff = s->stream.total_in ;
1708
1709 if (RETVAL == Z_STREAM_END)
1710 {
1711 s->matchedEndBlock = 1 ;
1712
1713 /* save the location of the end of the compressed data */
1714 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1715 s->window_endOffset = s->stream.total_in ;
1716 if (s->window_left)
1717 {
1718 -- s->window_endOffset ;
1719 }
1720
1721 /* if window wrapped, build dictionary from window by rotating */
1722 if (s->window_full) {
1723 rotate(s->window, WINDOW_SIZE, s->window_have);
1724 s->window_have = WINDOW_SIZE;
1725 }
1726
1727 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1728 if (1) {
1729 unsigned in = s->stream.avail_in ;
1730 SvCUR_set(buf, in) ;
1731 if (in)
1732 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1733 *SvEND(buf) = '\0';
1734 SvSETMAGIC(buf);
1735 }
1736 }
1737#endif
1738 OUTPUT:
1739 RETVAL
1740
1741
1742uLong
1743getEndOffset(s)
1744 Compress::Zlib::inflateScanStream s
1745 CODE:
1746#ifndef MAGIC_APPEND
1747 croak("getEndOffset needs zlib 1.2.1 or better");
1748#else
1749 RETVAL = s->window_endOffset;
1750#endif
1751 OUTPUT:
1752 RETVAL
1753
1754uLong
1755inflateCount(s)
1756 Compress::Zlib::inflateScanStream s
1757 CODE:
1758#ifndef MAGIC_APPEND
1759 croak("inflateCount needs zlib 1.2.1 or better");
1760#else
1761 RETVAL = s->bytesInflated;
1762#endif
1763 OUTPUT:
1764 RETVAL
1765
1766
1767uLong
1768getLastBlockOffset(s)
1769 Compress::Zlib::inflateScanStream s
1770 CODE:
1771#ifndef MAGIC_APPEND
1772 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1773#else
1774 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1775#endif
1776 OUTPUT:
1777 RETVAL
1778
1779uLong
1780getLastBufferOffset(s)
1781 Compress::Zlib::inflateScanStream s
1782 CODE:
1783#ifndef MAGIC_APPEND
1784 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1785#else
1786 RETVAL = s->window_lastoff;
1787#endif
1788 OUTPUT:
1789 RETVAL
1790
1791void
1792resetLastBlockByte(s, byte)
1793 Compress::Zlib::inflateScanStream s
1794 unsigned char* byte
1795 CODE:
1796#ifndef MAGIC_APPEND
1797 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1798#else
1799 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
1800#endif
1801
1802
1803void
1804_createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1805 Compress::Zlib::inflateScanStream inf_s
1806 int flags
1807 int level
1808 int method
1809 int windowBits
1810 int memLevel
1811 int strategy
1812 uLong bufsize
1813 PPCODE:
1814 {
1815#ifndef MAGIC_APPEND
1816 flags = flags;
1817 level = level ;
1818 method = method;
1819 windowBits = windowBits;
1820 memLevel = memLevel;
1821 strategy = strategy;
1822 bufsize= bufsize;
1823 croak("_createDeflateStream needs zlib 1.2.1 or better");
1824#else
1825 int err ;
1826 deflateStream s ;
1827
1828 if (trace)
1829 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1830 level, method, windowBits, memLevel, strategy, bufsize) ;
1831 if ((s = InitStream() )) {
1832
1833 s->Level = level;
1834 s->Method = method;
1835 s->WindowBits = windowBits;
1836 s->MemLevel = memLevel;
1837 s->Strategy = strategy;
1838
1839 err = deflateInit2(&(s->stream), level,
1840 method, windowBits, memLevel, strategy);
1841
1842 if (err == Z_OK) {
1843 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1844 s->dict_adler = s->stream.adler ;
1845 }
1846
1847 if (err != Z_OK) {
1848 Safefree(s) ;
1849 s = NULL ;
1850 }
1851 else {
1852 PostInitStream(s, flags, bufsize, windowBits) ;
1853 s->crc32 = inf_s->crc32;
1854 s->adler32 = inf_s->adler32;
1855 s->stream.adler = inf_s->stream.adler ;
1856 /* s->stream.total_out = inf_s->bytesInflated ; */
1857 s->stream.total_in = inf_s->stream.total_out ;
1858 if (inf_s->window_left) {
1859 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1860 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1861 }
1862 }
1863 }
1864 else
1865 err = Z_MEM_ERROR ;
1866
1867 XPUSHs(sv_setref_pv(sv_newmortal(),
1868 "Compress::Zlib::deflateStream", (void*)s));
1869 if (GIMME == G_ARRAY) {
1870 SV * sv = sv_2mortal(newSViv(err)) ;
1871 setDUALstatus(sv, err);
1872 XPUSHs(sv) ;
1873 }
1874#endif
1875 }
1876
1877DualType
1878status(s)
1879 Compress::Zlib::inflateScanStream s
1880 CODE:
1881 RETVAL = s->last_error ;
1882 OUTPUT:
1883 RETVAL
1884
1885uLong
1886crc32(s)
1887 Compress::Zlib::inflateScanStream s
1888 CODE:
1889 RETVAL = s->crc32 ;
1890 OUTPUT:
1891 RETVAL
1892
1893
1894uLong
1895adler32(s)
1896 Compress::Zlib::inflateScanStream s
1897 CODE:
1898 RETVAL = s->adler32 ;
1899 OUTPUT:
1900 RETVAL
1901