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