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