summaryrefslogtreecommitdiffabout
path: root/pwmanager/pwmanager/compressgzip.cpp
blob: 0a325c6319f1f876976996d0a5d4fc1bbf80a9fc (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/***************************************************************************
 *                                                                         *
 *   copyright (C) 2003, 2004 by Michael Buesch                            *
 *   email: mbuesch@freenet.de                                             *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation.                         *
 *                                                                         *
 ***************************************************************************/

/***************************************************************************
 * copyright (C) 2004 by Ulf Schenk
 * This file is originaly based on version 1.0.1 of pwmanager
 * and was modified to run on embedded devices that run microkde
 *
 * $Id$
 **************************************************************************/  

#include "compressgzip.h"

#include <stdlib.h>
#include <zlib.h>

#define COMPRESSION_LEVEL			Z_BEST_COMPRESSION
#define EXPAND_COMPRESS_DESTBUF_BYTES		1024
#define EXPAND_DECOMPRESS_DESTBUF_BYTES		(1024 * 10)


bool CompressGzip::compress(string *d)
{
	int ret;
	Bytef *dest;
	const Bytef *source;
	unsigned long sourceLen, destLen;

	source = reinterpret_cast<const Bytef *>(d->c_str());
	sourceLen = d->length();
	destLen = calcCompressDestLen(sourceLen);
	dest = static_cast<Bytef *>(malloc(destLen));
	if (!dest)
		return false;
	while (1) {
		ret = compress2(dest,
				static_cast<uLongf *>(&destLen),
				source,
				static_cast<uLong>(sourceLen),
				COMPRESSION_LEVEL);
		switch (ret) {
		case Z_OK:
			goto out;
		case Z_BUF_ERROR:
			/* we don't use realloc(), because it may
			 * (in this case) unneccessarily copy the old block
			 * to the new allocated block.
			 */
			free(dest);
			destLen += EXPAND_COMPRESS_DESTBUF_BYTES;
			dest = static_cast<Bytef *>(malloc(destLen));
			if (!dest)
				return false;
			break;
		default:
			free(dest);
			return false;
		}
	}
out:
	d->assign(reinterpret_cast<char *>(dest), destLen);
	free(dest);
	return true;
}

bool CompressGzip::decompress(string *d)
{
	int ret;
	Bytef *dest;
	const Bytef *source;
	unsigned long sourceLen, destLen;

	source = reinterpret_cast<const Bytef *>(d->c_str());
	sourceLen = d->length();
	destLen = calcDecompressDestLen(sourceLen);
	dest = static_cast<Bytef *>(malloc(destLen));
	if (!dest)
		return false;
	while (1) {
		ret = uncompress(dest,
				 static_cast<uLongf *>(&destLen),
				 source,
				 static_cast<uLong>(sourceLen));
		switch (ret) {
		case Z_OK:
			goto out;
		case Z_BUF_ERROR:
			/* we don't use realloc(), because it may
			 * (in this case) unneccessarily copy the old block
			 * to the new allocated block.
			 */
			free(dest);
			destLen += EXPAND_DECOMPRESS_DESTBUF_BYTES;
			dest = static_cast<Bytef *>(malloc(destLen));
			if (!dest)
				return false;
			break;
		default:
			free(dest);
			return false;
		}
	}
out:
	d->assign(reinterpret_cast<char *>(dest), destLen);
	free(dest);
	return true;
}