summaryrefslogtreecommitdiff
path: root/distfoldd/compressor.cc
blob: 98eaa922bcdea813b91608304442a425668a1024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <QtCore/QDebug>

#include <zlib.h>
#include "compressor.h"

Compressor::Compressor()
{
}

QByteArray Compressor::compress(const QByteArray& data)
{
	if (data.isEmpty()) return data;

	QByteArray in = data, out;
	z_stream strm;
	int ret;

	memset(&strm, 0, sizeof(strm));
	out.resize(qMax(in.size(), 1024));

	strm.avail_in = in.size();
	strm.next_in = reinterpret_cast<Bytef*>(in.data());
	strm.avail_out = out.size();
	strm.next_out = reinterpret_cast<Bytef*>(out.data());

	ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
	if (ret != Z_OK) {
		qWarning() << "deflateInit failed";
		return data;
	}

	do {
		if (strm.avail_out == 0) {
			int cur_size = out.size();
			out.resize(cur_size * 2);
			strm.avail_out = cur_size;
			strm.next_out = reinterpret_cast<Bytef*>(&out.data()[cur_size]);
		}
		ret = deflate(&strm, Z_FINISH);
	} while (ret == Z_OK || ret == Z_BUF_ERROR);

	Q_ASSERT(ret == Z_STREAM_END);
	Q_ASSERT(strm.avail_in == 0);
	if (strm.avail_out > 0) {
		out.resize(out.size() - strm.avail_out);
	}

	deflateEnd(&strm);

	return out;
}

QByteArray Compressor::decompress(const QByteArray& data)
{
	if (data.isEmpty()) return data;

	QByteArray in = data, out;
	z_stream strm;
	int ret;

	memset(&strm, 0, sizeof(strm));
	out.resize(qMax(static_cast<int>(in.size() * 1.5), 1024));

	strm.avail_in = in.size();
	strm.next_in = reinterpret_cast<Bytef*>(in.data());
	strm.avail_out = out.size();
	strm.next_out = reinterpret_cast<Bytef*>(out.data());

	ret = inflateInit(&strm);
	if (ret != Z_OK) {
		qWarning() << "inflateInit failed";
		return data;
	}

	do {
		if (strm.avail_out == 0) {
			int cur_size = out.size();
			out.resize(cur_size * 2);
			strm.avail_out = cur_size;
			strm.next_out = reinterpret_cast<Bytef*>(&out.data()[cur_size]);
		}
		ret = inflate(&strm, Z_FINISH);
	} while (ret == Z_OK || ret == Z_BUF_ERROR);

	Q_ASSERT(ret == Z_STREAM_END);
	Q_ASSERT(strm.avail_in == 0);
	if (strm.avail_out > 0) {
		out.resize(out.size() - strm.avail_out);
	}

	inflateEnd(&strm);

	return out;
}