Reference documentation for deal.II version 9.1.0-pre
patterns.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 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_patterns_h
17 #define dealii_patterns_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/exceptions.h>
23 #include <deal.II/base/point.h>
24 #include <deal.II/base/std_cxx14/algorithm.h>
25 #include <deal.II/base/std_cxx14/memory.h>
26 #include <deal.II/base/std_cxx14/utility.h>
27 #include <deal.II/base/subscriptor.h>
28 #include <deal.II/base/template_constraints.h>
29 #include <deal.II/base/utilities.h>
30 
31 #include <boost/archive/basic_archive.hpp>
32 #include <boost/core/demangle.hpp>
33 #include <boost/property_tree/ptree_fwd.hpp>
34 #include <boost/property_tree/ptree_serialization.hpp>
35 #include <boost/serialization/split_member.hpp>
36 
37 #include <array>
38 #include <deque>
39 #include <list>
40 #include <map>
41 #include <set>
42 #include <sstream>
43 #include <string>
44 #include <type_traits>
45 #include <unordered_map>
46 #include <unordered_set>
47 #include <utility>
48 #include <vector>
49 
50 DEAL_II_NAMESPACE_OPEN
51 
52 // forward declarations for interfaces and friendship
53 class LogStream;
55 
64 namespace Patterns
65 {
73  {
74  public:
78  virtual ~PatternBase() = default;
79 
83  virtual bool
84  match(const std::string &test_string) const = 0;
85 
92  {
109  };
110 
114  virtual std::string
115  description(const OutputStyle style = Machine) const = 0;
116 
126  virtual std::unique_ptr<PatternBase>
127  clone() const = 0;
128 
144  virtual std::size_t
145  memory_consumption() const;
146  };
147 
151  std::unique_ptr<PatternBase>
152  pattern_factory(const std::string &description);
153 
154  namespace internal
155  {
161  std::string
162  escape(const std::string &input, const PatternBase::OutputStyle style);
163 
164  } // namespace internal
165 
182  class Integer : public PatternBase
183  {
184  public:
190  static const int min_int_value;
191 
197  static const int max_int_value;
198 
211  Integer(const int lower_bound = min_int_value,
212  const int upper_bound = max_int_value);
213 
218  virtual bool
219  match(const std::string &test_string) const override;
220 
226  virtual std::string
227  description(const OutputStyle style = Machine) const override;
228 
234  virtual std::unique_ptr<PatternBase>
235  clone() const override;
236 
242  static std::unique_ptr<Integer>
243  create(const std::string &description);
244 
245  private:
252  const int lower_bound;
253 
260  const int upper_bound;
261 
265  static const char *description_init;
266  };
267 
285  class Double : public PatternBase
286  {
287  public:
292  static const double min_double_value;
293 
298  static const double max_double_value;
299 
307  Double(const double lower_bound = min_double_value,
308  const double upper_bound = max_double_value);
309 
314  virtual bool
315  match(const std::string &test_string) const override;
316 
322  virtual std::string
323  description(const OutputStyle style = Machine) const override;
324 
330  virtual std::unique_ptr<PatternBase>
331  clone() const override;
332 
340  static std::unique_ptr<Double>
341  create(const std::string &description);
342 
343  private:
350  const double lower_bound;
351 
358  const double upper_bound;
359 
363  static const char *description_init;
364  };
365 
375  class Selection : public PatternBase
376  {
377  public:
382  Selection(const std::string &seq);
383 
388  virtual bool
389  match(const std::string &test_string) const override;
390 
396  virtual std::string
397  description(const OutputStyle style = Machine) const override;
398 
404  virtual std::unique_ptr<PatternBase>
405  clone() const override;
406 
411  std::size_t
412  memory_consumption() const override;
413 
419  static std::unique_ptr<Selection>
420  create(const std::string &description);
421 
422  private:
427  std::string sequence;
428 
432  static const char *description_init;
433  };
434 
435 
443  class List : public PatternBase
444  {
445  public:
451  static const unsigned int max_int_value;
452 
461  List(const PatternBase &base_pattern,
462  const unsigned int min_elements = 0,
463  const unsigned int max_elements = max_int_value,
464  const std::string &separator = ",");
465 
466 
470  const std::string &
471  get_separator() const;
472 
476  const PatternBase &
477  get_base_pattern() const;
478 
482  List(const List &other);
483 
488  virtual bool
489  match(const std::string &test_string) const override;
490 
495  virtual std::string
496  description(const OutputStyle style = Machine) const override;
497 
503  virtual std::unique_ptr<PatternBase>
504  clone() const override;
505 
511  static std::unique_ptr<List>
512  create(const std::string &description);
513 
518  std::size_t
519  memory_consumption() const override;
520 
529  DeclException2(ExcInvalidRange,
530  int,
531  int,
532  << "The values " << arg1 << " and " << arg2
533  << " do not form a valid range.");
535  private:
539  std::unique_ptr<PatternBase> pattern;
540 
544  const unsigned int min_elements;
545 
549  const unsigned int max_elements;
550 
554  const std::string separator;
555 
559  static const char *description_init;
560  };
561 
562 
577  class Map : public PatternBase
578  {
579  public:
585  static const unsigned int max_int_value;
586 
595  Map(const PatternBase &key_pattern,
596  const PatternBase &value_pattern,
597  const unsigned int min_elements = 0,
598  const unsigned int max_elements = max_int_value,
599  const std::string &separator = ",",
600  const std::string &key_value_separator = ":");
601 
605  Map(const Map &other);
606 
611  virtual bool
612  match(const std::string &test_string) const override;
613 
618  virtual std::string
619  description(const OutputStyle style = Machine) const override;
620 
626  virtual std::unique_ptr<PatternBase>
627  clone() const override;
628 
634  static std::unique_ptr<Map>
635  create(const std::string &description);
636 
641  std::size_t
642  memory_consumption() const override;
643 
647  const PatternBase &
648  get_key_pattern() const;
649 
653  const PatternBase &
654  get_value_pattern() const;
655 
659  const std::string &
660  get_separator() const;
661 
665  const std::string &
666  get_key_value_separator() const;
667 
676  DeclException2(ExcInvalidRange,
677  int,
678  int,
679  << "The values " << arg1 << " and " << arg2
680  << " do not form a valid range.");
682  private:
687  std::unique_ptr<PatternBase> key_pattern;
688  std::unique_ptr<PatternBase> value_pattern;
689 
693  const unsigned int min_elements;
694 
698  const unsigned int max_elements;
699 
703  const std::string separator;
704 
705 
709  const std::string key_value_separator;
710 
714  static const char *description_init;
715  };
716 
717 
718 
766  class Tuple : public PatternBase
767  {
768  public:
777  Tuple(const std::vector<std::unique_ptr<PatternBase>> &patterns,
778  const std::string & separator = ":");
779 
785  Tuple(const std::vector<std::unique_ptr<PatternBase>> &patterns,
786  const char * separator);
787 
788 
796  template <class... PatternTypes>
797  Tuple(const std::string &separator, const PatternTypes &... patterns);
798 
806  template <class... PatternTypes>
807  Tuple(const char *separator, const PatternTypes &... patterns);
808 
814  template <typename... Patterns>
815  Tuple(const Patterns &... patterns);
816 
820  Tuple(const Tuple &other);
821 
826  virtual bool
827  match(const std::string &test_string) const override;
828 
833  virtual std::string
834  description(const OutputStyle style = Machine) const override;
835 
841  virtual std::unique_ptr<PatternBase>
842  clone() const override;
843 
849  static std::unique_ptr<Tuple>
850  create(const std::string &description);
851 
856  std::size_t
857  memory_consumption() const override;
858 
862  const PatternBase &
863  get_pattern(const unsigned int &i) const;
864 
868  const std::string &
869  get_separator() const;
870 
871  private:
875  std::vector<std::unique_ptr<PatternBase>> patterns;
876 
880  const std::string separator;
881 
885  static const char *description_init;
886  };
887 
888 
900  {
901  public:
905  MultipleSelection(const std::string &seq);
906 
911  virtual bool
912  match(const std::string &test_string) const override;
913 
919  virtual std::string
920  description(const OutputStyle style = Machine) const override;
921 
927  virtual std::unique_ptr<PatternBase>
928  clone() const override;
929 
935  static std::unique_ptr<MultipleSelection>
936  create(const std::string &description);
937 
942  std::size_t
943  memory_consumption() const override;
944 
954  ExcCommasNotAllowed,
955  int,
956  << "A comma was found at position " << arg1
957  << " of your input string, but commas are not allowed here.");
959  private:
964  std::string sequence;
965 
969  static const char *description_init;
970  };
971 
976  class Bool : public Selection
977  {
978  public:
982  Bool();
983 
988  virtual std::string
989  description(const OutputStyle style = Machine) const override;
990 
996  virtual std::unique_ptr<PatternBase>
997  clone() const override;
998 
1004  static std::unique_ptr<Bool>
1005  create(const std::string &description);
1006 
1007  private:
1011  static const char *description_init;
1012  };
1013 
1017  class Anything : public PatternBase
1018  {
1019  public:
1024  Anything() = default;
1025 
1030  virtual bool
1031  match(const std::string &test_string) const override;
1032 
1037  virtual std::string
1038  description(const OutputStyle style = Machine) const override;
1039 
1045  virtual std::unique_ptr<PatternBase>
1046  clone() const override;
1047 
1053  static std::unique_ptr<Anything>
1054  create(const std::string &description);
1055 
1056  private:
1060  static const char *description_init;
1061  };
1062 
1063 
1078  class FileName : public PatternBase
1079  {
1080  public:
1086  {
1090  input = 0,
1094  output = 1
1095  };
1096 
1101  FileName(const FileType type = input);
1102 
1107  virtual bool
1108  match(const std::string &test_string) const override;
1109 
1114  virtual std::string
1115  description(const OutputStyle style = Machine) const override;
1116 
1122  virtual std::unique_ptr<PatternBase>
1123  clone() const override;
1124 
1129 
1135  static std::unique_ptr<FileName>
1136  create(const std::string &description);
1137 
1138  private:
1142  static const char *description_init;
1143  };
1144 
1145 
1159  {
1160  public:
1164  DirectoryName() = default;
1165 
1170  virtual bool
1171  match(const std::string &test_string) const override;
1172 
1177  virtual std::string
1178  description(const OutputStyle style = Machine) const override;
1179 
1185  virtual std::unique_ptr<PatternBase>
1186  clone() const override;
1187 
1193  static std::unique_ptr<DirectoryName>
1194  create(const std::string &description);
1195 
1196  private:
1200  static const char *description_init;
1201  };
1202 
1203 
1283  namespace Tools
1284  {
1296  template <class T, class Enable = void>
1297  struct Convert
1298  {
1308  static std::unique_ptr<Patterns::PatternBase>
1309  to_pattern() = delete;
1310 
1321  static std::string
1322  to_string(const T & s,
1323  const std::unique_ptr<Patterns::PatternBase> &p =
1324  Convert<T>::to_pattern()) = delete;
1325 
1335  static T
1336  to_value(const std::string & s,
1337  const std::unique_ptr<Patterns::PatternBase> &p =
1338  Convert<T>::to_pattern()) = delete;
1339  };
1340 
1361  template <typename T>
1362  std::string
1363  to_string(const T &t);
1364 
1392  template <typename T>
1393  void
1394  to_value(const std::string &s, T &t);
1395 
1405  std::string,
1406  const Patterns::PatternBase *,
1407  << "The string " << arg1 << " does not match the pattern \""
1408  << arg2->description() << "\"");
1410  } // namespace Tools
1411 } // namespace Patterns
1412 
1413 
1414 // ---------------------- inline and template functions --------------------
1415 namespace Patterns
1416 {
1417  template <class... PatternTypes>
1418  Tuple::Tuple(const char *separator, const PatternTypes &... ps)
1419  : // forward to the version with std::string argument
1420  Tuple(std::string(separator), ps...)
1421  {}
1422 
1423 
1424 
1425  template <class... PatternTypes>
1426  Tuple::Tuple(const std::string &separator, const PatternTypes &... ps)
1427  : separator(separator)
1428  {
1430  "Not all of the input arguments of this function "
1431  "are derived from PatternBase");
1432  static_assert(sizeof...(ps) > 0,
1433  "The number of PatternTypes must be greater than zero!");
1434  auto pattern_pointers = {(static_cast<const PatternBase *>(&ps))...};
1435  for (auto p : pattern_pointers)
1436  patterns.push_back(p->clone());
1437  }
1438 
1439 
1440 
1441  template <class... PatternTypes>
1442  Tuple::Tuple(const PatternTypes &... ps)
1443  : // forward to the version with the separator argument
1444  Tuple(std::string(":"), ps...)
1445  {}
1446 
1447 
1448 
1449  namespace Tools
1450  {
1451  namespace internal
1452  {
1479  template <class T, class Enable = void>
1480  struct RankInfo
1481  {
1482  static constexpr int list_rank = 0;
1483  static constexpr int map_rank = 0;
1484  };
1485  } // namespace internal
1486 
1487  // Arithmetic types
1488  template <class T>
1489  struct Convert<T,
1490  typename std::enable_if<std::is_arithmetic<T>::value>::type>
1491  {
1492  static std::unique_ptr<Patterns::PatternBase>
1493  to_pattern()
1494  {
1495  if (std::is_same<T, bool>::value)
1496  return std_cxx14::make_unique<Patterns::Bool>();
1497  else if (std::is_integral<T>::value)
1498  return std_cxx14::make_unique<Patterns::Integer>(
1499  std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
1500  else if (std::is_floating_point<T>::value)
1501  return std_cxx14::make_unique<Patterns::Double>(
1502  -std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
1503 
1504  Assert(false, ExcNotImplemented());
1505  // the following line should never be invoked
1506  return nullptr;
1507  }
1508 
1509  static std::string
1510  to_string(const T & value,
1511  const std::unique_ptr<Patterns::PatternBase> &p =
1513  {
1514  std::stringstream str;
1515  if (std::is_same<T, unsigned char>::value ||
1516  std::is_same<T, signed char>::value || std::is_same<T, char>::value)
1517  str << (int)value;
1518  else if (std::is_same<T, bool>::value)
1519  str << (value ? "true" : "false");
1520  else
1521  str << value;
1522  AssertThrow(p->match(str.str()), ExcNoMatch(str.str(), p.get()));
1523  return str.str();
1524  }
1525 
1526  static T
1527  to_value(const std::string & s,
1528  const std::unique_ptr<Patterns::PatternBase> &p =
1530  {
1531  AssertThrow(p->match(s), ExcNoMatch(s, p.get()));
1532  T value;
1533  if (std::is_same<T, bool>::value)
1534  value = (s == "true");
1535  else
1536  {
1537  std::istringstream is(s);
1538  if (std::is_same<T, unsigned char>::value ||
1539  std::is_same<T, signed char>::value ||
1540  std::is_same<T, char>::value)
1541  {
1542  int i;
1543  is >> i;
1544  value = i;
1545  }
1546  else
1547  is >> value;
1548 
1549  // If someone passes "123 abc" to the function, the method yields an
1550  // integer 123 alright, but the space terminates the read from the
1551  // string although there is more to come. This case, however, is
1552  // checked for in the call p->match(s) at the beginning of this
1553  // function, and would throw earlier. Here it is safe to assume that
1554  // if we didn't fail the conversion with the operator >>, then we
1555  // are good to go.
1556  AssertThrow(
1557  !is.fail(),
1558  ExcMessage("Failed to convert from \"" + s + "\" to the type \"" +
1559  boost::core::demangle(typeid(T).name()) + "\""));
1560  }
1561  return value;
1562  }
1563  };
1564 
1565  namespace internal
1566  {
1567  const std::array<std::string, 4> default_list_separator{
1568  {",", ";", "|", "%"}};
1569  const std::array<std::string, 4> default_map_separator{
1570  {":", "=", "@", "#"}};
1571 
1572  // specialize a type for all of the STL containers and maps
1573  template <typename T>
1574  struct is_list_compatible : std::false_type
1575  {};
1576  template <typename T, std::size_t N>
1577  struct is_list_compatible<std::array<T, N>> : std::true_type
1578  {};
1579  template <typename... Args>
1580  struct is_list_compatible<std::vector<Args...>> : std::true_type
1581  {};
1582  template <typename... Args>
1583  struct is_list_compatible<std::deque<Args...>> : std::true_type
1584  {};
1585  template <typename... Args>
1586  struct is_list_compatible<std::list<Args...>> : std::true_type
1587  {};
1588  template <typename... Args>
1589  struct is_list_compatible<std::set<Args...>> : std::true_type
1590  {};
1591  template <typename... Args>
1592  struct is_list_compatible<std::multiset<Args...>> : std::true_type
1593  {};
1594  template <typename... Args>
1595  struct is_list_compatible<std::unordered_set<Args...>> : std::true_type
1596  {};
1597  template <typename... Args>
1598  struct is_list_compatible<std::unordered_multiset<Args...>>
1599  : std::true_type
1600  {};
1601 
1602  template <typename T>
1603  struct is_map_compatible : std::false_type
1604  {};
1605  template <class Key, class T, class Compare, class Allocator>
1606  struct is_map_compatible<std::map<Key, T, Compare, Allocator>>
1607  : std::true_type
1608  {};
1609  template <class Key, class T, class Compare, class Allocator>
1610  struct is_map_compatible<std::multimap<Key, T, Compare, Allocator>>
1611  : std::true_type
1612  {};
1613  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1614  struct is_map_compatible<
1615  std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type
1616  {};
1617  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1618  struct is_map_compatible<
1619  std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
1620  : std::true_type
1621  {};
1622  } // namespace internal
1623 
1624  // type trait to use the implementation type traits as well as decay the
1625  // type
1626  template <typename T>
1627  struct is_list_compatible
1628  {
1629  static constexpr bool const value =
1630  internal::is_list_compatible<typename std::decay<T>::type>::value;
1631  };
1632 
1633  template <typename T>
1634  struct is_map_compatible
1635  {
1636  static constexpr bool const value =
1637  internal::is_map_compatible<typename std::decay<T>::type>::value;
1638  };
1639 
1640  namespace internal
1641  {
1642  // Helper function for list_rank
1643  template <class T>
1644  constexpr int
1645  max_list_rank()
1646  {
1647  return RankInfo<T>::list_rank;
1648  }
1649 
1650  template <class T1, class T2, class... Types>
1651  constexpr int
1652  max_list_rank()
1653  {
1654  return std_cxx14::max(RankInfo<T1>::list_rank,
1655  max_list_rank<T2, Types...>());
1656  }
1657 
1658  // Helper function for map_rank
1659  template <class T>
1660  constexpr int
1661  max_map_rank()
1662  {
1663  return RankInfo<T>::map_rank;
1664  }
1665 
1666  template <class T1, class T2, class... Types>
1667  constexpr int
1668  max_map_rank()
1669  {
1670  return std_cxx14::max(RankInfo<T1>::map_rank,
1671  max_map_rank<T2, Types...>());
1672  }
1673 
1674  // Rank of vector types
1675  template <class T>
1676  struct RankInfo<
1677  T,
1678  typename std::enable_if<is_list_compatible<T>::value>::type>
1679  {
1680  static constexpr int list_rank =
1682  static constexpr int map_rank =
1684  };
1685 
1686  // Rank of map types
1687  template <class T>
1688  struct RankInfo<
1689  T,
1690  typename std::enable_if<is_map_compatible<T>::value>::type>
1691  {
1692  static constexpr int list_rank =
1693  max_list_rank<typename T::key_type, typename T::mapped_type>() + 1;
1694  static constexpr int map_rank =
1695  max_map_rank<typename T::key_type, typename T::mapped_type>() + 1;
1696  };
1697 
1698  // Rank of Tensor types
1699  template <int rank, int dim, class Number>
1700  struct RankInfo<Tensor<rank, dim, Number>>
1701  {
1702  static constexpr int list_rank = rank + RankInfo<Number>::list_rank;
1703  static constexpr int map_rank = RankInfo<Number>::map_rank;
1704  };
1705 
1706  template <int dim, class Number>
1707  struct RankInfo<Point<dim, Number>> : RankInfo<Tensor<1, dim, Number>>
1708  {};
1709 
1710  // Rank of complex types
1711  template <class Number>
1712  struct RankInfo<std::complex<Number>>
1713  {
1714  static constexpr int list_rank = RankInfo<Number>::list_rank + 1;
1715  static constexpr int map_rank = RankInfo<Number>::map_rank;
1716  };
1717 
1718  template <class Key, class Value>
1719  struct RankInfo<std::pair<Key, Value>>
1720  {
1721  static constexpr int list_rank =
1723  static constexpr int map_rank =
1725  1;
1726  };
1727 
1728 
1729  template <class... Types>
1730  struct RankInfo<std::tuple<Types...>>
1731  {
1732  static constexpr int list_rank = max_list_rank<Types...>();
1733  static constexpr int map_rank = max_map_rank<Types...>() + 1;
1734  };
1735  } // namespace internal
1736 
1737  // stl containers
1738  template <class T>
1739  struct Convert<T,
1740  typename std::enable_if<is_list_compatible<T>::value>::type>
1741  {
1742  static std::unique_ptr<Patterns::PatternBase>
1743  to_pattern()
1744  {
1745  static_assert(internal::RankInfo<T>::list_rank > 0,
1746  "Cannot use this class for non List-compatible types.");
1747  return std_cxx14::make_unique<Patterns::List>(
1749  0,
1750  std::numeric_limits<unsigned int>::max(),
1751  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1752  1]);
1753  }
1754 
1755  static std::string
1756  to_string(const T & t,
1757  const std::unique_ptr<Patterns::PatternBase> &pattern =
1759  {
1760  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1761  AssertThrow(p,
1762  ExcMessage("I need a List pattern to convert a "
1763  "string to a List type."));
1764  auto base_p = p->get_base_pattern().clone();
1765  std::vector<std::string> vec(t.size());
1766 
1767  unsigned int i = 0;
1768  for (const auto &ti : t)
1769  vec[i++] = Convert<typename T::value_type>::to_string(ti, base_p);
1770 
1771  std::string s;
1772  if (vec.size() > 0)
1773  s = vec[0];
1774  for (unsigned int i = 1; i < vec.size(); ++i)
1775  s += p->get_separator() + " " + vec[i];
1776 
1777  AssertThrow(pattern->match(s), ExcNoMatch(s, p));
1778  return s;
1779  }
1780 
1781  static T
1782  to_value(const std::string & s,
1783  const std::unique_ptr<Patterns::PatternBase> &pattern =
1785  {
1786  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1787 
1788  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1789  AssertThrow(p,
1790  ExcMessage("I need a List pattern to convert a string "
1791  "to a List type."));
1792 
1793  auto base_p = p->get_base_pattern().clone();
1794  T t;
1795 
1796  auto v = Utilities::split_string_list(s, p->get_separator());
1797  for (const auto &str : v)
1798  t.insert(t.end(),
1800 
1801  return t;
1802  }
1803  };
1804 
1805  // stl maps
1806  template <class T>
1807  struct Convert<T,
1808  typename std::enable_if<is_map_compatible<T>::value>::type>
1809  {
1810  static std::unique_ptr<Patterns::PatternBase>
1811  to_pattern()
1812  {
1813  static_assert(internal::RankInfo<T>::list_rank > 0,
1814  "Cannot use this class for non List-compatible types.");
1815  static_assert(internal::RankInfo<T>::map_rank > 0,
1816  "Cannot use this class for non Map-compatible types.");
1817  return std_cxx14::make_unique<Patterns::Map>(
1820  0,
1821  std::numeric_limits<unsigned int>::max(),
1822  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1823  1],
1824  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
1825  }
1826 
1827  static std::string
1828  to_string(const T & t,
1829  const std::unique_ptr<Patterns::PatternBase> &pattern =
1831  {
1832  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1833  AssertThrow(p,
1834  ExcMessage("I need a Map pattern to convert a string to "
1835  "a Map compatbile type."));
1836  auto key_p = p->get_key_pattern().clone();
1837  auto val_p = p->get_value_pattern().clone();
1838  std::vector<std::string> vec(t.size());
1839 
1840  unsigned int i = 0;
1841  for (const auto &ti : t)
1842  vec[i++] =
1843  Convert<typename T::key_type>::to_string(ti.first, key_p) +
1844  p->get_key_value_separator() +
1846 
1847  std::string s;
1848  if (vec.size() > 0)
1849  s = vec[0];
1850  for (unsigned int i = 1; i < vec.size(); ++i)
1851  s += p->get_separator() + " " + vec[i];
1852 
1853  AssertThrow(p->match(s), ExcNoMatch(s, p));
1854  return s;
1855  }
1856 
1857  static T
1858  to_value(const std::string & s,
1859  const std::unique_ptr<Patterns::PatternBase> &pattern =
1861  {
1862  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1863 
1864  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1865  AssertThrow(p,
1866  ExcMessage("I need a Map pattern to convert a "
1867  "string to a Map compatible type."));
1868 
1869  auto key_p = p->get_key_pattern().clone();
1870  auto val_p = p->get_value_pattern().clone();
1871  T t;
1872 
1873  auto v = Utilities::split_string_list(s, p->get_separator());
1874  for (const auto &str : v)
1875  {
1876  auto key_val =
1877  Utilities::split_string_list(str, p->get_key_value_separator());
1878  AssertDimension(key_val.size(), 2);
1879  t.insert(std::make_pair(
1880  Convert<typename T::key_type>::to_value(key_val[0], key_p),
1882  }
1883 
1884  return t;
1885  }
1886  };
1887 
1888  // Tensors
1889  template <int rank, int dim, class Number>
1890  struct Convert<Tensor<rank, dim, Number>>
1891  {
1892  using T = Tensor<rank, dim, Number>;
1893  static std::unique_ptr<Patterns::PatternBase>
1894  to_pattern()
1895  {
1896  static_assert(internal::RankInfo<T>::list_rank > 0,
1897  "Cannot use this class for non List-compatible types.");
1898  return std_cxx14::make_unique<Patterns::List>(
1900  dim,
1901  dim,
1902  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1903  1]);
1904  }
1905 
1906  static std::string
1907  to_string(const T & t,
1908  const std::unique_ptr<Patterns::PatternBase> &pattern =
1910  {
1911  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1912  AssertThrow(p,
1913  ExcMessage("I need a List pattern to convert a string "
1914  "to a List compatbile type."));
1915  auto base_p = p->get_base_pattern().clone();
1916  std::vector<std::string> vec(dim);
1917 
1918  for (unsigned int i = 0; i < dim; ++i)
1919  vec[i] = Convert<typename T::value_type>::to_string(t[i], base_p);
1920 
1921  std::string s;
1922  if (vec.size() > 0)
1923  s = vec[0];
1924  for (unsigned int i = 1; i < vec.size(); ++i)
1925  s += p->get_separator() + " " + vec[i];
1926 
1927  AssertThrow(p->match(s), ExcNoMatch(s, p));
1928  return s;
1929  }
1930 
1931  static T
1932  to_value(const std::string & s,
1933  const std::unique_ptr<Patterns::PatternBase> &pattern =
1935  {
1936  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1937 
1938  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1939  AssertThrow(p,
1940  ExcMessage("I need a List pattern to convert a string "
1941  "to a List compatbile type."));
1942 
1943  auto base_p = p->get_base_pattern().clone();
1944  T t;
1945 
1946  auto v = Utilities::split_string_list(s, p->get_separator());
1947  unsigned int i = 0;
1948  for (const auto &str : v)
1949  t[i++] = Convert<typename T::value_type>::to_value(str, base_p);
1950 
1951  return t;
1952  }
1953  };
1954 
1955  // Points
1956  template <int dim, class Number>
1957  struct Convert<Point<dim, Number>>
1958  {
1959  using T = Point<dim, Number>;
1960 
1961  static std::unique_ptr<Patterns::PatternBase>
1962  to_pattern()
1963  {
1964  return Convert<Tensor<1, dim, Number>>::to_pattern();
1965  }
1966 
1967  static std::string
1968  to_string(const T & t,
1969  const std::unique_ptr<Patterns::PatternBase> &pattern =
1971  {
1972  return Convert<Tensor<1, dim, Number>>::to_string(
1973  Tensor<1, dim, Number>(t), pattern);
1974  }
1975 
1976  static T
1977  to_value(const std::string & s,
1978  const std::unique_ptr<Patterns::PatternBase> &pattern =
1980  {
1981  return T(Convert<Tensor<1, dim, Number>>::to_value(s, pattern));
1982  }
1983  };
1984 
1985  // Complex numbers
1986  template <class Number>
1987  struct Convert<std::complex<Number>>
1988  {
1989  using T = std::complex<Number>;
1990 
1991  static std::unique_ptr<Patterns::PatternBase>
1992  to_pattern()
1993  {
1994  static_assert(internal::RankInfo<T>::list_rank > 0,
1995  "Cannot use this class for non List-compatible types.");
1996  return std_cxx14::make_unique<Patterns::List>(
1998  2,
1999  2,
2000  internal::default_list_separator[internal::RankInfo<T>::list_rank -
2001  1]);
2002  }
2003 
2004  static std::string
2005  to_string(const T & t,
2006  const std::unique_ptr<Patterns::PatternBase> &pattern =
2008  {
2009  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2010  AssertThrow(p,
2011  ExcMessage("I need a List pattern to convert a string "
2012  "to a List compatbile type."));
2013 
2014  auto base_p = p->get_base_pattern().clone();
2015  std::string s =
2016  Convert<typename T::value_type>::to_string(t.real(), base_p) +
2017  p->get_separator() + " " +
2019 
2020  AssertThrow(pattern->match(s), ExcNoMatch(s, p));
2021  return s;
2022  }
2023 
2027  static T
2028  to_value(const std::string & s,
2029  const std::unique_ptr<Patterns::PatternBase> &pattern =
2031  {
2032  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2033 
2034  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2035  AssertThrow(p,
2036  ExcMessage("I need a List pattern to convert a string "
2037  "to a List compatbile type."));
2038 
2039  auto base_p = p->get_base_pattern().clone();
2040 
2041  auto v = Utilities::split_string_list(s, p->get_separator());
2042  AssertDimension(v.size(), 2);
2045  return t;
2046  }
2047  };
2048 
2049  // Strings
2050  template <>
2051  struct Convert<std::string>
2052  {
2053  using T = std::string;
2054 
2055  static std::unique_ptr<Patterns::PatternBase>
2056  to_pattern()
2057  {
2058  return std_cxx14::make_unique<Patterns::Anything>();
2059  }
2060 
2061  static std::string
2062  to_string(const T & t,
2063  const std::unique_ptr<Patterns::PatternBase> &pattern =
2065  {
2066  AssertThrow(pattern->match(t), ExcNoMatch(t, pattern.get()));
2067  return t;
2068  }
2069 
2070  static T
2071  to_value(const std::string & s,
2072  const std::unique_ptr<Patterns::PatternBase> &pattern =
2074  {
2075  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2076  return s;
2077  }
2078  };
2079 
2080  // Pairs
2081  template <class Key, class Value>
2082  struct Convert<std::pair<Key, Value>>
2083  {
2084  using T = std::pair<Key, Value>;
2085 
2086  static std::unique_ptr<Patterns::PatternBase>
2087  to_pattern()
2088  {
2089  static_assert(internal::RankInfo<T>::map_rank > 0,
2090  "Cannot use this class for non Map-compatible types.");
2091  return std_cxx14::make_unique<Patterns::Map>(
2094  1,
2095  1,
2096  // We keep the same list separator of the previous level, as this is
2097  // a map with only 1 possible entry
2098  internal::default_list_separator[internal::RankInfo<T>::list_rank],
2099  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
2100  }
2101 
2102  static std::string
2103  to_string(const T & t,
2104  const std::unique_ptr<Patterns::PatternBase> &pattern =
2106  {
2107  std::unordered_map<Key, Value> m;
2108  m.insert(t);
2109  std::string s = Convert<decltype(m)>::to_string(m, pattern);
2110  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2111  return s;
2112  }
2113 
2114  static T
2115  to_value(const std::string & s,
2116  const std::unique_ptr<Patterns::PatternBase> &pattern =
2118  {
2119  std::unordered_map<Key, Value> m;
2120  m = Convert<decltype(m)>::to_value(s, pattern);
2121  return *m.begin();
2122  }
2123  };
2124 
2125  // Tuples
2126  template <class... Args>
2127  struct Convert<std::tuple<Args...>>
2128  {
2129  using T = std::tuple<Args...>;
2130 
2131  static std::unique_ptr<Patterns::PatternBase>
2132  to_pattern()
2133  {
2134  static_assert(internal::RankInfo<T>::map_rank > 0,
2135  "Cannot use this class for non tuple-compatible types.");
2136  return std_cxx14::make_unique<Patterns::Tuple>(
2137  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1],
2139  }
2140 
2141  static std::string
2142  to_string(const T & t,
2143  const std::unique_ptr<Patterns::PatternBase> &pattern =
2145  {
2146  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2147  AssertThrow(p,
2148  ExcMessage("I need a Tuple pattern to convert a tuple "
2149  "to a string."));
2150 
2151  const auto string_array = Convert<T>::to_string_internal_2(t, *p);
2152  std::string str;
2153  for (unsigned int i = 0; i < string_array.size(); ++i)
2154  str += (i ? " " + p->get_separator() + " " : "") + string_array[i];
2155  AssertThrow(p->match(str), ExcNoMatch(str, p));
2156  return str;
2157  }
2158 
2159  static T
2160  to_value(const std::string & s,
2161  const std::unique_ptr<Patterns::PatternBase> &pattern =
2163  {
2164  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2165 
2166  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2167  AssertThrow(p,
2168  ExcMessage("I need a Tuple pattern to convert a string "
2169  "to a tuple type."));
2170 
2171  auto v = Utilities::split_string_list(s, p->get_separator());
2172 
2173  return Convert<T>::to_value_internal_2(v, *p);
2174  }
2175 
2176  private:
2177  template <std::size_t... I>
2178  static std::array<std::string, std::tuple_size<T>::value>
2179  to_string_internal_1(const T & t,
2180  const Patterns::Tuple &pattern,
2181  std_cxx14::index_sequence<I...>)
2182  {
2183  std::array<std::string, std::tuple_size<T>::value> a = {
2185  std::get<I>(t), pattern.get_pattern(I).clone())...}};
2186  return a;
2187  }
2188 
2189  static std::array<std::string, std::tuple_size<T>::value>
2190  to_string_internal_2(const T &t, const Patterns::Tuple &pattern)
2191  {
2193  t,
2194  pattern,
2195  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2196  }
2197 
2198  template <std::size_t... I>
2199  static T
2200  to_value_internal_1(const std::vector<std::string> &s,
2201  const Patterns::Tuple & pattern,
2202  std_cxx14::index_sequence<I...>)
2203  {
2204  return std::make_tuple(
2205  Convert<typename std::tuple_element<I, T>::type>::to_value(
2206  s[I], pattern.get_pattern(I).clone())...);
2207  }
2208 
2209  static T
2210  to_value_internal_2(const std::vector<std::string> &s,
2211  const Patterns::Tuple & pattern)
2212  {
2214  s,
2215  pattern,
2216  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2217  }
2218  };
2219 
2220  // Utility function with default Pattern
2221  template <typename T>
2222  std::string
2223  to_string(const T &t)
2224  {
2225  return Convert<T>::to_string(t);
2226  }
2227 
2228  // Utility function with default Pattern
2229  template <typename T>
2230  void
2231  to_value(const std::string &s, T &t)
2232  {
2233  t = Convert<T>::to_value(s);
2234  }
2235  } // namespace Tools
2236 } // namespace Patterns
2237 
2238 
2239 DEAL_II_NAMESPACE_CLOSE
2240 
2241 #endif
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:279
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:420
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
void to_value(const std::string &s, T &t)
Definition: patterns.h:2231
std::string sequence
Definition: patterns.h:427
const double upper_bound
Definition: patterns.h:358
static const char * description_init
Definition: patterns.h:363
static const char * description_init
Definition: patterns.h:1142
const std::string separator
Definition: patterns.h:880
const std::string separator
Definition: patterns.h:703
std::unique_ptr< PatternBase > pattern
Definition: patterns.h:539
static const unsigned int max_int_value
Definition: patterns.h:585
virtual std::unique_ptr< PatternBase > clone() const =0
static const char * description_init
Definition: patterns.h:714
STL namespace.
static const int max_int_value
Definition: patterns.h:197
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const unsigned int max_elements
Definition: patterns.h:698
static const char * description_init
Definition: patterns.h:969
Definition: point.h:106
FileType file_type
Definition: patterns.h:1128
static const int min_int_value
Definition: patterns.h:190
const double lower_bound
Definition: patterns.h:350
static const char * description_init
Definition: patterns.h:559
static::ExceptionBase & ExcMessage(std::string arg1)
static const char * description_init
Definition: patterns.h:1011
static const char * description_init
Definition: patterns.h:432
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:408
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:875
#define Assert(cond, exc)
Definition: exceptions.h:1227
static const char * description_init
Definition: patterns.h:265
static const char * description_init
Definition: patterns.h:885
std::unique_ptr< PatternBase > key_pattern
Definition: patterns.h:687
virtual ~PatternBase()=default
std::string to_string(const T &t)
Definition: patterns.h:2223
static const double min_double_value
Definition: patterns.h:292
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
Definition: patterns.cc:136
static const char * description_init
Definition: patterns.h:1200
virtual bool match(const std::string &test_string) const =0
static const char * description_init
Definition: patterns.h:1060
virtual std::size_t memory_consumption() const
Definition: patterns.cc:188
static const double max_double_value
Definition: patterns.h:298
static::ExceptionBase & ExcNoMatch(std::string arg1, const Patterns::PatternBase *arg2)
virtual std::string description(const OutputStyle style=Machine) const =0
const int upper_bound
Definition: patterns.h:260
static::ExceptionBase & ExcNotImplemented()
Tuple(const std::vector< std::unique_ptr< PatternBase >> &patterns, const std::string &separator=":")
Definition: patterns.cc:1053
const PatternBase & get_pattern(const unsigned int &i) const
Definition: patterns.cc:1219
const unsigned int min_elements
Definition: patterns.h:693
static const unsigned int max_int_value
Definition: patterns.h:451
const int lower_bound
Definition: patterns.h:252
const std::string separator
Definition: patterns.h:554
const std::string key_value_separator
Definition: patterns.h:709
const unsigned int max_elements
Definition: patterns.h:549
const unsigned int min_elements
Definition: patterns.h:544