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