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 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 {
00276
00277 _zip_stream.zalloc = (alloc_func) 0;
00278 _zip_stream.zfree = (free_func) 0;
00279
00280 _zip_stream.next_in = NULL;
00281 _zip_stream.avail_in = 0;
00282 _zip_stream.avail_out = 0;
00283 _zip_stream.next_out = NULL;
00284
00285 _err = inflateInit2(&_zip_stream, window_size);
00286
00287 this->setg(&_buffer[0] + 4,
00288 &_buffer[0] + 4,
00289 &_buffer[0] + 4);
00290 }
00291
00295 template <class charT, class traits>
00296 basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
00297 {
00298 inflateEnd(&_zip_stream);
00299 }
00300
00301
00305 template <class charT, class traits>
00306 typename basic_unzip_streambuf<charT, traits>::int_type
00307 basic_unzip_streambuf<charT, traits>::underflow(void)
00308 {
00309 if(this->gptr() && ( this->gptr() < this->egptr()))
00310 return * reinterpret_cast<unsigned char *>(this->gptr());
00311
00312 int n_putback = static_cast<int>(this->gptr() - this->eback());
00313 if(n_putback > 4)
00314 n_putback = 4;
00315
00316 memcpy(&_buffer[0] + (4 - n_putback),
00317 this->gptr() - n_putback,
00318 n_putback * sizeof(char_type));
00319
00320 int num =
00321 unzip_from_stream(&_buffer[0] + 4,
00322 static_cast<std::streamsize>((_buffer.size() - 4) *
00323 sizeof(char_type)));
00324
00325 if(num <= 0)
00326 return EOF;
00327
00328
00329 this->setg(&_buffer[0] + (4 - n_putback),
00330 &_buffer[0] + 4,
00331 &_buffer[0] + 4 + num);
00332
00333
00334 return * reinterpret_cast<unsigned char *>(this->gptr());
00335 }
00336
00339 template <class charT, class traits> inline
00340 typename basic_unzip_streambuf<charT, traits>::istream_reference
00341 basic_unzip_streambuf<charT, traits>::get_istream(void)
00342 {
00343 return _istream;
00344 }
00345
00348 template <class charT, class traits> inline
00349 z_stream &
00350 basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
00351 {
00352 return _zip_stream;
00353 }
00354
00357 template <class charT, class traits> inline
00358 int
00359 basic_unzip_streambuf<charT, traits>::get_zerr(void) const
00360 {
00361 return _err;
00362 }
00363
00366 template <class charT, class traits> inline
00367 unsigned long
00368 basic_unzip_streambuf<charT, traits>::get_crc(void) const
00369 {
00370 return _crc;
00371 }
00372
00375 template <class charT, class traits> inline
00376 long
00377 basic_unzip_streambuf<charT, traits>::get_out_size(void) const
00378 {
00379 return _zip_stream.total_out;
00380 }
00381
00384 template <class charT, class traits> inline
00385 long
00386 basic_unzip_streambuf<charT, traits>::get_in_size(void) const
00387 {
00388 return _zip_stream.total_in;
00389 }
00390
00391
00392
00393
00394
00395
00398 template <class charT, class traits> inline
00399 void
00400 basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
00401 {
00402 if(_zip_stream.avail_in == 0)
00403 return;
00404
00405 _istream.clear(std::ios::goodbit);
00406 _istream.seekg(-intf(_zip_stream.avail_in),
00407 std::ios_base::cur);
00408
00409 _zip_stream.avail_in = 0;
00410 }
00411
00414 template <class charT, class traits> inline
00415 std::streamsize
00416 basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
00417 std::streamsize buffer_size)
00418 {
00419 _zip_stream.next_out =
00420 (byte_buffer_type) buffer;
00421 _zip_stream.avail_out =
00422 static_cast<uInt>(buffer_size * sizeof(char_type));
00423 size_t count = _zip_stream.avail_in;
00424
00425 do
00426 {
00427 if(_zip_stream.avail_in == 0)
00428 count=fill_input_buffer();
00429
00430 if(_zip_stream.avail_in)
00431 {
00432 _err = inflate(&_zip_stream, Z_SYNC_FLUSH);
00433 }
00434 }
00435 while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
00436
00437
00438 _crc = crc32(_crc, (byte_buffer_type) buffer,
00439 buffer_size - _zip_stream.avail_out / sizeof(char_type));
00440
00441 std::streamsize n_read =
00442 buffer_size - _zip_stream.avail_out / sizeof(char_type);
00443
00444
00445 if (_err == Z_STREAM_END)
00446 put_back_from_zip_stream();
00447
00448 return n_read;
00449 }
00450
00451
00454 template <class charT, class traits> inline
00455 size_t
00456 basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
00457 {
00458 _zip_stream.next_in = &_input_buffer[0];
00459 _istream.read((char_type*) &_input_buffer[0],
00460 static_cast<std::streamsize>(_input_buffer.size() /
00461 sizeof(char_type)));
00462
00463 return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00482 template <class charT, class traits> inline
00483 basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
00484 bool is_gzip,
00485 int level,
00486 EStrategy strategy,
00487 int window_size,
00488 int memory_level,
00489 size_t buffer_size) :
00490 basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
00491 memory_level, buffer_size),
00492 std::basic_ostream<charT, traits>(this),
00493 _is_gzip(is_gzip),
00494 _added_footer(false)
00495 {
00496 if(_is_gzip)
00497 add_header();
00498 }
00499
00502 template <class charT, class traits>
00503 basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
00504 {
00505 if(_is_gzip)
00506 add_footer();
00507 }
00508
00511 template <class charT, class traits> inline
00512 bool basic_zip_ostream<charT, traits>::is_gzip(void) const
00513 {
00514 return _is_gzip;
00515 }
00516
00520 template <class charT, class traits> inline
00521 basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
00522 {
00523 std::basic_ostream<charT, traits>::flush();
00524 basic_zip_streambuf<charT, traits>::flush();
00525 return *this;
00526 }
00527
00528 template <class charT, class traits> inline
00529 void basic_zip_ostream<charT, traits>::finished(void)
00530 {
00531 if(_is_gzip)
00532 add_footer();
00533 else
00534 zflush();
00535 }
00536
00537
00538
00539
00540
00541
00545 template <class charT, class traits>
00546 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
00547 {
00548 char_type zero = 0;
00549
00550 this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
00551 << static_cast<char_type>(detail::gz_magic[1])
00552 << static_cast<char_type>(Z_DEFLATED)
00553 << zero
00554 << zero<<zero<<zero<<zero
00555 << zero
00556 << static_cast<char_type>(OS_CODE);
00557
00558 return *this;
00559 }
00560
00564 template <class charT, class traits>
00565 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
00566 {
00567 if(_added_footer)
00568 return *this;
00569
00570 zflush();
00571
00572 _added_footer = true;
00573
00574
00575 unsigned long crc = this->get_crc();
00576 for(int n=0;n<4;++n)
00577 {
00578 this->get_ostream().put((int)(crc & 0xff));
00579 crc >>= 8;
00580 }
00581
00582 unsigned long length = this->get_in_size();
00583 for(int n=0;n<4;++n)
00584 {
00585 this->get_ostream().put((int)(length & 0xff));
00586 length >>= 8;
00587 }
00588
00589 return *this;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00607 template <class charT, class traits>
00608 basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
00609 int window_size,
00610 size_t read_buffer_size,
00611 size_t input_buffer_size)
00612 : basic_unzip_streambuf<charT, traits>(istream, window_size,
00613 read_buffer_size, input_buffer_size),
00614 std::basic_istream<charT, traits>(this),
00615 _is_gzip(false),
00616 _gzip_crc(0),
00617 _gzip_data_size(0)
00618 {
00619 if(this->get_zerr() == Z_OK)
00620 check_header();
00621 }
00622
00625 template <class charT, class traits> inline
00626 bool
00627 basic_zip_istream<charT, traits>::is_gzip(void) const
00628 {
00629 return _is_gzip;
00630 }
00631
00639 template <class charT, class traits> inline
00640 bool
00641 basic_zip_istream<charT, traits>::check_crc(void)
00642 {
00643 read_footer();
00644 return this->get_crc() == _gzip_crc;
00645 }
00646
00649 template <class charT, class traits> inline
00650 bool
00651 basic_zip_istream<charT, traits>::check_data_size(void) const
00652 {
00653 return this->get_out_size() == _gzip_data_size;
00654 }
00655
00658 template <class charT, class traits> inline
00659 long
00660 basic_zip_istream<charT, traits>::get_gzip_crc(void) const
00661 {
00662 return _gzip_crc;
00663 }
00664
00667 template <class charT, class traits> inline
00668 long
00669 basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
00670 {
00671 return _gzip_data_size;
00672 }
00673
00674
00675
00676
00677
00681 template <class charT, class traits>
00682 int
00683 basic_zip_istream<charT, traits>::check_header(void)
00684 {
00685 int method;
00686 int flags;
00687 uInt len;
00688 int c;
00689 int err=0;
00690 z_stream &zip_stream = this->get_zip_stream();
00691
00692
00693 for(len = 0; len < 2; len++)
00694 {
00695 c = (int)this->get_istream().get();
00696 if (c != detail::gz_magic[len])
00697 {
00698 if (len != 0)
00699 this->get_istream().unget();
00700 if (c!= EOF)
00701 {
00702 this->get_istream().unget();
00703 }
00704
00705 err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
00706 _is_gzip = false;
00707 return err;
00708 }
00709 }
00710
00711 _is_gzip = true;
00712 method = (int)this->get_istream().get();
00713 flags = (int)this->get_istream().get();
00714 if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0)
00715 {
00716 err = Z_DATA_ERROR;
00717 return err;
00718 }
00719
00720
00721 for (len = 0; len < 6; len++)
00722 this->get_istream().get();
00723
00724 if ((flags & detail::gz_extra_field) != 0)
00725 {
00726
00727 len = (uInt)this->get_istream().get();
00728 len += ((uInt)this->get_istream().get())<<8;
00729
00730 while (len-- != 0 && this->get_istream().get() != EOF) ;
00731 }
00732 if ((flags & detail::gz_orig_name) != 0)
00733 {
00734
00735 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00736 }
00737 if ((flags & detail::gz_comment) != 0)
00738 {
00739
00740 while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00741 }
00742 if ((flags & detail::gz_head_crc) != 0)
00743 {
00744 for (len = 0; len < 2; len++)
00745 this->get_istream().get();
00746 }
00747 err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
00748
00749 return err;
00750 }
00751
00755 template <class charT, class traits>
00756 void
00757 basic_zip_istream<charT, traits>::read_footer(void)
00758 {
00759 if(_is_gzip)
00760 {
00761 _gzip_crc = 0;
00762 for(int n=0;n<4;++n)
00763 _gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
00764
00765 _gzip_data_size = 0;
00766 for(int n=0;n<4;++n)
00767 _gzip_data_size +=
00768 ((((int) this->get_istream().get()) & 0xff) << (8*n));
00769 }
00770 }