Main Page   Class Hierarchy   Compound List   File List   Compound Members  

deflateoutputstreambuf.cpp

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

Generated at Tue Aug 14 20:39:26 2001 for Zipios++ by doxygen1.2.0 written by Dimitri van Heesch, © 1997-2000