Main Page   Class Hierarchy   Compound List   File List   Compound Members  

zipoutputstreambuf.cpp

Go to the documentation of this file.
00001 
00002 #include "zipios++/zipios-config.h"
00003 
00004 #include <algorithm>
00005 #include "zipios++/meta-iostreams.h"
00006 
00007 #include <zlib.h>
00008 
00009 #include "zipios++/zipoutputstreambuf.h"
00010 
00011 namespace zipios {
00012 
00013 using std::ios ;
00014 using std::cerr ;
00015 using std::endl ;
00016 using std::min ;
00017 
00018 ZipOutputStreambuf::ZipOutputStreambuf( streambuf *outbuf, bool del_outbuf ) 
00019   : DeflateOutputStreambuf( outbuf, false, del_outbuf ),
00020     _open_entry( false    ),
00021     _open      ( true     ),
00022     _method    ( DEFLATED ),
00023     _level     ( 6        )
00024 {
00025 }
00026 
00027 
00028 void ZipOutputStreambuf::closeEntry() {
00029   if ( ! _open_entry )
00030     return ;
00031 
00032   closeStream() ;
00033 
00034   updateEntryHeaderInfo() ;
00035   setEntryClosedState( ) ;
00036 }
00037 
00038 
00039 void ZipOutputStreambuf::close() {
00040   finish() ;
00041 }
00042 
00043 
00044 void ZipOutputStreambuf::finish() {
00045   if( ! _open )
00046     return ;
00047   closeEntry() ;
00048   ostream os( _outbuf ) ;
00049   writeCentralDirectory( _entries, EndOfCentralDirectory( _zip_comment), os ) ;
00050   _open = false ;
00051 }
00052 
00053 
00054 ZipOutputStreambuf::~ZipOutputStreambuf() {
00055   finish() ;
00056 }
00057 
00058 
00059 void ZipOutputStreambuf::putNextEntry( const ZipCDirEntry &entry ) {
00060   if ( _open_entry )
00061     closeEntry() ;
00062 
00063   if ( ! init( _level ) )
00064     cerr << "ZipOutputStreambuf::putNextEntry(): init() failed!\n" ;
00065 
00066   _entries.push_back( entry ) ;
00067   ZipCDirEntry &ent = _entries.back() ;
00068 
00069   ostream os( _outbuf ) ;
00070 
00071   // Update entry header info
00072   ent.setLocalHeaderOffset( os.tellp() ) ;
00073   ent.setMethod( _method ) ;
00074   
00075   os << static_cast< ZipLocalEntry >( ent ) ;
00076 
00077   _open_entry = true ;
00078 }
00079 
00080 
00081 void ZipOutputStreambuf::setComment( const string &comment ) {
00082   _zip_comment = comment ;
00083 }
00084 
00085 
00086 void ZipOutputStreambuf::setLevel( int level ) {
00087   _level = level ;
00088 }
00089 
00090 
00091 void ZipOutputStreambuf::setMethod( StorageMethod method ) {
00092   _method = method ;
00093   if( method == STORED )
00094     setLevel( NO_COMPRESSION ) ;
00095   else if ( method == DEFLATED ) {
00096     if( _level == NO_COMPRESSION )
00097       setLevel( DEFAULT_COMPRESSION ) ; 
00098   } else 
00099     throw FCollException( "Specified compression method not supported" ) ;
00100 }
00101 
00102 //
00103 // Protected and private methods
00104 //
00105 
00106 int ZipOutputStreambuf::overflow( int c ) {
00107   return DeflateOutputStreambuf::overflow( c ) ;
00108 //    // FIXME: implement
00109   
00110 //    cout << "ZipOutputStreambuf::overflow() not implemented yet!\n" ;
00111 //    return EOF ;
00112 }
00113 
00114 
00115 
00116 int ZipOutputStreambuf::sync() {
00117   return DeflateOutputStreambuf::sync() ;
00118 //    // FIXME: implement
00119 //    cout << "ZipOutputStreambuf::sync() not implemented yet!\n" ;
00120 //    return EOF ;
00121 }
00122 
00123 
00124 
00125 void ZipOutputStreambuf::setEntryClosedState() {
00126   _open_entry = false ;
00127   // FIXME: update put pointers to trigger overflow on write. overflow
00128   // should then return EOF while _open_entry is false.
00129 }
00130 
00131 
00132 void ZipOutputStreambuf::updateEntryHeaderInfo() {
00133   if ( ! _open_entry )
00134     return ;
00135 
00136   ostream os( _outbuf ) ;
00137   int curr_pos = os.tellp() ;
00138   
00139   // update fields in _entries.back()
00140   ZipCDirEntry &entry = _entries.back() ;
00141   entry.setSize( getCount() ) ;
00142   entry.setCrc( getCrc32() ) ;
00143   entry.setCompressedSize( curr_pos - entry.getLocalHeaderOffset() 
00144                            - entry.getLocalHeaderSize() ) ;
00145 
00146   // write ZipLocalEntry header to header position
00147   os.seekp( entry.getLocalHeaderOffset() ) ;
00148   os << static_cast< ZipLocalEntry >( entry ) ;
00149   os.seekp( curr_pos ) ;
00150 }
00151 
00152 
00153 void ZipOutputStreambuf::writeCentralDirectory( const vector< ZipCDirEntry > &entries, 
00154                                                 EndOfCentralDirectory eocd, 
00155                                                 ostream &os ) {
00156   int cdir_start = os.tellp() ;
00157   vector< ZipCDirEntry >::const_iterator it ;
00158   int cdir_size = 0 ;
00159 
00160   for ( it = entries.begin() ; it != entries.end() ; ++it ) {
00161     os << *it ;
00162     cdir_size += it->getCDirHeaderSize() ;
00163   }
00164   eocd.setOffset( cdir_start ) ;
00165   eocd.setCDirSize( cdir_size ) ;
00166   eocd.setTotalCount( entries.size() ) ;
00167   os << eocd ;
00168 }
00169 
00170 } // namespace
00171 
00176 /*
00177   Zipios++ - a small C++ library that provides easy access to .zip files.
00178   Copyright (C) 2000  Thomas Søndergaard
00179   
00180   This library is free software; you can redistribute it and/or
00181   modify it under the terms of the GNU Lesser General Public
00182   License as published by the Free Software Foundation; either
00183   version 2 of the License, or (at your option) any later version.
00184   
00185   This library is distributed in the hope that it will be useful,
00186   but WITHOUT ANY WARRANTY; without even the implied warranty of
00187   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00188   Lesser General Public License for more details.
00189   
00190   You should have received a copy of the GNU Lesser General Public
00191   License along with this library; if not, write to the Free Software
00192   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00193 */

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