/* * Copyright 1995, 2003 Perforce Software. All rights reserved. * * This file is part of Perforce - the FAST SCM System. */ /* * fileiozip.cc - FileIOGzip/FileIOGunzip methods */ # include # include # include # include # include "filesys.h" # include "fileio.h" FileIOCompress::~FileIOCompress() { Cleanup(); delete gzip; delete gzbuf; } void FileIOCompress::Open( FileOpenMode mode, Error *e ) { switch ( GetType() & FST_C_MASK ) { case FST_C_GZIP: compMode = FIOC_GZIP; break; case FST_C_GUNZIP: compMode = FIOC_GUNZIP; break; default: compMode = FIOC_PASS; } if( compMode != FIOC_PASS ) { gzip = new Gzip; gzbuf = new StrFixed( BufferSize() ); // Read expects is/ie; write os/oe. gzip->is = gzbuf->Text(); gzip->ie = gzbuf->Text(); gzip->os = gzbuf->Text(); gzip->oe = gzbuf->Text() + gzbuf->Length(); } FileIOBinary::Open( mode, e ); if( e->Test() ) { delete gzip; gzip = 0; delete gzbuf; gzbuf = 0; } } void FileIOCompress::Write( const char *buf, int len, Error *e ) { switch ( compMode ) { case FIOC_PASS: FileIOBinary::Write( buf, len, e ); break; case FIOC_GZIP: // Write( 0, 0 ) means flush (from Close()). // Don't be fooled by buf, 0. if( buf && !len ) return; gzip->is = buf; gzip->ie = buf + len; // Flush output if full and Compress input // util Compress() indicates input exhausted do if( gzip->OutputFull() ) { FileIOBinary::Write( gzbuf->Text(), gzip->os - gzbuf->Text(), e ); gzip->os = gzbuf->Text(); } while( !e->Test() && gzip->Compress( e ) && !gzip->InputEmpty() ); break; case FIOC_GUNZIP: gzip->is = buf; gzip->ie = buf + len; // Flush output if full and Compress input // util Compress() indicates input exhausted do if( gzip->OutputFull() ) { FileIOBinary::Write( gzbuf->Text(), gzip->os - gzbuf->Text(), e ); gzip->os = gzbuf->Text(); } while( !e->Test() && gzip->Uncompress( e ) && !gzip->InputEmpty() ); break; } } int FileIOCompress::Read( char *buf, int len, Error *e ) { int done; switch ( compMode ) { case FIOC_PASS: return FileIOBinary::Read( buf, len, e ); case FIOC_GZIP: gzip->os = buf; gzip->oe = buf + len; do if( gzip->InputEmpty() ) { int l = FileIOBinary::Read( gzbuf->Text(), gzbuf->Length(), e ); if( !l ) e->Set( E_FAILED, "Unexpected end of file" ); gzip->is = gzbuf->Text(); gzip->ie = gzbuf->Text() + l; } while( !e->Test() && gzip->Uncompress( e ) && !gzip->OutputFull() ); return gzip->os - buf; case FIOC_GUNZIP: gzip->os = buf; gzip->oe = buf + len; done = 0; do if( gzip->InputEmpty() && !done ) { int l = FileIOBinary::Read( gzbuf->Text(), gzbuf->Length(), e ); gzip->is = l ? gzbuf->Text() : 0; gzip->ie = gzbuf->Text() + l; done |= !l; } while( !e->Test() && gzip->Compress( e ) && !gzip->OutputFull() ); return gzip->os - buf; } e->Sys( "read", Name() ); return -1; } void FileIOCompress::Close( Error *e ) { // Flush & clear gzip switch( compMode ) { case FIOC_GZIP: if( gzip && mode == FOM_WRITE && GetFd() != -1 ) { Write( 0, 0, e ); FileIOBinary::Write( gzbuf->Text(), gzip->os - gzbuf->Text(), e ); } break; case FIOC_GUNZIP: // Flush & clear gzip if( gzip && mode == FOM_WRITE && gzip->os - gzbuf->Text() ) FileIOBinary::Write( gzbuf->Text(), gzip->os - gzbuf->Text(), e ); break; case FIOC_PASS: break; } delete gzip; gzip = 0; delete gzbuf; gzbuf = 0; // Rest of normal close FileIOBinary::Close( e ); } void FileIOCompress::Seek( offL_t offset, Error *e ) { if ( compMode == FIOC_PASS ) FileIOBinary::Seek( offset, e ); // else set error? The FileSys stub method is quiet on this }