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 new TQFile(file->name());
84 TQFile * f =
new TQFile( fileName );
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( (
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();
165 void KFilterDev::flush()
168 filter->
device()->flush();
172 TQIODevice::Offset KFilterDev::size()
const
180 kdDebug(7005) <<
"KFilterDev::size - can't be implemented, returning -1" << endl;
185 TQIODevice::Offset KFilterDev::at()
const
187 return TQIODevice::at();
190 bool 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;
229 bool KFilterDev::atEnd()
const
231 return filter->
device()->atEnd() && (d->result == KFilterBase::END)
232 && d->ungetchBuffer.isEmpty();
235 TQ_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;
323 uint outReceived = availOut - filter->outBufferAvailable();
325 if( availOut < (uint)filter->outBufferAvailable() )
326 kdWarning(7005) <<
" last availOut " << availOut <<
" smaller than new avail_out=" << filter->outBufferAvailable() <<
" !" << endl;
328 dataReceived += outReceived;
329 if ( !d->bIgnoreData )
332 availOut = maxlen - dataReceived;
334 else if ( maxlen - dataReceived < outBufferSize )
336 availOut = maxlen - dataReceived;
338 TQIODevice::at(TQIODevice::at() + outReceived);
339 if (d->result == KFilterBase::END)
344 if (filter->inBufferEmpty() && filter->outBufferAvailable() != 0 )
346 decompressedAll =
true;
348 filter->setOutBuffer( data, availOut );
354 TQ_LONG KFilterDev::writeBlock(
const char *data , TQ_ULONG len )
356 Q_ASSERT ( filter->mode() == IO_WriteOnly );
358 if ( d->result != KFilterBase::OK )
361 bool finish = (data == 0L);
364 filter->setInBuffer( data, len );
367 (void)filter->writeHeader( d->origFileName );
368 d->bNeedHeader =
false;
372 uint dataWritten = 0;
374 while ( dataWritten < len || finish )
377 d->result = filter->compress( finish );
379 if (d->result == KFilterBase::ERROR)
381 kdWarning(7005) <<
"KFilterDev: Error when compressing data" << endl;
387 if (filter->inBufferEmpty() || (d->result == KFilterBase::END))
390 uint wrote = availIn - filter->inBufferAvailable();
396 dataWritten += wrote;
397 TQIODevice::at(TQIODevice::at() + wrote);
399 availIn = len - dataWritten;
402 filter->setInBuffer( data, availIn );
405 if (filter->outBufferFull() || (d->result == KFilterBase::END))
408 int towrite = d->buffer.size() - filter->outBufferAvailable();
412 int size = filter->
device()->writeBlock( d->buffer.data(), towrite );
413 if ( size != towrite ) {
414 kdWarning(7005) <<
"KFilterDev::writeBlock. Could only write " << size <<
" out of " << towrite <<
" bytes" << endl;
420 d->buffer.resize( 8*1024 );
421 filter->setOutBuffer( d->buffer.data(), d->buffer.size() );
422 if (d->result == KFilterBase::END)
434 int KFilterDev::getch()
436 Q_ASSERT ( filter->mode() == IO_ReadOnly );
438 if ( !d->ungetchBuffer.isEmpty() ) {
439 int len = d->ungetchBuffer.length();
440 int ch = d->ungetchBuffer[ len-1 ];
441 d->ungetchBuffer.truncate( len - 1 );
442 TQIODevice::at(TQIODevice::at() + 1);
447 int ret = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
452 int KFilterDev::putch(
int c )
457 return writeBlock( buf, 1 ) == 1 ? c : -1;
460 int KFilterDev::ungetch(
int ch )
467 d->ungetchBuffer +=ch;
468 TQIODevice::at(TQIODevice::at() - 1);
474 d->origFileName = fileName;
479 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.
static KFilterBase * findFilterByFileName(const TQString &fileName)
Call this to create the appropriate filter for the file named fileName.
TQIODevice * device()
Returns the device on which the filter will work.
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...