pike.git/src/modules/Gz/zlibmod.c:1:
/*
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
*/
#include "global.h"
#include "zlib_machine.h"
#include "module.h"
#include "program.h"
+ #include "mapping.h"
#include "module_support.h"
#if !defined(HAVE_LIBZ) && !defined(HAVE_LIBGZ)
#undef HAVE_ZLIB_H
#endif
#ifdef HAVE_ZLIB_H
#include "interpret.h"
#include "svalue.h"
pike.git/src/modules/Gz/zlibmod.c:31:
#include <zlib.h>
#define sp Pike_sp
struct zipper
{
int level;
int state;
struct z_stream_s gz;
- struct pike_string *epilogue;
+ struct pike_string *epilogue, *dict;
#ifdef _REENTRANT
DEFINE_MUTEX(lock);
#endif /* _REENTRANT */
};
#define BUF 32768
#define MAX_BUF (64*BUF)
#undef THIS
#define THIS ((struct zipper *)(Pike_fp->current_storage))
pike.git/src/modules/Gz/zlibmod.c:78:
*! @note
*! This class is only available if libz was available and found when
*! Pike was compiled.
*!
*! @seealso
*! @[Gz.inflate()]
*/
/*! @decl void create(int(-9..9)|void level, int|void strategy,@
*! int(8..15)|void window_size)
+ *! @decl void create(mapping options)
*!
*! This function can also be used to re-initialize a Gz.deflate object
*! so it can be re-used.
*!
-
+ *! If a mapping is passed as the only argument, it will accept the
+ *! parameters described below as indices, and additionally it accepts
+ *! a @expr{string@} as @expr{dictionary@}.
+ *!
*! @param level
*! Indicates the level of effort spent to make the data compress
*! well. Zero means no packing, 2-3 is considered 'fast', 6 is
*! default and higher is considered 'slow' but gives better
*! packing.
*!
*! If the argument is negative, no headers will be emitted. This is
*! needed to produce ZIP-files, as an example. The negative value
*! is then negated, and handled as a positive value.
*!
pike.git/src/modules/Gz/zlibmod.c:135:
int strategy = Z_DEFAULT_STRATEGY;
THIS->level=Z_DEFAULT_COMPRESSION;
if(THIS->gz.state)
{
/* mt_lock(& THIS->lock); */
deflateEnd(&THIS->gz);
/* mt_unlock(& THIS->lock); */
}
+ do_free_string(THIS->dict);
+ THIS->dict = NULL;
+
if(args>2)
{
if(TYPEOF(sp[2-args]) != T_INT)
Pike_error("Bad argument 3 to gz->create()\n");
wbits = sp[2-args].u.integer;
if( wbits == 0 ) wbits = 15;
if( wbits < 8 || wbits > 15 )
Pike_error("Invalid window size for gz_deflate->create().\n");
}
-
+ #define TTS(type) (((type) == PIKE_T_STRING && "string") \
+ || ((type) == PIKE_T_MAPPING && "mapping")\
+ || ((type) == PIKE_T_ARRAY && "array") \
+ || ((type) == PIKE_T_FLOAT && "float") \
+ || ((type) == PIKE_T_INT && "int") \
+ || ((type) == PIKE_T_OBJECT && "object") \
+ || "mixed")
+ #define GET_TYPE(type, name) ((tmp = simple_mapping_string_lookup(m, name)) \
+ && (TYPEOF(*(tmp)) == PIKE_T_##type || (Pike_error("Expected type %s,"\
+ "got type %s for " name ".", TTS(PIKE_T_##type), TTS(TYPEOF(*tmp))), 0)))
if(args)
{
-
+ if (TYPEOF(sp[-args]) == T_MAPPING && args == 1) {
+ struct mapping *m = sp[-args].u.mapping;
+ struct svalue *tmp;
+
+ if (GET_TYPE(INT, "strategy")) strategy = tmp->u.integer;
+ if (GET_TYPE(INT, "window_size"))
+ {
+ wbits = tmp->u.integer;
+ if (wbits == 0) wbits = 15;
+ if (wbits < 8 || wbits > 15)
+ Pike_error("Invalid window size for gz_deflate->create().\n");
+ }
+ if (GET_TYPE(STRING, "dictionary"))
+ {
+ THIS->dict = tmp->u.string;
+ add_ref(THIS->dict);
+ }
+ if (GET_TYPE(INT, "level"))
+ {
+ THIS->level = tmp->u.integer;
+ goto LVL_CHECK;
+ }
+ } else {
if(TYPEOF(sp[-args]) != T_INT)
Pike_error("Bad argument 1 to gz->create()\n");
THIS->level=sp[-args].u.integer;
-
+ LVL_CHECK:
if( THIS->level < 0 )
{
wbits = -wbits;
THIS->level = -THIS->level;
}
if(THIS->level < Z_NO_COMPRESSION ||
THIS->level > Z_BEST_COMPRESSION)
{
Pike_error("Compression level out of range for gz_deflate->create()\n");
}
}
-
+ }
if(args>1)
{
if(TYPEOF(sp[1-args]) != T_INT)
Pike_error("Bad argument 2 to gz->create()\n");
strategy=sp[1-args].u.integer;
if(strategy != Z_DEFAULT_STRATEGY &&
strategy != Z_FILTERED &&
#ifdef Z_RLE
strategy != Z_RLE &&
pike.git/src/modules/Gz/zlibmod.c:202:
else if (wbits == 8) wbits = 9;
else break;
continue;
}
break;
} while(1);
/* mt_unlock(& THIS->lock); */
switch(tmp)
{
case Z_OK:
+ if (THIS->dict) {
+ int err;
+ err = deflateSetDictionary(&THIS->gz, (const Bytef*)THIS->dict->str,
+ THIS->dict->len);
+ if (err != Z_OK) {
+ Pike_error("failed to set dictionary in deflate init.\n");
+ }
+ }
return;
case Z_VERSION_ERROR:
Pike_error("libz not compatible with zlib.h!!!\n");
break;
case Z_MEM_ERROR:
Pike_error ("Out of memory while initializing Gz.deflate.\n");
break;
pike.git/src/modules/Gz/zlibmod.c:553:
THIS->state=0;
deflateInit(& THIS->gz, THIS->level = Z_DEFAULT_COMPRESSION);
THIS->epilogue = NULL;
}
static void exit_gz_deflate(struct object *o)
{
/* mt_lock(& THIS->lock); */
deflateEnd(&THIS->gz);
do_free_string(THIS->epilogue);
+ do_free_string(THIS->dict);
+ THIS->dict = NULL;
/* mt_unlock(& THIS->lock); */
mt_destroy( & THIS->lock );
}
/*! @endclass
*/
/*******************************************************************/
/*! @class inflate
pike.git/src/modules/Gz/zlibmod.c:576:
*!
*! @note
*! This program is only available if libz was available and found when
*! Pike was compiled.
*!
*! @seealso
*! @[deflate]
*/
/*! @decl void create(int|void window_size)
+ *! @decl void create(mapping options)
+ *!
+ *! If called with a mapping as only argument, @expr{create@} accepts
+ *! the entries @expr{window_size@} (described below) and @expr{dictionary@},
+ *! which is a string to be set as dictionary.
+ *!
*! The window_size value is passed down to inflateInit2 in zlib.
*!
*! If the argument is negative, no header checks are done, and no
*! verification of the data will be done either. This is needed for
*! uncompressing ZIP-files, as an example. The negative value is then
*! negated, and handled as a positive value.
*!
*! Positive arguments set the maximum dictionary size to an exponent
*! of 2, such that 8 (the minimum) will cause the window size to be
*! 256, and 15 (the maximum, and default value) will cause it to be
pike.git/src/modules/Gz/zlibmod.c:599:
*! It can be used to limit the amount of memory that is used to
*! uncompress files, but 32Kb is not all that much in the great
*! scheme of things.
*!
*! To decompress files compressed with level 9 compression, a 32Kb
*! window size is needed. level 1 compression only requires a 256
*! byte window.
*/
static void gz_inflate_create(INT32 args)
{
- int tmp;
+ int tmp, *tmp_p = &tmp;
if(THIS->gz.state)
{
/* mt_lock(& THIS->lock); */
inflateEnd(&THIS->gz);
/* mt_unlock(& THIS->lock); */
}
THIS->gz.zalloc=Z_NULL;
THIS->gz.zfree=Z_NULL;
THIS->gz.opaque=(void *)THIS;
-
+ if( args && TYPEOF(Pike_sp[-1]) == PIKE_T_MAPPING)
+ {
+ struct mapping *m = Pike_sp[-1].u.mapping;
+ struct svalue *tmp;
+
+ if (GET_TYPE(STRING, "dictionary")) {
+ THIS->dict = tmp->u.string;
+ add_ref(THIS->dict);
+ }
+ if (GET_TYPE(INT, "window_size"))
+ *tmp_p=inflateInit2(& THIS->gz, tmp->u.integer);
+ else
+ *tmp_p=inflateInit( &THIS->gz );
+ }
+ else
+ {
if( args && TYPEOF(Pike_sp[-1]) == PIKE_T_INT )
{
tmp=inflateInit2(& THIS->gz, Pike_sp[-1].u.integer);
}
else
{
tmp=inflateInit( &THIS->gz );
}
-
+ }
pop_n_elems(args);
/* mt_lock(& THIS->lock); */
/* mt_unlock(& THIS->lock); */
switch(tmp)
{
case Z_OK:
-
+ #if 0 // this apparently works with newer zlibs only.
+ if (THIS->dict) {
+ int err;
+
+ err = inflateSetDict(&THIS->gz, (const Bytef*)THIS->dict->str,
+ THIS->dict->len);
+
+ if (err != Z_OK)
+ Pike_error("inflateSetDict on startup failed.\n");
+ }
+ #endif
return;
case Z_VERSION_ERROR:
Pike_error("libz not compatible with zlib.h!!!\n");
break;
case Z_MEM_ERROR:
Pike_error ("Out of memory while initializing Gz.inflate.\n");
break;
pike.git/src/modules/Gz/zlibmod.c:699: Inside #if 0
this->gz.avail_out,
this->gz.avail_in,
ret);
#endif
THREADS_DISALLOW();
low_make_buf_space(-((ptrdiff_t)this->gz.avail_out), buf);
if(ret == Z_BUF_ERROR) ret=Z_OK;
+ if (ret == Z_NEED_DICT && this->dict)
+ ret = inflateSetDictionary(&this->gz,
+ (const Bytef*)this->dict->str,
+ this->dict->len);
+
if(ret != Z_OK)
{
fail=ret;
break;
}
} while(!this->gz.avail_out || flush==Z_FINISH || this->gz.avail_in);
}
#ifdef _REENTRANT
CALL_AND_UNSET_ONERROR (uwp);
pike.git/src/modules/Gz/zlibmod.c:924:
inflateInit(&THIS->gz);
inflateEnd(&THIS->gz);
THIS->epilogue = NULL;
}
static void exit_gz_inflate(struct object *o)
{
/* mt_lock(& THIS->lock); */
inflateEnd(& THIS->gz);
do_free_string(THIS->epilogue);
+ do_free_string(THIS->dict);
+ THIS->dict = NULL;
/* mt_unlock(& THIS->lock); */
mt_destroy( & THIS->lock );
}
/*! @endclass
*/
/*! @decl int crc32(string data, void|int start_value)
*!
*! This function calculates the standard ISO3309 Cyclic Redundancy Check.
pike.git/src/modules/Gz/zlibmod.c:979: Inside #if defined(HAVE_ZLIB_H)
{
#ifdef HAVE_ZLIB_H
struct z_stream_s z; /* Used to detect support for extensions. */
int have_rle = 0;
int have_fixed = 0;
start_new_program();
ADD_STORAGE(struct zipper);
/* function(int|void,int|void:void) */
- ADD_FUNCTION("create",gz_deflate_create,tFunc(tOr(tInt,tVoid) tOr(tInt,tVoid),tVoid),0);
+ ADD_FUNCTION("create",gz_deflate_create,tFunc(tOr(tMapping, tOr(tInt,tVoid)) tOr(tInt,tVoid),tVoid),0);
/* function(string,int|void:string) */
ADD_FUNCTION("deflate",gz_deflate,tFunc(tStr tOr(tInt,tVoid),tStr),0);
add_integer_constant("NO_FLUSH",Z_NO_FLUSH,0);
add_integer_constant("PARTIAL_FLUSH",Z_PARTIAL_FLUSH,0);
add_integer_constant("SYNC_FLUSH",Z_SYNC_FLUSH,0);
add_integer_constant("FINISH",Z_FINISH,0);
add_integer_constant("DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY,0);
add_integer_constant("FILTERED", Z_FILTERED,0);
add_integer_constant("HUFFMAN_ONLY", Z_HUFFMAN_ONLY,0);
pike.git/src/modules/Gz/zlibmod.c:1016: Inside #if defined(HAVE_ZLIB_H)
set_init_callback(init_gz_deflate);
set_exit_callback(exit_gz_deflate);
end_class("deflate",0);
start_new_program();
ADD_STORAGE(struct zipper);
/* function(int|void:void) */
- ADD_FUNCTION("create",gz_inflate_create,tFunc(tOr(tInt,tVoid),tVoid),0);
+ ADD_FUNCTION("create",gz_inflate_create,tFunc(tOr(tMapping,tOr(tInt,tVoid)),tVoid),0);
/* function(string:string) */
ADD_FUNCTION("inflate",gz_inflate,tFunc(tStr,tStr),0);
/* function(:string) */
ADD_FUNCTION("end_of_stream",gz_end_of_stream,tFunc(tNone,tStr),0);
add_integer_constant("NO_FLUSH",Z_NO_FLUSH,0);
add_integer_constant("PARTIAL_FLUSH",Z_PARTIAL_FLUSH,0);
add_integer_constant("SYNC_FLUSH",Z_SYNC_FLUSH,0);
add_integer_constant("FINISH",Z_FINISH,0);