Avoid possible dereference of NULL in the initialization of PL_origalen.
[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{
0added8b 637 dTHX;
642e522c 638 bool wipe = 0 ;
639
640 SvGETMAGIC(sv);
641 wipe = ! SvOK(sv) ;
642
643 if (SvROK(sv)) {
644 sv = SvRV(sv) ;
645 SvGETMAGIC(sv);
646 wipe = ! SvOK(sv) ;
647
648 switch(SvTYPE(sv)) {
649 case SVt_PVAV:
650 case SVt_PVHV:
651 case SVt_PVCV:
652 croak("%s: buffer parameter is not a SCALAR reference", string);
653 }
654 if (SvROK(sv))
655 croak("%s: buffer parameter is a reference to a reference", string) ;
656 }
657
658 if (SvREADONLY(sv) && PL_curcop != &PL_compiling)
659 croak("%s: buffer parameter is read-only", string);
660
661 SvUPGRADE(sv, SVt_PV);
662
663 if (wipe)
664 SvCUR_set(sv, 0);
665
666 SvOOK_off(sv);
667 SvPOK_only(sv);
668
f4c6fd49 669 return sv ;
670}
671
642e522c 672
f4c6fd49 673#include "constants.h"
674
642e522c 675MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
f4c6fd49 676
677REQUIRE: 1.924
678PROTOTYPES: DISABLE
679
680INCLUDE: constants.xs
681
682BOOT:
683 /* Check this version of zlib is == 1 */
684 if (zlibVersion()[0] != '1')
685 croak("Compress::Zlib needs zlib version 1.x\n") ;
686
687 {
642e522c 688 /* Create the $os_code scalar */
689 SV * os_code_sv = perl_get_sv("Compress::Zlib::gzip_os_code", GV_ADDMULTI) ;
690 sv_setiv(os_code_sv, GZIP_OS_CODE) ;
691 }
692
693 {
f4c6fd49 694 /* Create the $gzerror scalar */
695 SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ;
696 sv_setiv(gzerror_sv, 0) ;
697 sv_setpv(gzerror_sv, "") ;
698 SvIOK_on(gzerror_sv) ;
699 }
700
701
642e522c 702int
703_readonly_ref(sv)
704 SV* sv
705 CODE:
706 if (SvROK(sv))
707 RETVAL = SvREADONLY(SvRV(sv)) ;
708 else
709 RETVAL = SvREADONLY(sv) ;
710 OUTPUT:
711 RETVAL
712
713void
714_dualvar(num,str)
715 SV * num
716 SV * str
717PROTOTYPE: $$
718CODE:
719{
720 STRLEN len;
721 char *ptr = SvPVbyte(str,len);
722 ST(0) = sv_newmortal();
723 SvUPGRADE(ST(0),SVt_PVNV);
724 sv_setpvn(ST(0),ptr,len);
725 if(SvNOK(num) || SvPOK(num) || SvMAGICAL(num)) {
5e701d2b 726 SvNV_set(ST(0), SvNV(num));
642e522c 727 SvNOK_on(ST(0));
728 }
729#ifdef SVf_IVisUVXXXX
730 else if (SvUOK(num)) {
731 SvUVX(ST(0)) = SvUV(num);
732 SvIOK_on(ST(0));
733 SvIsUV_on(ST(0));
734 }
735#endif
736 else {
5e701d2b 737 SvIV_set(ST(0), SvIV(num));
642e522c 738 SvIOK_on(ST(0));
739 }
740 XSRETURN(1);
741}
742
743
f4c6fd49 744#define Zip_zlib_version() (char*)zlib_version
745char*
746Zip_zlib_version()
747
06edba15 748unsigned
749ZLIB_VERNUM()
750 CODE:
751#ifdef ZLIB_VERNUM
752 RETVAL = ZLIB_VERNUM ;
753#else
754 /* 1.1.4 => 0x1140 */
755 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
756 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
757 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
758#endif
759 OUTPUT:
760 RETVAL
761
642e522c 762MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
f4c6fd49 763
642e522c 764#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
f4c6fd49 765
642e522c 766uLong
767Zip_adler32(buf, adler=adlerInitial)
768 uLong adler = NO_INIT
769 STRLEN len = NO_INIT
770 Bytef * buf = NO_INIT
771 SV * sv = ST(0) ;
772 INIT:
773 /* If the buffer is a reference, dereference it */
774 sv = deRef(sv, "adler32") ;
775#ifdef UTF8_AVAILABLE
776 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
777 croak("Wide character in Compress::Zlib::adler32");
778#endif
779 buf = (Byte*)SvPVbyte(sv, len) ;
f4c6fd49 780
642e522c 781 if (items < 2)
782 adler = adlerInitial;
783 else if (SvOK(ST(1)))
784 adler = SvUV(ST(1)) ;
785 else
786 adler = adlerInitial;
787
788#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
f4c6fd49 789
642e522c 790uLong
791Zip_crc32(buf, crc=crcInitial)
792 uLong crc = NO_INIT
793 STRLEN len = NO_INIT
794 Bytef * buf = NO_INIT
795 SV * sv = ST(0) ;
796 INIT:
797 /* If the buffer is a reference, dereference it */
798 sv = deRef(sv, "crc32") ;
799#ifdef UTF8_AVAILABLE
800 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
801 croak("Wide character in Compress::Zlib::crc32");
802#endif
803 buf = (Byte*)SvPVbyte(sv, len) ;
f4c6fd49 804
642e522c 805 if (items < 2)
806 crc = crcInitial;
807 else if (SvOK(ST(1)))
808 crc = SvUV(ST(1)) ;
809 else
810 crc = crcInitial;
f4c6fd49 811
812
642e522c 813uLong
814crc32_combine(crc1, crc2, len2)
815 uLong crc1
816 uLong crc2
817 z_off_t len2
f4c6fd49 818 CODE:
642e522c 819#ifndef AT_LEAST_ZLIB_1_2_2_1
820 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
821 croak("crc32_combine needs zlib 1.2.3 or better");
f4c6fd49 822#else
642e522c 823 RETVAL = crc32_combine(crc1, crc2, len2);
f4c6fd49 824#endif
642e522c 825 OUTPUT:
826 RETVAL
f4c6fd49 827
828
642e522c 829uLong
830adler32_combine(adler1, adler2, len2)
831 uLong adler1
832 uLong adler2
833 z_off_t len2
f4c6fd49 834 CODE:
642e522c 835#ifndef AT_LEAST_ZLIB_1_2_2_1
836 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
837 croak("adler32_combine needs zlib 1.2.3 or better");
f4c6fd49 838#else
642e522c 839 RETVAL = adler32_combine(adler1, adler2, len2);
f4c6fd49 840#endif
642e522c 841 OUTPUT:
842 RETVAL
f4c6fd49 843
f4c6fd49 844
845MODULE = Compress::Zlib PACKAGE = Compress::Zlib
846
847void
642e522c 848_deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
849 int flags
f4c6fd49 850 int level
851 int method
852 int windowBits
853 int memLevel
854 int strategy
855 uLong bufsize
642e522c 856 SV* dictionary
f4c6fd49 857 PPCODE:
f4c6fd49 858 int err ;
859 deflateStream s ;
860
861 if (trace)
642e522c 862 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld\n",
f4c6fd49 863 level, method, windowBits, memLevel, strategy, bufsize) ;
642e522c 864 if ((s = InitStream() )) {
f4c6fd49 865
866 s->Level = level;
867 s->Method = method;
868 s->WindowBits = windowBits;
869 s->MemLevel = memLevel;
870 s->Strategy = strategy;
871
872 err = deflateInit2(&(s->stream), level,
873 method, windowBits, memLevel, strategy);
874
875 /* Check if a dictionary has been specified */
642e522c 876
f4c6fd49 877 if (err == Z_OK && SvCUR(dictionary)) {
642e522c 878#ifdef UTF8_AVAILABLE
879 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
880 croak("Wide character in Compress::Zlib::Deflate::new dicrionary parameter");
881#endif
882 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
f4c6fd49 883 SvCUR(dictionary)) ;
884 s->dict_adler = s->stream.adler ;
885 }
886
887 if (err != Z_OK) {
888 Safefree(s) ;
889 s = NULL ;
890 }
642e522c 891 else
892 PostInitStream(s, flags, bufsize, windowBits) ;
f4c6fd49 893
894 }
895 else
896 err = Z_MEM_ERROR ;
897
898 XPUSHs(sv_setref_pv(sv_newmortal(),
899 "Compress::Zlib::deflateStream", (void*)s));
642e522c 900 if (GIMME == G_ARRAY) {
901 SV * sv = sv_2mortal(newSViv(err)) ;
902 setDUALstatus(sv, err);
903 XPUSHs(sv) ;
904 }
f4c6fd49 905
906void
642e522c 907_inflateInit(flags, windowBits, bufsize, dictionary)
908 int flags
f4c6fd49 909 int windowBits
910 uLong bufsize
911 SV * dictionary
642e522c 912 ALIAS:
913 _inflateScanInit = 1
f4c6fd49 914 PPCODE:
915
916 int err = Z_OK ;
917 inflateStream s ;
642e522c 918#ifndef MAGIC_APPEND
919 if (ix == 1)
920 croak("inflateScanInit needs zlib 1.2.1 or better");
921#endif
f4c6fd49 922 if (trace)
642e522c 923 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
924 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
925 if ((s = InitStream() )) {
f4c6fd49 926
927 s->WindowBits = windowBits;
928
929 err = inflateInit2(&(s->stream), windowBits);
f4c6fd49 930 if (err != Z_OK) {
931 Safefree(s) ;
932 s = NULL ;
933 }
934 else if (SvCUR(dictionary)) {
935 /* Dictionary specified - take a copy for use in inflate */
936 s->dictionary = newSVsv(dictionary) ;
937 }
642e522c 938 if (s) {
939 PostInitStream(s, flags, bufsize, windowBits) ;
940#ifdef MAGIC_APPEND
941 if (ix == 1)
942 {
943 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
944 }
945#endif
946 }
f4c6fd49 947 }
948 else
949 err = Z_MEM_ERROR ;
950
951 XPUSHs(sv_setref_pv(sv_newmortal(),
642e522c 952 ix == 1
953 ? "Compress::Zlib::inflateScanStream"
954 : "Compress::Zlib::inflateStream",
955 (void*)s));
956 if (GIMME == G_ARRAY) {
957 SV * sv = sv_2mortal(newSViv(err)) ;
958 setDUALstatus(sv, err);
959 XPUSHs(sv) ;
960 }
f4c6fd49 961
962
963
964MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
965
966void
967DispStream(s, message=NULL)
642e522c 968 Compress::Zlib::deflateStream s
969 char * message
970
971DualType
972deflateReset(s)
973 Compress::Zlib::deflateStream s
974 CODE:
975 RETVAL = deflateReset(&(s->stream)) ;
976 if (RETVAL == Z_OK) {
977 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
978 }
979 OUTPUT:
980 RETVAL
f4c6fd49 981
642e522c 982DualType
983deflate (s, buf, output)
f4c6fd49 984 Compress::Zlib::deflateStream s
985 SV * buf
642e522c 986 SV * output
987 uInt cur_length = NO_INIT
988 uInt increment = NO_INIT
989 int RETVAL = 0;
990 CODE:
991
992 /* If the input buffer is a reference, dereference it */
f4c6fd49 993 buf = deRef(buf, "deflate") ;
994
995 /* initialise the input buffer */
642e522c 996#ifdef UTF8_AVAILABLE
997 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
998 croak("Wide character in Compress::Zlib::Deflate::deflate input parameter");
999#endif
d13b0db4 1000 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1001 s->stream.avail_in = SvCUR(buf) ;
642e522c 1002
1003 if (s->flags & FLAG_CRC32)
1004 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
1005
1006 if (s->flags & FLAG_ADLER32)
1007 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
1008
1009 /* and retrieve the output buffer */
1010 output = deRef_l(output, "deflate") ;
1011#ifdef UTF8_AVAILABLE
1012 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1013 croak("Wide character in Compress::Zlib::Deflate::deflate output parameter");
1014#endif
1015
1016 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1017 SvCUR_set(output, 0);
1018 /* sv_setpvn(output, "", 0); */
1019 }
1020 cur_length = SvCUR(output) ;
1021 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1022 increment = SvLEN(output) - cur_length;
1023 s->stream.avail_out = increment;
1024#ifdef SETP_BYTE
f4c6fd49 1025 /* Check for saved output from deflateParams */
1026 if (s->deflateParams_out_valid) {
1027 *(s->stream.next_out) = s->deflateParams_out_byte;
1028 ++ s->stream.next_out;
1029 -- s->stream.avail_out ;
1030 s->deflateParams_out_valid = FALSE;
1031 }
642e522c 1032#else
1033 /* Check for saved output from deflateParams */
1034 if (s->deflateParams_out_length) {
1035 uLong plen = s->deflateParams_out_length ;
1036 /* printf("Copy %d bytes saved data\n", plen);*/
1037 if (s->stream.avail_out < plen) {
1038 /*printf("GROW from %d to %d\n", s->stream.avail_out,
1039 SvLEN(output) + plen - s->stream.avail_out); */
1040 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1041 }
1042
1043 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1044 cur_length = cur_length + plen;
1045 SvCUR_set(output, cur_length);
1046 s->stream.next_out += plen ;
1047 s->stream.avail_out = SvLEN(output) - cur_length ;
1048 increment = s->stream.avail_out;
1049 s->deflateParams_out_length = 0;
1050 }
1051#endif
f4c6fd49 1052 while (s->stream.avail_in != 0) {
1053
1054 if (s->stream.avail_out == 0) {
642e522c 1055 /* out of space in the output buffer so make it bigger */
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;
6f5df6bc 1061 s->bufinc *= 2 ;
f4c6fd49 1062 }
642e522c 1063
1064 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
1065 if (RETVAL != Z_OK)
f4c6fd49 1066 break;
1067 }
1068
642e522c 1069 s->last_error = RETVAL ;
1070 if (RETVAL == Z_OK) {
f4c6fd49 1071 SvPOK_only(output);
642e522c 1072 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
f4c6fd49 1073 }
642e522c 1074 OUTPUT:
1075 RETVAL
1076 output
f4c6fd49 1077
1078
f4c6fd49 1079void
642e522c 1080DESTROY(s)
f4c6fd49 1081 Compress::Zlib::deflateStream s
642e522c 1082 CODE:
1083 deflateEnd(&s->stream) ;
1084 if (s->dictionary)
1085 SvREFCNT_dec(s->dictionary) ;
1086#ifndef SETP_BYTE
1087 if (s->deflateParams_out_buffer)
1088 Safefree(s->deflateParams_out_buffer);
1089#endif
1090 Safefree(s) ;
1091
1092
1093DualType
1094flush(s, output, f=Z_FINISH)
1095 Compress::Zlib::deflateStream s
1096 SV * output
1097 int f
1098 uInt cur_length = NO_INIT
1099 uInt increment = NO_INIT
1100 CODE:
f4c6fd49 1101
1102 s->stream.avail_in = 0; /* should be zero already anyway */
1103
642e522c 1104 /* retrieve the output buffer */
1105 output = deRef_l(output, "flush") ;
1106#ifdef UTF8_AVAILABLE
1107 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1108 croak("Wide character in Compress::Zlib::Deflate::flush input parameter");
1109#endif
1110 if(! s->flags & FLAG_APPEND) {
1111 SvCUR_set(output, 0);
1112 /* sv_setpvn(output, "", 0); */
1113 }
1114 cur_length = SvCUR(output) ;
1115 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1116 increment = SvLEN(output) - cur_length;
1117 s->stream.avail_out = increment;
1118#ifdef SETP_BYTE
f4c6fd49 1119 /* Check for saved output from deflateParams */
1120 if (s->deflateParams_out_valid) {
1121 *(s->stream.next_out) = s->deflateParams_out_byte;
1122 ++ s->stream.next_out;
1123 -- s->stream.avail_out ;
1124 s->deflateParams_out_valid = FALSE;
1125 }
642e522c 1126#else
1127 /* Check for saved output from deflateParams */
1128 if (s->deflateParams_out_length) {
1129 uLong plen = s->deflateParams_out_length ;
1130 /* printf("Copy %d bytes saved data\n", plen); */
1131 if (s->stream.avail_out < plen) {
1132 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1133 SvLEN(output) + plen - s->stream.avail_out); */
1134 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1135 }
1136
1137 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1138 cur_length = cur_length + plen;
1139 SvCUR_set(output, cur_length);
1140 s->stream.next_out += plen ;
1141 s->stream.avail_out = SvLEN(output) - cur_length ;
1142 increment = s->stream.avail_out;
1143 s->deflateParams_out_length = 0;
1144 }
1145#endif
f4c6fd49 1146
1147 for (;;) {
1148 if (s->stream.avail_out == 0) {
1149 /* consumed all the available output, so extend it */
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;
6f5df6bc 1155 s->bufinc *= 2 ;
f4c6fd49 1156 }
642e522c 1157 RETVAL = deflate(&(s->stream), f);
f4c6fd49 1158
1159 /* deflate has finished flushing only when it hasn't used up
1160 * all the available space in the output buffer:
1161 */
642e522c 1162 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
f4c6fd49 1163 break;
1164 }
1165
642e522c 1166 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1167 s->last_error = RETVAL ;
f4c6fd49 1168
642e522c 1169 if (RETVAL == Z_OK) {
f4c6fd49 1170 SvPOK_only(output);
642e522c 1171 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
f4c6fd49 1172 }
642e522c 1173 OUTPUT:
1174 RETVAL
1175 output
f4c6fd49 1176
642e522c 1177
1178DualType
f4c6fd49 1179_deflateParams(s, flags, level, strategy, bufsize)
1180 Compress::Zlib::deflateStream s
1181 int flags
1182 int level
1183 int strategy
1184 uLong bufsize
1185 CODE:
642e522c 1186 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1187 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
f4c6fd49 1188 if (flags & 1)
1189 s->Level = level ;
1190 if (flags & 2)
1191 s->Strategy = strategy ;
642e522c 1192 if (flags & 4) {
f4c6fd49 1193 s->bufsize = bufsize;
1194 s->bufinc = bufsize;
1195 }
642e522c 1196 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1197#ifdef SETP_BYTE
f4c6fd49 1198 s->stream.avail_in = 0;
1199 s->stream.next_out = &(s->deflateParams_out_byte) ;
1200 s->stream.avail_out = 1;
1201 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1202 s->deflateParams_out_valid =
1203 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
642e522c 1204 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1205#else
1206 /* printf("Level %d Strategy %d, Prev Len %d\n",
1207 s->Level, s->Strategy, s->deflateParams_out_length); */
1208 s->stream.avail_in = 0;
1209 if (s->deflateParams_out_buffer == NULL)
1210 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1211 s->stream.next_out = s->deflateParams_out_buffer ;
1212 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1213
1214 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1215 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1216 /* printf("RETVAL %d, length out %d, avail %d\n",
1217 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1218#endif
f4c6fd49 1219 OUTPUT:
1220 RETVAL
1221
1222
1223int
1224get_Level(s)
1225 Compress::Zlib::deflateStream s
1226 CODE:
1227 RETVAL = s->Level ;
1228 OUTPUT:
1229 RETVAL
1230
1231int
1232get_Strategy(s)
1233 Compress::Zlib::deflateStream s
1234 CODE:
1235 RETVAL = s->Strategy ;
1236 OUTPUT:
1237 RETVAL
1238
642e522c 1239
1240uLong
1241get_Bufsize(s)
1242 Compress::Zlib::deflateStream s
1243 CODE:
1244 RETVAL = s->bufsize ;
1245 OUTPUT:
1246 RETVAL
f4c6fd49 1247
1248
642e522c 1249int
1250status(s)
1251 Compress::Zlib::deflateStream s
1252 CODE:
1253 RETVAL = s->last_error ;
1254 OUTPUT:
1255 RETVAL
1256
1257uLong
1258crc32(s)
1259 Compress::Zlib::deflateStream s
1260 CODE:
1261 RETVAL = s->crc32 ;
1262 OUTPUT:
1263 RETVAL
1264
f4c6fd49 1265uLong
1266dict_adler(s)
1267 Compress::Zlib::deflateStream s
1268 CODE:
1269 RETVAL = s->dict_adler ;
1270 OUTPUT:
1271 RETVAL
1272
1273uLong
642e522c 1274adler32(s)
1275 Compress::Zlib::deflateStream s
1276 CODE:
1277 RETVAL = s->adler32 ;
1278 OUTPUT:
1279 RETVAL
1280
1281uLong
f4c6fd49 1282total_in(s)
1283 Compress::Zlib::deflateStream s
1284 CODE:
642e522c 1285 RETVAL = s->stream.total_in ;
f4c6fd49 1286 OUTPUT:
1287 RETVAL
1288
1289uLong
1290total_out(s)
1291 Compress::Zlib::deflateStream s
1292 CODE:
642e522c 1293 RETVAL = s->stream.total_out ;
f4c6fd49 1294 OUTPUT:
1295 RETVAL
1296
1297char*
1298msg(s)
1299 Compress::Zlib::deflateStream s
1300 CODE:
642e522c 1301 RETVAL = s->stream.msg;
f4c6fd49 1302 OUTPUT:
1303 RETVAL
1304
642e522c 1305int
1306deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1307 Compress::Zlib::deflateStream s
1308 int good_length
1309 int max_lazy
1310 int nice_length
1311 int max_chain
1312 CODE:
1313#ifndef AT_LEAST_ZLIB_1_2_2_3
1314 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1315 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1316 croak("deflateTune needs zlib 1.2.2.3 or better");
1317#else
1318 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1319#endif
1320 OUTPUT:
1321 RETVAL
1322
f4c6fd49 1323
1324MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
1325
1326void
1327DispStream(s, message=NULL)
642e522c 1328 Compress::Zlib::inflateStream s
1329 char * message
f4c6fd49 1330
642e522c 1331DualType
1332inflateReset(s)
1333 Compress::Zlib::inflateStream s
1334 CODE:
1335 RETVAL = inflateReset(&(s->stream)) ;
1336 if (RETVAL == Z_OK) {
1337 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1338 }
1339 OUTPUT:
1340 RETVAL
1341
1342DualType
1343inflate (s, buf, output)
f4c6fd49 1344 Compress::Zlib::inflateStream s
1345 SV * buf
642e522c 1346 SV * output
6f5df6bc 1347 uInt cur_length = 0;
1348 uInt prefix_length = 0;
1349 uInt increment = 0;
d13b0db4 1350 STRLEN stmp = NO_INIT
642e522c 1351 PREINIT:
1352#ifdef UTF8_AVAILABLE
1353 bool out_utf8 = FALSE;
1354#endif
1355 CODE:
f4c6fd49 1356 /* If the buffer is a reference, dereference it */
1357 buf = deRef(buf, "inflate") ;
642e522c 1358
1359 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
1360 croak("Compress::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified");
1361#ifdef UTF8_AVAILABLE
1362 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1363 croak("Wide character in Compress::Zlib::Inflate::inflate input parameter");
1364#endif
f4c6fd49 1365
1366 /* initialise the input buffer */
d13b0db4 1367 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1368 s->stream.avail_in = SvCUR(buf) ;
f4c6fd49 1369
642e522c 1370 /* and retrieve the output buffer */
1371 output = deRef_l(output, "inflate") ;
1372#ifdef UTF8_AVAILABLE
1373 if (DO_UTF8(output))
1374 out_utf8 = TRUE ;
1375 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1376 croak("Wide character in Compress::Zlib::Inflate::inflate output parameter");
1377#endif
1378 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1379 SvCUR_set(output, 0);
1380 }
6f5df6bc 1381 if (SvLEN(output)) {
1382 prefix_length = cur_length = SvCUR(output) ;
1383 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1384 increment = SvLEN(output) - cur_length - 1;
1385 s->stream.avail_out = increment;
1386 }
1387 else {
1388 s->stream.avail_out = 0;
1389 }
642e522c 1390 s->bytesInflated = 0;
1391
f4c6fd49 1392 while (1) {
1393
1394 if (s->stream.avail_out == 0) {
642e522c 1395 /* out of space in the output buffer so make it bigger */
6f5df6bc 1396 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
642e522c 1397 cur_length += increment ;
1398 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1399 increment = s->bufinc ;
1400 s->stream.avail_out = increment;
6f5df6bc 1401 s->bufinc *= 2 ;
f4c6fd49 1402 }
1403
642e522c 1404 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
f4c6fd49 1405
642e522c 1406
1407 if (RETVAL == Z_BUF_ERROR) {
1408 if (s->stream.avail_out == 0)
1409 continue ;
1410 if (s->stream.avail_in == 0) {
1411 RETVAL = Z_OK ;
1412 break ;
1413 }
1414 }
1415
1416 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1417 s->dict_adler = s->stream.adler ;
1418 RETVAL = inflateSetDictionary(&(s->stream),
1419 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1420 SvCUR(s->dictionary));
1421 }
1422
1423 if (RETVAL != Z_OK)
f4c6fd49 1424 break;
1425 }
1426
642e522c 1427 s->last_error = RETVAL ;
1428 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) {
f4c6fd49 1429 unsigned in ;
642e522c 1430
1431 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
f4c6fd49 1432 SvPOK_only(output);
642e522c 1433 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1434 *SvEND(output) = '\0';
1435#ifdef UTF8_AVAILABLE
1436 if (out_utf8)
1437 sv_utf8_upgrade(output);
1438#endif
1439
1440 if (s->flags & FLAG_CRC32 )
1441 s->crc32 = crc32(s->crc32,
1442 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1443 SvCUR(output)-prefix_length) ;
1444
1445 if (s->flags & FLAG_ADLER32)
1446 s->adler32 = adler32(s->adler32,
1447 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1448 SvCUR(output)-prefix_length) ;
1449
1450 /* fix the input buffer */
1451 if (s->flags & FLAG_CONSUME_INPUT) {
1452 in = s->stream.avail_in ;
1453 SvCUR_set(buf, in) ;
1454 if (in)
1455 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
f4c6fd49 1456 *SvEND(buf) = '\0';
1457 SvSETMAGIC(buf);
1458 }
1459 }
642e522c 1460 OUTPUT:
1461 RETVAL
1462 buf
1463 output
f4c6fd49 1464
642e522c 1465uLong
1466inflateCount(s)
1467 Compress::Zlib::inflateStream s
1468 CODE:
1469 RETVAL = s->bytesInflated;
1470 OUTPUT:
1471 RETVAL
1472
1473
1474DualType
f4c6fd49 1475inflateSync (s, buf)
1476 Compress::Zlib::inflateStream s
1477 SV * buf
1478 CODE:
1479
1480 /* If the buffer is a reference, dereference it */
1481 buf = deRef(buf, "inflateSync") ;
642e522c 1482#ifdef UTF8_AVAILABLE
1483 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1484 croak("Wide character in Compress::Zlib::Inflate::inflateSync");
1485#endif
f4c6fd49 1486
1487 /* initialise the input buffer */
642e522c 1488 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
f4c6fd49 1489 s->stream.avail_in = SvCUR(buf) ;
1490
1491 /* inflateSync doesn't create any output */
1492 s->stream.next_out = (Bytef*) NULL;
1493 s->stream.avail_out = 0;
1494
1495 RETVAL = inflateSync(&(s->stream));
642e522c 1496 s->last_error = RETVAL ;
1497
1498 /* fix the input buffer */
f4c6fd49 1499 {
f4c6fd49 1500 unsigned in = s->stream.avail_in ;
f4c6fd49 1501 SvCUR_set(buf, in) ;
1502 if (in)
642e522c 1503 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
f4c6fd49 1504 *SvEND(buf) = '\0';
1505 SvSETMAGIC(buf);
1506 }
1507 OUTPUT:
1508 RETVAL
642e522c 1509 buf
f4c6fd49 1510
1511void
1512DESTROY(s)
1513 Compress::Zlib::inflateStream s
1514 CODE:
1515 inflateEnd(&s->stream) ;
1516 if (s->dictionary)
1517 SvREFCNT_dec(s->dictionary) ;
642e522c 1518#ifndef SETP_BYTE
1519 if (s->deflateParams_out_buffer)
1520 Safefree(s->deflateParams_out_buffer);
1521#endif
1522#ifdef MAGIC_APPEND
1523 if (s->window)
1524 Safefree(s->window);
1525#endif
f4c6fd49 1526 Safefree(s) ;
1527
1528
1529uLong
642e522c 1530status(s)
1531 Compress::Zlib::inflateStream s
1532 CODE:
1533 RETVAL = s->last_error ;
1534 OUTPUT:
1535 RETVAL
1536
1537uLong
1538crc32(s)
1539 Compress::Zlib::inflateStream s
1540 CODE:
1541 RETVAL = s->crc32 ;
1542 OUTPUT:
1543 RETVAL
1544
1545uLong
f4c6fd49 1546dict_adler(s)
1547 Compress::Zlib::inflateStream s
1548 CODE:
1549 RETVAL = s->dict_adler ;
1550 OUTPUT:
1551 RETVAL
1552
1553uLong
1554total_in(s)
1555 Compress::Zlib::inflateStream s
1556 CODE:
642e522c 1557 RETVAL = s->stream.total_in ;
1558 OUTPUT:
1559 RETVAL
1560
1561uLong
1562adler32(s)
1563 Compress::Zlib::inflateStream s
1564 CODE:
1565 RETVAL = s->adler32 ;
f4c6fd49 1566 OUTPUT:
1567 RETVAL
1568
1569uLong
1570total_out(s)
1571 Compress::Zlib::inflateStream s
1572 CODE:
642e522c 1573 RETVAL = s->stream.total_out ;
f4c6fd49 1574 OUTPUT:
1575 RETVAL
1576
1577char*
1578msg(s)
1579 Compress::Zlib::inflateStream s
1580 CODE:
642e522c 1581 RETVAL = s->stream.msg;
f4c6fd49 1582 OUTPUT:
1583 RETVAL
1584
1585
642e522c 1586uLong
1587get_Bufsize(s)
1588 Compress::Zlib::inflateStream s
1589 CODE:
1590 RETVAL = s->bufsize ;
1591 OUTPUT:
1592 RETVAL
1593
1594bool
1595set_Append(s, mode)
1596 Compress::Zlib::inflateStream s
1597 bool mode
1598 CODE:
1599 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1600 if (mode)
1601 s->flags |= FLAG_APPEND ;
1602 else
1603 s->flags &= ~FLAG_APPEND ;
1604 OUTPUT:
1605 RETVAL
1606
1607MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateScanStream
1608
1609void
1610DESTROY(s)
1611 Compress::Zlib::inflateScanStream s
1612 CODE:
1613 inflateEnd(&s->stream) ;
1614 if (s->dictionary)
1615 SvREFCNT_dec(s->dictionary) ;
1616#ifndef SETP_BYTE
1617 if (s->deflateParams_out_buffer)
1618 Safefree(s->deflateParams_out_buffer);
1619#endif
1620#ifdef MAGIC_APPEND
1621 if (s->window)
1622 Safefree(s->window);
1623#endif
1624 Safefree(s) ;
1625
1626void
1627DispStream(s, message=NULL)
1628 Compress::Zlib::inflateScanStream s
1629 char * message
1630
1631DualType
1632scan(s, buf, out=NULL)
1633 Compress::Zlib::inflateScanStream s
1634 SV * buf
1635 SV * out
1636 int start_len = NO_INIT
d13b0db4 1637 STRLEN stmp = NO_INIT
642e522c 1638 ALIAS:
1639 inflate = 1
1640 CODE:
1641 /* If the input buffer is a reference, dereference it */
1642 ix = ix ; /* warning suppression */
1643#ifndef MAGIC_APPEND
1644 buf = buf;
1645 croak("scan needs zlib 1.2.1 or better");
1646#else
1647 buf = deRef(buf, "inflateScan") ;
1648#ifdef UTF8_AVAILABLE
1649 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1650 croak("Wide character in Compress::Zlib::InflateScan::scan input parameter");
1651#endif
1652
1653 /* initialise the input buffer */
d13b0db4 1654 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1655 s->stream.avail_in = SvCUR(buf) ;
642e522c 1656 start_len = s->stream.avail_in ;
1657 s->bytesInflated = 0 ;
1658 do
1659 {
1660 if (s->stream.avail_in == 0) {
1661 RETVAL = Z_OK ;
1662 break ;
1663 }
1664
1665 /* set up output to next available section of sliding window */
1666 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1667 s->stream.next_out = s->window + s->window_have;
1668
1669 /* DispStream(s, "before inflate\n"); */
1670
1671 /* inflate and check for errors */
1672 RETVAL = inflate(&(s->stream), Z_BLOCK);
1673
1674
1675 if (start_len > 1)
1676 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1677
1678 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1679 RETVAL == Z_DATA_ERROR )
1680 break ;
1681
1682 if (s->flags & FLAG_CRC32 )
1683 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1684 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1685
1686 if (s->flags & FLAG_ADLER32)
1687 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1688 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1689
1690 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1691
1692 if (s->stream.avail_out)
1693 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1694 else {
1695 s->window_have = 0;
1696 s->window_full = 1;
1697 }
1698
1699 /* process end of block */
1700 if (s->stream.data_type & 128) {
1701 if (s->stream.data_type & 64) {
1702 s->window_left = s->stream.data_type & 0x1f;
1703 }
1704 else {
1705 s->window_lastbit = s->stream.data_type & 0x1f;
1706 s->lastBlockOffset = s->stream.total_in;
1707 }
1708 }
1709
1710 } while (RETVAL != Z_STREAM_END);
1711
1712 s->last_error = RETVAL ;
1713 s->window_lastoff = s->stream.total_in ;
1714
1715 if (RETVAL == Z_STREAM_END)
1716 {
1717 s->matchedEndBlock = 1 ;
1718
1719 /* save the location of the end of the compressed data */
1720 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1721 s->window_endOffset = s->stream.total_in ;
1722 if (s->window_left)
1723 {
1724 -- s->window_endOffset ;
1725 }
1726
1727 /* if window wrapped, build dictionary from window by rotating */
1728 if (s->window_full) {
1729 rotate(s->window, WINDOW_SIZE, s->window_have);
1730 s->window_have = WINDOW_SIZE;
1731 }
1732
1733 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1734 if (1) {
1735 unsigned in = s->stream.avail_in ;
1736 SvCUR_set(buf, in) ;
1737 if (in)
1738 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1739 *SvEND(buf) = '\0';
1740 SvSETMAGIC(buf);
1741 }
1742 }
1743#endif
1744 OUTPUT:
1745 RETVAL
1746
1747
1748uLong
1749getEndOffset(s)
1750 Compress::Zlib::inflateScanStream s
1751 CODE:
1752#ifndef MAGIC_APPEND
1753 croak("getEndOffset needs zlib 1.2.1 or better");
1754#else
1755 RETVAL = s->window_endOffset;
1756#endif
1757 OUTPUT:
1758 RETVAL
1759
1760uLong
1761inflateCount(s)
1762 Compress::Zlib::inflateScanStream s
1763 CODE:
1764#ifndef MAGIC_APPEND
1765 croak("inflateCount needs zlib 1.2.1 or better");
1766#else
1767 RETVAL = s->bytesInflated;
1768#endif
1769 OUTPUT:
1770 RETVAL
1771
1772
1773uLong
1774getLastBlockOffset(s)
1775 Compress::Zlib::inflateScanStream s
1776 CODE:
1777#ifndef MAGIC_APPEND
1778 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1779#else
1780 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1781#endif
1782 OUTPUT:
1783 RETVAL
1784
1785uLong
1786getLastBufferOffset(s)
1787 Compress::Zlib::inflateScanStream s
1788 CODE:
1789#ifndef MAGIC_APPEND
1790 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1791#else
1792 RETVAL = s->window_lastoff;
1793#endif
1794 OUTPUT:
1795 RETVAL
1796
1797void
1798resetLastBlockByte(s, byte)
1799 Compress::Zlib::inflateScanStream s
1800 unsigned char* byte
1801 CODE:
1802#ifndef MAGIC_APPEND
1803 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1804#else
1805 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
1806#endif
1807
1808
1809void
1810_createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1811 Compress::Zlib::inflateScanStream inf_s
1812 int flags
1813 int level
1814 int method
1815 int windowBits
1816 int memLevel
1817 int strategy
1818 uLong bufsize
1819 PPCODE:
1820 {
1821#ifndef MAGIC_APPEND
1822 flags = flags;
1823 level = level ;
1824 method = method;
1825 windowBits = windowBits;
1826 memLevel = memLevel;
1827 strategy = strategy;
1828 bufsize= bufsize;
1829 croak("_createDeflateStream needs zlib 1.2.1 or better");
1830#else
1831 int err ;
1832 deflateStream s ;
1833
1834 if (trace)
1835 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1836 level, method, windowBits, memLevel, strategy, bufsize) ;
1837 if ((s = InitStream() )) {
1838
1839 s->Level = level;
1840 s->Method = method;
1841 s->WindowBits = windowBits;
1842 s->MemLevel = memLevel;
1843 s->Strategy = strategy;
1844
1845 err = deflateInit2(&(s->stream), level,
1846 method, windowBits, memLevel, strategy);
1847
1848 if (err == Z_OK) {
1849 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1850 s->dict_adler = s->stream.adler ;
1851 }
1852
1853 if (err != Z_OK) {
1854 Safefree(s) ;
1855 s = NULL ;
1856 }
1857 else {
1858 PostInitStream(s, flags, bufsize, windowBits) ;
1859 s->crc32 = inf_s->crc32;
1860 s->adler32 = inf_s->adler32;
1861 s->stream.adler = inf_s->stream.adler ;
1862 /* s->stream.total_out = inf_s->bytesInflated ; */
1863 s->stream.total_in = inf_s->stream.total_out ;
1864 if (inf_s->window_left) {
1865 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1866 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1867 }
1868 }
1869 }
1870 else
1871 err = Z_MEM_ERROR ;
1872
1873 XPUSHs(sv_setref_pv(sv_newmortal(),
1874 "Compress::Zlib::deflateStream", (void*)s));
1875 if (GIMME == G_ARRAY) {
1876 SV * sv = sv_2mortal(newSViv(err)) ;
1877 setDUALstatus(sv, err);
1878 XPUSHs(sv) ;
1879 }
1880#endif
1881 }
1882
1883DualType
1884status(s)
1885 Compress::Zlib::inflateScanStream s
1886 CODE:
1887 RETVAL = s->last_error ;
1888 OUTPUT:
1889 RETVAL
1890
1891uLong
1892crc32(s)
1893 Compress::Zlib::inflateScanStream s
1894 CODE:
1895 RETVAL = s->crc32 ;
1896 OUTPUT:
1897 RETVAL
1898
1899
1900uLong
1901adler32(s)
1902 Compress::Zlib::inflateScanStream s
1903 CODE:
1904 RETVAL = s->adler32 ;
1905 OUTPUT:
1906 RETVAL
1907