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;
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) TDE_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.
virtual bool open(int mode)
Open for reading or writing.
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 void close()
Close after reading or writing.