Call SvMAGICAL_off in mg_free
[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
d54256af 231//static const char * const my_z_errmsg[] = {
232static const char my_z_errmsg[][32] = {
25f0751f 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
92905b42 514deRef(SV * sv, const char * string)
25f0751f 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
92905b42 546deRef_l(SV * sv, const char * string)
25f0751f 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
d56f7e4c 610#define Zip_zlib_version() (const char*)zlib_version
611const char*
25f0751f 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;
d56f7e4c 653 OUTPUT:
654 RETVAL
25f0751f 655
656#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
657
658uLong
659Zip_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
681uLong
682crc32_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
697uLong
698adler32_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
713MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib
714
715void
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
d56f7e4c 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) ;
25f0751f 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
d56f7e4c 766 {
767 SV* obj = sv_setref_pv(sv_newmortal(),
768 "Compress::Raw::Zlib::deflateStream", (void*)s);
769 XPUSHs(obj);
770 }
25f0751f 771 if (GIMME == G_ARRAY) {
772 SV * sv = sv_2mortal(newSViv(err)) ;
773 setDUALstatus(sv, err);
774 XPUSHs(sv) ;
775 }
776
777void
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
d56f7e4c 822 {
823 SV* obj = sv_setref_pv(sv_newmortal(),
25f0751f 824 ix == 1
825 ? "Compress::Raw::Zlib::inflateScanStream"
826 : "Compress::Raw::Zlib::inflateStream",
d56f7e4c 827 (void*)s);
828 XPUSHs(obj);
829 }
25f0751f 830 if (GIMME == G_ARRAY) {
831 SV * sv = sv_2mortal(newSViv(err)) ;
832 setDUALstatus(sv, err);
833 XPUSHs(sv) ;
834 }
835
836
837
838MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream
839
840void
841DispStream(s, message=NULL)
842 Compress::Raw::Zlib::deflateStream s
843 char * message
844
845DualType
846deflateReset(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
856DualType
857deflate (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;
258133d1 865 uLong bufinc = NO_INIT
25f0751f 866 CODE:
258133d1 867 bufinc = s->bufsize;
25f0751f 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 */
258133d1 933 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 934 cur_length += increment ;
935 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 936 increment = bufinc ;
25f0751f 937 s->stream.avail_out = increment;
258133d1 938 bufinc *= 2 ;
25f0751f 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) ;
4e7676c7 953 SvSETMAGIC(output);
25f0751f 954 }
955 OUTPUT:
956 RETVAL
25f0751f 957
958
959void
960DESTROY(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
973DualType
974flush(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
258133d1 981 uLong bufinc = NO_INIT
25f0751f 982 CODE:
258133d1 983 bufinc = s->bufsize;
25f0751f 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 */
258133d1 1033 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1034 cur_length += increment ;
1035 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1036 increment = bufinc ;
25f0751f 1037 s->stream.avail_out = increment;
258133d1 1038 bufinc *= 2 ;
25f0751f 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) ;
4e7676c7 1057 SvSETMAGIC(output);
25f0751f 1058 }
1059 OUTPUT:
1060 RETVAL
25f0751f 1061
1062
1063DualType
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;
25f0751f 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
1107int
1108get_Level(s)
1109 Compress::Raw::Zlib::deflateStream s
1110 CODE:
1111 RETVAL = s->Level ;
1112 OUTPUT:
1113 RETVAL
1114
1115int
1116get_Strategy(s)
1117 Compress::Raw::Zlib::deflateStream s
1118 CODE:
1119 RETVAL = s->Strategy ;
1120 OUTPUT:
1121 RETVAL
1122
1123
1124uLong
1125get_Bufsize(s)
1126 Compress::Raw::Zlib::deflateStream s
1127 CODE:
1128 RETVAL = s->bufsize ;
1129 OUTPUT:
1130 RETVAL
1131
1132
1133int
1134status(s)
1135 Compress::Raw::Zlib::deflateStream s
1136 CODE:
1137 RETVAL = s->last_error ;
1138 OUTPUT:
1139 RETVAL
1140
1141uLong
1142crc32(s)
1143 Compress::Raw::Zlib::deflateStream s
1144 CODE:
1145 RETVAL = s->crc32 ;
1146 OUTPUT:
1147 RETVAL
1148
1149uLong
1150dict_adler(s)
1151 Compress::Raw::Zlib::deflateStream s
1152 CODE:
1153 RETVAL = s->dict_adler ;
1154 OUTPUT:
1155 RETVAL
1156
1157uLong
1158adler32(s)
1159 Compress::Raw::Zlib::deflateStream s
1160 CODE:
1161 RETVAL = s->adler32 ;
1162 OUTPUT:
1163 RETVAL
1164
1165uLong
1166compressedBytes(s)
1167 Compress::Raw::Zlib::deflateStream s
1168 CODE:
1169 RETVAL = s->compressedBytes;
1170 OUTPUT:
1171 RETVAL
1172
1173uLong
1174uncompressedBytes(s)
1175 Compress::Raw::Zlib::deflateStream s
1176 CODE:
1177 RETVAL = s->uncompressedBytes;
1178 OUTPUT:
1179 RETVAL
1180
1181uLong
1182total_in(s)
1183 Compress::Raw::Zlib::deflateStream s
1184 CODE:
1185 RETVAL = s->stream.total_in ;
1186 OUTPUT:
1187 RETVAL
1188
1189uLong
1190total_out(s)
1191 Compress::Raw::Zlib::deflateStream s
1192 CODE:
1193 RETVAL = s->stream.total_out ;
1194 OUTPUT:
1195 RETVAL
1196
1197char*
1198msg(s)
1199 Compress::Raw::Zlib::deflateStream s
1200 CODE:
1201 RETVAL = s->stream.msg;
1202 OUTPUT:
1203 RETVAL
1204
1205int
1206deflateTune(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
1224MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream
1225
1226void
1227DispStream(s, message=NULL)
1228 Compress::Raw::Zlib::inflateStream s
1229 char * message
1230
1231DualType
1232inflateReset(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
1242DualType
1243inflate (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
258133d1 1252 uLong bufinc = NO_INIT
25f0751f 1253 PREINIT:
1254#ifdef UTF8_AVAILABLE
1255 bool out_utf8 = FALSE;
1256#endif
1257 CODE:
258133d1 1258 bufinc = s->bufsize;
25f0751f 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
258133d1 1297 if (s->stream.avail_out == 0 ) {
25f0751f 1298 /* out of space in the output buffer so make it bigger */
258133d1 1299 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1300 cur_length += increment ;
1301 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1302 increment = bufinc ;
25f0751f 1303 s->stream.avail_out = increment;
258133d1 1304 bufinc *= 2 ;
25f0751f 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 */
258133d1 1340 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f 1341 cur_length += increment ;
1342 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1343 increment = bufinc ;
25f0751f 1344 s->stream.avail_out = increment;
258133d1 1345 bufinc *= 2 ;
25f0751f 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
4e7676c7 1368 SvSETMAGIC(output);
25f0751f 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
25f0751f 1392
1393uLong
1394inflateCount(s)
1395 Compress::Raw::Zlib::inflateStream s
1396 CODE:
1397 RETVAL = s->bytesInflated;
1398 OUTPUT:
1399 RETVAL
1400
1401uLong
1402compressedBytes(s)
1403 Compress::Raw::Zlib::inflateStream s
1404 CODE:
1405 RETVAL = s->compressedBytes;
1406 OUTPUT:
1407 RETVAL
1408
1409uLong
1410uncompressedBytes(s)
1411 Compress::Raw::Zlib::inflateStream s
1412 CODE:
1413 RETVAL = s->uncompressedBytes;
1414 OUTPUT:
1415 RETVAL
1416
1417
1418DualType
1419inflateSync (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
25f0751f 1453
1454void
1455DESTROY(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
1472uLong
1473status(s)
1474 Compress::Raw::Zlib::inflateStream s
1475 CODE:
1476 RETVAL = s->last_error ;
1477 OUTPUT:
1478 RETVAL
1479
1480uLong
1481crc32(s)
1482 Compress::Raw::Zlib::inflateStream s
1483 CODE:
1484 RETVAL = s->crc32 ;
1485 OUTPUT:
1486 RETVAL
1487
1488uLong
1489dict_adler(s)
1490 Compress::Raw::Zlib::inflateStream s
1491 CODE:
1492 RETVAL = s->dict_adler ;
1493 OUTPUT:
1494 RETVAL
1495
1496uLong
1497total_in(s)
1498 Compress::Raw::Zlib::inflateStream s
1499 CODE:
1500 RETVAL = s->stream.total_in ;
1501 OUTPUT:
1502 RETVAL
1503
1504uLong
1505adler32(s)
1506 Compress::Raw::Zlib::inflateStream s
1507 CODE:
1508 RETVAL = s->adler32 ;
1509 OUTPUT:
1510 RETVAL
1511
1512uLong
1513total_out(s)
1514 Compress::Raw::Zlib::inflateStream s
1515 CODE:
1516 RETVAL = s->stream.total_out ;
1517 OUTPUT:
1518 RETVAL
1519
1520char*
1521msg(s)
1522 Compress::Raw::Zlib::inflateStream s
1523 CODE:
1524 RETVAL = s->stream.msg;
1525 OUTPUT:
1526 RETVAL
1527
1528
1529uLong
1530get_Bufsize(s)
1531 Compress::Raw::Zlib::inflateStream s
1532 CODE:
1533 RETVAL = s->bufsize ;
1534 OUTPUT:
1535 RETVAL
1536
1537bool
1538set_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
1550MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream
1551
1552void
1553DESTROY(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
1569void
1570DispStream(s, message=NULL)
1571 Compress::Raw::Zlib::inflateScanStream s
1572 char * message
1573
1574DualType
1575inflateReset(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
1585DualType
1586scan(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
1701uLong
1702getEndOffset(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
1713uLong
1714inflateCount(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
1725uLong
1726compressedBytes(s)
1727 Compress::Raw::Zlib::inflateScanStream s
1728 CODE:
1729 RETVAL = s->compressedBytes;
1730 OUTPUT:
1731 RETVAL
1732
1733uLong
1734uncompressedBytes(s)
1735 Compress::Raw::Zlib::inflateScanStream s
1736 CODE:
1737 RETVAL = s->uncompressedBytes;
1738 OUTPUT:
1739 RETVAL
1740
1741
1742uLong
1743getLastBlockOffset(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
1754uLong
1755getLastBufferOffset(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
1766void
1767resetLastBlockByte(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
cb7abd7f 1774 if (byte != NULL)
1775 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
25f0751f 1776#endif
1777
1778
1779void
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
1853DualType
1854status(s)
1855 Compress::Raw::Zlib::inflateScanStream s
1856 CODE:
1857 RETVAL = s->last_error ;
1858 OUTPUT:
1859 RETVAL
1860
1861uLong
1862crc32(s)
1863 Compress::Raw::Zlib::inflateScanStream s
1864 CODE:
1865 RETVAL = s->crc32 ;
1866 OUTPUT:
1867 RETVAL
1868
1869
1870uLong
1871adler32(s)
1872 Compress::Raw::Zlib::inflateScanStream s
1873 CODE:
1874 RETVAL = s->adler32 ;
1875 OUTPUT:
1876 RETVAL
1877