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