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;
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 );
359 TQ_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)
439 int 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;
457 int KFilterDev::putch(
int c )
462 return writeBlock( buf, 1 ) == 1 ? c : -1;
465 int KFilterDev::ungetch(
int ch )
472 d->ungetchBuffer +=ch;
473 TQIODevice::at(TQIODevice::at() - 1);
479 d->origFileName = fileName;
484 d->bSkipHeaders =
true;