[patch] perlhack.pod
[p5sagit/p5-mst-13.2.git] / ext / Compress / Raw / Zlib / Zlib.xs
CommitLineData
25f0751f 1/* Filename: Zlib.xs
2 * Author : Paul Marquess, <pmqs@cpan.org>
3 * Created : 22nd January 1996
4 * Version : 2.000
5 *
4e7676c7 6 * Copyright (c) 1995-2007 Paul Marquess. All rights reserved.
25f0751f 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
9f44f717 61#ifdef USE_PPPORT_H
62# define NEED_sv_2pvbyte
63# define NEED_sv_2pv_nolen
64# include "ppport.h"
65#endif
25f0751f 66
258133d1 67#if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
25f0751f 68
69# ifdef SvPVbyte_force
70# undef SvPVbyte_force
71# endif
72
73# define SvPVbyte_force(sv,lp) SvPV_force(sv,lp)
74
258133d1 75#endif
25f0751f 76
258133d1 77#ifndef SvPVbyte_nolen
25f0751f 78# define SvPVbyte_nolen SvPV_nolen
258133d1 79#endif
25f0751f 80
81
25f0751f 82
258133d1 83#if 0
25f0751f 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
258133d1 91#endif
25f0751f 92
93#if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 ))
94# define UTF8_AVAILABLE
95#endif
96
97typedef int DualType ;
98typedef int int_undef ;
99
100typedef 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;
25f0751f 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
149typedef di_stream * deflateStream ;
150typedef di_stream * Compress__Raw__Zlib__deflateStream ;
151typedef di_stream * inflateStream ;
152typedef di_stream * Compress__Raw__Zlib__inflateStream ;
153typedef di_stream * Compress__Raw__Zlib__inflateScanStream ;
154
25f0751f 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
232static const char * const my_z_errmsg[] = {
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
265static char *
266#ifdef CAN_PROTOTYPE
267GetErrorString(int error_no)
268#else
269GetErrorString(error_no)
270int 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
25f0751f 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 */
299static unsigned
300#ifdef CAN_PROTOTYPE
301gcd(unsigned a, unsigned b)
302#else
303gcd(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 */
327static void
328#ifdef CAN_PROTOTYPE
329rotate(unsigned char *list, unsigned len, unsigned rot)
330#else
331rotate(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
383static void
384#ifdef CAN_PROTOTYPE
385DispHex(void * ptr, int length)
386#else
387DispHex(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
400static void
401#ifdef CAN_PROTOTYPE
402DispStream(di_stream * s, char * message)
403#else
404DispStream(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
473static di_stream *
474#ifdef CAN_PROTOTYPE
475InitStream(void)
476#else
477InitStream()
478#endif
479{
480 di_stream *s ;
481
482 ZMALLOC(s, di_stream) ;
483
484 return s ;
485
486}
487
488static void
489#ifdef CAN_PROTOTYPE
490PostInitStream(di_stream * s, int flags, int bufsize, int windowBits)
491#else
492PostInitStream(s, flags, bufsize, windowBits)
493 di_stream *s ;
494 int flags ;
495 int bufsize ;
496 int windowBits ;
497#endif
498{
499 s->bufsize = bufsize ;
25f0751f 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
512static SV*
513#ifdef CAN_PROTOTYPE
514deRef(SV * sv, char * string)
515#else
516deRef(sv, string)
517SV * sv ;
518char * 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
544static SV*
545#ifdef CAN_PROTOTYPE
546deRef_l(SV * sv, char * string)
547#else
548deRef_l(sv, string)
549SV * sv ;
550char * 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
591MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
592
593REQUIRE: 1.924
594PROTOTYPES: DISABLE
595
596INCLUDE: constants.xs
597
598BOOT:
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() (char*)zlib_version
611char*
612Zip_zlib_version()
613
614unsigned
615ZLIB_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
628MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
629
630#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
631
632uLong
633Zip_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
654#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
655
656uLong
657Zip_crc32(buf, crc=crcInitial)
658 uLong crc = NO_INIT
659 STRLEN len = NO_INIT
660 Bytef * buf = NO_INIT
661 SV * sv = ST(0) ;
662 INIT:
663 /* If the buffer is a reference, dereference it */
664 sv = deRef(sv, "crc32") ;
665#ifdef UTF8_AVAILABLE
666 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
667 croak("Wide character in Compress::Raw::Zlib::crc32");
668#endif
669 buf = (Byte*)SvPVbyte(sv, len) ;
670
671 if (items < 2)
672 crc = crcInitial;
673 else if (SvOK(ST(1)))
674 crc = SvUV(ST(1)) ;
675 else
676 crc = crcInitial;
677
678
679uLong
680crc32_combine(crc1, crc2, len2)
681 uLong crc1
682 uLong crc2
683 z_off_t len2
684 CODE:
685#ifndef AT_LEAST_ZLIB_1_2_2_1
686 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
687 croak("crc32_combine needs zlib 1.2.3 or better");
688#else
689 RETVAL = crc32_combine(crc1, crc2, len2);
690#endif
691 OUTPUT:
692 RETVAL
693
694
695uLong
696adler32_combine(adler1, adler2, len2)
697 uLong adler1
698 uLong adler2
699 z_off_t len2
700 CODE:
701#ifndef AT_LEAST_ZLIB_1_2_2_1
702 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
703 croak("adler32_combine needs zlib 1.2.3 or better");
704#else
705 RETVAL = adler32_combine(adler1, adler2, len2);
706#endif
707 OUTPUT:
708 RETVAL
709
710
711MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib
712
713void
714_deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
715 int flags
716 int level
717 int method
718 int windowBits
719 int memLevel
720 int strategy
721 uLong bufsize
722 SV* dictionary
723 PPCODE:
724 int err ;
725 deflateStream s ;
726
727 if (trace)
728 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld\n",
729 level, method, windowBits, memLevel, strategy, bufsize) ;
730 if ((s = InitStream() )) {
731
732 s->Level = level;
733 s->Method = method;
734 s->WindowBits = windowBits;
735 s->MemLevel = memLevel;
736 s->Strategy = strategy;
737
738 err = deflateInit2(&(s->stream), level,
739 method, windowBits, memLevel, strategy);
740
741 /* Check if a dictionary has been specified */
742
743 if (err == Z_OK && SvCUR(dictionary)) {
744#ifdef UTF8_AVAILABLE
745 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
746 croak("Wide character in Compress::Raw::Zlib::Deflate::new dicrionary parameter");
747#endif
748 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
749 SvCUR(dictionary)) ;
750 s->dict_adler = s->stream.adler ;
751 }
752
753 if (err != Z_OK) {
754 Safefree(s) ;
755 s = NULL ;
756 }
757 else
758 PostInitStream(s, flags, bufsize, windowBits) ;
759
760 }
761 else
762 err = Z_MEM_ERROR ;
763
764 XPUSHs(sv_setref_pv(sv_newmortal(),
765 "Compress::Raw::Zlib::deflateStream", (void*)s));
766 if (GIMME == G_ARRAY) {
767 SV * sv = sv_2mortal(newSViv(err)) ;
768 setDUALstatus(sv, err);
769 XPUSHs(sv) ;
770 }
771
772void
773_inflateInit(flags, windowBits, bufsize, dictionary)
774 int flags
775 int windowBits
776 uLong bufsize
777 SV * dictionary
778 ALIAS:
779 _inflateScanInit = 1
780 PPCODE:
781
782 int err = Z_OK ;
783 inflateStream s ;
784#ifndef MAGIC_APPEND
785 if (ix == 1)
786 croak("inflateScanInit needs zlib 1.2.1 or better");
787#endif
788 if (trace)
789 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
790 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
791 if ((s = InitStream() )) {
792
793 s->WindowBits = windowBits;
794
795 err = inflateInit2(&(s->stream), windowBits);
796 if (err != Z_OK) {
797 Safefree(s) ;
798 s = NULL ;
799 }
800 else if (SvCUR(dictionary)) {
801 /* Dictionary specified - take a copy for use in inflate */
802 s->dictionary = newSVsv(dictionary) ;
803 }
804 if (s) {
805 PostInitStream(s, flags, bufsize, windowBits) ;
806#ifdef MAGIC_APPEND
807 if (ix == 1)
808 {
809 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
810 }
811#endif
812 }
813 }
814 else
815 err = Z_MEM_ERROR ;
816
817 XPUSHs(sv_setref_pv(sv_newmortal(),
818 ix == 1
819 ? "Compress::Raw::Zlib::inflateScanStream"
820 : "Compress::Raw::Zlib::inflateStream",
821 (void*)s));
822 if (GIMME == G_ARRAY) {
823 SV * sv = sv_2mortal(newSViv(err)) ;
824 setDUALstatus(sv, err);
825 XPUSHs(sv) ;
826 }
827
828
829
830MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream
831
832void
833DispStream(s, message=NULL)
834 Compress::Raw::Zlib::deflateStream s
835 char * message
836
837DualType
838deflateReset(s)
839 Compress::Raw::Zlib::deflateStream s
840 CODE:
841 RETVAL = deflateReset(&(s->stream)) ;
842 if (RETVAL == Z_OK) {
843 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
844 }
845 OUTPUT:
846 RETVAL
847
848DualType
849deflate (s, buf, output)
850 Compress::Raw::Zlib::deflateStream s
851 SV * buf
852 SV * output
853 uInt cur_length = NO_INIT
854 uInt increment = NO_INIT
855 uInt prefix = NO_INIT
856 int RETVAL = 0;
258133d1 857 uLong bufinc = NO_INIT
25f0751f 858 CODE:
258133d1 859 bufinc = s->bufsize;
25f0751f 860
861 /* If the input buffer is a reference, dereference it */
862 buf = deRef(buf, "deflate") ;
863
864 /* initialise the input buffer */
865#ifdef UTF8_AVAILABLE
866 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
867 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter");
868#endif
869 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
870 s->stream.avail_in = SvCUR(buf) ;
871
872 if (s->flags & FLAG_CRC32)
873 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
874
875 if (s->flags & FLAG_ADLER32)
876 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
877
878 /* and retrieve the output buffer */
879 output = deRef_l(output, "deflate") ;
880#ifdef UTF8_AVAILABLE
881 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
882 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate output parameter");
883#endif
884
885 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
886 SvCUR_set(output, 0);
887 /* sv_setpvn(output, "", 0); */
888 }
889 prefix = cur_length = SvCUR(output) ;
890 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
891 increment = SvLEN(output) - cur_length;
892 s->stream.avail_out = increment;
893#ifdef SETP_BYTE
894 /* Check for saved output from deflateParams */
895 if (s->deflateParams_out_valid) {
896 *(s->stream.next_out) = s->deflateParams_out_byte;
897 ++ s->stream.next_out;
898 -- s->stream.avail_out ;
899 s->deflateParams_out_valid = FALSE;
900 }
901#else
902 /* Check for saved output from deflateParams */
903 if (s->deflateParams_out_length) {
904 uLong plen = s->deflateParams_out_length ;
905 /* printf("Copy %d bytes saved data\n", plen);*/
906 if (s->stream.avail_out < plen) {
907 /*printf("GROW from %d to %d\n", s->stream.avail_out,
908 SvLEN(output) + plen - s->stream.avail_out); */
909 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
910 }
911
912 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
913 cur_length = cur_length + plen;
914 SvCUR_set(output, cur_length);
915 s->stream.next_out += plen ;
916 s->stream.avail_out = SvLEN(output) - cur_length ;
917 increment = s->stream.avail_out;
918 s->deflateParams_out_length = 0;
919 }
920#endif
921 while (s->stream.avail_in != 0) {
922
923 if (s->stream.avail_out == 0) {
924 /* out of space in the output buffer so make it bigger */
258133d1 925 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 926 cur_length += increment ;
927 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 928 increment = bufinc ;
25f0751f 929 s->stream.avail_out = increment;
258133d1 930 bufinc *= 2 ;
25f0751f 931 }
932
933 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
934 if (RETVAL != Z_OK)
935 break;
936 }
937
938 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
939 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ;
940
941 s->last_error = RETVAL ;
942 if (RETVAL == Z_OK) {
943 SvPOK_only(output);
944 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
4e7676c7 945 SvSETMAGIC(output);
25f0751f 946 }
947 OUTPUT:
948 RETVAL
25f0751f 949
950
951void
952DESTROY(s)
953 Compress::Raw::Zlib::deflateStream s
954 CODE:
955 deflateEnd(&s->stream) ;
956 if (s->dictionary)
957 SvREFCNT_dec(s->dictionary) ;
958#ifndef SETP_BYTE
959 if (s->deflateParams_out_buffer)
960 Safefree(s->deflateParams_out_buffer);
961#endif
962 Safefree(s) ;
963
964
965DualType
966flush(s, output, f=Z_FINISH)
967 Compress::Raw::Zlib::deflateStream s
968 SV * output
969 int f
970 uInt cur_length = NO_INIT
971 uInt increment = NO_INIT
972 uInt prefix = NO_INIT
258133d1 973 uLong bufinc = NO_INIT
25f0751f 974 CODE:
258133d1 975 bufinc = s->bufsize;
25f0751f 976
977 s->stream.avail_in = 0; /* should be zero already anyway */
978
979 /* retrieve the output buffer */
980 output = deRef_l(output, "flush") ;
981#ifdef UTF8_AVAILABLE
982 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
983 croak("Wide character in Compress::Raw::Zlib::Deflate::flush input parameter");
984#endif
985 if(! s->flags & FLAG_APPEND) {
986 SvCUR_set(output, 0);
987 /* sv_setpvn(output, "", 0); */
988 }
989 prefix = cur_length = SvCUR(output) ;
990 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
991 increment = SvLEN(output) - cur_length;
992 s->stream.avail_out = increment;
993#ifdef SETP_BYTE
994 /* Check for saved output from deflateParams */
995 if (s->deflateParams_out_valid) {
996 *(s->stream.next_out) = s->deflateParams_out_byte;
997 ++ s->stream.next_out;
998 -- s->stream.avail_out ;
999 s->deflateParams_out_valid = FALSE;
1000 }
1001#else
1002 /* Check for saved output from deflateParams */
1003 if (s->deflateParams_out_length) {
1004 uLong plen = s->deflateParams_out_length ;
1005 /* printf("Copy %d bytes saved data\n", plen); */
1006 if (s->stream.avail_out < plen) {
1007 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1008 SvLEN(output) + plen - s->stream.avail_out); */
1009 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1010 }
1011
1012 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1013 cur_length = cur_length + plen;
1014 SvCUR_set(output, cur_length);
1015 s->stream.next_out += plen ;
1016 s->stream.avail_out = SvLEN(output) - cur_length ;
1017 increment = s->stream.avail_out;
1018 s->deflateParams_out_length = 0;
1019 }
1020#endif
1021
1022 for (;;) {
1023 if (s->stream.avail_out == 0) {
1024 /* consumed all the available output, so extend it */
258133d1 1025 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1026 cur_length += increment ;
1027 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1028 increment = bufinc ;
25f0751f 1029 s->stream.avail_out = increment;
258133d1 1030 bufinc *= 2 ;
25f0751f 1031 }
1032 RETVAL = deflate(&(s->stream), f);
1033
1034 /* deflate has finished flushing only when it hasn't used up
1035 * all the available space in the output buffer:
1036 */
1037 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
1038 break;
1039 }
1040
1041 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1042 s->last_error = RETVAL ;
1043
1044 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1045
1046 if (RETVAL == Z_OK) {
1047 SvPOK_only(output);
1048 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
4e7676c7 1049 SvSETMAGIC(output);
25f0751f 1050 }
1051 OUTPUT:
1052 RETVAL
25f0751f 1053
1054
1055DualType
1056_deflateParams(s, flags, level, strategy, bufsize)
1057 Compress::Raw::Zlib::deflateStream s
1058 int flags
1059 int level
1060 int strategy
1061 uLong bufsize
1062 CODE:
1063 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1064 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
1065 if (flags & 1)
1066 s->Level = level ;
1067 if (flags & 2)
1068 s->Strategy = strategy ;
1069 if (flags & 4) {
1070 s->bufsize = bufsize;
25f0751f 1071 }
1072 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1073#ifdef SETP_BYTE
1074 s->stream.avail_in = 0;
1075 s->stream.next_out = &(s->deflateParams_out_byte) ;
1076 s->stream.avail_out = 1;
1077 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1078 s->deflateParams_out_valid =
1079 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
1080 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1081#else
1082 /* printf("Level %d Strategy %d, Prev Len %d\n",
1083 s->Level, s->Strategy, s->deflateParams_out_length); */
1084 s->stream.avail_in = 0;
1085 if (s->deflateParams_out_buffer == NULL)
1086 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1087 s->stream.next_out = s->deflateParams_out_buffer ;
1088 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1089
1090 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1091 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1092 /* printf("RETVAL %d, length out %d, avail %d\n",
1093 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1094#endif
1095 OUTPUT:
1096 RETVAL
1097
1098
1099int
1100get_Level(s)
1101 Compress::Raw::Zlib::deflateStream s
1102 CODE:
1103 RETVAL = s->Level ;
1104 OUTPUT:
1105 RETVAL
1106
1107int
1108get_Strategy(s)
1109 Compress::Raw::Zlib::deflateStream s
1110 CODE:
1111 RETVAL = s->Strategy ;
1112 OUTPUT:
1113 RETVAL
1114
1115
1116uLong
1117get_Bufsize(s)
1118 Compress::Raw::Zlib::deflateStream s
1119 CODE:
1120 RETVAL = s->bufsize ;
1121 OUTPUT:
1122 RETVAL
1123
1124
1125int
1126status(s)
1127 Compress::Raw::Zlib::deflateStream s
1128 CODE:
1129 RETVAL = s->last_error ;
1130 OUTPUT:
1131 RETVAL
1132
1133uLong
1134crc32(s)
1135 Compress::Raw::Zlib::deflateStream s
1136 CODE:
1137 RETVAL = s->crc32 ;
1138 OUTPUT:
1139 RETVAL
1140
1141uLong
1142dict_adler(s)
1143 Compress::Raw::Zlib::deflateStream s
1144 CODE:
1145 RETVAL = s->dict_adler ;
1146 OUTPUT:
1147 RETVAL
1148
1149uLong
1150adler32(s)
1151 Compress::Raw::Zlib::deflateStream s
1152 CODE:
1153 RETVAL = s->adler32 ;
1154 OUTPUT:
1155 RETVAL
1156
1157uLong
1158compressedBytes(s)
1159 Compress::Raw::Zlib::deflateStream s
1160 CODE:
1161 RETVAL = s->compressedBytes;
1162 OUTPUT:
1163 RETVAL
1164
1165uLong
1166uncompressedBytes(s)
1167 Compress::Raw::Zlib::deflateStream s
1168 CODE:
1169 RETVAL = s->uncompressedBytes;
1170 OUTPUT:
1171 RETVAL
1172
1173uLong
1174total_in(s)
1175 Compress::Raw::Zlib::deflateStream s
1176 CODE:
1177 RETVAL = s->stream.total_in ;
1178 OUTPUT:
1179 RETVAL
1180
1181uLong
1182total_out(s)
1183 Compress::Raw::Zlib::deflateStream s
1184 CODE:
1185 RETVAL = s->stream.total_out ;
1186 OUTPUT:
1187 RETVAL
1188
1189char*
1190msg(s)
1191 Compress::Raw::Zlib::deflateStream s
1192 CODE:
1193 RETVAL = s->stream.msg;
1194 OUTPUT:
1195 RETVAL
1196
1197int
1198deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1199 Compress::Raw::Zlib::deflateStream s
1200 int good_length
1201 int max_lazy
1202 int nice_length
1203 int max_chain
1204 CODE:
1205#ifndef AT_LEAST_ZLIB_1_2_2_3
1206 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1207 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1208 croak("deflateTune needs zlib 1.2.2.3 or better");
1209#else
1210 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1211#endif
1212 OUTPUT:
1213 RETVAL
1214
1215
1216MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream
1217
1218void
1219DispStream(s, message=NULL)
1220 Compress::Raw::Zlib::inflateStream s
1221 char * message
1222
1223DualType
1224inflateReset(s)
1225 Compress::Raw::Zlib::inflateStream s
1226 CODE:
1227 RETVAL = inflateReset(&(s->stream)) ;
1228 if (RETVAL == Z_OK) {
1229 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1230 }
1231 OUTPUT:
1232 RETVAL
1233
1234DualType
1235inflate (s, buf, output, eof=FALSE)
1236 Compress::Raw::Zlib::inflateStream s
1237 SV * buf
1238 SV * output
1239 bool eof
1240 uInt cur_length = 0;
1241 uInt prefix_length = 0;
1242 uInt increment = 0;
1243 STRLEN stmp = NO_INIT
258133d1 1244 uLong bufinc = NO_INIT
25f0751f 1245 PREINIT:
1246#ifdef UTF8_AVAILABLE
1247 bool out_utf8 = FALSE;
1248#endif
1249 CODE:
258133d1 1250 bufinc = s->bufsize;
25f0751f 1251 /* If the buffer is a reference, dereference it */
1252 buf = deRef(buf, "inflate") ;
1253
1254 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
1255 croak("Compress::Raw::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified");
1256#ifdef UTF8_AVAILABLE
1257 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1258 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate input parameter");
1259#endif
1260
1261 /* initialise the input buffer */
1262 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1263 s->stream.avail_in = SvCUR(buf) ;
1264
1265 /* and retrieve the output buffer */
1266 output = deRef_l(output, "inflate") ;
1267#ifdef UTF8_AVAILABLE
1268 if (DO_UTF8(output))
1269 out_utf8 = TRUE ;
1270 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1271 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate output parameter");
1272#endif
1273 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1274 SvCUR_set(output, 0);
1275 }
1276 if (SvLEN(output)) {
1277 prefix_length = cur_length = SvCUR(output) ;
1278 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1279 increment = SvLEN(output) - cur_length - 1;
1280 s->stream.avail_out = increment;
1281 }
1282 else {
1283 s->stream.avail_out = 0;
1284 }
1285 s->bytesInflated = 0;
1286
1287 while (1) {
1288
258133d1 1289 if (s->stream.avail_out == 0 ) {
25f0751f 1290 /* out of space in the output buffer so make it bigger */
258133d1 1291 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1292 cur_length += increment ;
1293 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1294 increment = bufinc ;
25f0751f 1295 s->stream.avail_out = increment;
258133d1 1296 bufinc *= 2 ;
25f0751f 1297 }
1298
1299 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1300
1301 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1302 RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END )
1303 break ;
1304
1305 if (RETVAL == Z_BUF_ERROR) {
1306 if (s->stream.avail_out == 0)
1307 continue ;
1308 if (s->stream.avail_in == 0) {
1309 RETVAL = Z_OK ;
1310 break ;
1311 }
1312 }
1313
1314 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1315 s->dict_adler = s->stream.adler ;
1316 RETVAL = inflateSetDictionary(&(s->stream),
1317 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1318 SvCUR(s->dictionary));
1319 }
1320
1321 if (RETVAL != Z_OK)
1322 break;
1323 }
1324#ifdef NEED_DUMMY_BYTE_AT_END
1325 if (eof && RETVAL == Z_OK) {
1326 Bytef* nextIn = s->stream.next_in;
1327 uInt availIn = s->stream.avail_in;
1328 s->stream.next_in = (Bytef*) " ";
1329 s->stream.avail_in = 1;
1330 if (s->stream.avail_out == 0) {
1331 /* out of space in the output buffer so make it bigger */
258133d1 1332 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1333 cur_length += increment ;
1334 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1335 increment = bufinc ;
25f0751f 1336 s->stream.avail_out = increment;
258133d1 1337 bufinc *= 2 ;
25f0751f 1338 }
1339 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1340 s->stream.next_in = nextIn ;
1341 s->stream.avail_in = availIn ;
1342 }
1343#endif
1344
1345 s->last_error = RETVAL ;
1346 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) {
1347 unsigned in ;
1348
1349 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
1350 s->uncompressedBytes += s->bytesInflated ;
1351 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1352
1353 SvPOK_only(output);
1354 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1355 *SvEND(output) = '\0';
1356#ifdef UTF8_AVAILABLE
1357 if (out_utf8)
1358 sv_utf8_upgrade(output);
1359#endif
4e7676c7 1360 SvSETMAGIC(output);
25f0751f 1361
1362 if (s->flags & FLAG_CRC32 )
1363 s->crc32 = crc32(s->crc32,
1364 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1365 SvCUR(output)-prefix_length) ;
1366
1367 if (s->flags & FLAG_ADLER32)
1368 s->adler32 = adler32(s->adler32,
1369 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1370 SvCUR(output)-prefix_length) ;
1371
1372 /* fix the input buffer */
1373 if (s->flags & FLAG_CONSUME_INPUT) {
1374 in = s->stream.avail_in ;
1375 SvCUR_set(buf, in) ;
1376 if (in)
1377 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1378 *SvEND(buf) = '\0';
1379 SvSETMAGIC(buf);
1380 }
1381 }
1382 OUTPUT:
1383 RETVAL
25f0751f 1384
1385uLong
1386inflateCount(s)
1387 Compress::Raw::Zlib::inflateStream s
1388 CODE:
1389 RETVAL = s->bytesInflated;
1390 OUTPUT:
1391 RETVAL
1392
1393uLong
1394compressedBytes(s)
1395 Compress::Raw::Zlib::inflateStream s
1396 CODE:
1397 RETVAL = s->compressedBytes;
1398 OUTPUT:
1399 RETVAL
1400
1401uLong
1402uncompressedBytes(s)
1403 Compress::Raw::Zlib::inflateStream s
1404 CODE:
1405 RETVAL = s->uncompressedBytes;
1406 OUTPUT:
1407 RETVAL
1408
1409
1410DualType
1411inflateSync (s, buf)
1412 Compress::Raw::Zlib::inflateStream s
1413 SV * buf
1414 CODE:
1415
1416 /* If the buffer is a reference, dereference it */
1417 buf = deRef(buf, "inflateSync") ;
1418#ifdef UTF8_AVAILABLE
1419 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1420 croak("Wide character in Compress::Raw::Zlib::Inflate::inflateSync");
1421#endif
1422
1423 /* initialise the input buffer */
1424 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1425 s->stream.avail_in = SvCUR(buf) ;
1426
1427 /* inflateSync doesn't create any output */
1428 s->stream.next_out = (Bytef*) NULL;
1429 s->stream.avail_out = 0;
1430
1431 RETVAL = inflateSync(&(s->stream));
1432 s->last_error = RETVAL ;
1433
1434 /* fix the input buffer */
1435 {
1436 unsigned in = s->stream.avail_in ;
1437 SvCUR_set(buf, in) ;
1438 if (in)
1439 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1440 *SvEND(buf) = '\0';
1441 SvSETMAGIC(buf);
1442 }
1443 OUTPUT:
1444 RETVAL
25f0751f 1445
1446void
1447DESTROY(s)
1448 Compress::Raw::Zlib::inflateStream s
1449 CODE:
1450 inflateEnd(&s->stream) ;
1451 if (s->dictionary)
1452 SvREFCNT_dec(s->dictionary) ;
1453#ifndef SETP_BYTE
1454 if (s->deflateParams_out_buffer)
1455 Safefree(s->deflateParams_out_buffer);
1456#endif
1457#ifdef MAGIC_APPEND
1458 if (s->window)
1459 Safefree(s->window);
1460#endif
1461 Safefree(s) ;
1462
1463
1464uLong
1465status(s)
1466 Compress::Raw::Zlib::inflateStream s
1467 CODE:
1468 RETVAL = s->last_error ;
1469 OUTPUT:
1470 RETVAL
1471
1472uLong
1473crc32(s)
1474 Compress::Raw::Zlib::inflateStream s
1475 CODE:
1476 RETVAL = s->crc32 ;
1477 OUTPUT:
1478 RETVAL
1479
1480uLong
1481dict_adler(s)
1482 Compress::Raw::Zlib::inflateStream s
1483 CODE:
1484 RETVAL = s->dict_adler ;
1485 OUTPUT:
1486 RETVAL
1487
1488uLong
1489total_in(s)
1490 Compress::Raw::Zlib::inflateStream s
1491 CODE:
1492 RETVAL = s->stream.total_in ;
1493 OUTPUT:
1494 RETVAL
1495
1496uLong
1497adler32(s)
1498 Compress::Raw::Zlib::inflateStream s
1499 CODE:
1500 RETVAL = s->adler32 ;
1501 OUTPUT:
1502 RETVAL
1503
1504uLong
1505total_out(s)
1506 Compress::Raw::Zlib::inflateStream s
1507 CODE:
1508 RETVAL = s->stream.total_out ;
1509 OUTPUT:
1510 RETVAL
1511
1512char*
1513msg(s)
1514 Compress::Raw::Zlib::inflateStream s
1515 CODE:
1516 RETVAL = s->stream.msg;
1517 OUTPUT:
1518 RETVAL
1519
1520
1521uLong
1522get_Bufsize(s)
1523 Compress::Raw::Zlib::inflateStream s
1524 CODE:
1525 RETVAL = s->bufsize ;
1526 OUTPUT:
1527 RETVAL
1528
1529bool
1530set_Append(s, mode)
1531 Compress::Raw::Zlib::inflateStream s
1532 bool mode
1533 CODE:
1534 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1535 if (mode)
1536 s->flags |= FLAG_APPEND ;
1537 else
1538 s->flags &= ~FLAG_APPEND ;
1539 OUTPUT:
1540 RETVAL
1541
1542MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream
1543
1544void
1545DESTROY(s)
1546 Compress::Raw::Zlib::inflateScanStream s
1547 CODE:
1548 inflateEnd(&s->stream) ;
1549 if (s->dictionary)
1550 SvREFCNT_dec(s->dictionary) ;
1551#ifndef SETP_BYTE
1552 if (s->deflateParams_out_buffer)
1553 Safefree(s->deflateParams_out_buffer);
1554#endif
1555#ifdef MAGIC_APPEND
1556 if (s->window)
1557 Safefree(s->window);
1558#endif
1559 Safefree(s) ;
1560
1561void
1562DispStream(s, message=NULL)
1563 Compress::Raw::Zlib::inflateScanStream s
1564 char * message
1565
1566DualType
1567inflateReset(s)
1568 Compress::Raw::Zlib::inflateScanStream s
1569 CODE:
1570 RETVAL = inflateReset(&(s->stream)) ;
1571 if (RETVAL == Z_OK) {
1572 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1573 }
1574 OUTPUT:
1575 RETVAL
1576
1577DualType
1578scan(s, buf, out=NULL, eof=FALSE)
1579 Compress::Raw::Zlib::inflateScanStream s
1580 SV * buf
1581 SV * out
1582 bool eof
1583 bool eof_mode = FALSE;
1584 int start_len = NO_INIT
1585 STRLEN stmp = NO_INIT
1586 CODE:
1587 /* If the input buffer is a reference, dereference it */
1588#ifndef MAGIC_APPEND
1589 buf = buf;
1590 croak("scan needs zlib 1.2.1 or better");
1591#else
1592 buf = deRef(buf, "inflateScan") ;
1593#ifdef UTF8_AVAILABLE
1594 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1595 croak("Wide character in Compress::Raw::Zlib::InflateScan::scan input parameter");
1596#endif
1597 /* initialise the input buffer */
1598 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1599 s->stream.avail_in = SvCUR(buf) ;
1600 start_len = s->stream.avail_in ;
1601 s->bytesInflated = 0 ;
1602 do
1603 {
1604 if (s->stream.avail_in == 0) {
1605 RETVAL = Z_OK ;
1606 break ;
1607 }
1608
1609 /* set up output to next available section of sliding window */
1610 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1611 s->stream.next_out = s->window + s->window_have;
1612
1613 /* DispStream(s, "before inflate\n"); */
1614
1615 /* inflate and check for errors */
1616 RETVAL = inflate(&(s->stream), Z_BLOCK);
1617
1618 if (start_len > 1 && ! eof_mode)
1619 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1620
1621 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1622 RETVAL == Z_DATA_ERROR )
1623 break ;
1624
1625 if (s->flags & FLAG_CRC32 )
1626 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1627 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1628
1629 if (s->flags & FLAG_ADLER32)
1630 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1631 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1632
1633 s->uncompressedBytes =
1634 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1635
1636 if (s->stream.avail_out)
1637 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1638 else {
1639 s->window_have = 0;
1640 s->window_full = 1;
1641 }
1642
1643 /* process end of block */
1644 if (s->stream.data_type & 128) {
1645 if (s->stream.data_type & 64) {
1646 s->window_left = s->stream.data_type & 0x1f;
1647 }
1648 else {
1649 s->window_lastbit = s->stream.data_type & 0x1f;
1650 s->lastBlockOffset = s->stream.total_in;
1651 }
1652 }
1653
1654 } while (RETVAL != Z_STREAM_END);
1655
1656 s->last_error = RETVAL ;
1657 s->window_lastoff = s->stream.total_in ;
1658 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1659
1660 if (RETVAL == Z_STREAM_END)
1661 {
1662 s->matchedEndBlock = 1 ;
1663
1664 /* save the location of the end of the compressed data */
1665 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1666 s->window_endOffset = s->stream.total_in ;
1667 if (s->window_left)
1668 {
1669 -- s->window_endOffset ;
1670 }
1671
1672 /* if window wrapped, build dictionary from window by rotating */
1673 if (s->window_full) {
1674 rotate(s->window, WINDOW_SIZE, s->window_have);
1675 s->window_have = WINDOW_SIZE;
1676 }
1677
1678 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1679 if (1) {
1680 unsigned in = s->stream.avail_in ;
1681 SvCUR_set(buf, in) ;
1682 if (in)
1683 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1684 *SvEND(buf) = '\0';
1685 SvSETMAGIC(buf);
1686 }
1687 }
1688#endif
1689 OUTPUT:
1690 RETVAL
1691
1692
1693uLong
1694getEndOffset(s)
1695 Compress::Raw::Zlib::inflateScanStream s
1696 CODE:
1697#ifndef MAGIC_APPEND
1698 croak("getEndOffset needs zlib 1.2.1 or better");
1699#else
1700 RETVAL = s->window_endOffset;
1701#endif
1702 OUTPUT:
1703 RETVAL
1704
1705uLong
1706inflateCount(s)
1707 Compress::Raw::Zlib::inflateScanStream s
1708 CODE:
1709#ifndef MAGIC_APPEND
1710 croak("inflateCount needs zlib 1.2.1 or better");
1711#else
1712 RETVAL = s->bytesInflated;
1713#endif
1714 OUTPUT:
1715 RETVAL
1716
1717uLong
1718compressedBytes(s)
1719 Compress::Raw::Zlib::inflateScanStream s
1720 CODE:
1721 RETVAL = s->compressedBytes;
1722 OUTPUT:
1723 RETVAL
1724
1725uLong
1726uncompressedBytes(s)
1727 Compress::Raw::Zlib::inflateScanStream s
1728 CODE:
1729 RETVAL = s->uncompressedBytes;
1730 OUTPUT:
1731 RETVAL
1732
1733
1734uLong
1735getLastBlockOffset(s)
1736 Compress::Raw::Zlib::inflateScanStream s
1737 CODE:
1738#ifndef MAGIC_APPEND
1739 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1740#else
1741 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1742#endif
1743 OUTPUT:
1744 RETVAL
1745
1746uLong
1747getLastBufferOffset(s)
1748 Compress::Raw::Zlib::inflateScanStream s
1749 CODE:
1750#ifndef MAGIC_APPEND
1751 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1752#else
1753 RETVAL = s->window_lastoff;
1754#endif
1755 OUTPUT:
1756 RETVAL
1757
1758void
1759resetLastBlockByte(s, byte)
1760 Compress::Raw::Zlib::inflateScanStream s
1761 unsigned char* byte
1762 CODE:
1763#ifndef MAGIC_APPEND
1764 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1765#else
cb7abd7f 1766 if (byte != NULL)
1767 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
25f0751f 1768#endif
1769
1770
1771void
1772_createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1773 Compress::Raw::Zlib::inflateScanStream inf_s
1774 int flags
1775 int level
1776 int method
1777 int windowBits
1778 int memLevel
1779 int strategy
1780 uLong bufsize
1781 PPCODE:
1782 {
1783#ifndef MAGIC_APPEND
1784 flags = flags;
1785 level = level ;
1786 method = method;
1787 windowBits = windowBits;
1788 memLevel = memLevel;
1789 strategy = strategy;
1790 bufsize= bufsize;
1791 croak("_createDeflateStream needs zlib 1.2.1 or better");
1792#else
1793 int err ;
1794 deflateStream s ;
1795
1796 if (trace)
1797 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1798 level, method, windowBits, memLevel, strategy, bufsize) ;
1799 if ((s = InitStream() )) {
1800
1801 s->Level = level;
1802 s->Method = method;
1803 s->WindowBits = windowBits;
1804 s->MemLevel = memLevel;
1805 s->Strategy = strategy;
1806
1807 err = deflateInit2(&(s->stream), level,
1808 method, windowBits, memLevel, strategy);
1809
1810 if (err == Z_OK) {
1811 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1812 s->dict_adler = s->stream.adler ;
1813 }
1814
1815 if (err != Z_OK) {
1816 Safefree(s) ;
1817 s = NULL ;
1818 }
1819 else {
1820 PostInitStream(s, flags, bufsize, windowBits) ;
1821 s->crc32 = inf_s->crc32;
1822 s->adler32 = inf_s->adler32;
1823 s->stream.adler = inf_s->stream.adler ;
1824 /* s->stream.total_out = inf_s->bytesInflated ; */
1825 s->stream.total_in = inf_s->stream.total_out ;
1826 if (inf_s->window_left) {
1827 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1828 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1829 }
1830 }
1831 }
1832 else
1833 err = Z_MEM_ERROR ;
1834
1835 XPUSHs(sv_setref_pv(sv_newmortal(),
1836 "Compress::Raw::Zlib::deflateStream", (void*)s));
1837 if (GIMME == G_ARRAY) {
1838 SV * sv = sv_2mortal(newSViv(err)) ;
1839 setDUALstatus(sv, err);
1840 XPUSHs(sv) ;
1841 }
1842#endif
1843 }
1844
1845DualType
1846status(s)
1847 Compress::Raw::Zlib::inflateScanStream s
1848 CODE:
1849 RETVAL = s->last_error ;
1850 OUTPUT:
1851 RETVAL
1852
1853uLong
1854crc32(s)
1855 Compress::Raw::Zlib::inflateScanStream s
1856 CODE:
1857 RETVAL = s->crc32 ;
1858 OUTPUT:
1859 RETVAL
1860
1861
1862uLong
1863adler32(s)
1864 Compress::Raw::Zlib::inflateScanStream s
1865 CODE:
1866 RETVAL = s->adler32 ;
1867 OUTPUT:
1868 RETVAL
1869