This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge branch 'blead' of ssh://perl5.git.perl.org/gitroot/perl into blead
[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 *
9b5fd1d4 6 * Copyright (c) 1995-2010 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{
14c55418
A
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
578 if (!SvOK(sv)) {
579 sv = newSVpv("", 0);
580 }
581
582 return sv ;
583}
584
585static SV*
586#ifdef CAN_PROTOTYPE
92905b42 587deRef_l(SV * sv, const char * string)
25f0751f
PM
588#else
589deRef_l(sv, string)
590SV * sv ;
591char * string ;
592#endif
593{
594 dTHX;
595 bool wipe = 0 ;
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
620 SvUPGRADE(sv, SVt_PV);
621
622 if (wipe)
623 SvCUR_set(sv, 0);
624
625 SvOOK_off(sv);
626 SvPOK_only(sv);
627
628 return sv ;
629}
630
631
632#include "constants.h"
633
634MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
635
636REQUIRE: 1.924
637PROTOTYPES: DISABLE
638
639INCLUDE: constants.xs
640
641BOOT:
642 /* Check this version of zlib is == 1 */
643 if (zlibVersion()[0] != '1')
644 croak("Compress::Raw::Zlib needs zlib version 1.x\n") ;
645
646 {
647 /* Create the $os_code scalar */
648 SV * os_code_sv = perl_get_sv("Compress::Raw::Zlib::gzip_os_code", GV_ADDMULTI) ;
649 sv_setiv(os_code_sv, GZIP_OS_CODE) ;
650 }
651
652
d56f7e4c
PM
653#define Zip_zlib_version() (const char*)zlib_version
654const char*
25f0751f
PM
655Zip_zlib_version()
656
657unsigned
658ZLIB_VERNUM()
659 CODE:
660#ifdef ZLIB_VERNUM
661 RETVAL = ZLIB_VERNUM ;
662#else
663 /* 1.1.4 => 0x1140 */
664 RETVAL = (ZLIB_VERSION[0] - '0') << 12 ;
665 RETVAL += (ZLIB_VERSION[2] - '0') << 8 ;
666 RETVAL += (ZLIB_VERSION[4] - '0') << 4 ;
589c1691
CBW
667 if (strlen(ZLIB_VERSION) > 5)
668 RETVAL += (ZLIB_VERSION[6] - '0') ;
25f0751f
PM
669#endif
670 OUTPUT:
671 RETVAL
672
589c1691
CBW
673
674#ifndef AT_LEAST_ZLIB_1_2_1
675#define zlibCompileFlags() 0
676#endif
677uLong
678zlibCompileFlags()
679
25f0751f
PM
680MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_
681
682#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
683
684uLong
685Zip_adler32(buf, adler=adlerInitial)
686 uLong adler = NO_INIT
687 STRLEN len = NO_INIT
688 Bytef * buf = NO_INIT
689 SV * sv = ST(0) ;
690 INIT:
691 /* If the buffer is a reference, dereference it */
692 sv = deRef(sv, "adler32") ;
693#ifdef UTF8_AVAILABLE
694 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
695 croak("Wide character in Compress::Raw::Zlib::adler32");
696#endif
697 buf = (Byte*)SvPVbyte(sv, len) ;
698
699 if (items < 2)
700 adler = adlerInitial;
701 else if (SvOK(ST(1)))
702 adler = SvUV(ST(1)) ;
703 else
704 adler = adlerInitial;
d56f7e4c
PM
705 OUTPUT:
706 RETVAL
25f0751f 707
bc771c2e 708#define Zip_crc32(buf, crc, offset) crc32(crc, buf+offset, (uInt)len-offset)
25f0751f
PM
709
710uLong
bc771c2e 711Zip_crc32(buf, crc=crcInitial, offset=0)
25f0751f
PM
712 uLong crc = NO_INIT
713 STRLEN len = NO_INIT
714 Bytef * buf = NO_INIT
bc771c2e 715 int offset
25f0751f
PM
716 SV * sv = ST(0) ;
717 INIT:
718 /* If the buffer is a reference, dereference it */
719 sv = deRef(sv, "crc32") ;
720#ifdef UTF8_AVAILABLE
721 if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1))
722 croak("Wide character in Compress::Raw::Zlib::crc32");
723#endif
724 buf = (Byte*)SvPVbyte(sv, len) ;
725
726 if (items < 2)
727 crc = crcInitial;
728 else if (SvOK(ST(1)))
729 crc = SvUV(ST(1)) ;
730 else
731 crc = crcInitial;
bc771c2e 732
25f0751f
PM
733uLong
734crc32_combine(crc1, crc2, len2)
735 uLong crc1
736 uLong crc2
737 z_off_t len2
738 CODE:
739#ifndef AT_LEAST_ZLIB_1_2_2_1
740 crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */
741 croak("crc32_combine needs zlib 1.2.3 or better");
742#else
743 RETVAL = crc32_combine(crc1, crc2, len2);
744#endif
745 OUTPUT:
746 RETVAL
747
748
749uLong
750adler32_combine(adler1, adler2, len2)
751 uLong adler1
752 uLong adler2
753 z_off_t len2
754 CODE:
755#ifndef AT_LEAST_ZLIB_1_2_2_1
756 adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */
757 croak("adler32_combine needs zlib 1.2.3 or better");
758#else
759 RETVAL = adler32_combine(adler1, adler2, len2);
760#endif
761 OUTPUT:
762 RETVAL
763
764
765MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib
766
767void
768_deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary)
769 int flags
770 int level
771 int method
772 int windowBits
773 int memLevel
774 int strategy
775 uLong bufsize
776 SV* dictionary
777 PPCODE:
778 int err ;
779 deflateStream s ;
780
d56f7e4c
PM
781 if (trace)
782 warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld dictionary=%p)\n",
783 level, method, windowBits, memLevel, strategy, bufsize, dictionary) ;
25f0751f
PM
784 if ((s = InitStream() )) {
785
786 s->Level = level;
787 s->Method = method;
788 s->WindowBits = windowBits;
789 s->MemLevel = memLevel;
790 s->Strategy = strategy;
791
792 err = deflateInit2(&(s->stream), level,
793 method, windowBits, memLevel, strategy);
794
589c1691
CBW
795 if (trace)
796 warn(" _deflateInit2 returned %d\n", err);
797
25f0751f
PM
798 /* Check if a dictionary has been specified */
799
800 if (err == Z_OK && SvCUR(dictionary)) {
801#ifdef UTF8_AVAILABLE
802 if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1))
803 croak("Wide character in Compress::Raw::Zlib::Deflate::new dicrionary parameter");
804#endif
805 err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary),
806 SvCUR(dictionary)) ;
807 s->dict_adler = s->stream.adler ;
808 }
809
810 if (err != Z_OK) {
811 Safefree(s) ;
812 s = NULL ;
813 }
814 else
815 PostInitStream(s, flags, bufsize, windowBits) ;
816
817 }
818 else
819 err = Z_MEM_ERROR ;
820
d56f7e4c
PM
821 {
822 SV* obj = sv_setref_pv(sv_newmortal(),
823 "Compress::Raw::Zlib::deflateStream", (void*)s);
824 XPUSHs(obj);
825 }
25f0751f
PM
826 if (GIMME == G_ARRAY) {
827 SV * sv = sv_2mortal(newSViv(err)) ;
828 setDUALstatus(sv, err);
829 XPUSHs(sv) ;
830 }
831
832void
833_inflateInit(flags, windowBits, bufsize, dictionary)
834 int flags
835 int windowBits
836 uLong bufsize
837 SV * dictionary
838 ALIAS:
839 _inflateScanInit = 1
840 PPCODE:
841
842 int err = Z_OK ;
843 inflateStream s ;
844#ifndef MAGIC_APPEND
845 if (ix == 1)
846 croak("inflateScanInit needs zlib 1.2.1 or better");
847#endif
848 if (trace)
849 warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n",
850 windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ;
851 if ((s = InitStream() )) {
852
853 s->WindowBits = windowBits;
854
855 err = inflateInit2(&(s->stream), windowBits);
856 if (err != Z_OK) {
857 Safefree(s) ;
858 s = NULL ;
859 }
860 else if (SvCUR(dictionary)) {
e11a3f9e
PM
861#ifdef AT_LEAST_ZLIB_1_2_2_1
862 /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */
863 if (s->WindowBits < 0) {
864 err = inflateSetDictionary(&(s->stream),
865 (const Bytef*)SvPVbyte_nolen(dictionary),
866 SvCUR(dictionary));
867 if (err != Z_OK) {
868 Safefree(s) ;
869 s = NULL ;
870 }
871 }
872 else
873#endif
25f0751f
PM
874 /* Dictionary specified - take a copy for use in inflate */
875 s->dictionary = newSVsv(dictionary) ;
876 }
877 if (s) {
878 PostInitStream(s, flags, bufsize, windowBits) ;
879#ifdef MAGIC_APPEND
880 if (ix == 1)
881 {
882 s->window = (unsigned char *)safemalloc(WINDOW_SIZE);
883 }
884#endif
885 }
886 }
887 else
888 err = Z_MEM_ERROR ;
889
d56f7e4c
PM
890 {
891 SV* obj = sv_setref_pv(sv_newmortal(),
25f0751f
PM
892 ix == 1
893 ? "Compress::Raw::Zlib::inflateScanStream"
894 : "Compress::Raw::Zlib::inflateStream",
d56f7e4c
PM
895 (void*)s);
896 XPUSHs(obj);
897 }
25f0751f
PM
898 if (GIMME == G_ARRAY) {
899 SV * sv = sv_2mortal(newSViv(err)) ;
900 setDUALstatus(sv, err);
901 XPUSHs(sv) ;
902 }
903
904
905
906MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream
907
908void
909DispStream(s, message=NULL)
910 Compress::Raw::Zlib::deflateStream s
911 char * message
912
913DualType
914deflateReset(s)
915 Compress::Raw::Zlib::deflateStream s
916 CODE:
917 RETVAL = deflateReset(&(s->stream)) ;
918 if (RETVAL == Z_OK) {
919 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
920 }
921 OUTPUT:
922 RETVAL
923
924DualType
925deflate (s, buf, output)
926 Compress::Raw::Zlib::deflateStream s
927 SV * buf
928 SV * output
929 uInt cur_length = NO_INIT
930 uInt increment = NO_INIT
931 uInt prefix = NO_INIT
932 int RETVAL = 0;
258133d1 933 uLong bufinc = NO_INIT
25f0751f 934 CODE:
258133d1 935 bufinc = s->bufsize;
25f0751f
PM
936
937 /* If the input buffer is a reference, dereference it */
938 buf = deRef(buf, "deflate") ;
939
940 /* initialise the input buffer */
941#ifdef UTF8_AVAILABLE
942 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
943 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter");
944#endif
945 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
946 s->stream.avail_in = SvCUR(buf) ;
947
948 if (s->flags & FLAG_CRC32)
949 s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ;
950
951 if (s->flags & FLAG_ADLER32)
952 s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ;
953
954 /* and retrieve the output buffer */
955 output = deRef_l(output, "deflate") ;
956#ifdef UTF8_AVAILABLE
957 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
958 croak("Wide character in Compress::Raw::Zlib::Deflate::deflate output parameter");
959#endif
960
961 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
962 SvCUR_set(output, 0);
963 /* sv_setpvn(output, "", 0); */
964 }
965 prefix = cur_length = SvCUR(output) ;
966 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
967 increment = SvLEN(output) - cur_length;
968 s->stream.avail_out = increment;
969#ifdef SETP_BYTE
970 /* Check for saved output from deflateParams */
971 if (s->deflateParams_out_valid) {
972 *(s->stream.next_out) = s->deflateParams_out_byte;
973 ++ s->stream.next_out;
974 -- s->stream.avail_out ;
975 s->deflateParams_out_valid = FALSE;
976 }
977#else
978 /* Check for saved output from deflateParams */
979 if (s->deflateParams_out_length) {
980 uLong plen = s->deflateParams_out_length ;
981 /* printf("Copy %d bytes saved data\n", plen);*/
982 if (s->stream.avail_out < plen) {
983 /*printf("GROW from %d to %d\n", s->stream.avail_out,
984 SvLEN(output) + plen - s->stream.avail_out); */
985 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
986 }
987
988 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
989 cur_length = cur_length + plen;
990 SvCUR_set(output, cur_length);
991 s->stream.next_out += plen ;
992 s->stream.avail_out = SvLEN(output) - cur_length ;
993 increment = s->stream.avail_out;
994 s->deflateParams_out_length = 0;
995 }
996#endif
997 while (s->stream.avail_in != 0) {
998
999 if (s->stream.avail_out == 0) {
1000 /* out of space in the output buffer so make it bigger */
258133d1 1001 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f
PM
1002 cur_length += increment ;
1003 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1004 increment = bufinc ;
25f0751f 1005 s->stream.avail_out = increment;
258133d1 1006 bufinc *= 2 ;
25f0751f
PM
1007 }
1008
1009 RETVAL = deflate(&(s->stream), Z_NO_FLUSH);
1010 if (RETVAL != Z_OK)
1011 break;
1012 }
1013
1014 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1015 s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ;
1016
1017 s->last_error = RETVAL ;
1018 if (RETVAL == Z_OK) {
1019 SvPOK_only(output);
1020 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
4e7676c7 1021 SvSETMAGIC(output);
25f0751f
PM
1022 }
1023 OUTPUT:
1024 RETVAL
25f0751f
PM
1025
1026
1027void
1028DESTROY(s)
1029 Compress::Raw::Zlib::deflateStream s
1030 CODE:
1031 deflateEnd(&s->stream) ;
1032 if (s->dictionary)
1033 SvREFCNT_dec(s->dictionary) ;
1034#ifndef SETP_BYTE
1035 if (s->deflateParams_out_buffer)
1036 Safefree(s->deflateParams_out_buffer);
1037#endif
1038 Safefree(s) ;
1039
1040
1041DualType
1042flush(s, output, f=Z_FINISH)
1043 Compress::Raw::Zlib::deflateStream s
1044 SV * output
1045 int f
1046 uInt cur_length = NO_INIT
1047 uInt increment = NO_INIT
1048 uInt prefix = NO_INIT
258133d1 1049 uLong bufinc = NO_INIT
589c1691 1050 uLong availableout = NO_INIT
25f0751f 1051 CODE:
258133d1 1052 bufinc = s->bufsize;
25f0751f
PM
1053
1054 s->stream.avail_in = 0; /* should be zero already anyway */
1055
1056 /* retrieve the output buffer */
1057 output = deRef_l(output, "flush") ;
1058#ifdef UTF8_AVAILABLE
1059 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1060 croak("Wide character in Compress::Raw::Zlib::Deflate::flush input parameter");
1061#endif
1062 if(! s->flags & FLAG_APPEND) {
1063 SvCUR_set(output, 0);
1064 /* sv_setpvn(output, "", 0); */
1065 }
1066 prefix = cur_length = SvCUR(output) ;
1067 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1068 increment = SvLEN(output) - cur_length;
1069 s->stream.avail_out = increment;
1070#ifdef SETP_BYTE
1071 /* Check for saved output from deflateParams */
1072 if (s->deflateParams_out_valid) {
1073 *(s->stream.next_out) = s->deflateParams_out_byte;
1074 ++ s->stream.next_out;
1075 -- s->stream.avail_out ;
1076 s->deflateParams_out_valid = FALSE;
1077 }
1078#else
1079 /* Check for saved output from deflateParams */
1080 if (s->deflateParams_out_length) {
1081 uLong plen = s->deflateParams_out_length ;
1082 /* printf("Copy %d bytes saved data\n", plen); */
1083 if (s->stream.avail_out < plen) {
1084 /* printf("GROW from %d to %d\n", s->stream.avail_out,
1085 SvLEN(output) + plen - s->stream.avail_out); */
1086 Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ;
1087 }
1088
1089 Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ;
1090 cur_length = cur_length + plen;
1091 SvCUR_set(output, cur_length);
1092 s->stream.next_out += plen ;
1093 s->stream.avail_out = SvLEN(output) - cur_length ;
1094 increment = s->stream.avail_out;
1095 s->deflateParams_out_length = 0;
1096 }
1097#endif
1098
1099 for (;;) {
589c1691
CBW
1100 if (s->stream.avail_out == 0) {
1101 /* consumed all the available output, so extend it */
258133d1 1102 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f
PM
1103 cur_length += increment ;
1104 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1105 increment = bufinc ;
25f0751f 1106 s->stream.avail_out = increment;
258133d1 1107 bufinc *= 2 ;
25f0751f 1108 }
589c1691
CBW
1109
1110 availableout = s->stream.avail_out ;
1111
25f0751f
PM
1112 RETVAL = deflate(&(s->stream), f);
1113
589c1691
CBW
1114 /* Ignore the second of two consecutive flushes: */
1115 if (availableout == s->stream.avail_out && RETVAL == Z_BUF_ERROR)
1116 RETVAL = Z_OK;
1117
25f0751f
PM
1118 /* deflate has finished flushing only when it hasn't used up
1119 * all the available space in the output buffer:
1120 */
1121 if (s->stream.avail_out != 0 || RETVAL != Z_OK )
1122 break;
1123 }
1124
1125 RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ;
1126 s->last_error = RETVAL ;
1127
1128 s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ;
1129
1130 if (RETVAL == Z_OK) {
1131 SvPOK_only(output);
1132 SvCUR_set(output, cur_length + increment - s->stream.avail_out) ;
4e7676c7 1133 SvSETMAGIC(output);
25f0751f
PM
1134 }
1135 OUTPUT:
1136 RETVAL
25f0751f
PM
1137
1138
1139DualType
1140_deflateParams(s, flags, level, strategy, bufsize)
1141 Compress::Raw::Zlib::deflateStream s
1142 int flags
1143 int level
1144 int strategy
1145 uLong bufsize
1146 CODE:
1147 /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize);
1148 printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */
1149 if (flags & 1)
1150 s->Level = level ;
1151 if (flags & 2)
1152 s->Strategy = strategy ;
1153 if (flags & 4) {
1154 s->bufsize = bufsize;
25f0751f
PM
1155 }
1156 /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/
1157#ifdef SETP_BYTE
1158 s->stream.avail_in = 0;
1159 s->stream.next_out = &(s->deflateParams_out_byte) ;
1160 s->stream.avail_out = 1;
1161 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1162 s->deflateParams_out_valid =
1163 (RETVAL == Z_OK && s->stream.avail_out == 0) ;
1164 /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */
1165#else
1166 /* printf("Level %d Strategy %d, Prev Len %d\n",
1167 s->Level, s->Strategy, s->deflateParams_out_length); */
1168 s->stream.avail_in = 0;
1169 if (s->deflateParams_out_buffer == NULL)
1170 s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE);
1171 s->stream.next_out = s->deflateParams_out_buffer ;
1172 s->stream.avail_out = deflateParams_BUFFER_SIZE;
1173
1174 RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
1175 s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out;
1176 /* printf("RETVAL %d, length out %d, avail %d\n",
1177 RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */
1178#endif
1179 OUTPUT:
1180 RETVAL
1181
1182
1183int
1184get_Level(s)
1185 Compress::Raw::Zlib::deflateStream s
1186 CODE:
1187 RETVAL = s->Level ;
1188 OUTPUT:
1189 RETVAL
1190
1191int
1192get_Strategy(s)
1193 Compress::Raw::Zlib::deflateStream s
1194 CODE:
1195 RETVAL = s->Strategy ;
1196 OUTPUT:
1197 RETVAL
1198
1199
1200uLong
1201get_Bufsize(s)
1202 Compress::Raw::Zlib::deflateStream s
1203 CODE:
1204 RETVAL = s->bufsize ;
1205 OUTPUT:
1206 RETVAL
1207
1208
1209int
1210status(s)
1211 Compress::Raw::Zlib::deflateStream s
1212 CODE:
1213 RETVAL = s->last_error ;
1214 OUTPUT:
1215 RETVAL
1216
1217uLong
1218crc32(s)
1219 Compress::Raw::Zlib::deflateStream s
1220 CODE:
1221 RETVAL = s->crc32 ;
1222 OUTPUT:
1223 RETVAL
1224
1225uLong
1226dict_adler(s)
1227 Compress::Raw::Zlib::deflateStream s
1228 CODE:
1229 RETVAL = s->dict_adler ;
1230 OUTPUT:
1231 RETVAL
1232
1233uLong
1234adler32(s)
1235 Compress::Raw::Zlib::deflateStream s
1236 CODE:
1237 RETVAL = s->adler32 ;
1238 OUTPUT:
1239 RETVAL
1240
1241uLong
1242compressedBytes(s)
1243 Compress::Raw::Zlib::deflateStream s
1244 CODE:
1245 RETVAL = s->compressedBytes;
1246 OUTPUT:
1247 RETVAL
1248
1249uLong
1250uncompressedBytes(s)
1251 Compress::Raw::Zlib::deflateStream s
1252 CODE:
1253 RETVAL = s->uncompressedBytes;
1254 OUTPUT:
1255 RETVAL
1256
1257uLong
1258total_in(s)
1259 Compress::Raw::Zlib::deflateStream s
1260 CODE:
1261 RETVAL = s->stream.total_in ;
1262 OUTPUT:
1263 RETVAL
1264
1265uLong
1266total_out(s)
1267 Compress::Raw::Zlib::deflateStream s
1268 CODE:
1269 RETVAL = s->stream.total_out ;
1270 OUTPUT:
1271 RETVAL
1272
1273char*
1274msg(s)
1275 Compress::Raw::Zlib::deflateStream s
1276 CODE:
1277 RETVAL = s->stream.msg;
1278 OUTPUT:
1279 RETVAL
1280
1281int
1282deflateTune(s, good_length, max_lazy, nice_length, max_chain)
1283 Compress::Raw::Zlib::deflateStream s
1284 int good_length
1285 int max_lazy
1286 int nice_length
1287 int max_chain
1288 CODE:
1289#ifndef AT_LEAST_ZLIB_1_2_2_3
1290 good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */
1291 nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */
1292 croak("deflateTune needs zlib 1.2.2.3 or better");
1293#else
1294 RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain);
1295#endif
1296 OUTPUT:
1297 RETVAL
1298
1299
1300MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream
1301
1302void
1303DispStream(s, message=NULL)
1304 Compress::Raw::Zlib::inflateStream s
1305 char * message
1306
1307DualType
1308inflateReset(s)
1309 Compress::Raw::Zlib::inflateStream s
1310 CODE:
1311 RETVAL = inflateReset(&(s->stream)) ;
1312 if (RETVAL == Z_OK) {
1313 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1314 }
1315 OUTPUT:
1316 RETVAL
1317
1318DualType
1319inflate (s, buf, output, eof=FALSE)
1320 Compress::Raw::Zlib::inflateStream s
1321 SV * buf
1322 SV * output
1323 bool eof
1324 uInt cur_length = 0;
1325 uInt prefix_length = 0;
319fab50 1326 int increment = 0;
25f0751f 1327 STRLEN stmp = NO_INIT
258133d1 1328 uLong bufinc = NO_INIT
25f0751f
PM
1329 PREINIT:
1330#ifdef UTF8_AVAILABLE
1331 bool out_utf8 = FALSE;
1332#endif
1333 CODE:
258133d1 1334 bufinc = s->bufsize;
25f0751f
PM
1335 /* If the buffer is a reference, dereference it */
1336 buf = deRef(buf, "inflate") ;
1337
1338 if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf))
1339 croak("Compress::Raw::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified");
1340#ifdef UTF8_AVAILABLE
1341 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1342 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate input parameter");
1343#endif
1344
1345 /* initialise the input buffer */
1346 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1347 s->stream.avail_in = SvCUR(buf) ;
1348
1349 /* and retrieve the output buffer */
1350 output = deRef_l(output, "inflate") ;
1351#ifdef UTF8_AVAILABLE
1352 if (DO_UTF8(output))
1353 out_utf8 = TRUE ;
1354 if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1))
1355 croak("Wide character in Compress::Raw::Zlib::Inflate::inflate output parameter");
1356#endif
1357 if((s->flags & FLAG_APPEND) != FLAG_APPEND) {
1358 SvCUR_set(output, 0);
1359 }
319fab50
PM
1360
1361 /* Assume no output buffer - the code below will update if there is any available */
1362 s->stream.avail_out = 0;
1363
1364
25f0751f
PM
1365 if (SvLEN(output)) {
1366 prefix_length = cur_length = SvCUR(output) ;
319fab50
PM
1367
1368 if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc)
1369 {
1370 Sv_Grow(output, bufinc + cur_length + 1) ;
1371 }
1372
1373 /* Only setup the stream output pointers if there is spare
1374 capacity in the outout SV
1375 */
1376 if (SvLEN(output) > cur_length + 1)
1377 {
1378 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length;
1379 increment = SvLEN(output) - cur_length - 1;
1380 s->stream.avail_out = increment;
1381 }
25f0751f 1382 }
319fab50
PM
1383
1384
25f0751f
PM
1385 s->bytesInflated = 0;
1386
e11a3f9e 1387 RETVAL = Z_OK;
25f0751f 1388
e11a3f9e 1389 while (RETVAL == Z_OK) {
319fab50 1390 if (s->stream.avail_out == 0) {
25f0751f 1391 /* out of space in the output buffer so make it bigger */
7efcbeef 1392 Sv_Grow(output, SvLEN(output) + bufinc +1) ;
25f0751f
PM
1393 cur_length += increment ;
1394 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1395 increment = bufinc ;
25f0751f 1396 s->stream.avail_out = increment;
258133d1 1397 bufinc *= 2 ;
25f0751f
PM
1398 }
1399
319fab50
PM
1400 /* printf("INFLATE Availl In %d, Out %d\n", s->stream.avail_in,
1401 s->stream.avail_out);
1402DispStream(s, "BEFORE");
1403Perl_sv_dump(output); */
25f0751f 1404 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
319fab50
PM
1405 /* printf("INFLATE returned %d %s, avail in %d, out %d\n", RETVAL,
1406 GetErrorString(RETVAL), s->stream.avail_in, s->stream.avail_out); */
25f0751f 1407
9253672d
SH
1408
1409 if (RETVAL == Z_NEED_DICT && s->dictionary) {
1410 s->dict_adler = s->stream.adler ;
1411 RETVAL = inflateSetDictionary(&(s->stream),
1412 (const Bytef*)SvPVbyte_nolen(s->dictionary),
1413 SvCUR(s->dictionary));
319fab50
PM
1414 if (RETVAL == Z_OK)
1415 continue;
9253672d
SH
1416 }
1417
319fab50
PM
1418 if (s->flags & FLAG_LIMIT_OUTPUT &&
1419 (RETVAL == Z_OK || RETVAL == Z_BUF_ERROR ))
1420 break;
1421
1422 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1423 RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END )
25f0751f
PM
1424 break ;
1425
1426 if (RETVAL == Z_BUF_ERROR) {
1427 if (s->stream.avail_out == 0)
1428 continue ;
1429 if (s->stream.avail_in == 0) {
1430 RETVAL = Z_OK ;
1431 break ;
1432 }
1433 }
25f0751f
PM
1434 }
1435#ifdef NEED_DUMMY_BYTE_AT_END
9253672d 1436 if (eof && RETVAL == Z_OK && s->flags & FLAG_LIMIT_OUTPUT == 0) {
25f0751f
PM
1437 Bytef* nextIn = s->stream.next_in;
1438 uInt availIn = s->stream.avail_in;
1439 s->stream.next_in = (Bytef*) " ";
1440 s->stream.avail_in = 1;
1441 if (s->stream.avail_out == 0) {
1442 /* out of space in the output buffer so make it bigger */
258133d1 1443 Sv_Grow(output, SvLEN(output) + bufinc) ;
25f0751f
PM
1444 cur_length += increment ;
1445 s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ;
258133d1 1446 increment = bufinc ;
25f0751f 1447 s->stream.avail_out = increment;
258133d1 1448 bufinc *= 2 ;
25f0751f
PM
1449 }
1450 RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH);
1451 s->stream.next_in = nextIn ;
1452 s->stream.avail_in = availIn ;
1453 }
1454#endif
1455
1456 s->last_error = RETVAL ;
319fab50
PM
1457 if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_BUF_ERROR || RETVAL == Z_DATA_ERROR) {
1458 unsigned in ;
25f0751f
PM
1459
1460 s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length;
1461 s->uncompressedBytes += s->bytesInflated ;
1462 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1463
1464 SvPOK_only(output);
1465 SvCUR_set(output, prefix_length + s->bytesInflated) ;
1466 *SvEND(output) = '\0';
1467#ifdef UTF8_AVAILABLE
1468 if (out_utf8)
1469 sv_utf8_upgrade(output);
1470#endif
4e7676c7 1471 SvSETMAGIC(output);
25f0751f
PM
1472
1473 if (s->flags & FLAG_CRC32 )
1474 s->crc32 = crc32(s->crc32,
1475 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1476 SvCUR(output)-prefix_length) ;
1477
1478 if (s->flags & FLAG_ADLER32)
1479 s->adler32 = adler32(s->adler32,
1480 (const Bytef*)SvPVbyte_nolen(output)+prefix_length,
1481 SvCUR(output)-prefix_length) ;
1482
1483 /* fix the input buffer */
9253672d 1484 if (s->flags & FLAG_CONSUME_INPUT || s->flags & FLAG_LIMIT_OUTPUT) {
25f0751f
PM
1485 in = s->stream.avail_in ;
1486 SvCUR_set(buf, in) ;
1487 if (in)
1488 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1489 *SvEND(buf) = '\0';
1490 SvSETMAGIC(buf);
1491 }
319fab50 1492
25f0751f
PM
1493 }
1494 OUTPUT:
1495 RETVAL
25f0751f
PM
1496
1497uLong
1498inflateCount(s)
1499 Compress::Raw::Zlib::inflateStream s
1500 CODE:
1501 RETVAL = s->bytesInflated;
1502 OUTPUT:
1503 RETVAL
1504
1505uLong
1506compressedBytes(s)
1507 Compress::Raw::Zlib::inflateStream s
1508 CODE:
1509 RETVAL = s->compressedBytes;
1510 OUTPUT:
1511 RETVAL
1512
1513uLong
1514uncompressedBytes(s)
1515 Compress::Raw::Zlib::inflateStream s
1516 CODE:
1517 RETVAL = s->uncompressedBytes;
1518 OUTPUT:
1519 RETVAL
1520
1521
1522DualType
1523inflateSync (s, buf)
1524 Compress::Raw::Zlib::inflateStream s
1525 SV * buf
1526 CODE:
1527
1528 /* If the buffer is a reference, dereference it */
1529 buf = deRef(buf, "inflateSync") ;
1530#ifdef UTF8_AVAILABLE
1531 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1532 croak("Wide character in Compress::Raw::Zlib::Inflate::inflateSync");
1533#endif
1534
1535 /* initialise the input buffer */
1536 s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ;
1537 s->stream.avail_in = SvCUR(buf) ;
1538
1539 /* inflateSync doesn't create any output */
1540 s->stream.next_out = (Bytef*) NULL;
1541 s->stream.avail_out = 0;
1542
1543 RETVAL = inflateSync(&(s->stream));
1544 s->last_error = RETVAL ;
1545
1546 /* fix the input buffer */
1547 {
1548 unsigned in = s->stream.avail_in ;
1549 SvCUR_set(buf, in) ;
1550 if (in)
1551 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1552 *SvEND(buf) = '\0';
1553 SvSETMAGIC(buf);
1554 }
1555 OUTPUT:
1556 RETVAL
25f0751f
PM
1557
1558void
1559DESTROY(s)
1560 Compress::Raw::Zlib::inflateStream s
1561 CODE:
1562 inflateEnd(&s->stream) ;
1563 if (s->dictionary)
1564 SvREFCNT_dec(s->dictionary) ;
1565#ifndef SETP_BYTE
1566 if (s->deflateParams_out_buffer)
1567 Safefree(s->deflateParams_out_buffer);
1568#endif
1569#ifdef MAGIC_APPEND
1570 if (s->window)
1571 Safefree(s->window);
1572#endif
1573 Safefree(s) ;
1574
1575
1576uLong
1577status(s)
1578 Compress::Raw::Zlib::inflateStream s
1579 CODE:
1580 RETVAL = s->last_error ;
1581 OUTPUT:
1582 RETVAL
1583
1584uLong
1585crc32(s)
1586 Compress::Raw::Zlib::inflateStream s
1587 CODE:
1588 RETVAL = s->crc32 ;
1589 OUTPUT:
1590 RETVAL
1591
1592uLong
1593dict_adler(s)
1594 Compress::Raw::Zlib::inflateStream s
1595 CODE:
1596 RETVAL = s->dict_adler ;
1597 OUTPUT:
1598 RETVAL
1599
1600uLong
1601total_in(s)
1602 Compress::Raw::Zlib::inflateStream s
1603 CODE:
1604 RETVAL = s->stream.total_in ;
1605 OUTPUT:
1606 RETVAL
1607
1608uLong
1609adler32(s)
1610 Compress::Raw::Zlib::inflateStream s
1611 CODE:
1612 RETVAL = s->adler32 ;
1613 OUTPUT:
1614 RETVAL
1615
1616uLong
1617total_out(s)
1618 Compress::Raw::Zlib::inflateStream s
1619 CODE:
1620 RETVAL = s->stream.total_out ;
1621 OUTPUT:
1622 RETVAL
1623
1624char*
1625msg(s)
1626 Compress::Raw::Zlib::inflateStream s
1627 CODE:
1628 RETVAL = s->stream.msg;
1629 OUTPUT:
1630 RETVAL
1631
1632
1633uLong
1634get_Bufsize(s)
1635 Compress::Raw::Zlib::inflateStream s
1636 CODE:
1637 RETVAL = s->bufsize ;
1638 OUTPUT:
1639 RETVAL
1640
1641bool
1642set_Append(s, mode)
1643 Compress::Raw::Zlib::inflateStream s
1644 bool mode
1645 CODE:
1646 RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND);
1647 if (mode)
1648 s->flags |= FLAG_APPEND ;
1649 else
1650 s->flags &= ~FLAG_APPEND ;
1651 OUTPUT:
1652 RETVAL
1653
1654MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream
1655
1656void
1657DESTROY(s)
1658 Compress::Raw::Zlib::inflateScanStream s
1659 CODE:
1660 inflateEnd(&s->stream) ;
1661 if (s->dictionary)
1662 SvREFCNT_dec(s->dictionary) ;
1663#ifndef SETP_BYTE
1664 if (s->deflateParams_out_buffer)
1665 Safefree(s->deflateParams_out_buffer);
1666#endif
1667#ifdef MAGIC_APPEND
1668 if (s->window)
1669 Safefree(s->window);
1670#endif
1671 Safefree(s) ;
1672
1673void
1674DispStream(s, message=NULL)
1675 Compress::Raw::Zlib::inflateScanStream s
1676 char * message
1677
1678DualType
1679inflateReset(s)
1680 Compress::Raw::Zlib::inflateScanStream s
1681 CODE:
1682 RETVAL = inflateReset(&(s->stream)) ;
1683 if (RETVAL == Z_OK) {
1684 PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ;
1685 }
1686 OUTPUT:
1687 RETVAL
1688
1689DualType
1690scan(s, buf, out=NULL, eof=FALSE)
1691 Compress::Raw::Zlib::inflateScanStream s
1692 SV * buf
1693 SV * out
1694 bool eof
1695 bool eof_mode = FALSE;
1696 int start_len = NO_INIT
1697 STRLEN stmp = NO_INIT
1698 CODE:
1699 /* If the input buffer is a reference, dereference it */
1700#ifndef MAGIC_APPEND
1701 buf = buf;
1702 croak("scan needs zlib 1.2.1 or better");
1703#else
1704 buf = deRef(buf, "inflateScan") ;
1705#ifdef UTF8_AVAILABLE
1706 if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1))
1707 croak("Wide character in Compress::Raw::Zlib::InflateScan::scan input parameter");
1708#endif
1709 /* initialise the input buffer */
1710 s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ;
1711 s->stream.avail_in = SvCUR(buf) ;
1712 start_len = s->stream.avail_in ;
1713 s->bytesInflated = 0 ;
1714 do
1715 {
1716 if (s->stream.avail_in == 0) {
1717 RETVAL = Z_OK ;
1718 break ;
1719 }
1720
1721 /* set up output to next available section of sliding window */
1722 s->stream.avail_out = WINDOW_SIZE - s->window_have;
1723 s->stream.next_out = s->window + s->window_have;
1724
1725 /* DispStream(s, "before inflate\n"); */
1726
1727 /* inflate and check for errors */
1728 RETVAL = inflate(&(s->stream), Z_BLOCK);
1729
1730 if (start_len > 1 && ! eof_mode)
1731 s->window_lastByte = *(s->stream.next_in - 1 ) ;
1732
1733 if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR ||
1734 RETVAL == Z_DATA_ERROR )
1735 break ;
1736
1737 if (s->flags & FLAG_CRC32 )
1738 s->crc32 = crc32(s->crc32, s->window + s->window_have,
1739 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1740
1741 if (s->flags & FLAG_ADLER32)
1742 s->adler32 = adler32(s->adler32, s->window + s->window_have,
1743 WINDOW_SIZE - s->window_have - s->stream.avail_out);
1744
1745 s->uncompressedBytes =
1746 s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out;
1747
1748 if (s->stream.avail_out)
1749 s->window_have = WINDOW_SIZE - s->stream.avail_out;
1750 else {
1751 s->window_have = 0;
1752 s->window_full = 1;
1753 }
1754
1755 /* process end of block */
1756 if (s->stream.data_type & 128) {
1757 if (s->stream.data_type & 64) {
1758 s->window_left = s->stream.data_type & 0x1f;
1759 }
1760 else {
1761 s->window_lastbit = s->stream.data_type & 0x1f;
1762 s->lastBlockOffset = s->stream.total_in;
1763 }
1764 }
1765
1766 } while (RETVAL != Z_STREAM_END);
1767
1768 s->last_error = RETVAL ;
1769 s->window_lastoff = s->stream.total_in ;
1770 s->compressedBytes += SvCUR(buf) - s->stream.avail_in ;
1771
1772 if (RETVAL == Z_STREAM_END)
1773 {
1774 s->matchedEndBlock = 1 ;
1775
1776 /* save the location of the end of the compressed data */
1777 s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ;
1778 s->window_endOffset = s->stream.total_in ;
1779 if (s->window_left)
1780 {
1781 -- s->window_endOffset ;
1782 }
1783
1784 /* if window wrapped, build dictionary from window by rotating */
1785 if (s->window_full) {
1786 rotate(s->window, WINDOW_SIZE, s->window_have);
1787 s->window_have = WINDOW_SIZE;
1788 }
1789
1790 /* if (s->flags & FLAG_CONSUME_INPUT) { */
1791 if (1) {
1792 unsigned in = s->stream.avail_in ;
1793 SvCUR_set(buf, in) ;
1794 if (in)
1795 Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ;
1796 *SvEND(buf) = '\0';
1797 SvSETMAGIC(buf);
1798 }
1799 }
1800#endif
1801 OUTPUT:
1802 RETVAL
1803
1804
1805uLong
1806getEndOffset(s)
1807 Compress::Raw::Zlib::inflateScanStream s
1808 CODE:
1809#ifndef MAGIC_APPEND
1810 croak("getEndOffset needs zlib 1.2.1 or better");
1811#else
1812 RETVAL = s->window_endOffset;
1813#endif
1814 OUTPUT:
1815 RETVAL
1816
1817uLong
1818inflateCount(s)
1819 Compress::Raw::Zlib::inflateScanStream s
1820 CODE:
1821#ifndef MAGIC_APPEND
1822 croak("inflateCount needs zlib 1.2.1 or better");
1823#else
1824 RETVAL = s->bytesInflated;
1825#endif
1826 OUTPUT:
1827 RETVAL
1828
1829uLong
1830compressedBytes(s)
1831 Compress::Raw::Zlib::inflateScanStream s
1832 CODE:
1833 RETVAL = s->compressedBytes;
1834 OUTPUT:
1835 RETVAL
1836
1837uLong
1838uncompressedBytes(s)
1839 Compress::Raw::Zlib::inflateScanStream s
1840 CODE:
1841 RETVAL = s->uncompressedBytes;
1842 OUTPUT:
1843 RETVAL
1844
1845
1846uLong
1847getLastBlockOffset(s)
1848 Compress::Raw::Zlib::inflateScanStream s
1849 CODE:
1850#ifndef MAGIC_APPEND
1851 croak("getLastBlockOffset needs zlib 1.2.1 or better");
1852#else
1853 RETVAL = s->lastBlockOffset - (s->window_lastbit != 0);
1854#endif
1855 OUTPUT:
1856 RETVAL
1857
1858uLong
1859getLastBufferOffset(s)
1860 Compress::Raw::Zlib::inflateScanStream s
1861 CODE:
1862#ifndef MAGIC_APPEND
1863 croak("getLastBufferOffset needs zlib 1.2.1 or better");
1864#else
1865 RETVAL = s->window_lastoff;
1866#endif
1867 OUTPUT:
1868 RETVAL
1869
1870void
1871resetLastBlockByte(s, byte)
1872 Compress::Raw::Zlib::inflateScanStream s
1873 unsigned char* byte
1874 CODE:
1875#ifndef MAGIC_APPEND
1876 croak("resetLastBlockByte needs zlib 1.2.1 or better");
1877#else
cb7abd7f
PM
1878 if (byte != NULL)
1879 *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7));
25f0751f
PM
1880#endif
1881
1882
1883void
1884_createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize)
1885 Compress::Raw::Zlib::inflateScanStream inf_s
1886 int flags
1887 int level
1888 int method
1889 int windowBits
1890 int memLevel
1891 int strategy
1892 uLong bufsize
1893 PPCODE:
1894 {
1895#ifndef MAGIC_APPEND
1896 flags = flags;
1897 level = level ;
1898 method = method;
1899 windowBits = windowBits;
1900 memLevel = memLevel;
1901 strategy = strategy;
1902 bufsize= bufsize;
1903 croak("_createDeflateStream needs zlib 1.2.1 or better");
1904#else
1905 int err ;
1906 deflateStream s ;
1907
1908 if (trace)
1909 warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n",
1910 level, method, windowBits, memLevel, strategy, bufsize) ;
1911 if ((s = InitStream() )) {
1912
1913 s->Level = level;
1914 s->Method = method;
1915 s->WindowBits = windowBits;
1916 s->MemLevel = memLevel;
1917 s->Strategy = strategy;
1918
1919 err = deflateInit2(&(s->stream), level,
1920 method, windowBits, memLevel, strategy);
1921
1922 if (err == Z_OK) {
1923 err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have);
1924 s->dict_adler = s->stream.adler ;
1925 }
1926
1927 if (err != Z_OK) {
1928 Safefree(s) ;
1929 s = NULL ;
1930 }
1931 else {
1932 PostInitStream(s, flags, bufsize, windowBits) ;
1933 s->crc32 = inf_s->crc32;
1934 s->adler32 = inf_s->adler32;
1935 s->stream.adler = inf_s->stream.adler ;
1936 /* s->stream.total_out = inf_s->bytesInflated ; */
1937 s->stream.total_in = inf_s->stream.total_out ;
1938 if (inf_s->window_left) {
1939 /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */
1940 deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte);
1941 }
1942 }
1943 }
1944 else
1945 err = Z_MEM_ERROR ;
1946
1947 XPUSHs(sv_setref_pv(sv_newmortal(),
1948 "Compress::Raw::Zlib::deflateStream", (void*)s));
1949 if (GIMME == G_ARRAY) {
1950 SV * sv = sv_2mortal(newSViv(err)) ;
1951 setDUALstatus(sv, err);
1952 XPUSHs(sv) ;
1953 }
1954#endif
1955 }
1956
1957DualType
1958status(s)
1959 Compress::Raw::Zlib::inflateScanStream s
1960 CODE:
1961 RETVAL = s->last_error ;
1962 OUTPUT:
1963 RETVAL
1964
1965uLong
1966crc32(s)
1967 Compress::Raw::Zlib::inflateScanStream s
1968 CODE:
1969 RETVAL = s->crc32 ;
1970 OUTPUT:
1971 RETVAL
1972
1973
1974uLong
1975adler32(s)
1976 Compress::Raw::Zlib::inflateScanStream s
1977 CODE:
1978 RETVAL = s->adler32 ;
1979 OUTPUT:
1980 RETVAL
1981