Zipios++
|
00001 00002 #include "zipios++/zipios-config.h" 00003 00004 #include "zipios++/meta-iostreams.h" 00005 00006 #include <zlib.h> 00007 00008 #include "zipios++/fcollexceptions.h" 00009 #include "zipios++/deflateoutputstreambuf.h" 00010 00011 #include "outputstringstream.h" 00012 00013 namespace zipios { 00014 00015 using std::cerr ; 00016 using std::endl ; 00017 00018 DeflateOutputStreambuf::DeflateOutputStreambuf( streambuf *outbuf, bool user_init, 00019 bool del_outbuf ) 00020 : FilterOutputStreambuf( outbuf, del_outbuf ), 00021 _zs_initialized ( false ), 00022 _invecsize ( 1000 ), 00023 _invec ( _invecsize ), 00024 _outvecsize ( 1000 ), 00025 _outvec ( _outvecsize ) 00026 { 00027 // NOTICE: It is important that this constructor and the methods it 00028 // calls doesn't do anything with the output streambuf _outbuf The 00029 // reason is that this class can be subclassed, and the subclass 00030 // should get a chance to write to the buffer first 00031 00032 // zlib init: 00033 _zs.zalloc = Z_NULL ; 00034 _zs.zfree = Z_NULL ; 00035 _zs.opaque = Z_NULL ; 00036 00037 if ( user_init && ! init() ) 00038 cerr << "DeflateOutputStreambuf::reset() failed!\n" ; // FIXME: throw something 00039 00040 } 00041 00042 00043 DeflateOutputStreambuf::~DeflateOutputStreambuf() { 00044 closeStream() ; 00045 } 00046 00047 00048 // This method is called in the constructor, so it must not write 00049 // anything to the output streambuf _outbuf (see notice in 00050 // constructor) 00051 bool DeflateOutputStreambuf::init( int comp_level ) { 00052 static const int default_mem_level = 8 ; 00053 00054 // _zs.next_in and avail_in must be set according to 00055 // zlib.h (inline doc). 00056 _zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ; 00057 _zs.avail_in = 0 ; 00058 00059 _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ; 00060 _zs.avail_out = _outvecsize ; 00061 00062 int err ; 00063 if( _zs_initialized ) { // just reset it 00064 endDeflation() ; 00065 err = deflateReset( &_zs ) ; 00066 // FIXME: bug, for deflateReset we do not update the compression level 00067 } else { // init it 00068 err = deflateInit2( &_zs, comp_level, Z_DEFLATED, -MAX_WBITS, 00069 default_mem_level, Z_DEFAULT_STRATEGY ) ; 00070 /* windowBits is passed < 0 to tell that no zlib header should be 00071 written. */ 00072 _zs_initialized = true ; 00073 } 00074 00075 // streambuf init: 00076 setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ; 00077 00078 _crc32 = crc32( 0, Z_NULL, 0 ) ; 00079 _overflown_bytes = 0 ; 00080 00081 if ( err == Z_OK ) 00082 return true ; 00083 else 00084 return false ; 00085 } 00086 00087 00088 bool DeflateOutputStreambuf::closeStream() { 00089 int err = Z_OK ; 00090 if( _zs_initialized ) { 00091 endDeflation() ; 00092 err = deflateEnd( &_zs ) ; 00093 _zs_initialized = false ; 00094 } 00095 00096 if ( err == Z_OK ) 00097 return true ; 00098 else { 00099 cerr << "DeflateOutputStreambuf::closeStream(): deflateEnd failed" ; 00100 #ifdef HAVE_ZERROR 00101 cerr << ": " << zError( err ) ; 00102 #endif 00103 cerr << endl ; 00104 return false ; 00105 } 00106 } 00107 00108 00109 int DeflateOutputStreambuf::overflow( int c ) { 00110 _zs.avail_in = pptr() - pbase() ; 00111 _zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ; 00112 00113 _crc32 = crc32( _crc32, _zs.next_in, _zs.avail_in ) ; // update crc32 00114 _overflown_bytes += _zs.avail_in ; 00115 00116 _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ; 00117 _zs.avail_out = _outvecsize ; 00118 00119 // Deflate until _invec is empty. 00120 int err = Z_OK ; 00121 while ( ( _zs.avail_in > 0 || _zs.avail_out == 0 ) && err == Z_OK ) { 00122 if ( _zs.avail_out == 0 ) 00123 flushOutvec() ; 00124 00125 err = deflate( &_zs, Z_NO_FLUSH ) ; 00126 } 00127 00128 flushOutvec() ; 00129 00130 // Update 'put' pointers 00131 setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ; 00132 00133 if( err != Z_OK && err != Z_STREAM_END ) { 00134 #if defined (HAVE_STD_IOSTREAM) && defined (USE_STD_IOSTREAM) 00135 // Throw an exception to make istream set badbit 00136 OutputStringStream msgs ; 00137 msgs << "Deflation failed" ; 00138 #ifdef HAVE_ZERROR 00139 msgs << ": " << zError( err ) ; 00140 #endif 00141 throw IOException( msgs.str() ) ; 00142 #endif 00143 cerr << "Deflation failed\n" ; 00144 return EOF ; 00145 } 00146 00147 if ( c != EOF ) { 00148 *pptr() = c ; 00149 pbump( 1 ) ; 00150 } 00151 00152 return 0 ; 00153 } 00154 00155 int DeflateOutputStreambuf::sync() { 00156 // FIXME: Do something 00157 // return overflow() ; 00158 return 0 ; 00159 } 00160 00161 00162 bool DeflateOutputStreambuf::flushOutvec() { 00163 int deflated_bytes = _outvecsize - _zs.avail_out ; 00164 int bc = _outbuf->sputn( &( _outvec[ 0 ] ), deflated_bytes ) ; 00165 00166 _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ; 00167 _zs.avail_out = _outvecsize ; 00168 00169 return deflated_bytes == bc ; 00170 } 00171 00172 00173 void DeflateOutputStreambuf::endDeflation() { 00174 overflow() ; 00175 00176 _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ; 00177 _zs.avail_out = _outvecsize ; 00178 00179 // Deflate until _invec is empty. 00180 int err = Z_OK ; 00181 00182 while ( err == Z_OK ) { 00183 if ( _zs.avail_out == 0 ) 00184 flushOutvec() ; 00185 00186 err = deflate( &_zs, Z_FINISH ) ; 00187 } 00188 00189 flushOutvec() ; 00190 00191 if ( err != Z_STREAM_END ) { 00192 cerr << "DeflateOutputStreambuf::endDeflation(): deflation failed:\n" ; 00193 #ifdef HAVE_ZERROR 00194 cerr << ": " << zError( err ) ; 00195 #endif 00196 cerr << endl ; 00197 } 00198 } 00199 00200 00201 } // namespace 00202 00207 /* 00208 Zipios++ - a small C++ library that provides easy access to .zip files. 00209 Copyright (C) 2000 Thomas Søndergaard 00210 00211 This library is free software; you can redistribute it and/or 00212 modify it under the terms of the GNU Lesser General Public 00213 License as published by the Free Software Foundation; either 00214 version 2 of the License, or (at your option) any later version. 00215 00216 This library is distributed in the hope that it will be useful, 00217 but WITHOUT ANY WARRANTY; without even the implied warranty of 00218 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00219 Lesser General Public License for more details. 00220 00221 You should have received a copy of the GNU Lesser General Public 00222 License along with this library; if not, write to the Free Software 00223 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00224 */