77 # if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
82 #endif // GENESIS_ZLIB
103 class GzipStreamWrapper
108 GzipStreamWrapper(
bool is_input =
true,
int level = Z_DEFAULT_COMPRESSION )
109 : is_input_(is_input)
111 this->zalloc = Z_NULL;
112 this->zfree = Z_NULL;
113 this->opaque = Z_NULL;
118 this->next_in = Z_NULL;
119 ret = inflateInit2(
this, 15+32 );
125 throw std::invalid_argument(
126 "Compression level " +
std::to_string(
static_cast<int>(level )) +
127 " is invalid for usage in gzip output stream. Valid range is [ -1, 9 ]."
130 ret = deflateInit2(
this, level, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY );
134 throw GzipError( this->msg, ret );
175 :
public std::streambuf
184 std::streambuf * sbuf_p,
185 bool auto_detect =
true,
189 , zstrm_ptr_(nullptr)
190 , auto_detect_(auto_detect)
191 , buff_size_(buff_size)
192 , auto_detect_run_(false)
196 in_buff_ =
new char [buff_size_];
197 in_buff_start_ = in_buff_;
198 in_buff_end_ = in_buff_;
199 out_buff_ =
new char [buff_size_];
200 setg(out_buff_, out_buff_, out_buff_);
203 GzipIStreambuf( GzipIStreambuf
const& ) =
delete;
204 GzipIStreambuf( GzipIStreambuf && ) =
delete;
205 GzipIStreambuf& operator = ( GzipIStreambuf
const& ) =
delete;
206 GzipIStreambuf& operator = ( GzipIStreambuf && ) =
delete;
208 virtual ~GzipIStreambuf()
221 virtual std::streambuf::int_type underflow()
override
223 if (this->gptr() == this->egptr()) {
225 char * out_buff_free_start = out_buff_;
229 if (in_buff_start_ == in_buff_end_) {
231 in_buff_start_ = in_buff_;
232 std::streamsize sz = sbuf_p_->sgetn(in_buff_, buff_size_);
233 in_buff_end_ = in_buff_ + sz;
234 if (in_buff_end_ == in_buff_start_)
break;
238 if (auto_detect_ && ! auto_detect_run_) {
239 auto_detect_run_ =
true;
240 unsigned char b0 = *
reinterpret_cast< unsigned char *
>(in_buff_start_);
241 unsigned char b1 = *
reinterpret_cast< unsigned char *
>(in_buff_start_ + 1);
246 is_text_ = ! (in_buff_start_ + 2 <= in_buff_end_
247 && ((b0 == 0x1F && b1 == 0x8B)
248 || (b0 == 0x78 && (b1 == 0x01
256 assert(in_buff_start_ == in_buff_);
258 out_buff_free_start = in_buff_end_;
259 in_buff_start_ = in_buff_;
260 in_buff_end_ = in_buff_;
266 zstrm_ptr_ =
new GzipStreamWrapper(
true);
268 zstrm_ptr_->next_in =
reinterpret_cast< decltype(zstrm_ptr_-
>next_in) >(in_buff_start_);
269 zstrm_ptr_->avail_in = in_buff_end_ - in_buff_start_;
270 zstrm_ptr_->next_out =
reinterpret_cast< decltype(zstrm_ptr_-
>next_out) >(out_buff_free_start);
271 zstrm_ptr_->avail_out = (out_buff_ + buff_size_) - out_buff_free_start;
272 int ret = inflate(zstrm_ptr_, Z_NO_FLUSH);
275 if (ret != Z_OK && ret != Z_STREAM_END) {
276 throw GzipError(zstrm_ptr_->msg, ret);
280 in_buff_start_ =
reinterpret_cast< decltype(in_buff_start_)
>(zstrm_ptr_->next_in);
281 in_buff_end_ = in_buff_start_ + zstrm_ptr_->avail_in;
282 out_buff_free_start =
reinterpret_cast< decltype(out_buff_free_start)
>(zstrm_ptr_->next_out);
283 assert(out_buff_free_start + zstrm_ptr_->avail_out == out_buff_ + buff_size_);
286 if (ret == Z_STREAM_END) {
288 zstrm_ptr_ =
nullptr;
291 }
while (out_buff_free_start == out_buff_);
296 this->setg(out_buff_, out_buff_, out_buff_free_start);
299 return this->gptr() == this->egptr()
301 : traits_type::to_int_type(*this->gptr())
311 std::streambuf * sbuf_p_;
313 char * in_buff_start_;
316 GzipStreamWrapper * zstrm_ptr_;
318 std::size_t buff_size_;
319 bool auto_detect_run_;
346 :
public std::streambuf
355 std::streambuf * sbuf_p
361 std::streambuf * sbuf_p,
366 , zstrm_ptr_(new GzipStreamWrapper(false, level))
367 , buff_size_(buff_size)
370 in_buff_ =
new char [buff_size_];
371 out_buff_ =
new char [buff_size_];
372 setp(in_buff_, in_buff_ + buff_size_);
375 GzipOStreambuf( GzipOStreambuf
const& ) =
delete;
376 GzipOStreambuf( GzipOStreambuf &&) =
delete;
377 GzipOStreambuf& operator = ( GzipOStreambuf
const& ) =
delete;
378 GzipOStreambuf& operator = ( GzipOStreambuf &&) =
delete;
380 virtual ~GzipOStreambuf()
402 virtual std::streambuf::int_type overflow(std::streambuf::int_type c = traits_type::eof())
override
404 zstrm_ptr_->next_in =
reinterpret_cast< decltype(zstrm_ptr_-
>next_in) >(pbase());
405 zstrm_ptr_->avail_in = pptr() - pbase();
406 while (zstrm_ptr_->avail_in > 0) {
407 int r = deflate_loop_(Z_NO_FLUSH);
409 setp(
nullptr,
nullptr);
410 return traits_type::eof();
413 setp(in_buff_, in_buff_ + buff_size_);
414 return traits_type::eq_int_type(c, traits_type::eof()) ? traits_type::eof() : sputc(c);
417 virtual int sync()
override
426 zstrm_ptr_->next_in =
nullptr;
427 zstrm_ptr_->avail_in = 0;
429 if (deflate_loop_(Z_FINISH) != 0) {
432 deflateReset(zstrm_ptr_);
438 int deflate_loop_(
int flush)
441 zstrm_ptr_->next_out =
reinterpret_cast< decltype(zstrm_ptr_-
>next_out) >(out_buff_);
442 zstrm_ptr_->avail_out = buff_size_;
443 int ret = deflate(zstrm_ptr_, flush);
444 if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
445 throw GzipError( zstrm_ptr_->msg, ret );
448 std::streamsize sz = sbuf_p_->sputn(
449 out_buff_,
reinterpret_cast< decltype(out_buff_)
>(zstrm_ptr_->next_out) - out_buff_
452 if (sz !=
reinterpret_cast< decltype(out_buff_)
>(zstrm_ptr_->next_out) - out_buff_) {
457 if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0) {
470 std::streambuf * sbuf_p_;
473 GzipStreamWrapper * zstrm_ptr_;
474 std::size_t buff_size_;
484 : std::istream( new GzipIStreambuf( is.rdbuf(), auto_detect, buffer_size ))
486 exceptions(std::ios_base::badbit);
490 : std::istream( new GzipIStreambuf( sbuf_p, auto_detect, buffer_size ))
492 exceptions(std::ios_base::badbit);
511 "It seems that the zlib-internal compression levels values have changed "
512 "compared to the values that we internally use in genesis. This needs to be fixed, "
513 "please submit a bug report to https://github.com/lczech/genesis/issues"
519 : std::ostream( new GzipOStreambuf( os.rdbuf(), static_cast<int>(level), buffer_size ))
521 exceptions(std::ios_base::badbit);
525 : std::ostream( new GzipOStreambuf( sbuf_p, static_cast<int>(level), buffer_size ))
527 exceptions(std::ios_base::badbit);
540 std::string
const& filename,
541 std::ios_base::openmode mode,
543 std::size_t buffer_size
549 , std::istream( new GzipIStreambuf( file_stream_.rdbuf(), auto_detect, buffer_size ))
551 exceptions(std::ios_base::badbit);
566 std::string
const& filename,
567 std::ios_base::openmode mode,
569 std::size_t buffer_size
572 , std::ostream( new GzipOStreambuf( file_stream_.rdbuf(), static_cast<int>(level), buffer_size ))
574 exceptions(std::ios_base::badbit);
586 std::ostream::flush();
594 #else // GENESIS_ZLIB
602 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
607 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
619 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
624 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
636 std::ios_base::openmode,
640 : StrictFStreamHolder<StrictIFStream>(
"", std::ios_base::binary )
642 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
656 std::ios_base::openmode,
660 : StrictFStreamHolder<StrictOFStream>(
"", std::ios_base::binary )
662 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
672 throw std::runtime_error(
"zlib: Genesis was not compiled with zlib support." );
675 #endif // GENESIS_ZLIB