4 //*****************************************************************************
5 // template class basic_zip_streambuf
6 //*****************************************************************************
8 //-----------------------------------------------------------------------------
10 //-----------------------------------------------------------------------------
12 /* Construct a zip stream
13 * More info on the following parameters can be found in the zlib documentation.
16 #ifdef OSG_DEBUG_OLD_C_CASTS
17 # if ZLIB_VERNUM >= 0x1270
20 # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
21 deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
22 (strategy), ZLIB_VERSION, int(sizeof(z_stream)))
28 template <class charT, class traits> inline
29 basic_zip_streambuf<charT,
30 traits>::basic_zip_streambuf(
31 ostream_reference ostream,
36 size_t buffer_size ) :
40 _output_buffer(buffer_size, 0),
41 _buffer (buffer_size, 0),
44 _zip_stream.zalloc = NULL;
45 _zip_stream.zfree = NULL;
47 _zip_stream.next_in = NULL;
48 _zip_stream.avail_in = 0;
49 _zip_stream.avail_out = 0;
50 _zip_stream.next_out = NULL;
58 _err=deflateInit2(&_zip_stream,
63 static_cast<int>(strategy));
65 this->setp(&(_buffer[0]), &(_buffer[_buffer.size() - 1]));
68 #ifdef OSG_DEBUG_OLD_C_CASTS
69 # if ZLIB_VERNUM >= 0x1270
72 # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
73 deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
74 (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
81 template <class charT, class traits> inline
82 basic_zip_streambuf<charT, traits>::~basic_zip_streambuf(void)
86 _err=deflateEnd(&_zip_stream);
89 /* Do the synchronization
93 template <class charT, class traits> inline
94 int basic_zip_streambuf<charT, traits>::sync(void)
96 if(this->pptr() && this->pptr() > this->pbase())
98 /*int c =*/ overflow(EOF);
100 // ACHTUNG wenn das drin ist hoert er nach dem ersten endl auf!
112 * document correctly!
114 template <class charT, class traits> inline
115 typename basic_zip_streambuf<charT, traits>::int_type
116 basic_zip_streambuf<charT, traits>::overflow(int_type c)
118 int w = static_cast<int>(this->pptr() - this->pbase());
124 if (zip_to_stream(this->pbase(), w))
126 this->setp(this->pbase(), this->epptr() - 1);
135 /* flushes the zip buffer and output buffer.
137 * This method should be called at the end of the compression. Calling flush
138 * multiple times, will lower the compression ratio.
140 template <class charT, class traits> inline
141 std::streamsize basic_zip_streambuf<charT, traits>::flush(void)
143 std::streamsize written_byte_size = 0, total_written_byte_size = 0;
145 size_t remainder = 0;
148 _crc = crc32(_crc, _zip_stream.next_in,
149 _zip_stream.avail_in);
153 _err = deflate(&_zip_stream, Z_FINISH);
154 if(_err == Z_OK || _err == Z_STREAM_END)
156 written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
157 total_written_byte_size += written_byte_size;
158 // ouput buffer is full, dumping to ostream
159 _ostream.write( reinterpret_cast<const char_type*>(&(_output_buffer[0])),
160 static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
162 // checking if some bytes were not written.
163 if((remainder = written_byte_size%sizeof(char_type)) != 0)
165 // copy to the beginning of the stream
166 memcpy(&(_output_buffer[0]),
167 &(_output_buffer[written_byte_size-remainder]), remainder);
171 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
172 _zip_stream.next_out = &_output_buffer[remainder];
179 return total_written_byte_size;
182 /* returns a reference to the output stream
184 template <class charT, class traits> inline
185 typename basic_zip_streambuf<charT, traits>::ostream_reference
186 basic_zip_streambuf<charT, traits>::get_ostream(void) const
191 /* returns the latest zlib error status
193 template <class charT, class traits> inline
194 int basic_zip_streambuf<charT, traits>::get_zerr(void) const
199 /* returns the crc of the input data compressed so far.
201 template <class charT, class traits> inline
203 basic_zip_streambuf<charT, traits>:: get_crc(void) const
208 /* returns the size (bytes) of the input data compressed so far.
210 template <class charT, class traits> inline
212 basic_zip_streambuf<charT, traits>::get_in_size(void) const
214 return _zip_stream.total_in;
217 /* returns the size (bytes) of the compressed data so far.
219 template <class charT, class traits> inline
221 basic_zip_streambuf<charT, traits>::get_out_size(void) const
223 return _zip_stream.total_out;
226 //-----------------------------------------------------------------------------
228 //-----------------------------------------------------------------------------
234 template <class charT, class traits> inline
235 bool basic_zip_streambuf<charT, traits>::zip_to_stream(
237 std::streamsize buffer_size)
239 std::streamsize written_byte_size = 0, total_written_byte_size = 0;
241 _zip_stream.next_in = reinterpret_cast<byte_buffer_type>(buffer);
242 _zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
243 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
244 _zip_stream.next_out = &_output_buffer[0];
245 size_t remainder = 0;
248 _crc = crc32(_crc, _zip_stream.next_in,
249 _zip_stream.avail_in);
253 _err = deflate(&_zip_stream, 0);
255 if (_err == Z_OK || _err == Z_STREAM_END)
257 written_byte_size= static_cast<std::streamsize>(_output_buffer.size()) -
258 _zip_stream.avail_out;
259 total_written_byte_size += written_byte_size;
260 // ouput buffer is full, dumping to ostream
262 _ostream.write(reinterpret_cast<const char_type*>(&_output_buffer[0]),
263 static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
265 // checking if some bytes were not written.
266 if((remainder = written_byte_size % sizeof(char_type)) != 0)
268 // copy to the beginning of the stream
269 memcpy(&_output_buffer[0],
270 &_output_buffer[written_byte_size-remainder],
274 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
275 _zip_stream.next_out = &_output_buffer[remainder];
278 while(_zip_stream.avail_in != 0 && _err == Z_OK);
289 //*****************************************************************************
290 // template class basic_unzip_streambuf
291 //*****************************************************************************
293 //-----------------------------------------------------------------------------
295 //-----------------------------------------------------------------------------
300 #ifdef OSG_DEBUG_OLD_C_CASTS
301 # if ZLIB_VERNUM >= 0x1270
304 # define inflateInit2(strm, windowBits) \
305 inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
306 int(sizeof(z_stream)))
312 template <class charT, class traits> inline
313 basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(
314 istream_reference istream,
316 size_t read_buffer_size,
317 size_t input_buffer_size) :
319 _input_buffer(input_buffer_size),
320 _buffer (read_buffer_size ),
321 _streamType (UNKNOWN_ST ),
327 // setting zalloc, zfree and opaque
328 _zip_stream.zalloc = NULL;
329 _zip_stream.zfree = NULL;
331 _zip_stream.next_in = NULL;
332 _zip_stream.avail_in = 0;
333 _zip_stream.avail_out = 0;
334 _zip_stream.next_out = NULL;
336 _err = inflateInit2(&_zip_stream, window_size);
338 this->setg(&_buffer[0] + 4, // beginning of putback area
339 &_buffer[0] + 4, // read position
340 &_buffer[0] + 4); // end position
343 #ifdef OSG_DEBUG_OLD_C_CASTS
344 # if ZLIB_VERNUM >= 0x1270
347 # define inflateInit2(strm, windowBits) \
348 inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
349 (int)sizeof(z_stream))
358 template <class charT, class traits> inline
359 basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
361 inflateEnd(&_zip_stream);
368 template <class charT, class traits> inline
369 typename basic_unzip_streambuf<charT, traits>::int_type
370 basic_unzip_streambuf<charT, traits>::underflow(void)
372 if(this->gptr() && ( this->gptr() < this->egptr()))
373 return * reinterpret_cast<unsigned char *>(this->gptr());
375 int n_putback = static_cast<int>(this->gptr() - this->eback());
379 memcpy(&_buffer[0] + (4 - n_putback),
380 this->gptr() - n_putback,
381 n_putback * sizeof(char_type));
384 unzip_from_stream(&_buffer[0] + 4,
385 static_cast<std::streamsize>((_buffer.size() - 4) *
388 if(num <= 0) // ERROR or EOF
391 // reset buffer pointers
392 this->setg(&_buffer[0] + (4 - n_putback), // beginning of putback area
393 &_buffer[0] + 4, // read position
394 &_buffer[0] + 4 + num); // end of buffer
396 // return next character
397 return * reinterpret_cast<unsigned char *>(this->gptr());
400 /* returns the compressed input istream
402 template <class charT, class traits> inline
403 typename basic_unzip_streambuf<charT, traits>::istream_reference
404 basic_unzip_streambuf<charT, traits>::get_istream(void)
409 /* returns the zlib stream structure
411 template <class charT, class traits> inline
413 basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
418 /* returns the latest zlib error state
420 template <class charT, class traits> inline
422 basic_unzip_streambuf<charT, traits>::get_zerr(void) const
427 /* returns the crc of the uncompressed data so far
429 template <class charT, class traits> inline
431 basic_unzip_streambuf<charT, traits>::get_crc(void) const
436 /* returns the number of uncompressed bytes
438 template <class charT, class traits> inline
440 basic_unzip_streambuf<charT, traits>::get_out_size(void) const
442 return _zip_stream.total_out;
445 /* returns the number of read compressed bytes
447 template <class charT, class traits> inline
449 basic_unzip_streambuf<charT, traits>::get_in_size(void) const
451 return _zip_stream.total_in;
455 //-----------------------------------------------------------------------------
457 //-----------------------------------------------------------------------------
461 template <class charT, class traits> inline
463 basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
465 if(_zip_stream.avail_in == 0)
468 _istream.clear(std::ios::goodbit);
469 _istream.seekg(-intf(_zip_stream.avail_in),
472 _zip_stream.avail_in = 0;
477 template <class charT, class traits> inline
479 basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
480 std::streamsize buffer_size)
482 _zip_stream.next_out =
483 reinterpret_cast<byte_buffer_type>(buffer);
484 _zip_stream.avail_out =
485 static_cast<uInt>(buffer_size * sizeof(char_type));
486 size_t count = _zip_stream.avail_in;
490 if(_zip_stream.avail_in == 0)
491 count=fill_input_buffer();
493 if(_zip_stream.avail_in)
495 switch (_streamType) {
497 _err = inflate(&_zip_stream, Z_SYNC_FLUSH);
500 if (_zip_stream.avail_out < count)
501 count = _zip_stream.avail_out;
502 memcpy ( _zip_stream.next_out, _zip_stream.next_in, count );
503 _zip_stream.avail_in -= count;
504 _zip_stream.avail_out -= count;
505 _zip_stream.next_in += count;
506 _zip_stream.next_out += count;
509 FWARNING (("Unknown _streamType: %d\n", _streamType ));
514 while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
517 _crc = crc32(_crc, reinterpret_cast<byte_buffer_type>(buffer),
518 buffer_size - _zip_stream.avail_out / sizeof(char_type));
520 std::streamsize n_read =
521 buffer_size - _zip_stream.avail_out / sizeof(char_type);
523 // check if it is the end
524 if (_err == Z_STREAM_END)
525 put_back_from_zip_stream();
533 template <class charT, class traits> inline
535 basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
537 _zip_stream.next_in = &_input_buffer[0];
538 _istream.read(reinterpret_cast<char_type*>(&_input_buffer[0]),
539 static_cast<std::streamsize>(_input_buffer.size() /
542 return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
551 //*****************************************************************************
552 // template class basic_zip_ostream
553 //*****************************************************************************
555 //-----------------------------------------------------------------------------
557 //-----------------------------------------------------------------------------
561 template <class charT, class traits> inline
562 basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
568 size_t buffer_size) :
569 basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
570 memory_level, buffer_size),
571 std::basic_ostream<charT, traits>(this),
581 template <class charT, class traits> inline
582 basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
588 /* returns true if it is a gzip
590 template <class charT, class traits> inline
591 bool basic_zip_ostream<charT, traits>::is_gzip(void) const
596 /* flush inner buffer and zipper buffer
599 template <class charT, class traits> inline
600 basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
602 std::basic_ostream<charT, traits>::flush();
603 basic_zip_streambuf<charT, traits>::flush();
607 template <class charT, class traits> inline
608 void basic_zip_ostream<charT, traits>::finished(void)
617 //-----------------------------------------------------------------------------
619 //-----------------------------------------------------------------------------
624 template <class charT, class traits> inline
625 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
629 this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
630 << static_cast<char_type>(detail::gz_magic[1])
631 << static_cast<char_type>(Z_DEFLATED)
633 << zero<<zero<<zero<<zero // time
635 << static_cast<char_type>(OS_CODE);
643 template <class charT, class traits> inline
644 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
651 _added_footer = true;
653 // Writes crc and length in LSB order to the stream.
654 unsigned long crc = this->get_crc();
657 this->get_ostream().put(int(crc & 0xff));
661 unsigned long length = this->get_in_size();
664 this->get_ostream().put(int(length & 0xff));
676 //*****************************************************************************
677 // template class basic_zip_istream
678 //*****************************************************************************
680 //-----------------------------------------------------------------------------
682 //-----------------------------------------------------------------------------
686 template <class charT, class traits> inline
687 basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
689 size_t read_buffer_size,
690 size_t input_buffer_size)
691 : basic_unzip_streambuf<charT, traits>(istream, window_size,
692 read_buffer_size, input_buffer_size),
693 std::basic_istream<charT, traits>(this),
698 if(this->get_zerr() == Z_OK)
702 /* returns true if it is a gzip file
704 template <class charT, class traits> inline
706 basic_zip_istream<charT, traits>::is_gzip(void) const
711 /* return crc check result
713 * This must be called after the reading of compressed data is finished! This
714 * method compares it to the crc of the uncompressed data.
716 * \return true if crc check is succesful
718 template <class charT, class traits> inline
720 basic_zip_istream<charT, traits>::check_crc(void)
723 return this->get_crc() == static_cast<unsigned long>(_gzip_crc);
726 /* return data size check
728 template <class charT, class traits> inline
730 basic_zip_istream<charT, traits>::check_data_size(void) const
732 return this->get_out_size() == _gzip_data_size;
735 /* return the crc value in the file
737 template <class charT, class traits> inline
739 basic_zip_istream<charT, traits>::get_gzip_crc(void) const
744 /* return the data size in the file
746 template <class charT, class traits> inline
748 basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
750 return _gzip_data_size;
753 //-----------------------------------------------------------------------------
755 //-----------------------------------------------------------------------------
760 template <class charT, class traits> inline
762 basic_zip_istream<charT, traits>::check_header(void)
764 int method; /* method byte */
765 int localFlags; /* flags byte */
769 z_stream &zip_stream = this->get_zip_stream();
771 /* Check the gzip magic header */
772 zip_stream.next_in = &this->_input_buffer[0];
773 this->get_istream().read( reinterpret_cast<char*>(&this->_input_buffer[0]), 2 );
774 zip_stream.avail_in = this->get_istream().gcount();
776 if ( (zip_stream.avail_in >= 2) &&
777 (this->_input_buffer[0] == detail::gz_magic[0]) &&
778 (this->_input_buffer[1] == detail::gz_magic[1]) ) {
779 this->_streamType = BufferType::GZIP_ST;
780 zip_stream.avail_in = 0;
783 this->_streamType = BufferType::DATA_ST;
785 err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
790 method = int(this->get_istream().get());
791 localFlags = int(this->get_istream().get());
792 if (method != Z_DEFLATED || (localFlags & detail::gz_reserved) != 0)
798 /* Discard time, xflags and OS code: */
799 for (len = 0; len < 6; len++)
800 this->get_istream().get();
802 if ((localFlags & detail::gz_extra_field) != 0)
804 /* skip the extra field */
805 len = uInt(this->get_istream().get());
806 len += uInt(this->get_istream().get())<<8;
807 /* len is garbage if EOF but the loop below will quit anyway */
808 while (len-- != 0 && this->get_istream().get() != EOF) ;
810 if ((localFlags & detail::gz_orig_name) != 0)
812 /* skip the original file name */
813 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
815 if ((localFlags & detail::gz_comment) != 0)
817 /* skip the .gz file comment */
818 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
820 if ((localFlags & detail::gz_head_crc) != 0)
821 { /* skip the header crc */
822 for (len = 0; len < 2; len++)
823 this->get_istream().get();
825 err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
833 template <class charT, class traits> inline
835 basic_zip_istream<charT, traits>::read_footer(void)
841 _gzip_crc += ((int(this->get_istream().get()) & 0xff) << (8*n));
846 ((int(this->get_istream().get()) & 0xff) << (8*n));