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

File Contents

# User Rev Content
1 tim 2312 /*
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 *