19#include "kfilterdev.h"
20#include "kfilterbase.h"
27#define BUFFER_SIZE 8*1024
29class KFilterDev::KFilterDevPrivate
32 KFilterDevPrivate() : bNeedHeader(true), bSkipHeaders(false),
33 autoDeleteFilterBase(false), bOpenedUnderlyingDevice(false),
37 bool autoDeleteFilterBase;
38 bool bOpenedUnderlyingDevice;
41 TQCString ungetchBuffer;
42 TQCString origFileName;
43 KFilterBase::Result result;
50 d =
new KFilterDevPrivate;
51 d->autoDeleteFilterBase = autoDeleteFilterBase;
58 if ( d->autoDeleteFilterBase )
73 return new TQFile(file->name());
84 TQFile * f =
new TQFile( fileName );
103 return device( inDevice, mimetype,
true );
106TQIODevice *
KFilterDev::device( TQIODevice* inDevice,
const TQString & mimetype,
bool autoDeleteInDevice )
113 base->
setDevice(inDevice, autoDeleteInDevice);
122 if ( mode == IO_ReadOnly )
125 d->ungetchBuffer.resize(0);
129 d->buffer.resize( BUFFER_SIZE );
130 filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
132 d->bNeedHeader = !d->bSkipHeaders;
133 filter->init( mode );
134 d->bOpenedUnderlyingDevice = !filter->device()->isOpen();
135 bool ret = d->bOpenedUnderlyingDevice ? filter->device()->open( (
int)mode ) :
true;
136 d->result = KFilterBase::OK;
139 kdWarning(7005) <<
"KFilterDev::open: Couldn't open underlying device" << endl;
154 if ( filter->mode() == IO_WriteOnly )
159 if ( d->bOpenedUnderlyingDevice )
160 filter->device()->close();
165void KFilterDev::flush()
168 filter->
device()->flush();
172TQIODevice::Offset KFilterDev::size()
const
180 kdDebug(7005) <<
"KFilterDev::size - can't be implemented, returning -1" << endl;
185TQIODevice::Offset KFilterDev::at()
const
187 return TQIODevice::at();
190bool KFilterDev::at( TQIODevice::Offset pos )
194 if ( TQIODevice::at() == pos )
197 Q_ASSERT ( filter->mode() == IO_ReadOnly );
203 d->ungetchBuffer.resize(0);
204 d->bNeedHeader = !d->bSkipHeaders;
205 d->result = KFilterBase::OK;
206 filter->setInBuffer(0L,0);
208 return filter->device()->reset();
211 if ( TQIODevice::at() < pos )
212 pos = pos - TQIODevice::at();
222 TQByteArray dummy( TQMIN( pos, 3*BUFFER_SIZE ) );
223 d->bIgnoreData =
true;
224 bool result = ( (TQIODevice::Offset)readBlock( dummy.data(), pos ) == pos );
225 d->bIgnoreData =
false;
229bool KFilterDev::atEnd()
const
231 return filter->
device()->atEnd() && (d->result == KFilterBase::END)
232 && d->ungetchBuffer.isEmpty();
235TQ_LONG KFilterDev::readBlock(
char *data, TQ_ULONG maxlen )
237 Q_ASSERT ( filter->mode() == IO_ReadOnly );
240 uint dataReceived = 0;
241 if ( !d->ungetchBuffer.isEmpty() )
243 uint len = d->ungetchBuffer.length();
244 if ( !d->bIgnoreData )
246 while ( ( dataReceived < len ) && ( dataReceived < maxlen ) )
248 *data = d->ungetchBuffer[ len - dataReceived - 1 ];
255 dataReceived = TQMIN( len, maxlen );
257 d->ungetchBuffer.truncate( len - dataReceived );
258 TQIODevice::at(TQIODevice::at() + dataReceived);
263 if ( d->result == KFilterBase::END )
267 if ( d->result != KFilterBase::OK )
271 TQ_ULONG outBufferSize;
272 if ( d->bIgnoreData )
274 outBufferSize = TQMIN( maxlen, 3*BUFFER_SIZE );
278 outBufferSize = maxlen;
280 outBufferSize -= dataReceived;
281 TQ_ULONG availOut = outBufferSize;
282 filter->setOutBuffer( data, outBufferSize );
284 bool decompressedAll =
false;
285 while ( dataReceived < maxlen )
287 if (filter->inBufferEmpty())
291 d->buffer.resize( BUFFER_SIZE );
293 int size = filter->device()->readBlock( d->buffer.data(),
296 filter->setInBuffer( d->buffer.data(), size );
298 if ( decompressedAll )
302 d->result = KFilterBase::END;
310 (void) filter->readHeader();
311 d->bNeedHeader =
false;
314 d->result = filter->uncompress();
316 if (d->result == KFilterBase::ERROR)
318 kdWarning(7005) <<
"KFilterDev: Error when uncompressing data" << endl;
322 if ( dataReceived == 0 )
328 uint outReceived = availOut - filter->outBufferAvailable();
330 if( availOut < (uint)filter->outBufferAvailable() )
331 kdWarning(7005) <<
" last availOut " << availOut <<
" smaller than new avail_out=" << filter->outBufferAvailable() <<
" !" << endl;
333 dataReceived += outReceived;
334 if ( !d->bIgnoreData )
337 availOut = maxlen - dataReceived;
339 else if ( maxlen - dataReceived < outBufferSize )
341 availOut = maxlen - dataReceived;
343 TQIODevice::at(TQIODevice::at() + outReceived);
344 if (d->result == KFilterBase::END)
349 if (filter->inBufferEmpty() && filter->outBufferAvailable() != 0 )
351 decompressedAll =
true;
353 filter->setOutBuffer( data, availOut );
359TQ_LONG KFilterDev::writeBlock(
const char *data , TQ_ULONG len )
361 Q_ASSERT ( filter->mode() == IO_WriteOnly );
363 if ( d->result != KFilterBase::OK )
366 bool finish = (data == 0L);
369 filter->setInBuffer( data, len );
372 (void)filter->writeHeader( d->origFileName );
373 d->bNeedHeader =
false;
377 uint dataWritten = 0;
379 while ( dataWritten < len || finish )
382 d->result = filter->compress( finish );
384 if (d->result == KFilterBase::ERROR)
386 kdWarning(7005) <<
"KFilterDev: Error when compressing data" << endl;
392 if (filter->inBufferEmpty() || (d->result == KFilterBase::END))
395 uint wrote = availIn - filter->inBufferAvailable();
401 dataWritten += wrote;
402 TQIODevice::at(TQIODevice::at() + wrote);
404 availIn = len - dataWritten;
407 filter->setInBuffer( data, availIn );
410 if (filter->outBufferFull() || (d->result == KFilterBase::END))
413 int towrite = d->buffer.size() - filter->outBufferAvailable();
417 int size = filter->device()->writeBlock( d->buffer.data(), towrite );
418 if ( size != towrite ) {
419 kdWarning(7005) <<
"KFilterDev::writeBlock. Could only write " << size <<
" out of " << towrite <<
" bytes" << endl;
425 d->buffer.resize( 8*1024 );
426 filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
427 if (d->result == KFilterBase::END)
439int KFilterDev::getch()
441 Q_ASSERT ( filter->mode() == IO_ReadOnly );
443 if ( !d->ungetchBuffer.isEmpty() ) {
444 int len = d->ungetchBuffer.length();
445 int ch = d->ungetchBuffer[ len-1 ];
446 d->ungetchBuffer.truncate( len - 1 );
447 TQIODevice::at(TQIODevice::at() + 1);
452 int ret = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
457int KFilterDev::putch(
int c )
462 return writeBlock( buf, 1 ) == 1 ? c : -1;
465int KFilterDev::ungetch(
int ch )
472 d->ungetchBuffer +=ch;
473 TQIODevice::at(TQIODevice::at() - 1);
479 d->origFileName = fileName;
484 d->bSkipHeaders =
true;
This is the base class for compression filters such as gzip and bzip2.
static KFilterBase * findFilterByMimeType(const TQString &mimeType)
Call this to create the appropriate filter for the mimetype mimeType.
TQIODevice * device()
Returns the device on which the filter will work.
static KFilterBase * findFilterByFileName(const TQString &fileName)
Call this to create the appropriate filter for the file named fileName.
void setDevice(TQIODevice *dev, bool autodelete=false)
Sets the device on which the filter will work.
static TQIODevice * createFilterDevice(KFilterBase *base, TQFile *file) TDE_DEPRECATED
Call this to create the appropriate filter device for base working on file .
void setOrigFileName(const TQCString &fileName)
For writing gzip compressed files only: set the name of the original file, to be used in the gzip hea...
static TQIODevice * deviceForFile(const TQString &fileName, const TQString &mimetype=TQString::null, bool forceFilter=false)
Creates an i/o device that is able to read from fileName, whether it's compressed or not.
virtual bool open(int mode)
Open for reading or writing.
virtual void close()
Close after reading or writing.
KFilterDev(KFilterBase *filter, bool autoDeleteFilterBase=false)
Constructs a KFilterDev for a given filter (e.g.
void setSkipHeaders()
Call this let this device skip the gzip headers when reading/writing.
virtual ~KFilterDev()
Destructs the KFilterDev.
static TQIODevice * device(TQIODevice *inDevice, const TQString &mimetype)
Creates an i/o device that is able to read from the TQIODevice inDevice, whether the data is compress...