Make WvStreams compile with gcc 4.4.
[wvstreams.git] / utils / wvgzip.cc
blob0929d82f2d09851b62890bd7d0f521024c981129
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>
11 #define ZBUFSIZE 10240
14 WvGzipEncoder::WvGzipEncoder(Mode _mode, size_t _out_limit) :
15 out_limit(_out_limit), tmpbuf(ZBUFSIZE), mode(_mode)
17 ignore_decompression_errors = false;
18 full_flush = false;
19 init();
23 WvGzipEncoder::~WvGzipEncoder()
25 close();
29 void WvGzipEncoder::init()
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;
38 int retval;
39 if (mode == Deflate)
40 retval = deflateInit(zstr, Z_BEST_SPEED);
41 else
42 retval = inflateInit(zstr);
44 if (retval != Z_OK)
46 seterror("error %s initializing gzip %s: %s", retval,
47 mode == Deflate ? "compressor" : "decompressor",
48 zstr->msg ? zstr->msg : "unknown");
49 return;
51 zstr->next_in = zstr->next_out = NULL;
52 zstr->avail_in = zstr->avail_out = 0;
55 void WvGzipEncoder::close()
57 if (mode == Deflate)
58 deflateEnd(zstr);
59 else
60 inflateEnd(zstr);
62 delete zstr;
66 bool WvGzipEncoder::_encode(WvBuf &inbuf, WvBuf &outbuf, bool flush)
68 bool success;
69 output = 0;
70 for (;;)
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)
78 // unget unused data
79 inbuf.unget(zstr->avail_in);
80 zstr->avail_in = 0;
82 if (! success)
83 return false;
84 if (alldata || (starting_size == inbuf.used()) ||
85 (out_limit && (output >= out_limit)))
86 return true;
91 bool WvGzipEncoder::_finish(WvBuf &outbuf)
93 prepare(NULL);
94 return process(outbuf, false, true);
98 bool WvGzipEncoder::_reset()
100 close();
101 init();
102 return true;
106 void WvGzipEncoder::prepare(WvBuf *inbuf)
108 assert(zstr->avail_in == 0);
109 if (inbuf && inbuf->used() != 0)
111 size_t avail = inbuf->optgettable();
112 zstr->avail_in = avail;
113 zstr->next_in = const_cast<Bytef*>(
114 (const Bytef*)inbuf->get(avail));
116 else
118 zstr->avail_in = 0;
119 zstr->next_in = (Bytef*)""; // so it's not NULL
124 bool WvGzipEncoder::process(WvBuf &outbuf, bool flush, bool finish)
126 int flushmode = finish ? Z_FINISH :
127 flush ? (full_flush ? Z_FULL_FLUSH : Z_SYNC_FLUSH) : Z_NO_FLUSH;
128 int retval;
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);
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);
146 output += avail_out - zstr->avail_out;
148 // consume pending output
149 outbuf.merge(tmpbuf);
151 if (retval == Z_DATA_ERROR && mode == Inflate
152 && ignore_decompression_errors)
153 retval = inflateSync(zstr);
154 } while (retval == Z_OK && (!out_limit || (out_limit > output)));
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
160 && ignore_decompression_errors))
162 seterror("error %s during gzip %s: %s", retval,
163 mode == Deflate ? "compression" : "decompression",
164 zstr->msg ? zstr->msg : "unknown");
165 return false;
168 return true;