deflateoutputstreambuf.cpp

Go to the documentation of this file.
00001 
00002 #include "zipios-config.h"
00003 
00004 #include "meta-iostreams.h"
00005 
00006 #include <zlib.h>
00007 
00008 #include "fcollexceptions.h"
00009 #include "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 */

Generated on Wed Nov 23 19:00:05 2011 for FreeCAD by  doxygen 1.6.1