00001
00002
00003
00004
00005
00006
00007
#include "wvgzip.h"
00008
#include <zlib.h>
00009
#include <assert.h>
00010
00011 #define ZBUFSIZE 10240
00012
00013
00014
00015 WvGzipEncoder::WvGzipEncoder(Mode _mode) :
00016 tmpbuf(
ZBUFSIZE), mode(_mode)
00017 {
00018 init();
00019 }
00020
00021
00022 WvGzipEncoder::~WvGzipEncoder()
00023 {
00024 close();
00025 }
00026
00027
00028
void WvGzipEncoder::init()
00029 {
00030 zstr =
new z_stream;
00031 memset(zstr, 0,
sizeof(*zstr));
00032 zstr->zalloc = Z_NULL;
00033 zstr->zfree = Z_NULL;
00034 zstr->opaque = NULL;
00035 zstr->msg = NULL;
00036
00037
int retval;
00038
if (mode == Deflate)
00039 retval = deflateInit(zstr, Z_DEFAULT_COMPRESSION);
00040
else
00041 retval = inflateInit(zstr);
00042
00043
if (retval != Z_OK)
00044 {
00045 seterror(
"error %s initializing gzip %s: %s", retval,
00046 mode == Deflate ?
"compressor" :
"decompressor",
00047 zstr->msg ? zstr->msg :
"unknown");
00048
return;
00049 }
00050 zstr->next_in = zstr->next_out = NULL;
00051 zstr->avail_in = zstr->avail_out = 0;
00052 }
00053
00054
void WvGzipEncoder::close()
00055 {
00056
if (mode ==
Deflate)
00057 deflateEnd(zstr);
00058
else
00059 inflateEnd(zstr);
00060
00061
delete zstr;
00062
00063 }
00064
00065 bool WvGzipEncoder::_encode(
WvBuf &inbuf,
WvBuf &outbuf,
bool flush)
00066 {
00067
bool success;
00068
for (;;)
00069 {
00070 prepare(& inbuf);
00071
bool alldata = inbuf.
used() == 0;
00072 success = process(outbuf, flush && alldata,
false);
00073
if (zstr->avail_in != 0)
00074 {
00075
00076 inbuf.
unget(zstr->avail_in);
00077 zstr->avail_in = 0;
00078 }
00079
if (! success)
00080
return false;
00081
if (alldata)
00082
return true;
00083 }
00084 }
00085
00086
00087 bool WvGzipEncoder::_finish(
WvBuf &outbuf)
00088 {
00089 prepare(NULL);
00090
return process(outbuf,
false,
true);
00091 }
00092
00093
00094 bool WvGzipEncoder::_reset()
00095 {
00096 close();
00097 init();
00098
return true;
00099 }
00100
00101
00102
void WvGzipEncoder::prepare(
WvBuf *inbuf)
00103 {
00104 assert(zstr->avail_in == 0);
00105
if (inbuf && inbuf->
used() != 0)
00106 {
00107 size_t avail = inbuf->
optgettable();
00108 zstr->avail_in = avail;
00109 zstr->next_in = const_cast<Bytef*>(
00110 (
const Bytef*)inbuf->
get(avail));
00111 }
00112
else
00113 {
00114 zstr->avail_in = 0;
00115 zstr->next_in = (Bytef*)
"";
00116 }
00117 }
00118
00119
00120
bool WvGzipEncoder::process(
WvBuf &outbuf,
bool flush,
bool finish)
00121 {
00122
int flushmode = finish ? Z_FINISH :
00123 flush ? Z_SYNC_FLUSH : Z_NO_FLUSH;
00124
int retval;
00125
do
00126 {
00127
00128 tmpbuf.
zap();
00129 zstr->avail_out = tmpbuf.
free();
00130 zstr->next_out = tmpbuf.
alloc(tmpbuf.
free());
00131
if (mode ==
Deflate)
00132 retval = deflate(zstr, flushmode);
00133
else
00134 retval = inflate(zstr, flushmode);
00135 tmpbuf.
unalloc(zstr->avail_out);
00136
00137
00138 outbuf.
merge(tmpbuf);
00139 }
while (retval == Z_OK);
00140
00141
if (retval == Z_STREAM_END)
00142
setfinished();
00143
else if (retval != Z_OK && retval != Z_BUF_ERROR)
00144 {
00145
seterror(
"error %s during gzip %s: %s", retval,
00146 mode == Deflate ?
"compression" :
"decompression",
00147 zstr->msg ? zstr->msg :
"unknown");
00148
return false;
00149 }
00150
return true;
00151 }
00152