e576bb2002-10-11Martin Nilsson /* || 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. */
aedfb12002-10-09Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "global.h" #include "zlib_machine.h"
51ef5c2002-10-21Marcus Comstedt #include "module.h"
c83e002006-01-03Marcus Comstedt #include "program.h"
64d6c42012-03-11Tobias S. Josefowitz #include "mapping.h"
c83e002006-01-03Marcus Comstedt #include "module_support.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #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 "stralloc.h" #include "object.h" #include "pike_types.h" #include "threads.h" #include "dynamic_buffer.h"
27ec272003-09-10Martin Stjernholm #include "operators.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include <zlib.h>
2505872002-09-25Marcus Comstedt 
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;
64d6c42012-03-11Tobias S. Josefowitz  struct pike_string *epilogue, *dict;
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
f0b0f12009-03-12Martin Nilsson  *! This class is only available if libz was available and found when
050d9c2001-11-18Martin Nilsson  *! Pike was compiled. *!
6461ef2001-01-05Henrik Grubbström (Grubba)  *! @seealso *! @[Gz.inflate()] */
f0b0f12009-03-12Martin Nilsson /*! @decl void create(int(-9..9)|void level, int|void strategy,@
50af292010-07-09Martin Nilsson  *! int(8..15)|void window_size)
64d6c42012-03-11Tobias S. Josefowitz  *! @decl void create(mapping options)
6461ef2001-01-05Henrik Grubbström (Grubba)  *! *! This function can also be used to re-initialize a Gz.deflate object *! so it can be re-used.
90c27b2003-03-31Per Hedbor  *!
64d6c42012-03-11Tobias S. Josefowitz  *! 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@}. *!
f0b0f12009-03-12Martin Nilsson  *! @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.
b8f7652003-04-14Marcus Comstedt  *!
f0b0f12009-03-12Martin Nilsson  *! 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.
d5abc32007-06-02Martin Nilsson  *!
f0b0f12009-03-12Martin Nilsson  *! @param strategy *! The strategy to be used when compressing the data. One of the *! following. *! @int *! @value DEFAULT_STRATEGY *! The default strategy as selected in the zlib library. *! @value FILTERED *! This strategy is intented for data created by a filter or *! predictor and will put more emphasis on huffman encoding and *! less on LZ string matching. This is between DEFAULT_STRATEGY *! and HUFFMAN_ONLY. *! @value RLE *! This strategy is even closer to the HUFFMAN_ONLY in that it *! only looks at the latest byte in the window, i.e. a window *! size of 1 byte is sufficient for decompression. This mode is *! not available in all zlib versions. *! @value HUFFMAN_ONLY *! This strategy will turn of string matching completely, only *! doing huffman encoding. Window size doesn't matter in this *! mode and the data can be decompressed with a zero size window. *! @value FIXED *! In this mode dynamic huffman codes are disabled, allowing for *! a simpler decoder for special applications. This mode is not *! available in all zlib versions. *! @endint *! *! @param window_size *! Defines the size of the LZ77 window from 256 bytes to 32768 *! bytes, expressed as 2^x.
6461ef2001-01-05Henrik Grubbström (Grubba)  */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_deflate_create(INT32 args) {
90c27b2003-03-31Per Hedbor  int tmp, wbits = 15;
b8f7652003-04-14Marcus Comstedt  int strategy = Z_DEFAULT_STRATEGY;
e85aa92001-07-04Fredrik Hübinette (Hubbe)  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)  }
64d6c42012-03-11Tobias S. Josefowitz  do_free_string(THIS->dict); THIS->dict = NULL;
d5abc32007-06-02Martin Nilsson  if(args>2) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[2-args]) != T_INT)
50af292010-07-09Martin Nilsson  Pike_error("Bad argument 3 to gz->create()\n"); wbits = sp[2-args].u.integer;
d5abc32007-06-02Martin Nilsson  if( wbits == 0 ) wbits = 15; if( wbits < 8 || wbits > 15 ) Pike_error("Invalid window size for gz_deflate->create().\n"); }
64d6c42012-03-11Tobias S. Josefowitz #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)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(args) {
64d6c42012-03-11Tobias S. Josefowitz  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"); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } }
b8f7652003-04-14Marcus Comstedt  if(args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[1-args]) != T_INT)
b8f7652003-04-14Marcus Comstedt  Pike_error("Bad argument 2 to gz->create()\n"); strategy=sp[1-args].u.integer;
2220da2006-07-26Martin Nilsson  if(strategy != Z_DEFAULT_STRATEGY && strategy != Z_FILTERED && #ifdef Z_RLE strategy != Z_RLE && #endif #ifdef Z_FIXED strategy != Z_FIXED && #endif
b8f7652003-04-14Marcus Comstedt  strategy != Z_HUFFMAN_ONLY) { Pike_error("Invalid compression strategy 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); */
5fbd6d2007-07-05Henrik Grubbström (Grubba)  do { tmp=deflateInit2(&THIS->gz, THIS->level, Z_DEFLATED, wbits, 9, strategy ); if (tmp == Z_STREAM_ERROR) { /* zlib 1.1.4's deflateInit2() only supports wbits 9..15 (not 8). */ if (wbits == -8) wbits = -9; else if (wbits == 8) wbits = 9; else break; continue; } break; } while(1);
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:
64d6c42012-03-11Tobias S. Josefowitz  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"); } }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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;
5cfecb2007-07-03Martin Stjernholm  case Z_MEM_ERROR: Pike_error ("Out of memory while initializing Gz.deflate.\n"); break;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  default: if(THIS->gz.msg)
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.deflate: %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.deflate (%d).\n", tmp);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } }
b3d5ee2006-08-02Martin Nilsson 
f9fb252009-08-30Henrik Grubbström (Grubba) #ifdef _REENTRANT
c0f9ea2009-08-28Martin Stjernholm static void do_mt_unlock (PIKE_MUTEX_T *lock) { mt_unlock (lock); }
f9fb252009-08-30Henrik Grubbström (Grubba) #endif
c0f9ea2009-08-28Martin Stjernholm 
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;
f9fb252009-08-30Henrik Grubbström (Grubba) #ifdef _REENTRANT ONERROR uwp;
b280771999-06-08Mirar (Pontus Hagland)  THREADS_ALLOW(); mt_lock(& this->lock); THREADS_DISALLOW();
c0f9ea2009-08-28Martin Stjernholm  SET_ONERROR (uwp, do_mt_unlock, &this->lock);
f9fb252009-08-30Henrik Grubbström (Grubba) #endif
c0f9ea2009-08-28Martin Stjernholm 
b280771999-06-08Mirar (Pontus Hagland)  if(!this->gz.state) ret=Z_STREAM_ERROR; else do
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
34f2262004-03-19Martin Nilsson  this->gz.next_out=(Bytef *)low_make_buf_space(
b280771999-06-08Mirar (Pontus Hagland)  /* 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) 
f9fb252009-08-30Henrik Grubbström (Grubba) #ifdef _REENTRANT
c0f9ea2009-08-28Martin Stjernholm  CALL_AND_UNSET_ONERROR (uwp);
f9fb252009-08-30Henrik Grubbström (Grubba) #endif
b280771999-06-08Mirar (Pontus Hagland)  return ret;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
a512e62006-08-02Martin Stjernholm void zlibmod_pack(struct pike_string *data, dynamic_buffer *buf, int level, int strategy, int wbits)
b3d5ee2006-08-02Martin Nilsson { struct zipper z; int ret; if(level < Z_NO_COMPRESSION || level > Z_BEST_COMPRESSION) Pike_error("Compression level out of range for pack. %d %d %d\n", Z_DEFAULT_COMPRESSION, Z_NO_COMPRESSION, Z_BEST_COMPRESSION); if(strategy != Z_DEFAULT_STRATEGY && strategy != Z_FILTERED && #ifdef Z_RLE strategy != Z_RLE && #endif #ifdef Z_FIXED strategy != Z_FIXED && #endif strategy != Z_HUFFMAN_ONLY) Pike_error("Invalid compression strategy %d for pack.\n", strategy);
d5abc32007-06-02Martin Nilsson  if( wbits<0 ? (wbits<-15 || wbits>-8) : (wbits<8 || wbits>15 ) ) Pike_error("Invalid window size value %d for pack.\n", wbits);
b3d5ee2006-08-02Martin Nilsson  MEMSET(&z, 0, sizeof(z)); z.gz.zalloc = Z_NULL; z.gz.zfree = Z_NULL;
ff43ce2007-05-01Martin Nilsson  z.gz.next_in = (Bytef *)data->str; z.gz.avail_in = (unsigned INT32)(data->len);
5fbd6d2007-07-05Henrik Grubbström (Grubba)  do { ret = deflateInit2(&z.gz, level, Z_DEFLATED, wbits, 9, strategy); if (ret == Z_STREAM_ERROR) { /* zlib 1.1.4's deflateInit2() only supports wbits 9..15 (not 8). */ if (wbits == -8) wbits = -9; else if (wbits == 8) wbits = 9; else break; continue; } break; } while(1);
b3d5ee2006-08-02Martin Nilsson  switch(ret) { case Z_OK: break; case Z_VERSION_ERROR: Pike_error("libz not compatible with zlib.h!!!\n"); break;
5cfecb2007-07-03Martin Stjernholm  case Z_MEM_ERROR: Pike_error ("Out of memory while initializing Gz.compress.\n"); break;
b3d5ee2006-08-02Martin Nilsson  default:
b532702007-05-19Per Hedbor  deflateEnd(&z.gz);
ff43ce2007-05-01Martin Nilsson  if(z.gz.msg)
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.compress: %s\n", z.gz.msg);
b3d5ee2006-08-02Martin Nilsson  else
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.compress (%d).\n", ret);
b3d5ee2006-08-02Martin Nilsson  } mt_init(&z.lock); ret = do_deflate(buf, &z, Z_FINISH); deflateEnd(&z.gz); mt_destroy(&z.lock);
ff43ce2007-05-01Martin Nilsson  if(ret != Z_STREAM_END) Pike_error("Error while deflating data (%d).\n",ret);
b3d5ee2006-08-02Martin Nilsson }
f0b0f12009-03-12Martin Nilsson /*! @endclass */
6174882007-05-01Martin Nilsson /*! @decl string compress(string data, void|int(0..1) raw, @
e6beaf2007-06-02Martin Bähr  *! void|int(0..9) level, void|int strategy, @
d5abc32007-06-02Martin Nilsson  *! void|int(8..15) window_size)
6174882007-05-01Martin Nilsson  *!
f0b0f12009-03-12Martin Nilsson  *! Encodes and returns the input @[data] according to the deflate *! format defined in RFC 1951. *! *! @param data *! The data to be encoded. *! *! @param raw *! If set, the data is encoded without the header and footer *! defined in RFC 1950. Example of uses is the ZIP container *! format. *! *! @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. *! *! @param strategy *! The strategy to be used when compressing the data. One of the *! following. *! @int *! @value DEFAULT_STRATEGY *! The default strategy as selected in the zlib library. *! @value FILTERED *! This strategy is intented for data created by a filter or *! predictor and will put more emphasis on huffman encoding and *! less on LZ string matching. This is between DEFAULT_STRATEGY *! and HUFFMAN_ONLY. *! @value RLE *! This strategy is even closer to the HUFFMAN_ONLY in that it *! only looks at the latest byte in the window, i.e. a window *! size of 1 byte is sufficient for decompression. This mode is *! not available in all zlib versions. *! @value HUFFMAN_ONLY *! This strategy will turn of string matching completely, only *! doing huffman encoding. Window size doesn't matter in this *! mode and the data can be decompressed with a zero size window. *! @value FIXED *! In this mode dynamic huffman codes are disabled, allowing for *! a simpler decoder for special applications. This mode is not *! available in all zlib versions. *! @endint *! *! @param window_size *! Defines the size of the LZ77 window from 256 bytes to 32768 *! bytes, expressed as 2^x. *!
b3d5ee2006-08-02Martin Nilsson  */
6174882007-05-01Martin Nilsson static void gz_compress(INT32 args)
b3d5ee2006-08-02Martin Nilsson { struct pike_string *data; dynamic_buffer buf;
ff43ce2007-05-01Martin Nilsson  ONERROR err;
b3d5ee2006-08-02Martin Nilsson  int wbits = 15; int raw = 0; int level = 8; int strategy = Z_DEFAULT_STRATEGY;
d5abc32007-06-02Martin Nilsson  get_all_args("compress", args, "%n.%d%d%d%d", &data, &raw, &level, &strategy, &wbits); if( !wbits ) wbits = 15;
b3d5ee2006-08-02Martin Nilsson  if( raw ) wbits = -wbits;
ff43ce2007-05-01Martin Nilsson  initialize_buf(&buf); SET_ONERROR(err, toss_buffer, &buf);
a512e62006-08-02Martin Stjernholm  zlibmod_pack(data, &buf, level, strategy, wbits);
ff43ce2007-05-01Martin Nilsson  UNSET_ONERROR(err);
b3d5ee2006-08-02Martin Nilsson  pop_n_elems(args); push_string(low_free_buf(&buf)); }
f0b0f12009-03-12Martin Nilsson /*! @class deflate */
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 *!
f5c4fe2010-06-24Jonas Wallden  *! @note *! Data must not be wide string. *!
6461ef2001-01-05Henrik Grubbström (Grubba)  *! @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) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != 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;
f5c4fe2010-06-24Jonas Wallden  if (data->size_shift) Pike_error("Cannot input wide string to gz_deflate->deflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[1-args]) != 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);
0a41162003-04-15Marcus Comstedt  THIS->epilogue = NULL;
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);
0a41162003-04-15Marcus Comstedt  do_free_string(THIS->epilogue);
64d6c42012-03-11Tobias S. Josefowitz  do_free_string(THIS->dict); THIS->dict = NULL;
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) 
90c27b2003-03-31Per Hedbor /*! @decl void create(int|void window_size)
64d6c42012-03-11Tobias S. Josefowitz  *! @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. *!
90c27b2003-03-31Per Hedbor  *! 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 *! 32Kb. Setting this to anything except 15 is rather pointless in *! Pike. *! *! 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.
6461ef2001-01-05Henrik Grubbström (Grubba)  */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) static void gz_inflate_create(INT32 args) {
64d6c42012-03-11Tobias S. Josefowitz  int tmp, *tmp_p = &tmp;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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;
64d6c42012-03-11Tobias S. Josefowitz  if( args && TYPEOF(Pike_sp[-1]) == PIKE_T_MAPPING)
5ab86f2003-03-30Per Hedbor  {
64d6c42012-03-11Tobias S. Josefowitz  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 );
5ab86f2003-03-30Per Hedbor  } else {
64d6c42012-03-11Tobias S. Josefowitz  if( args && TYPEOF(Pike_sp[-1]) == PIKE_T_INT ) { tmp=inflateInit2(& THIS->gz, Pike_sp[-1].u.integer); } else { tmp=inflateInit( &THIS->gz ); }
5ab86f2003-03-30Per Hedbor  }
04e3032003-03-30Martin Nilsson  pop_n_elems(args);
7260951997-09-01Per Hedbor /* mt_lock(& THIS->lock); */ /* mt_unlock(& THIS->lock); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  switch(tmp) { case Z_OK:
33aae82012-03-11Tobias S. Josefowitz #if 0 /* this apparently works with newer zlibs only. */
64d6c42012-03-11Tobias S. Josefowitz  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
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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;
5cfecb2007-07-03Martin Stjernholm  case Z_MEM_ERROR: Pike_error ("Out of memory while initializing Gz.inflate.\n"); break;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  default: if(THIS->gz.msg)
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.inflate: %s\n",THIS->gz.msg);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.inflate (%d).\n", tmp);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } static int do_inflate(dynamic_buffer *buf, struct zipper *this, int flush) { int fail=0;
c0f9ea2009-08-28Martin Stjernholm 
10e9d62009-08-30Henrik Grubbström (Grubba) #ifdef _REENTRANT ONERROR uwp;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
7260951997-09-01Per Hedbor  mt_lock(& this->lock);
cadacf1997-10-21Henrik Grubbström (Grubba)  THREADS_DISALLOW();
c0f9ea2009-08-28Martin Stjernholm  SET_ONERROR (uwp, do_mt_unlock, &this->lock);
10e9d62009-08-30Henrik Grubbström (Grubba) #endif
c0f9ea2009-08-28Martin Stjernholm 
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;
64d6c42012-03-11Tobias S. Josefowitz  if (ret == Z_NEED_DICT && this->dict) ret = inflateSetDictionary(&this->gz, (const Bytef*)this->dict->str, this->dict->len);
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); }
c0f9ea2009-08-28Martin Stjernholm 
10e9d62009-08-30Henrik Grubbström (Grubba) #ifdef _REENTRANT
c0f9ea2009-08-28Martin Stjernholm  CALL_AND_UNSET_ONERROR (uwp);
10e9d62009-08-30Henrik Grubbström (Grubba) #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  return fail; }
ff43ce2007-05-01Martin Nilsson void zlibmod_unpack(struct pike_string *data, dynamic_buffer *buf, int raw) { struct zipper z; int ret; MEMSET(&z, 0, sizeof(z)); z.gz.zalloc = Z_NULL; z.gz.zfree = Z_NULL; z.gz.next_in=(Bytef *)data->str; z.gz.avail_in = DO_NOT_WARN((unsigned INT32)(data->len)); if( raw ) ret = inflateInit2(&z.gz, -15); else ret = inflateInit( &z.gz ); switch(ret) { case Z_OK: break; case Z_VERSION_ERROR: Pike_error("libz not compatible with zlib.h!!!\n"); break;
5cfecb2007-07-03Martin Stjernholm  case Z_MEM_ERROR: Pike_error ("Out of memory while initializing Gz.uncompress.\n"); inflateEnd(&z.gz); break;
ff43ce2007-05-01Martin Nilsson  default:
b532702007-05-19Per Hedbor  inflateEnd( &z.gz );
ff43ce2007-05-01Martin Nilsson  if(z.gz.msg)
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.uncompress: %s\n", z.gz.msg);
ff43ce2007-05-01Martin Nilsson  else
5cfecb2007-07-03Martin Stjernholm  Pike_error("Failed to initialize Gz.uncompress (%d).\n", ret);
ff43ce2007-05-01Martin Nilsson  } mt_init(&z.lock); ret = do_inflate(buf, &z, Z_SYNC_FLUSH); mt_destroy(&z.lock);
b532702007-05-19Per Hedbor  inflateEnd( &z.gz );
ff43ce2007-05-01Martin Nilsson  if(ret==Z_OK) Pike_error("Compressed data is truncated.\n"); if(ret!=Z_STREAM_END) Pike_error("Failed to inflate data (%d).\n", ret); }
f0b0f12009-03-12Martin Nilsson /*! @endclass */
ff43ce2007-05-01Martin Nilsson /*! @decl string uncompress(string data, void|int(0..1) raw)
f0b0f12009-03-12Martin Nilsson  *! *! Uncompresses the @[data] and returns it. The @[raw] parameter *! tells the decoder that the indata lacks the data header and footer *! defined in RFC 1950.
ff43ce2007-05-01Martin Nilsson  */ static void gz_uncompress(INT32 args) { dynamic_buffer buf; ONERROR err; int raw = 0; if(args<1) SIMPLE_TOO_FEW_ARGS_ERROR("uncompress", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
ff43ce2007-05-01Martin Nilsson  SIMPLE_BAD_ARG_ERROR("uncompress", 1, "string");
f5c4fe2010-06-24Jonas Wallden  if (Pike_sp[-args].u.string->size_shift) Pike_error("Cannot input wide string to uncompress\n");
ff43ce2007-05-01Martin Nilsson  if(args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[1-args]) == PIKE_T_INT)
ff43ce2007-05-01Martin Nilsson  raw = Pike_sp[1-args].u.integer; else SIMPLE_BAD_ARG_ERROR("uncompress", 2, "int"); } initialize_buf(&buf); SET_ONERROR(err, toss_buffer, &buf); zlibmod_unpack(Pike_sp[-args].u.string, &buf, raw); UNSET_ONERROR(err); pop_n_elems(args); push_string(low_free_buf(&buf)); }
f0b0f12009-03-12Martin Nilsson /*! @class inflate */
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
f580112009-04-26Peter Bortas  *! write(Gz.inflate()->inflate(stdin->read(0x7fffffff));
050d9c2001-11-18Martin Nilsson  *! *! // streaming (blocks)
f580112009-04-26Peter Bortas  *! function inflate=Gz.inflate()->inflate;
050d9c2001-11-18Martin Nilsson  *! 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) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != 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;
f5c4fe2010-06-24Jonas Wallden  if (data->size_shift) Pike_error("Cannot input wide string to gz_inflate->inflate()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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));
0a41162003-04-15Marcus Comstedt  if(fail == Z_STREAM_END) { struct pike_string *old_epilogue = this->epilogue; if(old_epilogue) { push_string(old_epilogue); this->epilogue = NULL; }
34f2262004-03-19Martin Nilsson  push_string(make_shared_binary_string((const char *)this->gz.next_in,
0a41162003-04-15Marcus Comstedt  this->gz.avail_in)); if(old_epilogue) f_add(2);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) == PIKE_T_STRING)
0a41162003-04-15Marcus Comstedt  this->epilogue = (--sp)->u.string; else pop_stack(); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if(fail != Z_STREAM_END && fail!=Z_OK && !sp[-1].u.string->len) { pop_stack(); push_int(0); } }
0a41162003-04-15Marcus Comstedt /*! @decl string end_of_stream() *! *! This function returns 0 if the end of stream marker has not yet *! been encountered, or a string (possibly empty) containg any extra data *! received following the end of stream marker if the marker has been *! encountered. If the extra data is not needed, the result of this *! function can be treated as a logical value. */ static void gz_end_of_stream(INT32 args) { struct zipper *this=THIS; pop_n_elems(args); if(this->epilogue) ref_push_string(this->epilogue); else push_int(0); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 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);
0a41162003-04-15Marcus Comstedt  THIS->epilogue = NULL;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } 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);
0a41162003-04-15Marcus Comstedt  do_free_string(THIS->epilogue);
64d6c42012-03-11Tobias S. Josefowitz  do_free_string(THIS->dict); THIS->dict = NULL;
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) *!
90fc482002-11-25Henrik Grubbström (Grubba)  *! This function calculates the standard ISO3309 Cyclic Redundancy Check.
f5c4fe2010-06-24Jonas Wallden  *! *! @note *! Data must not be wide string.
6461ef2001-01-05Henrik Grubbström (Grubba)  */
8d36d51998-02-27Mirar (Pontus Hagland) static void gz_crc32(INT32 args) { unsigned INT32 crc;
017b572011-10-28Henrik Grubbström (Grubba)  if (!args || TYPEOF(sp[-args]) != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Gz.crc32: illegal or missing argument 1 (expected string)\n");
f5c4fe2010-06-24Jonas Wallden  if (sp[-args].u.string->size_shift) Pike_error("Cannot input wide string to Gz.crc32\n");
8d36d51998-02-27Mirar (Pontus Hagland) 
b804b21998-03-24Henrik Grubbström (Grubba)  if (args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[1-args]) != 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); }
6461ef2001-01-05Henrik Grubbström (Grubba) /*! @endmodule */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #endif
51ef5c2002-10-21Marcus Comstedt PIKE_MODULE_EXIT {}
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
51ef5c2002-10-21Marcus Comstedt PIKE_MODULE_INIT
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { #ifdef HAVE_ZLIB_H
5fbd6d2007-07-05Henrik Grubbström (Grubba)  struct z_stream_s z; /* Used to detect support for extensions. */ int have_rle = 0; int have_fixed = 0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct zipper);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
b8f7652003-04-14Marcus Comstedt  /* function(int|void,int|void:void) */
64d6c42012-03-11Tobias S. Josefowitz  ADD_FUNCTION("create",gz_deflate_create,tFunc(tOr(tMapping, tOr(tInt,tVoid)) tOr(tInt,tVoid),tVoid),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* 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);
b8f7652003-04-14Marcus Comstedt  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);
5fbd6d2007-07-05Henrik Grubbström (Grubba)  MEMSET(&z, 0, sizeof(z));
0f34062006-07-26Martin Nilsson #ifdef Z_RLE
5fbd6d2007-07-05Henrik Grubbström (Grubba)  if (deflateInit2(&z, 8, Z_DEFLATED, 9, 9, Z_RLE) == Z_OK) { have_rle = 1; deflateEnd(&z); add_integer_constant("RLE", Z_RLE,0); }
0f34062006-07-26Martin Nilsson #endif #ifdef Z_FIXED
5fbd6d2007-07-05Henrik Grubbström (Grubba)  if (deflateInit2(&z, 8, Z_DEFLATED, 9, 9, Z_FIXED) == Z_OK) { have_fixed = 1; deflateEnd(&z); add_integer_constant("FIXED", Z_FIXED,0); }
0f34062006-07-26Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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) */
64d6c42012-03-11Tobias S. Josefowitz  ADD_FUNCTION("create",gz_inflate_create,tFunc(tOr(tMapping,tOr(tInt,tVoid)),tVoid),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:string) */ ADD_FUNCTION("inflate",gz_inflate,tFunc(tStr,tStr),0);
0a41162003-04-15Marcus Comstedt  /* function(:string) */ ADD_FUNCTION("end_of_stream",gz_end_of_stream,tFunc(tNone,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)  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);
b8f7652003-04-14Marcus Comstedt  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);
2220da2006-07-26Martin Nilsson #ifdef Z_RLE
5fbd6d2007-07-05Henrik Grubbström (Grubba)  if (have_rle) { add_integer_constant("RLE", Z_RLE,0); }
2220da2006-07-26Martin Nilsson #endif #ifdef Z_FIXED
5fbd6d2007-07-05Henrik Grubbström (Grubba)  if (have_fixed) { add_integer_constant("FIXED", Z_FIXED,0); }
2220da2006-07-26Martin Nilsson #endif
2e87841997-04-06Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string,void|int:int) */
b3d5ee2006-08-02Martin Nilsson  ADD_FUNCTION("crc32",gz_crc32,tFunc(tStr tOr(tVoid,tInt),tInt),0); /* function(string,void|int(0..1),void|int,void|int:string) */
d5abc32007-06-02Martin Nilsson  ADD_FUNCTION("compress",gz_compress,tFunc(tStr tOr(tVoid,tInt01) tOr(tVoid,tInt09) tOr(tVoid,tInt) tOr(tVoid,tInt),tStr),0);
8d36d51998-02-27Mirar (Pontus Hagland) 
ff43ce2007-05-01Martin Nilsson  /* function(string,void|int(0..1):string) */ ADD_FUNCTION("uncompress",gz_uncompress,tFunc(tStr tOr(tVoid,tInt01),tStr),0);
48f8222005-10-19Martin Nilsson  PIKE_MODULE_EXPORT(Gz, crc32);
a512e62006-08-02Martin Stjernholm  PIKE_MODULE_EXPORT(Gz, zlibmod_pack);
2fd8852007-05-02Martin Nilsson  PIKE_MODULE_EXPORT(Gz, zlibmod_unpack);
1fbe3e2005-11-14Martin Nilsson #else if(!TEST_COMPAT(7,6)) HIDE_MODULE();
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 */