GzStream.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                                                                      |
00003 |                      __   __    ____ _____ ____                      |
00004 |                      \ \ / /_ _/ ___|_   _|___ \                     |
00005 |                       \ V / _` \___ \ | |   __) |                    |
00006 |                        | | (_| |___) || |  / __/                     |
00007 |                        |_|\__,_|____/ |_| |_____|                    |
00008 |                                                                      |
00009 |                               core system                            |
00010 |                                         (C) SuSE Linux Products GmbH |
00011 \----------------------------------------------------------------------/
00012 
00013   File:       GzStream.cc
00014 
00015   Author:     Michael Andres <ma@suse.de>
00016   Maintainer: Michael Andres <ma@suse.de>
00017 
00018   Purpose: Streams reading and writing gzip files.
00019 
00020 /-*/
00021 
00022 #include "zypp/base/GzStream.h"
00023 
00025 namespace zypp
00026 { 
00027 
00028   namespace gzstream_detail
00029   { 
00030 
00031 
00033     //
00034     //  CLASS NAME : ZlibError
00035     //
00037 
00039     //
00040     //  METHOD NAME : ZlibError::strerror
00041     //  METHOD TYPE : std::string
00042     //
00043     std::string
00044     ZlibError::strerror() const
00045     {
00046       std::string ret = ( _zError ? ::zError( _zError ) : "OK" );
00047       if ( _zError == Z_ERRNO )
00048         ret += std::string("(") + ::strerror( _errno ) + ")";
00049       return ret;
00050     }
00051 
00053     //
00054     //  CLASS NAME : fgzstreambuf
00055     //
00057 
00059     //
00060     //  METHOD NAME : fgzstreambuf::open
00061     //  METHOD TYPE : fgzstreambuf *
00062     //
00063     fgzstreambuf *
00064     fgzstreambuf::open( const char * name_r, std::ios_base::openmode mode_r )
00065     {
00066       fgzstreambuf * ret = NULL;
00067       if ( ! isOpen() )
00068         {
00069           if ( mode_r == std::ios_base::in )
00070             _file = gzopen( name_r, "rb" );
00071           else if ( mode_r == std::ios_base::out )
00072             _file = gzopen( name_r, "wb" );
00073           // else: not supported
00074 
00075           if ( isOpen() )
00076             {
00077               // Store mode and initialize the internal buffer.
00078               _mode = mode_r;
00079               if ( inReadMode() )
00080                 {
00081                   setp( NULL, NULL );
00082                   setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00083                 }
00084               else
00085                 {
00086                   setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
00087                   setg( NULL, NULL, NULL );
00088                 }
00089               ret = this;
00090             }
00091           else
00092             setZError();
00093         }
00094       return ret;
00095     }
00096 
00098     //
00099     //  METHOD NAME : fgzstreambuf::close
00100     //  METHOD TYPE : fgzstreambuf *
00101     //
00102     fgzstreambuf *
00103     fgzstreambuf::close()
00104     {
00105       fgzstreambuf * ret = NULL;
00106       if ( isOpen() )
00107         {
00108           bool failed = false;
00109           if ( sync() != 0 )
00110             failed = true;
00111           if ( gzclose( _file ) != Z_OK )
00112             {
00113               failed = true;
00114               setZError();
00115             }
00116 
00117           // Reset everything
00118           _file = NULL;
00119           _mode = std::ios_base::openmode(0);
00120           setp( NULL, NULL );
00121           setg( NULL, NULL, NULL );
00122           if ( ! failed )
00123             ret = this;
00124         }
00125       return ret;
00126     }
00127 
00129     //
00130     //  METHOD NAME : fgzstreambuf::sync
00131     //  METHOD TYPE : int
00132     //
00133     int
00134     fgzstreambuf::sync()
00135     {
00136       int ret = 0;
00137       if ( pbase() < pptr() ) {
00138         const int_type res = overflow();
00139         if ( traits_type::eq_int_type( res, traits_type::eof() ) )
00140           ret = -1;
00141       }
00142       return ret;
00143     }
00144 
00146     //
00147     //  METHOD NAME : fgzstreambuf::overflow
00148     //  METHOD TYPE : fgzstreambuf::int_type
00149     //
00150     fgzstreambuf::int_type
00151     fgzstreambuf::overflow( int_type c )
00152     {
00153       int_type ret = traits_type::eof();
00154       if ( inWriteMode() )
00155         {
00156           if ( ! traits_type::eq_int_type( c, traits_type::eof() ) )
00157             {
00158               *pptr() = traits_type::to_char_type( c );
00159               pbump(1);
00160             }
00161           if ( pbase() <= pptr() )
00162             {
00163               if ( zWriteFrom( pbase(), pptr() - pbase() ) )
00164                 {
00165                   setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
00166                   ret = traits_type::not_eof( c );
00167                 }
00168               // else: error writing the file
00169             }
00170         }
00171       return ret;
00172     }
00173 
00175     //
00176     //  METHOD NAME : fgzstreambuf::underflow
00177     //  METHOD TYPE : fgzstreambuf::int_type
00178     //
00179     fgzstreambuf::int_type
00180     fgzstreambuf::underflow()
00181     {
00182       int_type ret = traits_type::eof();
00183       if ( inReadMode() )
00184         {
00185           if ( gptr() < egptr() )
00186             return traits_type::to_int_type( *gptr() );
00187 
00188           const std::streamsize got = zReadTo( &(_buffer[0]), _buffer.size() );
00189           if ( got > 0 )
00190             {
00191               setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[got]) );
00192               ret = traits_type::to_int_type( *gptr() );
00193             }
00194           else if ( got == 0 )
00195             {
00196               // EOF
00197               setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00198             }
00199           // else: error reading the file
00200         }
00201       return ret;
00202     }
00203 
00205     //
00206     //  METHOD NAME : fgzstreambuf::zReadTo
00207     //  METHOD TYPE : std::streamsize
00208     //
00209     std::streamsize
00210     fgzstreambuf::zReadTo( char * buffer_r, std::streamsize maxcount_r )
00211     {
00212       int read = gzread( _file, buffer_r, maxcount_r );
00213       if ( read < 0 )
00214         setZError();
00215       return read;
00216     }
00217 
00219     //
00220     //  METHOD NAME : fgzstreambuf::zWriteFrom
00221     //  METHOD TYPE : bool
00222     //
00223     bool
00224     fgzstreambuf::zWriteFrom( const char * buffer_r, std::streamsize count_r )
00225     {
00226       int written = 0;
00227       if ( count_r )
00228         {
00229           if ( (written = gzwrite( _file, buffer_r, count_r )) == 0 )
00230             setZError();
00231         }
00232       return( written == count_r );
00233     }
00234 
00236     //
00237     //  METHOD NAME : fgzstreambuf::zSeekTo
00238     //  METHOD TYPE : fgzstreambuf::pos_type
00239     //
00240     fgzstreambuf::pos_type
00241     fgzstreambuf::zSeekTo( off_type off_r, std::ios_base::seekdir way_r )
00242     {
00243       z_off_t ret = gzseek( _file, off_r, way_r );
00244       if ( ret == -1 )
00245         setZError();
00246       return ret;
00247     }
00248 
00250     //
00251     //  METHOD NAME : fgzstreambuf::zTell
00252     //  METHOD TYPE : fgzstreambuf::pos_type
00253     //
00254     fgzstreambuf::pos_type
00255     fgzstreambuf::zTell()
00256     {
00257       z_off_t ret = gztell( _file );
00258       if ( ret == -1 )
00259         setZError();
00260       return ret;
00261     }
00262 
00264     //
00265     //  METHOD NAME : fgzstreambuf::seekTo
00266     //  METHOD TYPE : fgzstreambuf::pos_type
00267     //
00268     fgzstreambuf::pos_type
00269     fgzstreambuf::seekTo( off_type off_r, std::ios_base::seekdir way_r )
00270     {
00271       pos_type ret = pos_type(off_type(-1));
00272       if ( isOpen() )
00273         {
00274           if ( inWriteMode() )
00275             {
00276               if ( sync() == 0 )
00277                 ret = zSeekTo( off_r, way_r );
00278             }
00279           else
00280             {
00281               off_type zegptr = zTell();
00282               if ( zegptr != off_type(-1) )
00283                 {
00284                   if ( way_r == std::ios_base::end )
00285                     {
00286                       // Invalidate buffer and seek.
00287                       // XXX improve by transformation into ios_base::beg
00288                       // to see whether we stay inside the buffer.
00289                       setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00290                       ret = zSeekTo( off_r, way_r );
00291                     }
00292                   else
00293                     {
00294                       // Transform into ios_base::beg and seek.
00295                       off_type zeback = zegptr - ( egptr() - eback() );
00296                       off_type zgptr  = zegptr - ( egptr() - gptr() );
00297                       off_type zngptr = off_r;
00298                       if ( way_r == std::ios_base::cur )
00299                         {
00300                           zngptr += zgptr;
00301                           way_r = std::ios_base::beg;
00302                         }
00303 
00304                       if ( way_r == std::ios_base::beg )
00305                         {
00306                           if ( zeback <= zngptr && zngptr <= zegptr )
00307                             {
00308                               // Still inside buffer, adjust gptr and
00309                               // calculate new position.
00310                               setg( eback(),
00311                                     eback() + (zngptr-zeback),
00312                                     egptr() );
00313                               ret = pos_type(zngptr);
00314                             }
00315                           else
00316                             {
00317                               // Invalidate buffer and seek.
00318                               setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00319                               ret = zSeekTo( off_r, way_r );
00320                             }
00321                         }
00322                     }
00323                 }
00324             }
00325         }
00326       return ret;
00327     }
00328 
00330   } // namespace gzstream_detail
00333 } // namespace zypp
00335 

Generated on Thu Jul 6 00:07:20 2006 for zypp by  doxygen 1.4.6