2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Gzip encoder/decoder based on zlib.
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;
23 WvGzipEncoder::~WvGzipEncoder()
29 void WvGzipEncoder::init()
32 memset(zstr
, 0, sizeof(*zstr
));
33 zstr
->zalloc
= Z_NULL
;
40 retval
= deflateInit(zstr
, Z_BEST_SPEED
);
42 retval
= inflateInit(zstr
);
46 seterror("error %s initializing gzip %s: %s", retval
,
47 mode
== Deflate
? "compressor" : "decompressor",
48 zstr
->msg
? zstr
->msg
: "unknown");
51 zstr
->next_in
= zstr
->next_out
= NULL
;
52 zstr
->avail_in
= zstr
->avail_out
= 0;
55 void WvGzipEncoder::close()
66 bool WvGzipEncoder::_encode(WvBuf
&inbuf
, WvBuf
&outbuf
, bool flush
)
72 size_t starting_size
= inbuf
.used();
74 bool alldata
= inbuf
.used() == 0;
75 success
= process(outbuf
, flush
&& alldata
, false);
76 if (zstr
->avail_in
!= 0)
79 inbuf
.unget(zstr
->avail_in
);
84 if (alldata
|| (starting_size
== inbuf
.used()) ||
85 (out_limit
&& (output
>= out_limit
)))
91 bool WvGzipEncoder::_finish(WvBuf
&outbuf
)
94 return process(outbuf
, false, true);
98 bool WvGzipEncoder::_reset()
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
));
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
;
131 // process the next chunk
133 size_t avail_out
= tmpbuf
.free();
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
);
141 retval
= deflate(zstr
, flushmode
);
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
)
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");