Panda3D
|
00001 // Filename: zStreamBuf.cxx 00002 // Created by: drose (05Aug02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 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 // Define functions that hook zlib into panda's memory allocation system. 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 // Function: ZStreamBuf::Constructor 00036 // Access: Public 00037 // Description: 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 // Function: ZStreamBuf::Destructor 00061 // Access: Public, Virtual 00062 // Description: 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 // Function: ZStreamBuf::open_read 00075 // Access: Public 00076 // Description: 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 // Function: ZStreamBuf::close_read 00107 // Access: Public 00108 // Description: 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 // Function: ZStreamBuf::open_write 00130 // Access: Public 00131 // Description: 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 // Function: ZStreamBuf::close_write 00162 // Access: Public 00163 // Description: 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 // Function: ZStreamBuf::overflow 00188 // Access: Protected, Virtual 00189 // Description: Called by the system ostream implementation when its 00190 // internal buffer is filled, plus one character. 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 // Write one more character. 00202 char c = ch; 00203 write_chars(&c, 1, 0); 00204 } 00205 00206 return 0; 00207 } 00208 00209 //////////////////////////////////////////////////////////////////// 00210 // Function: ZStreamBuf::sync 00211 // Access: Protected, Virtual 00212 // Description: Called by the system iostream implementation to 00213 // implement a flush operation. 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 // Function: ZStreamBuf::underflow 00234 // Access: Protected, Virtual 00235 // Description: Called by the system istream implementation when its 00236 // internal buffer needs more characters. 00237 //////////////////////////////////////////////////////////////////// 00238 int ZStreamBuf:: 00239 underflow() { 00240 // Sometimes underflow() is called even if the buffer is not empty. 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 // Oops, we didn't read what we thought we would. 00250 if (read_count == 0) { 00251 gbump(num_bytes); 00252 return EOF; 00253 } 00254 00255 // Slide what we did read to the top of the buffer. 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 // Function: ZStreamBuf::read_chars 00269 // Access: Private 00270 // Description: Gets some characters from the source stream. 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 // Here's the end of the file. 00295 return bytes_read; 00296 00297 } else if (result == Z_BUF_ERROR && flush == 0) { 00298 // We might get this if no progress is possible, for instance if 00299 // the input stream is truncated. In this case, tell zlib to 00300 // dump everything it's got. 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 // Function: ZStreamBuf::write_chars 00314 // Access: Private 00315 // Description: Sends some characters to the dest stream. The flush 00316 // parameter is passed to deflate(). 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 // Function: ZStreamBuf::show_zlib_error 00362 // Access: Private 00363 // Description: Reports a recent error code returned by zlib. 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