|
|
|
|
|
#include "global.h" |
RCSID("$Id: zlibmod.c,v 1.1 1996/11/16 05:17:15 hubbe Exp $"); |
|
#include "zlib_machine.h" |
#include "types.h" |
|
#if !defined(HAVE_LIBZ) && !defined(HAVE_LIBGZ) |
#undef HAVE_ZLIB_H |
#endif |
|
#ifdef HAVE_ZLIB_H |
|
#include "interpret.h" |
#include "svalue.h" |
#include "stralloc.h" |
#include "array.h" |
#include "macros.h" |
#include "program.h" |
#include "stralloc.h" |
#include "object.h" |
#include "pike_types.h" |
#include "threads.h" |
#include "dynamic_buffer.h" |
|
#include <zlib.h> |
|
struct zipper |
{ |
struct z_stream_s gz; |
DEFINE_MUTEX(lock); |
}; |
|
#define BUF 16384 |
|
#define THIS ((struct zipper *)(fp->current_storage)) |
|
static void gz_deflate_create(INT32 args) |
{ |
int level=Z_DEFAULT_COMPRESSION; |
|
if(THIS->gz.state) |
{ |
mt_lock(& this->lock); |
deflateEnd(&THIS->gz); |
mt_unlock(& this->lock); |
} |
|
if(args) |
{ |
if(sp[-args].type != T_INT) |
error("Bad argument 1 to gz->create()\n"); |
if(sp[-args].u.integer < Z_NO_COMPRESSION || |
sp[-args].u.integer > Z_BEST_COMPRESSION) |
{ |
error("Compression level out of range for gz_deflate->create()\n"); |
} |
} |
|
THIS->gz.zalloc=Z_NULL; |
THIS->gz.zfree=Z_NULL; |
THIS->gz.opaque=THIS; |
|
pop_n_elems(args); |
mt_lock(& THIS->lock); |
level=deflateInit(&THIS->gz, level); |
mt_unlock(& THIS->lock); |
switch(level) |
{ |
case Z_OK: |
return; |
|
case Z_VERSION_ERROR: |
error("libz not compatible with zlib.h!!!\n"); |
break; |
|
default: |
if(THIS->gz.msg) |
error("Failed to initialize gz_deflate: %s\n",THIS->gz.msg); |
else |
error("Failed to initialize gz_deflate\n"); |
} |
} |
|
static int do_deflate(dynamic_buffer *buf, |
struct zipper *this, |
int flush) |
{ |
int fail=0; |
|
THREADS_ALLOW(); |
mt_lock(& this->lock); |
if(!this->gz.state) |
{ |
fail=Z_STREAM_ERROR; |
}else{ |
do |
{ |
char *loc; |
int ret; |
loc=low_make_buf_space(BUF,buf); |
this->gz.next_out=(Bytef *)loc; |
this->gz.avail_out=BUF; |
ret=deflate(& this->gz, flush); |
low_make_buf_space(-this->gz.avail_out,buf); |
if(ret != Z_OK) |
{ |
fail=ret; |
break; |
} |
} while(!this->gz.avail_out || flush==Z_FINISH || this->gz.avail_in); |
} |
|
mt_unlock(& this->lock); |
THREADS_DISALLOW(); |
return fail; |
} |
|
static void gz_deflate(INT32 args) |
{ |
struct pike_string *data; |
int flush, fail; |
struct zipper *this=THIS; |
dynamic_buffer buf; |
|
if(!THIS->gz.state) |
error("gz_deflate not initialized or destructed\n"); |
|
initialize_buf(&buf); |
|
if(args<1) |
error("Too few arguments to gz_deflate->deflate()\n"); |
|
if(sp[-args].type != T_STRING) |
error("Bad argument 1 to gz_deflate->deflate()\n"); |
|
data=sp[-args].u.string; |
|
if(args>1) |
{ |
if(sp[1-args].type != T_INT) |
error("Bad argument 2 to gz_deflate->deflate()\n"); |
|
flush=sp[1-args].u.integer; |
|
switch(flush) |
{ |
case Z_PARTIAL_FLUSH: |
case Z_FINISH: |
case Z_SYNC_FLUSH: |
case Z_NO_FLUSH: |
break; |
|
defualt: |
error("Argument 2 to gz_deflate->deflate() out of range.\n"); |
} |
}else{ |
flush=Z_NO_FLUSH; |
} |
|
this->gz.next_in=(Bytef *)data->str; |
this->gz.avail_in=data->len; |
|
fail=do_deflate(&buf,this,flush); |
pop_n_elems(args); |
|
if(fail != Z_OK && fail != Z_STREAM_END) |
{ |
free(buf.s.str); |
if(THIS->gz.msg) |
error("Error in gz_deflate->deflate(): %s\n",THIS->gz.msg); |
else |
error("Error in gz_deflate->deflate(): %d\n",fail); |
} |
|
push_string(low_free_buf(&buf)); |
} |
|
|
static void init_gz_deflate(struct object *o) |
{ |
mt_init(& THIS->locked); |
MEMSET(& THIS->gz, 0, sizeof(THIS->gz)); |
THIS->gz.zalloc=Z_NULL; |
THIS->gz.zfree=Z_NULL; |
THIS->gz.opaque=THIS; |
deflateInit(& THIS->gz, Z_DEFAULT_COMPRESSION); |
} |
|
static void exit_gz_deflate(struct object *o) |
{ |
mt_lock(& THIS->lock); |
deflateEnd(&THIS->gz); |
mt_unlock(& THIS->lock); |
} |
|
|
|
|
static void gz_inflate_create(INT32 args) |
{ |
int level; |
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=THIS; |
|
pop_n_elems(args); |
mt_lock(THIS->lock); |
level=inflateInit(& THIS->gz); |
mt_unlock(THIS->lock); |
switch(level) |
{ |
case Z_OK: |
return; |
|
case Z_VERSION_ERROR: |
error("libz not compatible with zlib.h!!!\n"); |
break; |
|
default: |
if(THIS->gz.msg) |
error("Failed to initialize gz_inflate: %s\n",THIS->gz.msg); |
else |
error("Failed to initialize gz_inflate\n"); |
} |
} |
|
static int do_inflate(dynamic_buffer *buf, |
struct zipper *this, |
int flush) |
{ |
int fail=0; |
|
THREADS_ALLOW(); |
mt_lock(this->lock); |
if(!this->gz.state) |
{ |
fail=Z_STREAM_ERROR; |
}else{ |
do |
{ |
char *loc; |
int ret; |
loc=low_make_buf_space(BUF,buf); |
this->gz.next_out=(Bytef *)loc; |
this->gz.avail_out=BUF; |
ret=inflate(& this->gz, flush); |
low_make_buf_space(-this->gz.avail_out,buf); |
if(ret != Z_OK) |
{ |
fail=ret; |
break; |
} |
} while(!this->gz.avail_out || flush==Z_FINISH || this->gz.avail_in); |
} |
mt_unlock(this->lock); |
THREADS_DISALLOW(); |
return fail; |
} |
|
static void gz_inflate(INT32 args) |
{ |
struct pike_string *data; |
int fail; |
struct zipper *this=THIS; |
dynamic_buffer buf; |
|
if(!THIS->gz.state) |
error("gz_inflate not initialized or destructed\n"); |
|
initialize_buf(&buf); |
|
if(args<1) |
error("Too few arguments to gz_inflate->inflate()\n"); |
|
if(sp[-args].type != T_STRING) |
error("Bad argument 1 to gz_inflate->inflate()\n"); |
|
data=sp[-args].u.string; |
|
this->gz.next_in=(Bytef *)data->str; |
this->gz.avail_in=data->len; |
|
fail=do_inflate(&buf,this,Z_PARTIAL_FLUSH); |
pop_n_elems(args); |
|
if(fail != Z_OK && fail != Z_STREAM_END) |
{ |
free(buf.s.str); |
if(THIS->gz.msg) |
error("Error in gz_inflate->inflate(): %s\n",THIS->gz.msg); |
else |
error("Error in gz_inflate->inflate(): %d\n",fail); |
} |
push_string(low_free_buf(&buf)); |
if(fail == Z_STREAM_END && !sp[-1].u.string->len) |
{ |
pop_stack(); |
push_int(0); |
} |
} |
|
static void init_gz_inflate(struct object *o) |
{ |
mt_init(THIS->locked); |
MEMSET(& THIS->gz, 0, sizeof(THIS->gz)); |
THIS->gz.zalloc=Z_NULL; |
THIS->gz.zfree=Z_NULL; |
THIS->gz.opaque=0; |
inflateInit(&THIS->gz); |
inflateEnd(&THIS->gz); |
} |
|
static void exit_gz_inflate(struct object *o) |
{ |
mt_lock(& THIS->lock); |
inflateEnd(& THIS->gz); |
mt_unlock(& THIS->lock); |
} |
|
#endif |
|
void init_zlibmod_efuns(void) {} |
void exit_zlibmod(void) { } |
|
void init_zlibmod_programs(void) |
{ |
#ifdef HAVE_ZLIB_H |
start_new_program(); |
add_storage(sizeof(struct zipper)); |
|
add_function("create",gz_deflate_create,"function(int|void:void)",0); |
add_function("deflate",gz_deflate,"function(string,int|void:string)",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); |
|
set_init_callback(init_gz_deflate); |
set_exit_callback(exit_gz_deflate); |
|
end_c_program("/precompiled/gz_deflate"); |
|
start_new_program(); |
add_storage(sizeof(struct zipper)); |
|
add_function("create",gz_inflate_create,"function(int|void:void)",0); |
add_function("inflate",gz_inflate,"function(string:string)",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); |
|
set_init_callback(init_gz_inflate); |
set_exit_callback(exit_gz_inflate); |
|
end_c_program("/precompiled/gz_inflate"); |
#endif |
} |
|
|
|