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 Q_ASSERT ( filter->mode() == IO_ReadOnly );
00187
00188
00189 if ( ioIndex == pos )
00190 return true;
00191
00192 if ( pos == 0 )
00193 {
00194 ioIndex = 0;
00195
00196 d->ungetchBuffer.resize(0);
00197 d->bNeedHeader = !d->bSkipHeaders;
00198 d->result = KFilterBase::OK;
00199 filter->setInBuffer(0L,0);
00200 filter->reset();
00201 return filter->device()->reset();
00202 }
00203
00204 if ( ioIndex < pos )
00205 pos = pos - ioIndex;
00206 else
00207 {
00208
00209
00210 if (!at(0))
00211 return false;
00212 }
00213
00214
00215
00216
00217
00218 QByteArray dummy( pos );
00219 return ( (QIODevice::Offset)readBlock( dummy.data(), pos ) == pos ) ;
00220 }
00221
00222 bool KFilterDev::atEnd() const
00223 {
00224 return filter->device()->atEnd() && (d->result == KFilterBase::END);
00225 }
00226
00227 Q_LONG KFilterDev::readBlock( char *data, Q_ULONG maxlen )
00228 {
00229 Q_ASSERT ( filter->mode() == IO_ReadOnly );
00230
00231
00232 if ( d->result == KFilterBase::END )
00233 return 0;
00234
00235 if ( d->result != KFilterBase::OK )
00236 return -1;
00237
00238 filter->setOutBuffer( data, maxlen );
00239
00240 bool readEverything = false;
00241 uint dataReceived = 0;
00242 uint availOut = maxlen;
00243 while ( dataReceived < maxlen )
00244 {
00245 if (filter->inBufferEmpty())
00246 {
00247
00248
00249 d->buffer.resize( 8*1024 );
00250
00251 int size = filter->device()->readBlock( d->buffer.data(),
00252 d->buffer.size() );
00253 if ( size )
00254 filter->setInBuffer( d->buffer.data(), size );
00255 else
00256 readEverything = true;
00257
00258 }
00259 if (d->bNeedHeader)
00260 {
00261 (void) filter->readHeader();
00262 d->bNeedHeader = false;
00263 }
00264
00265 d->result = filter->uncompress();
00266
00267 if (d->result == KFilterBase::ERROR)
00268 {
00269 kdWarning(7005) << "KFilterDev: Error when uncompressing data" << endl;
00270 break;
00271 }
00272
00273
00274 uint outReceived = availOut - filter->outBufferAvailable();
00275
00276 if( availOut < (uint)filter->outBufferAvailable() )
00277 kdWarning(7005) << " last availOut " << availOut << " smaller than new avail_out=" << filter->outBufferAvailable() << " !" << endl;
00278
00279
00280 data += outReceived;
00281 dataReceived += outReceived;
00282 ioIndex += outReceived;
00283 if (d->result == KFilterBase::END)
00284 {
00285
00286 break;
00287 }
00288 if (readEverything && filter->inBufferEmpty() && filter->outBufferAvailable() != 0 )
00289 {
00290
00291
00292 d->result = KFilterBase::END;
00293 break;
00294 }
00295 availOut = maxlen - dataReceived;
00296 filter->setOutBuffer( data, availOut );
00297 }
00298
00299 return dataReceived;
00300 }
00301
00302 Q_LONG KFilterDev::writeBlock( const char *data , Q_ULONG len )
00303 {
00304 Q_ASSERT ( filter->mode() == IO_WriteOnly );
00305
00306 if ( d->result != KFilterBase::OK )
00307 return 0;
00308
00309 bool finish = (data == 0L);
00310 if (!finish)
00311 {
00312 filter->setInBuffer( data, len );
00313 if (d->bNeedHeader)
00314 {
00315 (void)filter->writeHeader( d->origFileName );
00316 d->bNeedHeader = false;
00317 }
00318 }
00319
00320 uint dataWritten = 0;
00321 uint availIn = len;
00322 while ( dataWritten < len || finish )
00323 {
00324
00325 d->result = filter->compress( finish );
00326
00327 if (d->result == KFilterBase::ERROR)
00328 {
00329 kdWarning(7005) << "KFilterDev: Error when compressing data" << endl;
00330
00331 break;
00332 }
00333
00334
00335 if (filter->inBufferEmpty() || (d->result == KFilterBase::END))
00336 {
00337
00338 uint wrote = availIn - filter->inBufferAvailable();
00339
00340
00341
00342
00343 data += wrote;
00344 dataWritten += wrote;
00345 ioIndex += wrote;
00346
00347 availIn = len - dataWritten;
00348
00349 if ( availIn > 0 )
00350 filter->setInBuffer( data, availIn );
00351 }
00352
00353 if (filter->outBufferFull() || (d->result == KFilterBase::END))
00354 {
00355
00356 int towrite = d->buffer.size() - filter->outBufferAvailable();
00357 if ( towrite > 0 )
00358 {
00359
00360 int size = filter->device()->writeBlock( d->buffer.data(), towrite );
00361 if ( size != towrite )
00362 kdWarning(7005) << "KFilterDev::writeBlock. Could only write " << size << " out of " << towrite << " bytes" << endl;
00363
00364
00365 }
00366 d->buffer.resize( 8*1024 );
00367 filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
00368 if (d->result == KFilterBase::END)
00369 {
00370
00371 Q_ASSERT(finish);
00372 break;
00373 }
00374 }
00375 }
00376
00377 return dataWritten;
00378 }
00379
00380 int KFilterDev::getch()
00381 {
00382 Q_ASSERT ( filter->mode() == IO_ReadOnly );
00383
00384 if ( !d->ungetchBuffer.isEmpty() ) {
00385 int len = d->ungetchBuffer.length();
00386 int ch = d->ungetchBuffer[ len-1 ];
00387 d->ungetchBuffer.truncate( len - 1 );
00388
00389 return ch;
00390 }
00391 char buf[1];
00392 int ret = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
00393
00394 return ret;
00395 }
00396
00397 int KFilterDev::putch( int c )
00398 {
00399
00400 char buf[1];
00401 buf[0] = c;
00402 return writeBlock( buf, 1 ) == 1 ? c : -1;
00403 }
00404
00405 int KFilterDev::ungetch( int ch )
00406 {
00407
00408 if ( ch == EOF )
00409 return ch;
00410
00411
00412 d->ungetchBuffer +=ch;
00413 return ch;
00414 }
00415
00416 void KFilterDev::setOrigFileName( const QCString & fileName )
00417 {
00418 d->origFileName = fileName;
00419 }
00420
00421 void KFilterDev::setSkipHeaders()
00422 {
00423 d->bSkipHeaders = true;
00424 }
This file is part of the documentation for kdelibs Version 3.1.0.