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
return 0;
00369 }
00370
00371
00372 }
00373 d->buffer.resize( 8*1024 );
00374 filter->
setOutBuffer( d->buffer.data(), d->buffer.size() );
00375
if (d->result == KFilterBase::END)
00376 {
00377
00378 Q_ASSERT(finish);
00379
break;
00380 }
00381 }
00382 }
00383
00384
return dataWritten;
00385 }
00386
00387
int KFilterDev::getch()
00388 {
00389 Q_ASSERT ( filter->
mode() == IO_ReadOnly );
00390
00391
if ( !d->ungetchBuffer.isEmpty() ) {
00392
int len = d->ungetchBuffer.length();
00393
int ch = d->ungetchBuffer[ len-1 ];
00394 d->ungetchBuffer.truncate( len - 1 );
00395
00396
return ch;
00397 }
00398
char buf[1];
00399
int ret =
readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
00400
00401
return ret;
00402 }
00403
00404
int KFilterDev::putch(
int c )
00405 {
00406
00407
char buf[1];
00408 buf[0] = c;
00409
return writeBlock( buf, 1 ) == 1 ? c : -1;
00410 }
00411
00412
int KFilterDev::ungetch(
int ch )
00413 {
00414
00415
if ( ch == EOF )
00416
return ch;
00417
00418
00419 d->ungetchBuffer +=ch;
00420
return ch;
00421 }
00422
00423 void KFilterDev::setOrigFileName(
const QCString & fileName )
00424 {
00425 d->origFileName = fileName;
00426 }
00427
00428 void KFilterDev::setSkipHeaders()
00429 {
00430 d->bSkipHeaders =
true;
00431 }