00001
00002
00003
00004
00005
00006
00007
00008
00013 template <class charT, class traits>
00014 basic_zip_streambuf<charT, traits>::basic_zip_streambuf(ostream_reference ostream,
00015 int level,
00016 EStrategy strategy,
00017 int window_size,
00018 int memory_level,
00019 size_t buffer_size)
00020 : _ostream(ostream),
00021 _output_buffer(buffer_size, 0),
00022 _buffer(buffer_size, 0),
00023 _crc(0)
00024 {
00025 _zip_stream.zalloc = (alloc_func) 0;
00026 _zip_stream.zfree = (free_func) 0;
00027
00028 _zip_stream.next_in = NULL;
00029 _zip_stream.avail_in = 0;
00030 _zip_stream.avail_out = 0;
00031 _zip_stream.next_out = NULL;
00032
00033 if(level > 9)
00034 level = 9;
00035
00036 if(memory_level > 9)
00037 memory_level = 9;
00038
00039 _err=deflateInit2(&_zip_stream, level, Z_DEFLATED,
00040 window_size, memory_level,
00041 static_cast<int>(strategy));
00042
00043 this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
00044 }
00045
00048 template <class charT, class traits>
00049 basic_zip_streambuf<charT, traits>::~basic_zip_streambuf(void)
00050 {
00051 flush();
00052 _ostream.flush();
00053 _err=deflateEnd(&_zip_stream);
00054 }
00055
00060 template <class charT, class traits>
00061 int basic_zip_streambuf<charT, traits>::sync(void)
00062 {
00063 if(this->pptr() && this->pptr() > this->pbase())
00064 {
00065 overflow(EOF);
00066
00067
00068
00069
00070
00071
00072 }
00073
00074 return 0;
00075 }
00076
00081 template <class charT, class traits>
00082 typename basic_zip_streambuf<charT, traits>::int_type
00083 basic_zip_streambuf<charT, traits>::overflow(int_type c)
00084 {
00085 int w = static_cast<int>(this->pptr() - this->pbase());
00086 if (c != EOF)
00087 {
00088 *this->pptr() = c;
00089 ++w;
00090 }
00091 if (zip_to_stream(this->pbase(), w))
00092 {
00093 setp(this->pbase(), this->epptr() - 1);
00094 return c;
00095 }
00096 else
00097 {
00098 return EOF;
00099 }
00100 }
00101
00107 template <class charT, class traits>
00108 std::streamsize basic_zip_streambuf<charT, traits>::flush(void)
00109 {
00110 std::streamsize written_byte_size = 0, total_written_byte_size = 0;
00111
00112 size_t remainder = 0;
00113
00114
00115 _crc = crc32(_crc, _zip_stream.next_in,
00116 _zip_stream.avail_in);
00117
00118 do
00119 {
00120 _err = deflate(&_zip_stream, Z_FINISH);
00121 if(_err == Z_OK || _err == Z_STREAM_END)
00122 {
00123 written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
00124 total_written_byte_size += written_byte_size;
00125
00126 _ostream.write( (const char_type*) &(_output_buffer[0]),
00127 static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
00128
00129
00130 if((remainder = written_byte_size%sizeof(char_type)) != 0)
00131 {
00132
00133 memcpy(&(_output_buffer[0]),
00134 &(_output_buffer[written_byte_size-remainder]), remainder);
00135
00136 }
00137
00138 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
00139 _zip_stream.next_out = &_output_buffer[remainder];
00140 }
00141 }
00142 while(_err == Z_OK);
00143
00144 _ostream.flush();
00145
00146 return total_written_byte_size;
00147 }
00148
00151 template <class charT, class traits> inline
00152 typename basic_zip_streambuf<charT, traits>::ostream_reference
00153 basic_zip_streambuf<charT, traits>::get_ostream(void) const
00154 {
00155 return _ostream;
00156 }
00157
00160 template <class charT, class traits> inline
00161 int basic_zip_streambuf<charT, traits>::get_zerr(void) const
00162 {
00163 return _err;
00164 }
00165
00168 template <class charT, class traits> inline
00169 unsigned long
00170 basic_zip_streambuf<charT, traits>:: get_crc(void) const
00171 {
00172 return _crc;
00173 }
00174
00177 template <class charT, class traits> inline
00178 unsigned long
00179 basic_zip_streambuf<charT, traits>::get_in_size(void) const
00180 {
00181 return _zip_stream.total_in;
00182 }
00183
00186 template <class charT, class traits> inline
00187 long
00188 basic_zip_streambuf<charT, traits>::get_out_size(void) const
00189 {
00190 return _zip_stream.total_out;
00191 }
00192
00193
00194
00195
00196
00201 template <class charT, class traits>
00202 bool basic_zip_streambuf<charT, traits>::zip_to_stream(
00203 char_type *buffer,
00204 std::streamsize buffer_size)
00205 {
00206 std::streamsize written_byte_size = 0, total_written_byte_size = 0;
00207
00208 _zip_stream.next_in = (byte_buffer_type) buffer;
00209 _zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
00210 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
00211 _zip_stream.next_out = &_output_buffer[0];
00212 size_t remainder = 0;
00213
00214
00215 _crc = crc32(_crc, _zip_stream.next_in,
00216 _zip_stream.avail_in);
00217
00218 do
00219 {
00220 _err = deflate(&_zip_stream, 0);
00221
00222 if (_err == Z_OK || _err == Z_STREAM_END)
00223 {
00224 written_byte_size= static_cast<std::streamsize>(_output_buffer.size()) -
00225 _zip_stream.avail_out;
00226 total_written_byte_size += written_byte_size;
00227
00228
00229 _ostream.write((const char_type*) &_output_buffer[0],
00230 static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
00231
00232
00233 if((remainder = written_byte_size % sizeof(char_type)) != 0)
00234 {
00235
00236 memcpy(&_output_buffer[0],
00237 &_output_buffer[written_byte_size-remainder],
00238 remainder);
00239 }
00240
00241 _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
00242 _zip_stream.next_out = &_output_buffer[remainder];
00243 }
00244 }
00245 while(_zip_stream.avail_in != 0 && _err == Z_OK);
00246
00247 return _err == Z_OK;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00266 template <class charT, class traits>
00267 basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(istream_reference istream,
00268 int window_size,
00269 size_t read_buffer_size,
00270 size_t input_buffer_size)
00271 : _istream(istream),
00272 _input_buffer(input_buffer_size),
00273 _buffer(read_buffer_size),
00274 _crc(0),
00275 _streamType ( UNKNOWN_ST )
00276 {
00277
00278 _zip_stream.zalloc = (alloc_func) 0;
00279 _zip_stream.zfree = (free_func) 0;
00280
00281 _zip_stream.next_in = NULL;
00282 _zip_stream.avail_in = 0;
00283 _zip_stream.avail_out = 0;
00284 _zip_stream.next_out = NULL;
00285
00286
00287 _err = inflateInit2(&_zip_stream, window_size);
00288
00289 this->setg(&_buffer[0] + 4,
00290 &_buffer[0] + 4,
00291 &_buffer[0] + 4);
00292 }
00293
00297 template <class charT, class traits>
00298 basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
00299 {
00300 inflateEnd(&_zip_stream);
00301 }
00302
00303
00307 template <class charT, class traits>
00308 typename basic_unzip_streambuf<charT, traits>::int_type
00309 basic_unzip_streambuf<charT, traits>::underflow(void)
00310 {
00311 if(this->gptr() && ( this->gptr() < this->egptr()))
00312 return * reinterpret_cast<unsigned char *>(this->gptr());
00313
00314 int n_putback = static_cast<int>(this->gptr() - this->eback());
00315 if(n_putback > 4)
00316 n_putback = 4;
00317
00318 memcpy(&_buffer[0] + (4 - n_putback),
00319 this->gptr() - n_putback,
00320 n_putback * sizeof(char_type));
00321
00322 int num =
00323 unzip_from_stream(&_buffer[0] + 4,
00324 static_cast<std::streamsize>((_buffer.size() - 4) *
00325 sizeof(char_type)));
00326
00327 if(num <= 0)
00328 return EOF;
00329
00330
00331 this->setg(&_buffer[0] + (4 - n_putback),
00332 &_buffer[0] + 4,
00333 &_buffer[0] + 4 + num);
00334
00335
00336 return * reinterpret_cast<unsigned char *>(this->gptr());
00337 }
00338
00341 template <class charT, class traits> inline
00342 typename basic_unzip_streambuf<charT, traits>::istream_reference
00343 basic_unzip_streambuf<charT, traits>::get_istream(void)
00344 {
00345 return _istream;
00346 }
00347
00350 template <class charT, class traits> inline
00351 z_stream &
00352 basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
00353 {
00354 return _zip_stream;
00355 }
00356
00359 template <class charT, class traits> inline
00360 int
00361 basic_unzip_streambuf<charT, traits>::get_zerr(void) const
00362 {
00363 return _err;
00364 }
00365
00368 template <class charT, class traits> inline
00369 unsigned long
00370 basic_unzip_streambuf<charT, traits>::get_crc(void) const
00371 {
00372 return _crc;
00373 }
00374
00377 template <class charT, class traits> inline
00378 long
00379 basic_unzip_streambuf<charT, traits>::get_out_size(void) const
00380 {
00381 return _zip_stream.total_out;
00382 }
00383
00386 template <class charT, class traits> inline
00387 long
00388 basic_unzip_streambuf<charT, traits>::get_in_size(void) const
00389 {
00390 return _zip_stream.total_in;
00391 }
00392
00393
00394
00395
00396
00397
00400 template <class charT, class traits> inline
00401 void
00402 basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
00403 {
00404 if(_zip_stream.avail_in == 0)
00405 return;
00406
00407 _istream.clear(std::ios::goodbit);
00408 _istream.seekg(-intf(_zip_stream.avail_in),
00409 std::ios_base::cur);
00410
00411 _zip_stream.avail_in = 0;
00412 }
00413
00416 template <class charT, class traits> inline
00417 std::streamsize
00418 basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
00419 std::streamsize buffer_size)
00420 {
00421 _zip_stream.next_out =
00422 (byte_buffer_type) buffer;
00423 _zip_stream.avail_out =
00424 static_cast<uInt>(buffer_size * sizeof(char_type));
00425 size_t count = _zip_stream.avail_in;
00426
00427 do
00428 {
00429 if(_zip_stream.avail_in == 0)
00430 count=fill_input_buffer();
00431
00432 if(_zip_stream.avail_in)
00433 {
00434 switch (_streamType) {
00435 case GZIP_ST:
00436 _err = inflate(&_zip_stream, Z_SYNC_FLUSH);
00437 break;
00438 case DATA_ST:
00439 if (_zip_stream.avail_out < count)
00440 count = _zip_stream.avail_out;
00441 memcpy ( _zip_stream.next_out, _zip_stream.next_in, count );
00442 _zip_stream.avail_in -= count;
00443 _zip_stream.avail_out -= count;
00444 _zip_stream.next_in += count;
00445 _zip_stream.next_out += count;
00446 break;
00447 default:
00448 FWARNING (("Unknown _streamType: %d\n", _streamType ));
00449 break;
00450 }
00451 }
00452 }
00453 while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
00454
00455
00456 _crc = crc32(_crc, (byte_buffer_type) buffer,
00457 buffer_size - _zip_stream.avail_out / sizeof(char_type));
00458
00459 std::streamsize n_read =
00460 buffer_size - _zip_stream.avail_out / sizeof(char_type);
00461
00462
00463 if (_err == Z_STREAM_END)
00464 put_back_from_zip_stream();
00465
00466 return n_read;
00467 }
00468
00469
00472 template <class charT, class traits> inline
00473 size_t
00474 basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
00475 {
00476 _zip_stream.next_in = &_input_buffer[0];
00477 _istream.read((char_type*) &_input_buffer[0],
00478 static_cast<std::streamsize>(_input_buffer.size() /
00479 sizeof(char_type)));
00480
00481 return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00500 template <class charT, class traits> inline
00501 basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
00502 bool is_gzip,
00503 int level,
00504 EStrategy strategy,
00505 int window_size,
00506 int memory_level,
00507 size_t buffer_size) :
00508 basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
00509 memory_level, buffer_size),
00510 std::basic_ostream<charT, traits>(this),
00511 _is_gzip(is_gzip),
00512 _added_footer(false)
00513 {
00514 if(_is_gzip)
00515 add_header();
00516 }
00517
00520 template <class charT, class traits>
00521 basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
00522 {
00523 if(_is_gzip)
00524 add_footer();
00525 }
00526
00529 template <class charT, class traits> inline
00530 bool basic_zip_ostream<charT, traits>::is_gzip(void) const
00531 {
00532 return _is_gzip;
00533 }
00534
00538 template <class charT, class traits> inline
00539 basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
00540 {
00541 std::basic_ostream<charT, traits>::flush();
00542 basic_zip_streambuf<charT, traits>::flush();
00543 return *this;
00544 }
00545
00546 template <class charT, class traits> inline
00547 void basic_zip_ostream<charT, traits>::finished(void)
00548 {
00549 if(_is_gzip)
00550 add_footer();
00551 else
00552 zflush();
00553 }
00554
00555
00556
00557
00558
00559
00563 template <class charT, class traits>
00564 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
00565 {
00566 char_type zero = 0;
00567
00568 this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
00569 << static_cast<char_type>(detail::gz_magic[1])
00570 << static_cast<char_type>(Z_DEFLATED)
00571 << zero
00572 << zero<<zero<<zero<<zero
00573 << zero
00574 << static_cast<char_type>(OS_CODE);
00575
00576 return *this;
00577 }
00578
00582 template <class charT, class traits>
00583 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
00584 {
00585 if(_added_footer)
00586 return *this;
00587
00588 zflush();
00589
00590 _added_footer = true;
00591
00592
00593 unsigned long crc = this->get_crc();
00594 for(int n=0;n<4;++n)
00595 {
00596 this->get_ostream().put((int)(crc & 0xff));
00597 crc >>= 8;
00598 }
00599
00600 unsigned long length = this->get_in_size();
00601 for(int n=0;n<4;++n)
00602 {
00603 this->get_ostream().put((int)(length & 0xff));
00604 length >>= 8;
00605 }
00606
00607 return *this;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00625 template <class charT, class traits>
00626 basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
00627 int window_size,
00628 size_t read_buffer_size,
00629 size_t input_buffer_size)
00630 : basic_unzip_streambuf<charT, traits>(istream, window_size,
00631 read_buffer_size, input_buffer_size),
00632 std::basic_istream<charT, traits>(this),
00633 _is_gzip(false),
00634 _gzip_crc(0),
00635 _gzip_data_size(0)
00636 {
00637 if(this->get_zerr() == Z_OK)
00638 check_header();
00639 }
00640
00643 template <class charT, class traits> inline
00644 bool
00645 basic_zip_istream<charT, traits>::is_gzip(void) const
00646 {
00647 return _is_gzip;
00648 }
00649
00657 template <class charT, class traits> inline
00658 bool
00659 basic_zip_istream<charT, traits>::check_crc(void)
00660 {
00661 read_footer();
00662 return this->get_crc() == _gzip_crc;
00663 }
00664
00667 template <class charT, class traits> inline
00668 bool
00669 basic_zip_istream<charT, traits>::check_data_size(void) const
00670 {
00671 return this->get_out_size() == _gzip_data_size;
00672 }
00673
00676 template <class charT, class traits> inline
00677 long
00678 basic_zip_istream<charT, traits>::get_gzip_crc(void) const
00679 {
00680 return _gzip_crc;
00681 }
00682
00685 template <class charT, class traits> inline
00686 long
00687 basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
00688 {
00689 return _gzip_data_size;
00690 }
00691
00692
00693
00694
00695
00699 template <class charT, class traits>
00700 int
00701 basic_zip_istream<charT, traits>::check_header(void)
00702 {
00703 int method;
00704 int flags;
00705 uInt len;
00706 int c;
00707 int err=0;
00708 z_stream &zip_stream = this->get_zip_stream();
00709
00710
00711 zip_stream.next_in = &this->_input_buffer[0];
00712 this->get_istream().read( (char*)(&this->_input_buffer[0]), 2 );
00713 zip_stream.avail_in = this->get_istream().gcount();
00714
00715 if ( (zip_stream.avail_in >= 2) &&
00716 (this->_input_buffer[0] == detail::gz_magic[0]) &&
00717 (this->_input_buffer[1] == detail::gz_magic[1]) ) {
00718 this->_streamType = BufferType::GZIP_ST;
00719 zip_stream.avail_in = 0;
00720 }
00721 else {
00722 this->_streamType = BufferType::DATA_ST;
00723 _is_gzip = false;
00724 err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
00725 return err;
00726 }
00727
00728 _is_gzip = true;
00729 method = (int)this->get_istream().get();
00730 flags = (int)this->get_istream().get();
00731 if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0)
00732 {
00733 err = Z_DATA_ERROR;
00734 return err;
00735 }
00736
00737
00738 for (len = 0; len < 6; len++)
00739 this->get_istream().get();
00740
00741 if ((flags & detail::gz_extra_field) != 0)
00742 {
00743
00744 len = (uInt)this->get_istream().get();
00745 len += ((uInt)this->get_istream().get())<<8;
00746
00747 while (len-- != 0 && this->get_istream().get() != EOF) ;
00748 }
00749 if ((flags & detail::gz_orig_name) != 0)
00750 {
00751
00752 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00753 }
00754 if ((flags & detail::gz_comment) != 0)
00755 {
00756
00757 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00758 }
00759 if ((flags & detail::gz_head_crc) != 0)
00760 {
00761 for (len = 0; len < 2; len++)
00762 this->get_istream().get();
00763 }
00764 err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
00765
00766 return err;
00767 }
00768
00772 template <class charT, class traits>
00773 void
00774 basic_zip_istream<charT, traits>::read_footer(void)
00775 {
00776 if(_is_gzip)
00777 {
00778 _gzip_crc = 0;
00779 for(int n=0;n<4;++n)
00780 _gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
00781
00782 _gzip_data_size = 0;
00783 for(int n=0;n<4;++n)
00784 _gzip_data_size +=
00785 ((((int) this->get_istream().get()) & 0xff) << (8*n));
00786 }
00787 }