Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/express/zStreamBuf.cxx

Go to the documentation of this file.
00001 // Filename: zStreamBuf.cxx
00002 // Created by:  drose (05Aug02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "zStreamBuf.h"
00020 
00021 #ifdef HAVE_ZLIB
00022 
00023 #ifndef HAVE_STREAMSIZE
00024 // Some compilers (notably SGI) don't define this for us
00025 typedef int streamsize;
00026 #endif /* HAVE_STREAMSIZE */
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: ZStreamBuf::Constructor
00030 //       Access: Public
00031 //  Description:
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 //     Function: ZStreamBuf::Destructor
00055 //       Access: Public, Virtual
00056 //  Description:
00057 ////////////////////////////////////////////////////////////////////
00058 ZStreamBuf::
00059 ~ZStreamBuf() {
00060   close_read();
00061   close_write();
00062 }
00063 
00064 ////////////////////////////////////////////////////////////////////
00065 //     Function: ZStreamBuf::open_read
00066 //       Access: Public
00067 //  Description:
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 //     Function: ZStreamBuf::close_read
00090 //       Access: Public
00091 //  Description:
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 //     Function: ZStreamBuf::open_write
00112 //       Access: Public
00113 //  Description:
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 //     Function: ZStreamBuf::close_write
00134 //       Access: Public
00135 //  Description:
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 //     Function: ZStreamBuf::overflow
00159 //       Access: Protected, Virtual
00160 //  Description: Called by the system ostream implementation when its
00161 //               internal buffer is filled, plus one character.
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     // Write one more character.
00173     char c = ch;
00174     write_chars(&c, 1, 0);
00175   }
00176 
00177   return 0;
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: ZStreamBuf::sync
00182 //       Access: Protected, Virtual
00183 //  Description: Called by the system iostream implementation to
00184 //               implement a flush operation.
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 //     Function: ZStreamBuf::underflow
00204 //       Access: Protected, Virtual
00205 //  Description: Called by the system istream implementation when its
00206 //               internal buffer needs more characters.
00207 ////////////////////////////////////////////////////////////////////
00208 int ZStreamBuf::
00209 underflow() {
00210   // Sometimes underflow() is called even if the buffer is not empty.
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       // Oops, we didn't read what we thought we would.
00220       if (read_count == 0) {
00221         gbump(num_bytes);
00222         return EOF;
00223       }
00224 
00225       // Slide what we did read to the top of the buffer.
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 //     Function: ZStreamBuf::read_chars
00239 //       Access: Private
00240 //  Description: Gets some characters from the source stream.
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       // Here's the end of the file.
00263       return bytes_read;
00264     }
00265     // It might return Z_BUF_ERROR if we passed in Z_FINISH but not a
00266     // big enough output buffer for everything.
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 //     Function: ZStreamBuf::write_chars
00278 //       Access: Private
00279 //  Description: Sends some characters to the dest stream.  The flush
00280 //               parameter is passed to deflate().
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 //     Function: ZStreamBuf::show_zlib_error
00323 //       Access: Private
00324 //  Description: Reports a recent error code returned by zlib.
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

Generated on Fri May 2 00:38:52 2003 for Panda by doxygen1.3