Compress-Raw-Zlib-2.023 (omitting changes to private/MakeUtil.pm) (omitting changes to perl-5.10.0/t/lib/compress; these are in IO-Compress-Base 2.015 update) diff -urN perl-5.10.0.orig/MANIFEST perl-5.10.0/MANIFEST --- perl-5.10.0.orig/MANIFEST 2009-12-01 14:46:37.000000000 +0100 +++ perl-5.10.0/MANIFEST 2009-12-01 15:43:34.000000000 +0100 @@ -124,6 +124,7 @@ ext/Compress/Raw/Zlib/t/01version.t Compress::Raw::Zlib ext/Compress/Raw/Zlib/t/02zlib.t Compress::Raw::Zlib ext/Compress/Raw/Zlib/t/07bufsize.t Compress::Raw::Zlib +ext/Compress/Raw/Zlib/t/09limitoutput.t Compress::Raw::Zlib ext/Compress/Raw/Zlib/t/18lvalue.t Compress::Raw::Zlib ext/Compress/Raw/Zlib/typemap Compress::Raw::Zlib ext/Compress/Raw/Zlib/zlib-src/adler32.c Compress::Raw::Zlib diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/Changes perl-5.10.0/ext/Compress/Raw/Zlib/Changes --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/Changes 2009-12-01 15:36:07.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/Changes 2009-12-01 15:38:24.000000000 +0100 @@ -1,6 +1,73 @@ CHANGES ------- + 2.023 9 November 2009 + + * fixed instance where $[ should have been $] in t/02zlib.t + Thanks to Robin Barker and zefram [RT #50765] for independantly + spotting the issue. + + 2.021 30 August 2009 + + * Changed test harness so that it can cope with PERL5OPT=-MCarp=verbose + [RT# 47225] + + 2.020 3 June 2009 + + * Minor documentation update. + + 2.019 4 May 2009 + + * No Changes + + 2.018 3 May 2009 + + * No Changes + + 2.017 28 March 2009 + + * Added 'LimitOutput' option + + * Removed MAN3PODS from Makefile.PL + + * Fixed coring issue when LimitOutput was used. + + * Documented Compress::Raw::Zlib::zlib_version() + + * Documented Compress::Raw::Zlib::deflateReset() + [RT #40566] + + 2.015 3 September 2008 + + * Makefile.PL + Backout changes made in 2.014 + + 2.014 2 September 2008 + + * Makefile.PL + Updated to check for indirect dependencies. + + 2.012 15 July 2008 + + * Document the gzip flags that WindowBits can take. + + * Allow a dictionary to be used with a raw inflate. + Needs zlib 1.2.2.1 or better. + [RT #36046] + + 2.011 5 May 2008 + + * A C++-style comment sneaked in with the last update. Fixed. + [core patch #33828] + + 2.010 5 May 2008 + + * No Changes + + 2.009 20 April 2008 + + * No Changes + 2.008 2 November 2007 * Minor documentation changes in README diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/Makefile.PL perl-5.10.0/ext/Compress/Raw/Zlib/Makefile.PL --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/Makefile.PL 2009-12-01 14:47:16.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/Makefile.PL 2009-12-01 15:38:24.000000000 +0100 @@ -77,24 +77,11 @@ }, ( - $ENV{SKIP_FOR_CORE} - ? (MAN3PODS => {}) - : () - ), - - ( $BUILD_ZLIB ? zlib_files($ZLIB_LIB) : (LIBS => [ "-L$ZLIB_LIB -lz " ]) ), - ( - $] >= 5.005 - ? (ABSTRACT_FROM => 'lib/Compress/Raw/Zlib.pm', - AUTHOR => 'Paul Marquess ') - : () - ), - INSTALLDIRS => ($] >= 5.009 ? 'perl' : 'site'), ((ExtUtils::MakeMaker->VERSION() gt '6.30') ? diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/README perl-5.10.0/ext/Compress/Raw/Zlib/README --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/README 2009-12-01 15:36:07.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/README 2009-12-01 15:38:24.000000000 +0100 @@ -1,16 +1,14 @@ Compress-Raw-Zlib - Version 2.008 + Version 2.023 - 2nd November 2007 + 9th November 2009 - - Copyright (c) 2005-2007 Paul Marquess. All rights reserved. + Copyright (c) 2005-2009 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. - The directory zlib-src contains a subset of the source files copied directly from zlib version 1.2.3. These files are Copyright(C) 1995-2005 @@ -18,39 +16,27 @@ Full source for the zlib library is available at http://www.zlib.org - - DESCRIPTION ----------- - This module provides a Perl interface to the zlib compression library. - - - - PREREQUISITES ------------- Before you can build Compress-Raw-Zlib you need to have the following installed on your system: - * A C compiler * Perl 5.004 or better. - - By default, Compress-Raw-Zlib will build its own private copy of the zlib library. If you want to use a different version of zlib, follow the instructions in the section called "Controlling the version of zlib used by Compress-Raw-Zlib" later in this document. - - BUILDING THE MODULE ------------------- @@ -61,8 +47,6 @@ make make test - - INSTALLATION ------------ @@ -70,9 +54,6 @@ make install - - - Controlling the version of zlib used by Compress-Raw-Zlib ---------------------------------------------------------- @@ -92,7 +73,6 @@ Note that if you intend to use either Option 2 or 3, you need to have zlib version 1.0.5 or better. - The contents of the file config.in are used to control which of the three options is actually used. This file is read during the @@ -101,8 +81,6 @@ step of the build, so remember to make any required changes to config.in before building this module. - - Option 1 -------- @@ -169,10 +147,9 @@ ------------------------ Every gzip stream stores a byte in its header to identify the Operating -System that was used to create the gzip stream. When you build -Compress-Raw-Zlib it will attempt to determine the value that is correct for -your Operating System. This will then be used by IO::Gzip as the default -value for the OS byte in all gzip headers it creates. +System that was used to create the gzip stream. When you build Compress-Raw-Zlib it will attempt to determine the value that is correct for +your Operating System. This will then be used by IO::Compress::Gzip as the +default value for the OS byte in all gzip headers it creates. The variable GZIP_OS_CODE in the config.in file controls the setting of this value when building Compress-Raw-Zlib. If GZIP_OS_CODE is set to @@ -197,16 +174,37 @@ detected is incorrect, please take a few moments to contact the author of this module. - - TROUBLESHOOTING --------------- +Undefined Symbol gzsetparams +---------------------------- +If you get the error shown below when you run the Compress-Raw-Zlib test +harness it probably means you are running a copy of zlib that is +version 1.0.5 or older. +t/01version.........Can't load 'blib/arch/auto/Compress/Zlib/Zlib.so' for + module Compress::Raw::Zlib: blib/arch/auto/Compress/Raw/Zlib/Zlib.so: + undefined symbol: gzsetparams at ... +There are two ways to fix this problem: + 1. Upgrade to the latest version of zlib. + 2. Edit config.in and set the OLD_ZLIB variable to True. + +Test Harness 01version fails +---------------------------- +If the 01version test harness fails, and the problem isn't covered by the +scenario above, it probably means that you have two versions of +zlib installed on your system. + +Run the command below to see if this is indeed the case + + make test TEST_VERBOSE=1 TEST_FILES=t/01version.t + +Try removing the one you don't want to use and rebuild. Solaris build fails with "language optional software package not installed" --------------------------------------------------------------------------- @@ -245,9 +243,6 @@ If that doesn't work for you, it's time to make changes to the Makefile by hand. Good luck! - - - Solaris build fails with "gcc: unrecognized option `-KPIC'" ----------------------------------------------------------- @@ -285,10 +280,6 @@ is necessary to have first built the zlib library with the -fpic option. - - - - Linux Notes ----------- @@ -307,9 +298,6 @@ for zlib. Check for an RPM that start with "zlib-devel" in your Linux distribution. - - - Win32 Notes ----------- @@ -318,15 +306,11 @@ newer version of Compress-Raw-Zlib is available run this from the command prompt - C:\> ppm verify -upgrade Compress-Zlib - + C:\> ppm verify -upgrade Compress-Raw-Zlib If you are not running Activestate Perl and you don't have access to a C compiler, you will not be able to build and install this module. - - - Win32 & Cygwin Notes -------------------- @@ -338,7 +322,6 @@ The workaround is to install Compress-Raw-Zlib manually using the instructions given at the start of this file. - FEEDBACK -------- @@ -372,8 +355,7 @@ If you haven't installed Compress-Raw-Zlib then search Compress::Raw::Zlib.pm for a line like this: - $VERSION = "2.008" ; - + $VERSION = "2.023" ; c. The version of zlib you have used. If you have successfully installed Compress-Raw-Zlib, this one-liner @@ -381,10 +363,8 @@ perl -MCompress::Raw::Zlib -e "print q[zlib ver ]. Compress::Raw::Zlib::ZLIB_VERSION.qq[\n]" - If not, look at the beginning of the file zlib.h. - 2. If you are having problems building Compress-Raw-Zlib, send me a complete log of what happened. Start by unpacking the Compress-Raw-Zlib module into a fresh directory and keep a log of all the steps @@ -394,5 +374,4 @@ make make test TEST_VERBOSE=1 - Paul Marquess diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/Zlib.xs perl-5.10.0/ext/Compress/Raw/Zlib/Zlib.xs --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/Zlib.xs 2009-12-01 15:36:07.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/Zlib.xs 2009-12-01 15:38:24.000000000 +0100 @@ -3,7 +3,7 @@ * Created : 22nd January 1996 * Version : 2.000 * - * Copyright (c) 1995-2007 Paul Marquess. All rights reserved. + * Copyright (c) 1995-2009 Paul Marquess. All rights reserved. * This program is free software; you can redistribute it and/or * modify it under the same terms as Perl itself. * @@ -50,6 +50,10 @@ # define AT_LEAST_ZLIB_1_2_2_1 #endif +#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1222 +# define AT_LEAST_ZLIB_1_2_2_2 +#endif + #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223 # define AT_LEAST_ZLIB_1_2_2_3 #endif @@ -64,6 +68,11 @@ # include "ppport.h" #endif +#if PERL_REVISION == 5 && PERL_VERSION == 9 + /* For Andreas */ +# define sv_pvbyte_force(sv,lp) sv_pvbyten_force(sv,lp) +#endif + #if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) # ifdef SvPVbyte_force @@ -103,6 +112,7 @@ #define FLAG_CRC32 2 #define FLAG_ADLER32 4 #define FLAG_CONSUME_INPUT 8 +#define FLAG_LIMIT_OUTPUT 16 uLong crc32 ; uLong adler32 ; z_stream stream; @@ -228,7 +238,8 @@ #define adlerInitial adler32(0L, Z_NULL, 0) #define crcInitial crc32(0L, Z_NULL, 0) -static const char * const my_z_errmsg[] = { +/* static const char * const my_z_errmsg[] = { */ +static const char my_z_errmsg[][32] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ @@ -460,6 +471,8 @@ printf(" CRC32 %s\n", EnDis(FLAG_CRC32)); printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32)); printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT)); + printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT)); + #ifdef MAGIC_APPEND printf(" window 0x%p\n", s->window); @@ -510,7 +523,7 @@ static SV* #ifdef CAN_PROTOTYPE -deRef(SV * sv, char * string) +deRef(SV * sv, const char * string) #else deRef(sv, string) SV * sv ; @@ -528,6 +541,8 @@ case SVt_PVHV: case SVt_PVCV: croak("%s: buffer parameter is not a SCALAR reference", string); + default: + break; } if (SvROK(sv)) croak("%s: buffer parameter is a reference to a reference", string) ; @@ -542,7 +557,7 @@ static SV* #ifdef CAN_PROTOTYPE -deRef_l(SV * sv, char * string) +deRef_l(SV * sv, const char * string) #else deRef_l(sv, string) SV * sv ; @@ -565,6 +580,8 @@ case SVt_PVHV: case SVt_PVCV: croak("%s: buffer parameter is not a SCALAR reference", string); + default: + break; } if (SvROK(sv)) croak("%s: buffer parameter is a reference to a reference", string) ; @@ -802,6 +819,19 @@ s = NULL ; } else if (SvCUR(dictionary)) { +#ifdef AT_LEAST_ZLIB_1_2_2_1 + /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */ + if (s->WindowBits < 0) { + err = inflateSetDictionary(&(s->stream), + (const Bytef*)SvPVbyte_nolen(dictionary), + SvCUR(dictionary)); + if (err != Z_OK) { + Safefree(s) ; + s = NULL ; + } + } + else +#endif /* Dictionary specified - take a copy for use in inflate */ s->dictionary = newSVsv(dictionary) ; } @@ -1246,7 +1276,7 @@ bool eof uInt cur_length = 0; uInt prefix_length = 0; - uInt increment = 0; + int increment = 0; STRLEN stmp = NO_INIT uLong bufinc = NO_INIT PREINIT: @@ -1280,22 +1310,39 @@ if((s->flags & FLAG_APPEND) != FLAG_APPEND) { SvCUR_set(output, 0); } + + /* Assume no output buffer - the code below will update if there is any available */ + s->stream.avail_out = 0; + + if (SvLEN(output)) { prefix_length = cur_length = SvCUR(output) ; - s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; - increment = SvLEN(output) - cur_length - 1; - s->stream.avail_out = increment; - } - else { - s->stream.avail_out = 0; + + if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) + { + Sv_Grow(output, bufinc + cur_length + 1) ; + } + + /* Only setup the stream output pointers if there is spare + capacity in the outout SV + */ + if (SvLEN(output) > cur_length + 1) + { + s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; + increment = SvLEN(output) - cur_length - 1; + s->stream.avail_out = increment; + } } + + s->bytesInflated = 0; - while (1) { + RETVAL = Z_OK; - if (s->stream.avail_out == 0 ) { + while (RETVAL == Z_OK) { + if (s->stream.avail_out == 0) { /* out of space in the output buffer so make it bigger */ - Sv_Grow(output, SvLEN(output) + bufinc) ; + Sv_Grow(output, SvLEN(output) + bufinc +1) ; cur_length += increment ; s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; increment = bufinc ; @@ -1303,10 +1350,30 @@ bufinc *= 2 ; } + /* printf("INFLATE Availl In %d, Out %d\n", s->stream.avail_in, + s->stream.avail_out); +DispStream(s, "BEFORE"); +Perl_sv_dump(output); */ RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH); + /* printf("INFLATE returned %d %s, avail in %d, out %d\n", RETVAL, + GetErrorString(RETVAL), s->stream.avail_in, s->stream.avail_out); */ + + + if (RETVAL == Z_NEED_DICT && s->dictionary) { + s->dict_adler = s->stream.adler ; + RETVAL = inflateSetDictionary(&(s->stream), + (const Bytef*)SvPVbyte_nolen(s->dictionary), + SvCUR(s->dictionary)); + if (RETVAL == Z_OK) + continue; + } + + if (s->flags & FLAG_LIMIT_OUTPUT && + (RETVAL == Z_OK || RETVAL == Z_BUF_ERROR )) + break; if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR || - RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END ) + RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END ) break ; if (RETVAL == Z_BUF_ERROR) { @@ -1317,19 +1384,9 @@ break ; } } - - if (RETVAL == Z_NEED_DICT && s->dictionary) { - s->dict_adler = s->stream.adler ; - RETVAL = inflateSetDictionary(&(s->stream), - (const Bytef*)SvPVbyte_nolen(s->dictionary), - SvCUR(s->dictionary)); - } - - if (RETVAL != Z_OK) - break; } #ifdef NEED_DUMMY_BYTE_AT_END - if (eof && RETVAL == Z_OK) { + if (eof && RETVAL == Z_OK && s->flags & FLAG_LIMIT_OUTPUT == 0) { Bytef* nextIn = s->stream.next_in; uInt availIn = s->stream.avail_in; s->stream.next_in = (Bytef*) " "; @@ -1350,8 +1407,8 @@ #endif s->last_error = RETVAL ; - if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_DATA_ERROR) { - unsigned in ; + if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_BUF_ERROR || RETVAL == Z_DATA_ERROR) { + unsigned in ; s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; s->uncompressedBytes += s->bytesInflated ; @@ -1377,7 +1434,7 @@ SvCUR(output)-prefix_length) ; /* fix the input buffer */ - if (s->flags & FLAG_CONSUME_INPUT) { + if (s->flags & FLAG_CONSUME_INPUT || s->flags & FLAG_LIMIT_OUTPUT) { in = s->stream.avail_in ; SvCUR_set(buf, in) ; if (in) @@ -1385,6 +1442,7 @@ *SvEND(buf) = '\0'; SvSETMAGIC(buf); } + } OUTPUT: RETVAL diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm perl-5.10.0/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm 2009-12-01 15:36:07.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm 2009-12-01 15:38:24.000000000 +0100 @@ -13,7 +13,7 @@ use bytes ; our ($VERSION, $XS_VERSION, @ISA, @EXPORT, $AUTOLOAD); -$VERSION = '2.008'; +$VERSION = '2.023'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -62,8 +62,13 @@ Z_SYNC_FLUSH Z_UNKNOWN Z_VERSION_ERROR + + WANT_GZIP + WANT_GZIP_OR_ZLIB ); +use constant WANT_GZIP => 16; +use constant WANT_GZIP_OR_ZLIB => 32; sub AUTOLOAD { my($constname); @@ -79,6 +84,7 @@ use constant FLAG_CRC => 2 ; use constant FLAG_ADLER => 4 ; use constant FLAG_CONSUME_INPUT => 8 ; +use constant FLAG_LIMIT_OUTPUT => 16 ; eval { require XSLoader; @@ -361,10 +367,14 @@ $flags |= FLAG_CRC if $got->value('CRC32') ; $flags |= FLAG_ADLER if $got->value('ADLER32') ; + my $windowBits = $got->value('WindowBits'); + $windowBits += MAX_WBITS() + if ($windowBits & MAX_WBITS()) == 0 ; + _deflateInit($flags, $got->value('Level'), $got->value('Method'), - $got->value('WindowBits'), + $windowBits, $got->value('MemLevel'), $got->value('Strategy'), $got->value('Bufsize'), @@ -378,6 +388,7 @@ my ($got) = ParseParameters(0, { 'AppendOutput' => [1, 1, Parse_boolean, 0], + 'LimitOutput' => [1, 1, Parse_boolean, 0], 'CRC32' => [1, 1, Parse_boolean, 0], 'ADLER32' => [1, 1, Parse_boolean, 0], 'ConsumeInput' => [1, 1, Parse_boolean, 1], @@ -397,8 +408,14 @@ $flags |= FLAG_CRC if $got->value('CRC32') ; $flags |= FLAG_ADLER if $got->value('ADLER32') ; $flags |= FLAG_CONSUME_INPUT if $got->value('ConsumeInput') ; + $flags |= FLAG_LIMIT_OUTPUT if $got->value('LimitOutput') ; + + + my $windowBits = $got->value('WindowBits'); + $windowBits += MAX_WBITS() + if ($windowBits & MAX_WBITS()) == 0 ; - _inflateInit($flags, $got->value('WindowBits'), $got->value('Bufsize'), + _inflateInit($flags, $windowBits, $got->value('Bufsize'), $got->value('Dictionary')) ; } @@ -530,6 +547,7 @@ ($d, $status) = new Compress::Raw::Zlib::Deflate( [OPT] ) ; $status = $d->deflate($input, $output) ; $status = $d->flush($output [, $flush_type]) ; + $d->deflateReset() ; $d->deflateParams(OPTS) ; $d->deflateTune(OPTS) ; $d->dict_adler() ; @@ -559,8 +577,7 @@ $crc = adler32_combine($crc1, $crc2, $len2)l $crc = crc32_combine($adler1, $adler2, $len2) - ZLIB_VERSION - ZLIB_VERNUM + my $version = Compress::Raw::Zlib::zlib_version(); =head1 DESCRIPTION @@ -568,8 +585,6 @@ compression library (see L for details about where to get I). - - =head1 Compress::Raw::Zlib::Deflate This section defines an interface that allows in-memory compression using @@ -577,7 +592,6 @@ Here is a definition of the interface available: - =head2 B<($d, $status) = new Compress::Raw::Zlib::Deflate( [OPT] ) > Initialises a deflation object. @@ -610,7 +624,7 @@ C, C, C, and C. -The default is Z_DEFAULT_COMPRESSION. +The default is C. =item B<-Method> @@ -619,10 +633,18 @@ =item B<-WindowBits> +To compress an RFC 1950 data stream, set C to a positive +number between 8 and 15. + +To compress an RFC 1951 data stream, set C to C<-MAX_WBITS>. + +To compress an RFC 1952 data stream (i.e. gzip), set C to +C. + For a definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to MAX_WBITS. +Defaults to C. =item B<-MemLevel> @@ -678,7 +700,6 @@ This option defaults to false. - =item B<-ADLER32> If set to true, an adler32 checksum of the uncompressed data will be @@ -686,7 +707,6 @@ This option defaults to false. - =back Here is an example of using the C optional @@ -696,7 +716,6 @@ my $d = new Compress::Raw::Zlib::Deflate ( -Bufsize => 300, -Level => Z_BEST_SPEED ) ; - =head2 B<$status = $d-Edeflate($input, $output)> Deflates the contents of C<$input> and writes the compressed data to @@ -744,6 +763,16 @@ it is false, C<$output> will be truncated before any compressed data is written to it. +=head2 B<$status = $d-EdeflateReset() > + +This method will reset the deflation object C<$d>. It can be used when you +are compressing multiple data streams and want to use the same object to +compress each of them. It should only be used once the previous data stream +has been flushed successfully, i.e. a call to C<< $d->flush(Z_FINISH) >> has +returned C. + +Returns C if successful. + =head2 B<$status = $d-EdeflateParams([OPT])> Change settings for the deflate object C<$d>. @@ -751,7 +780,6 @@ The list of the valid options is shown below. Options not specified will remain unchanged. - =over 5 =item B<-Level> @@ -772,7 +800,6 @@ reallocated to increase the size, it will grow in increments of C. - =back =head2 B<$status = $d-EdeflateTune($good_length, $max_lazy, $nice_length, $max_chain)> @@ -815,7 +842,6 @@ Returns the deflation strategy currently used. Valid values are C, C and C. - =head2 B<$d-Eget_Level()> Returns the compression level being used. @@ -826,7 +852,6 @@ =head2 Example - Here is a trivial example of using C. It simply reads standard input, deflates it and writes it to standard output. @@ -865,7 +890,6 @@ Here is a definition of the interface: - =head2 B< ($i, $status) = new Compress::Raw::Zlib::Inflate( [OPT] ) > Initialises an inflation object. @@ -894,14 +918,20 @@ =item B<-WindowBits> To uncompress an RFC 1950 data stream, set C to a positive -number. +number between 8 and 15. To uncompress an RFC 1951 data stream, set C to C<-MAX_WBITS>. +To uncompress an RFC 1952 data stream (i.e. gzip), set C to +C. + +To auto-detect and uncompress an RFC 1950 or RFC 1952 data stream (i.e. +gzip), set C to C. + For a full definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to MAX_WBITS. +Defaults to C. =item B<-Bufsize> @@ -928,7 +958,6 @@ This option defaults to false. - =item B<-CRC32> If set to true, a crc32 checksum of the uncompressed data will be @@ -946,7 +975,7 @@ =item B<-ConsumeInput> If set to true, this option will remove compressed data from the input -buffer of the the C< $i-Einflate > method as the inflate progresses. +buffer of the C<< $i->inflate >> method as the inflate progresses. This option can be useful when you are processing compressed data that is embedded in another file/buffer. In this case the data that immediately @@ -954,6 +983,29 @@ This option defaults to true. +=item B<-LimitOutput> + +The C option changes the behavior of the C<< $i->inflate >> +method so that the amount of memory used by the output buffer can be +limited. + +When C is used the size of the output buffer used will either +be the value of the C option or the amount of memory already +allocated to C<$output>, whichever is larger. Predicting the output size +available is tricky, so don't rely on getting an exact output buffer size. + +When C is not specified C<< $i->inflate >> will use as much +memory as it takes to write all the uncompressed data it creates by +uncompressing the input buffer. + +If C is enabled, the C option will also be +enabled. + +This option defaults to false. + +See L for a discussion on why C is +needed and how to use it. + =back Here is an example of using an optional parameter to override the default @@ -1048,7 +1100,6 @@ data streams. They must have been added explicitly when the data stream was created by calling C with C. - =head2 B<$i-Edict_adler()> Returns the adler32 value for the dictionary. @@ -1083,7 +1134,7 @@ Returns the buffer size used to carry out the decompression. -=head2 Example +=head2 Examples Here is an example of using C. @@ -1102,10 +1153,9 @@ my ($output, $status) ; while (read(STDIN, $input, 4096)) { - $status = $x->inflate(\$input, $output) ; + $status = $x->inflate($input, $output) ; - print $output - if $status == Z_OK or $status == Z_STREAM_END ; + print $output ; last if $status != Z_OK ; } @@ -1113,6 +1163,46 @@ die "inflation failed\n" unless $status == Z_STREAM_END ; +The next example show how to use the C option. Notice the use +of two nested loops in this case. The outer loop reads the data from the +input source - STDIN and the inner loop repeatedly calls C until +C<$input> is exhausted, we get an error, or the end of the stream is +reached. One point worth remembering is by using the C option +you also get C set as well - this makes the code below much +simpler. + + use strict ; + use warnings ; + + use Compress::Raw::Zlib; + + my $x = new Compress::Raw::Zlib::Inflate(LimitOutput => 1) + or die "Cannot create a inflation stream\n" ; + + my $input = '' ; + binmode STDIN; + binmode STDOUT; + + my ($output, $status) ; + + OUTER: + while (read(STDIN, $input, 4096)) + { + do + { + $status = $x->inflate($input, $output) ; + + print $output ; + + last OUTER + unless $status == Z_OK || $status == Z_BUF_ERROR ; + } + while ($status == Z_OK && length $input); + } + + die "inflation failed\n" + unless $status == Z_STREAM_END ; + =head1 CHECKSUM FUNCTIONS Two functions are provided by I to calculate checksums. For the @@ -1135,24 +1225,163 @@ These functions allow checksums to be merged. -=head1 ACCESSING ZIP FILES +=head1 Misc + +=head2 my $version = Compress::Raw::Zlib::zlib_version(); + +Returns the version of the zlib library. + +=head1 The LimitOutput option. + +By default C<< $i->inflate($input, $output) >> will uncompress I data +in C<$input> and write I of the uncompressed data it has generated to +C<$output>. This makes the interface to C much simpler - if the +method has uncompressed C<$input> successfully I compressed data in +C<$input> will have been dealt with. So if you are reading from an input +source and uncompressing as you go the code will look something like this + + use strict ; + use warnings ; + + use Compress::Raw::Zlib; + + my $x = new Compress::Raw::Zlib::Inflate() + or die "Cannot create a inflation stream\n" ; + + my $input = '' ; + + my ($output, $status) ; + while (read(STDIN, $input, 4096)) + { + $status = $x->inflate($input, $output) ; + + print $output ; + + last if $status != Z_OK ; + } + + die "inflation failed\n" + unless $status == Z_STREAM_END ; + +The points to note are + +=over 5 + +=item * + +The main processing loop in the code handles reading of compressed data +from STDIN. + +=item * + +The status code returned from C will only trigger termination of +the main processing loop if it isn't C. When C has not +been used the C status means means that the end of the compressed +data stream has been reached or there has been an error in uncompression. + +=item * + +After the call to C I of the uncompressed data in C<$input> +will have been processed. This means the subsequent call to C can +overwrite it's contents without any problem. + +=back + +For most use-cases the behavior described above is acceptable (this module +and it's predecessor, C, have used it for over 10 years +without an issue), but in a few very specific use-cases the amount of +memory required for C<$output> can prohibitively large. For example, if the +compressed data stream contains the same pattern repeated thousands of +times, a relatively small compressed data stream can uncompress into +hundreds of megabytes. Remember C will keep allocating memory +until I the uncompressed data has been written to the output buffer - +the size of C<$output> is unbounded. + +The C option is designed to help with this use-case. + +The main difference in your code when using C is having to +deal with cases where the C<$input> parameter still contains some +uncompressed data that C hasn't processed yet. The status code +returned from C will be C if uncompression took place and +C if the output buffer is full. + +Below is typical code that shows how to use C. + + use strict ; + use warnings ; + + use Compress::Raw::Zlib; + + my $x = new Compress::Raw::Zlib::Inflate(LimitOutput => 1) + or die "Cannot create a inflation stream\n" ; + + my $input = '' ; + binmode STDIN; + binmode STDOUT; + + my ($output, $status) ; + + OUTER: + while (read(STDIN, $input, 4096)) + { + do + { + $status = $x->inflate($input, $output) ; -Although it is possible (with some effort on your part) to use this -module to access .zip files, there is a module on CPAN that will do all -the hard work for you. Check out the C module on CPAN at + print $output ; - http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz + last OUTER + unless $status == Z_OK || $status == Z_BUF_ERROR ; + } + while ($status == Z_OK && length $input); + } + + die "inflation failed\n" + unless $status == Z_STREAM_END ; +Points to note this time: + +=over 5 + +=item * + +There are now two nested loops in the code: the outer loop for reading the +compressed data from STDIN, as before; and the inner loop to carry out the +uncompression. + +=item * + +There are two exit points from the inner uncompression loop. + +Firstly when C has returned a status other than C or +C. This means that either the end of the compressed data +stream has been reached (C) or there is an error in the +compressed data. In either of these cases there is no point in continuing +with reading the compressed data, so both loops are terminated. + +The second exit point tests if there is any data left in the input buffer, +C<$input> - remember that the C option is automatically +enabled when C is used. When the input buffer has been +exhausted, the outer loop can run again and overwrite a now empty +C<$input>. + +=back + +=head1 ACCESSING ZIP FILES + +Although it is possible (with some effort on your part) to use this module +to access .zip files, there are other perl modules available that will +do all the hard work for you. Check out C, +C and C. =head1 CONSTANTS All the I constants are automatically imported when you make use of I. - =head1 SEE ALSO -L, L, L, L, L, L, L, L, L, L, L, L, L, L, L +L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L L @@ -1160,7 +1389,6 @@ L, L - For RFC 1950, 1951 and 1952 see F, F and @@ -1174,25 +1402,18 @@ The primary site for gzip is F. - - - =head1 AUTHOR This module was written by Paul Marquess, F. - - =head1 MODIFICATION HISTORY See the Changes file. =head1 COPYRIGHT AND LICENSE -Copyright (c) 2005-2007 Paul Marquess. All rights reserved. +Copyright (c) 2005-2009 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. - - diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/t/02zlib.t perl-5.10.0/ext/Compress/Raw/Zlib/t/02zlib.t --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/t/02zlib.t 2009-12-01 15:36:07.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/t/02zlib.t 2009-12-01 15:38:24.000000000 +0100 @@ -24,13 +24,13 @@ my $count = 0 ; if ($] < 5.005) { - $count = 189 ; + $count = 230 ; } elsif ($] >= 5.006) { - $count = 243 ; + $count = 300 ; } else { - $count = 201 ; + $count = 258 ; } plan tests => $count + $extra; @@ -443,10 +443,13 @@ # create a flush point cmp_ok $x->flush($Answer, Z_FULL_FLUSH), '==', Z_OK ; + + my $len1 = length $Answer; cmp_ok $x->deflate($goodbye, $Answer), '==', Z_OK; cmp_ok $x->flush($Answer), '==', Z_OK ; + my $len2 = length($Answer) - $len1 ; my ($first, @Answer) = split('', $Answer) ; @@ -475,7 +478,6 @@ $GOT .= $Z if defined $Z ; # print "x $status\n"; last if $status == Z_STREAM_END or $status != Z_OK ; - } cmp_ok $status, '==', Z_DATA_ERROR ; @@ -488,7 +490,7 @@ my $initial = $1 ; - ok(($k, $err) = new Compress::Raw::Zlib::Inflate(-ConsumeInput => 0)) ; + ok(($k, $err) = new Compress::Raw::Zlib::Inflate(ConsumeInput => 0)) ; ok $k ; cmp_ok $err, '==', Z_OK ; @@ -499,8 +501,11 @@ cmp_ok $status, '==', Z_OK or diag "status '$status'\nlength rest is " . length($rest) . "\n" ; - cmp_ok $k->inflate($rest, $GOT), '==', Z_DATA_ERROR; - is $Z . $GOT, $goodbye ; + is length($rest), $len2, "expected compressed output"; + + $GOT = ''; + cmp_ok $k->inflate($rest, $GOT), '==', Z_DATA_ERROR, "inflate returns Z_DATA_ERROR"; + is $GOT, $goodbye ; } { @@ -598,7 +603,7 @@ foreach (1 .. 2) { - next if $[ < 5.005 ; + next if $] < 5.005 ; title 'test inflate/deflate with a substr'; @@ -726,6 +731,142 @@ ok 1, "resetLastBlockByte(undef) is ok" ; } +{ + + title "gzip mode"; + # ================ + + my $hello = "I am a HAL 9000 computer" ; + my @hello = split('', $hello) ; + my ($err, $x, $X, $status); + + ok( ($x, $err) = new Compress::Raw::Zlib::Deflate ( + WindowBits => WANT_GZIP , + AppendOutput => 1 + ), "Create deflate object" ); + ok $x, "Compress::Raw::Zlib::Deflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $x->deflate($hello, $X) ; + cmp_ok $status, '==', Z_OK, "deflate returned Z_OK" ; + + cmp_ok $x->flush($X), '==', Z_OK, "flush returned Z_OK" ; + + my ($k, $GOT); + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => WANT_GZIP , + ConsumeInput => 0 , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_STREAM_END, "Got Z_STREAM_END" ; + is $GOT, $hello, "uncompressed data matches ok" ; + + $GOT = ''; + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => WANT_GZIP_OR_ZLIB , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP_OR_ZLIB ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_STREAM_END, "Got Z_STREAM_END" ; + is $GOT, $hello, "uncompressed data matches ok" ; +} + +{ + + title "gzip error mode"; + # Create gzip - + # read with no special windowbits setting - this will fail + # then read with WANT_GZIP_OR_ZLIB - thi swill work + # ================ + + my $hello = "I am a HAL 9000 computer" ; + my ($err, $x, $X, $status); + + ok( ($x, $err) = new Compress::Raw::Zlib::Deflate ( + WindowBits => WANT_GZIP , + AppendOutput => 1 + ), "Create deflate object" ); + ok $x, "Compress::Raw::Zlib::Deflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $x->deflate($hello, $X) ; + cmp_ok $status, '==', Z_OK, "deflate returned Z_OK" ; + + cmp_ok $x->flush($X), '==', Z_OK, "flush returned Z_OK" ; + + my ($k, $GOT); + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => MAX_WBITS , + ConsumeInput => 0 , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_DATA_ERROR, "Got Z_DATA_ERROR" ; + + $GOT = ''; + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => WANT_GZIP_OR_ZLIB , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP_OR_ZLIB ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_STREAM_END, "Got Z_STREAM_END" ; + is $GOT, $hello, "uncompressed data matches ok" ; +} + +{ + + title "gzip/zlib error mode"; + # Create zlib - + # read with no WANT_GZIP windowbits setting - this will fail + # then read with WANT_GZIP_OR_ZLIB - thi swill work + # ================ + + my $hello = "I am a HAL 9000 computer" ; + my ($err, $x, $X, $status); + + ok( ($x, $err) = new Compress::Raw::Zlib::Deflate ( + AppendOutput => 1 + ), "Create deflate object" ); + ok $x, "Compress::Raw::Zlib::Deflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $x->deflate($hello, $X) ; + cmp_ok $status, '==', Z_OK, "deflate returned Z_OK" ; + + cmp_ok $x->flush($X), '==', Z_OK, "flush returned Z_OK" ; + + my ($k, $GOT); + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => WANT_GZIP , + ConsumeInput => 0 , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_DATA_ERROR, "Got Z_DATA_ERROR" ; + + $GOT = ''; + ($k, $err) = new Compress::Raw::Zlib::Inflate( + WindowBits => WANT_GZIP_OR_ZLIB , + AppendOutput => 1); + ok $k, "Compress::Raw::Zlib::Inflate WANT_GZIP_OR_ZLIB ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $status = $k->inflate($X, $GOT) ; + cmp_ok $status, '==', Z_STREAM_END, "Got Z_STREAM_END" ; + is $GOT, $hello, "uncompressed data matches ok" ; +} + exit if $] < 5.006 ; title 'Looping Append test with substr output - substr the end of the string'; diff -urN perl-5.10.0.orig/ext/Compress/Raw/Zlib/t/09limitoutput.t perl-5.10.0/ext/Compress/Raw/Zlib/t/09limitoutput.t --- perl-5.10.0.orig/ext/Compress/Raw/Zlib/t/09limitoutput.t 1970-01-01 01:00:00.000000000 +0100 +++ perl-5.10.0/ext/Compress/Raw/Zlib/t/09limitoutput.t 2009-03-25 12:14:56.000000000 +0100 @@ -0,0 +1,129 @@ +BEGIN { + if ($ENV{PERL_CORE}) { + chdir 't' if -d 't'; + @INC = ("../lib", "lib/compress"); + } +} + +use lib qw(t t/compress); +use strict; +use warnings; +use bytes; + +use Test::More ; +use CompTestUtils; + +BEGIN +{ + # use Test::NoWarnings, if available + my $extra = 0 ; + $extra = 1 + if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; + + plan tests => 98 + $extra ; + + use_ok('Compress::Raw::Zlib', 2) ; +} + + + +my $hello = "I am a HAL 9000 computer" x 2001; +my $tmp = $hello ; + +my ($err, $x, $X, $status); + +ok( ($x, $err) = new Compress::Raw::Zlib::Deflate (-AppendOutput => 1)); +ok $x ; +cmp_ok $err, '==', Z_OK, " status is Z_OK" ; + +my $out ; +$status = $x->deflate($tmp, $out) ; +cmp_ok $status, '==', Z_OK, " status is Z_OK" ; + +cmp_ok $x->flush($out), '==', Z_OK, " flush returned Z_OK" ; + + +sub getOut { my $x = ''; return \$x } + +for my $bufsize (1, 2, 3, 13, 4096, 1024*10) +{ + print "#\n#Bufsize $bufsize\n#\n"; + $tmp = $out; + + my $k; + ok(($k, $err) = new Compress::Raw::Zlib::Inflate( AppendOutput => 1, + LimitOutput => 1, + Bufsize => $bufsize + )); + ok $k ; + cmp_ok $err, '==', Z_OK, " status is Z_OK" ; + + ok ! defined $k->msg(), " no msg" ; + is $k->total_in(), 0, " total_in == 0" ; + is $k->total_out(), 0, " total_out == 0" ; + my $GOT = getOut(); + my $prev; + my $deltaOK = 1; + my $looped = 0; + while (length $tmp) + { + ++ $looped; + my $prev = length $GOT; + $status = $k->inflate($tmp, $GOT) ; + last if $status == Z_STREAM_END || $status == Z_DATA_ERROR || $status == Z_STREAM_ERROR ; + $deltaOK = 0 if length($GOT) - $prev > $bufsize; + } + + ok $deltaOK, " Output Delta never > $bufsize"; + cmp_ok $looped, '>=', 1, " looped $looped"; + is length($tmp), 0, " length of input buffer is zero"; + + cmp_ok $status, '==', Z_STREAM_END, " status is Z_STREAM_END" ; + is $$GOT, $hello, " got expected output" ; + ok ! defined $k->msg(), " no msg" ; + is $k->total_in(), length $out, " length total_in ok" ; + is $k->total_out(), length $hello, " length total_out ok " . $k->total_out() ; +} + +sub getit +{ + my $obj = shift ; + my $input = shift; + + my $data ; + 1 while $obj->inflate($input, $data) != Z_STREAM_END ; + return \$data ; +} + +{ + title "regression test"; + + my ($err, $x, $X, $status); + + ok( ($x, $err) = new Compress::Raw::Zlib::Deflate (-AppendOutput => 1)); + ok $x ; + cmp_ok $err, '==', Z_OK, " status is Z_OK" ; + + my $line1 = ("abcdefghijklmnopq" x 1000) . "\n" ; + my $line2 = "second line\n" ; + my $text = $line1 . $line2 ; + my $tmp = $text; + + my $out ; + $status = $x->deflate($tmp, $out) ; + cmp_ok $status, '==', Z_OK, " status is Z_OK" ; + + cmp_ok $x->flush($out), '==', Z_OK, " flush returned Z_OK" ; + + my $k; + ok(($k, $err) = new Compress::Raw::Zlib::Inflate( AppendOutput => 1, + LimitOutput => 1 + )); + + + my $c = getit($k, $out); + is $$c, $text; + + +} +