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 }