Reference documentation for deal.II version Git cb0bd54b52 2019-09-21 16:31:22 -0400
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
table_handler.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2019 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_table_handler_h
17 #define dealii_table_handler_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/exceptions.h>
23 
24 #include <boost/serialization/map.hpp>
25 #include <boost/serialization/split_member.hpp>
26 #include <boost/serialization/string.hpp>
27 #include <boost/serialization/vector.hpp>
28 #include <boost/variant.hpp>
29 
30 #include <fstream>
31 #include <map>
32 #include <ostream>
33 #include <string>
34 #include <vector>
35 
36 
37 DEAL_II_NAMESPACE_OPEN
38 
39 // Forward declaration
40 #ifndef DOXYGEN
41 class TableHandler;
42 #endif
43 
44 namespace internal
45 {
54  struct TableEntry
55  {
56  public:
60  TableEntry() = default;
61 
66  template <typename T>
67  TableEntry(const T &t);
68 
75  template <typename T>
76  T
77  get() const;
78 
85  double
86  get_numeric_value() const;
87 
95  void
96  cache_string(bool scientific, unsigned int precision) const;
97 
102  const std::string &
103  get_cached_string() const;
104 
105 
111  TableEntry
113 
118  template <class Archive>
119  void
120  save(Archive &ar, const unsigned int version) const;
121 
126  template <class Archive>
127  void
128  load(Archive &ar, const unsigned int version);
129 
130  BOOST_SERIALIZATION_SPLIT_MEMBER()
131 
132  private:
136  using value_type = boost::
137  variant<int, unsigned int, unsigned long long int, double, std::string>;
138 
143 
147  mutable std::string cached_value;
148 
149  friend class ::TableHandler;
150  };
151 } // namespace internal
152 
153 
281 {
282 public:
342  {
359  org_mode_table
360  };
361 
365  TableHandler();
366 
367 
389  void
390  declare_column(const std::string &key);
391 
398  template <typename T>
399  void
400  add_value(const std::string &key, const T value);
401 
415  void
416  start_new_row();
417 
422  void
423  set_auto_fill_mode(const bool state);
424 
437  void
438  add_column_to_supercolumn(const std::string &key,
439  const std::string &superkey);
440 
457  void
458  set_column_order(const std::vector<std::string> &new_order);
459 
465  void
466  set_precision(const std::string &key, const unsigned int precision);
467 
472  void
473  set_scientific(const std::string &key, const bool scientific);
474 
480  void
481  set_tex_caption(const std::string &key, const std::string &tex_caption);
482 
486  void
487  set_tex_table_caption(const std::string &table_caption);
488 
492  void
493  set_tex_table_label(const std::string &table_label);
494 
500  void
501  set_tex_supercaption(const std::string &superkey,
502  const std::string &tex_supercaption);
503 
510  void
511  set_tex_format(const std::string &key, const std::string &format = "c");
512 
524  void
525  write_text(std::ostream & out,
526  const TextOutputFormat format = table_with_headers) const;
527 
535  void
536  write_tex(std::ostream &file, const bool with_header = true) const;
537 
542  void
543  clear();
544 
550  void
551  clear_current_row();
552 
557  template <class Archive>
558  void
559  serialize(Archive &ar, const unsigned int version);
560 
569  DeclException1(ExcColumnNotExistent,
570  std::string,
571  << "Column <" << arg1 << "> does not exist.");
572 
576  DeclException1(ExcSuperColumnNotExistent,
577  std::string,
578  << "Supercolumn <" << arg1 << "> does not exist.");
579 
583  DeclException1(ExcColumnOrSuperColumnNotExistent,
584  std::string,
585  << "Column or supercolumn <" << arg1 << "> does not exist.");
586 
590  DeclException4(ExcWrongNumberOfDataEntries,
591  std::string,
592  int,
593  std::string,
594  int,
595  << "Column <" << arg1 << "> has " << arg2
596  << " rows, but Column <" << arg3 << "> has " << arg4
597  << " rows.");
598 
602  DeclException1(ExcUndefinedTexFormat,
603  std::string,
604  << "<" << arg1 << "> is not a tex column format. Use "
605  << "'l', 'c', or 'r' to indicate left, centered, or "
606  << "right aligned text.");
608 protected:
613  struct Column
614  {
618  Column();
619 
623  Column(const std::string &tex_caption);
624 
629  void
630  pad_column_below(const unsigned int length);
631 
636  template <class Archive>
637  void
638  save(Archive &ar, const unsigned int version) const;
639  template <class Archive>
640  void
641  load(Archive &ar, const unsigned int version);
642  BOOST_SERIALIZATION_SPLIT_MEMBER()
643 
644 
645 
649  void
650  invalidate_cache();
651 
656  std::vector<internal::TableEntry> entries;
657 
664  std::string tex_caption;
665 
673  std::string tex_format;
674 
679  unsigned int precision;
680 
685 
693  unsigned int flag;
694 
699  unsigned int max_length;
700  };
701 
710  void
711  get_selected_columns(std::vector<std::string> &sel_columns) const;
712 
718  unsigned int
719  n_rows() const;
720 
726  std::vector<std::string> column_order;
727 
735  mutable std::map<std::string, Column> columns;
736 
745  std::map<std::string, std::vector<std::string>> supercolumns;
746 
754  std::map<std::string, std::string> tex_supercaptions;
755 
759  std::string tex_table_caption;
763  std::string tex_table_label;
764 
769 };
770 
771 
772 namespace internal
773 {
774  template <typename T>
776  : value(t)
777  {}
778 
779 
780  template <typename T>
781  T
783  {
784  // we don't quite know the data type in 'value', but
785  // it must be one of the ones in the type list of the
786  // boost::variant. so if T is not in the list, or if
787  // the data stored in the TableEntry is not of type
788  // T, then we will get an exception that we can
789  // catch and produce an error message
790  try
791  {
792  return boost::get<T>(value);
793  }
794  catch (...)
795  {
796  Assert(false,
797  ExcMessage(
798  "This TableEntry object does not store a datum of type T"));
799  throw;
800  }
801  }
802 
803 
804 
805  template <class Archive>
806  void
807  TableEntry::save(Archive &ar, const unsigned int) const
808  {
809  // write first an identifier for the kind
810  // of data stored and then the actual
811  // data, in its correct data type
812  if (const int *p = boost::get<int>(&value))
813  {
814  char c = 'i';
815  ar &c &*p;
816  }
817  else if (const unsigned int *p = boost::get<unsigned int>(&value))
818  {
819  char c = 'u';
820  ar &c &*p;
821  }
822  else if (const double *p = boost::get<double>(&value))
823  {
824  char c = 'd';
825  ar &c &*p;
826  }
827  else if (const std::string *p = boost::get<std::string>(&value))
828  {
829  char c = 's';
830  ar &c &*p;
831  }
832  else if (const unsigned long long int *p =
833  boost::get<unsigned long long int>(&value))
834  {
835  char c = 'l';
836  ar &c &*p;
837  }
838  else
839  Assert(false, ExcInternalError());
840  }
841 
842 
843 
844  template <class Archive>
845  void
846  TableEntry::load(Archive &ar, const unsigned int)
847  {
848  // following what we do in the save()
849  // function, first read in the data type
850  // as a one-character id, and then read
851  // the data
852  char c;
853  ar & c;
854 
855  switch (c)
856  {
857  case 'i':
858  {
859  int val;
860  ar &val;
861  value = val;
862  break;
863  }
864 
865  case 'u':
866  {
867  unsigned int val;
868  ar & val;
869  value = val;
870  break;
871  }
872 
873  case 'd':
874  {
875  double val;
876  ar & val;
877  value = val;
878  break;
879  }
880 
881  case 's':
882  {
883  std::string val;
884  ar & val;
885  value = val;
886  break;
887  }
888 
889  case 'l':
890  {
891  unsigned long long int val;
892  ar & val;
893  value = val;
894  break;
895  }
896 
897  default:
898  Assert(false, ExcInternalError());
899  }
900  }
901 } // namespace internal
902 
903 
904 
905 template <typename T>
906 void
907 TableHandler::add_value(const std::string &key, const T value)
908 {
909  // see if the column already exists
910  if (columns.find(key) == columns.end())
911  declare_column(key);
912 
913  if (auto_fill_mode == true)
914  {
915  // follow the algorithm given in the introduction to this class
916  // of padding columns as necessary
917  unsigned int max_col_length = 0;
918  for (const auto &column : columns)
919  max_col_length =
920  std::max(max_col_length,
921  static_cast<unsigned int>(column.second.entries.size()));
922 
923  while (columns[key].entries.size() + 1 < max_col_length)
924  {
925  columns[key].entries.push_back(internal::TableEntry(T()));
926  internal::TableEntry &entry = columns[key].entries.back();
927  entry.cache_string(columns[key].scientific, columns[key].precision);
928  columns[key].max_length =
929  std::max(columns[key].max_length,
930  static_cast<unsigned int>(
931  entry.get_cached_string().length()));
932  }
933  }
934 
935  // now push the value given to this function
936  columns[key].entries.push_back(internal::TableEntry(value));
937  internal::TableEntry &entry = columns[key].entries.back();
938  entry.cache_string(columns[key].scientific, columns[key].precision);
939  columns[key].max_length =
940  std::max(columns[key].max_length,
941  static_cast<unsigned int>(entry.get_cached_string().length()));
942 }
943 
944 
945 
946 template <class Archive>
947 void
948 TableHandler::Column::save(Archive &ar, const unsigned int /*version*/) const
949 {
950  ar &entries &tex_caption &tex_format &precision &scientific &flag &max_length;
951 }
952 
953 
954 
955 template <class Archive>
956 void
957 TableHandler::Column::load(Archive &ar, const unsigned int /*version*/)
958 {
959  ar &entries &tex_caption &tex_format &precision &scientific &flag &max_length;
960  invalidate_cache();
961 }
962 
963 
964 template <class Archive>
965 void
966 TableHandler::serialize(Archive &ar, const unsigned int)
967 {
968  ar &column_order &columns &supercolumns &tex_supercaptions &tex_table_caption
969  &tex_table_label &auto_fill_mode;
970 }
971 
972 
973 DEAL_II_NAMESPACE_CLOSE
974 
975 #endif
std::map< std::string, std::string > tex_supercaptions
unsigned int max_length
void save(Archive &ar, const unsigned int version) const
boost::variant< int, unsigned int, unsigned long long int, double, std::string > value_type
std::map< std::string, Column > columns
void add_value(const std::string &key, const T value)
const std::string & get_cached_string() const
void cache_string(bool scientific, unsigned int precision) const
void load(Archive &ar, const unsigned int version)
std::vector< std::string > column_order
std::string tex_format
static ::ExceptionBase & ExcMessage(std::string arg1)
std::string tex_table_caption
double get_numeric_value() const
TableEntry get_default_constructed_copy() const
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:518
std::string cached_value
#define Assert(cond, exc)
Definition: exceptions.h:1407
void save(Archive &ar, const unsigned int version) const
unsigned int precision
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:587
void serialize(Archive &ar, const unsigned int version)
std::vector< internal::TableEntry > entries
std::string tex_caption
std::map< std::string, std::vector< std::string > > supercolumns
std::string tex_table_label
static ::ExceptionBase & ExcInternalError()