File indexing completed on 2024-06-16 05:01:51

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0004 ** All rights reserved.
0005 ** Contact: Nokia Corporation (qt-info@nokia.com)
0006 **
0007 ** This file is part of the Qt Messaging Framework.
0008 **
0009 ** $QT_BEGIN_LICENSE:LGPL$
0010 ** GNU Lesser General Public License Usage
0011 ** This file may be used under the terms of the GNU Lesser General Public
0012 ** License version 2.1 as published by the Free Software Foundation and
0013 ** appearing in the file LICENSE.LGPL included in the packaging of this
0014 ** file. Please review the following information to ensure the GNU Lesser
0015 ** General Public License version 2.1 requirements will be met:
0016 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0017 **
0018 ** In addition, as a special exception, Nokia gives you certain additional
0019 ** rights. These rights are described in the Nokia Qt LGPL Exception
0020 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
0021 **
0022 ** GNU General Public License Usage
0023 ** Alternatively, this file may be used under the terms of the GNU General
0024 ** Public License version 3.0 as published by the Free Software Foundation
0025 ** and appearing in the file LICENSE.GPL included in the packaging of this
0026 ** file. Please review the following information to ensure the GNU General
0027 ** Public License version 3.0 requirements will be met:
0028 ** http://www.gnu.org/copyleft/gpl.html.
0029 **
0030 ** Other Usage
0031 ** Alternatively, this file may be used in accordance with the terms and
0032 ** conditions contained in a signed written agreement between you and Nokia.
0033 **
0034 **
0035 **
0036 **
0037 **
0038 ** $QT_END_LICENSE$
0039 
0040 This file contains modifications by Jan Kundrát <jkt@flaska.net> for use in Trojitá.
0041 These modifications are released into public domain.
0042 
0043 **
0044 ****************************************************************************/
0045 
0046 #include "rfc1951.h"
0047 
0048 namespace Streams {
0049 
0050 Rfc1951Compressor::Rfc1951Compressor(int chunkSize)
0051 {
0052     _chunkSize = chunkSize;
0053     _buffer = new char[chunkSize];
0054 
0055     /* allocate deflate state */
0056     _zStream.zalloc = Z_NULL;
0057     _zStream.zfree = Z_NULL;
0058     _zStream.opaque = Z_NULL;
0059 
0060     bool ok(deflateInit2(&_zStream,
0061                           Z_DEFAULT_COMPRESSION, 
0062                           Z_DEFLATED, 
0063                           -(MAX_WBITS-2), // 32KB // MAX_WBITS == 15 (zconf.h) MEM128KB
0064                           MAX_MEM_LEVEL-2 , // 64KB // MAX_MEM_LEVEL = 9 (zconf.h) MEM256KB
0065                           Z_DEFAULT_STRATEGY) == Z_OK);
0066     Q_ASSERT(ok); Q_UNUSED(ok);
0067 }
0068 
0069 Rfc1951Compressor::~Rfc1951Compressor()
0070 {
0071     delete[] _buffer;
0072     deflateEnd(&_zStream);
0073 }
0074 
0075 bool Rfc1951Compressor::write(QIODevice *out, QByteArray *in)
0076 {
0077     _zStream.next_in = reinterpret_cast<Bytef*>(in->data());
0078     _zStream.avail_in = in->size();
0079     
0080     do {
0081         _zStream.next_out = reinterpret_cast<Bytef*>(_buffer);
0082         _zStream.avail_out = _chunkSize;
0083         int result = deflate(&_zStream, Z_SYNC_FLUSH);
0084         if (result != Z_OK &&
0085             result != Z_STREAM_END &&
0086             result != Z_BUF_ERROR) {
0087             return false;
0088         }
0089         out->write(_buffer, _chunkSize - _zStream.avail_out);
0090     } while (!_zStream.avail_out);
0091     return true;
0092 }
0093 
0094 
0095 Rfc1951Decompressor::Rfc1951Decompressor(int chunkSize)
0096 {
0097     _chunkSize = chunkSize;
0098     _stagingBuffer = new char[_chunkSize];
0099 
0100     /* allocate inflate state */
0101     _zStream.zalloc = Z_NULL;
0102     _zStream.zfree = Z_NULL;
0103     _zStream.opaque = Z_NULL;
0104     _zStream.avail_in = 0;
0105     _zStream.next_in = Z_NULL;
0106     bool ok(inflateInit2(&_zStream, -MAX_WBITS) == Z_OK);
0107     Q_ASSERT(ok); Q_UNUSED(ok);
0108 }
0109 
0110 Rfc1951Decompressor::~Rfc1951Decompressor()
0111 {
0112     inflateEnd(&_zStream);
0113     delete[] _stagingBuffer;
0114 }
0115 
0116 bool Rfc1951Decompressor::consume(QIODevice *in)
0117 {
0118     while (in->bytesAvailable()) {
0119         _inBuffer = in->read(_chunkSize);
0120         _zStream.next_in = reinterpret_cast<Bytef*>(_inBuffer.data());
0121         _zStream.avail_in = _inBuffer.size();
0122         do {
0123             _zStream.next_out = reinterpret_cast<Bytef *>(_stagingBuffer);
0124             _zStream.avail_out = _chunkSize;
0125             int result = inflate(&_zStream, Z_SYNC_FLUSH);
0126             if (result != Z_OK &&
0127                 result != Z_STREAM_END &&
0128                 result != Z_BUF_ERROR) {
0129                 return false;
0130             }
0131             _output.append(_stagingBuffer, _chunkSize - _zStream.avail_out);
0132         } while (_zStream.avail_out == 0);
0133     }
0134     return true;
0135 }
0136 
0137 bool Rfc1951Decompressor::canReadLine() const
0138 {
0139     return _output.contains('\n');
0140 }
0141 
0142 QByteArray Rfc1951Decompressor::readLine()
0143 {
0144     int eolPos = _output.indexOf('\n');
0145     if (eolPos == -1) {
0146         return QByteArray();
0147     }
0148     
0149     QByteArray result = _output.left(eolPos + 1);
0150     _output = _output.mid(eolPos + 1);
0151     return result;
0152 }
0153 
0154 QByteArray Rfc1951Decompressor::read(qint64 maxSize)
0155 {
0156     QByteArray res = _output.left(maxSize);
0157     _output = _output.mid(maxSize);
0158     return res;
0159 }
0160 
0161 }