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