File indexing completed on 2024-06-02 04:07:14
0001 #include "xmpp/zlib/zlibdecompressor.h" 0002 0003 #include <QtDebug> 0004 #include <QIODevice> 0005 #include <zlib.h> 0006 0007 #include "xmpp/zlib/common.h" 0008 0009 ZLibDecompressor::ZLibDecompressor(QIODevice* device) : device_(device) 0010 { 0011 zlib_stream_ = (z_stream*) malloc(sizeof(z_stream)); 0012 initZStream(zlib_stream_); 0013 int result = inflateInit(zlib_stream_); 0014 Q_ASSERT(result == Z_OK); 0015 Q_UNUSED(result); 0016 connect(device, &QIODevice::aboutToClose, this, &ZLibDecompressor::flush); 0017 flushed_ = false; 0018 } 0019 0020 ZLibDecompressor::~ZLibDecompressor() 0021 { 0022 flush(); 0023 free(zlib_stream_); 0024 } 0025 0026 void ZLibDecompressor::flush() 0027 { 0028 if (flushed_) 0029 return; 0030 0031 // Flush 0032 write(QByteArray(),true); 0033 int result = inflateEnd(zlib_stream_); 0034 if (result != Z_OK) 0035 qWarning("compressor.c: inflateEnd failed (%d)", result); 0036 0037 flushed_ = true; 0038 } 0039 0040 int ZLibDecompressor::write(const QByteArray& input) 0041 { 0042 return write(input,false); 0043 } 0044 0045 int ZLibDecompressor::write(const QByteArray& input, bool flush) 0046 { 0047 int result; 0048 zlib_stream_->avail_in = input.size(); 0049 zlib_stream_->next_in = (Bytef*) input.data(); 0050 QByteArray output; 0051 0052 // Write the data 0053 int output_position = 0; 0054 do { 0055 output.resize(output_position + CHUNK_SIZE); 0056 zlib_stream_->avail_out = CHUNK_SIZE; 0057 zlib_stream_->next_out = (Bytef*) (output.data() + output_position); 0058 result = inflate(zlib_stream_,(flush ? Z_FINISH : Z_NO_FLUSH)); 0059 if (result == Z_STREAM_ERROR) { 0060 qWarning("compressor.cpp: Error ('%s')", zlib_stream_->msg); 0061 return result; 0062 } 0063 output_position += CHUNK_SIZE; 0064 } 0065 while (zlib_stream_->avail_out == 0); 0066 //Q_ASSERT(zlib_stream_->avail_in == 0); 0067 if (zlib_stream_->avail_in != 0) { 0068 qWarning() << "ZLibDecompressor: Unexpected state: avail_in=" << zlib_stream_->avail_in << ",avail_out=" << zlib_stream_->avail_out << ",result=" << result; 0069 return Z_STREAM_ERROR; // FIXME: Should probably return 'result' 0070 } 0071 output_position -= zlib_stream_->avail_out; 0072 0073 // Flush the data 0074 if (!flush) { 0075 do { 0076 output.resize(output_position + CHUNK_SIZE); 0077 zlib_stream_->avail_out = CHUNK_SIZE; 0078 zlib_stream_->next_out = (Bytef*) (output.data() + output_position); 0079 result = inflate(zlib_stream_,Z_SYNC_FLUSH); 0080 if (result == Z_STREAM_ERROR) { 0081 qWarning("compressor.cpp: Error ('%s')", zlib_stream_->msg); 0082 return result; 0083 } 0084 output_position += CHUNK_SIZE; 0085 } 0086 while (zlib_stream_->avail_out == 0); 0087 output_position -= zlib_stream_->avail_out; 0088 } 0089 output.resize(output_position); 0090 0091 // Write the compressed data 0092 device_->write(output); 0093 return 0; 0094 }