1 |
tim |
613 |
/* |
2 |
|
|
zipstream Library License: |
3 |
|
|
-------------------------- |
4 |
|
|
|
5 |
|
|
The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. |
6 |
|
|
|
7 |
|
|
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. |
8 |
|
|
|
9 |
|
|
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: |
10 |
|
|
|
11 |
|
|
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. |
12 |
|
|
|
13 |
|
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. |
14 |
|
|
|
15 |
|
|
3. This notice may not be removed or altered from any source distribution |
16 |
|
|
|
17 |
|
|
Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#ifndef ZIPSTREAM_HPP |
21 |
|
|
#define ZIPSTREAM_HPP |
22 |
|
|
|
23 |
|
|
#include <vector> |
24 |
|
|
#include <iostream> |
25 |
|
|
#include <algorithm> |
26 |
|
|
#include <sstream> |
27 |
|
|
#include <zlib.h> |
28 |
|
|
//#include <zlib/zlib.h> |
29 |
|
|
//#include <zlib/zutil.h> |
30 |
|
|
|
31 |
|
|
#ifdef HAVE_ZUTIL_H |
32 |
|
|
#include <zutil.h> |
33 |
|
|
#else |
34 |
|
|
#ifdef MSDOS |
35 |
|
|
# define OS_CODE 0x00 |
36 |
|
|
# if defined(__TURBOC__) || defined(__BORLANDC__) |
37 |
|
|
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) |
38 |
|
|
/* Allow compilation with ANSI keywords only enabled */ |
39 |
|
|
void _Cdecl farfree( void *block ); |
40 |
|
|
void *_Cdecl farmalloc( unsigned long nbytes ); |
41 |
|
|
# else |
42 |
|
|
# include <alloc.h> |
43 |
|
|
# endif |
44 |
|
|
# else /* MSC or DJGPP */ |
45 |
|
|
# include <malloc.h> |
46 |
|
|
# endif |
47 |
|
|
#endif |
48 |
|
|
|
49 |
|
|
#ifdef OS2 |
50 |
|
|
# define OS_CODE 0x06 |
51 |
|
|
#endif |
52 |
|
|
|
53 |
|
|
#ifdef WIN32 /* Window 95 & Windows NT */ |
54 |
|
|
# define OS_CODE 0x0b |
55 |
|
|
#endif |
56 |
|
|
|
57 |
|
|
#if defined(VAXC) || defined(VMS) |
58 |
|
|
# define OS_CODE 0x02 |
59 |
|
|
# define F_OPEN(name, mode) \ |
60 |
|
|
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") |
61 |
|
|
#endif |
62 |
|
|
|
63 |
|
|
#ifdef AMIGA |
64 |
|
|
# define OS_CODE 0x01 |
65 |
|
|
#endif |
66 |
|
|
|
67 |
|
|
#if defined(ATARI) || defined(atarist) |
68 |
|
|
# define OS_CODE 0x05 |
69 |
|
|
#endif |
70 |
|
|
|
71 |
|
|
#if defined(MACOS) || defined(TARGET_OS_MAC) |
72 |
|
|
# define OS_CODE 0x07 |
73 |
|
|
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os |
74 |
|
|
# include <unix.h> /* for fdopen */ |
75 |
|
|
# else |
76 |
|
|
# ifndef fdopen |
77 |
|
|
# define fdopen(fd,mode) NULL /* No fdopen() */ |
78 |
|
|
# endif |
79 |
|
|
# endif |
80 |
|
|
#endif |
81 |
|
|
|
82 |
|
|
#ifdef __50SERIES /* Prime/PRIMOS */ |
83 |
|
|
# define OS_CODE 0x0F |
84 |
|
|
#endif |
85 |
|
|
|
86 |
|
|
#ifdef TOPS20 |
87 |
|
|
# define OS_CODE 0x0a |
88 |
|
|
#endif |
89 |
|
|
|
90 |
|
|
#if defined(_BEOS_) || defined(RISCOS) |
91 |
|
|
# define fdopen(fd,mode) NULL /* No fdopen() */ |
92 |
|
|
#endif |
93 |
|
|
|
94 |
|
|
#if (defined(_MSC_VER) && (_MSC_VER > 600)) |
95 |
|
|
# define fdopen(fd,type) _fdopen(fd,type) |
96 |
|
|
#endif |
97 |
|
|
|
98 |
|
|
|
99 |
|
|
/* Common defaults */ |
100 |
|
|
|
101 |
|
|
#ifndef OS_CODE |
102 |
|
|
# define OS_CODE 0x03 /* assume Unix */ |
103 |
|
|
#endif |
104 |
|
|
|
105 |
|
|
#endif |
106 |
|
|
|
107 |
|
|
namespace zlib_stream{ |
108 |
|
|
|
109 |
|
|
/// default gzip buffer size, |
110 |
|
|
/// change this to suite your needs |
111 |
|
|
const size_t default_buffer_size = 4096; |
112 |
|
|
|
113 |
|
|
/// Compression strategy, see zlib doc. |
114 |
|
|
enum EStrategy |
115 |
|
|
{ |
116 |
|
|
StrategyFiltered = 1, |
117 |
|
|
StrategyHuffmanOnly = 2, |
118 |
|
|
DefaultStrategy = 0 |
119 |
|
|
}; |
120 |
|
|
|
121 |
|
|
/** \brief A stream decorator that takes raw input and zips it to a ostream. |
122 |
|
|
|
123 |
|
|
The class wraps up the inflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/ |
124 |
|
|
*/ |
125 |
|
|
template< |
126 |
|
|
typename Elem, |
127 |
|
|
typename Tr = std::char_traits<Elem>, |
128 |
|
|
typename ElemA = std::allocator<Elem>, |
129 |
|
|
typename ByteT = unsigned char, |
130 |
|
|
typename ByteAT = std::allocator<ByteT> |
131 |
|
|
> |
132 |
|
|
class basic_zip_streambuf : public std::basic_streambuf<Elem, Tr> |
133 |
|
|
{ |
134 |
|
|
public: |
135 |
|
|
typedef std::basic_ostream<Elem, Tr>& ostream_reference; |
136 |
|
|
typedef ElemA char_allocator_type; |
137 |
|
|
typedef ByteT byte_type; |
138 |
|
|
typedef ByteAT byte_allocator_type; |
139 |
|
|
typedef byte_type* byte_buffer_type; |
140 |
|
|
typedef std::vector<byte_type, byte_allocator_type > byte_vector_type; |
141 |
|
|
typedef std::vector<char_type, char_allocator_type > char_vector_type; |
142 |
|
|
|
143 |
|
|
/** Construct a zip stream |
144 |
|
|
* More info on the following parameters can be found in the zlib documentation. |
145 |
|
|
*/ |
146 |
|
|
basic_zip_streambuf( |
147 |
|
|
ostream_reference ostream_, |
148 |
|
|
size_t level_, |
149 |
|
|
EStrategy strategy_, |
150 |
|
|
size_t window_size_, |
151 |
|
|
size_t memory_level_, |
152 |
|
|
size_t buffer_size_ |
153 |
|
|
); |
154 |
|
|
|
155 |
|
|
~basic_zip_streambuf(); |
156 |
|
|
|
157 |
|
|
int sync (); |
158 |
|
|
int_type overflow (int_type c); |
159 |
|
|
|
160 |
|
|
/** flushes the zip buffer and output buffer. |
161 |
|
|
|
162 |
|
|
This method should be called at the end of the compression. Calling flush multiple times, will lower the |
163 |
|
|
compression ratio. |
164 |
|
|
*/ |
165 |
|
|
std::streamsize flush(); |
166 |
|
|
/// returns a reference to the output stream |
167 |
|
|
ostream_reference get_ostream() const { return m_ostream;}; |
168 |
|
|
/// returns the latest zlib error status |
169 |
|
|
int get_zerr() const { return m_err;}; |
170 |
|
|
/// returns the crc of the input data compressed so far. |
171 |
|
|
long get_crc() const { return m_crc;}; |
172 |
|
|
/// returns the size (bytes) of the input data compressed so far. |
173 |
|
|
long get_in_size() const { return m_zip_stream.total_in;}; |
174 |
|
|
/// returns the size (bytes) of the compressed data so far. |
175 |
|
|
long get_out_size() const { return m_zip_stream.total_out;}; |
176 |
|
|
private: |
177 |
|
|
bool zip_to_stream( char_type*, std::streamsize); |
178 |
|
|
size_t fill_input_buffer(); |
179 |
|
|
|
180 |
|
|
ostream_reference m_ostream; |
181 |
|
|
z_stream m_zip_stream; |
182 |
|
|
int m_err; |
183 |
|
|
byte_vector_type m_output_buffer; |
184 |
|
|
char_vector_type m_buffer; |
185 |
|
|
long m_crc; |
186 |
|
|
}; |
187 |
|
|
|
188 |
|
|
/** \brief A stream decorator that takes compressed input and unzips it to a istream. |
189 |
|
|
|
190 |
|
|
The class wraps up the deflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/ |
191 |
|
|
*/ |
192 |
|
|
template< |
193 |
|
|
typename Elem, |
194 |
|
|
typename Tr = std::char_traits<Elem>, |
195 |
|
|
typename ElemA = std::allocator<Elem>, |
196 |
|
|
typename ByteT = unsigned char, |
197 |
|
|
typename ByteAT = std::allocator<ByteT> |
198 |
|
|
> |
199 |
|
|
class basic_unzip_streambuf : |
200 |
|
|
public std::basic_streambuf<Elem, Tr> |
201 |
|
|
{ |
202 |
|
|
public: |
203 |
|
|
typedef std::basic_istream<Elem, Tr>& istream_reference; |
204 |
|
|
typedef ElemA char_allocator_type; |
205 |
|
|
typedef ByteT byte_type; |
206 |
|
|
typedef ByteAT byte_allocator_type; |
207 |
|
|
typedef byte_type* byte_buffer_type; |
208 |
|
|
typedef std::vector<byte_type, byte_allocator_type > byte_vector_type; |
209 |
|
|
typedef std::vector<char_type, char_allocator_type > char_vector_type; |
210 |
|
|
|
211 |
|
|
/** Construct a unzip stream |
212 |
|
|
* More info on the following parameters can be found in the zlib documentation. |
213 |
|
|
*/ |
214 |
|
|
basic_unzip_streambuf( |
215 |
|
|
istream_reference istream_, |
216 |
|
|
size_t window_size_, |
217 |
|
|
size_t read_buffer_size_, |
218 |
|
|
size_t input_buffer_size_ |
219 |
|
|
); |
220 |
|
|
|
221 |
|
|
~basic_unzip_streambuf(); |
222 |
|
|
|
223 |
|
|
int_type underflow(); |
224 |
|
|
|
225 |
|
|
|
226 |
|
|
/// returns the compressed input istream |
227 |
|
|
istream_reference get_istream() { return m_istream;}; |
228 |
|
|
/// returns the zlib stream structure |
229 |
|
|
z_stream& get_zip_stream() { return m_zip_stream;}; |
230 |
|
|
/// returns the latest zlib error state |
231 |
|
|
int get_zerr() const { return m_err;}; |
232 |
|
|
/// returns the crc of the uncompressed data so far |
233 |
|
|
long get_crc() const { return m_crc;}; |
234 |
|
|
/// returns the number of uncompressed bytes |
235 |
|
|
long get_out_size() const { return m_zip_stream.total_out;}; |
236 |
|
|
/// returns the number of read compressed bytes |
237 |
|
|
long get_in_size() const { return m_zip_stream.total_in;}; |
238 |
|
|
private: |
239 |
|
|
void put_back_from_zip_stream(); |
240 |
|
|
std::streamsize unzip_from_stream( char_type*, std::streamsize); |
241 |
|
|
|
242 |
|
|
size_t fill_input_buffer(); |
243 |
|
|
|
244 |
|
|
istream_reference m_istream; |
245 |
|
|
z_stream m_zip_stream; |
246 |
|
|
int m_err; |
247 |
|
|
byte_vector_type m_input_buffer; |
248 |
|
|
char_vector_type m_buffer; |
249 |
|
|
long m_crc; |
250 |
|
|
}; |
251 |
|
|
|
252 |
|
|
/*! \brief Base class for zip ostreams |
253 |
|
|
|
254 |
|
|
Contains a basic_zip_streambuf. |
255 |
|
|
*/ |
256 |
|
|
template< |
257 |
|
|
typename Elem, |
258 |
|
|
typename Tr = std::char_traits<Elem>, |
259 |
|
|
typename ElemA = std::allocator<Elem>, |
260 |
|
|
typename ByteT = unsigned char, |
261 |
|
|
typename ByteAT = std::allocator<ByteT> |
262 |
|
|
> |
263 |
|
|
class basic_zip_ostreambase : virtual public std::basic_ios<Elem,Tr> |
264 |
|
|
{ |
265 |
|
|
public: |
266 |
|
|
typedef std::basic_ostream<Elem, Tr>& ostream_reference; |
267 |
|
|
typedef basic_zip_streambuf< |
268 |
|
|
Elem, |
269 |
|
|
Tr, |
270 |
|
|
ElemA, |
271 |
|
|
ByteT, |
272 |
|
|
ByteAT |
273 |
|
|
> zip_streambuf_type; |
274 |
|
|
|
275 |
|
|
/** Construct a zip stream |
276 |
|
|
* More info on the following parameters can be found in the zlib documentation. |
277 |
|
|
*/ |
278 |
|
|
basic_zip_ostreambase( |
279 |
|
|
ostream_reference ostream_, |
280 |
|
|
size_t level_, |
281 |
|
|
EStrategy strategy_, |
282 |
|
|
size_t window_size_, |
283 |
|
|
size_t memory_level_, |
284 |
|
|
size_t buffer_size_ |
285 |
|
|
) |
286 |
|
|
: m_buf(ostream_,level_,strategy_,window_size_,memory_level_,buffer_size_) |
287 |
|
|
{ |
288 |
|
|
init(&m_buf ); |
289 |
|
|
}; |
290 |
|
|
|
291 |
|
|
/// returns the underlying zip ostream object |
292 |
|
|
zip_streambuf_type* rdbuf() { return &m_buf; }; |
293 |
|
|
|
294 |
|
|
/// returns the zlib error state |
295 |
|
|
int get_zerr() const { return m_buf.get_err();}; |
296 |
|
|
/// returns the uncompressed data crc |
297 |
|
|
long get_crc() const { return m_buf.get_crc();}; |
298 |
|
|
/// returns the compressed data size |
299 |
|
|
long get_out_size() const { return m_buf.get_out_size();}; |
300 |
|
|
/// returns the uncompressed data size |
301 |
|
|
long get_in_size() const { return m_buf.get_in_size();}; |
302 |
|
|
private: |
303 |
|
|
zip_streambuf_type m_buf; |
304 |
|
|
}; |
305 |
|
|
|
306 |
|
|
/*! \brief Base class for unzip istreams |
307 |
|
|
|
308 |
|
|
Contains a basic_unzip_streambuf. |
309 |
|
|
*/ |
310 |
|
|
template< |
311 |
|
|
typename Elem, |
312 |
|
|
typename Tr = std::char_traits<Elem>, |
313 |
|
|
typename ElemA = std::allocator<Elem>, |
314 |
|
|
typename ByteT = unsigned char, |
315 |
|
|
typename ByteAT = std::allocator<ByteT> |
316 |
|
|
> |
317 |
|
|
class basic_zip_istreambase : virtual public std::basic_ios<Elem,Tr> |
318 |
|
|
{ |
319 |
|
|
public: |
320 |
|
|
typedef std::basic_istream<Elem, Tr>& istream_reference; |
321 |
|
|
typedef basic_unzip_streambuf< |
322 |
|
|
Elem, |
323 |
|
|
Tr, |
324 |
|
|
ElemA, |
325 |
|
|
ByteT, |
326 |
|
|
ByteAT |
327 |
|
|
> unzip_streambuf_type; |
328 |
|
|
|
329 |
|
|
basic_zip_istreambase( |
330 |
|
|
istream_reference ostream_, |
331 |
|
|
size_t window_size_, |
332 |
|
|
size_t read_buffer_size_, |
333 |
|
|
size_t input_buffer_size_ |
334 |
|
|
) |
335 |
|
|
: m_buf(ostream_,window_size_, read_buffer_size_, input_buffer_size_) |
336 |
|
|
{ |
337 |
|
|
init(&m_buf ); |
338 |
|
|
}; |
339 |
|
|
|
340 |
|
|
/// returns the underlying unzip istream object |
341 |
|
|
unzip_streambuf_type* rdbuf() { return &m_buf; }; |
342 |
|
|
|
343 |
|
|
/// returns the zlib error state |
344 |
|
|
int get_zerr() const { return m_buf.get_zerr();}; |
345 |
|
|
/// returns the uncompressed data crc |
346 |
|
|
long get_crc() const { return m_buf.get_crc();}; |
347 |
|
|
/// returns the uncompressed data size |
348 |
|
|
long get_out_size() const { return m_buf.get_out_size();}; |
349 |
|
|
/// returns the compressed data size |
350 |
|
|
long get_in_size() const { return m_buf.get_in_size();}; |
351 |
|
|
private: |
352 |
|
|
unzip_streambuf_type m_buf; |
353 |
|
|
}; |
354 |
|
|
|
355 |
|
|
/*! \brief A zipper ostream |
356 |
|
|
|
357 |
|
|
This class is a ostream decorator that behaves 'almost' like any other ostream. |
358 |
|
|
|
359 |
|
|
At construction, it takes any ostream that shall be used to output of the compressed data. |
360 |
|
|
|
361 |
|
|
When finished, you need to call the special method zflush or call the destructor |
362 |
|
|
to flush all the intermidiate streams. |
363 |
|
|
|
364 |
|
|
Example: |
365 |
|
|
\code |
366 |
|
|
// creating the target zip string, could be a fstream |
367 |
|
|
ostringstream ostringstream_; |
368 |
|
|
// creating the zip layer |
369 |
|
|
zip_ostream zipper(ostringstream_); |
370 |
|
|
|
371 |
|
|
|
372 |
|
|
// writing data |
373 |
|
|
zipper<<f<<" "<<d<<" "<<ui<<" "<<ul<<" "<<us<<" "<<c<<" "<<dum; |
374 |
|
|
// zip ostream needs special flushing... |
375 |
|
|
zipper.zflush(); |
376 |
|
|
\endcode |
377 |
|
|
*/ |
378 |
|
|
template< |
379 |
|
|
typename Elem, |
380 |
|
|
typename Tr = std::char_traits<Elem>, |
381 |
|
|
typename ElemA = std::allocator<Elem>, |
382 |
|
|
typename ByteT = unsigned char, |
383 |
|
|
typename ByteAT = std::allocator<ByteT> |
384 |
|
|
> |
385 |
|
|
class basic_zip_ostream : |
386 |
|
|
public basic_zip_ostreambase<Elem,Tr,ElemA,ByteT,ByteAT>, |
387 |
|
|
public std::basic_ostream<Elem,Tr> |
388 |
|
|
{ |
389 |
|
|
public: |
390 |
|
|
typedef basic_zip_ostreambase< |
391 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT> zip_ostreambase_type; |
392 |
|
|
typedef std::basic_ostream<Elem,Tr> ostream_type; |
393 |
|
|
|
394 |
|
|
/** Constructs a zipper ostream decorator |
395 |
|
|
* |
396 |
|
|
* \param ostream_ ostream where the compressed output is written |
397 |
|
|
* \param is_gzip_ true if gzip header and footer have to be added |
398 |
|
|
* \param level_ level of compression 0, bad and fast, 9, good and slower, |
399 |
|
|
* \param strategy_ compression strategy |
400 |
|
|
* \param window_size_ see zlib doc |
401 |
|
|
* \param memory_level_ see zlib doc |
402 |
|
|
* \param buffer_size_ the buffer size used to zip data |
403 |
|
|
|
404 |
|
|
When is_gzip_ is true, a gzip header and footer is automatically added. |
405 |
|
|
*/ |
406 |
|
|
basic_zip_ostream( |
407 |
|
|
ostream_reference ostream_, |
408 |
|
|
int open_mode = std::ios::out, |
409 |
|
|
bool is_gzip_ = false, |
410 |
|
|
size_t level_ = Z_DEFAULT_COMPRESSION, |
411 |
|
|
EStrategy strategy_ = DefaultStrategy, |
412 |
|
|
size_t window_size_ = 15, |
413 |
|
|
size_t memory_level_ = 8, |
414 |
|
|
size_t buffer_size_ = default_buffer_size |
415 |
|
|
) |
416 |
|
|
: |
417 |
|
|
zip_ostreambase_type( |
418 |
|
|
ostream_, |
419 |
|
|
level_, |
420 |
|
|
strategy_, |
421 |
|
|
window_size_, |
422 |
|
|
memory_level_, |
423 |
|
|
buffer_size_ |
424 |
|
|
), |
425 |
|
|
m_is_gzip(is_gzip_), |
426 |
|
|
ostream_type(rdbuf()) |
427 |
|
|
{ |
428 |
|
|
if (m_is_gzip) |
429 |
|
|
add_header(); |
430 |
|
|
}; |
431 |
|
|
~basic_zip_ostream() |
432 |
|
|
{ |
433 |
|
|
if (m_is_gzip) |
434 |
|
|
add_footer(); |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
/// returns true if it is a gzip |
438 |
|
|
bool is_gzip() const { return m_is_gzip;}; |
439 |
|
|
/// flush inner buffer and zipper buffer |
440 |
|
|
basic_zip_ostream<Elem,Tr>& zflush() |
441 |
|
|
{ |
442 |
|
|
flush(); rdbuf()->flush(); return *this; |
443 |
|
|
}; |
444 |
|
|
|
445 |
|
|
private: |
446 |
|
|
static void put_long(ostream_reference out_, unsigned long x_); |
447 |
|
|
|
448 |
|
|
void add_header(); |
449 |
|
|
void add_footer(); |
450 |
|
|
bool m_is_gzip; |
451 |
|
|
}; |
452 |
|
|
|
453 |
|
|
/*! \brief A zipper istream |
454 |
|
|
|
455 |
|
|
This class is a istream decorator that behaves 'almost' like any other ostream. |
456 |
|
|
|
457 |
|
|
At construction, it takes any istream that shall be used to input of the compressed data. |
458 |
|
|
|
459 |
|
|
Simlpe example: |
460 |
|
|
\code |
461 |
|
|
// create a stream on zip string |
462 |
|
|
istringstream istringstream_( ostringstream_.str()); |
463 |
|
|
// create unzipper istream |
464 |
|
|
zip_istream unzipper( istringstream_); |
465 |
|
|
|
466 |
|
|
// read and unzip |
467 |
|
|
unzipper>>f_r>>d_r>>ui_r>>ul_r>>us_r>>c_r>>dum_r; |
468 |
|
|
\endcode |
469 |
|
|
*/ |
470 |
|
|
template< |
471 |
|
|
typename Elem, |
472 |
|
|
typename Tr = std::char_traits<Elem>, |
473 |
|
|
typename ElemA = std::allocator<Elem>, |
474 |
|
|
typename ByteT = unsigned char, |
475 |
|
|
typename ByteAT = std::allocator<ByteT> |
476 |
|
|
> |
477 |
|
|
class basic_zip_istream : |
478 |
|
|
public basic_zip_istreambase<Elem,Tr,ElemA,ByteT,ByteAT>, |
479 |
|
|
public std::basic_istream<Elem,Tr> |
480 |
|
|
{ |
481 |
|
|
public: |
482 |
|
|
typedef basic_zip_istreambase< |
483 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT> zip_istreambase_type; |
484 |
|
|
typedef std::basic_istream<Elem,Tr> istream_type; |
485 |
|
|
typedef unsigned char byte_type; |
486 |
|
|
|
487 |
|
|
/** Construct a unzipper stream |
488 |
|
|
* |
489 |
|
|
* \param istream_ input buffer |
490 |
|
|
* \param window_size_ |
491 |
|
|
* \param read_buffer_size_ |
492 |
|
|
* \param input_buffer_size_ |
493 |
|
|
*/ |
494 |
|
|
basic_zip_istream( |
495 |
|
|
istream_reference istream_, |
496 |
|
|
size_t window_size_ = 15, |
497 |
|
|
size_t read_buffer_size_ = default_buffer_size, |
498 |
|
|
size_t input_buffer_size_ = default_buffer_size |
499 |
|
|
) |
500 |
|
|
: |
501 |
|
|
zip_istreambase_type(istream_,window_size_, read_buffer_size_, input_buffer_size_), |
502 |
|
|
istream_type(rdbuf()), |
503 |
|
|
m_is_gzip(false), |
504 |
|
|
m_gzip_crc(0), |
505 |
|
|
m_gzip_data_size(0) |
506 |
|
|
{ |
507 |
|
|
if (rdbuf()->get_zerr()==Z_OK) |
508 |
|
|
check_header(); |
509 |
|
|
}; |
510 |
|
|
|
511 |
|
|
/// returns true if it is a gzip file |
512 |
|
|
bool is_gzip() const { return m_is_gzip;}; |
513 |
|
|
/// reads the gzip header |
514 |
|
|
void read_footer(); |
515 |
|
|
/** return crc check result |
516 |
|
|
|
517 |
|
|
When you have finished reading the compressed data, call read_footer to read the uncompressed data crc. |
518 |
|
|
This method compares it to the crc of the uncompressed data. |
519 |
|
|
|
520 |
|
|
\return true if crc check is succesful |
521 |
|
|
*/ |
522 |
|
|
bool check_crc() const { return get_crc() == m_gzip_crc;}; |
523 |
|
|
/// return data size check |
524 |
|
|
bool check_data_size() const { return get_out_size() == m_gzip_data_size;}; |
525 |
|
|
|
526 |
|
|
/// return the crc value in the file |
527 |
|
|
long get_gzip_crc() const { return m_gzip_crc;}; |
528 |
|
|
/// return the data size in the file |
529 |
|
|
long get_gzip_data_size() const { return m_gzip_data_size;}; |
530 |
|
|
protected: |
531 |
|
|
static void read_long(istream_reference in_, unsigned long& x_); |
532 |
|
|
|
533 |
|
|
int check_header(); |
534 |
|
|
bool m_is_gzip; |
535 |
|
|
unsigned long m_gzip_crc; |
536 |
|
|
unsigned long m_gzip_data_size; |
537 |
|
|
}; |
538 |
|
|
|
539 |
|
|
/// A typedef for basic_zip_ostream<char> |
540 |
|
|
typedef basic_zip_ostream<char> zip_ostream; |
541 |
|
|
/// A typedef for basic_zip_ostream<wchar_t> |
542 |
|
|
typedef basic_zip_ostream<wchar_t> zip_wostream; |
543 |
|
|
/// A typedef for basic_zip_istream<char> |
544 |
|
|
typedef basic_zip_istream<char> zip_istream; |
545 |
|
|
/// A typedef for basic_zip_istream<wchart> |
546 |
|
|
typedef basic_zip_istream<wchar_t> zip_wistream; |
547 |
|
|
|
548 |
|
|
}; // zlib_sream |
549 |
|
|
|
550 |
|
|
|
551 |
|
|
|
552 |
|
|
namespace zlib_stream{ |
553 |
|
|
|
554 |
|
|
namespace detail{ |
555 |
|
|
const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ |
556 |
|
|
|
557 |
|
|
/* gzip flag byte */ |
558 |
|
|
const int gz_ascii_flag = 0x01; /* bit 0 set: file probably ascii text */ |
559 |
|
|
const int gz_head_crc = 0x02; /* bit 1 set: header CRC present */ |
560 |
|
|
const int gz_extra_field = 0x04; /* bit 2 set: extra field present */ |
561 |
|
|
const int gz_orig_name = 0x08; /* bit 3 set: original file name present */ |
562 |
|
|
const int gz_comment = 0x10; /* bit 4 set: file comment present */ |
563 |
|
|
const int gz_reserved = 0xE0; /* bits 5..7: reserved */ |
564 |
|
|
} |
565 |
|
|
|
566 |
|
|
template< |
567 |
|
|
typename Elem, |
568 |
|
|
typename Tr, |
569 |
|
|
typename ElemA, |
570 |
|
|
typename ByteT, |
571 |
|
|
typename ByteAT |
572 |
|
|
> |
573 |
|
|
basic_zip_streambuf< |
574 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
575 |
|
|
>::basic_zip_streambuf( |
576 |
|
|
ostream_reference ostream_, |
577 |
|
|
size_t level_, |
578 |
|
|
EStrategy strategy_, |
579 |
|
|
size_t window_size_, |
580 |
|
|
size_t memory_level_, |
581 |
|
|
size_t buffer_size_ |
582 |
|
|
) |
583 |
|
|
: |
584 |
|
|
m_ostream(ostream_), |
585 |
|
|
m_output_buffer(buffer_size_,0), |
586 |
|
|
m_buffer(buffer_size_,0), |
587 |
|
|
m_crc(0) |
588 |
|
|
{ |
589 |
|
|
m_zip_stream.zalloc=(alloc_func)0; |
590 |
|
|
m_zip_stream.zfree=(free_func)0; |
591 |
|
|
|
592 |
|
|
m_zip_stream.next_in=NULL; |
593 |
|
|
m_zip_stream.avail_in=0; |
594 |
|
|
m_zip_stream.avail_out=0; |
595 |
|
|
m_zip_stream.next_out=NULL; |
596 |
|
|
|
597 |
|
|
m_err=deflateInit2( |
598 |
|
|
&m_zip_stream, |
599 |
|
|
std::min( 9, static_cast<int>(level_)), |
600 |
|
|
Z_DEFLATED, |
601 |
|
|
- static_cast<int>(window_size_), // <-- changed |
602 |
|
|
std::min( 9, static_cast<int>(memory_level_) ), |
603 |
|
|
static_cast<int>(strategy_) |
604 |
|
|
); |
605 |
|
|
|
606 |
|
|
setp( &(m_buffer[0]), &(m_buffer[m_buffer.size()-1])); |
607 |
|
|
}; |
608 |
|
|
|
609 |
|
|
template< |
610 |
|
|
typename Elem, |
611 |
|
|
typename Tr, |
612 |
|
|
typename ElemA, |
613 |
|
|
typename ByteT, |
614 |
|
|
typename ByteAT |
615 |
|
|
> |
616 |
|
|
basic_zip_streambuf< |
617 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
618 |
|
|
>::~basic_zip_streambuf() |
619 |
|
|
{ |
620 |
|
|
flush(); |
621 |
|
|
m_ostream.flush(); |
622 |
|
|
m_err=deflateEnd(&m_zip_stream); |
623 |
|
|
}; |
624 |
|
|
|
625 |
|
|
template< |
626 |
|
|
typename Elem, |
627 |
|
|
typename Tr, |
628 |
|
|
typename ElemA, |
629 |
|
|
typename ByteT, |
630 |
|
|
typename ByteAT |
631 |
|
|
> |
632 |
|
|
int basic_zip_streambuf< |
633 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
634 |
|
|
>::sync () |
635 |
|
|
{ |
636 |
|
|
if ( pptr() && pptr() > pbase()) |
637 |
|
|
{ |
638 |
|
|
int c = overflow( EOF); |
639 |
|
|
|
640 |
|
|
if ( c == EOF) |
641 |
|
|
return -1; |
642 |
|
|
} |
643 |
|
|
|
644 |
|
|
return 0; |
645 |
|
|
} |
646 |
|
|
|
647 |
|
|
template< |
648 |
|
|
typename Elem, |
649 |
|
|
typename Tr, |
650 |
|
|
typename ElemA, |
651 |
|
|
typename ByteT, |
652 |
|
|
typename ByteAT |
653 |
|
|
> |
654 |
|
|
typename basic_zip_streambuf< |
655 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
656 |
|
|
>::int_type |
657 |
|
|
basic_zip_streambuf< |
658 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
659 |
|
|
>::overflow ( |
660 |
|
|
typename basic_zip_streambuf< |
661 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
662 |
|
|
>::int_type c |
663 |
|
|
) |
664 |
|
|
{ |
665 |
|
|
int w = static_cast<int>(pptr() - pbase()); |
666 |
|
|
if (c != EOF) { |
667 |
|
|
*pptr() = c; |
668 |
|
|
++w; |
669 |
|
|
} |
670 |
|
|
if ( zip_to_stream( pbase(), w)) { |
671 |
|
|
setp( pbase(), epptr() - 1); |
672 |
|
|
return c; |
673 |
|
|
} else |
674 |
|
|
return EOF; |
675 |
|
|
} |
676 |
|
|
|
677 |
|
|
template< |
678 |
|
|
typename Elem, |
679 |
|
|
typename Tr, |
680 |
|
|
typename ElemA, |
681 |
|
|
typename ByteT, |
682 |
|
|
typename ByteAT |
683 |
|
|
> |
684 |
|
|
bool basic_zip_streambuf< |
685 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
686 |
|
|
>::zip_to_stream( |
687 |
|
|
typename basic_zip_streambuf< |
688 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
689 |
|
|
>::char_type* buffer_, |
690 |
|
|
std::streamsize buffer_size_ |
691 |
|
|
) |
692 |
|
|
{ |
693 |
|
|
std::streamsize written_byte_size=0, total_written_byte_size = 0; |
694 |
|
|
|
695 |
|
|
m_zip_stream.next_in=(byte_buffer_type)buffer_; |
696 |
|
|
m_zip_stream.avail_in=static_cast<uInt>(buffer_size_*sizeof(char_type)); |
697 |
|
|
m_zip_stream.avail_out=static_cast<uInt>(m_output_buffer.size()); |
698 |
|
|
m_zip_stream.next_out=&(m_output_buffer[0]); |
699 |
|
|
size_t remainder=0; |
700 |
|
|
|
701 |
|
|
// updating crc |
702 |
|
|
m_crc = crc32( |
703 |
|
|
m_crc, |
704 |
|
|
m_zip_stream.next_in, |
705 |
|
|
m_zip_stream.avail_in |
706 |
|
|
); |
707 |
|
|
|
708 |
|
|
do |
709 |
|
|
{ |
710 |
|
|
m_err = deflate(&m_zip_stream, 0); |
711 |
|
|
|
712 |
|
|
if (m_err == Z_OK || m_err == Z_STREAM_END) |
713 |
|
|
{ |
714 |
|
|
written_byte_size= |
715 |
|
|
static_cast<std::streamsize>(m_output_buffer.size()) |
716 |
|
|
- m_zip_stream.avail_out; |
717 |
|
|
total_written_byte_size+=written_byte_size; |
718 |
|
|
// ouput buffer is full, dumping to ostream |
719 |
|
|
m_ostream.write( |
720 |
|
|
(const char_type*) &(m_output_buffer[0]), |
721 |
|
|
static_cast<std::streamsize>( |
722 |
|
|
written_byte_size/sizeof(char_type) |
723 |
|
|
) |
724 |
|
|
); |
725 |
|
|
|
726 |
|
|
// checking if some bytes were not written. |
727 |
|
|
if ( (remainder = written_byte_size%sizeof(char_type))!=0) |
728 |
|
|
{ |
729 |
|
|
// copy to the beginning of the stream |
730 |
|
|
memcpy( |
731 |
|
|
&(m_output_buffer[0]), |
732 |
|
|
&(m_output_buffer[written_byte_size-remainder]), |
733 |
|
|
remainder); |
734 |
|
|
|
735 |
|
|
} |
736 |
|
|
|
737 |
|
|
m_zip_stream.avail_out= |
738 |
|
|
static_cast<uInt>(m_output_buffer.size()-remainder); |
739 |
|
|
m_zip_stream.next_out=&m_output_buffer[remainder]; |
740 |
|
|
} |
741 |
|
|
} |
742 |
|
|
while (m_zip_stream.avail_in != 0 && m_err == Z_OK); |
743 |
|
|
|
744 |
|
|
return m_err == Z_OK; |
745 |
|
|
}; |
746 |
|
|
|
747 |
|
|
template< |
748 |
|
|
typename Elem, |
749 |
|
|
typename Tr, |
750 |
|
|
typename ElemA, |
751 |
|
|
typename ByteT, |
752 |
|
|
typename ByteAT |
753 |
|
|
> |
754 |
|
|
std::streamsize basic_zip_streambuf< |
755 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
756 |
|
|
>::flush() |
757 |
|
|
{ |
758 |
|
|
std::streamsize written_byte_size=0, total_written_byte_size=0; |
759 |
|
|
|
760 |
|
|
size_t remainder=0; |
761 |
|
|
|
762 |
|
|
// updating crc |
763 |
|
|
m_crc = crc32( |
764 |
|
|
m_crc, |
765 |
|
|
m_zip_stream.next_in, |
766 |
|
|
m_zip_stream.avail_in |
767 |
|
|
); |
768 |
|
|
|
769 |
|
|
do |
770 |
|
|
{ |
771 |
|
|
m_err = deflate(&m_zip_stream, Z_FINISH); |
772 |
|
|
if (m_err == Z_OK || m_err == Z_STREAM_END) |
773 |
|
|
{ |
774 |
|
|
written_byte_size= |
775 |
|
|
static_cast<std::streamsize>(m_output_buffer.size()) |
776 |
|
|
- m_zip_stream.avail_out; |
777 |
|
|
total_written_byte_size+=written_byte_size; |
778 |
|
|
// ouput buffer is full, dumping to ostream |
779 |
|
|
m_ostream.write( |
780 |
|
|
(const char_type*) &(m_output_buffer[0]), |
781 |
|
|
static_cast<std::streamsize>( |
782 |
|
|
written_byte_size/sizeof(char_type)*sizeof(byte_type) |
783 |
|
|
) |
784 |
|
|
); |
785 |
|
|
|
786 |
|
|
// checking if some bytes were not written. |
787 |
|
|
if ( (remainder = written_byte_size%sizeof(char_type))!=0) |
788 |
|
|
{ |
789 |
|
|
// copy to the beginning of the stream |
790 |
|
|
memcpy( |
791 |
|
|
&(m_output_buffer[0]), |
792 |
|
|
&(m_output_buffer[written_byte_size-remainder]), |
793 |
|
|
remainder); |
794 |
|
|
|
795 |
|
|
} |
796 |
|
|
|
797 |
|
|
m_zip_stream.avail_out=static_cast<uInt>(m_output_buffer.size()-remainder); |
798 |
|
|
m_zip_stream.next_out=&m_output_buffer[remainder]; |
799 |
|
|
} |
800 |
|
|
} while (m_err == Z_OK); |
801 |
|
|
|
802 |
|
|
m_ostream.flush(); |
803 |
|
|
|
804 |
|
|
return total_written_byte_size; |
805 |
|
|
}; |
806 |
|
|
|
807 |
|
|
|
808 |
|
|
template< |
809 |
|
|
typename Elem, |
810 |
|
|
typename Tr, |
811 |
|
|
typename ElemA, |
812 |
|
|
typename ByteT, |
813 |
|
|
typename ByteAT |
814 |
|
|
> |
815 |
|
|
basic_unzip_streambuf< |
816 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
817 |
|
|
>::basic_unzip_streambuf( |
818 |
|
|
istream_reference istream_, |
819 |
|
|
size_t window_size_, |
820 |
|
|
size_t read_buffer_size_, |
821 |
|
|
size_t input_buffer_size_ |
822 |
|
|
) |
823 |
|
|
: |
824 |
|
|
m_istream(istream_), |
825 |
|
|
m_input_buffer(input_buffer_size_), |
826 |
|
|
m_buffer(read_buffer_size_), |
827 |
|
|
m_crc(0) |
828 |
|
|
{ |
829 |
|
|
// setting zalloc, zfree and opaque |
830 |
|
|
m_zip_stream.zalloc=(alloc_func)0; |
831 |
|
|
m_zip_stream.zfree=(free_func)0; |
832 |
|
|
|
833 |
|
|
m_zip_stream.next_in=NULL; |
834 |
|
|
m_zip_stream.avail_in=0; |
835 |
|
|
m_zip_stream.avail_out=0; |
836 |
|
|
m_zip_stream.next_out=NULL; |
837 |
|
|
|
838 |
|
|
m_err=inflateInit2( |
839 |
|
|
&m_zip_stream, |
840 |
|
|
-static_cast<int>(window_size_) |
841 |
|
|
); |
842 |
|
|
|
843 |
|
|
setg( &(m_buffer[0])+4, // beginning of putback area |
844 |
|
|
&(m_buffer[0])+4, // read position |
845 |
|
|
&(m_buffer[0])+4); // end position |
846 |
|
|
}; |
847 |
|
|
|
848 |
|
|
template< |
849 |
|
|
typename Elem, |
850 |
|
|
typename Tr, |
851 |
|
|
typename ElemA, |
852 |
|
|
typename ByteT, |
853 |
|
|
typename ByteAT |
854 |
|
|
> |
855 |
|
|
size_t basic_unzip_streambuf< |
856 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
857 |
|
|
>::fill_input_buffer() |
858 |
|
|
{ |
859 |
|
|
m_zip_stream.next_in=&(m_input_buffer[0]); |
860 |
|
|
m_istream.read( |
861 |
|
|
(char_type*)(&(m_input_buffer[0])), |
862 |
|
|
static_cast<std::streamsize>(m_input_buffer.size()/sizeof(char_type)) |
863 |
|
|
); |
864 |
|
|
return m_zip_stream.avail_in=m_istream.gcount()*sizeof(char_type); |
865 |
|
|
} |
866 |
|
|
|
867 |
|
|
|
868 |
|
|
template< |
869 |
|
|
typename Elem, |
870 |
|
|
typename Tr, |
871 |
|
|
typename ElemA, |
872 |
|
|
typename ByteT, |
873 |
|
|
typename ByteAT |
874 |
|
|
> |
875 |
|
|
basic_unzip_streambuf< |
876 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
877 |
|
|
>::~basic_unzip_streambuf() |
878 |
|
|
{ |
879 |
|
|
inflateEnd(&m_zip_stream); |
880 |
|
|
}; |
881 |
|
|
|
882 |
|
|
template< |
883 |
|
|
typename Elem, |
884 |
|
|
typename Tr, |
885 |
|
|
typename ElemA, |
886 |
|
|
typename ByteT, |
887 |
|
|
typename ByteAT |
888 |
|
|
> |
889 |
|
|
typename basic_unzip_streambuf< |
890 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
891 |
|
|
>::int_type |
892 |
|
|
basic_unzip_streambuf< |
893 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
894 |
|
|
>::underflow() |
895 |
|
|
{ |
896 |
|
|
if ( gptr() && ( gptr() < egptr())) |
897 |
|
|
return * reinterpret_cast<unsigned char *>( gptr()); |
898 |
|
|
|
899 |
|
|
int n_putback = static_cast<int>(gptr() - eback()); |
900 |
|
|
if ( n_putback > 4) |
901 |
|
|
n_putback = 4; |
902 |
|
|
memcpy( |
903 |
|
|
&(m_buffer[0]) + (4 - n_putback), |
904 |
|
|
gptr() - n_putback, |
905 |
|
|
n_putback*sizeof(char_type) |
906 |
|
|
); |
907 |
|
|
|
908 |
|
|
int num = unzip_from_stream( |
909 |
|
|
&(m_buffer[0])+4, |
910 |
|
|
static_cast<std::streamsize>((m_buffer.size()-4)*sizeof(char_type)) |
911 |
|
|
); |
912 |
|
|
if (num <= 0) // ERROR or EOF |
913 |
|
|
return EOF; |
914 |
|
|
|
915 |
|
|
// reset buffer pointers |
916 |
|
|
setg( &(m_buffer[0]) + (4 - n_putback), // beginning of putback area |
917 |
|
|
&(m_buffer[0]) + 4, // read position |
918 |
|
|
&(m_buffer[0]) + 4 + num); // end of buffer |
919 |
|
|
|
920 |
|
|
// return next character |
921 |
|
|
return* reinterpret_cast<unsigned char *>( gptr()); |
922 |
|
|
} |
923 |
|
|
|
924 |
|
|
template< |
925 |
|
|
typename Elem, |
926 |
|
|
typename Tr, |
927 |
|
|
typename ElemA, |
928 |
|
|
typename ByteT, |
929 |
|
|
typename ByteAT |
930 |
|
|
> |
931 |
|
|
std::streamsize basic_unzip_streambuf< |
932 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
933 |
|
|
>::unzip_from_stream( |
934 |
|
|
char_type* buffer_, |
935 |
|
|
std::streamsize buffer_size_ |
936 |
|
|
) |
937 |
|
|
{ |
938 |
|
|
m_zip_stream.next_out=(byte_buffer_type)buffer_; |
939 |
|
|
m_zip_stream.avail_out=static_cast<uInt>(buffer_size_*sizeof(char_type)); |
940 |
|
|
size_t count =m_zip_stream.avail_in; |
941 |
|
|
|
942 |
|
|
do |
943 |
|
|
{ |
944 |
|
|
if (m_zip_stream.avail_in==0) |
945 |
|
|
count=fill_input_buffer(); |
946 |
|
|
|
947 |
|
|
if (m_zip_stream.avail_in) |
948 |
|
|
{ |
949 |
|
|
m_err = inflate( &m_zip_stream, Z_SYNC_FLUSH ); |
950 |
|
|
} |
951 |
|
|
} while (m_err==Z_OK && m_zip_stream.avail_out != 0 && count != 0); |
952 |
|
|
|
953 |
|
|
// updating crc |
954 |
|
|
m_crc = crc32( |
955 |
|
|
m_crc, |
956 |
|
|
(byte_buffer_type)buffer_, |
957 |
|
|
buffer_size_ - m_zip_stream.avail_out/sizeof(char_type) |
958 |
|
|
); |
959 |
|
|
std::streamsize n_read = buffer_size_ - m_zip_stream.avail_out/sizeof(char_type); |
960 |
|
|
|
961 |
|
|
// check if it is the end |
962 |
|
|
if (m_err==Z_STREAM_END) |
963 |
|
|
put_back_from_zip_stream(); |
964 |
|
|
|
965 |
|
|
return n_read; |
966 |
|
|
} |
967 |
|
|
|
968 |
|
|
template< |
969 |
|
|
typename Elem, |
970 |
|
|
typename Tr, |
971 |
|
|
typename ElemA, |
972 |
|
|
typename ByteT, |
973 |
|
|
typename ByteAT |
974 |
|
|
> |
975 |
|
|
void basic_unzip_streambuf< |
976 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
977 |
|
|
>::put_back_from_zip_stream() |
978 |
|
|
{ |
979 |
|
|
if (m_zip_stream.avail_in==0) |
980 |
|
|
return; |
981 |
|
|
|
982 |
|
|
m_istream.clear( ios::goodbit ); |
983 |
|
|
m_istream.seekg( |
984 |
|
|
-static_cast<int>(m_zip_stream.avail_in), |
985 |
|
|
ios_base::cur |
986 |
|
|
); |
987 |
|
|
|
988 |
|
|
m_zip_stream.avail_in=0; |
989 |
|
|
}; |
990 |
|
|
|
991 |
|
|
template< |
992 |
|
|
typename Elem, |
993 |
|
|
typename Tr, |
994 |
|
|
typename ElemA, |
995 |
|
|
typename ByteT, |
996 |
|
|
typename ByteAT |
997 |
|
|
> |
998 |
|
|
int basic_zip_istream< |
999 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1000 |
|
|
>::check_header() |
1001 |
|
|
{ |
1002 |
|
|
int method; /* method byte */ |
1003 |
|
|
int flags; /* flags byte */ |
1004 |
|
|
uInt len; |
1005 |
|
|
int c; |
1006 |
|
|
int err=0; |
1007 |
|
|
z_stream& zip_stream = rdbuf()->get_zip_stream(); |
1008 |
|
|
|
1009 |
|
|
/* Check the gzip magic header */ |
1010 |
|
|
for (len = 0; len < 2; len++) |
1011 |
|
|
{ |
1012 |
|
|
c = (int)rdbuf()->get_istream().get(); |
1013 |
|
|
if (c != detail::gz_magic[len]) |
1014 |
|
|
{ |
1015 |
|
|
if (len != 0) |
1016 |
|
|
rdbuf()->get_istream().unget(); |
1017 |
|
|
if (c!= EOF) |
1018 |
|
|
{ |
1019 |
|
|
rdbuf()->get_istream().unget(); |
1020 |
|
|
} |
1021 |
|
|
|
1022 |
|
|
err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END; |
1023 |
|
|
m_is_gzip = false; |
1024 |
|
|
return err; |
1025 |
|
|
} |
1026 |
|
|
} |
1027 |
|
|
|
1028 |
|
|
m_is_gzip = true; |
1029 |
|
|
method = (int)rdbuf()->get_istream().get(); |
1030 |
|
|
flags = (int)rdbuf()->get_istream().get(); |
1031 |
|
|
if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0) |
1032 |
|
|
{ |
1033 |
|
|
err = Z_DATA_ERROR; |
1034 |
|
|
return err; |
1035 |
|
|
} |
1036 |
|
|
|
1037 |
|
|
/* Discard time, xflags and OS code: */ |
1038 |
|
|
for (len = 0; len < 6; len++) |
1039 |
|
|
rdbuf()->get_istream().get(); |
1040 |
|
|
|
1041 |
|
|
if ((flags & detail::gz_extra_field) != 0) |
1042 |
|
|
{ |
1043 |
|
|
/* skip the extra field */ |
1044 |
|
|
len = (uInt)rdbuf()->get_istream().get(); |
1045 |
|
|
len += ((uInt)rdbuf()->get_istream().get())<<8; |
1046 |
|
|
/* len is garbage if EOF but the loop below will quit anyway */ |
1047 |
|
|
while (len-- != 0 && rdbuf()->get_istream().get() != EOF) ; |
1048 |
|
|
} |
1049 |
|
|
if ((flags & detail::gz_orig_name) != 0) |
1050 |
|
|
{ |
1051 |
|
|
/* skip the original file name */ |
1052 |
|
|
while ((c = rdbuf()->get_istream().get()) != 0 && c != EOF) ; |
1053 |
|
|
} |
1054 |
|
|
if ((flags & detail::gz_comment) != 0) |
1055 |
|
|
{ |
1056 |
|
|
/* skip the .gz file comment */ |
1057 |
|
|
while ((c = rdbuf()->get_istream().get()) != 0 && c != EOF) ; |
1058 |
|
|
} |
1059 |
|
|
if ((flags & detail::gz_head_crc) != 0) |
1060 |
|
|
{ /* skip the header crc */ |
1061 |
|
|
for (len = 0; len < 2; len++) |
1062 |
|
|
rdbuf()->get_istream().get(); |
1063 |
|
|
} |
1064 |
|
|
err = rdbuf()->get_istream().eof() ? Z_DATA_ERROR : Z_OK; |
1065 |
|
|
|
1066 |
|
|
return err; |
1067 |
|
|
} |
1068 |
|
|
|
1069 |
|
|
template< |
1070 |
|
|
typename Elem, |
1071 |
|
|
typename Tr, |
1072 |
|
|
typename ElemA, |
1073 |
|
|
typename ByteT, |
1074 |
|
|
typename ByteAT |
1075 |
|
|
> |
1076 |
|
|
void basic_zip_istream< |
1077 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1078 |
|
|
>::read_footer() |
1079 |
|
|
{ |
1080 |
|
|
if (m_is_gzip) |
1081 |
|
|
{ |
1082 |
|
|
read_long( rdbuf()->get_istream(), m_gzip_crc ); |
1083 |
|
|
read_long( rdbuf()->get_istream(), m_gzip_data_size ); |
1084 |
|
|
} |
1085 |
|
|
} |
1086 |
|
|
|
1087 |
|
|
template< |
1088 |
|
|
typename Elem, |
1089 |
|
|
typename Tr, |
1090 |
|
|
typename ElemA, |
1091 |
|
|
typename ByteT, |
1092 |
|
|
typename ByteAT |
1093 |
|
|
> |
1094 |
|
|
void basic_zip_ostream< |
1095 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1096 |
|
|
>::put_long( |
1097 |
|
|
typename basic_zip_ostream< |
1098 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1099 |
|
|
>::ostream_reference out_, |
1100 |
|
|
unsigned long x_ |
1101 |
|
|
) |
1102 |
|
|
{ |
1103 |
|
|
static const int size_ul = sizeof(unsigned long); |
1104 |
|
|
static const int size_c = sizeof(char_type); |
1105 |
|
|
static const int n_end = size_ul/size_c; |
1106 |
|
|
out_.write(reinterpret_cast<char_type const*>(&x_), n_end); |
1107 |
|
|
} |
1108 |
|
|
|
1109 |
|
|
template< |
1110 |
|
|
typename Elem, |
1111 |
|
|
typename Tr, |
1112 |
|
|
typename ElemA, |
1113 |
|
|
typename ByteT, |
1114 |
|
|
typename ByteAT |
1115 |
|
|
> |
1116 |
|
|
void basic_zip_istream< |
1117 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1118 |
|
|
>::read_long( |
1119 |
|
|
istream_reference in_, |
1120 |
|
|
unsigned long& x_ |
1121 |
|
|
) |
1122 |
|
|
{ |
1123 |
|
|
static const int size_ul = sizeof(unsigned long); |
1124 |
|
|
static const int size_c = sizeof(char_type); |
1125 |
|
|
static const int n_end = size_ul/size_c; |
1126 |
|
|
in_.read(reinterpret_cast<char*>(&x_),n_end); |
1127 |
|
|
} |
1128 |
|
|
|
1129 |
|
|
template< |
1130 |
|
|
typename Elem, |
1131 |
|
|
typename Tr, |
1132 |
|
|
typename ElemA, |
1133 |
|
|
typename ByteT, |
1134 |
|
|
typename ByteAT |
1135 |
|
|
> |
1136 |
|
|
void basic_zip_ostream< |
1137 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1138 |
|
|
>::add_header() |
1139 |
|
|
{ |
1140 |
|
|
char_type zero=0; |
1141 |
|
|
|
1142 |
|
|
rdbuf()->get_ostream() |
1143 |
|
|
.put(static_cast<char_type>(detail::gz_magic[0])) |
1144 |
|
|
.put(static_cast<char_type>(detail::gz_magic[1])) |
1145 |
|
|
.put(static_cast<char_type>(Z_DEFLATED)) |
1146 |
|
|
.put(zero) //flags |
1147 |
|
|
.put(zero).put(zero).put(zero).put(zero) // time |
1148 |
|
|
.put(zero) //xflags |
1149 |
|
|
.put(static_cast<char_type>(OS_CODE)); |
1150 |
|
|
} |
1151 |
|
|
|
1152 |
|
|
template< |
1153 |
|
|
typename Elem, |
1154 |
|
|
typename Tr, |
1155 |
|
|
typename ElemA, |
1156 |
|
|
typename ByteT, |
1157 |
|
|
typename ByteAT |
1158 |
|
|
> |
1159 |
|
|
void basic_zip_ostream< |
1160 |
|
|
Elem,Tr,ElemA,ByteT,ByteAT |
1161 |
|
|
>::add_footer() |
1162 |
|
|
{ |
1163 |
|
|
put_long( rdbuf()->get_ostream(), rdbuf()->get_crc() ); |
1164 |
|
|
put_long( rdbuf()->get_ostream(), rdbuf()->get_in_size() ); |
1165 |
|
|
}; |
1166 |
|
|
|
1167 |
|
|
}; // zlib_sream |
1168 |
|
|
|
1169 |
|
|
|
1170 |
|
|
#endif |
1171 |
|
|
|