NDDEM
gzip.hpp
Go to the documentation of this file.
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 // Contains the definitions of the class templates gzip_compressor and
9 // gzip_decompressor for reading and writing files in the gzip file format
10 // (RFC 1952). Based in part on work of Jonathan de Halleux; see [...]
11 
12 #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
13 #define BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
14 
15 #if defined(_MSC_VER)
16 # pragma once
17 #endif
18 
19 #include <boost/config.hpp> // STATIC_CONSTANT, STDC_NAMESPACE,
20  // DINKUMWARE_STDLIB, __STL_CONFIG_H.
21 #include <algorithm> // min.
22 #include <boost/assert.hpp>
23 #include <cstdio> // EOF.
24 #include <cstddef> // size_t.
25 #include <ctime> // std::time_t.
26 #include <memory> // allocator.
27 #include <boost/config.hpp> // Put size_t in std.
28 #include <boost/detail/workaround.hpp>
29 #include <boost/cstdint.hpp> // uint8_t, uint32_t.
30 #include <boost/iostreams/checked_operations.hpp>
31 #include <boost/iostreams/constants.hpp> // buffer size.
32 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
33 #include <boost/iostreams/detail/adapter/range_adapter.hpp>
34 #include <boost/iostreams/detail/char_traits.hpp>
35 #include <boost/iostreams/detail/ios.hpp> // failure, streamsize.
36 #include <boost/iostreams/detail/error.hpp>
37 #include <boost/iostreams/operations.hpp>
38 #include <boost/iostreams/device/back_inserter.hpp>
39 #include <boost/iostreams/filter/zlib.hpp>
40 #include <boost/iostreams/pipeline.hpp>
41 #include <boost/iostreams/putback.hpp>
42 #include <boost/throw_exception.hpp>
43 
44 // Must come last.
45 #if defined(BOOST_MSVC)
46 # pragma warning(push)
47 # pragma warning(disable:4244) // Possible truncation
48 # pragma warning(disable:4251) // Missing DLL interface for std::string
49 # pragma warning(disable:4309) // Truncation of constant value.
50 #endif
51 
52 #ifdef BOOST_NO_STDC_NAMESPACE
53 namespace std { using ::time_t; }
54 #endif
55 
56 namespace boost { namespace iostreams {
57 
58 //------------------Definitions of constants----------------------------------//
59 
60 namespace gzip {
61 
62 using namespace boost::iostreams::zlib;
63 
64  // Error codes used by gzip_error.
65 
66 const int zlib_error = 1;
67 const int bad_crc = 2; // Recorded crc doesn't match data.
68 const int bad_length = 3; // Recorded length doesn't match data.
69 const int bad_header = 4; // Malformed header.
70 const int bad_footer = 5; // Malformed footer.
71 const int bad_method = 6; // Unsupported compression method.
72 
73 namespace magic {
74 
75  // Magic numbers used by gzip header.
76 
77 const int id1 = 0x1f;
78 const int id2 = 0x8b;
79 
80 } // End namespace magic.
81 
82 namespace method {
83 
84  // Codes used for the 'CM' byte of the gzip header.
85 
86 const int deflate = 8;
87 
88 } // End namespace method.
89 
90 namespace flags {
91 
92  // Codes used for the 'FLG' byte of the gzip header.
93 
94 const int text = 1;
95 const int header_crc = 2;
96 const int extra = 4;
97 const int name = 8;
98 const int comment = 16;
99 
100 } // End namespace flags.
101 
102 namespace extra_flags {
103 
104  // Codes used for the 'XFL' byte of the gzip header.
105 
106 const int best_compression = 2;
107 const int best_speed = 4;
108 
109 } // End namespace extra_flags.
110 
111  // Codes used for the 'OS' byte of the gzip header.
112 
113 const int os_fat = 0;
114 const int os_amiga = 1;
115 const int os_vms = 2;
116 const int os_unix = 3;
117 const int os_vm_cms = 4;
118 const int os_atari = 5;
119 const int os_hpfs = 6;
120 const int os_macintosh = 7;
121 const int os_z_system = 8;
122 const int os_cp_m = 9;
123 const int os_tops_20 = 10;
124 const int os_ntfs = 11;
125 const int os_qdos = 12;
126 const int os_acorn = 13;
127 const int os_unknown = 255;
128 
129 } // End namespace gzip.
130 
131 //------------------Definition of gzip_params---------------------------------//
132 
133 //
134 // Class name: gzip_params.
135 // Description: Subclass of zlib_params with an additional field
136 // representing a file name.
137 //
138 struct gzip_params : zlib_params {
139 
140  // Non-explicit constructor.
141  gzip_params( int level = gzip::default_compression,
142  int method = gzip::deflated,
143  int window_bits = gzip::default_window_bits,
144  int mem_level = gzip::default_mem_level,
145  int strategy = gzip::default_strategy,
146  std::string file_name_ = "",
147  std::string comment_ = "",
148  std::time_t mtime_ = 0 )
149  : zlib_params(level, method, window_bits, mem_level, strategy),
150  file_name(file_name_), comment(comment_), mtime(mtime_)
151  { }
152  std::string file_name;
153  std::string comment;
154  std::time_t mtime;
155 };
156 
157 //------------------Definition of gzip_error----------------------------------//
158 
159 //
160 // Class name: gzip_error.
161 // Description: Subclass of std::ios_base::failure thrown to indicate
162 // zlib errors other than out-of-memory conditions.
163 //
164 class gzip_error : public BOOST_IOSTREAMS_FAILURE {
165 public:
166  explicit gzip_error(int error)
167  : BOOST_IOSTREAMS_FAILURE("gzip error"),
168  error_(error), zlib_error_code_(zlib::okay) { }
169  explicit gzip_error(const zlib_error& e)
170  : BOOST_IOSTREAMS_FAILURE("gzip error"),
171  error_(gzip::zlib_error), zlib_error_code_(e.error())
172  { }
173  int error() const { return error_; }
174  int zlib_error_code() const { return zlib_error_code_; }
175 private:
176  int error_;
177  int zlib_error_code_;
178 };
179 
180 //------------------Definition of gzip_compressor-----------------------------//
181 
182 //
183 // Template name: gzip_compressor
184 // Description: Model of OutputFilter implementing compression in the
185 // gzip format.
186 //
187 template<typename Alloc = std::allocator<char> >
188 class basic_gzip_compressor : basic_zlib_compressor<Alloc> {
189 private:
190  typedef basic_zlib_compressor<Alloc> base_type;
191 public:
192  typedef char char_type;
193  struct category
194  : dual_use,
195  filter_tag,
196  multichar_tag,
197  closable_tag
198  { };
199  basic_gzip_compressor( const gzip_params& = gzip::default_compression,
200  std::streamsize buffer_size = default_device_buffer_size );
201 
202  template<typename Source>
203  std::streamsize read(Source& src, char_type* s, std::streamsize n)
204  {
205  std::streamsize result = 0;
206 
207  // Read header.
208  if (!(flags_ & f_header_done))
209  result += read_string(s, n, header_);
210 
211  // Read body.
212  if (!(flags_ & f_body_done)) {
213 
214  // Read from basic_zlib_filter.
215  std::streamsize amt = base_type::read(src, s + result, n - result);
216  if (amt != -1) {
217  result += amt;
218  if (amt < n - result) { // Double-check for EOF.
219  amt = base_type::read(src, s + result, n - result);
220  if (amt != -1)
221  result += amt;
222  }
223  }
224  if (amt == -1)
225  prepare_footer();
226  }
227 
228  // Read footer.
229  if ((flags_ & f_body_done) != 0 && result < n)
230  result += read_string(s + result, n - result, footer_);
231 
232  return result != 0 ? result : -1;
233  }
234 
235  template<typename Sink>
236  std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
237  {
238  if (!(flags_ & f_header_done)) {
239  std::streamsize amt =
240  static_cast<std::streamsize>(header_.size() - offset_);
241  offset_ += boost::iostreams::write_if(snk, header_.data() + offset_, amt);
242  if (offset_ == header_.size())
243  flags_ |= f_header_done;
244  else
245  return 0;
246  }
247  return base_type::write(snk, s, n);
248  }
249 
250  template<typename Sink>
251  void close(Sink& snk, BOOST_IOS::openmode m)
252  {
253  try {
254  if (m == BOOST_IOS::out && !(flags_ & f_header_done))
255  this->write(snk, 0, 0);
256 
257  // Close zlib compressor.
258  base_type::close(snk, m);
259 
260  if (m == BOOST_IOS::out) {
261  if (flags_ & f_header_done) {
262 
263  // Write final fields of gzip file format.
264  write_long(this->crc(), snk);
265  write_long(this->total_in(), snk);
266  }
267  }
268  } catch(...) {
269  close_impl();
270  throw;
271  }
272  close_impl();
273  }
274 private:
275  static gzip_params normalize_params(gzip_params p);
276  void prepare_footer();
277  std::streamsize read_string(char* s, std::streamsize n, std::string& str);
278 
279  template<typename Sink>
280  static void write_long(long n, Sink& next, boost::mpl::true_)
281  {
282  boost::iostreams::put(next, static_cast<char>(0xFF & n));
283  boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 8)));
284  boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 16)));
285  boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 24)));
286  }
287  template<typename Sink>
288  static void write_long(long, Sink&, boost::mpl::false_)
289  {
290  }
291  template<typename Sink>
292  static void write_long(long n, Sink& next)
293  {
294  typedef typename category_of<Sink>::type category;
295  typedef is_convertible<category, output> can_write;
296  write_long(n, next, can_write());
297  }
298 
299  void close_impl()
300  {
301  footer_.clear();
302  offset_ = 0;
303  flags_ = 0;
304  }
305 
306  enum state_type {
307  f_header_done = 1,
308  f_body_done = f_header_done << 1,
309  f_footer_done = f_body_done << 1
310  };
311  std::string header_;
312  std::string footer_;
313  std::size_t offset_;
314  int flags_;
315 };
316 BOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1)
317 
318 typedef basic_gzip_compressor<> gzip_compressor;
319 
320 //------------------Definition of helper templates for decompression----------//
321 
322 namespace detail {
323 
324 // Processes gzip headers
325 class BOOST_IOSTREAMS_DECL gzip_header {
326 public:
327  gzip_header() { reset(); }
328 
329  // Members for processing header data
330  void process(char c);
331  bool done() const { return state_ == s_done; }
332  void reset();
333 
334  // Members for accessing header data
335  std::string file_name() const { return file_name_; }
336  std::string comment() const { return comment_; }
337  bool text() const { return (flags_ & gzip::flags::text) != 0; }
338  int os() const { return os_; }
339  std::time_t mtime() const { return mtime_; }
340 private:
341  enum state_type {
342  s_id1 = 1,
343  s_id2 = s_id1 + 1,
344  s_cm = s_id2 + 1,
345  s_flg = s_cm + 1,
346  s_mtime = s_flg + 1,
347  s_xfl = s_mtime + 1,
348  s_os = s_xfl + 1,
349  s_xlen = s_os + 1,
350  s_extra = s_xlen + 1,
351  s_name = s_extra + 1,
352  s_comment = s_name + 1,
353  s_hcrc = s_comment + 1,
354  s_done = s_hcrc + 1
355  };
356  std::string file_name_;
357  std::string comment_;
358  int os_;
359  std::time_t mtime_;
360  int flags_;
361  int state_;
362  int offset_; // Offset within fixed-length region.
363  int xlen_; // Bytes remaining in extra field.
364 };
365 
366 // Processes gzip footers
367 class BOOST_IOSTREAMS_DECL gzip_footer {
368 public:
369  gzip_footer() { reset(); }
370 
371  // Members for processing footer data
372  void process(char c);
373  bool done() const { return state_ == s_done; }
374  void reset();
375 
376  // Members for accessing footer data
377  zlib::ulong crc() const { return crc_; }
378  zlib::ulong uncompressed_size() const { return isize_; }
379 private:
380  enum state_type {
381  s_crc = 1,
382  s_isize = s_crc + 1,
383  s_done = s_isize + 1
384  };
385  zlib::ulong crc_;
386  zlib::ulong isize_;
387  int state_;
388  int offset_;
389 };
390 
391 } // End namespace boost::iostreams::detail.
392 
393 //------------------Definition of basic_gzip_decompressor---------------------//
394 
395 //
396 // Template name: basic_gzip_decompressor
397 // Description: Model of InputFilter implementing compression in the
398 // gzip format.
399 //
400 template<typename Alloc = std::allocator<char> >
401 class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> {
402 private:
403  typedef basic_zlib_decompressor<Alloc> base_type;
404  typedef typename base_type::string_type string_type;
405 public:
406  typedef char char_type;
407  struct category
408  : dual_use,
409  filter_tag,
410  multichar_tag,
411  closable_tag
412  { };
413  basic_gzip_decompressor( int window_bits = gzip::default_window_bits,
414  std::streamsize buffer_size = default_device_buffer_size );
415 
416  template<typename Sink>
417  std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
418  {
419  std::streamsize result = 0;
420  while(result < n) {
421  if(state_ == s_start) {
422  state_ = s_header;
423  header_.reset();
424  footer_.reset();
425  }
426  if (state_ == s_header) {
427  int c = s[result++];
428  header_.process(c);
429  if (header_.done())
430  state_ = s_body;
431  } else if (state_ == s_body) {
432  try {
433  std::streamsize amt =
434  base_type::write(snk, s + result, n - result);
435  result += amt;
436  if (!this->eof()) {
437  break;
438  } else {
439  state_ = s_footer;
440  }
441  } catch (const zlib_error& e) {
442  boost::throw_exception(gzip_error(e));
443  }
444  } else { // state_ == s_footer
445  if (footer_.done()) {
446  if (footer_.crc() != this->crc())
447  boost::throw_exception(gzip_error(gzip::bad_crc));
448 
449  base_type::close(snk, BOOST_IOS::out);
450  state_ = s_start;
451  } else {
452  int c = s[result++];
453  footer_.process(c);
454  }
455  }
456  }
457  return result;
458  }
459 
460  template<typename Source>
461  std::streamsize read(Source& src, char_type* s, std::streamsize n)
462  {
463  typedef char_traits<char> traits_type;
464  std::streamsize result = 0;
465  peekable_source<Source> peek(src, putback_);
466  while (result < n && state_ != s_done) {
467  if (state_ == s_start) {
468  state_ = s_header;
469  header_.reset();
470  footer_.reset();
471  }
472  if (state_ == s_header) {
473  int c = boost::iostreams::get(peek);
474  if (traits_type::is_eof(c)) {
475  boost::throw_exception(gzip_error(gzip::bad_header));
476  } else if (traits_type::would_block(c)) {
477  break;
478  }
479  header_.process(c);
480  if (header_.done())
481  state_ = s_body;
482  } else if (state_ == s_body) {
483  try {
484  std::streamsize amt =
485  base_type::read(peek, s + result, n - result);
486  if (amt != -1) {
487  result += amt;
488  if (amt < n - result)
489  break;
490  } else {
491  peek.putback(this->unconsumed_input());
492  state_ = s_footer;
493  }
494  } catch (const zlib_error& e) {
495  boost::throw_exception(gzip_error(e));
496  }
497  } else { // state_ == s_footer
498  int c = boost::iostreams::get(peek);
499  if (traits_type::is_eof(c)) {
500  boost::throw_exception(gzip_error(gzip::bad_footer));
501  } else if (traits_type::would_block(c)) {
502  break;
503  }
504  footer_.process(c);
505  if (footer_.done()) {
506  if (footer_.crc() != this->crc())
507  boost::throw_exception(gzip_error(gzip::bad_crc));
508  c = boost::iostreams::get(peek);
509  if (traits_type::is_eof(c)) {
510  state_ = s_done;
511  } else {
512  peek.putback(c);
513  base_type::close(peek, BOOST_IOS::in);
514  state_ = s_start;
515  header_.reset();
516  footer_.reset();
517  }
518  }
519  }
520  }
521  if (peek.has_unconsumed_input()) {
522  putback_ = peek.unconsumed_input();
523  } else {
524  putback_.clear();
525  }
526  return result != 0 || state_ != s_done ?
527  result :
528  -1;
529  }
530 
531  template<typename Source>
532  void close(Source& src, BOOST_IOS::openmode m)
533  {
534  try {
535  base_type::close(src, m);
536  } catch (const zlib_error& e) {
537  state_ = s_start;
538  boost::throw_exception(gzip_error(e));
539  }
540  if (m == BOOST_IOS::out) {
541  if (state_ == s_start || state_ == s_header)
542  boost::throw_exception(gzip_error(gzip::bad_header));
543  else if (state_ == s_body)
544  boost::throw_exception(gzip_error(gzip::bad_footer));
545  else if (state_ == s_footer) {
546  if (!footer_.done())
547  boost::throw_exception(gzip_error(gzip::bad_footer));
548  else if(footer_.crc() != this->crc())
549  boost::throw_exception(gzip_error(gzip::bad_crc));
550  } else {
551  BOOST_ASSERT(!"Bad state");
552  }
553  }
554  state_ = s_start;
555  }
556 
557  std::string file_name() const { return header_.file_name(); }
558  std::string comment() const { return header_.comment(); }
559  bool text() const { return header_.text(); }
560  int os() const { return header_.os(); }
561  std::time_t mtime() const { return header_.mtime(); }
562 private:
563  static gzip_params make_params(int window_bits);
564 
565  // Source adapter allowing an arbitrary character sequence to be put back.
566  template<typename Source>
567  struct peekable_source {
568  typedef char char_type;
569  struct category : source_tag, peekable_tag { };
570  explicit peekable_source(Source& src, const string_type& putback = "")
571  : src_(src), putback_(putback), offset_(0)
572  { }
573  std::streamsize read(char* s, std::streamsize n)
574  {
575  std::streamsize result = 0;
576 
577  // Copy characters from putback buffer
578  std::streamsize pbsize =
579  static_cast<std::streamsize>(putback_.size());
580  if (offset_ < pbsize) {
581  result = (std::min)(n, pbsize - offset_);
582  BOOST_IOSTREAMS_CHAR_TRAITS(char)::copy(
583  s, putback_.data() + offset_, result);
584  offset_ += result;
585  if (result == n)
586  return result;
587  }
588 
589  // Read characters from src_
590  std::streamsize amt =
591  boost::iostreams::read(src_, s + result, n - result);
592  return amt != -1 ?
593  result + amt :
594  result ? result : -1;
595  }
596  bool putback(char c)
597  {
598  if (offset_) {
599  putback_[--offset_] = c;
600  } else {
601  boost::throw_exception(
602  boost::iostreams::detail::bad_putback());
603  }
604  return true;
605  }
606  void putback(const string_type& s)
607  {
608  putback_.replace(0, offset_, s);
609  offset_ = 0;
610  }
611 
612  // Returns true if some characters have been putback but not re-read.
613  bool has_unconsumed_input() const
614  {
615  return offset_ < static_cast<std::streamsize>(putback_.size());
616  }
617 
618  // Returns the sequence of characters that have been put back but not re-read.
619  string_type unconsumed_input() const
620  {
621  return string_type(putback_, offset_, putback_.size() - offset_);
622  }
623  Source& src_;
624  string_type putback_;
625  std::streamsize offset_;
626  };
627 
628  enum state_type {
629  s_start = 1,
630  s_header = s_start + 1,
631  s_body = s_header + 1,
632  s_footer = s_body + 1,
633  s_done = s_footer + 1
634  };
635  detail::gzip_header header_;
636  detail::gzip_footer footer_;
637  string_type putback_;
638  int state_;
639 };
640 BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1)
641 
642 typedef basic_gzip_decompressor<> gzip_decompressor;
643 
644 //------------------Implementation of gzip_compressor-------------------------//
645 
646 template<typename Alloc>
647 basic_gzip_compressor<Alloc>::basic_gzip_compressor
648  (const gzip_params& p, std::streamsize buffer_size)
649  : base_type(normalize_params(p), buffer_size),
650  offset_(0), flags_(0)
651 {
652  // Calculate gzip header.
653  bool has_name = !p.file_name.empty();
654  bool has_comment = !p.comment.empty();
655 
656  std::string::size_type length =
657  10 +
658  (has_name ? p.file_name.size() + 1 : 0) +
659  (has_comment ? p.comment.size() + 1 : 0);
660  // + 2; // Header crc confuses gunzip.
661  int flags =
662  //gzip::flags::header_crc +
663  (has_name ? gzip::flags::name : 0) +
664  (has_comment ? gzip::flags::comment : 0);
665  int extra_flags =
666  ( p.level == zlib::best_compression ?
667  gzip::extra_flags::best_compression :
668  0 ) +
669  ( p.level == zlib::best_speed ?
670  gzip::extra_flags::best_speed :
671  0 );
672  header_.reserve(length);
673  header_ += gzip::magic::id1; // ID1.
674  header_ += static_cast<char>(gzip::magic::id2); // ID2.
675  header_ += gzip::method::deflate; // CM.
676  header_ += static_cast<char>(flags); // FLG.
677  header_ += static_cast<char>(0xFF & p.mtime); // MTIME.
678  header_ += static_cast<char>(0xFF & (p.mtime >> 8));
679  header_ += static_cast<char>(0xFF & (p.mtime >> 16));
680  header_ += static_cast<char>(0xFF & (p.mtime >> 24));
681  header_ += static_cast<char>(extra_flags); // XFL.
682  header_ += static_cast<char>(gzip::os_unknown); // OS.
683  if (has_name) {
684  header_ += p.file_name;
685  header_ += '\0';
686  }
687  if (has_comment) {
688  header_ += p.comment;
689  header_ += '\0';
690  }
691 }
692 
693 template<typename Alloc>
694 gzip_params basic_gzip_compressor<Alloc>::normalize_params(gzip_params p)
695 {
696  p.noheader = true;
697  p.calculate_crc = true;
698  return p;
699 }
700 
701 template<typename Alloc>
702 void basic_gzip_compressor<Alloc>::prepare_footer()
703 {
704  boost::iostreams::back_insert_device<std::string> out(footer_);
705  write_long(this->crc(), out);
706  write_long(this->total_in(), out);
707  flags_ |= f_body_done;
708  offset_ = 0;
709 }
710 
711 template<typename Alloc>
712 std::streamsize basic_gzip_compressor<Alloc>::read_string
713  (char* s, std::streamsize n, std::string& str)
714 {
715  std::streamsize avail =
716  static_cast<std::streamsize>(str.size() - offset_);
717  std::streamsize amt = (std::min)(avail, n);
718  std::copy( str.data() + offset_,
719  str.data() + offset_ + amt,
720  s );
721  offset_ += amt;
722  if ( !(flags_ & f_header_done) &&
723  offset_ == static_cast<std::size_t>(str.size()) )
724  {
725  flags_ |= f_header_done;
726  }
727  return amt;
728 }
729 
730 //------------------Implementation of gzip_decompressor-----------------------//
731 
732 template<typename Alloc>
733 basic_gzip_decompressor<Alloc>::basic_gzip_decompressor
734  (int window_bits, std::streamsize buffer_size)
735  : base_type(make_params(window_bits), buffer_size),
736  state_(s_start)
737  { }
738 
739 template<typename Alloc>
740 gzip_params basic_gzip_decompressor<Alloc>::make_params(int window_bits)
741 {
742  gzip_params p;
743  p.window_bits = window_bits;
744  p.noheader = true;
745  p.calculate_crc = true;
746  return p;
747 }
748 
749 //----------------------------------------------------------------------------//
750 
751 } } // End namespaces iostreams, boost.
752 
753 #if defined(BOOST_MSVC)
754 # pragma warning(pop)
755 #endif
756 
757 #endif // #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
@ id2
Definition: Typedefs.h:19
@ id1
Definition: Typedefs.h:19
type
The type the bitset is encoded with.
Definition: bitset.hpp:44
CEREAL_SIZE_TYPE size_type
The size type used by cereal.
Definition: helpers.hpp:61
detail namespace with internal helper functions
Definition: json.hpp:260
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5657
@ error
throw a parse_error exception in case of a tag
Definition: json.hpp:5678
void close(FILE *out)
Definition: Vtk.h:123
#define const
Definition: zconf.h:233