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