2 * Author : Paul Marquess, <pmqs@cpan.org>
3 * Created : 22nd January 1996
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.
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
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
22 /* gzappend -- command to append to a gzip file
24 Copyright (C) 2003 Mark Adler, all rights reserved
25 version 1.1, 4 Nov 2003
36 /* zlib prior to 1.06 doesn't know about z_off_t */
41 #if ! defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200
42 # define NEED_DUMMY_BYTE_AT_END
45 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1210
49 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221
50 # define AT_LEAST_ZLIB_1_2_2_1
53 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223
54 # define AT_LEAST_ZLIB_1_2_2_3
57 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
58 # define AT_LEAST_ZLIB_1_2_3
68 # include "patchlevel.h"
69 # define PERL_REVISION 5
70 # define PERL_VERSION PATCHLEVEL
71 # define PERL_SUBVERSION SUBVERSION
74 # if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
76 # define PL_sv_undef sv_undef
78 # define PL_curcop curcop
79 # define PL_compiling compiling
84 # define newSVuv newSViv
89 # if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
91 # ifdef SvPVbyte_force
92 # undef SvPVbyte_force
95 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
99 # ifndef SvPVbyte_nolen
100 # define SvPVbyte_nolen SvPV_nolen
104 # define SvPVbyte SvPV
113 # define sv_2pv_nolen(a) my_sv_2pv_nolen(a)
116 my_sv_2pv_nolen(register SV *sv)
120 return sv_2pv(sv, &n_a);
124 /* SvPV_nolen depends on sv_2pv_nolen */
125 # define SvPV_nolen(sv) \
126 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
127 ? SvPVX(sv) : sv_2pv_nolen(sv))
133 # define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
138 # ifndef SvPVbyte_nolen
139 # define SvPVbyte_nolen SvPV_nolen
142 # ifndef SvPVbyte_force
143 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
146 #if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
147 # define UTF8_AVAILABLE
150 typedef int DualType ;
151 typedef int int_undef ;
153 typedef struct di_stream {
155 #define FLAG_APPEND 1
157 #define FLAG_ADLER32 4
158 #define FLAG_CONSUME_INPUT 8
170 bool deflateParams_out_valid ;
171 Bytef deflateParams_out_byte;
173 #define deflateParams_BUFFER_SIZE 0x4000
174 uLong deflateParams_out_length;
175 Bytef* deflateParams_out_buffer;
182 uLong bytesInflated ;
183 uLong compressedBytes ;
184 uLong uncompressedBytes ;
187 #define WINDOW_SIZE 32768U
189 bool matchedEndBlock;
191 int window_lastbit, window_left, window_full;
192 unsigned window_have;
193 off_t window_lastoff, window_end;
194 off_t window_endOffset;
196 uLong lastBlockOffset ;
197 unsigned char window_lastByte ;
203 typedef di_stream * deflateStream ;
204 typedef di_stream * Compress__Zlib__deflateStream ;
205 typedef di_stream * inflateStream ;
206 typedef di_stream * Compress__Zlib__inflateStream ;
207 typedef di_stream * Compress__Zlib__inflateScanStream ;
209 #define GZERRNO "Compress::Zlib::gzerrno"
211 #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
214 /* Figure out the Operating System */
216 # define OS_CODE 0x00
219 #if defined(AMIGA) || defined(AMIGAOS)
220 # define OS_CODE 0x01
223 #if defined(VAXC) || defined(VMS)
224 # define OS_CODE 0x02
228 # define OS_CODE 0x04
231 #if defined(ATARI) || defined(atarist)
232 # define OS_CODE 0x05
236 # define OS_CODE 0x06
239 #if defined(MACOS) || defined(TARGET_OS_MAC)
240 # define OS_CODE 0x07
244 # define OS_CODE 0x08
248 # define OS_CODE 0x09
252 # define OS_CODE 0x0a
255 #ifdef WIN32 /* Window 95 & Windows NT */
256 # define OS_CODE 0x0b
260 # define OS_CODE 0x0c
263 #if 0 /* Acorn RISCOS */
264 # define OS_CODE 0x0d
268 # define OS_CODE 0x0e
271 #ifdef __50SERIES /* Prime/PRIMOS */
272 # define OS_CODE 0x0F
275 /* Default to UNIX */
277 # define OS_CODE 0x03 /* assume Unix */
281 # define GZIP_OS_CODE OS_CODE
284 #define adlerInitial adler32(0L, Z_NULL, 0)
285 #define crcInitial crc32(0L, Z_NULL, 0)
288 static const char * const my_z_errmsg[] = {
289 "need dictionary", /* Z_NEED_DICT 2 */
290 "stream end", /* Z_STREAM_END 1 */
292 "file error", /* Z_ERRNO (-1) */
293 "stream error", /* Z_STREAM_ERROR (-2) */
294 "data error", /* Z_DATA_ERROR (-3) */
295 "insufficient memory", /* Z_MEM_ERROR (-4) */
296 "buffer error", /* Z_BUF_ERROR (-5) */
297 "incompatible version",/* Z_VERSION_ERROR(-6) */
300 #define setDUALstatus(var, err) \
301 sv_setnv(var, (double)err) ; \
302 sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \
306 #if defined(__SYMBIAN32__)
307 # define NO_WRITEABLE_DATA
310 #define TRACE_DEFAULT 0
312 #ifdef NO_WRITEABLE_DATA
313 # define trace TRACE_DEFAULT
315 static int trace = TRACE_DEFAULT ;
318 /* Dodge PerlIO hiding of these functions. */
323 GetErrorString(int error_no)
325 GetErrorString(error_no)
332 if (error_no == Z_ERRNO) {
333 errstr = Strerror(errno) ;
336 /* errstr = gzerror(fil, &error_no) ; */
337 errstr = (char*) my_z_errmsg[2 - error_no];
345 SetGzErrorNo(int error_no)
347 SetGzErrorNo(error_no)
353 SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ;
355 if (error_no == Z_ERRNO) {
357 errstr = Strerror(errno) ;
360 /* errstr = gzerror(fil, &error_no) ; */
361 errstr = (char*) my_z_errmsg[2 - error_no];
363 if (SvIV(gzerror_sv) != error_no) {
364 sv_setiv(gzerror_sv, error_no) ;
365 sv_setpv(gzerror_sv, errstr) ;
366 SvIOK_on(gzerror_sv) ;
374 SetGzError(gzFile file)
382 (void)gzerror(file, &error_no) ;
383 SetGzErrorNo(error_no) ;
391 The following two functions are taken almost directly from
392 examples/gzappend.c. Only cosmetic changes have been made to conform to
393 the coding style of the rest of the code in this file.
397 /* return the greatest common divisor of a and b using Euclid's algorithm,
398 modified to be fast when one argument much greater than the other, and
399 coded to avoid unnecessary swapping */
402 gcd(unsigned a, unsigned b)
427 /* rotate list[0..len-1] left by rot positions, in place */
430 rotate(unsigned char *list, unsigned len, unsigned rot)
432 rotate(list, len, rot)
440 unsigned char *start, *last, *to, *from;
442 /* normalize rot and handle degenerate cases */
444 if (rot >= len) rot %= len;
445 if (rot == 0) return;
447 /* pointer to last entry in list */
448 last = list + (len - 1);
450 /* do simple left shift by one */
453 memcpy(list, list + 1, len - 1);
458 /* do simple right shift by one */
459 if (rot == len - 1) {
461 memmove(list + 1, list, len - 1);
466 /* otherwise do rotate as a set of cycles in place */
467 cycles = gcd(len, rot); /* number of cycles */
469 start = from = list + cycles; /* start index is arbitrary */
470 tmp = *from; /* save entry to be overwritten */
472 to = from; /* next step in cycle */
473 from += rot; /* go right rot positions */
474 if (from > last) from -= len; /* (pointer better not wrap) */
475 if (from == start) break; /* all but one shifted */
476 *to = *from; /* shift left */
478 *to = tmp; /* complete the circle */
482 #endif /* MAGIC_APPEND */
486 DispHex(void * ptr, int length)
493 char * p = (char*)ptr;
495 for (i = 0; i < length; ++i) {
496 printf(" %02x", 0xFF & *(p+i));
503 DispStream(di_stream * s, char * message)
505 DispStream(s, message)
516 #define EnDis(f) (s->flags & f ? "Enabled" : "Disabled")
518 printf("DispStream 0x%p", s) ;
520 printf("- %s \n", message) ;
524 printf(" stream pointer is NULL\n");
527 printf(" stream 0x%p\n", &(s->stream));
528 printf(" zalloc 0x%p\n", s->stream.zalloc);
529 printf(" zfree 0x%p\n", s->stream.zfree);
530 printf(" opaque 0x%p\n", s->stream.opaque);
532 printf(" msg %s\n", s->stream.msg);
535 printf(" next_in 0x%p", s->stream.next_in);
536 if (s->stream.next_in){
538 DispHex(s->stream.next_in, 4);
542 printf(" next_out 0x%p", s->stream.next_out);
543 if (s->stream.next_out){
545 DispHex(s->stream.next_out, 4);
549 printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in);
550 printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out);
551 printf(" total_in %ld\n", s->stream.total_in);
552 printf(" total_out %ld\n", s->stream.total_out);
553 printf(" adler %ld\n", s->stream.adler );
554 printf(" bufsize %ld\n", s->bufsize);
555 printf(" dictionary 0x%p\n", s->dictionary);
556 printf(" dict_adler 0x%ld\n",s->dict_adler);
557 printf(" zip_mode %d\n", s->zip_mode);
558 printf(" crc32 0x%x\n", (unsigned)s->crc32);
559 printf(" adler32 0x%x\n", (unsigned)s->adler32);
560 printf(" flags 0x%x\n", s->flags);
561 printf(" APPEND %s\n", EnDis(FLAG_APPEND));
562 printf(" CRC32 %s\n", EnDis(FLAG_CRC32));
563 printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32));
564 printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT));
567 printf(" window 0x%p\n", s->window);
583 ZMALLOC(s, di_stream) ;
591 PostInitStream(di_stream * s, int flags, int bufsize, int windowBits)
593 PostInitStream(s, flags, bufsize, windowBits)
600 s->bufsize = bufsize ;
601 s->bufinc = bufsize ;
603 s->uncompressedBytes =
606 s->zip_mode = (windowBits < 0) ;
607 if (flags & FLAG_CRC32)
608 s->crc32 = crcInitial ;
609 if (flags & FLAG_ADLER32)
610 s->adler32 = adlerInitial ;
616 deRef(SV * sv, char * string)
633 croak("%s: buffer parameter is not a SCALAR reference", string);
636 croak("%s: buffer parameter is a reference to a reference", string) ;
648 deRef_l(SV * sv, char * string)
670 croak("%s: buffer parameter is not a SCALAR reference", string);
673 croak("%s: buffer parameter is a reference to a reference", string) ;
676 if (SvREADONLY(sv) && PL_curcop != &PL_compiling)
677 croak("%s: buffer parameter is read-only", string);
679 SvUPGRADE(sv, SVt_PV);
691 #include "constants.h"
693 MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
698 INCLUDE: constants.xs
701 /* Check this version of zlib is == 1 */
702 if (zlibVersion()[0] != '1')
703 croak("Compress::Zlib needs zlib version 1.x\n") ;
706 /* Create the $os_code scalar */
707 SV * os_code_sv = perl_get_sv("Compress::Zlib::gzip_os_code", GV_ADDMULTI) ;
708 sv_setiv(os_code_sv, GZIP_OS_CODE) ;
712 /* Create the $gzerror scalar */
713 SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ;
714 sv_setiv(gzerror_sv, 0) ;
715 sv_setpv(gzerror_sv, "") ;
716 SvIOK_on(gzerror_sv) ;
719 #define Zip_zlib_version() (char*)zlib_version
727 RETVAL = ZLIB_VERNUM ;
729 /* 1.1.4 => 0x1140 */
730 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
731 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
732 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
737 MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
739 #define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
742 Zip_adler32(buf, adler=adlerInitial)
743 uLong adler = NO_INIT
745 Bytef * buf = NO_INIT
748 /* If the buffer is a reference, dereference it */
749 sv = deRef(sv, "adler32") ;
750 #ifdef UTF8_AVAILABLE
751 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
752 croak("Wide character in Compress::Zlib::adler32");
754 buf = (Byte*)SvPVbyte(sv, len) ;
757 adler = adlerInitial;
758 else if (SvOK(ST(1)))
759 adler = SvUV(ST(1)) ;
761 adler = adlerInitial;
763 #define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
766 Zip_crc32(buf, crc=crcInitial)
769 Bytef * buf = NO_INIT
772 /* If the buffer is a reference, dereference it */
773 sv = deRef(sv, "crc32") ;
774 #ifdef UTF8_AVAILABLE
775 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
776 croak("Wide character in Compress::Zlib::crc32");
778 buf = (Byte*)SvPVbyte(sv, len) ;
782 else if (SvOK(ST(1)))
789 crc32_combine(crc1, crc2, len2)
794 #ifndef AT_LEAST_ZLIB_1_2_2_1
795 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
796 croak("crc32_combine needs zlib 1.2.3 or better");
798 RETVAL = crc32_combine(crc1, crc2, len2);
805 adler32_combine(adler1, adler2, len2)
810 #ifndef AT_LEAST_ZLIB_1_2_2_1
811 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
812 croak("adler32_combine needs zlib 1.2.3 or better");
814 RETVAL = adler32_combine(adler1, adler2, len2);
820 MODULE = Compress::Zlib PACKAGE = Compress::Zlib
823 _deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
837 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld\n",
838 level, method, windowBits, memLevel, strategy, bufsize) ;
839 if ((s = InitStream() )) {
843 s->WindowBits = windowBits;
844 s->MemLevel = memLevel;
845 s->Strategy = strategy;
847 err = deflateInit2(&(s->stream), level,
848 method, windowBits, memLevel, strategy);
850 /* Check if a dictionary has been specified */
852 if (err == Z_OK && SvCUR(dictionary)) {
853 #ifdef UTF8_AVAILABLE
854 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
855 croak("Wide character in Compress::Zlib::Deflate::new dicrionary parameter");
857 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
859 s->dict_adler = s->stream.adler ;
867 PostInitStream(s, flags, bufsize, windowBits) ;
873 XPUSHs(sv_setref_pv(sv_newmortal(),
874 "Compress::Zlib::deflateStream", (void*)s));
875 if (GIMME == G_ARRAY) {
876 SV * sv = sv_2mortal(newSViv(err)) ;
877 setDUALstatus(sv, err);
882 _inflateInit(flags, windowBits, bufsize, dictionary)
895 croak("inflateScanInit needs zlib 1.2.1 or better");
898 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
899 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
900 if ((s = InitStream() )) {
902 s->WindowBits = windowBits;
904 err = inflateInit2(&(s->stream), windowBits);
909 else if (SvCUR(dictionary)) {
910 /* Dictionary specified - take a copy for use in inflate */
911 s->dictionary = newSVsv(dictionary) ;
914 PostInitStream(s, flags, bufsize, windowBits) ;
918 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
926 XPUSHs(sv_setref_pv(sv_newmortal(),
928 ? "Compress::Zlib::inflateScanStream"
929 : "Compress::Zlib::inflateStream",
931 if (GIMME == G_ARRAY) {
932 SV * sv = sv_2mortal(newSViv(err)) ;
933 setDUALstatus(sv, err);
939 MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
942 DispStream(s, message=NULL)
943 Compress::Zlib::deflateStream s
948 Compress::Zlib::deflateStream s
950 RETVAL = deflateReset(&(s->stream)) ;
951 if (RETVAL == Z_OK) {
952 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
958 deflate (s, buf, output)
959 Compress::Zlib::deflateStream s
962 uInt cur_length = NO_INIT
963 uInt increment = NO_INIT
964 uInt prefix = NO_INIT
968 /* If the input buffer is a reference, dereference it */
969 buf = deRef(buf, "deflate") ;
971 /* initialise the input buffer */
972 #ifdef UTF8_AVAILABLE
973 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
974 croak("Wide character in Compress::Zlib::Deflate::deflate input parameter");
976 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
977 s->stream.avail_in = SvCUR(buf) ;
979 if (s->flags & FLAG_CRC32)
980 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
982 if (s->flags & FLAG_ADLER32)
983 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
985 /* and retrieve the output buffer */
986 output = deRef_l(output, "deflate") ;
987 #ifdef UTF8_AVAILABLE
988 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
989 croak("Wide character in Compress::Zlib::Deflate::deflate output parameter");
992 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
993 SvCUR_set(output, 0);
994 /* sv_setpvn(output, "", 0); */
996 prefix = cur_length = SvCUR(output) ;
997 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
998 increment = SvLEN(output) - cur_length;
999 s->stream.avail_out = increment;
1001 /* Check for saved output from deflateParams */
1002 if (s->deflateParams_out_valid) {
1003 *(s->stream.next_out) = s->deflateParams_out_byte;
1004 ++ s->stream.next_out;
1005 -- s->stream.avail_out ;
1006 s->deflateParams_out_valid = FALSE;
1009 /* Check for saved output from deflateParams */
1010 if (s->deflateParams_out_length) {
1011 uLong plen = s->deflateParams_out_length ;
1012 /* printf("Copy %d bytes saved data\n", plen);*/
1013 if (s->stream.avail_out < plen) {
1014 /*printf("GROW from %d to %d\n", s->stream.avail_out,
1015 SvLEN(output) + plen - s->stream.avail_out); */
1016 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1019 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1020 cur_length = cur_length + plen;
1021 SvCUR_set(output, cur_length);
1022 s->stream.next_out += plen ;
1023 s->stream.avail_out = SvLEN(output) - cur_length ;
1024 increment = s->stream.avail_out;
1025 s->deflateParams_out_length = 0;
1028 while (s->stream.avail_in != 0) {
1030 if (s->stream.avail_out == 0) {
1031 /* out of space in the output buffer so make it bigger */
1032 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1033 cur_length += increment ;
1034 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1035 increment = s->bufinc ;
1036 s->stream.avail_out = increment;
1040 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
1045 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1046 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ;
1048 s->last_error = RETVAL ;
1049 if (RETVAL == Z_OK) {
1051 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
1060 Compress::Zlib::deflateStream s
1062 deflateEnd(&s->stream) ;
1064 SvREFCNT_dec(s->dictionary) ;
1066 if (s->deflateParams_out_buffer)
1067 Safefree(s->deflateParams_out_buffer);
1073 flush(s, output, f=Z_FINISH)
1074 Compress::Zlib::deflateStream s
1077 uInt cur_length = NO_INIT
1078 uInt increment = NO_INIT
1079 uInt prefix = NO_INIT
1082 s->stream.avail_in = 0; /* should be zero already anyway */
1084 /* retrieve the output buffer */
1085 output = deRef_l(output, "flush") ;
1086 #ifdef UTF8_AVAILABLE
1087 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1088 croak("Wide character in Compress::Zlib::Deflate::flush input parameter");
1090 if(! s->flags & FLAG_APPEND) {
1091 SvCUR_set(output, 0);
1092 /* sv_setpvn(output, "", 0); */
1094 prefix = cur_length = SvCUR(output) ;
1095 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1096 increment = SvLEN(output) - cur_length;
1097 s->stream.avail_out = increment;
1099 /* Check for saved output from deflateParams */
1100 if (s->deflateParams_out_valid) {
1101 *(s->stream.next_out) = s->deflateParams_out_byte;
1102 ++ s->stream.next_out;
1103 -- s->stream.avail_out ;
1104 s->deflateParams_out_valid = FALSE;
1107 /* Check for saved output from deflateParams */
1108 if (s->deflateParams_out_length) {
1109 uLong plen = s->deflateParams_out_length ;
1110 /* printf("Copy %d bytes saved data\n", plen); */
1111 if (s->stream.avail_out < plen) {
1112 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1113 SvLEN(output) + plen - s->stream.avail_out); */
1114 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1117 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1118 cur_length = cur_length + plen;
1119 SvCUR_set(output, cur_length);
1120 s->stream.next_out += plen ;
1121 s->stream.avail_out = SvLEN(output) - cur_length ;
1122 increment = s->stream.avail_out;
1123 s->deflateParams_out_length = 0;
1128 if (s->stream.avail_out == 0) {
1129 /* consumed all the available output, so extend it */
1130 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1131 cur_length += increment ;
1132 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1133 increment = s->bufinc ;
1134 s->stream.avail_out = increment;
1137 RETVAL = deflate(&(s->stream), f);
1139 /* deflate has finished flushing only when it hasn't used up
1140 * all the available space in the output buffer:
1142 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
1146 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1147 s->last_error = RETVAL ;
1149 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1151 if (RETVAL == Z_OK) {
1153 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
1161 _deflateParams(s, flags, level, strategy, bufsize)
1162 Compress::Zlib::deflateStream s
1168 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1169 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
1173 s->Strategy = strategy ;
1175 s->bufsize = bufsize;
1176 s->bufinc = bufsize;
1178 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1180 s->stream.avail_in = 0;
1181 s->stream.next_out = &(s->deflateParams_out_byte) ;
1182 s->stream.avail_out = 1;
1183 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1184 s->deflateParams_out_valid =
1185 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
1186 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1188 /* printf("Level %d Strategy %d, Prev Len %d\n",
1189 s->Level, s->Strategy, s->deflateParams_out_length); */
1190 s->stream.avail_in = 0;
1191 if (s->deflateParams_out_buffer == NULL)
1192 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1193 s->stream.next_out = s->deflateParams_out_buffer ;
1194 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1196 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1197 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1198 /* printf("RETVAL %d, length out %d, avail %d\n",
1199 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1207 Compress::Zlib::deflateStream s
1215 Compress::Zlib::deflateStream s
1217 RETVAL = s->Strategy ;
1224 Compress::Zlib::deflateStream s
1226 RETVAL = s->bufsize ;
1233 Compress::Zlib::deflateStream s
1235 RETVAL = s->last_error ;
1241 Compress::Zlib::deflateStream s
1249 Compress::Zlib::deflateStream s
1251 RETVAL = s->dict_adler ;
1257 Compress::Zlib::deflateStream s
1259 RETVAL = s->adler32 ;
1265 Compress::Zlib::deflateStream s
1267 RETVAL = s->compressedBytes;
1272 uncompressedBytes(s)
1273 Compress::Zlib::deflateStream s
1275 RETVAL = s->uncompressedBytes;
1281 Compress::Zlib::deflateStream s
1283 RETVAL = s->stream.total_in ;
1289 Compress::Zlib::deflateStream s
1291 RETVAL = s->stream.total_out ;
1297 Compress::Zlib::deflateStream s
1299 RETVAL = s->stream.msg;
1304 deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1305 Compress::Zlib::deflateStream s
1311 #ifndef AT_LEAST_ZLIB_1_2_2_3
1312 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1313 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1314 croak("deflateTune needs zlib 1.2.2.3 or better");
1316 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1322 MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
1325 DispStream(s, message=NULL)
1326 Compress::Zlib::inflateStream s
1331 Compress::Zlib::inflateStream s
1333 RETVAL = inflateReset(&(s->stream)) ;
1334 if (RETVAL == Z_OK) {
1335 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1341 inflate (s, buf, output, eof=FALSE)
1342 Compress::Zlib::inflateStream s
1346 uInt cur_length = 0;
1347 uInt prefix_length = 0;
1349 STRLEN stmp = NO_INIT
1351 #ifdef UTF8_AVAILABLE
1352 bool out_utf8 = FALSE;
1355 /* If the buffer is a reference, dereference it */
1356 buf = deRef(buf, "inflate") ;
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");
1365 /* initialise the input buffer */
1366 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1367 s->stream.avail_in = SvCUR(buf) ;
1369 /* and retrieve the output buffer */
1370 output = deRef_l(output, "inflate") ;
1371 #ifdef UTF8_AVAILABLE
1372 if (DO_UTF8(output))
1374 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1375 croak("Wide character in Compress::Zlib::Inflate::inflate output parameter");
1377 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1378 SvCUR_set(output, 0);
1380 if (SvLEN(output)) {
1381 prefix_length = cur_length = SvCUR(output) ;
1382 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1383 increment = SvLEN(output) - cur_length - 1;
1384 s->stream.avail_out = increment;
1387 s->stream.avail_out = 0;
1389 s->bytesInflated = 0;
1393 if (s->stream.avail_out == 0) {
1394 /* out of space in the output buffer so make it bigger */
1395 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1396 cur_length += increment ;
1397 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1398 increment = s->bufinc ;
1399 s->stream.avail_out = increment;
1403 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1405 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1406 RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END )
1409 if (RETVAL == Z_BUF_ERROR) {
1410 if (s->stream.avail_out == 0)
1412 if (s->stream.avail_in == 0) {
1418 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1419 s->dict_adler = s->stream.adler ;
1420 RETVAL = inflateSetDictionary(&(s->stream),
1421 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1422 SvCUR(s->dictionary));
1428 #ifdef NEED_DUMMY_BYTE_AT_END
1429 if (eof && RETVAL == Z_OK) {
1430 Bytef* nextIn = s->stream.next_in;
1431 uInt availIn = s->stream.avail_in;
1432 s->stream.next_in = (Bytef*) " ";
1433 s->stream.avail_in = 1;
1434 if (s->stream.avail_out == 0) {
1435 /* out of space in the output buffer so make it bigger */
1436 Sv_Grow(output, SvLEN(output) + s->bufinc) ;
1437 cur_length += increment ;
1438 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1439 increment = s->bufinc ;
1440 s->stream.avail_out = increment;
1443 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1444 s->stream.next_in = nextIn ;
1445 s->stream.avail_in = availIn ;
1449 s->last_error = RETVAL ;
1450 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) {
1453 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
1454 s->uncompressedBytes += s->bytesInflated ;
1455 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1458 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1459 *SvEND(output) = '\0';
1460 #ifdef UTF8_AVAILABLE
1462 sv_utf8_upgrade(output);
1465 if (s->flags & FLAG_CRC32 )
1466 s->crc32 = crc32(s->crc32,
1467 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1468 SvCUR(output)-prefix_length) ;
1470 if (s->flags & FLAG_ADLER32)
1471 s->adler32 = adler32(s->adler32,
1472 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1473 SvCUR(output)-prefix_length) ;
1475 /* fix the input buffer */
1476 if (s->flags & FLAG_CONSUME_INPUT) {
1477 in = s->stream.avail_in ;
1478 SvCUR_set(buf, in) ;
1480 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1492 Compress::Zlib::inflateStream s
1494 RETVAL = s->bytesInflated;
1500 Compress::Zlib::inflateStream s
1502 RETVAL = s->compressedBytes;
1507 uncompressedBytes(s)
1508 Compress::Zlib::inflateStream s
1510 RETVAL = s->uncompressedBytes;
1516 inflateSync (s, buf)
1517 Compress::Zlib::inflateStream s
1521 /* If the buffer is a reference, dereference it */
1522 buf = deRef(buf, "inflateSync") ;
1523 #ifdef UTF8_AVAILABLE
1524 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1525 croak("Wide character in Compress::Zlib::Inflate::inflateSync");
1528 /* initialise the input buffer */
1529 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1530 s->stream.avail_in = SvCUR(buf) ;
1532 /* inflateSync doesn't create any output */
1533 s->stream.next_out = (Bytef*) NULL;
1534 s->stream.avail_out = 0;
1536 RETVAL = inflateSync(&(s->stream));
1537 s->last_error = RETVAL ;
1539 /* fix the input buffer */
1541 unsigned in = s->stream.avail_in ;
1542 SvCUR_set(buf, in) ;
1544 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1554 Compress::Zlib::inflateStream s
1556 inflateEnd(&s->stream) ;
1558 SvREFCNT_dec(s->dictionary) ;
1560 if (s->deflateParams_out_buffer)
1561 Safefree(s->deflateParams_out_buffer);
1565 Safefree(s->window);
1572 Compress::Zlib::inflateStream s
1574 RETVAL = s->last_error ;
1580 Compress::Zlib::inflateStream s
1588 Compress::Zlib::inflateStream s
1590 RETVAL = s->dict_adler ;
1596 Compress::Zlib::inflateStream s
1598 RETVAL = s->stream.total_in ;
1604 Compress::Zlib::inflateStream s
1606 RETVAL = s->adler32 ;
1612 Compress::Zlib::inflateStream s
1614 RETVAL = s->stream.total_out ;
1620 Compress::Zlib::inflateStream s
1622 RETVAL = s->stream.msg;
1629 Compress::Zlib::inflateStream s
1631 RETVAL = s->bufsize ;
1637 Compress::Zlib::inflateStream s
1640 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1642 s->flags |= FLAG_APPEND ;
1644 s->flags &= ~FLAG_APPEND ;
1648 MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateScanStream
1652 Compress::Zlib::inflateScanStream s
1654 inflateEnd(&s->stream) ;
1656 SvREFCNT_dec(s->dictionary) ;
1658 if (s->deflateParams_out_buffer)
1659 Safefree(s->deflateParams_out_buffer);
1663 Safefree(s->window);
1668 DispStream(s, message=NULL)
1669 Compress::Zlib::inflateScanStream s
1674 Compress::Zlib::inflateScanStream s
1676 RETVAL = inflateReset(&(s->stream)) ;
1677 if (RETVAL == Z_OK) {
1678 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1684 scan(s, buf, out=NULL, eof=FALSE)
1685 Compress::Zlib::inflateScanStream s
1689 bool eof_mode = FALSE;
1690 int start_len = NO_INIT
1691 STRLEN stmp = NO_INIT
1693 /* If the input buffer is a reference, dereference it */
1694 #ifndef MAGIC_APPEND
1696 croak("scan needs zlib 1.2.1 or better");
1698 buf = deRef(buf, "inflateScan") ;
1699 #ifdef UTF8_AVAILABLE
1700 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1701 croak("Wide character in Compress::Zlib::InflateScan::scan input parameter");
1703 /* initialise the input buffer */
1704 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1705 s->stream.avail_in = SvCUR(buf) ;
1706 start_len = s->stream.avail_in ;
1707 s->bytesInflated = 0 ;
1710 if (s->stream.avail_in == 0) {
1715 /* set up output to next available section of sliding window */
1716 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1717 s->stream.next_out = s->window + s->window_have;
1719 /* DispStream(s, "before inflate\n"); */
1721 /* inflate and check for errors */
1722 RETVAL = inflate(&(s->stream), Z_BLOCK);
1724 if (start_len > 1 && ! eof_mode)
1725 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1727 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1728 RETVAL == Z_DATA_ERROR )
1731 if (s->flags & FLAG_CRC32 )
1732 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1733 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1735 if (s->flags & FLAG_ADLER32)
1736 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1737 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1739 s->uncompressedBytes =
1740 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1742 if (s->stream.avail_out)
1743 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1749 /* process end of block */
1750 if (s->stream.data_type & 128) {
1751 if (s->stream.data_type & 64) {
1752 s->window_left = s->stream.data_type & 0x1f;
1755 s->window_lastbit = s->stream.data_type & 0x1f;
1756 s->lastBlockOffset = s->stream.total_in;
1760 } while (RETVAL != Z_STREAM_END);
1762 s->last_error = RETVAL ;
1763 s->window_lastoff = s->stream.total_in ;
1764 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1766 if (RETVAL == Z_STREAM_END)
1768 s->matchedEndBlock = 1 ;
1770 /* save the location of the end of the compressed data */
1771 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1772 s->window_endOffset = s->stream.total_in ;
1775 -- s->window_endOffset ;
1778 /* if window wrapped, build dictionary from window by rotating */
1779 if (s->window_full) {
1780 rotate(s->window, WINDOW_SIZE, s->window_have);
1781 s->window_have = WINDOW_SIZE;
1784 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1786 unsigned in = s->stream.avail_in ;
1787 SvCUR_set(buf, in) ;
1789 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1801 Compress::Zlib::inflateScanStream s
1803 #ifndef MAGIC_APPEND
1804 croak("getEndOffset needs zlib 1.2.1 or better");
1806 RETVAL = s->window_endOffset;
1813 Compress::Zlib::inflateScanStream s
1815 #ifndef MAGIC_APPEND
1816 croak("inflateCount needs zlib 1.2.1 or better");
1818 RETVAL = s->bytesInflated;
1825 Compress::Zlib::inflateStream s
1827 RETVAL = s->compressedBytes;
1832 uncompressedBytes(s)
1833 Compress::Zlib::inflateStream s
1835 RETVAL = s->uncompressedBytes;
1841 getLastBlockOffset(s)
1842 Compress::Zlib::inflateScanStream s
1844 #ifndef MAGIC_APPEND
1845 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1847 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1853 getLastBufferOffset(s)
1854 Compress::Zlib::inflateScanStream s
1856 #ifndef MAGIC_APPEND
1857 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1859 RETVAL = s->window_lastoff;
1865 resetLastBlockByte(s, byte)
1866 Compress::Zlib::inflateScanStream s
1869 #ifndef MAGIC_APPEND
1870 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1872 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
1877 _createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1878 Compress::Zlib::inflateScanStream inf_s
1888 #ifndef MAGIC_APPEND
1892 windowBits = windowBits;
1893 memLevel = memLevel;
1894 strategy = strategy;
1896 croak("_createDeflateStream needs zlib 1.2.1 or better");
1902 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1903 level, method, windowBits, memLevel, strategy, bufsize) ;
1904 if ((s = InitStream() )) {
1908 s->WindowBits = windowBits;
1909 s->MemLevel = memLevel;
1910 s->Strategy = strategy;
1912 err = deflateInit2(&(s->stream), level,
1913 method, windowBits, memLevel, strategy);
1916 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1917 s->dict_adler = s->stream.adler ;
1925 PostInitStream(s, flags, bufsize, windowBits) ;
1926 s->crc32 = inf_s->crc32;
1927 s->adler32 = inf_s->adler32;
1928 s->stream.adler = inf_s->stream.adler ;
1929 /* s->stream.total_out = inf_s->bytesInflated ; */
1930 s->stream.total_in = inf_s->stream.total_out ;
1931 if (inf_s->window_left) {
1932 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1933 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1940 XPUSHs(sv_setref_pv(sv_newmortal(),
1941 "Compress::Zlib::deflateStream", (void*)s));
1942 if (GIMME == G_ARRAY) {
1943 SV * sv = sv_2mortal(newSViv(err)) ;
1944 setDUALstatus(sv, err);
1952 Compress::Zlib::inflateScanStream s
1954 RETVAL = s->last_error ;
1960 Compress::Zlib::inflateScanStream s
1969 Compress::Zlib::inflateScanStream s
1971 RETVAL = s->adler32 ;