
git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5000 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
206 lines
5.1 KiB
C++
206 lines
5.1 KiB
C++
|
||
#include "zipios-config.h"
|
||
|
||
#include <algorithm>
|
||
#include <vector>
|
||
#include <time.h>
|
||
#include "meta-iostreams.h"
|
||
|
||
#include <zlib.h>
|
||
|
||
#include "zipoutputstreambuf.h"
|
||
|
||
namespace zipios {
|
||
|
||
using std::ios ;
|
||
using std::cerr ;
|
||
using std::endl ;
|
||
using std::min ;
|
||
using std::vector ;
|
||
|
||
ZipOutputStreambuf::ZipOutputStreambuf( streambuf *outbuf, bool del_outbuf )
|
||
: DeflateOutputStreambuf( outbuf, false, del_outbuf ),
|
||
_open_entry( false ),
|
||
_open ( true ),
|
||
_method ( DEFLATED ),
|
||
_level ( 6 )
|
||
{
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::closeEntry() {
|
||
if ( ! _open_entry )
|
||
return ;
|
||
|
||
closeStream() ;
|
||
|
||
updateEntryHeaderInfo() ;
|
||
setEntryClosedState( ) ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::close() {
|
||
finish() ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::finish() {
|
||
if( ! _open )
|
||
return ;
|
||
closeEntry() ;
|
||
ostream os( _outbuf ) ;
|
||
writeCentralDirectory( _entries, EndOfCentralDirectory( _zip_comment), os ) ;
|
||
_open = false ;
|
||
}
|
||
|
||
|
||
ZipOutputStreambuf::~ZipOutputStreambuf() {
|
||
finish() ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::putNextEntry( const ZipCDirEntry &entry ) {
|
||
if ( _open_entry )
|
||
closeEntry() ;
|
||
|
||
if ( ! init( _level ) )
|
||
cerr << "ZipOutputStreambuf::putNextEntry(): init() failed!\n" ;
|
||
|
||
_entries.push_back( entry ) ;
|
||
ZipCDirEntry &ent = _entries.back() ;
|
||
|
||
ostream os( _outbuf ) ;
|
||
|
||
// Update entry header info
|
||
ent.setLocalHeaderOffset( os.tellp() ) ;
|
||
ent.setMethod( _method ) ;
|
||
|
||
os << static_cast< ZipLocalEntry >( ent ) ;
|
||
|
||
_open_entry = true ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::setComment( const string &comment ) {
|
||
_zip_comment = comment ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::setLevel( int level ) {
|
||
_level = level ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::setMethod( StorageMethod method ) {
|
||
_method = method ;
|
||
if( method == STORED )
|
||
setLevel( NO_COMPRESSION ) ;
|
||
else if ( method == DEFLATED ) {
|
||
if( _level == NO_COMPRESSION )
|
||
setLevel( DEFAULT_COMPRESSION ) ;
|
||
} else
|
||
throw FCollException( "Specified compression method not supported" ) ;
|
||
}
|
||
|
||
//
|
||
// Protected and private methods
|
||
//
|
||
|
||
int ZipOutputStreambuf::overflow( int c ) {
|
||
return DeflateOutputStreambuf::overflow( c ) ;
|
||
// // FIXME: implement
|
||
|
||
// cout << "ZipOutputStreambuf::overflow() not implemented yet!\n" ;
|
||
// return EOF ;
|
||
}
|
||
|
||
|
||
|
||
int ZipOutputStreambuf::sync() {
|
||
return DeflateOutputStreambuf::sync() ;
|
||
// // FIXME: implement
|
||
// cout << "ZipOutputStreambuf::sync() not implemented yet!\n" ;
|
||
// return EOF ;
|
||
}
|
||
|
||
|
||
|
||
void ZipOutputStreambuf::setEntryClosedState() {
|
||
_open_entry = false ;
|
||
// FIXME: update put pointers to trigger overflow on write. overflow
|
||
// should then return EOF while _open_entry is false.
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::updateEntryHeaderInfo() {
|
||
if ( ! _open_entry )
|
||
return ;
|
||
|
||
ostream os( _outbuf ) ;
|
||
int curr_pos = os.tellp() ;
|
||
|
||
// update fields in _entries.back()
|
||
ZipCDirEntry &entry = _entries.back() ;
|
||
entry.setSize( getCount() ) ;
|
||
entry.setCrc( getCrc32() ) ;
|
||
entry.setCompressedSize( curr_pos - entry.getLocalHeaderOffset()
|
||
- entry.getLocalHeaderSize() ) ;
|
||
|
||
// Mark Donszelmann: added current date and time
|
||
time_t ltime;
|
||
time( <ime );
|
||
struct tm *now;
|
||
now = localtime( <ime );
|
||
int dosTime = (now->tm_year - 80) << 25 | (now->tm_mon + 1) << 21 | now->tm_mday << 16 |
|
||
now->tm_hour << 11 | now->tm_min << 5 | now->tm_sec >> 1;
|
||
entry.setTime(dosTime);
|
||
|
||
// write ZipLocalEntry header to header position
|
||
os.seekp( entry.getLocalHeaderOffset() ) ;
|
||
os << static_cast< ZipLocalEntry >( entry ) ;
|
||
os.seekp( curr_pos ) ;
|
||
}
|
||
|
||
|
||
void ZipOutputStreambuf::writeCentralDirectory( const vector< ZipCDirEntry > &entries,
|
||
EndOfCentralDirectory eocd,
|
||
ostream &os ) {
|
||
int cdir_start = os.tellp() ;
|
||
std::vector< ZipCDirEntry >::const_iterator it ;
|
||
int cdir_size = 0 ;
|
||
|
||
for ( it = entries.begin() ; it != entries.end() ; ++it ) {
|
||
os << *it ;
|
||
cdir_size += it->getCDirHeaderSize() ;
|
||
}
|
||
eocd.setOffset( cdir_start ) ;
|
||
eocd.setCDirSize( cdir_size ) ;
|
||
eocd.setTotalCount( entries.size() ) ;
|
||
os << eocd ;
|
||
}
|
||
|
||
} // namespace
|
||
|
||
/** \file
|
||
Implementation of ZipOutputStreambuf.
|
||
*/
|
||
|
||
/*
|
||
Zipios++ - a small C++ library that provides easy access to .zip files.
|
||
Copyright (C) 2000 Thomas S<>ndergaard
|
||
|
||
This library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
License as published by the Free Software Foundation; either
|
||
version 2 of the License, or (at your option) any later version.
|
||
|
||
This library is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public
|
||
License along with this library; if not, write to the Free Software
|
||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
*/
|