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