00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "zStreamBuf.h"
00016
00017 #ifdef HAVE_ZLIB
00018
00019 #include "pnotify.h"
00020 #include "config_express.h"
00021
00022 #if !defined(USE_MEMORY_NOWRAPPERS)
00023
00024 static void *
00025 do_zlib_alloc(voidpf opaque, uInt items, uInt size) {
00026 return PANDA_MALLOC_ARRAY(items * size);
00027 }
00028 static void
00029 do_zlib_free(voidpf opaque, voidpf address) {
00030 PANDA_FREE_ARRAY(address);
00031 }
00032 #endif // !USE_MEMORY_NOWRAPPERS
00033
00034
00035
00036
00037
00038
00039 ZStreamBuf::
00040 ZStreamBuf() {
00041 _source = (istream *)NULL;
00042 _owns_source = false;
00043 _dest = (ostream *)NULL;
00044 _owns_dest = false;
00045
00046 #ifdef PHAVE_IOSTREAM
00047 _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
00048 char *ebuf = _buffer + 4096;
00049 setg(_buffer, ebuf, ebuf);
00050 setp(_buffer, ebuf);
00051
00052 #else
00053 allocate();
00054 setg(base(), ebuf(), ebuf());
00055 setp(base(), ebuf());
00056 #endif
00057 }
00058
00059
00060
00061
00062
00063
00064 ZStreamBuf::
00065 ~ZStreamBuf() {
00066 close_read();
00067 close_write();
00068 #ifdef PHAVE_IOSTREAM
00069 PANDA_FREE_ARRAY(_buffer);
00070 #endif
00071 }
00072
00073
00074
00075
00076
00077
00078 void ZStreamBuf::
00079 open_read(istream *source, bool owns_source) {
00080 _source = source;
00081 _owns_source = owns_source;
00082
00083 _z_source.next_in = Z_NULL;
00084 _z_source.avail_in = 0;
00085 _z_source.next_out = Z_NULL;
00086 _z_source.avail_out = 0;
00087 #ifdef USE_MEMORY_NOWRAPPERS
00088 _z_source.zalloc = Z_NULL;
00089 _z_source.zfree = Z_NULL;
00090 #else
00091 _z_source.zalloc = (alloc_func)&do_zlib_alloc;
00092 _z_source.zfree = (free_func)&do_zlib_free;
00093 #endif
00094 _z_source.opaque = Z_NULL;
00095 _z_source.msg = (char *)"no error message";
00096
00097 int result = inflateInit(&_z_source);
00098 if (result < 0) {
00099 show_zlib_error("inflateInit", result, _z_source);
00100 close_read();
00101 }
00102 thread_consider_yield();
00103 }
00104
00105
00106
00107
00108
00109
00110 void ZStreamBuf::
00111 close_read() {
00112 if (_source != (istream *)NULL) {
00113
00114 int result = inflateEnd(&_z_source);
00115 if (result < 0) {
00116 show_zlib_error("inflateEnd", result, _z_source);
00117 }
00118 thread_consider_yield();
00119
00120 if (_owns_source) {
00121 delete _source;
00122 _owns_source = false;
00123 }
00124 _source = (istream *)NULL;
00125 }
00126 }
00127
00128
00129
00130
00131
00132
00133 void ZStreamBuf::
00134 open_write(ostream *dest, bool owns_dest, int compression_level) {
00135 _dest = dest;
00136 _owns_dest = owns_dest;
00137
00138 _z_dest.next_in = Z_NULL;
00139 _z_dest.avail_in = 0;
00140 _z_dest.next_out = Z_NULL;
00141 _z_dest.avail_out = 0;
00142 #ifdef USE_MEMORY_NOWRAPPERS
00143 _z_dest.zalloc = Z_NULL;
00144 _z_dest.zfree = Z_NULL;
00145 #else
00146 _z_dest.zalloc = (alloc_func)&do_zlib_alloc;
00147 _z_dest.zfree = (free_func)&do_zlib_free;
00148 #endif
00149 _z_dest.opaque = Z_NULL;
00150 _z_dest.msg = (char *)"no error message";
00151
00152 int result = deflateInit(&_z_dest, compression_level);
00153 if (result < 0) {
00154 show_zlib_error("deflateInit", result, _z_dest);
00155 close_write();
00156 }
00157 thread_consider_yield();
00158 }
00159
00160
00161
00162
00163
00164
00165 void ZStreamBuf::
00166 close_write() {
00167 if (_dest != (ostream *)NULL) {
00168 size_t n = pptr() - pbase();
00169 write_chars(pbase(), n, Z_FINISH);
00170 pbump(-(int)n);
00171
00172 int result = deflateEnd(&_z_dest);
00173 if (result < 0) {
00174 show_zlib_error("deflateEnd", result, _z_dest);
00175 }
00176 thread_consider_yield();
00177
00178 if (_owns_dest) {
00179 delete _dest;
00180 _owns_dest = false;
00181 }
00182 _dest = (ostream *)NULL;
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 int ZStreamBuf::
00193 overflow(int ch) {
00194 size_t n = pptr() - pbase();
00195 if (n != 0) {
00196 write_chars(pbase(), n, 0);
00197 pbump(-(int)n);
00198 }
00199
00200 if (ch != EOF) {
00201
00202 char c = ch;
00203 write_chars(&c, 1, 0);
00204 }
00205
00206 return 0;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 int ZStreamBuf::
00216 sync() {
00217 if (_source != (istream *)NULL) {
00218 size_t n = egptr() - gptr();
00219 gbump(n);
00220 }
00221
00222 if (_dest != (ostream *)NULL) {
00223 size_t n = pptr() - pbase();
00224 write_chars(pbase(), n, Z_SYNC_FLUSH);
00225 pbump(-(int)n);
00226 }
00227
00228 _dest->flush();
00229 return 0;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 int ZStreamBuf::
00239 underflow() {
00240
00241 if (gptr() >= egptr()) {
00242 size_t buffer_size = egptr() - eback();
00243 gbump(-(int)buffer_size);
00244
00245 size_t num_bytes = buffer_size;
00246 size_t read_count = read_chars(gptr(), buffer_size);
00247
00248 if (read_count != num_bytes) {
00249
00250 if (read_count == 0) {
00251 gbump(num_bytes);
00252 return EOF;
00253 }
00254
00255
00256 nassertr(read_count < num_bytes, EOF);
00257 size_t delta = num_bytes - read_count;
00258 memmove(gptr() + delta, gptr(), read_count);
00259 gbump(delta);
00260 }
00261 }
00262
00263 return (unsigned char)*gptr();
00264 }
00265
00266
00267
00268
00269
00270
00271
00272 size_t ZStreamBuf::
00273 read_chars(char *start, size_t length) {
00274 _z_source.next_out = (Bytef *)start;
00275 _z_source.avail_out = length;
00276
00277 bool eof = (_source->eof() || _source->fail());
00278 int flush = 0;
00279
00280 while (_z_source.avail_out > 0) {
00281 if (_z_source.avail_in == 0 && !eof) {
00282 _source->read(decompress_buffer, decompress_buffer_size);
00283 size_t read_count = _source->gcount();
00284 eof = (read_count == 0 || _source->eof() || _source->fail());
00285
00286 _z_source.next_in = (Bytef *)decompress_buffer;
00287 _z_source.avail_in = read_count;
00288 }
00289 int result = inflate(&_z_source, flush);
00290 thread_consider_yield();
00291 size_t bytes_read = length - _z_source.avail_out;
00292
00293 if (result == Z_STREAM_END) {
00294
00295 return bytes_read;
00296
00297 } else if (result == Z_BUF_ERROR && flush == 0) {
00298
00299
00300
00301 flush = Z_FINISH;
00302
00303 } else if (result < 0) {
00304 show_zlib_error("inflate", result, _z_source);
00305 return bytes_read;
00306 }
00307 }
00308
00309 return length;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 void ZStreamBuf::
00319 write_chars(const char *start, size_t length, int flush) {
00320 static const size_t compress_buffer_size = 4096;
00321 char compress_buffer[compress_buffer_size];
00322
00323 _z_dest.next_in = (Bytef *)(char *)start;
00324 _z_dest.avail_in = length;
00325
00326 _z_dest.next_out = (Bytef *)compress_buffer;
00327 _z_dest.avail_out = compress_buffer_size;
00328
00329 int result = deflate(&_z_dest, flush);
00330 if (result < 0 && result != Z_BUF_ERROR) {
00331 show_zlib_error("deflate", result, _z_dest);
00332 }
00333 thread_consider_yield();
00334
00335 while (_z_dest.avail_in != 0) {
00336 if (_z_dest.avail_out != compress_buffer_size) {
00337 _dest->write(compress_buffer, compress_buffer_size - _z_dest.avail_out);
00338 _z_dest.next_out = (Bytef *)compress_buffer;
00339 _z_dest.avail_out = compress_buffer_size;
00340 }
00341 result = deflate(&_z_dest, flush);
00342 if (result < 0) {
00343 show_zlib_error("deflate", result, _z_dest);
00344 }
00345 thread_consider_yield();
00346 }
00347
00348 while (_z_dest.avail_out != compress_buffer_size) {
00349 _dest->write(compress_buffer, compress_buffer_size - _z_dest.avail_out);
00350 _z_dest.next_out = (Bytef *)compress_buffer;
00351 _z_dest.avail_out = compress_buffer_size;
00352 result = deflate(&_z_dest, flush);
00353 if (result < 0 && result != Z_BUF_ERROR) {
00354 show_zlib_error("deflate", result, _z_dest);
00355 }
00356 thread_consider_yield();
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365 void ZStreamBuf::
00366 show_zlib_error(const char *function, int error_code, z_stream &z) {
00367 stringstream error_line;
00368
00369 error_line
00370 << "zlib error in " << function << ": ";
00371 switch (error_code) {
00372 case Z_OK:
00373 error_line << "Z_OK";
00374 break;
00375 case Z_STREAM_END:
00376 error_line << "Z_STREAM_END";
00377 break;
00378 case Z_NEED_DICT:
00379 error_line << "Z_NEED_DICT";
00380 break;
00381 case Z_ERRNO:
00382 error_line << "Z_ERRNO";
00383 break;
00384 case Z_STREAM_ERROR:
00385 error_line << "Z_STREAM_ERROR";
00386 break;
00387 case Z_DATA_ERROR:
00388 error_line << "Z_DATA_ERROR";
00389 break;
00390 case Z_MEM_ERROR:
00391 error_line << "Z_MEM_ERROR";
00392 break;
00393 case Z_BUF_ERROR:
00394 error_line << "Z_BUF_ERROR";
00395 break;
00396 case Z_VERSION_ERROR:
00397 error_line << "Z_VERSION_ERROR";
00398 break;
00399 default:
00400 error_line << error_code;
00401 }
00402 if (z.msg != (char *)NULL) {
00403 error_line
00404 << " = " << z.msg;
00405 }
00406
00407 express_cat.warning() << error_line.str() << "\n";
00408 }
00409
00410 #endif // HAVE_ZLIB