ce398f2002-09-19Marcus Comstedt /*\
3e9a462002-01-16Martin Nilsson ||| This file is part of Pike. For copyright information see COPYRIGHT.
59e32d2002-06-01Martin Nilsson ||| Pike is distributed under GPL, LGPL and MPL. See the file COPYING ||| for more information.
ab6aec1997-02-11Fredrik Hübinette (Hubbe) \*/
2bb2221999-08-20Henrik Grubbström (Grubba) /**/
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "global.h"
ce398f2002-09-19Marcus Comstedt RCSID("$Id: zlibmod.c,v 1.51 2002/09/19 13:42:32 marcus Exp $");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "zlib_machine.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"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "program.h" #include "stralloc.h" #include "object.h" #include "pike_types.h" #include "threads.h" #include "dynamic_buffer.h" #include <zlib.h>
6dc2772000-07-28Fredrik Hübinette (Hubbe) /* This must be included last! */ #include "module_magic.h"
65bd332002-05-11Martin Stjernholm #define sp Pike_sp
ab6aec1997-02-11Fredrik Hübinette (Hubbe) struct zipper {
98a7e12002-04-07Leif Stensson  int level; int state;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  struct z_stream_s gz;
1549c82002-08-25Marcus Agehall  gzFile gzfile;
e0c81f1997-03-22Henrik Grubbström (Grubba) #ifdef _REENTRANT
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  DEFINE_MUTEX(lock);
e0c81f1997-03-22Henrik Grubbström (Grubba) #endif /* _REENTRANT */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) };
1d90b91997-11-11Henrik Grubbström (Grubba) #define BUF 32768
d7288e1997-11-11Henrik Grubbström (Grubba) #define MAX_BUF (64*BUF)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
3568261998-05-07Fredrik Hübinette (Hubbe) #undef THIS
39221e2000-07-07Henrik Grubbström (Grubba) #define THIS ((struct zipper *)(Pike_fp->current_storage))
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @module Gz *! *! The Gz module contains functions to compress and uncompress strings using *! the same algorithm as the program @tt{gzip@}. Compressing can be done in *! streaming mode or all at once. *! *! The Gz module consists of two classes; Gz.deflate and Gz.inflate. *! Gz.deflate is used to pack data *! and Gz.inflate is used to unpack data. (Think "inflatable boat") *! *! @note *! Note that this module is only available if the gzip library was *! available when Pike was compiled. *! *! Note that although these functions use the same @i{algorithm@} as *! @tt{gzip@}, they do not use the exact same format, so you cannot directly *! unzip gzipped files with these routines. Support for this will be *! added in the future. */ /*! @class deflate *!
050d9c2001-11-18Martin Nilsson  *! Gz_deflate is a builtin program written in C. It interfaces the *! packing routines in the libz library. *! *! @note *! This program is only available if libz was available and found when *! Pike was compiled. *!
6461ef2001-01-05Henrik Grubbström (Grubba)  *! @seealso *! @[Gz.inflate()] */ /*! @decl void create(int(0..9)|void X) *! *! If given, @[X] should be a number from 0 to 9 indicating the *! packing / CPU ratio. Zero means no packing, 2-3 is considered 'fast', *! 6 is default and higher is considered 'slow' but gives better packing. *! *! This function can also be used to re-initialize a Gz.deflate object *! so it can be re-used. */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_deflate_create(INT32 args) {
e85aa92001-07-04Fredrik Hübinette (Hubbe)  int tmp; THIS->level=Z_DEFAULT_COMPRESSION;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(THIS->gz.state) {
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  deflateEnd(&THIS->gz);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } if(args) { if(sp[-args].type != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 1 to gz->create()\n");
e85aa92001-07-04Fredrik Hübinette (Hubbe)  THIS->level=sp[-args].u.integer; if(THIS->level < Z_NO_COMPRESSION || THIS->level > Z_BEST_COMPRESSION)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Compression level out of range for gz_deflate->create()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } THIS->gz.zalloc=Z_NULL; THIS->gz.zfree=Z_NULL;
3164751998-04-30Henrik Grubbström (Grubba)  THIS->gz.opaque=(void *)THIS;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args);
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
e85aa92001-07-04Fredrik Hübinette (Hubbe)  tmp=deflateInit(&THIS->gz, THIS->level);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
e85aa92001-07-04Fredrik Hübinette (Hubbe)  switch(tmp)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { case Z_OK: return; case Z_VERSION_ERROR:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("libz not compatible with zlib.h!!!\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  break; default: if(THIS->gz.msg)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to initialize gz_deflate: %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to initialize gz_deflate\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } static int do_deflate(dynamic_buffer *buf, struct zipper *this, int flush) {
b280771999-06-08Mirar (Pontus Hagland)  int ret=0; THREADS_ALLOW(); mt_lock(& this->lock); THREADS_DISALLOW(); if(!this->gz.state) ret=Z_STREAM_ERROR; else do
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
b280771999-06-08Mirar (Pontus Hagland)  this->gz.next_out=low_make_buf_space( /* recommended by the zlib people */ (this->gz.avail_out =
9189f32000-12-13Fredrik Hübinette (Hubbe)  this->gz.avail_in ? this->gz.avail_in+this->gz.avail_in/1000+42 : 4096),
b280771999-06-08Mirar (Pontus Hagland)  buf); THREADS_ALLOW(); ret=deflate(& this->gz, flush); THREADS_DISALLOW();
ffc0991999-07-15Fredrik Hübinette (Hubbe)  /* Absorb any unused space /Hubbe */
3919712000-08-17Henrik Grubbström (Grubba)  low_make_buf_space(-((ptrdiff_t)this->gz.avail_out), buf);
ffc0991999-07-15Fredrik Hübinette (Hubbe) 
3b13762001-02-15Fredrik Hübinette (Hubbe)  if(ret == Z_BUF_ERROR) ret=Z_OK;
7260951997-09-01Per Hedbor  }
9189f32000-12-13Fredrik Hübinette (Hubbe)  while (ret==Z_OK && (this->gz.avail_in || !this->gz.avail_out));
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
b280771999-06-08Mirar (Pontus Hagland)  mt_unlock(& this->lock); return ret;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @decl string deflate(string data, int|void flush) *! *! This function performs gzip style compression on a string @[data] and *! returns the packed data. Streaming can be done by calling this *! function several times and concatenating the returned data. *! *! The optional argument @[flush] should be one of the following: *! @int *! @value Gz.NO_FLUSH *! Only data that doesn't fit in the internal buffers is returned. *! @value Gz.PARTIAL_FLUSH *! All input is packed and returned. *! @value Gz.SYNC_FLUSH *! All input is packed and returned. *! @value Gz.FINISH *! All input is packed and an 'end of data' marker is appended. *! @endint *! *! @seealso *! @[Gz.inflate->inflate()] */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_deflate(INT32 args) { struct pike_string *data; int flush, fail; struct zipper *this=THIS; dynamic_buffer buf;
a598cd2001-01-23Fredrik Hübinette (Hubbe)  ONERROR err;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e85aa92001-07-04Fredrik Hübinette (Hubbe)  if(THIS->state == 1) { deflateEnd(& THIS->gz); deflateInit(& THIS->gz, THIS->level); THIS->state=0; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(!THIS->gz.state)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("gz_deflate not initialized or destructed\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(args<1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too few arguments to gz_deflate->deflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(sp[-args].type != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 1 to gz_deflate->deflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  data=sp[-args].u.string; if(args>1) { if(sp[1-args].type != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 2 to gz_deflate->deflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  flush=sp[1-args].u.integer; switch(flush) { case Z_PARTIAL_FLUSH: case Z_FINISH: case Z_SYNC_FLUSH: case Z_NO_FLUSH: break;
8d36d51998-02-27Mirar (Pontus Hagland)  default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Argument 2 to gz_deflate->deflate() out of range.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } }else{ flush=Z_FINISH; } this->gz.next_in=(Bytef *)data->str;
340c562001-06-13Henrik Grubbström (Grubba)  this->gz.avail_in = DO_NOT_WARN((unsigned INT32)(data->len));
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
2bb2221999-08-20Henrik Grubbström (Grubba)  initialize_buf(&buf);
a598cd2001-01-23Fredrik Hübinette (Hubbe)  SET_ONERROR(err,toss_buffer,&buf);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  fail=do_deflate(&buf,this,flush);
a598cd2001-01-23Fredrik Hübinette (Hubbe)  UNSET_ONERROR(err);
e85aa92001-07-04Fredrik Hübinette (Hubbe) 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(fail != Z_OK && fail != Z_STREAM_END) {
a5b2c72001-01-24Henrik Grubbström (Grubba)  toss_buffer(&buf);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(THIS->gz.msg)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in gz_deflate->deflate(): %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in gz_deflate->deflate(): %d\n",fail);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
e85aa92001-07-04Fredrik Hübinette (Hubbe)  if(fail == Z_STREAM_END) THIS->state=1;
a5b2c72001-01-24Henrik Grubbström (Grubba)  pop_n_elems(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  push_string(low_free_buf(&buf)); } static void init_gz_deflate(struct object *o) {
2383021997-02-27Fredrik Hübinette (Hubbe)  mt_init(& THIS->lock);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  MEMSET(& THIS->gz, 0, sizeof(THIS->gz)); THIS->gz.zalloc=Z_NULL; THIS->gz.zfree=Z_NULL;
3164751998-04-30Henrik Grubbström (Grubba)  THIS->gz.opaque=(void *)THIS;
e85aa92001-07-04Fredrik Hübinette (Hubbe)  THIS->state=0; deflateInit(& THIS->gz, THIS->level = Z_DEFAULT_COMPRESSION);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } static void exit_gz_deflate(struct object *o) {
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  deflateEnd(&THIS->gz);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
4e77fb1999-06-10Fredrik Hübinette (Hubbe)  mt_destroy( & THIS->lock );
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @endclass */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) /*******************************************************************/
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @class inflate
050d9c2001-11-18Martin Nilsson  *! *! Gz_deflate is a builtin program written in C. It interfaces the *! unpacking routines in the libz library. *! *! @note *! This program is only available if libz was available and found when *! Pike was compiled. *! *! @seealso *! @[deflate]
6461ef2001-01-05Henrik Grubbström (Grubba)  */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @decl void create() */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_inflate_create(INT32 args) { int tmp; if(THIS->gz.state) {
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  inflateEnd(&THIS->gz);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } THIS->gz.zalloc=Z_NULL; THIS->gz.zfree=Z_NULL;
3164751998-04-30Henrik Grubbström (Grubba)  THIS->gz.opaque=(void *)THIS;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args);
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  tmp=inflateInit(& THIS->gz);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  switch(tmp) { case Z_OK: return; case Z_VERSION_ERROR:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("libz not compatible with zlib.h!!!\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  break; default: if(THIS->gz.msg)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to initialize gz_inflate: %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to initialize gz_inflate\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } static int do_inflate(dynamic_buffer *buf, struct zipper *this, int flush) { int fail=0; THREADS_ALLOW();
7260951997-09-01Per Hedbor  mt_lock(& this->lock);
cadacf1997-10-21Henrik Grubbström (Grubba)  THREADS_DISALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(!this->gz.state) { fail=Z_STREAM_ERROR; }else{
4951fc2001-02-08Fredrik Hübinette (Hubbe) #if 0 static int fnord=0; fnord++; #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  do { char *loc; int ret; loc=low_make_buf_space(BUF,buf);
cadacf1997-10-21Henrik Grubbström (Grubba)  THREADS_ALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  this->gz.next_out=(Bytef *)loc; this->gz.avail_out=BUF;
4951fc2001-02-08Fredrik Hübinette (Hubbe) #if 0 fprintf(stderr,"INFLATE[%d]: avail_out=%7d avail_in=%7d flush=%d\n", fnord, this->gz.avail_out, this->gz.avail_in, flush); fprintf(stderr,"INFLATE[%d]: mode=%d\n",fnord, this->gz.state ? *(int *)(this->gz.state) : -1); #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  ret=inflate(& this->gz, flush);
4951fc2001-02-08Fredrik Hübinette (Hubbe) #if 0 fprintf(stderr,"Result [%d]: avail_out=%7d avail_in=%7d ret=%d\n", fnord, this->gz.avail_out, this->gz.avail_in, ret); #endif
cadacf1997-10-21Henrik Grubbström (Grubba)  THREADS_DISALLOW();
3919712000-08-17Henrik Grubbström (Grubba)  low_make_buf_space(-((ptrdiff_t)this->gz.avail_out), buf);
4951fc2001-02-08Fredrik Hübinette (Hubbe)  if(ret == Z_BUF_ERROR) ret=Z_OK;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(ret != Z_OK)
7260951997-09-01Per Hedbor  { fail=ret; break; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } while(!this->gz.avail_out || flush==Z_FINISH || this->gz.avail_in); }
7260951997-09-01Per Hedbor  mt_unlock(& this->lock);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  return fail; }
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @decl string inflate(string data) *! *! This function performs gzip style decompression. It can inflate *! a whole file at once or in blocks. *!
050d9c2001-11-18Martin Nilsson  *! @example *! // whole file *! write(Gz_inflate()->inflate(stdin->read(0x7fffffff)); *! *! // streaming (blocks) *! function inflate=Gz_inflate()->inflate; *! while(string s=stdin->read(8192)) *! write(inflate(s)); *!
6461ef2001-01-05Henrik Grubbström (Grubba)  *! @seealso *! @[Gz.deflate->deflate()] */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_inflate(INT32 args) { struct pike_string *data; int fail; struct zipper *this=THIS; dynamic_buffer buf;
a598cd2001-01-23Fredrik Hübinette (Hubbe)  ONERROR err;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(!THIS->gz.state)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("gz_inflate not initialized or destructed\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(args<1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too few arguments to gz_inflate->inflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(sp[-args].type != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 1 to gz_inflate->inflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  data=sp[-args].u.string; this->gz.next_in=(Bytef *)data->str;
340c562001-06-13Henrik Grubbström (Grubba)  this->gz.avail_in = DO_NOT_WARN((unsigned INT32)(data->len));
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
2bb2221999-08-20Henrik Grubbström (Grubba)  initialize_buf(&buf);
a5b2c72001-01-24Henrik Grubbström (Grubba) 
a598cd2001-01-23Fredrik Hübinette (Hubbe)  SET_ONERROR(err,toss_buffer,&buf);
3b13762001-02-15Fredrik Hübinette (Hubbe)  fail=do_inflate(&buf,this,Z_SYNC_FLUSH);
a598cd2001-01-23Fredrik Hübinette (Hubbe)  UNSET_ONERROR(err);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(fail != Z_OK && fail != Z_STREAM_END) {
a5b2c72001-01-24Henrik Grubbström (Grubba)  toss_buffer(&buf);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(THIS->gz.msg)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in gz_inflate->inflate(): %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in gz_inflate->inflate(): %d\n",fail);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
e85aa92001-07-04Fredrik Hübinette (Hubbe) 
a5b2c72001-01-24Henrik Grubbström (Grubba)  pop_n_elems(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  push_string(low_free_buf(&buf)); if(fail != Z_STREAM_END && fail!=Z_OK && !sp[-1].u.string->len) { pop_stack(); push_int(0); } } static void init_gz_inflate(struct object *o) {
77fe171997-02-27Fredrik Hübinette (Hubbe)  mt_init(& THIS->lock);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  MEMSET(& THIS->gz, 0, sizeof(THIS->gz)); THIS->gz.zalloc=Z_NULL; THIS->gz.zfree=Z_NULL;
e85aa92001-07-04Fredrik Hübinette (Hubbe)  THIS->gz.opaque=(void *)THIS;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  inflateInit(&THIS->gz); inflateEnd(&THIS->gz); } static void exit_gz_inflate(struct object *o) {
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  inflateEnd(& THIS->gz);
7260951997-09-01Per Hedbor /* mt_unlock(& THIS->lock); */
4e77fb1999-06-10Fredrik Hübinette (Hubbe)  mt_destroy( & THIS->lock );
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @endclass */
8d36d51998-02-27Mirar (Pontus Hagland) 
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @decl int crc32(string data, void|int start_value) *! *! This function calculates the standard ISO3309 Cyclic Redundancy Check. */
8d36d51998-02-27Mirar (Pontus Hagland) static void gz_crc32(INT32 args) { unsigned INT32 crc; if (!args || sp[-args].type!=T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Gz.crc32: illegal or missing argument 1 (expected string)\n");
8d36d51998-02-27Mirar (Pontus Hagland) 
b804b21998-03-24Henrik Grubbström (Grubba)  if (args>1) {
8d36d51998-02-27Mirar (Pontus Hagland)  if (sp[1-args].type!=T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Gz.crc32: illegal argument 2 (expected integer)\n");
8d36d51998-02-27Mirar (Pontus Hagland)  else crc=(unsigned INT32)sp[1-args].u.integer;
b804b21998-03-24Henrik Grubbström (Grubba)  } else
8d36d51998-02-27Mirar (Pontus Hagland)  crc=0; crc=crc32(crc, (unsigned char*)sp[-args].u.string->str,
340c562001-06-13Henrik Grubbström (Grubba)  DO_NOT_WARN((unsigned INT32)(sp[-args].u.string->len)));
8d36d51998-02-27Mirar (Pontus Hagland)  pop_n_elems(args); push_int((INT32)crc); }
1549c82002-08-25Marcus Agehall /*! @class gzip_file *! Read-support for GZip files */ /*! @decl int open(string|int file, void|string mode) *! Opens a file for I/O. *! @param file *! The filename or an open filedescriptor for the GZip file to open. *! @param mode *! Mode for the fileoperations. Defaults to read only. *! *! @note *! If the object represents a file, it will first be closed. */ void gz_file_open(INT32 args) { char default_mode[] = "rb"; char *mode = default_mode; if (THIS->gzfile!=NULL) { gzclose(THIS->gzfile); THIS->gzfile = NULL; } if (args<1 || args>2) { Pike_error("Bad number of arguments to file->open()\n" "Got %d, expected 1 or 2.\n", args); } if (sp[-args].type != PIKE_T_STRING && sp[-args].type != PIKE_T_INT) { Pike_error("Bad parameter 1 to file->open()\n"); } if (args == 2 && sp[1-args].type != PIKE_T_STRING) { Pike_error("Bad parameter 2 to file->open()\n"); } else if (args == 2) { mode = sp[1-args].u.string->str; } if (sp[-args].type == PIKE_T_INT) {
9b76352002-08-25Marcus Agehall  THIS->gzfile = gzdopen(sp[-args].u.integer,
1549c82002-08-25Marcus Agehall  mode); } else { THIS->gzfile = gzopen(sp[-args].u.string->str, mode); } pop_n_elems(args); push_int(THIS->gzfile != NULL); }
e889da2002-08-26Marek Habersack /*! @decl void create(void|string gzFile, void|string mode)
1549c82002-08-25Marcus Agehall  *! Opens a gzip file for reading. */ void gz_file_create(INT32 args) { THIS->gzfile = NULL; if (args) { gz_file_open(args); if (sp[-1].u.integer == 0) { Pike_error("Failed to open file.\n"); } pop_n_elems(1); } } /*! @decl int close() *! closes the file
e889da2002-08-26Marek Habersack  *! @returns *! 1 if successful
1549c82002-08-25Marcus Agehall  */ void gz_file_close(INT32 args) { if (args!=0) { Pike_error("Bad number of arguments to file->close()\n" "Got %d, expected 0.\n", args); } if (THIS->gzfile!=NULL) { gzclose(THIS->gzfile); THIS->gzfile = NULL; } push_int(1); } /*! @decl int|string read(int len) *! Reads len (uncompressed) bytes from the file. *! If read is unsuccessful, 0 is returned. */ void gz_file_read(INT32 args) { char *buf; int len; int res; if (args!=1) { Pike_error("Bad number of arguments to gz_file->read()\n" "Got %d, expected 1.\n", args); } if (sp[-args].type != PIKE_T_INT) { Pike_error("Bad argument 1 to gz_file->read()\n"); } if (THIS->gzfile == NULL) { Pike_error("File not open!\n"); } len = sp[-args].u.integer; buf = malloc(sizeof(char) * (len+1)); pop_n_elems(args); res = gzread(THIS->gzfile, buf, len); if (res<0) { push_int(0); free(buf); return; } buf[res] = '\0'; push_string(make_shared_string(buf)); free(buf); } /*! @decl int write(string data) *! Writes the data to the file.
e889da2002-08-26Marek Habersack  *! @returns *! the number of bytes written to the file.
1549c82002-08-25Marcus Agehall  */ void gz_file_write(INT32 args) { int res = 0; if (args!=1) { Pike_error("Bad number of arguments to gz_file->write()\n" "Got %d, expected 1.\n", args); } if (sp[-args].type != PIKE_T_STRING) { Pike_error("Bad argument 1 to gz_file->write()\n"); } if (THIS->gzfile == NULL) { Pike_error("File not open!\n"); } res = gzwrite(THIS->gzfile, sp[-args].u.string->str, (unsigned INT32)sp[-args].u.string->len); pop_n_elems(args); push_int(res); }
dd8fa72002-09-10Henrik Grubbström (Grubba) #ifdef HAVE_GZSEEK
1549c82002-08-25Marcus Agehall /*! @decl int seek(int pos, void|int type)
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! Seeks within the file.
1549c82002-08-25Marcus Agehall  *! @param pos
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! Position relative to the searchtype.
1549c82002-08-25Marcus Agehall  *! @param type
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! SEEK_SET = set current position in file to pos *! SEEK_CUR = new position is current+pos *! SEEK_END is not supported.
e889da2002-08-26Marek Habersack  *! @returns
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! New position or negative number if seek failed. *! *! @note *! Not supported on all operating systems.
1549c82002-08-25Marcus Agehall  */ void gz_file_seek(INT32 args) { int res, newpos; int type = SEEK_SET; if (args>2) { Pike_error("Bad number of arguments to file->seek()\n" "Got %d, expected 1 or 2.\n", args); } if (sp[-args].type != PIKE_T_INT) { Pike_error("Bad argument 1 to file->seek()\n"); } if (args == 2 && sp[1-args].type != PIKE_T_INT) { Pike_error("Bad argument 2 to file->seek()\n"); } else if (args == 2) { type = sp[1-args].u.integer; } if (THIS->gzfile == NULL) { Pike_error("File not open!\n"); } newpos = sp[-args].u.integer; pop_n_elems(args); res = gzseek(THIS->gzfile, newpos, type); push_int(res); }
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZSEEK */
1549c82002-08-25Marcus Agehall 
dd8fa72002-09-10Henrik Grubbström (Grubba) #ifdef HAVE_GZTELL /*! @decl int tell()
e889da2002-08-26Marek Habersack  *! @returns *! the current position within the file.
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! *! @note *! Not supported on all operating systems.
1549c82002-08-25Marcus Agehall  */ void gz_file_tell(INT32 args) { if (args!=0) { Pike_error("Bad number of arguments to file->tell()\n" "Got %d, expected 0.\n", args); } if (THIS->gzfile == NULL) { Pike_error("File not open!\n"); } push_int(gztell(THIS->gzfile)); }
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZTELL */
1549c82002-08-25Marcus Agehall 
dd8fa72002-09-10Henrik Grubbström (Grubba) #ifdef HAVE_GZEOF
1549c82002-08-25Marcus Agehall /*! @decl int(0..1) eof()
e889da2002-08-26Marek Habersack  *! @returns *! 1 if EOF has been reached.
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! *! @note *! Not supported on all operating systems.
1549c82002-08-25Marcus Agehall  */ void gz_file_eof(INT32 args) { if (args!=0) { Pike_error("Bad number of arguments to file->eof()\n" "Got %d, expected 0.\n", args); } push_int(gzeof(THIS->gzfile)); }
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZEOF */
1549c82002-08-25Marcus Agehall 
dd8fa72002-09-10Henrik Grubbström (Grubba) #ifdef HAVE_GZSETPARAMS
1549c82002-08-25Marcus Agehall /*! @decl int setparams(int level, int strategy)
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! Sets the encoding level and strategy
1549c82002-08-25Marcus Agehall  *! @param level
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! Level of the compression. *! 0 is the least compression, 9 is max. 8 is default.
1549c82002-08-25Marcus Agehall  *! @param strategy
dd8fa72002-09-10Henrik Grubbström (Grubba)  *! Set strategy for encoding to one of the following: *! Z_DEFAULT_STRATEGY *! Z_FILTERED *! Z_HUFFMAN_ONLY *! *! @note *! Not supported on all operating systems.
1549c82002-08-25Marcus Agehall  */ void gz_file_setparams(INT32 args) { int res; if (args!=2) { Pike_error("Bad number of arguments to file->setparams()\n" "Got %d, expected 2.\n", args); } if (sp[-args].type != PIKE_T_INT || sp[1-args].type != PIKE_T_INT) { Pike_error("Bad type in argument\n"); } res = gzsetparams(THIS->gzfile, sp[-args].u.integer, sp[1-args].u.integer); pop_n_elems(args); push_int(res == Z_OK); }
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZSETPARAMS */
1549c82002-08-25Marcus Agehall  static void init_gz_file(struct object *o) { mt_init(& THIS->lock); THIS->gzfile = NULL; } static void exit_gz_file(struct object *o) { if (THIS->gzfile != NULL) gzclose(THIS->gzfile); mt_destroy( & THIS->lock ); } /*! @endclass */
8d36d51998-02-27Mirar (Pontus Hagland) 
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @endmodule */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #endif void pike_module_exit(void) {} void pike_module_init(void) { #ifdef HAVE_ZLIB_H start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct zipper);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(int|void:void) */ ADD_FUNCTION("create",gz_deflate_create,tFunc(tOr(tInt,tVoid),tVoid),0); /* function(string,int|void:string) */ ADD_FUNCTION("deflate",gz_deflate,tFunc(tStr tOr(tInt,tVoid),tStr),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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_class("deflate",0); start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct zipper);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(int|void:void) */ ADD_FUNCTION("create",gz_inflate_create,tFunc(tOr(tInt,tVoid),tVoid),0); /* function(string:string) */ ADD_FUNCTION("inflate",gz_inflate,tFunc(tStr,tStr),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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_class("inflate",0);
2e87841997-04-06Fredrik Hübinette (Hubbe) 
1549c82002-08-25Marcus Agehall  start_new_program(); ADD_STORAGE(struct zipper); ADD_FUNCTION("create", gz_file_create, tFunc(tOr(tVoid, tString) tOr(tVoid, tString), tVoid), 0); ADD_FUNCTION("open", gz_file_open, tFunc(tString tOr(tVoid, tString), tInt), 0); ADD_FUNCTION("close", gz_file_close, tFunc(tVoid, tInt), 0); ADD_FUNCTION("read", gz_file_read, tFunc(tInt,tOr(tString,tInt)), 0); ADD_FUNCTION("write", gz_file_write, tFunc(tString,tInt), 0);
dd8fa72002-09-10Henrik Grubbström (Grubba) #ifdef HAVE_GZSEEK
1549c82002-08-25Marcus Agehall  ADD_FUNCTION("seek", gz_file_seek, tFunc(tInt tOr(tVoid,tInt), tInt), 0);
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZSEEK */ #ifdef HAVE_GZTELL
1549c82002-08-25Marcus Agehall  ADD_FUNCTION("tell", gz_file_tell, tFunc(tVoid, tInt), 0);
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZTELL */ #ifdef HAVE_GZEOF
1549c82002-08-25Marcus Agehall  ADD_FUNCTION("eof", gz_file_eof, tFunc(tVoid, tInt), 0);
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZEOF */ #ifdef HAVE_GZSETPARAMS
1549c82002-08-25Marcus Agehall  ADD_FUNCTION("setparams", gz_file_setparams, tFunc(tInt tInt, tInt), 0);
dd8fa72002-09-10Henrik Grubbström (Grubba) #endif /* HAVE_GZSETPARAMS */
1549c82002-08-25Marcus Agehall  add_integer_constant("SEEK_SET", SEEK_SET, 0); add_integer_constant("SEEK_CUR", SEEK_CUR, 0); add_integer_constant("Z_DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY,0); add_integer_constant("Z_FILTERED", Z_FILTERED,0); add_integer_constant("Z_HUFFMAN_ONLY", Z_HUFFMAN_ONLY,0); set_init_callback(init_gz_file); set_exit_callback(exit_gz_file); end_class("_file", 0);
2e87841997-04-06Fredrik Hübinette (Hubbe)  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);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string,void|int:int) */ ADD_FUNCTION("crc32",gz_crc32,tFunc(tStr tOr(tVoid,tInt),tInt),
8d36d51998-02-27Mirar (Pontus Hagland)  OPT_TRY_OPTIMIZE);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #endif }
9eed301997-10-26Henrik Grubbström (Grubba) #if defined(HAVE___VTBL__9TYPE_INFO) || defined(HAVE___T_9__NOTHROW)
35d10a1997-10-12Henrik Grubbström (Grubba) /* Super-special kluge for IRIX 6.3 */
9eed301997-10-26Henrik Grubbström (Grubba) #ifdef HAVE___VTBL__9TYPE_INFO
297fff1997-10-14Henrik Grubbström (Grubba) extern void __vtbl__9type_info(void);
9eed301997-10-26Henrik Grubbström (Grubba) #endif /* HAVE___VTBL__9TYPE_INFO */ #ifdef HAVE___T_9__NOTHROW extern void __T_9__nothrow(void); #endif /* HAVE___T_9__NOTHROW */ /* Don't even think of calling this one * Not static, so the compiler can't optimize it away totally. */
297fff1997-10-14Henrik Grubbström (Grubba) void zlibmod_strap_kluge(void)
35d10a1997-10-12Henrik Grubbström (Grubba) {
9eed301997-10-26Henrik Grubbström (Grubba) #ifdef HAVE___VTBL__9TYPE_INFO
35d10a1997-10-12Henrik Grubbström (Grubba)  __vtbl__9type_info(); #endif /* HAVE___VTBL__9TYPE_INFO */
9eed301997-10-26Henrik Grubbström (Grubba) #ifdef HAVE___T_9__NOTHROW __T_9__nothrow(); #endif /* HAVE___T_9__NOTHROW */ } #endif /* HAVE___VTBL__9TYPE_INFO || HAVE___T_9__NOTHROW */