File: gzip.cpp

package info (click to toggle)
btanks 0.9.8083-9
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 43,616 kB
  • sloc: cpp: 46,425; ansic: 12,005; xml: 4,262; python: 313; sh: 13; makefile: 13
file content (118 lines) | stat: -rw-r--r-- 3,218 bytes parent folder | download | duplicates (5)
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
116
117
118
/* M-runtime for c++
 * Copyright (C) 2005-2008 Vladimir Menshakov
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "gzip.h"
#include "chunk.h"
#include "exception.h"
#include "logger.h"
#include <string.h>

using namespace mrt;

#define throw_z(method, ret) throw_ex(("zlib.%s failed: %s, code: %d", method, z.msg, ret));

#define BUF 0x10000

void ZStream::decompress(mrt::Chunk &dst, const mrt::Chunk &src, const bool gzip_header) {
	z_stream z;
	memset(&z, 0, sizeof(z));
	try {
		int ret;
		z.avail_in = src.get_size();
		z.next_in = (Bytef*) src.get_ptr();

		if ((ret = inflateInit2(&z, gzip_header?0x1f:0x0f)) != Z_OK)
			throw_z("inflateInit", ret);
		
		dst.set_size(BUF);
		do { 
			if (z.avail_in == 0)
				break;
			z.avail_out = dst.get_size() - z.total_out;
			z.next_out = (Bytef*)dst.get_ptr() + z.total_out;
		
			ret = inflate(&z, Z_FINISH);
			
			if (ret == Z_STREAM_END) 
				break;
			
			if (ret == Z_BUF_ERROR || z.avail_out == 0) {
				if (z.avail_out == 0) {
					LOG_DEBUG(("ran out of out buf"));
					dst.set_size(dst.get_size() + BUF);					
					continue;
				} else if (z.avail_in == 0) {
					throw_ex(("stream was truncated. unable to proceed."));
				}
			}

			if (ret != Z_OK)
				throw_z("inflate", ret);
		
		} while(true);

		if ((ret = inflateEnd(&z)) != Z_OK) 
			throw_z("inflateEnd", ret);
		
		dst.set_size(z.total_out);
	} CATCH("decompress", {inflateEnd(&z); throw;});
}

void ZStream::compress(mrt::Chunk &dst, const mrt::Chunk &src, const bool gzip_header, const int level) {
	z_stream z;
	memset(&z, 0, sizeof(z));
	try {
		int ret;
		z.avail_in = src.get_size();
		z.next_in = (Bytef*) src.get_ptr();

		if ((ret = deflateInit2(&z, level, Z_DEFLATED, gzip_header?0x1f:0x0f, 8, Z_DEFAULT_STRATEGY)) != Z_OK)
			throw_z("DeflateInit", ret);
		
		dst.set_size(BUF);

		do {
			z.avail_out = dst.get_size() - z.total_out;
			z.next_out = (Bytef*)dst.get_ptr() + z.total_out;
		
			ret = deflate(&z, Z_FINISH);
			
			if (ret == Z_STREAM_END) 
				break;
			
			if (ret == Z_BUF_ERROR || z.avail_out == 0) {
				if (z.avail_out == 0) {
					LOG_DEBUG(("ran out of out buf"));
					dst.set_size(dst.get_size() + BUF);					
					continue;
				} else if (z.avail_in == 0) {
					throw_ex(("stream was truncated. unable to proceed."));
				}
			}

			if (ret != Z_OK)
				throw_z("deflate", ret);
			
		} while(true);
		if ((ret = deflateEnd(&z)) != Z_OK) 
			throw_z("deflateEnd", ret);
		
		dst.set_size(z.total_out);
	} CATCH("compress", {deflateEnd(&z); throw;});

}