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