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