-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathizstream.hpp
277 lines (221 loc) · 8.71 KB
/
izstream.hpp
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
zstream-cpp Library License:
--------------------------
The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux.
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution
Author: Jonathan de Halleux, [email protected], 2003
Gero Mueller, [email protected], 2015
*/
#ifndef INPUT_ZIP_STREAM_HPP
#define INPUT_ZIP_STREAM_HPP
#include <vector>
#include <iostream>
#include <algorithm>
#include <zlib.h>
#include "zstream_common.hpp"
namespace zstream {
/** \brief A stream decorator that takes compressed input and unzips it to a istream.
The class wraps up the deflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/
*/
template<typename Elem, typename Tr = std::char_traits<Elem>,
typename ElemA = std::allocator<Elem>, typename ByteT = unsigned char,
typename ByteAT = std::allocator<ByteT> >
class basic_unzip_streambuf: public std::basic_streambuf<Elem, Tr> {
public:
typedef std::basic_istream<Elem, Tr>& istream_reference;
typedef ElemA char_allocator_type;
typedef ByteT byte_type;
typedef ByteAT byte_allocator_type;
typedef byte_type* byte_buffer_type;
typedef typename std::basic_streambuf<Elem, Tr>::char_type char_type;
typedef typename std::basic_streambuf<Elem, Tr>::int_type int_type;
typedef std::vector<byte_type, byte_allocator_type> byte_vector_type;
typedef std::vector<char_type, char_allocator_type> char_vector_type;
/** Construct a unzip stream
* More info on the following parameters can be found in the zlib documentation.
*/
basic_unzip_streambuf(istream_reference istream_, size_t window_size_,
size_t read_buffer_size_, size_t input_buffer_size_);
~basic_unzip_streambuf();
int_type underflow();
/// returns the compressed input istream
istream_reference get_istream() {
return m_istream;
}
/// returns the zlib stream structure
z_stream& get_zip_stream() {
return m_zip_stream;
}
/// returns the latest zlib error state
int get_zerr() const {
return m_err;
}
/// returns the crc of the uncompressed data so far
unsigned int get_crc() const {
return m_crc;
}
/// returns the number of uncompressed bytes
unsigned int get_out_size() const {
return m_zip_stream.total_out;
}
/// returns the number of read compressed bytes
unsigned long get_in_size() const {
return m_zip_stream.total_in;
}
private:
void put_back_from_zip_stream();
std::streamsize unzip_from_stream(char_type*, std::streamsize);
size_t fill_input_buffer();
istream_reference m_istream;
z_stream m_zip_stream;
int m_err;
byte_vector_type m_input_buffer;
char_vector_type m_buffer;
long m_crc;
};
/*! \brief Base class for unzip istreams
Contains a basic_unzip_streambuf.
*/
template<typename Elem, typename Tr = std::char_traits<Elem>,
typename ElemA = std::allocator<Elem>, typename ByteT = unsigned char,
typename ByteAT = std::allocator<ByteT> >
class basic_zip_istreambase: virtual public std::basic_ios<Elem, Tr> {
public:
typedef std::basic_istream<Elem, Tr>& istream_reference;
typedef basic_unzip_streambuf<Elem, Tr, ElemA, ByteT, ByteAT> unzip_streambuf_type;
basic_zip_istreambase(istream_reference ostream_, size_t window_size_,
size_t read_buffer_size_, size_t input_buffer_size_) :
m_buf(ostream_, window_size_, read_buffer_size_, input_buffer_size_) {
this->init(&m_buf);
}
/// returns the underlying unzip istream object
unzip_streambuf_type* rdbuf() {
return &m_buf;
}
/// returns the zlib error state
int get_zerr() const {
return m_buf.get_zerr();
}
/// returns the uncompressed data crc
long get_crc() const {
return m_buf.get_crc();
}
/// returns the uncompressed data size
long get_out_size() const {
return m_buf.get_out_size();
}
/// returns the compressed data size
unsigned long get_in_size() const {
return m_buf.get_in_size();
}
private:
unzip_streambuf_type m_buf;
};
/*! \brief A zipper istream
This class is a istream decorator that behaves 'almost' like any other ostream.
At construction, it takes any istream that shall be used to input of the compressed data.
Simlpe example:
\code
// create a stream on zip string
istringstream istringstream_( ostringstream_.str());
// create unzipper istream
zip_istream unzipper( istringstream_);
// read and unzip
unzipper>>f_r>>d_r>>ui_r>>ul_r>>us_r>>c_r>>dum_r;
\endcode
*/
template<typename Elem, typename Tr = std::char_traits<Elem>,
typename ElemA = std::allocator<Elem>, typename ByteT = unsigned char,
typename ByteAT = std::allocator<ByteT> >
class basic_gzip_istream: public basic_zip_istreambase<Elem, Tr, ElemA, ByteT,
ByteAT>, public std::basic_istream<Elem, Tr> {
public:
typedef typename std::basic_istream<Elem, Tr>::char_type char_type;
typedef std::basic_istream<Elem, Tr>& istream_reference;
typedef basic_zip_istreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_istreambase_type;
typedef std::basic_istream<Elem, Tr> istream_type;
typedef unsigned char byte_type;
/** Construct a unzipper stream
*
* \param istream_ input buffer
* \param window_size_
* \param read_buffer_size_
* \param input_buffer_size_
*/
basic_gzip_istream(istream_reference istream_, size_t window_size_ = 15,
size_t read_buffer_size_ = detail::default_buffer_size,
size_t input_buffer_size_ = detail::default_buffer_size) :
zip_istreambase_type(istream_, window_size_, read_buffer_size_,
input_buffer_size_), istream_type(this->rdbuf()), m_gzip_crc(
0), m_gzip_data_size(0) {
if (this->rdbuf()->get_zerr() == Z_OK)
check_header();
}
/// reads the gzip header
void read_footer();
/** return crc check result
When you have finished reading the compressed data, call read_footer to read the uncompressed data crc.
This method compares it to the crc of the uncompressed data.
\return true if crc check is succesful
*/
bool check_crc() const {
return this->get_crc() == m_gzip_crc;
}
/// return data size check
bool check_data_size() const {
return this->get_out_size() == m_gzip_data_size;
}
/// return the crc value in the file
unsigned int get_gzip_crc() const {
return m_gzip_crc;
}
/// return the data size in the file
unsigned int get_gzip_data_size() const {
return m_gzip_data_size;
}
protected:
static void read_long(istream_reference in_, unsigned int& x_);
int check_header();
unsigned int m_gzip_crc;
unsigned int m_gzip_data_size;
};
template<typename Elem, typename Tr = std::char_traits<Elem>,
typename ElemA = std::allocator<Elem>, typename ByteT = unsigned char,
typename ByteAT = std::allocator<ByteT> >
class basic_zip_istream: public basic_zip_istreambase<Elem, Tr, ElemA, ByteT,
ByteAT>, public std::basic_istream<Elem, Tr> {
public:
typedef typename std::basic_istream<Elem, Tr>::char_type char_type;
typedef std::basic_istream<Elem, Tr>& istream_reference;
typedef basic_zip_istreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_istreambase_type;
typedef std::basic_istream<Elem, Tr> istream_type;
typedef unsigned char byte_type;
/** Construct a unzipper stream
*
* \param istream_ input buffer
* \param window_size_
* \param read_buffer_size_
* \param input_buffer_size_
*/
basic_zip_istream(istream_reference istream_, size_t window_size_ = 15,
size_t read_buffer_size_ = detail::default_buffer_size,
size_t input_buffer_size_ = detail::default_buffer_size) :
zip_istreambase_type(istream_, window_size_, read_buffer_size_,
input_buffer_size_), istream_type(this->rdbuf()) {
}
};
/// A typedef for basic_zip_istream<char>
typedef basic_gzip_istream<char> igzstream;
/// A typedef for basic_zip_istream<wchart>
typedef basic_gzip_istream<wchar_t> wigzstream;
/// A typedef for basic_zip_istream<char>
typedef basic_zip_istream<char> izstream;
/// A typedef for basic_zip_istream<wchart>
typedef basic_zip_istream<wchar_t> wizstream;
} // zstream
#include "izstream_impl.hpp"
#endif