A library for working with phylogenetic and population genetic data.
v0.27.0
gzip_stream.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2020 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
24 /*
25  The code in this file as well as the according header file lib/utils/io/gzip_stream.hpp are
26  adapted from the excellent zstr library (C++ header-only ZLib wrapper" classes) by Matei David,
27  see https://github.com/mateidavid/zstr
28 
29  We adapted the original code by renaming all classes and variables to our standards,
30  moving much of the implementation into a source file (so that the header does not clutter
31  its callers with zlib-internal symbols), and refining some functionality.
32 
33  For this and the according header file, we need to include the following original license:
34 
35  The MIT License (MIT)
36 
37  Copyright (c) 2015 Matei David, Ontario Institute for Cancer Research
38 
39  Permission is hereby granted, free of charge, to any person obtaining a copy
40  of this software and associated documentation files (the "Software"), to deal
41  in the Software without restriction, including without limitation the rights
42  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43  copies of the Software, and to permit persons to whom the Software is
44  furnished to do so, subject to the following conditions:
45 
46  The above copyright notice and this permission notice shall be included in all
47  copies or substantial portions of the Software.
48 
49  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55  SOFTWARE.
56  */
57 
66 
67 #include <cassert>
68 #include <fstream>
69 #include <sstream>
70 #include <stdexcept>
71 #include <string>
72 
73 #ifdef GENESIS_ZLIB
74 
75 # include "zlib.h"
76 
77 # if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
78 # include <fcntl.h>
79 # include <io.h>
80 # endif
81 
82 #endif // GENESIS_ZLIB
83 
84 namespace genesis {
85 namespace utils {
86 
87 // We only include all the class definitions if we actually use zlib.
88 // If not, we later also provide dummy implementations that throw if instanciated.
89 #ifdef GENESIS_ZLIB
90 
91 // ================================================================================================
92 // Gzip Stream Wrapper
93 // ================================================================================================
94 
103 class GzipStreamWrapper
104  : public z_stream
105 {
106 public:
107 
108  GzipStreamWrapper( bool is_input = true, int level = Z_DEFAULT_COMPRESSION )
109  : is_input_(is_input)
110  {
111  this->zalloc = Z_NULL;
112  this->zfree = Z_NULL;
113  this->opaque = Z_NULL;
114  int ret;
115 
116  if( is_input_ ) {
117  this->avail_in = 0;
118  this->next_in = Z_NULL;
119  ret = inflateInit2( this, 15+32 );
120  } else {
121  if(
122  level < static_cast<int>( GzipCompressionLevel::kDefaultCompression ) ||
123  level > static_cast<int>( GzipCompressionLevel::kBestCompression )
124  ) {
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 ]."
128  );
129  }
130  ret = deflateInit2( this, level, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY );
131  }
132 
133  if( ret != Z_OK ) {
134  throw except::GzipError( this->msg, ret );
135  }
136  }
137 
138  ~GzipStreamWrapper()
139  {
140  if( is_input_ ) {
141  inflateEnd(this);
142  } else {
143  deflateEnd(this);
144  }
145  }
146 
147 private:
148 
149  bool is_input_;
150 };
151 
152 // ================================================================================================
153 // Gzip Input Stream Buffer
154 // ================================================================================================
155 
174 class GzipIStreambuf
175  : public std::streambuf
176 {
177 public:
178 
179  // -------------------------------------------------------------
180  // Constructors and Rule of Five
181  // -------------------------------------------------------------
182 
183  GzipIStreambuf(
184  std::streambuf * sbuf_p,
185  bool auto_detect = true,
186  std::size_t buff_size = GZIP_DEFAULT_BUFFER_SIZE
187  )
188  : sbuf_p_(sbuf_p)
189  , zstrm_ptr_(nullptr)
190  , auto_detect_(auto_detect)
191  , buff_size_(buff_size)
192  , auto_detect_run_(false)
193  , is_text_(false)
194  {
195  assert(sbuf_p_);
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_);
201  }
202 
203  GzipIStreambuf( GzipIStreambuf const& ) = delete;
204  GzipIStreambuf( GzipIStreambuf && ) = delete;
205  GzipIStreambuf& operator = ( GzipIStreambuf const& ) = delete;
206  GzipIStreambuf& operator = ( GzipIStreambuf && ) = delete;
207 
208  virtual ~GzipIStreambuf()
209  {
210  delete [] in_buff_;
211  delete [] out_buff_;
212  if( zstrm_ptr_ ) {
213  delete zstrm_ptr_;
214  }
215  }
216 
217  // -------------------------------------------------------------
218  // Virtual functions
219  // -------------------------------------------------------------
220 
221  virtual std::streambuf::int_type underflow() override
222  {
223  if (this->gptr() == this->egptr()) {
224  // pointers for free region in output buffer
225  char * out_buff_free_start = out_buff_;
226 
227  do {
228  // read more input if none available
229  if (in_buff_start_ == in_buff_end_) {
230  // empty input buffer: refill from the start
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; // end of input
235  }
236 
237  // auto detect if the stream contains text or deflate data
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);
242 
243  // Ref:
244  // http://en.wikipedia.org/wiki/Gzip
245  // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
246  is_text_ = ! (in_buff_start_ + 2 <= in_buff_end_
247  && ((b0 == 0x1F && b1 == 0x8B) // gzip header
248  || (b0 == 0x78 && (b1 == 0x01 // zlib header
249  || b1 == 0x9C
250  || b1 == 0xDA))));
251  }
252 
253  if (is_text_) {
254 
255  // simply swap in_buff_ and out_buff_, and adjust pointers
256  assert(in_buff_start_ == in_buff_);
257  std::swap(in_buff_, out_buff_);
258  out_buff_free_start = in_buff_end_;
259  in_buff_start_ = in_buff_;
260  in_buff_end_ = in_buff_;
261 
262  } else {
263 
264  // run inflate() on input
265  if (! zstrm_ptr_) {
266  zstrm_ptr_ = new GzipStreamWrapper(true);
267  }
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);
273 
274  // process return code
275  if (ret != Z_OK && ret != Z_STREAM_END) {
276  throw except::GzipError(zstrm_ptr_->msg, ret);
277  }
278 
279  // update in&out pointers following inflate()
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_);
284 
285  // if stream ended, deallocate inflator
286  if (ret == Z_STREAM_END) {
287  delete zstrm_ptr_;
288  zstrm_ptr_ = nullptr;
289  }
290  }
291  } while (out_buff_free_start == out_buff_);
292 
293  // 2 exit conditions:
294  // - end of input: there might or might not be output available
295  // - out_buff_free_start != out_buff_: output available
296  this->setg(out_buff_, out_buff_, out_buff_free_start);
297  }
298 
299  return this->gptr() == this->egptr()
300  ? traits_type::eof()
301  : traits_type::to_int_type(*this->gptr())
302  ;
303  }
304 
305  // -------------------------------------------------------------
306  // Members
307  // -------------------------------------------------------------
308 
309 private:
310 
311  std::streambuf * sbuf_p_;
312  char * in_buff_;
313  char * in_buff_start_;
314  char * in_buff_end_;
315  char * out_buff_;
316  GzipStreamWrapper * zstrm_ptr_;
317  bool auto_detect_;
318  std::size_t buff_size_;
319  bool auto_detect_run_;
320  bool is_text_;
321 };
322 
323 // ================================================================================================
324 // Gzip Output Stream Buffer
325 // ================================================================================================
326 
345 class GzipOStreambuf
346  : public std::streambuf
347 {
348 public:
349 
350  // -------------------------------------------------------------
351  // Constructors and Rule of Five
352  // -------------------------------------------------------------
353 
354  GzipOStreambuf(
355  std::streambuf * sbuf_p
356  )
357  : GzipOStreambuf( sbuf_p, Z_DEFAULT_COMPRESSION, GZIP_DEFAULT_BUFFER_SIZE )
358  {}
359 
360  GzipOStreambuf(
361  std::streambuf * sbuf_p,
362  int level,
363  std::size_t buff_size = GZIP_DEFAULT_BUFFER_SIZE
364  )
365  : sbuf_p_(sbuf_p)
366  , zstrm_ptr_(new GzipStreamWrapper(false, level))
367  , buff_size_(buff_size)
368  {
369  assert(sbuf_p_);
370  in_buff_ = new char [buff_size_];
371  out_buff_ = new char [buff_size_];
372  setp(in_buff_, in_buff_ + buff_size_);
373  }
374 
375  GzipOStreambuf( GzipOStreambuf const& ) = delete;
376  GzipOStreambuf( GzipOStreambuf &&) = delete;
377  GzipOStreambuf& operator = ( GzipOStreambuf const& ) = delete;
378  GzipOStreambuf& operator = ( GzipOStreambuf &&) = delete;
379 
380  virtual ~GzipOStreambuf()
381  {
382  // flush the zlib stream
383  //
384  // NOTE: Errors here (sync() return value not 0) are ignored, because we
385  // cannot throw in a destructor. This mirrors the behaviour of
386  // std::basic_filebuf::~basic_filebuf(). To see an exception on error,
387  // close the ofstream with an explicit call to close(), and do not rely
388  // on the implicit call in the destructor.
389  try {
390  sync();
391  } catch (...) {}
392 
393  delete [] in_buff_;
394  delete [] out_buff_;
395  delete zstrm_ptr_;
396  }
397 
398  // -------------------------------------------------------------
399  // Internal and Virtual Functions
400  // -------------------------------------------------------------
401 
402  virtual std::streambuf::int_type overflow(std::streambuf::int_type c = traits_type::eof()) override
403  {
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);
408  if (r != 0) {
409  setp(nullptr, nullptr);
410  return traits_type::eof();
411  }
412  }
413  setp(in_buff_, in_buff_ + buff_size_);
414  return traits_type::eq_int_type(c, traits_type::eof()) ? traits_type::eof() : sputc(c);
415  }
416 
417  virtual int sync() override
418  {
419  // first, call overflow to clear in_buff_
420  overflow();
421  if (! pptr()) {
422  return -1;
423  }
424 
425  // then, call deflate asking to finish the zlib stream
426  zstrm_ptr_->next_in = nullptr;
427  zstrm_ptr_->avail_in = 0;
428 
429  if (deflate_loop_(Z_FINISH) != 0) {
430  return -1;
431  }
432  deflateReset(zstrm_ptr_);
433  return 0;
434  }
435 
436 private:
437 
438  int deflate_loop_(int flush)
439  {
440  while( true ) {
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 except::GzipError( zstrm_ptr_->msg, ret );
446  }
447 
448  std::streamsize sz = sbuf_p_->sputn(
449  out_buff_, reinterpret_cast< decltype(out_buff_) >(zstrm_ptr_->next_out) - out_buff_
450  );
451 
452  if (sz != reinterpret_cast< decltype(out_buff_) >(zstrm_ptr_->next_out) - out_buff_) {
453  // there was an error in the sink stream
454  return -1;
455  }
456 
457  if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0) {
458  break;
459  }
460  }
461  return 0;
462  }
463 
464  // -------------------------------------------------------------
465  // Members
466  // -------------------------------------------------------------
467 
468 private:
469 
470  std::streambuf * sbuf_p_;
471  char * in_buff_;
472  char * out_buff_;
473  GzipStreamWrapper * zstrm_ptr_;
474  std::size_t buff_size_;
475 };
476 
477 // ================================================================================================
478 // Gzip Input Stream
479 // ================================================================================================
480 
481 // We have all the implementation here, so that we do not need to expose the stream buffers.
482 
483 GzipIStream::GzipIStream( std::istream& is, bool auto_detect, std::size_t buffer_size )
484  : std::istream( new GzipIStreambuf( is.rdbuf(), auto_detect, buffer_size ))
485 {
486  exceptions(std::ios_base::badbit);
487 }
488 
489 GzipIStream::GzipIStream( std::streambuf* sbuf_p, bool auto_detect, std::size_t buffer_size )
490  : std::istream( new GzipIStreambuf( sbuf_p, auto_detect, buffer_size ))
491 {
492  exceptions(std::ios_base::badbit);
493 }
494 
496 {
497  delete rdbuf();
498 }
499 
500 // ================================================================================================
501 // Gzip Output Stream
502 // ================================================================================================
503 
504 // Let's make sure that our levels match the zlib levels. Pretty sure that zlib will never
505 // change their levels, but if they ever do, we want to know.
506 static_assert(
507  static_cast<int>(GzipCompressionLevel::kDefaultCompression) == Z_DEFAULT_COMPRESSION &&
508  static_cast<int>(GzipCompressionLevel::kNoCompression) == Z_NO_COMPRESSION &&
509  static_cast<int>(GzipCompressionLevel::kBestSpeed) == Z_BEST_SPEED &&
510  static_cast<int>(GzipCompressionLevel::kBestCompression) == Z_BEST_COMPRESSION,
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"
514 );
515 
516 // We have all the implementation here, so that we do not need to expose the stream buffers.
517 
518 GzipOStream::GzipOStream( std::ostream& os, GzipCompressionLevel level, std::size_t buffer_size )
519  : std::ostream( new GzipOStreambuf( os.rdbuf(), static_cast<int>(level), buffer_size ))
520 {
521  exceptions(std::ios_base::badbit);
522 }
523 
524 GzipOStream::GzipOStream( std::streambuf* sbuf_p, GzipCompressionLevel level, std::size_t buffer_size )
525  : std::ostream( new GzipOStreambuf( sbuf_p, static_cast<int>(level), buffer_size ))
526 {
527  exceptions(std::ios_base::badbit);
528 }
529 
531 {
532  delete rdbuf();
533 }
534 
535 // ================================================================================================
536 // Gzip Input File Stream
537 // ================================================================================================
538 
540  std::string const& filename,
541  std::ios_base::openmode mode,
542  bool auto_detect,
543  std::size_t buffer_size
544 )
545  // Open in binary mode, which should also work for uncompressed files on Unix,
546  // but might break on Windowas, as it then does not do the line ending conversions.
547  // See https://github.com/mateidavid/zstr/issues/15
548  : StrictFStreamHolder<StrictIFStream>( filename, mode | std::ios_base::binary )
549  , std::istream( new GzipIStreambuf( file_stream_.rdbuf(), auto_detect, buffer_size ))
550 {
551  exceptions(std::ios_base::badbit);
552 }
553 
555 {
556  if (rdbuf()) {
557  delete rdbuf();
558  }
559 }
560 
561 // ================================================================================================
562 // Gzip Output File Stream
563 // ================================================================================================
564 
566  std::string const& filename,
567  std::ios_base::openmode mode,
568  GzipCompressionLevel level,
569  std::size_t buffer_size
570 )
571  : StrictFStreamHolder<StrictOFStream>( filename, mode | std::ios_base::binary )
572  , std::ostream( new GzipOStreambuf( file_stream_.rdbuf(), static_cast<int>(level), buffer_size ))
573 {
574  exceptions(std::ios_base::badbit);
575 }
576 
578 {
579  if (rdbuf()) {
580  delete rdbuf();
581  }
582 }
583 
585 {
586  std::ostream::flush();
587  file_stream_.flush();
588  return *this;
589 }
590 
591 // Up until here, we defined all classes needed for gzip streaming.
592 // However, if genesis is compiled without zlib support, we instead use dummy implementations
593 // which throw exceptions when being used.
594 #else // GENESIS_ZLIB
595 
596 // ================================================================================================
597 // Gzip Input Stream
598 // ================================================================================================
599 
600 GzipIStream::GzipIStream( std::istream&, bool, std::size_t )
601 {
602  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
603 }
604 
605 GzipIStream::GzipIStream( std::streambuf*, bool, std::size_t )
606 {
607  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
608 }
609 
611 {}
612 
613 // ================================================================================================
614 // Gzip Output Stream
615 // ================================================================================================
616 
617 GzipOStream::GzipOStream( std::ostream&, GzipCompressionLevel, std::size_t )
618 {
619  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
620 }
621 
622 GzipOStream::GzipOStream( std::streambuf*, GzipCompressionLevel, std::size_t )
623 {
624  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
625 }
626 
628 {}
629 
630 // ================================================================================================
631 // Gzip Input File Stream
632 // ================================================================================================
633 
635  std::string const&,
636  std::ios_base::openmode,
637  bool,
638  std::size_t
639 )
640  : StrictFStreamHolder<StrictIFStream>( "", std::ios_base::binary )
641 {
642  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
643 }
644 
646 {
647  // Nothing to do;
648 }
649 
650 // ================================================================================================
651 // Gzip Output File Stream
652 // ================================================================================================
653 
655  std::string const&,
656  std::ios_base::openmode,
658  std::size_t
659 )
660  : StrictFStreamHolder<StrictOFStream>( "", std::ios_base::binary )
661 {
662  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
663 }
664 
666 {
667  // Nothing to do;
668 }
669 
670 GzipOFStream& GzipOFStream::flush()
671 {
672  throw std::runtime_error( "zlib: Genesis was not compiled with zlib support." );
673 }
674 
675 #endif // GENESIS_ZLIB
676 
677 } // namespace utils
678 } // namespace genesis
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::utils::StrictFStreamHolder
Helper class template for managing the construction order between stream classes.
Definition: gzip_stream.hpp:233
genesis::utils::GzipOStream::~GzipOStream
virtual ~GzipOStream()
Definition: gzip_stream.cpp:530
genesis::utils::GzipCompressionLevel::kBestSpeed
@ kBestSpeed
genesis::utils::GzipOStream::GzipOStream
GzipOStream(std::ostream &os, GzipCompressionLevel level=GzipCompressionLevel::kDefaultCompression, std::size_t buffer_size=GZIP_DEFAULT_BUFFER_SIZE)
Definition: gzip_stream.cpp:518
genesis::utils::GzipIFStream::~GzipIFStream
virtual ~GzipIFStream()
Definition: gzip_stream.cpp:554
genesis::utils::GzipOFStream::flush
GzipOFStream & flush()
Flush, so one can save in the middle of writing a file for synchronization purposes.
Definition: gzip_stream.cpp:584
genesis::utils::GzipCompressionLevel
GzipCompressionLevel
List of possible compression levels used for GzipOStream.
Definition: gzip_stream.hpp:100
genesis::utils::GzipIStream::GzipIStream
GzipIStream(std::istream &is, bool auto_detect=true, std::size_t buffer_size=GZIP_DEFAULT_BUFFER_SIZE)
Definition: gzip_stream.cpp:483
genesis::utils::GzipCompressionLevel::kBestCompression
@ kBestCompression
genesis::utils::GZIP_DEFAULT_BUFFER_SIZE
static const std::size_t GZIP_DEFAULT_BUFFER_SIZE
Default buffer size for all gzip (de)compression buffers.
Definition: gzip_stream.hpp:116
genesis::utils::StrictFStreamHolder< StrictOFStream >::file_stream_
StrictOFStream file_stream_
Definition: gzip_stream.hpp:239
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: functions/genome_locus.hpp:48
genesis::utils::GzipOFStream::~GzipOFStream
virtual ~GzipOFStream()
Definition: gzip_stream.cpp:577
genesis::utils::StrictIFStream
Stream that defines a strict wrapper around std::ifstream.
Definition: strict_fstream.hpp:96
gzip_stream.hpp
genesis::utils::StrictOFStream
Stream that defines a strict wrapper around std::ofstream.
Definition: strict_fstream.hpp:133
genesis::utils::GzipIStream::~GzipIStream
virtual ~GzipIStream()
Definition: gzip_stream.cpp:495
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::GzipOFStream
Out file stream that offers on-the-fly gzip-compression.
Definition: gzip_stream.hpp:313
genesis::utils::GzipCompressionLevel::kNoCompression
@ kNoCompression
genesis::utils::GzipCompressionLevel::kDefaultCompression
@ kDefaultCompression
genesis::utils::GzipIFStream::GzipIFStream
GzipIFStream(std::string const &filename, std::ios_base::openmode mode=std::ios_base::in, bool auto_detect=true, std::size_t buffer_size=GZIP_DEFAULT_BUFFER_SIZE)
Definition: gzip_stream.cpp:539
genesis::utils::GzipOFStream::GzipOFStream
GzipOFStream(std::string const &filename, std::ios_base::openmode mode=std::ios_base::out, GzipCompressionLevel level=GzipCompressionLevel::kDefaultCompression, std::size_t buffer_size=GZIP_DEFAULT_BUFFER_SIZE)
Definition: gzip_stream.cpp:565