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