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