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