19 #include "kfilterdev.h"
20 #include "kfilterbase.h"
27 #define BUFFER_SIZE 8*1024
29 class 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 TQT_TQIODEVICE(
new TQFile(file->name()));
84 TQFile * f =
new TQFile( fileName );
93 return TQT_TQIODEVICE(f);
103 return device( inDevice, mimetype,
true );
106 TQIODevice *
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( (TQ_OpenMode)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();
165 void KFilterDev::flush()
168 filter->
device()->flush();
173 qint64 KFilterDev::size() const
175 TQIODevice::Offset KFilterDev::size() const
184 kdDebug(7005) <<
"KFilterDev::size - can't be implemented, returning -1" << endl;
189 TQIODevice::Offset KFilterDev::at()
const
191 return TQIODevice::at();
194 bool KFilterDev::at( TQIODevice::Offset pos )
198 if ( TQIODevice::at() == pos )
201 Q_ASSERT ( filter->mode() == IO_ReadOnly );
207 d->ungetchBuffer.resize(0);
208 d->bNeedHeader = !d->bSkipHeaders;
209 d->result = KFilterBase::OK;
210 filter->setInBuffer(0L,0);
212 return filter->
device()->reset();
215 if ( TQIODevice::at() < pos )
216 pos = pos - TQIODevice::at();
226 TQByteArray dummy( TQMIN( pos, 3*BUFFER_SIZE ) );
227 d->bIgnoreData =
true;
228 bool result = ( (TQIODevice::Offset)readBlock( dummy.data(), pos ) == pos );
229 d->bIgnoreData =
false;
233 bool KFilterDev::atEnd()
const
235 return filter->
device()->atEnd() && (d->result == KFilterBase::END)
236 && d->ungetchBuffer.isEmpty();
239 TQT_TQIO_LONG KFilterDev::tqreadBlock(
char *data, TQT_TQIO_ULONG maxlen )
241 Q_ASSERT ( filter->mode() == IO_ReadOnly );
244 uint dataReceived = 0;
245 if ( !d->ungetchBuffer.isEmpty() )
247 uint len = d->ungetchBuffer.length();
248 if ( !d->bIgnoreData )
250 while ( ( dataReceived < len ) && ( dataReceived < maxlen ) )
252 *data = d->ungetchBuffer[ len - dataReceived - 1 ];
259 dataReceived = TQMIN( len, maxlen );
261 d->ungetchBuffer.truncate( len - dataReceived );
262 TQIODevice::at(TQIODevice::at() + dataReceived);
267 if ( d->result == KFilterBase::END )
271 if ( d->result != KFilterBase::OK )
275 TQ_ULONG outBufferSize;
276 if ( d->bIgnoreData )
278 outBufferSize = TQMIN( maxlen, 3*BUFFER_SIZE );
282 outBufferSize = maxlen;
284 outBufferSize -= dataReceived;
285 TQ_ULONG availOut = outBufferSize;
286 filter->setOutBuffer( data, outBufferSize );
288 bool decompressedAll =
false;
289 while ( dataReceived < maxlen )
291 if (filter->inBufferEmpty())
295 d->buffer.resize( BUFFER_SIZE );
297 int size = filter->
device()->readBlock( d->buffer.data(),
300 filter->setInBuffer( d->buffer.data(), size );
302 if ( decompressedAll )
306 d->result = KFilterBase::END;
314 (void) filter->readHeader();
315 d->bNeedHeader =
false;
318 d->result = filter->uncompress();
320 if (d->result == KFilterBase::ERROR)
322 kdWarning(7005) <<
"KFilterDev: Error when uncompressing data" << endl;
327 uint outReceived = availOut - filter->outBufferAvailable();
329 if( availOut < (uint)filter->outBufferAvailable() )
330 kdWarning(7005) <<
" last availOut " << availOut <<
" smaller than new avail_out=" << filter->outBufferAvailable() <<
" !" << endl;
332 dataReceived += outReceived;
333 if ( !d->bIgnoreData )
336 availOut = maxlen - dataReceived;
338 else if ( maxlen - dataReceived < outBufferSize )
340 availOut = maxlen - dataReceived;
342 TQIODevice::at(TQIODevice::at() + outReceived);
343 if (d->result == KFilterBase::END)
348 if (filter->inBufferEmpty() && filter->outBufferAvailable() != 0 )
350 decompressedAll =
true;
352 filter->setOutBuffer( data, availOut );
358 TQT_TQIO_LONG KFilterDev::tqwriteBlock(
const char *data , TQT_TQIO_ULONG len )
360 Q_ASSERT ( filter->mode() == IO_WriteOnly );
362 if ( d->result != KFilterBase::OK )
365 bool finish = (data == 0L);
368 filter->setInBuffer( data, len );
371 (void)filter->writeHeader( d->origFileName );
372 d->bNeedHeader =
false;
376 uint dataWritten = 0;
378 while ( dataWritten < len || finish )
381 d->result = filter->compress( finish );
383 if (d->result == KFilterBase::ERROR)
385 kdWarning(7005) <<
"KFilterDev: Error when compressing data" << endl;
391 if (filter->inBufferEmpty() || (d->result == KFilterBase::END))
394 uint wrote = availIn - filter->inBufferAvailable();
400 dataWritten += wrote;
401 TQIODevice::at(TQIODevice::at() + wrote);
403 availIn = len - dataWritten;
406 filter->setInBuffer( data, availIn );
409 if (filter->outBufferFull() || (d->result == KFilterBase::END))
412 int towrite = d->buffer.size() - filter->outBufferAvailable();
416 int size = filter->
device()->writeBlock( d->buffer.data(), towrite );
417 if ( size != towrite ) {
418 kdWarning(7005) <<
"KFilterDev::writeBlock. Could only write " << size <<
" out of " << towrite <<
" bytes" << endl;
424 d->buffer.resize( 8*1024 );
425 filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
426 if (d->result == KFilterBase::END)
438 int KFilterDev::getch()
440 Q_ASSERT ( filter->mode() == IO_ReadOnly );
442 if ( !d->ungetchBuffer.isEmpty() ) {
443 int len = d->ungetchBuffer.length();
444 int ch = d->ungetchBuffer[ len-1 ];
445 d->ungetchBuffer.truncate( len - 1 );
446 TQIODevice::at(TQIODevice::at() + 1);
451 int ret = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
456 int KFilterDev::putch(
int c )
461 return writeBlock( buf, 1 ) == 1 ? c : -1;
464 int KFilterDev::ungetch(
int ch )
471 d->ungetchBuffer +=ch;
472 TQIODevice::at(TQIODevice::at() - 1);
478 d->origFileName = fileName;
483 d->bSkipHeaders =
true;
static KFilterBase * findFilterByFileName(const TQString &fileName)
Call this to create the appropriate filter for the file named fileName.
static TQIODevice * createFilterDevice(KFilterBase *base, TQFile *file) KDE_DEPRECATED
Call this to create the appropriate filter device for base working on file .
static KFilterBase * findFilterByMimeType(const TQString &mimeType)
Call this to create the appropriate filter for the mimetype mimeType.
void setDevice(TQIODevice *dev, bool autodelete=false)
Sets the device on which the filter will work.
TQIODevice * device()
Returns the device on which the filter will work.
This is the base class for compression filters such as gzip and bzip2.
KFilterDev(KFilterBase *filter, bool autoDeleteFilterBase=false)
Constructs a KFilterDev for a given filter (e.g.
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...
void setSkipHeaders()
Call this let this device skip the gzip headers when reading/writing.
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 ~KFilterDev()
Destructs the KFilterDev.
virtual bool open(TQ_OpenMode mode)
Open for reading or writing.
virtual void close()
Close after reading or writing.