kfilterdev.cpp
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 #include "kfilterdev.h"
00020 #include "kfilterbase.h"
00021 #include <kdebug.h>
00022 #include <stdio.h> 
00023 #include <stdlib.h>
00024 #include <assert.h>
00025 #include <qfile.h>
00026 
00027 class KFilterDev::KFilterDevPrivate
00028 {
00029 public:
00030     KFilterDevPrivate() : bNeedHeader(true), bSkipHeaders(false),
00031                           autoDeleteFilterBase(false), bOpenedUnderlyingDevice(false) {}
00032     bool bNeedHeader;
00033     bool bSkipHeaders;
00034     bool autoDeleteFilterBase;
00035     bool bOpenedUnderlyingDevice;
00036     QByteArray buffer; 
00037     QCString ungetchBuffer;
00038     QCString origFileName;
00039     KFilterBase::Result result;
00040 };
00041 
00042 KFilterDev::KFilterDev( KFilterBase * _filter, bool autoDeleteFilterBase )
00043     : filter(_filter)
00044 {
00045     assert(filter);
00046     d = new KFilterDevPrivate;
00047     d->autoDeleteFilterBase = autoDeleteFilterBase;
00048 }
00049 
00050 KFilterDev::~KFilterDev()
00051 {
00052     if ( isOpen() )
00053         close();
00054     if ( d->autoDeleteFilterBase )
00055         delete filter;
00056     delete d;
00057 }
00058 
00059 #ifndef KDE_NO_COMPAT
00060 
00061 
00062 QIODevice* KFilterDev::createFilterDevice(KFilterBase* base, QFile* file)
00063 {
00064    if (file==0)
00065       return 0;
00066 
00067    
00068    if (base==0)
00069        return new QFile(file->name()); 
00070 
00071    base->setDevice(file);
00072    return new KFilterDev(base);
00073 }
00074 #endif
00075 
00076 
00077 QIODevice * KFilterDev::deviceForFile( const QString & fileName, const QString & mimetype,
00078                                        bool forceFilter )
00079 {
00080     QFile * f = new QFile( fileName );
00081     KFilterBase * base = mimetype.isEmpty() ? KFilterBase::findFilterByFileName( fileName )
00082                          : KFilterBase::findFilterByMimeType( mimetype );
00083     if ( base )
00084     {
00085         base->setDevice(f, true);
00086         return new KFilterDev(base, true);
00087     }
00088     if(!forceFilter)
00089         return f;
00090     else
00091     {
00092         delete f;
00093         return 0L;
00094     }
00095 }
00096 
00097 QIODevice * KFilterDev::device( QIODevice* inDevice, const QString & mimetype)
00098 {
00099     return device( inDevice, mimetype, true );
00100 }
00101 
00102 QIODevice * KFilterDev::device( QIODevice* inDevice, const QString & mimetype, bool autoDeleteInDevice )
00103 {
00104    if (inDevice==0)
00105       return 0;
00106    KFilterBase * base = KFilterBase::findFilterByMimeType(mimetype);
00107    if ( base )
00108    {
00109       base->setDevice(inDevice, autoDeleteInDevice);
00110       return new KFilterDev(base, true );
00111    }
00112    return 0;
00113 }
00114 
00115 bool KFilterDev::open( int mode )
00116 {
00117     
00118     if ( mode == IO_ReadOnly )
00119     {
00120         d->buffer.resize(0);
00121         d->ungetchBuffer.resize(0);
00122     }
00123     else
00124     {
00125         d->buffer.resize( 8*1024 );
00126         filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
00127     }
00128     d->bNeedHeader = !d->bSkipHeaders;
00129     filter->init( mode );
00130     d->bOpenedUnderlyingDevice = !filter->device()->isOpen();
00131     bool ret = d->bOpenedUnderlyingDevice ? filter->device()->open( mode ) : true;
00132     d->result = KFilterBase::OK;
00133 
00134     if ( !ret )
00135         kdWarning(7005) << "KFilterDev::open: Couldn't open underlying device" << endl;
00136     else
00137     {
00138         setState( IO_Open );
00139         setMode( mode );
00140     }
00141     ioIndex = 0;
00142     return ret;
00143 }
00144 
00145 void KFilterDev::close()
00146 {
00147     
00148     if ( filter->mode() == IO_WriteOnly )
00149         writeBlock( 0L, 0 ); 
00150     
00151 
00152     filter->terminate();
00153     if ( d->bOpenedUnderlyingDevice )
00154         filter->device()->close();
00155 
00156     setState( 0 ); 
00157 }
00158 
00159 void KFilterDev::flush()
00160 {
00161     
00162     filter->device()->flush();
00163     
00164 }
00165 
00166 QIODevice::Offset KFilterDev::size() const
00167 {
00168     
00169     
00170     
00171 
00172     
00173 
00174     kdWarning(7005) << "KFilterDev::size - can't be implemented !!!!!!!! Returning -1 " << endl;
00175     
00176     return (uint)-1;
00177 }
00178 
00179 QIODevice::Offset KFilterDev::at() const
00180 {
00181     return ioIndex;
00182 }
00183 
00184 bool KFilterDev::at( QIODevice::Offset pos )
00185 {
00186     
00187 
00188     if ( ioIndex == pos )
00189         return true;
00190 
00191     Q_ASSERT ( filter->mode() == IO_ReadOnly );
00192 
00193     if ( pos == 0 )
00194     {
00195         ioIndex = 0;
00196         
00197         d->ungetchBuffer.resize(0);
00198         d->bNeedHeader = !d->bSkipHeaders;
00199         d->result = KFilterBase::OK;
00200         filter->setInBuffer(0L,0);
00201         filter->reset();
00202         return filter->device()->reset();
00203     }
00204 
00205     if ( ioIndex < pos ) 
00206         pos = pos - ioIndex;
00207     else
00208     {
00209         
00210         
00211         if (!at(0)) 
00212             return false;
00213     }
00214 
00215     
00216     
00217     
00218     
00219     QByteArray dummy( pos );
00220     return ( (QIODevice::Offset)readBlock( dummy.data(), pos ) == pos ) ;
00221 }
00222 
00223 bool KFilterDev::atEnd() const
00224 {
00225     return filter->device()->atEnd() && (d->result == KFilterBase::END);
00226 }
00227 
00228 Q_LONG KFilterDev::readBlock( char *data, Q_ULONG maxlen )
00229 {
00230     Q_ASSERT ( filter->mode() == IO_ReadOnly );
00231     
00232     
00233     if ( d->result == KFilterBase::END )
00234         return 0;
00235     
00236     if ( d->result != KFilterBase::OK )
00237         return -1;
00238 
00239     filter->setOutBuffer( data, maxlen );
00240 
00241     bool decompressedAll = false;
00242     uint dataReceived = 0;
00243     uint availOut = maxlen;
00244     while ( dataReceived < maxlen )
00245     {
00246         if (filter->inBufferEmpty())
00247         {
00248             
00249             
00250             d->buffer.resize( 8*1024 );
00251             
00252             int size = filter->device()->readBlock( d->buffer.data(),
00253                                                     d->buffer.size() );
00254             if ( size )
00255                 filter->setInBuffer( d->buffer.data(), size );
00256             else {
00257                 if ( decompressedAll )
00258                 {
00259                     
00260                     
00261                     d->result = KFilterBase::END;
00262                     break;
00263                 }
00264             }
00265             
00266         }
00267         if (d->bNeedHeader)
00268         {
00269             (void) filter->readHeader();
00270             d->bNeedHeader = false;
00271         }
00272 
00273         d->result = filter->uncompress();
00274 
00275         if (d->result == KFilterBase::ERROR)
00276         {
00277             kdWarning(7005) << "KFilterDev: Error when uncompressing data" << endl;
00278             break;
00279         }
00280 
00281         
00282         uint outReceived = availOut - filter->outBufferAvailable();
00283         
00284         if( availOut < (uint)filter->outBufferAvailable() )
00285             kdWarning(7005) << " last availOut " << availOut << " smaller than new avail_out=" << filter->outBufferAvailable() << " !" << endl;
00286 
00287         
00288         data += outReceived;
00289         dataReceived += outReceived;
00290         ioIndex += outReceived;
00291         if (d->result == KFilterBase::END)
00292         {
00293             
00294             break; 
00295         }
00296         if (filter->inBufferEmpty() && filter->outBufferAvailable() != 0 )
00297         {
00298             decompressedAll = true;
00299         }
00300         availOut = maxlen - dataReceived;
00301         filter->setOutBuffer( data, availOut );
00302     }
00303 
00304     return dataReceived;
00305 }
00306 
00307 Q_LONG KFilterDev::writeBlock( const char *data , Q_ULONG len )
00308 {
00309     Q_ASSERT ( filter->mode() == IO_WriteOnly );
00310     
00311     if ( d->result != KFilterBase::OK )
00312         return 0;
00313 
00314     bool finish = (data == 0L);
00315     if (!finish)
00316     {
00317         filter->setInBuffer( data, len );
00318         if (d->bNeedHeader)
00319         {
00320             (void)filter->writeHeader( d->origFileName );
00321             d->bNeedHeader = false;
00322         }
00323     }
00324 
00325     uint dataWritten = 0;
00326     uint availIn = len;
00327     while ( dataWritten < len || finish )
00328     {
00329 
00330         d->result = filter->compress( finish );
00331 
00332         if (d->result == KFilterBase::ERROR)
00333         {
00334             kdWarning(7005) << "KFilterDev: Error when compressing data" << endl;
00335             
00336             break;
00337         }
00338 
00339         
00340         if (filter->inBufferEmpty() || (d->result == KFilterBase::END))
00341         {
00342             
00343             uint wrote = availIn - filter->inBufferAvailable();
00344 
00345             
00346 
00347             
00348             data += wrote;
00349             dataWritten += wrote;
00350             ioIndex += wrote;
00351 
00352             availIn = len - dataWritten;
00353             
00354             if ( availIn > 0 ) 
00355                 filter->setInBuffer( data, availIn );
00356         }
00357 
00358         if (filter->outBufferFull() || (d->result == KFilterBase::END))
00359         {
00360             
00361             int towrite = d->buffer.size() - filter->outBufferAvailable();
00362             if ( towrite > 0 )
00363             {
00364                 
00365                 int size = filter->device()->writeBlock( d->buffer.data(), towrite );
00366                 if ( size != towrite )
00367                     kdWarning(7005) << "KFilterDev::writeBlock. Could only write " << size << " out of " << towrite << " bytes" << endl;
00368                 
00369                     
00370             }
00371             d->buffer.resize( 8*1024 );
00372             filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
00373             if (d->result == KFilterBase::END)
00374             {
00375                 
00376                 Q_ASSERT(finish); 
00377                 break;
00378             }
00379         }
00380     }
00381 
00382     return dataWritten;
00383 }
00384 
00385 int KFilterDev::getch()
00386 {
00387     Q_ASSERT ( filter->mode() == IO_ReadOnly );
00388     
00389     if ( !d->ungetchBuffer.isEmpty() ) {
00390         int len = d->ungetchBuffer.length();
00391         int ch = d->ungetchBuffer[ len-1 ];
00392         d->ungetchBuffer.truncate( len - 1 );
00393         
00394         return ch;
00395     }
00396     char buf[1];
00397     int ret = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
00398     
00399     return ret;
00400 }
00401 
00402 int KFilterDev::putch( int c )
00403 {
00404     
00405     char buf[1];
00406     buf[0] = c;
00407     return writeBlock( buf, 1 ) == 1 ? c : -1;
00408 }
00409 
00410 int KFilterDev::ungetch( int ch )
00411 {
00412     
00413     if ( ch == EOF )                            
00414         return ch;
00415 
00416     
00417     d->ungetchBuffer +=ch;
00418     return ch;
00419 }
00420 
00421 void KFilterDev::setOrigFileName( const QCString & fileName )
00422 {
00423     d->origFileName = fileName;
00424 }
00425 
00426 void KFilterDev::setSkipHeaders()
00427 {
00428     d->bSkipHeaders = true;
00429 }
 
This file is part of the documentation for kio Library Version 3.2.0.