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