Reference documentation for deal.II version 9.1.0-pre
table_handler.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2017 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 class TableHandler;
40 
41 namespace internal
42 {
51  struct TableEntry
52  {
53  public:
57  TableEntry() = default;
58 
63  template <typename T>
64  TableEntry(const T &t);
65 
72  template <typename T>
73  T
74  get() const;
75 
82  double
83  get_numeric_value() const;
84 
92  void
93  cache_string(bool scientific, unsigned int precision) const;
94 
99  const std::string &
100  get_cached_string() const;
101 
102 
108  TableEntry
110 
115  template <class Archive>
116  void
117  save(Archive &ar, const unsigned int version) const;
118 
123  template <class Archive>
124  void
125  load(Archive &ar, const unsigned int version);
126 
127  BOOST_SERIALIZATION_SPLIT_MEMBER()
128 
129  private:
133  using value_type = boost::
134  variant<int, unsigned int, unsigned long long int, double, std::string>;
135 
140 
144  mutable std::string cached_value;
145 
146  friend class ::TableHandler;
147  };
148 } // namespace internal
149 
150 
271 {
272 public:
332  {
349  org_mode_table
350  };
351 
355  TableHandler();
356 
357 
379  void
380  declare_column(const std::string &key);
381 
388  template <typename T>
389  void
390  add_value(const std::string &key, const T value);
391 
405  void
406  start_new_row();
407 
412  void
413  set_auto_fill_mode(const bool state);
414 
427  void
428  add_column_to_supercolumn(const std::string &key,
429  const std::string &superkey);
430 
447  void
448  set_column_order(const std::vector<std::string> &new_order);
449 
455  void
456  set_precision(const std::string &key, const unsigned int precision);
457 
462  void
463  set_scientific(const std::string &key, const bool scientific);
464 
470  void
471  set_tex_caption(const std::string &key, const std::string &tex_caption);
472 
476  void
477  set_tex_table_caption(const std::string &table_caption);
478 
482  void
483  set_tex_table_label(const std::string &table_label);
484 
490  void
491  set_tex_supercaption(const std::string &superkey,
492  const std::string &tex_supercaption);
493 
500  void
501  set_tex_format(const std::string &key, const std::string &format = "c");
502 
514  void
515  write_text(std::ostream & out,
516  const TextOutputFormat format = table_with_headers) const;
517 
525  void
526  write_tex(std::ostream &file, const bool with_header = true) const;
527 
532  void
533  clear();
534 
540  void
541  clear_current_row();
542 
547  template <class Archive>
548  void
549  serialize(Archive &ar, const unsigned int version);
550 
559  DeclException1(ExcColumnNotExistent,
560  std::string,
561  << "Column <" << arg1 << "> does not exist.");
562 
566  DeclException1(ExcSuperColumnNotExistent,
567  std::string,
568  << "Supercolumn <" << arg1 << "> does not exist.");
569 
573  DeclException1(ExcColumnOrSuperColumnNotExistent,
574  std::string,
575  << "Column or supercolumn <" << arg1 << "> does not exist.");
576 
580  DeclException4(ExcWrongNumberOfDataEntries,
581  std::string,
582  int,
583  std::string,
584  int,
585  << "Column <" << arg1 << "> has " << arg2
586  << " rows, but Column <" << arg3 << "> has " << arg4
587  << " rows.");
588 
592  DeclException1(ExcUndefinedTexFormat,
593  std::string,
594  << "<" << arg1 << "> is not a tex column format. Use "
595  << "'l', 'c', or 'r' to indicate left, centered, or "
596  << "right aligned text.");
598 protected:
603  struct Column
604  {
608  Column();
609 
613  Column(const std::string &tex_caption);
614 
619  void
620  pad_column_below(const unsigned int length);
621 
626  template <class Archive>
627  void
628  save(Archive &ar, const unsigned int version) const;
629  template <class Archive>
630  void
631  load(Archive &ar, const unsigned int version);
632  BOOST_SERIALIZATION_SPLIT_MEMBER()
633 
634 
635 
639  void
640  invalidate_cache();
641 
646  std::vector<internal::TableEntry> entries;
647 
654  std::string tex_caption;
655 
663  std::string tex_format;
664 
669  unsigned int precision;
670 
675 
683  unsigned int flag;
684 
689  unsigned int max_length;
690  };
691 
700  void
701  get_selected_columns(std::vector<std::string> &sel_columns) const;
702 
708  unsigned int
709  n_rows() const;
710 
716  std::vector<std::string> column_order;
717 
725  mutable std::map<std::string, Column> columns;
726 
735  std::map<std::string, std::vector<std::string>> supercolumns;
736 
744  std::map<std::string, std::string> tex_supercaptions;
745 
749  std::string tex_table_caption;
753  std::string tex_table_label;
754 
759 };
760 
761 
762 namespace internal
763 {
764  template <typename T>
766  : value(t)
767  {}
768 
769 
770  template <typename T>
771  T
773  {
774  // we don't quite know the data type in 'value', but
775  // it must be one of the ones in the type list of the
776  // boost::variant. so if T is not in the list, or if
777  // the data stored in the TableEntry is not of type
778  // T, then we will get an exception that we can
779  // catch and produce an error message
780  try
781  {
782  return boost::get<T>(value);
783  }
784  catch (...)
785  {
786  Assert(false,
787  ExcMessage(
788  "This TableEntry object does not store a datum of type T"));
789  throw;
790  }
791  }
792 
793 
794 
795  template <class Archive>
796  void
797  TableEntry::save(Archive &ar, const unsigned int) const
798  {
799  // write first an identifier for the kind
800  // of data stored and then the actual
801  // data, in its correct data type
802  if (const int *p = boost::get<int>(&value))
803  {
804  char c = 'i';
805  ar &c &*p;
806  }
807  else if (const unsigned int *p = boost::get<unsigned int>(&value))
808  {
809  char c = 'u';
810  ar &c &*p;
811  }
812  else if (const double *p = boost::get<double>(&value))
813  {
814  char c = 'd';
815  ar &c &*p;
816  }
817  else if (const std::string *p = boost::get<std::string>(&value))
818  {
819  char c = 's';
820  ar &c &*p;
821  }
822  else if (const unsigned long long int *p =
823  boost::get<unsigned long long int>(&value))
824  {
825  char c = 'l';
826  ar &c &*p;
827  }
828  else
829  Assert(false, ExcInternalError());
830  }
831 
832 
833 
834  template <class Archive>
835  void
836  TableEntry::load(Archive &ar, const unsigned int)
837  {
838  // following what we do in the save()
839  // function, first read in the data type
840  // as a one-character id, and then read
841  // the data
842  char c;
843  ar & c;
844 
845  switch (c)
846  {
847  case 'i':
848  {
849  int val;
850  ar &val;
851  value = val;
852  break;
853  }
854 
855  case 'u':
856  {
857  unsigned int val;
858  ar & val;
859  value = val;
860  break;
861  }
862 
863  case 'd':
864  {
865  double val;
866  ar & val;
867  value = val;
868  break;
869  }
870 
871  case 's':
872  {
873  std::string val;
874  ar & val;
875  value = val;
876  break;
877  }
878 
879  case 'l':
880  {
881  unsigned long long int val;
882  ar & val;
883  value = val;
884  break;
885  }
886 
887  default:
888  Assert(false, ExcInternalError());
889  }
890  }
891 } // namespace internal
892 
893 
894 
895 template <typename T>
896 void
897 TableHandler::add_value(const std::string &key, const T value)
898 {
899  // see if the column already exists
900  if (columns.find(key) == columns.end())
901  declare_column(key);
902 
903  if (auto_fill_mode == true)
904  {
905  // follow the algorithm given in the introduction to this class
906  // of padding columns as necessary
907  unsigned int max_col_length = 0;
908  for (std::map<std::string, Column>::iterator p = columns.begin();
909  p != columns.end();
910  ++p)
911  max_col_length =
912  std::max(max_col_length,
913  static_cast<unsigned int>(p->second.entries.size()));
914 
915  while (columns[key].entries.size() + 1 < max_col_length)
916  {
917  columns[key].entries.push_back(internal::TableEntry(T()));
918  internal::TableEntry &entry = columns[key].entries.back();
919  entry.cache_string(columns[key].scientific, columns[key].precision);
920  columns[key].max_length =
921  std::max(columns[key].max_length,
922  static_cast<unsigned int>(
923  entry.get_cached_string().length()));
924  }
925  }
926 
927  // now push the value given to this function
928  columns[key].entries.push_back(internal::TableEntry(value));
929  internal::TableEntry &entry = columns[key].entries.back();
930  entry.cache_string(columns[key].scientific, columns[key].precision);
931  columns[key].max_length =
932  std::max(columns[key].max_length,
933  static_cast<unsigned int>(entry.get_cached_string().length()));
934 }
935 
936 
937 
938 template <class Archive>
939 void
940 TableHandler::Column::save(Archive &ar, const unsigned int /*version*/) const
941 {
942  ar &entries &tex_caption &tex_format &precision &scientific &flag &max_length;
943 }
944 
945 
946 
947 template <class Archive>
948 void
949 TableHandler::Column::load(Archive &ar, const unsigned int /*version*/)
950 {
951  ar &entries &tex_caption &tex_format &precision &scientific &flag &max_length;
952  invalidate_cache();
953 }
954 
955 
956 template <class Archive>
957 void
958 TableHandler::serialize(Archive &ar, const unsigned int)
959 {
960  ar &column_order &columns &supercolumns &tex_supercaptions &tex_table_caption
961  &tex_table_label &auto_fill_mode;
962 }
963 
964 
965 DEAL_II_NAMESPACE_CLOSE
966 
967 #endif
std::map< std::string, std::string > tex_supercaptions
unsigned int max_length
boost::variant< int, unsigned int, unsigned long long int, double, std::string > value_type
void save(Archive &ar, const unsigned int version) const
std::map< std::string, Column > columns
void add_value(const std::string &key, const T value)
void save(Archive &ar, const unsigned int version) const
void load(Archive &ar, const unsigned int version)
std::vector< std::string > column_order
std::string tex_format
void cache_string(bool scientific, unsigned int precision) const
static::ExceptionBase & ExcMessage(std::string arg1)
std::string tex_table_caption
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:408
std::string cached_value
#define Assert(cond, exc)
Definition: exceptions.h:1227
const std::string & get_cached_string() const
unsigned int precision
double get_numeric_value() const
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:444
TableEntry get_default_constructed_copy() const
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()