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.