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