WvStreams
wvgzip.cc
1 /*
2  * Worldvisions Weaver Software:
3  * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4  *
5  * Gzip encoder/decoder based on zlib.
6  */
7 #include "wvgzip.h"
8 #include <zlib.h>
9 #include <assert.h>
10 
11 #define ZBUFSIZE 10240
12 
13 
14 WvGzipEncoder::WvGzipEncoder(Mode _mode, size_t _out_limit) :
15  out_limit(_out_limit), tmpbuf(ZBUFSIZE), mode(_mode)
16 {
18  full_flush = false;
19  init();
20 }
21 
22 
23 WvGzipEncoder::~WvGzipEncoder()
24 {
25  close();
26 }
27 
28 
29 void WvGzipEncoder::init()
30 {
31  zstr = new z_stream;
32  memset(zstr, 0, sizeof(*zstr));
33  zstr->zalloc = Z_NULL;
34  zstr->zfree = Z_NULL;
35  zstr->opaque = NULL;
36  zstr->msg = NULL;
37 
38  int retval;
39  if (mode == Deflate)
40  retval = deflateInit(zstr, Z_BEST_SPEED);
41  else
42  retval = inflateInit(zstr);
43 
44  if (retval != Z_OK)
45  {
46  seterror("error %s initializing gzip %s: %s", retval,
47  mode == Deflate ? "compressor" : "decompressor",
48  zstr->msg ? zstr->msg : "unknown");
49  return;
50  }
51  zstr->next_in = zstr->next_out = NULL;
52  zstr->avail_in = zstr->avail_out = 0;
53 }
54 
55 void WvGzipEncoder::close()
56 {
57  if (mode == Deflate)
58  deflateEnd(zstr);
59  else
60  inflateEnd(zstr);
61 
62  delete zstr;
63 
64 }
65 
66 bool WvGzipEncoder::_encode(WvBuf &inbuf, WvBuf &outbuf, bool flush)
67 {
68  bool success;
69  output = 0;
70  for (;;)
71  {
72  size_t starting_size = inbuf.used();
73  prepare(& inbuf);
74  bool alldata = inbuf.used() == 0;
75  success = process(outbuf, flush && alldata, false);
76  if (zstr->avail_in != 0)
77  {
78  // unget unused data
79  inbuf.unget(zstr->avail_in);
80  zstr->avail_in = 0;
81  }
82  if (! success)
83  return false;
84  if (alldata || (starting_size == inbuf.used()) ||
85  (out_limit && (output >= out_limit)))
86  return true;
87  }
88 }
89 
90 
92 {
93  prepare(NULL);
94  return process(outbuf, false, true);
95 }
96 
97 
99 {
100  close();
101  init();
102  return true;
103 }
104 
105 
106 void WvGzipEncoder::prepare(WvBuf *inbuf)
107 {
108  assert(zstr->avail_in == 0);
109  if (inbuf && inbuf->used() != 0)
110  {
111  size_t avail = inbuf->optgettable();
112  zstr->avail_in = avail;
113  zstr->next_in = const_cast<Bytef*>(
114  (const Bytef*)inbuf->get(avail));
115  }
116  else
117  {
118  zstr->avail_in = 0;
119  zstr->next_in = (Bytef*)""; // so it's not NULL
120  }
121 }
122 
123 
124 bool WvGzipEncoder::process(WvBuf &outbuf, bool flush, bool finish)
125 {
126  int flushmode = finish ? Z_FINISH :
127  flush ? (full_flush ? Z_FULL_FLUSH : Z_SYNC_FLUSH) : Z_NO_FLUSH;
128  int retval;
129  do
130  {
131  // process the next chunk
132  tmpbuf.zap();
133  size_t avail_out = tmpbuf.free();
134  if (out_limit)
135  avail_out = tmpbuf.free() < (out_limit - output) ? tmpbuf.free()
136  : (out_limit - output);
137 
138  zstr->avail_out = avail_out;
139  zstr->next_out = tmpbuf.alloc(avail_out);
140  if (mode == Deflate)
141  retval = deflate(zstr, flushmode);
142  else
143  retval = inflate(zstr, flushmode);
144  tmpbuf.unalloc(zstr->avail_out);
145 
146  output += avail_out - zstr->avail_out;
147 
148  // consume pending output
149  outbuf.merge(tmpbuf);
150 
151  if (retval == Z_DATA_ERROR && mode == Inflate
153  retval = inflateSync(zstr);
154  } while (retval == Z_OK && (!out_limit || (out_limit > output)));
155 
156  if (retval == Z_STREAM_END)
157  setfinished();
158  else if (retval != Z_OK && retval != Z_BUF_ERROR &&
159  !(retval == Z_DATA_ERROR && mode == Inflate
161  {
162  seterror("error %s during gzip %s: %s", retval,
163  mode == Deflate ? "compression" : "decompression",
164  zstr->msg ? zstr->msg : "unknown");
165  return false;
166  }
167 
168  return true;
169 }
170 
WvBufBaseCommonImpl::get
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
WvBufBaseCommonImpl::unget
void unget(size_t count)
Ungets exactly the specified number of elements by returning them to the buffer for subsequent reads.
Definition: wvbufbase.h:177
WvBufBaseCommonImpl::alloc
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
Definition: wvbufbase.h:379
WvBufBaseCommonImpl::unalloc
void unalloc(size_t count)
Unallocates exactly the specified number of elements by removing them from the buffer and releasing t...
Definition: wvbufbase.h:421
WvBufBaseCommonImpl::free
size_t free() const
Returns the number of elements that the buffer can currently accept for writing.
Definition: wvbufbase.h:353
WvGzipEncoder::_finish
virtual bool _finish(WvBuf &outbuf)
Template method implementation of finish().
Definition: wvgzip.cc:91
WvBufBaseCommonImpl::optgettable
size_t optgettable() const
Returns the optimal maximum number of elements in the buffer currently available for reading without ...
Definition: wvbufbase.h:154
WvGzipEncoder::full_flush
bool full_flush
Do full flushes.
Definition: wvgzip.h:75
WvGzipEncoder::_encode
virtual bool _encode(WvBuf &inbuf, WvBuf &outbuf, bool flush)
Template method implementation of encode().
Definition: wvgzip.cc:66
WvGzipEncoder::_reset
virtual bool _reset()
Template method implementation of reset().
Definition: wvgzip.cc:98
WvBufBase< unsigned char >
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:22
WvGzipEncoder::ignore_decompression_errors
bool ignore_decompression_errors
Continue decompression if errors are found.
Definition: wvgzip.h:66
WvGzipEncoder::Mode
Mode
Definition: wvgzip.h:38
WvBufBaseCommonImpl::zap
void zap()
Clears the buffer.
Definition: wvbufbase.h:257
WvGzipEncoder::out_limit
size_t out_limit
Limit the amount of output produced in one call to encode().
Definition: wvgzip.h:55
WvEncoder::finish
bool finish(WvBuf &outbuf)
Tells the encoder that NO MORE DATA will ever be encoded.
Definition: wvencoder.cc:49
WvGzipEncoder::Inflate
@ Inflate
Definition: wvgzip.h:40
WvGzipEncoder::Deflate
@ Deflate
Definition: wvgzip.h:39
WvEncoder::flush
bool flush(WvBuf &inbuf, WvBuf &outbuf, bool finish=false)
Flushes the encoder and optionally finishes it.
Definition: wvencoder.h:163
WvEncoder::setfinished
void setfinished()
Sets 'finished' to true explicitly.
Definition: wvencoder.h:383
WvBufBaseCommonImpl::used
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
WvBufBaseCommonImpl::merge
void merge(Buffer &inbuf, size_t count)
Efficiently moves count bytes from the specified buffer into this one.
Definition: wvbufbase.h:558
WvEncoder::seterror
void seterror(WvStringParm message)
Sets an error condition, then setnotok().
Definition: wvencoder.h:375
WvGzipEncoder::WvGzipEncoder
WvGzipEncoder(Mode mode, size_t _out_limit=0)
Creates a Gzip encoder.
Definition: wvgzip.cc:14