ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/io/zipstream.hpp
Revision: 613
Committed: Tue Sep 20 15:41:39 2005 UTC (19 years, 7 months ago) by tim
File size: 29459 byte(s)
Log Message:
adding zipstream.hpp

File Contents

# Content
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

Properties

Name Value
svn:executable *