2 * Author : Paul Marquess, <pmqs@cpan.org>
3 * Created : 22nd January 1996
6 * Copyright (c) 1995-2007 Paul Marquess. All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the same terms as Perl itself.
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 >= 0x1222
54 # define AT_LEAST_ZLIB_1_2_2_2
57 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223
58 # define AT_LEAST_ZLIB_1_2_2_3
61 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
62 # define AT_LEAST_ZLIB_1_2_3
66 # define NEED_sv_2pvbyte
67 # define NEED_sv_2pv_nolen
71 #if PERL_REVISION == 5 && PERL_VERSION == 9
73 # define sv_pvbyte_force(sv,lp) sv_pvbyten_force(sv,lp)
76 #if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
78 # ifdef SvPVbyte_force
79 # undef SvPVbyte_force
82 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
86 #ifndef SvPVbyte_nolen
87 # define SvPVbyte_nolen SvPV_nolen
93 # ifndef SvPVbyte_nolen
94 # define SvPVbyte_nolen SvPV_nolen
97 # ifndef SvPVbyte_force
98 # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
102 #if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
103 # define UTF8_AVAILABLE
106 typedef int DualType ;
107 typedef int int_undef ;
109 typedef struct di_stream {
111 #define FLAG_APPEND 1
113 #define FLAG_ADLER32 4
114 #define FLAG_CONSUME_INPUT 8
115 #define FLAG_LIMIT_OUTPUT 16
126 bool deflateParams_out_valid ;
127 Bytef deflateParams_out_byte;
129 #define deflateParams_BUFFER_SIZE 0x4000
130 uLong deflateParams_out_length;
131 Bytef* deflateParams_out_buffer;
138 uLong bytesInflated ;
139 uLong compressedBytes ;
140 uLong uncompressedBytes ;
143 #define WINDOW_SIZE 32768U
145 bool matchedEndBlock;
147 int window_lastbit, window_left, window_full;
148 unsigned window_have;
149 off_t window_lastoff, window_end;
150 off_t window_endOffset;
152 uLong lastBlockOffset ;
153 unsigned char window_lastByte ;
159 typedef di_stream * deflateStream ;
160 typedef di_stream * Compress__Raw__Zlib__deflateStream ;
161 typedef di_stream * inflateStream ;
162 typedef di_stream * Compress__Raw__Zlib__inflateStream ;
163 typedef di_stream * Compress__Raw__Zlib__inflateScanStream ;
165 #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
168 /* Figure out the Operating System */
170 # define OS_CODE 0x00
173 #if defined(AMIGA) || defined(AMIGAOS)
174 # define OS_CODE 0x01
177 #if defined(VAXC) || defined(VMS)
178 # define OS_CODE 0x02
182 # define OS_CODE 0x04
185 #if defined(ATARI) || defined(atarist)
186 # define OS_CODE 0x05
190 # define OS_CODE 0x06
193 #if defined(MACOS) || defined(TARGET_OS_MAC)
194 # define OS_CODE 0x07
198 # define OS_CODE 0x08
202 # define OS_CODE 0x09
206 # define OS_CODE 0x0a
209 #ifdef WIN32 /* Window 95 & Windows NT */
210 # define OS_CODE 0x0b
214 # define OS_CODE 0x0c
217 #if 0 /* Acorn RISCOS */
218 # define OS_CODE 0x0d
222 # define OS_CODE 0x0e
225 #ifdef __50SERIES /* Prime/PRIMOS */
226 # define OS_CODE 0x0F
229 /* Default to UNIX */
231 # define OS_CODE 0x03 /* assume Unix */
235 # define GZIP_OS_CODE OS_CODE
238 #define adlerInitial adler32(0L, Z_NULL, 0)
239 #define crcInitial crc32(0L, Z_NULL, 0)
241 /* static const char * const my_z_errmsg[] = { */
242 static const char my_z_errmsg[][32] = {
243 "need dictionary", /* Z_NEED_DICT 2 */
244 "stream end", /* Z_STREAM_END 1 */
246 "file error", /* Z_ERRNO (-1) */
247 "stream error", /* Z_STREAM_ERROR (-2) */
248 "data error", /* Z_DATA_ERROR (-3) */
249 "insufficient memory", /* Z_MEM_ERROR (-4) */
250 "buffer error", /* Z_BUF_ERROR (-5) */
251 "incompatible version",/* Z_VERSION_ERROR(-6) */
254 #define setDUALstatus(var, err) \
255 sv_setnv(var, (double)err) ; \
256 sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \
260 #if defined(__SYMBIAN32__)
261 # define NO_WRITEABLE_DATA
264 #define TRACE_DEFAULT 0
266 #ifdef NO_WRITEABLE_DATA
267 # define trace TRACE_DEFAULT
269 static int trace = TRACE_DEFAULT ;
272 /* Dodge PerlIO hiding of these functions. */
277 GetErrorString(int error_no)
279 GetErrorString(error_no)
286 if (error_no == Z_ERRNO) {
287 errstr = Strerror(errno) ;
290 /* errstr = gzerror(fil, &error_no) ; */
291 errstr = (char*) my_z_errmsg[2 - error_no];
300 The following two functions are taken almost directly from
301 examples/gzappend.c. Only cosmetic changes have been made to conform to
302 the coding style of the rest of the code in this file.
306 /* return the greatest common divisor of a and b using Euclid's algorithm,
307 modified to be fast when one argument much greater than the other, and
308 coded to avoid unnecessary swapping */
311 gcd(unsigned a, unsigned b)
336 /* rotate list[0..len-1] left by rot positions, in place */
339 rotate(unsigned char *list, unsigned len, unsigned rot)
341 rotate(list, len, rot)
349 unsigned char *start, *last, *to, *from;
351 /* normalize rot and handle degenerate cases */
353 if (rot >= len) rot %= len;
354 if (rot == 0) return;
356 /* pointer to last entry in list */
357 last = list + (len - 1);
359 /* do simple left shift by one */
362 memcpy(list, list + 1, len - 1);
367 /* do simple right shift by one */
368 if (rot == len - 1) {
370 memmove(list + 1, list, len - 1);
375 /* otherwise do rotate as a set of cycles in place */
376 cycles = gcd(len, rot); /* number of cycles */
378 start = from = list + cycles; /* start index is arbitrary */
379 tmp = *from; /* save entry to be overwritten */
381 to = from; /* next step in cycle */
382 from += rot; /* go right rot positions */
383 if (from > last) from -= len; /* (pointer better not wrap) */
384 if (from == start) break; /* all but one shifted */
385 *to = *from; /* shift left */
387 *to = tmp; /* complete the circle */
391 #endif /* MAGIC_APPEND */
395 DispHex(void * ptr, int length)
402 char * p = (char*)ptr;
404 for (i = 0; i < length; ++i) {
405 printf(" %02x", 0xFF & *(p+i));
412 DispStream(di_stream * s, char * message)
414 DispStream(s, message)
425 #define EnDis(f) (s->flags & f ? "Enabled" : "Disabled")
427 printf("DispStream 0x%p", s) ;
429 printf("- %s \n", message) ;
433 printf(" stream pointer is NULL\n");
436 printf(" stream 0x%p\n", &(s->stream));
437 printf(" zalloc 0x%p\n", s->stream.zalloc);
438 printf(" zfree 0x%p\n", s->stream.zfree);
439 printf(" opaque 0x%p\n", s->stream.opaque);
441 printf(" msg %s\n", s->stream.msg);
444 printf(" next_in 0x%p", s->stream.next_in);
445 if (s->stream.next_in){
447 DispHex(s->stream.next_in, 4);
451 printf(" next_out 0x%p", s->stream.next_out);
452 if (s->stream.next_out){
454 DispHex(s->stream.next_out, 4);
458 printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in);
459 printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out);
460 printf(" total_in %ld\n", s->stream.total_in);
461 printf(" total_out %ld\n", s->stream.total_out);
462 printf(" adler %ld\n", s->stream.adler );
463 printf(" bufsize %ld\n", s->bufsize);
464 printf(" dictionary 0x%p\n", s->dictionary);
465 printf(" dict_adler 0x%ld\n",s->dict_adler);
466 printf(" zip_mode %d\n", s->zip_mode);
467 printf(" crc32 0x%x\n", (unsigned)s->crc32);
468 printf(" adler32 0x%x\n", (unsigned)s->adler32);
469 printf(" flags 0x%x\n", s->flags);
470 printf(" APPEND %s\n", EnDis(FLAG_APPEND));
471 printf(" CRC32 %s\n", EnDis(FLAG_CRC32));
472 printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32));
473 printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT));
474 printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT));
478 printf(" window 0x%p\n", s->window);
494 ZMALLOC(s, di_stream) ;
502 PostInitStream(di_stream * s, int flags, int bufsize, int windowBits)
504 PostInitStream(s, flags, bufsize, windowBits)
511 s->bufsize = bufsize ;
513 s->uncompressedBytes =
516 s->zip_mode = (windowBits < 0) ;
517 if (flags & FLAG_CRC32)
518 s->crc32 = crcInitial ;
519 if (flags & FLAG_ADLER32)
520 s->adler32 = adlerInitial ;
526 deRef(SV * sv, const char * string)
543 croak("%s: buffer parameter is not a SCALAR reference", string);
546 croak("%s: buffer parameter is a reference to a reference", string) ;
558 deRef_l(SV * sv, const char * string)
580 croak("%s: buffer parameter is not a SCALAR reference", string);
583 croak("%s: buffer parameter is a reference to a reference", string) ;
586 if (SvREADONLY(sv) && PL_curcop != &PL_compiling)
587 croak("%s: buffer parameter is read-only", string);
589 SvUPGRADE(sv, SVt_PV);
601 #include "constants.h"
603 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
608 INCLUDE: constants.xs
611 /* Check this version of zlib is == 1 */
612 if (zlibVersion()[0] != '1')
613 croak("Compress::Raw::Zlib needs zlib version 1.x\n") ;
616 /* Create the $os_code scalar */
617 SV * os_code_sv = perl_get_sv("Compress::Raw::Zlib::gzip_os_code", GV_ADDMULTI) ;
618 sv_setiv(os_code_sv, GZIP_OS_CODE) ;
622 #define Zip_zlib_version() (const char*)zlib_version
630 RETVAL = ZLIB_VERNUM ;
632 /* 1.1.4 => 0x1140 */
633 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
634 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
635 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
640 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
642 #define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
645 Zip_adler32(buf, adler=adlerInitial)
646 uLong adler = NO_INIT
648 Bytef * buf = NO_INIT
651 /* If the buffer is a reference, dereference it */
652 sv = deRef(sv, "adler32") ;
653 #ifdef UTF8_AVAILABLE
654 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
655 croak("Wide character in Compress::Raw::Zlib::adler32");
657 buf = (Byte*)SvPVbyte(sv, len) ;
660 adler = adlerInitial;
661 else if (SvOK(ST(1)))
662 adler = SvUV(ST(1)) ;
664 adler = adlerInitial;
668 #define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
671 Zip_crc32(buf, crc=crcInitial)
674 Bytef * buf = NO_INIT
677 /* If the buffer is a reference, dereference it */
678 sv = deRef(sv, "crc32") ;
679 #ifdef UTF8_AVAILABLE
680 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
681 croak("Wide character in Compress::Raw::Zlib::crc32");
683 buf = (Byte*)SvPVbyte(sv, len) ;
687 else if (SvOK(ST(1)))
694 crc32_combine(crc1, crc2, len2)
699 #ifndef AT_LEAST_ZLIB_1_2_2_1
700 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
701 croak("crc32_combine needs zlib 1.2.3 or better");
703 RETVAL = crc32_combine(crc1, crc2, len2);
710 adler32_combine(adler1, adler2, len2)
715 #ifndef AT_LEAST_ZLIB_1_2_2_1
716 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
717 croak("adler32_combine needs zlib 1.2.3 or better");
719 RETVAL = adler32_combine(adler1, adler2, len2);
725 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib
728 _deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
742 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld dictionary=%p)\n",
743 level, method, windowBits, memLevel, strategy, bufsize, dictionary) ;
744 if ((s = InitStream() )) {
748 s->WindowBits = windowBits;
749 s->MemLevel = memLevel;
750 s->Strategy = strategy;
752 err = deflateInit2(&(s->stream), level,
753 method, windowBits, memLevel, strategy);
755 /* Check if a dictionary has been specified */
757 if (err == Z_OK && SvCUR(dictionary)) {
758 #ifdef UTF8_AVAILABLE
759 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
760 croak("Wide character in Compress::Raw::Zlib::Deflate::new dicrionary parameter");
762 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
764 s->dict_adler = s->stream.adler ;
772 PostInitStream(s, flags, bufsize, windowBits) ;
779 SV* obj = sv_setref_pv(sv_newmortal(),
780 "Compress::Raw::Zlib::deflateStream", (void*)s);
783 if (GIMME == G_ARRAY) {
784 SV * sv = sv_2mortal(newSViv(err)) ;
785 setDUALstatus(sv, err);
790 _inflateInit(flags, windowBits, bufsize, dictionary)
803 croak("inflateScanInit needs zlib 1.2.1 or better");
806 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
807 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
808 if ((s = InitStream() )) {
810 s->WindowBits = windowBits;
812 err = inflateInit2(&(s->stream), windowBits);
817 else if (SvCUR(dictionary)) {
818 #ifdef AT_LEAST_ZLIB_1_2_2_1
819 /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */
820 if (s->WindowBits < 0) {
821 err = inflateSetDictionary(&(s->stream),
822 (const Bytef*)SvPVbyte_nolen(dictionary),
831 /* Dictionary specified - take a copy for use in inflate */
832 s->dictionary = newSVsv(dictionary) ;
835 PostInitStream(s, flags, bufsize, windowBits) ;
839 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
848 SV* obj = sv_setref_pv(sv_newmortal(),
850 ? "Compress::Raw::Zlib::inflateScanStream"
851 : "Compress::Raw::Zlib::inflateStream",
855 if (GIMME == G_ARRAY) {
856 SV * sv = sv_2mortal(newSViv(err)) ;
857 setDUALstatus(sv, err);
863 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream
866 DispStream(s, message=NULL)
867 Compress::Raw::Zlib::deflateStream s
872 Compress::Raw::Zlib::deflateStream s
874 RETVAL = deflateReset(&(s->stream)) ;
875 if (RETVAL == Z_OK) {
876 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
882 deflate (s, buf, output)
883 Compress::Raw::Zlib::deflateStream s
886 uInt cur_length = NO_INIT
887 uInt increment = NO_INIT
888 uInt prefix = NO_INIT
890 uLong bufinc = NO_INIT
894 /* If the input buffer is a reference, dereference it */
895 buf = deRef(buf, "deflate") ;
897 /* initialise the input buffer */
898 #ifdef UTF8_AVAILABLE
899 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
900 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter");
902 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
903 s->stream.avail_in = SvCUR(buf) ;
905 if (s->flags & FLAG_CRC32)
906 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
908 if (s->flags & FLAG_ADLER32)
909 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
911 /* and retrieve the output buffer */
912 output = deRef_l(output, "deflate") ;
913 #ifdef UTF8_AVAILABLE
914 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
915 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate output parameter");
918 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
919 SvCUR_set(output, 0);
920 /* sv_setpvn(output, "", 0); */
922 prefix = cur_length = SvCUR(output) ;
923 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
924 increment = SvLEN(output) - cur_length;
925 s->stream.avail_out = increment;
927 /* Check for saved output from deflateParams */
928 if (s->deflateParams_out_valid) {
929 *(s->stream.next_out) = s->deflateParams_out_byte;
930 ++ s->stream.next_out;
931 -- s->stream.avail_out ;
932 s->deflateParams_out_valid = FALSE;
935 /* Check for saved output from deflateParams */
936 if (s->deflateParams_out_length) {
937 uLong plen = s->deflateParams_out_length ;
938 /* printf("Copy %d bytes saved data\n", plen);*/
939 if (s->stream.avail_out < plen) {
940 /*printf("GROW from %d to %d\n", s->stream.avail_out,
941 SvLEN(output) + plen - s->stream.avail_out); */
942 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
945 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
946 cur_length = cur_length + plen;
947 SvCUR_set(output, cur_length);
948 s->stream.next_out += plen ;
949 s->stream.avail_out = SvLEN(output) - cur_length ;
950 increment = s->stream.avail_out;
951 s->deflateParams_out_length = 0;
954 while (s->stream.avail_in != 0) {
956 if (s->stream.avail_out == 0) {
957 /* out of space in the output buffer so make it bigger */
958 Sv_Grow(output, SvLEN(output) + bufinc) ;
959 cur_length += increment ;
960 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
962 s->stream.avail_out = increment;
966 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
971 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
972 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ;
974 s->last_error = RETVAL ;
975 if (RETVAL == Z_OK) {
977 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
986 Compress::Raw::Zlib::deflateStream s
988 deflateEnd(&s->stream) ;
990 SvREFCNT_dec(s->dictionary) ;
992 if (s->deflateParams_out_buffer)
993 Safefree(s->deflateParams_out_buffer);
999 flush(s, output, f=Z_FINISH)
1000 Compress::Raw::Zlib::deflateStream s
1003 uInt cur_length = NO_INIT
1004 uInt increment = NO_INIT
1005 uInt prefix = NO_INIT
1006 uLong bufinc = NO_INIT
1008 bufinc = s->bufsize;
1010 s->stream.avail_in = 0; /* should be zero already anyway */
1012 /* retrieve the output buffer */
1013 output = deRef_l(output, "flush") ;
1014 #ifdef UTF8_AVAILABLE
1015 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1016 croak("Wide character in Compress::Raw::Zlib::Deflate::flush input parameter");
1018 if(! s->flags & FLAG_APPEND) {
1019 SvCUR_set(output, 0);
1020 /* sv_setpvn(output, "", 0); */
1022 prefix = cur_length = SvCUR(output) ;
1023 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1024 increment = SvLEN(output) - cur_length;
1025 s->stream.avail_out = increment;
1027 /* Check for saved output from deflateParams */
1028 if (s->deflateParams_out_valid) {
1029 *(s->stream.next_out) = s->deflateParams_out_byte;
1030 ++ s->stream.next_out;
1031 -- s->stream.avail_out ;
1032 s->deflateParams_out_valid = FALSE;
1035 /* Check for saved output from deflateParams */
1036 if (s->deflateParams_out_length) {
1037 uLong plen = s->deflateParams_out_length ;
1038 /* printf("Copy %d bytes saved data\n", plen); */
1039 if (s->stream.avail_out < plen) {
1040 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1041 SvLEN(output) + plen - s->stream.avail_out); */
1042 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1045 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1046 cur_length = cur_length + plen;
1047 SvCUR_set(output, cur_length);
1048 s->stream.next_out += plen ;
1049 s->stream.avail_out = SvLEN(output) - cur_length ;
1050 increment = s->stream.avail_out;
1051 s->deflateParams_out_length = 0;
1056 if (s->stream.avail_out == 0) {
1057 /* consumed all the available output, so extend it */
1058 Sv_Grow(output, SvLEN(output) + bufinc) ;
1059 cur_length += increment ;
1060 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1061 increment = bufinc ;
1062 s->stream.avail_out = increment;
1065 RETVAL = deflate(&(s->stream), f);
1067 /* deflate has finished flushing only when it hasn't used up
1068 * all the available space in the output buffer:
1070 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
1074 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1075 s->last_error = RETVAL ;
1077 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1079 if (RETVAL == Z_OK) {
1081 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
1089 _deflateParams(s, flags, level, strategy, bufsize)
1090 Compress::Raw::Zlib::deflateStream s
1096 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1097 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
1101 s->Strategy = strategy ;
1103 s->bufsize = bufsize;
1105 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1107 s->stream.avail_in = 0;
1108 s->stream.next_out = &(s->deflateParams_out_byte) ;
1109 s->stream.avail_out = 1;
1110 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1111 s->deflateParams_out_valid =
1112 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
1113 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1115 /* printf("Level %d Strategy %d, Prev Len %d\n",
1116 s->Level, s->Strategy, s->deflateParams_out_length); */
1117 s->stream.avail_in = 0;
1118 if (s->deflateParams_out_buffer == NULL)
1119 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1120 s->stream.next_out = s->deflateParams_out_buffer ;
1121 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1123 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1124 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1125 /* printf("RETVAL %d, length out %d, avail %d\n",
1126 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1134 Compress::Raw::Zlib::deflateStream s
1142 Compress::Raw::Zlib::deflateStream s
1144 RETVAL = s->Strategy ;
1151 Compress::Raw::Zlib::deflateStream s
1153 RETVAL = s->bufsize ;
1160 Compress::Raw::Zlib::deflateStream s
1162 RETVAL = s->last_error ;
1168 Compress::Raw::Zlib::deflateStream s
1176 Compress::Raw::Zlib::deflateStream s
1178 RETVAL = s->dict_adler ;
1184 Compress::Raw::Zlib::deflateStream s
1186 RETVAL = s->adler32 ;
1192 Compress::Raw::Zlib::deflateStream s
1194 RETVAL = s->compressedBytes;
1199 uncompressedBytes(s)
1200 Compress::Raw::Zlib::deflateStream s
1202 RETVAL = s->uncompressedBytes;
1208 Compress::Raw::Zlib::deflateStream s
1210 RETVAL = s->stream.total_in ;
1216 Compress::Raw::Zlib::deflateStream s
1218 RETVAL = s->stream.total_out ;
1224 Compress::Raw::Zlib::deflateStream s
1226 RETVAL = s->stream.msg;
1231 deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1232 Compress::Raw::Zlib::deflateStream s
1238 #ifndef AT_LEAST_ZLIB_1_2_2_3
1239 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1240 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1241 croak("deflateTune needs zlib 1.2.2.3 or better");
1243 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1249 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream
1252 DispStream(s, message=NULL)
1253 Compress::Raw::Zlib::inflateStream s
1258 Compress::Raw::Zlib::inflateStream s
1260 RETVAL = inflateReset(&(s->stream)) ;
1261 if (RETVAL == Z_OK) {
1262 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1268 inflate (s, buf, output, eof=FALSE)
1269 Compress::Raw::Zlib::inflateStream s
1273 uInt cur_length = 0;
1274 uInt prefix_length = 0;
1276 STRLEN stmp = NO_INIT
1277 uLong bufinc = NO_INIT
1279 #ifdef UTF8_AVAILABLE
1280 bool out_utf8 = FALSE;
1283 bufinc = s->bufsize;
1284 /* If the buffer is a reference, dereference it */
1285 buf = deRef(buf, "inflate") ;
1287 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
1288 croak("Compress::Raw::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified");
1289 #ifdef UTF8_AVAILABLE
1290 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1291 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate input parameter");
1294 /* initialise the input buffer */
1295 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1296 s->stream.avail_in = SvCUR(buf) ;
1298 /* and retrieve the output buffer */
1299 output = deRef_l(output, "inflate") ;
1300 #ifdef UTF8_AVAILABLE
1301 if (DO_UTF8(output))
1303 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1304 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate output parameter");
1306 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1307 SvCUR_set(output, 0);
1309 if (SvLEN(output)) {
1310 prefix_length = cur_length = SvCUR(output) ;
1311 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1312 increment = SvLEN(output) - cur_length - 1;
1313 s->stream.avail_out = increment;
1316 s->stream.avail_out = 0;
1318 s->bytesInflated = 0;
1322 while (RETVAL == Z_OK) {
1323 if (s->stream.avail_out == 0 ) {
1324 /* out of space in the output buffer so make it bigger */
1325 Sv_Grow(output, SvLEN(output) + bufinc) ;
1326 cur_length += increment ;
1327 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1328 increment = bufinc ;
1329 s->stream.avail_out = increment;
1333 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1336 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1337 s->dict_adler = s->stream.adler ;
1338 RETVAL = inflateSetDictionary(&(s->stream),
1339 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1340 SvCUR(s->dictionary));
1343 if (s->flags & FLAG_LIMIT_OUTPUT ||
1344 RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1345 RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END )
1348 if (RETVAL == Z_BUF_ERROR) {
1349 if (s->stream.avail_out == 0)
1351 if (s->stream.avail_in == 0) {
1357 #ifdef NEED_DUMMY_BYTE_AT_END
1358 if (eof && RETVAL == Z_OK && s->flags & FLAG_LIMIT_OUTPUT == 0) {
1359 Bytef* nextIn = s->stream.next_in;
1360 uInt availIn = s->stream.avail_in;
1361 s->stream.next_in = (Bytef*) " ";
1362 s->stream.avail_in = 1;
1363 if (s->stream.avail_out == 0) {
1364 /* out of space in the output buffer so make it bigger */
1365 Sv_Grow(output, SvLEN(output) + bufinc) ;
1366 cur_length += increment ;
1367 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
1368 increment = bufinc ;
1369 s->stream.avail_out = increment;
1372 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1373 s->stream.next_in = nextIn ;
1374 s->stream.avail_in = availIn ;
1378 s->last_error = RETVAL ;
1379 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) {
1382 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
1383 s->uncompressedBytes += s->bytesInflated ;
1384 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1387 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1388 *SvEND(output) = '\0';
1389 #ifdef UTF8_AVAILABLE
1391 sv_utf8_upgrade(output);
1395 if (s->flags & FLAG_CRC32 )
1396 s->crc32 = crc32(s->crc32,
1397 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1398 SvCUR(output)-prefix_length) ;
1400 if (s->flags & FLAG_ADLER32)
1401 s->adler32 = adler32(s->adler32,
1402 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1403 SvCUR(output)-prefix_length) ;
1405 /* fix the input buffer */
1406 if (s->flags & FLAG_CONSUME_INPUT || s->flags & FLAG_LIMIT_OUTPUT) {
1407 in = s->stream.avail_in ;
1408 SvCUR_set(buf, in) ;
1410 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1420 Compress::Raw::Zlib::inflateStream s
1422 RETVAL = s->bytesInflated;
1428 Compress::Raw::Zlib::inflateStream s
1430 RETVAL = s->compressedBytes;
1435 uncompressedBytes(s)
1436 Compress::Raw::Zlib::inflateStream s
1438 RETVAL = s->uncompressedBytes;
1444 inflateSync (s, buf)
1445 Compress::Raw::Zlib::inflateStream s
1449 /* If the buffer is a reference, dereference it */
1450 buf = deRef(buf, "inflateSync") ;
1451 #ifdef UTF8_AVAILABLE
1452 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1453 croak("Wide character in Compress::Raw::Zlib::Inflate::inflateSync");
1456 /* initialise the input buffer */
1457 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1458 s->stream.avail_in = SvCUR(buf) ;
1460 /* inflateSync doesn't create any output */
1461 s->stream.next_out = (Bytef*) NULL;
1462 s->stream.avail_out = 0;
1464 RETVAL = inflateSync(&(s->stream));
1465 s->last_error = RETVAL ;
1467 /* fix the input buffer */
1469 unsigned in = s->stream.avail_in ;
1470 SvCUR_set(buf, in) ;
1472 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1481 Compress::Raw::Zlib::inflateStream s
1483 inflateEnd(&s->stream) ;
1485 SvREFCNT_dec(s->dictionary) ;
1487 if (s->deflateParams_out_buffer)
1488 Safefree(s->deflateParams_out_buffer);
1492 Safefree(s->window);
1499 Compress::Raw::Zlib::inflateStream s
1501 RETVAL = s->last_error ;
1507 Compress::Raw::Zlib::inflateStream s
1515 Compress::Raw::Zlib::inflateStream s
1517 RETVAL = s->dict_adler ;
1523 Compress::Raw::Zlib::inflateStream s
1525 RETVAL = s->stream.total_in ;
1531 Compress::Raw::Zlib::inflateStream s
1533 RETVAL = s->adler32 ;
1539 Compress::Raw::Zlib::inflateStream s
1541 RETVAL = s->stream.total_out ;
1547 Compress::Raw::Zlib::inflateStream s
1549 RETVAL = s->stream.msg;
1556 Compress::Raw::Zlib::inflateStream s
1558 RETVAL = s->bufsize ;
1564 Compress::Raw::Zlib::inflateStream s
1567 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1569 s->flags |= FLAG_APPEND ;
1571 s->flags &= ~FLAG_APPEND ;
1575 MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream
1579 Compress::Raw::Zlib::inflateScanStream s
1581 inflateEnd(&s->stream) ;
1583 SvREFCNT_dec(s->dictionary) ;
1585 if (s->deflateParams_out_buffer)
1586 Safefree(s->deflateParams_out_buffer);
1590 Safefree(s->window);
1595 DispStream(s, message=NULL)
1596 Compress::Raw::Zlib::inflateScanStream s
1601 Compress::Raw::Zlib::inflateScanStream s
1603 RETVAL = inflateReset(&(s->stream)) ;
1604 if (RETVAL == Z_OK) {
1605 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1611 scan(s, buf, out=NULL, eof=FALSE)
1612 Compress::Raw::Zlib::inflateScanStream s
1616 bool eof_mode = FALSE;
1617 int start_len = NO_INIT
1618 STRLEN stmp = NO_INIT
1620 /* If the input buffer is a reference, dereference it */
1621 #ifndef MAGIC_APPEND
1623 croak("scan needs zlib 1.2.1 or better");
1625 buf = deRef(buf, "inflateScan") ;
1626 #ifdef UTF8_AVAILABLE
1627 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1628 croak("Wide character in Compress::Raw::Zlib::InflateScan::scan input parameter");
1630 /* initialise the input buffer */
1631 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1632 s->stream.avail_in = SvCUR(buf) ;
1633 start_len = s->stream.avail_in ;
1634 s->bytesInflated = 0 ;
1637 if (s->stream.avail_in == 0) {
1642 /* set up output to next available section of sliding window */
1643 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1644 s->stream.next_out = s->window + s->window_have;
1646 /* DispStream(s, "before inflate\n"); */
1648 /* inflate and check for errors */
1649 RETVAL = inflate(&(s->stream), Z_BLOCK);
1651 if (start_len > 1 && ! eof_mode)
1652 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1654 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1655 RETVAL == Z_DATA_ERROR )
1658 if (s->flags & FLAG_CRC32 )
1659 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1660 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1662 if (s->flags & FLAG_ADLER32)
1663 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1664 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1666 s->uncompressedBytes =
1667 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1669 if (s->stream.avail_out)
1670 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1676 /* process end of block */
1677 if (s->stream.data_type & 128) {
1678 if (s->stream.data_type & 64) {
1679 s->window_left = s->stream.data_type & 0x1f;
1682 s->window_lastbit = s->stream.data_type & 0x1f;
1683 s->lastBlockOffset = s->stream.total_in;
1687 } while (RETVAL != Z_STREAM_END);
1689 s->last_error = RETVAL ;
1690 s->window_lastoff = s->stream.total_in ;
1691 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1693 if (RETVAL == Z_STREAM_END)
1695 s->matchedEndBlock = 1 ;
1697 /* save the location of the end of the compressed data */
1698 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1699 s->window_endOffset = s->stream.total_in ;
1702 -- s->window_endOffset ;
1705 /* if window wrapped, build dictionary from window by rotating */
1706 if (s->window_full) {
1707 rotate(s->window, WINDOW_SIZE, s->window_have);
1708 s->window_have = WINDOW_SIZE;
1711 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1713 unsigned in = s->stream.avail_in ;
1714 SvCUR_set(buf, in) ;
1716 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1728 Compress::Raw::Zlib::inflateScanStream s
1730 #ifndef MAGIC_APPEND
1731 croak("getEndOffset needs zlib 1.2.1 or better");
1733 RETVAL = s->window_endOffset;
1740 Compress::Raw::Zlib::inflateScanStream s
1742 #ifndef MAGIC_APPEND
1743 croak("inflateCount needs zlib 1.2.1 or better");
1745 RETVAL = s->bytesInflated;
1752 Compress::Raw::Zlib::inflateScanStream s
1754 RETVAL = s->compressedBytes;
1759 uncompressedBytes(s)
1760 Compress::Raw::Zlib::inflateScanStream s
1762 RETVAL = s->uncompressedBytes;
1768 getLastBlockOffset(s)
1769 Compress::Raw::Zlib::inflateScanStream s
1771 #ifndef MAGIC_APPEND
1772 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1774 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1780 getLastBufferOffset(s)
1781 Compress::Raw::Zlib::inflateScanStream s
1783 #ifndef MAGIC_APPEND
1784 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1786 RETVAL = s->window_lastoff;
1792 resetLastBlockByte(s, byte)
1793 Compress::Raw::Zlib::inflateScanStream s
1796 #ifndef MAGIC_APPEND
1797 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1800 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
1805 _createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1806 Compress::Raw::Zlib::inflateScanStream inf_s
1816 #ifndef MAGIC_APPEND
1820 windowBits = windowBits;
1821 memLevel = memLevel;
1822 strategy = strategy;
1824 croak("_createDeflateStream needs zlib 1.2.1 or better");
1830 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1831 level, method, windowBits, memLevel, strategy, bufsize) ;
1832 if ((s = InitStream() )) {
1836 s->WindowBits = windowBits;
1837 s->MemLevel = memLevel;
1838 s->Strategy = strategy;
1840 err = deflateInit2(&(s->stream), level,
1841 method, windowBits, memLevel, strategy);
1844 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1845 s->dict_adler = s->stream.adler ;
1853 PostInitStream(s, flags, bufsize, windowBits) ;
1854 s->crc32 = inf_s->crc32;
1855 s->adler32 = inf_s->adler32;
1856 s->stream.adler = inf_s->stream.adler ;
1857 /* s->stream.total_out = inf_s->bytesInflated ; */
1858 s->stream.total_in = inf_s->stream.total_out ;
1859 if (inf_s->window_left) {
1860 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1861 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1868 XPUSHs(sv_setref_pv(sv_newmortal(),
1869 "Compress::Raw::Zlib::deflateStream", (void*)s));
1870 if (GIMME == G_ARRAY) {
1871 SV * sv = sv_2mortal(newSViv(err)) ;
1872 setDUALstatus(sv, err);
1880 Compress::Raw::Zlib::inflateScanStream s
1882 RETVAL = s->last_error ;
1888 Compress::Raw::Zlib::inflateScanStream s
1897 Compress::Raw::Zlib::inflateScanStream s
1899 RETVAL = s->adler32 ;