MFEM  v4.6.0
Finite element discretization library
zstr.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------
2 // Copyright 2015 Ontario Institute for Cancer Research
3 // Written by Matei David (matei@cs.toronto.edu)
4 //---------------------------------------------------------
5 
6 // Original version, https://github.com/mateidavid/zstr, distributed under MIT
7 // license. This file is a combination of the zstr.hpp and strict_fstream.hpp
8 // files in the original src/ directory with additional MFEM modifications.
9 
10 // The MIT License (MIT)
11 //
12 // Copyright (c) 2015 Matei David, Ontario Institute for Cancer Research
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to deal
16 // in the Software without restriction, including without limitation the rights
17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 // copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included in all
22 // copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 
32 // Reference:
33 // http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c
34 
35 #ifndef __ZSTR_HPP
36 #define __ZSTR_HPP
37 
38 #include "../config/config.hpp"
39 
40 #include <cassert>
41 #include <fstream>
42 #include <sstream>
43 #include <cstring>
44 #include <string>
45 
46 #ifdef MFEM_USE_ZLIB
47 #include <zlib.h>
48 #endif
49 
50 // The section below is a modified content of the src/strict_fstream.hpp
51 // file from https://github.com/mateidavid/zstr.
52 
53 /**
54  * This namespace defines wrappers for std::ifstream, std::ofstream, and
55  * std::fstream objects. The wrappers perform the following steps:
56  * - check the open modes make sense
57  * - check that the call to open() is successful
58  * - (for input streams) check that the opened file is peek-able
59  * - turn on the badbit in the exception mask
60  */
61 namespace strict_fstream
62 {
63 
64 // Overloaded error checks to handle POSIX and GNU strerror_r
65 inline char* check_strerror_r(int r, char* buff, size_t buff_size)
66 {
67  if (r) { snprintf(buff, buff_size, "unknown error: %d", r); }
68  return buff;
69 }
70 
71 inline char* check_strerror_r(char* r, char*, int)
72 {
73  return r;
74 }
75 
76 /// Overload of error-reporting function, to enable use with VS.
77 /// Ref: http://stackoverflow.com/a/901316/717706
78 static std::string strerror()
79 {
80  std::string buff(80, '\0');
81 #ifdef _WIN32
82  if (strerror_s(&buff[0], buff.size(), errno) != 0)
83  {
84  buff = "Unknown error";
85  }
86 #else
87  char* p = check_strerror_r(strerror_r(errno, &buff[0], buff.size()), &buff[0],
88  buff.size());
89  std::string tmp(p, std::strlen(p));
90  std::swap(buff, tmp);
91 #endif
92  buff.resize(buff.find('\0'));
93  return buff;
94 }
95 
96 /// Exception class thrown by failed operations.
97 class Exception
98  : public std::exception
99 {
100 public:
101  Exception(const std::string& msg_) : msg(msg_) {}
102  const char * what() const noexcept { return msg.c_str(); }
103 private:
104  std::string msg;
105 }; // class Exception
106 
107 namespace detail
108 {
109 
111 {
112  static std::string mode_to_string(std::ios_base::openmode mode)
113  {
114  static const int n_modes = 6;
115  static const std::ios_base::openmode mode_val_v[n_modes] =
116  {
117  std::ios_base::in,
119  std::ios_base::app,
120  std::ios_base::ate,
121  std::ios_base::trunc,
122  std::ios_base::binary
123  };
124 
125  static const char * mode_name_v[n_modes] =
126  {
127  "in",
128  "out",
129  "app",
130  "ate",
131  "trunc",
132  "binary"
133  };
134  std::string res;
135  for (int i = 0; i < n_modes; ++i)
136  {
137  if (mode & mode_val_v[i])
138  {
139  res += (! res.empty()? "|" : "");
140  res += mode_name_v[i];
141  }
142  }
143  if (res.empty()) { res = "none"; }
144  return res;
145  }
146  static void check_mode(const std::string& filename,
147  std::ios_base::openmode mode)
148  {
149  if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
150  {
151  throw Exception(std::string("strict_fstream: open('") + filename +
152  "'): mode error: trunc and not out");
153  }
154  else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
155  {
156  throw Exception(std::string("strict_fstream: open('") + filename +
157  "'): mode error: app and not out");
158  }
159  else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
160  {
161  throw Exception(std::string("strict_fstream: open('") + filename +
162  "'): mode error: trunc and app");
163  }
164  }
165  static void check_open(std::ios * s_p, const std::string& filename,
166  std::ios_base::openmode mode)
167  {
168  if (s_p->fail())
169  {
170  throw Exception(std::string("strict_fstream: open('")
171  + filename + "'," + mode_to_string(mode) + "): open failed: "
172  + strerror());
173  }
174  }
175  static void check_peek(std::istream * is_p, const std::string& filename,
176  std::ios_base::openmode mode)
177  {
178  bool peek_failed = true;
179  try
180  {
181  is_p->peek();
182  peek_failed = is_p->fail();
183  }
184  catch (std::ios_base::failure&) {}
185  if (peek_failed)
186  {
187  throw Exception(std::string("strict_fstream: open('")
188  + filename + "'," + mode_to_string(mode) + "): peek failed: "
189  + strerror());
190  }
191  is_p->clear();
192  }
193 }; // struct static_method_holder
194 
195 } // namespace detail
196 
197 class ifstream
198  : public std::ifstream
199 {
200 public:
201  ifstream() = default;
202  ifstream(const std::string& filename,
203  std::ios_base::openmode mode = std::ios_base::in)
204  {
205  open(filename, mode);
206  }
207  void open(const std::string& filename,
208  std::ios_base::openmode mode = std::ios_base::in)
209  {
210  mode |= std::ios_base::in;
211  exceptions(std::ios_base::badbit);
212  // detail::static_method_holder::check_mode(filename, mode);
213  std::ifstream::open(filename, mode);
214  // detail::static_method_holder::check_open(this, filename, mode);
215  // detail::static_method_holder::check_peek(this, filename, mode);
216  }
217 }; // class ifstream
218 
219 class ofstream
220  : public std::ofstream
221 {
222 public:
223  ofstream() = default;
224  ofstream(const std::string& filename,
225  std::ios_base::openmode mode = std::ios_base::out)
226  {
227  open(filename, mode);
228  }
229  void open(const std::string& filename,
230  std::ios_base::openmode mode = std::ios_base::out)
231  {
232  mode |= std::ios_base::out;
233  exceptions(std::ios_base::badbit);
234  // detail::static_method_holder::check_mode(filename, mode);
235  std::ofstream::open(filename, mode);
236  // detail::static_method_holder::check_open(this, filename, mode);
237  }
238 }; // class ofstream
239 
240 class fstream
241  : public std::fstream
242 {
243 public:
244  fstream() = default;
245  fstream(const std::string& filename,
246  std::ios_base::openmode mode = std::ios_base::in)
247  {
248  open(filename, mode);
249  }
250  void open(const std::string& filename,
251  std::ios_base::openmode mode = std::ios_base::in)
252  {
253  if (! (mode & std::ios_base::out)) { mode |= std::ios_base::in; }
254  exceptions(std::ios_base::badbit);
255  // detail::static_method_holder::check_mode(filename, mode);
256  std::fstream::open(filename, mode);
257  // detail::static_method_holder::check_open(this, filename, mode);
258  // detail::static_method_holder::check_peek(this, filename, mode);
259  }
260 }; // class fstream
261 
262 } // namespace strict_fstream
263 
264 
265 // The section below is a modified content of the src/zstr.hpp file from
266 // https://github.com/mateidavid/zstr.
267 
268 namespace zstr
269 {
270 #ifdef MFEM_USE_ZLIB
271 /// Exception class thrown by failed zlib operations.
273  : public std::exception
274 {
275 public:
276  Exception(z_stream *zstrm_p, int ret)
277  : msg("zlib: ")
278  {
279  switch (ret)
280  {
281  case Z_STREAM_ERROR:
282  msg += "Z_STREAM_ERROR: ";
283  break;
284  case Z_DATA_ERROR:
285  msg += "Z_DATA_ERROR: ";
286  break;
287  case Z_MEM_ERROR:
288  msg += "Z_MEM_ERROR: ";
289  break;
290  case Z_VERSION_ERROR:
291  msg += "Z_VERSION_ERROR: ";
292  break;
293  case Z_BUF_ERROR:
294  msg += "Z_BUF_ERROR: ";
295  break;
296  default:
297  std::ostringstream oss;
298  oss << ret;
299  msg += "[" + oss.str() + "]: ";
300  break;
301  }
302  msg += zstrm_p->msg;
303  }
304  Exception(const std::string msg_) : msg(msg_) {}
305  const char *what() const noexcept { return msg.c_str(); }
306 
307 private:
308  std::string msg;
309 }; // class Exception
310 #endif
311 
312 #ifdef MFEM_USE_ZLIB
313 namespace detail
314 {
316  : public z_stream
317 {
318 public:
319  z_stream_wrapper(bool is_input_ = true, int level_ = Z_DEFAULT_COMPRESSION)
320  : is_input(is_input_)
321  {
322  this->zalloc = Z_NULL;
323  this->zfree = Z_NULL;
324  this->opaque = Z_NULL;
325  int ret;
326  if (is_input)
327  {
328  this->avail_in = 0;
329  this->next_in = Z_NULL;
330  ret = inflateInit2(this, 15 + 32);
331  }
332  else
333  {
334  ret = deflateInit2(this, level_, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
335  }
336  if (ret != Z_OK)
337  {
338  throw Exception(this, ret);
339  }
340  }
342  {
343  if (is_input)
344  {
345  inflateEnd(this);
346  }
347  else
348  {
349  deflateEnd(this);
350  }
351  }
352 
353 private:
354  bool is_input;
355 }; // class z_stream_wrapper
356 
357 } // namespace detail
358 
360  : public std::streambuf
361 {
362 public:
363  istreambuf(std::streambuf *sbuf_p_,
364  std::size_t buff_size_ = default_buff_size, bool auto_detect_ = true)
365  : sbuf_p(sbuf_p_),
366  zstrm_p(nullptr),
367  buff_size(buff_size_),
368  auto_detect(auto_detect_),
369  auto_detect_run(false),
370  is_text(false)
371  {
372  assert(sbuf_p);
373  in_buff = new char[buff_size];
374  in_buff_start = in_buff;
375  in_buff_end = in_buff;
376  out_buff = new char[buff_size];
377  setg(out_buff, out_buff, out_buff);
378  }
379 
380  istreambuf(const istreambuf &) = delete;
381  istreambuf(istreambuf &&) = default;
382  istreambuf &operator=(const istreambuf &) = delete;
383  istreambuf &operator=(istreambuf &&) = default;
384 
385  virtual ~istreambuf()
386  {
387  delete[] in_buff;
388  delete[] out_buff;
389  if (zstrm_p)
390  {
391  delete zstrm_p;
392  }
393  }
394 
395  virtual std::streambuf::int_type underflow()
396  {
397  if (this->gptr() == this->egptr())
398  {
399  // pointers for free region in output buffer
400  char *out_buff_free_start = out_buff;
401  do
402  {
403  // read more input if none available
404  if (in_buff_start == in_buff_end)
405  {
406  // empty input buffer: refill from the start
407  in_buff_start = in_buff;
408  std::streamsize sz = sbuf_p->sgetn(in_buff, buff_size);
409  in_buff_end = in_buff + sz;
410  if (in_buff_end == in_buff_start)
411  {
412  break;
413  } // end of input
414  }
415  // auto detect if the stream contains text or deflate data
416  if (auto_detect && !auto_detect_run)
417  {
418  auto_detect_run = true;
419  unsigned char b0 = *reinterpret_cast<unsigned char *>(in_buff_start);
420  unsigned char b1 = *reinterpret_cast<unsigned char *>(in_buff_start + 1);
421  // Ref:
422  // http://en.wikipedia.org/wiki/Gzip
423  // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
424  is_text = !(in_buff_start + 2 <= in_buff_end && ((b0 == 0x1F &&
425  b1 == 0x8B) // gzip header
426  || (b0 == 0x78 && (b1 == 0x01 // zlib header
427  || b1 == 0x9C || b1 == 0xDA))));
428  }
429  if (is_text)
430  {
431  // simply swap in_buff and out_buff, and adjust pointers
432  assert(in_buff_start == in_buff);
433  std::swap(in_buff, out_buff);
434  out_buff_free_start = in_buff_end;
435  in_buff_start = in_buff;
436  in_buff_end = in_buff;
437  }
438  else
439  {
440  // run inflate() on input
441  if (!zstrm_p)
442  {
443  zstrm_p = new detail::z_stream_wrapper(true);
444  }
445  zstrm_p->next_in = reinterpret_cast<decltype(zstrm_p->next_in)>(in_buff_start);
446  zstrm_p->avail_in = in_buff_end - in_buff_start;
447  zstrm_p->next_out = reinterpret_cast<decltype(zstrm_p->next_out)>
448  (out_buff_free_start);
449  zstrm_p->avail_out = (out_buff + buff_size) - out_buff_free_start;
450  int ret = inflate(zstrm_p, Z_NO_FLUSH);
451  // process return code
452  if (ret != Z_OK && ret != Z_STREAM_END)
453  {
454  throw Exception(zstrm_p, ret);
455  }
456  // update in&out pointers following inflate()
457  in_buff_start = reinterpret_cast<decltype(in_buff_start)>(zstrm_p->next_in);
458  in_buff_end = in_buff_start + zstrm_p->avail_in;
459  out_buff_free_start = reinterpret_cast<decltype(out_buff_free_start)>
460  (zstrm_p->next_out);
461  assert(out_buff_free_start + zstrm_p->avail_out == out_buff + buff_size);
462  // if stream ended, deallocate inflator
463  if (ret == Z_STREAM_END)
464  {
465  delete zstrm_p;
466  zstrm_p = nullptr;
467  }
468  }
469  }
470  while (out_buff_free_start == out_buff);
471  // 2 exit conditions:
472  // - end of input: there might or might not be output available
473  // - out_buff_free_start != out_buff: output available
474  this->setg(out_buff, out_buff, out_buff_free_start);
475  }
476  return this->gptr() == this->egptr()
477  ? traits_type::eof()
478  : traits_type::to_int_type(*this->gptr());
479  }
480 
481 private:
482  std::streambuf *sbuf_p;
483  char *in_buff;
484  char *in_buff_start;
485  char *in_buff_end;
486  char *out_buff;
487  detail::z_stream_wrapper *zstrm_p;
488  std::size_t buff_size;
489  bool auto_detect;
490  bool auto_detect_run;
491  bool is_text;
492 
493  static const std::size_t default_buff_size = (std::size_t)1 << 20;
494 }; // class istreambuf
495 
497  : public std::streambuf
498 {
499 public:
500  ostreambuf(std::streambuf *sbuf_p_,
501  std::size_t buff_size_ = default_buff_size, int level_ = Z_DEFAULT_COMPRESSION)
502  : sbuf_p(sbuf_p_),
503  zstrm_p(new detail::z_stream_wrapper(false, level_)),
504  buff_size(buff_size_)
505  {
506  assert(sbuf_p);
507  in_buff = new char[buff_size];
508  out_buff = new char[buff_size];
509  setp(in_buff, in_buff + buff_size);
510  }
511 
512  ostreambuf(const ostreambuf &) = delete;
513  ostreambuf(ostreambuf &&) = default;
514  ostreambuf &operator=(const ostreambuf &) = delete;
515  ostreambuf &operator=(ostreambuf &&) = default;
516 
517  int deflate_loop(int flush)
518  {
519  while (true)
520  {
521  zstrm_p->next_out = reinterpret_cast<decltype(zstrm_p->next_out)>(out_buff);
522  zstrm_p->avail_out = buff_size;
523  int ret = deflate(zstrm_p, flush);
524  if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR)
525  {
526  throw Exception(zstrm_p, ret);
527  }
528  std::streamsize sz = sbuf_p->sputn(out_buff,
529  reinterpret_cast<decltype(out_buff)>(zstrm_p->next_out) - out_buff);
530  if (sz != reinterpret_cast<decltype(out_buff)>(zstrm_p->next_out) - out_buff)
531  {
532  // there was an error in the sink stream
533  return -1;
534  }
535  if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0)
536  {
537  break;
538  }
539  }
540  return 0;
541  }
542 
543  virtual ~ostreambuf()
544  {
545  // flush the zlib stream
546  //
547  // NOTE: Errors here (sync() return value not 0) are ignored, because we
548  // cannot throw in a destructor. This mirrors the behaviour of
549  // std::basic_filebuf::~basic_filebuf(). To see an exception on error,
550  // close the ofstream with an explicit call to close(), and do not rely
551  // on the implicit call in the destructor.
552  //
553  sync();
554  delete[] in_buff;
555  delete[] out_buff;
556  delete zstrm_p;
557  }
558  virtual std::streambuf::int_type overflow(std::streambuf::int_type c =
559  traits_type::eof())
560  {
561  zstrm_p->next_in = reinterpret_cast<decltype(zstrm_p->next_in)>(pbase());
562  zstrm_p->avail_in = pptr() - pbase();
563  while (zstrm_p->avail_in > 0)
564  {
565  int r = deflate_loop(Z_NO_FLUSH);
566  if (r != 0)
567  {
568  setp(nullptr, nullptr);
569  return traits_type::eof();
570  }
571  }
572  setp(in_buff, in_buff + buff_size);
573  return traits_type::eq_int_type(c,
574  traits_type::eof())
575  ? traits_type::eof()
576  : sputc(c);
577  }
578  virtual int sync()
579  {
580  // first, call overflow to clear in_buff
581  overflow();
582  if (!pptr())
583  {
584  return -1;
585  }
586  // then, call deflate asking to finish the zlib stream
587  zstrm_p->next_in = nullptr;
588  zstrm_p->avail_in = 0;
589  if (deflate_loop(Z_FINISH) != 0)
590  {
591  return -1;
592  }
593  deflateReset(zstrm_p);
594  return 0;
595  }
596 
597 private:
598  std::streambuf *sbuf_p;
599  char *in_buff;
600  char *out_buff;
601  detail::z_stream_wrapper *zstrm_p;
602  std::size_t buff_size;
603 
604  static const std::size_t default_buff_size = (std::size_t)1 << 20;
605 }; // class ostreambuf
606 
607 class istream
608  : public std::istream
609 {
610 public:
611  istream(std::istream &is)
612  : std::istream(new istreambuf(is.rdbuf()))
613  {
614  exceptions(std::ios_base::badbit);
615  }
616  explicit istream(std::streambuf *sbuf_p)
617  : std::istream(new istreambuf(sbuf_p))
618  {
619  exceptions(std::ios_base::badbit);
620  }
621  virtual ~istream()
622  {
623  delete rdbuf();
624  }
625 }; // class istream
626 
627 class ostream
628  : public std::ostream
629 {
630 public:
631  ostream(std::ostream &os)
632  : std::ostream(new ostreambuf(os.rdbuf()))
633  {
634  exceptions(std::ios_base::badbit);
635  }
636  explicit ostream(std::streambuf *sbuf_p)
637  : std::ostream(new ostreambuf(sbuf_p))
638  {
639  exceptions(std::ios_base::badbit);
640  }
641  virtual ~ostream()
642  {
643  delete rdbuf();
644  }
645 }; // class ostream
646 #endif
647 
648 namespace detail
649 {
650 
651 template <typename FStream_Type>
653 {
654  strict_fstream_holder(const std::string &filename,
655  std::ios_base::openmode mode = std::ios_base::in)
656  : fs_(filename, mode)
657  {
658  }
659  FStream_Type fs_;
660 }; // class strict_fstream_holder
661 
662 } // namespace detail
663 
664 #ifdef MFEM_USE_ZLIB
665 class ifstream
666  : private detail::strict_fstream_holder<strict_fstream::ifstream>,
667  public std::istream
668 {
669 public:
670  explicit ifstream(const std::string &filename,
671  std::ios_base::openmode mode = std::ios_base::in)
672  : detail::strict_fstream_holder<strict_fstream::ifstream>(filename, mode),
673  std::istream(new istreambuf(fs_.rdbuf()))
674  {
675  exceptions(std::ios_base::badbit);
676  }
677  virtual ~ifstream()
678  {
679  if (rdbuf())
680  {
681  delete rdbuf();
682  }
683  }
684 }; // class ifstream
685 
686 class ofstream
687  : private detail::strict_fstream_holder<strict_fstream::ofstream>,
688  public std::ostream
689 {
690 public:
691  explicit ofstream(const std::string &filename,
692  std::ios_base::openmode mode = std::ios_base::out)
693  : detail::strict_fstream_holder<strict_fstream::ofstream>(filename,
694  mode | std::ios_base::binary),
695  std::ostream(new ostreambuf(fs_.rdbuf()))
696  {
697  exceptions(std::ios_base::badbit);
698  }
699  virtual ~ofstream()
700  {
701  if (rdbuf())
702  {
703  delete rdbuf();
704  }
705  }
706 }; // class ofstream
707 #endif
708 
709 } // namespace zstr
710 
711 
712 // The section below contains MFEM-specific additions.
713 
714 namespace mfem
715 {
716 
718  : private zstr::detail::strict_fstream_holder<strict_fstream::ofstream>,
719  public std::ostream
720 {
721 public:
722  explicit ofgzstream(const std::string &filename,
723  bool compression = false)
724  : zstr::detail::strict_fstream_holder<strict_fstream::ofstream>(filename,
725  std::ios_base::binary),
726  std::ostream(nullptr)
727  {
728 #ifdef MFEM_USE_ZLIB
729  if (compression)
730  {
731  strbuf = new zstr::ostreambuf(fs_.rdbuf());
732  rdbuf(strbuf);
733  }
734  else
735 #endif
736  {
737  rdbuf(fs_.rdbuf());
738  }
739  exceptions(std::ios_base::badbit);
740  }
741 
742  explicit ofgzstream(const std::string &filename,
743  char const *open_mode_chars)
744  : zstr::detail::strict_fstream_holder<strict_fstream::ofstream>(filename,
745  std::ios_base::binary),
746  std::ostream(nullptr)
747  {
748 #ifdef MFEM_USE_ZLIB
749  // If open_mode_chars contains any combination of open mode chars
750  // containing the 'z' char, compression is enabled. This preserves the
751  // behavior of the old interface but ignores the choice of the compression
752  // level (it is always set to 6).
753  if (std::string(open_mode_chars).find('z') != std::string::npos)
754  {
755  strbuf = new zstr::ostreambuf(fs_.rdbuf());
756  rdbuf(strbuf);
757  }
758  else
759 #endif
760  {
761  rdbuf(fs_.rdbuf());
762  }
763  setstate(fs_.rdstate());
764  exceptions(std::ios_base::badbit);
765  }
766 
767  virtual ~ofgzstream()
768  {
769  delete strbuf;
770  }
771 
772  std::streambuf *strbuf = nullptr;
773 };
774 
776  : private zstr::detail::strict_fstream_holder<strict_fstream::ifstream>,
777  public std::istream
778 {
779 public:
780  explicit ifgzstream(const std::string &filename)
781  : zstr::detail::strict_fstream_holder<strict_fstream::ifstream>(filename,
782  std::ios_base::in),
783  std::istream(nullptr)
784  {
785 #ifdef MFEM_USE_ZLIB
786  strbuf = new zstr::istreambuf(fs_.rdbuf());
787  rdbuf(strbuf);
788 #else
789  rdbuf(fs_.rdbuf());
790 #endif
791  setstate(fs_.rdstate());
792  exceptions(std::ios_base::badbit);
793  }
794 
795  virtual ~ifgzstream()
796  {
797  delete strbuf;
798  }
799 
800  std::streambuf *strbuf = nullptr;
801 };
802 
803 /// Input file stream that remembers the input file name (useful for example
804 /// when reading NetCDF meshes) and supports optional zlib decompression.
806 {
807 public:
808  named_ifgzstream(const std::string &mesh_name) : ifgzstream(mesh_name),
809  filename(mesh_name) {}
810 
811  const std::string filename;
812 };
813 
814 } // namespace mfem
815 
816 #endif
char * check_strerror_r(int r, char *buff, size_t buff_size)
Definition: zstr.hpp:65
static void check_peek(std::istream *is_p, const std::string &filename, std::ios_base::openmode mode)
Definition: zstr.hpp:175
const char * what() const noexcept
Definition: zstr.hpp:305
ofstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
Definition: zstr.hpp:224
std::streambuf * strbuf
Definition: zstr.hpp:772
const char * what() const noexcept
Definition: zstr.hpp:102
virtual std::streambuf::int_type underflow()
Definition: zstr.hpp:395
virtual ~ifstream()
Definition: zstr.hpp:677
virtual int sync()
Definition: zstr.hpp:578
ifgzstream(const std::string &filename)
Definition: zstr.hpp:780
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:207
istream(std::istream &is)
Definition: zstr.hpp:611
STL namespace.
Exception class thrown by failed zlib operations.
Definition: zstr.hpp:272
ostreambuf(std::streambuf *sbuf_p_, std::size_t buff_size_=default_buff_size, int level_=Z_DEFAULT_COMPRESSION)
Definition: zstr.hpp:500
fstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:245
std::streambuf * strbuf
Definition: zstr.hpp:800
ifstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:202
virtual ~istream()
Definition: zstr.hpp:621
Exception(z_stream *zstrm_p, int ret)
Definition: zstr.hpp:276
named_ifgzstream(const std::string &mesh_name)
Definition: zstr.hpp:808
istreambuf(std::streambuf *sbuf_p_, std::size_t buff_size_=default_buff_size, bool auto_detect_=true)
Definition: zstr.hpp:363
virtual ~ostream()
Definition: zstr.hpp:641
virtual ~ostreambuf()
Definition: zstr.hpp:543
ostreambuf & operator=(const ostreambuf &)=delete
Exception(const std::string msg_)
Definition: zstr.hpp:304
ostream(std::streambuf *sbuf_p)
Definition: zstr.hpp:636
int deflate_loop(int flush)
Definition: zstr.hpp:517
static void check_mode(const std::string &filename, std::ios_base::openmode mode)
Definition: zstr.hpp:146
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
Definition: zstr.hpp:229
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:250
Definition: zstr.hpp:268
ostream(std::ostream &os)
Definition: zstr.hpp:631
istreambuf & operator=(const istreambuf &)=delete
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
virtual ~istreambuf()
Definition: zstr.hpp:385
ifstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:670
virtual std::streambuf::int_type overflow(std::streambuf::int_type c=traits_type::eof())
Definition: zstr.hpp:558
virtual ~ifgzstream()
Definition: zstr.hpp:795
ofgzstream(const std::string &filename, bool compression=false)
Definition: zstr.hpp:722
ofstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
Definition: zstr.hpp:691
Exception(const std::string &msg_)
Definition: zstr.hpp:101
static std::string mode_to_string(std::ios_base::openmode mode)
Definition: zstr.hpp:112
istream(std::streambuf *sbuf_p)
Definition: zstr.hpp:616
virtual ~ofstream()
Definition: zstr.hpp:699
z_stream_wrapper(bool is_input_=true, int level_=Z_DEFAULT_COMPRESSION)
Definition: zstr.hpp:319
strict_fstream_holder(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Definition: zstr.hpp:654
const std::string filename
Definition: zstr.hpp:811
Exception class thrown by failed operations.
Definition: zstr.hpp:97
virtual ~ofgzstream()
Definition: zstr.hpp:767
ofgzstream(const std::string &filename, char const *open_mode_chars)
Definition: zstr.hpp:742
static void check_open(std::ios *s_p, const std::string &filename, std::ios_base::openmode mode)
Definition: zstr.hpp:165