1 |
/* |
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 |
|