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