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