Reference documentation for deal.II version 9.0.0
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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_patterns_h
17 #define dealii_patterns_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/subscriptor.h>
23 #include <deal.II/base/point.h>
24 #include <deal.II/base/subscriptor.h>
25 #include <deal.II/base/utilities.h>
26 #include <deal.II/base/template_constraints.h>
27 
28 #include <deal.II/base/std_cxx14/memory.h>
29 #include <deal.II/base/std_cxx14/algorithm.h>
30 #include <deal.II/base/std_cxx14/utility.h>
31 
32 #include <boost/archive/basic_archive.hpp>
33 #include <boost/core/demangle.hpp>
34 #include <boost/property_tree/ptree_fwd.hpp>
35 #include <boost/property_tree/ptree_serialization.hpp>
36 #include <boost/serialization/split_member.hpp>
37 
38 #include <array>
39 #include <deque>
40 #include <list>
41 #include <map>
42 #include <set>
43 #include <sstream>
44 #include <string>
45 #include <type_traits>
46 #include <unordered_map>
47 #include <unordered_set>
48 #include <utility>
49 #include <vector>
50 
51 DEAL_II_NAMESPACE_OPEN
52 
53 // forward declarations for interfaces and friendship
54 class LogStream;
56 
65 namespace Patterns
66 {
67 
75  {
76  public:
80  virtual ~PatternBase () = default;
81 
85  virtual bool match (const std::string &test_string) const = 0;
86 
93  {
110  };
111 
115  virtual std::string description (const OutputStyle style=Machine) const = 0;
116 
126  virtual std::unique_ptr<PatternBase> clone () const = 0;
127 
143  virtual std::size_t memory_consumption () const;
144  };
145 
149  std::unique_ptr<PatternBase> pattern_factory (const std::string &description);
150 
151  namespace internal
152  {
158  std::string escape(const std::string &input, const PatternBase::OutputStyle style);
159 
160  }
161 
178  class Integer : public PatternBase
179  {
180  public:
186  static const int min_int_value;
187 
193  static const int max_int_value;
194 
202  Integer (const int lower_bound = min_int_value,
203  const int upper_bound = max_int_value);
204 
209  virtual bool match (const std::string &test_string) const;
210 
216  virtual std::string description (const OutputStyle style=Machine) const;
217 
223  virtual std::unique_ptr<PatternBase> clone () const;
224 
230  static std::unique_ptr<Integer> create (const std::string &description);
231 
232  private:
239  const int lower_bound;
240 
247  const int upper_bound;
248 
252  static const char *description_init;
253  };
254 
272  class Double : public PatternBase
273  {
274  public:
279  static const double min_double_value;
280 
285  static const double max_double_value;
286 
294  Double (const double lower_bound = min_double_value,
295  const double upper_bound = max_double_value);
296 
301  virtual bool match (const std::string &test_string) const;
302 
308  virtual std::string description (const OutputStyle style=Machine) const;
309 
315  virtual std::unique_ptr<PatternBase> clone () const;
316 
324  static std::unique_ptr<Double> create(const std::string &description);
325 
326  private:
333  const double lower_bound;
334 
341  const double upper_bound;
342 
346  static const char *description_init;
347  };
348 
358  class Selection : public PatternBase
359  {
360  public:
365  Selection (const std::string &seq);
366 
371  virtual bool match (const std::string &test_string) const;
372 
378  virtual std::string description (const OutputStyle style=Machine) const;
379 
385  virtual std::unique_ptr<PatternBase> clone () const;
386 
391  std::size_t memory_consumption () const;
392 
398  static std::unique_ptr<Selection> create (const std::string &description);
399 
400  private:
405  std::string sequence;
406 
410  static const char *description_init;
411  };
412 
413 
421  class List : public PatternBase
422  {
423  public:
429  static const unsigned int max_int_value;
430 
439  List (const PatternBase &base_pattern,
440  const unsigned int min_elements = 0,
441  const unsigned int max_elements = max_int_value,
442  const std::string &separator = ",");
443 
444 
448  const std::string &get_separator() const;
449 
453  const PatternBase &get_base_pattern() const;
454 
458  List (const List &other);
459 
464  virtual bool match (const std::string &test_string) const;
465 
470  virtual std::string description (const OutputStyle style=Machine) const;
471 
477  virtual std::unique_ptr<PatternBase> clone () const;
478 
484  static std::unique_ptr<List> create (const std::string &description);
485 
490  std::size_t memory_consumption () const;
491 
501  int, int,
502  << "The values " << arg1 << " and " << arg2
503  << " do not form a valid range.");
505  private:
509  std::unique_ptr<PatternBase> pattern;
510 
514  const unsigned int min_elements;
515 
519  const unsigned int max_elements;
520 
524  const std::string separator;
525 
529  static const char *description_init;
530  };
531 
532 
547  class Map : public PatternBase
548  {
549  public:
555  static const unsigned int max_int_value;
556 
565  Map (const PatternBase &key_pattern,
566  const PatternBase &value_pattern,
567  const unsigned int min_elements = 0,
568  const unsigned int max_elements = max_int_value,
569  const std::string &separator = ",",
570  const std::string &key_value_separator = ":");
571 
575  Map (const Map &other);
576 
581  virtual bool match (const std::string &test_string) const;
582 
587  virtual std::string description (const OutputStyle style=Machine) const;
588 
594  virtual std::unique_ptr<PatternBase> clone () const;
595 
601  static std::unique_ptr<Map> create (const std::string &description);
602 
607  std::size_t memory_consumption () const;
608 
612  const PatternBase &get_key_pattern() const;
613 
617  const PatternBase &get_value_pattern() const;
618 
622  const std::string &get_separator() const;
623 
627  const std::string &get_key_value_separator() const;
628 
638  int, int,
639  << "The values " << arg1 << " and " << arg2
640  << " do not form a valid range.");
642  private:
647  std::unique_ptr<PatternBase> key_pattern;
648  std::unique_ptr<PatternBase> value_pattern;
649 
653  const unsigned int min_elements;
654 
658  const unsigned int max_elements;
659 
663  const std::string separator;
664 
665 
669  const std::string key_value_separator;
670 
674  static const char *description_init;
675  };
676 
677 
678 
726  class Tuple : public PatternBase
727  {
728  public:
737  Tuple (const std::vector<std::unique_ptr<PatternBase> > &patterns,
738  const std::string &separator = ":");
739 
745  Tuple (const std::vector<std::unique_ptr<PatternBase> > &patterns,
746  const char *separator);
747 
748 
756  template<class... PatternTypes>
757  Tuple (const std::string &separator,
758  const PatternTypes &... patterns);
759 
767  template<class... PatternTypes>
768  Tuple (const char *separator,
769  const PatternTypes &... patterns);
770 
776  template<typename... Patterns>
777  Tuple (const Patterns &... patterns);
778 
782  Tuple (const Tuple &other);
783 
788  virtual bool match (const std::string &test_string) const;
789 
794  virtual std::string description (const OutputStyle style=Machine) const;
795 
801  virtual std::unique_ptr<PatternBase> clone () const;
802 
808  static std::unique_ptr<Tuple> create (const std::string &description);
809 
814  std::size_t memory_consumption () const;
815 
819  const PatternBase &get_pattern(const unsigned int &i) const;
820 
824  const std::string &get_separator() const;
825 
826  private:
830  std::vector<std::unique_ptr<PatternBase> > patterns;
831 
835  const std::string separator;
836 
840  static const char *description_init;
841  };
842 
843 
855  {
856  public:
860  MultipleSelection (const std::string &seq);
861 
866  virtual bool match (const std::string &test_string) const;
867 
873  virtual std::string description (const OutputStyle style=Machine) const;
874 
880  virtual std::unique_ptr<PatternBase> clone () const;
881 
887  static std::unique_ptr<MultipleSelection> create (const std::string &description);
888 
893  std::size_t memory_consumption () const;
894 
904  int,
905  << "A comma was found at position " << arg1
906  << " of your input string, but commas are not allowed here.");
908  private:
913  std::string sequence;
914 
918  static const char *description_init;
919  };
920 
925  class Bool : public Selection
926  {
927  public:
931  Bool ();
932 
937  virtual std::string description (const OutputStyle style=Machine) const;
938 
944  virtual std::unique_ptr<PatternBase> clone () const;
945 
951  static std::unique_ptr<Bool> create(const std::string &description);
952 
953  private:
957  static const char *description_init;
958  };
959 
963  class Anything : public PatternBase
964  {
965  public:
970  Anything () = default;
971 
976  virtual bool match (const std::string &test_string) const;
977 
982  virtual std::string description (const OutputStyle style=Machine) const;
983 
989  virtual std::unique_ptr<PatternBase> clone () const;
990 
996  static std::unique_ptr<Anything> create(const std::string &description);
997 
998  private:
1002  static const char *description_init;
1003  };
1004 
1005 
1020  class FileName : public PatternBase
1021  {
1022  public:
1028  {
1032  input = 0,
1037  };
1038 
1043  FileName (const FileType type = input);
1044 
1049  virtual bool match (const std::string &test_string) const;
1050 
1055  virtual std::string description (const OutputStyle style=Machine) const;
1056 
1062  virtual std::unique_ptr<PatternBase> clone () const;
1063 
1068 
1074  static std::unique_ptr<FileName> create (const std::string &description);
1075 
1076  private:
1080  static const char *description_init;
1081  };
1082 
1083 
1097  {
1098  public:
1102  DirectoryName () = default;
1103 
1108  virtual bool match (const std::string &test_string) const;
1109 
1114  virtual std::string description (const OutputStyle style=Machine) const;
1115 
1121  virtual std::unique_ptr<PatternBase> clone () const;
1122 
1128  static std::unique_ptr<DirectoryName> create(const std::string &description);
1129 
1130  private:
1134  static const char *description_init;
1135  };
1136 
1137 
1215  namespace Tools
1216  {
1228  template <class T, class Enable = void>
1229  struct Convert
1230  {
1231 
1240  static std::unique_ptr<Patterns::PatternBase> to_pattern() = delete;
1241 
1251  static std::string to_string(const T &s,
1252  const std::unique_ptr<Patterns::PatternBase>
1253  &p = Convert<T>::to_pattern()) = delete;
1254 
1263  static T to_value(const std::string &s,
1264  const std::unique_ptr<Patterns::PatternBase> &p =
1265  Convert<T>::to_pattern()) = delete;
1266  };
1267 
1288  template<typename T>
1289  std::string to_string(const T &t);
1290 
1318  template<typename T>
1319  void to_value(const std::string &s, T &t);
1320 
1330  std::string,
1332  << "The string " << arg1 << " does not match the pattern \""
1333  << arg2.description()
1334  << "\"");
1336  }
1337 }
1338 
1339 
1340 // ---------------------- inline and template functions --------------------
1341 namespace Patterns
1342 {
1343  template<class... PatternTypes>
1344  Tuple::Tuple(const char *separator,
1345  const PatternTypes &... ps)
1346  :
1347  // forward to the version with std::string argument
1348  Tuple (std::string(separator), ps...)
1349  {}
1350 
1351 
1352 
1353  template<class... PatternTypes>
1354  Tuple::Tuple(const std::string &separator,
1355  const PatternTypes &... ps)
1356  :
1357  separator (separator)
1358  {
1360  "Not all of the input arguments of this function "
1361  "are derived from PatternBase");
1362  static_assert(sizeof...(ps) > 0,
1363  "The number of PatternTypes must be greater than zero!");
1364  auto pattern_pointers = { (static_cast<const PatternBase *>(&ps))... };
1365  for (auto p : pattern_pointers)
1366  patterns.push_back (p->clone());
1367  }
1368 
1369 
1370 
1371  template<class... PatternTypes>
1372  Tuple::Tuple(const PatternTypes &... ps)
1373  :
1374  // forward to the version with the separator argument
1375  Tuple (std::string(":"), ps...)
1376  {}
1377 
1378 
1379 
1380  namespace Tools
1381  {
1382  namespace internal
1383  {
1410  template <class T, class Enable = void>
1411  struct RankInfo
1412  {
1413  static constexpr int list_rank = 0;
1414  static constexpr int map_rank = 0;
1415  };
1416  }
1417 
1418  // Arithmetic types
1419  template <class T>
1420  struct Convert<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
1421  {
1422 
1423  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1424  {
1425  if (std::is_same<T,bool>::value)
1426  return std_cxx14::make_unique<Patterns::Bool>();
1427  else if (std::is_integral<T>::value)
1428  return std_cxx14::make_unique<Patterns::Integer>(
1429  std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
1430  else if (std::is_floating_point<T>::value)
1431  return std_cxx14::make_unique<Patterns::Double>(
1432  -std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
1433 
1434  Assert(false, ExcNotImplemented());
1435  //the following line should never be invoked
1436  return nullptr;
1437  }
1438 
1439  static std::string to_string(const T &value,
1440  const std::unique_ptr<Patterns::PatternBase>
1441  &p = Convert<T>::to_pattern())
1442  {
1443  std::stringstream str;
1444  if (std::is_same<T, unsigned char>::value ||
1445  std::is_same<T, signed char>::value ||
1446  std::is_same<T, char>::value)
1447  str << (int)value;
1448  else if (std::is_same<T,bool>::value)
1449  str << (value ? "true" : "false");
1450  else
1451  str << value;
1452  AssertThrow(p->match(str.str()), ExcNoMatch(str.str(), *p));
1453  return str.str();
1454  }
1455 
1456  static T to_value(const std::string &s,
1457  const std::unique_ptr<Patterns::PatternBase> &p =
1459  {
1460  AssertThrow(p->match(s), ExcNoMatch(s, *p));
1461  T value;
1462  if (std::is_same<T,bool>::value)
1463  value = (s == "true");
1464  else
1465  {
1466  std::istringstream is(s);
1467  if (std::is_same<T, unsigned char>::value ||
1468  std::is_same<T, signed char>::value ||
1469  std::is_same<T, char>::value)
1470  {
1471  int i;
1472  is >> i;
1473  value = i;
1474  }
1475  else
1476  is >> value;
1477 
1478  // If someone passes "123 abc" to the function, the method yields an
1479  // integer 123 alright, but the space terminates the read from the string
1480  // although there is more to come. This case, however, is checked for in
1481  // the call p->match(s) at the beginning of this function, and would
1482  // throw earlier. Here it is safe to assume that if we didn't fail the
1483  // conversion with the operator >>, then we are good to go.
1484  AssertThrow(!is.fail(),
1485  ExcMessage("Failed to convert from \"" + s +
1486  "\" to the type \"" +
1487  boost::core::demangle(typeid(T).name()) + "\""));
1488  }
1489  return value;
1490  }
1491  };
1492 
1493  namespace internal
1494  {
1495  const std::array<std::string, 4> default_list_separator {{"," , ";" , "|" , "%"}};
1496  const std::array<std::string, 4> default_map_separator {{":" , "=" , "@" , "#"}};
1497 
1498  //specialize a type for all of the STL containers and maps
1499  template <typename T> struct is_list_compatible : std::false_type {};
1500  template <typename T, std::size_t N> struct is_list_compatible<std::array <T,N>> : std::true_type {};
1501  template <typename... Args> struct is_list_compatible<std::vector <Args...>> : std::true_type {};
1502  template <typename... Args> struct is_list_compatible<std::deque <Args...>> : std::true_type {};
1503  template <typename... Args> struct is_list_compatible<std::list <Args...>> : std::true_type {};
1504  template <typename... Args> struct is_list_compatible<std::set <Args...>> : std::true_type {};
1505  template <typename... Args> struct is_list_compatible<std::multiset <Args...>> : std::true_type {};
1506  template <typename... Args> struct is_list_compatible<std::unordered_set <Args...>> : std::true_type {};
1507  template <typename... Args> struct is_list_compatible<std::unordered_multiset<Args...>> : std::true_type {};
1508 
1509  template <typename T> struct is_map_compatible : std::false_type {};
1510  template <class Key, class T, class Compare, class Allocator>
1511  struct is_map_compatible<std::map<Key,T,Compare,Allocator>> : std::true_type {};
1512  template <class Key, class T, class Compare, class Allocator>
1513  struct is_map_compatible<std::multimap<Key,T,Compare,Allocator>> : std::true_type {};
1514  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1515  struct is_map_compatible<std::unordered_map<Key,T,Hash,KeyEqual,Allocator>> : std::true_type {};
1516  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1517  struct is_map_compatible<std::unordered_multimap<Key,T,Hash,KeyEqual,Allocator>> : std::true_type {};
1518  }
1519 
1520  // type trait to use the implementation type traits as well as decay the type
1521  template <typename T>
1522  struct is_list_compatible
1523  {
1524  static constexpr bool const value =
1525  internal::is_list_compatible<typename std::decay<T>::type>::value;
1526  };
1527 
1528  template <typename T>
1529  struct is_map_compatible
1530  {
1531  static constexpr bool const value =
1532  internal::is_map_compatible<typename std::decay<T>::type>::value;
1533  };
1534 
1535  namespace internal
1536  {
1537  // Helper function for list_rank
1538  template <class T>
1539  constexpr int max_list_rank()
1540  {
1541  return RankInfo<T>::list_rank;
1542  }
1543 
1544  template <class T1, class T2, class... Types>
1545  constexpr int max_list_rank()
1546  {
1547  return std_cxx14::max(RankInfo<T1>::list_rank,
1548  max_list_rank<T2,Types...>());
1549  }
1550 
1551  // Helper function for map_rank
1552  template <class T>
1553  constexpr int max_map_rank()
1554  {
1555  return RankInfo<T>::map_rank;
1556  }
1557 
1558  template <class T1, class T2, class... Types>
1559  constexpr int max_map_rank()
1560  {
1561  return std_cxx14::max(RankInfo<T1>::map_rank,
1562  max_map_rank<T2,Types...>());
1563  }
1564 
1565  // Rank of vector types
1566  template <class T>
1567  struct RankInfo<T,
1568  typename std::enable_if<is_list_compatible<T>::value>::type>
1569  {
1570  static constexpr int list_rank =
1571  RankInfo<typename T::value_type>::list_rank + 1;
1572  static constexpr int map_rank =
1573  RankInfo<typename T::value_type>::map_rank;
1574  };
1575 
1576  // Rank of map types
1577  template <class T>
1578  struct RankInfo<T, typename std::enable_if<is_map_compatible<T>::value>::type>
1579  {
1580  static constexpr int list_rank =
1581  max_list_rank<typename T::key_type, typename T::mapped_type>() + 1;
1582  static constexpr int map_rank =
1583  max_map_rank<typename T::key_type, typename T::mapped_type>() + 1;
1584  };
1585 
1586  // Rank of Tensor types
1587  template <int rank, int dim, class Number>
1588  struct RankInfo<Tensor<rank, dim, Number>>
1589  {
1590  static constexpr int list_rank = rank + RankInfo<Number>::list_rank;
1591  static constexpr int map_rank = RankInfo<Number>::map_rank;
1592  };
1593 
1594  template <int dim, class Number>
1595  struct RankInfo<Point<dim, Number>> : RankInfo<Tensor<1, dim, Number>>
1596  {
1597  };
1598 
1599  // Rank of complex types
1600  template <class Number>
1601  struct RankInfo<std::complex<Number>>
1602  {
1603  static constexpr int list_rank = RankInfo<Number>::list_rank + 1;
1604  static constexpr int map_rank = RankInfo<Number>::map_rank;
1605  };
1606 
1607  template <class Key, class Value>
1608  struct RankInfo<std::pair<Key,Value>>
1609  {
1610  static constexpr int list_rank = std_cxx14::max(RankInfo<Key>::list_rank, RankInfo<Value>::list_rank);
1611  static constexpr int map_rank = std_cxx14::max(RankInfo<Key>::map_rank, RankInfo<Value>::map_rank)+1;
1612  };
1613 
1614 
1615  template <class... Types>
1616  struct RankInfo<std::tuple<Types...>>
1617  {
1618  static constexpr int list_rank = max_list_rank<Types...>();
1619  static constexpr int map_rank = max_map_rank<Types...>()+1;
1620  };
1621  }
1622 
1623  // stl containers
1624  template <class T>
1625  struct Convert<T, typename std::enable_if<is_list_compatible<T>::value>::type>
1626  {
1627  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1628  {
1629  static_assert(internal::RankInfo<T>::list_rank > 0,
1630  "Cannot use this class for non List-compatible types.");
1631  return std_cxx14::make_unique<Patterns::List>(
1633  0,
1634  std::numeric_limits<unsigned int>::max(),
1635  internal::default_list_separator[internal::RankInfo<T>::list_rank - 1]);
1636  }
1637 
1638  static std::string to_string(const T &t,
1639  const std::unique_ptr<Patterns::PatternBase>
1640  &pattern = Convert<T>::to_pattern())
1641  {
1642  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1643  AssertThrow(p, ExcMessage("I need a List pattern to convert a "
1644  "string to a List type."));
1645  auto base_p = p->get_base_pattern().clone();
1646  std::vector<std::string> vec(t.size());
1647 
1648  unsigned int i = 0;
1649  for (const auto &ti : t)
1650  vec[i++] = Convert<typename T::value_type>::to_string(ti, base_p);
1651 
1652  std::string s;
1653  if (vec.size() > 0)
1654  s = vec[0];
1655  for (unsigned int i = 1; i < vec.size(); ++i)
1656  s += p->get_separator() + " " + vec[i];
1657 
1658  AssertThrow(pattern->match(s), ExcNoMatch(s, *p));
1659  return s;
1660  }
1661 
1662  static T to_value(const std::string &s,
1663  const std::unique_ptr<Patterns::PatternBase> &pattern =
1665  {
1666 
1667  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1668 
1669  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1670  AssertThrow(p,ExcMessage("I need a List pattern to convert a string "
1671  "to a List type."));
1672 
1673  auto base_p = p->get_base_pattern().clone();
1674  T t;
1675 
1676  auto v = Utilities::split_string_list(s, p->get_separator());
1677  for (const auto &str : v)
1678  t.insert(t.end(),
1680 
1681  return t;
1682  }
1683  };
1684 
1685  // stl maps
1686  template <class T>
1687  struct Convert<T, typename std::enable_if<is_map_compatible<T>::value>::type>
1688  {
1689  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1690  {
1691  static_assert(internal::RankInfo<T>::list_rank > 0,
1692  "Cannot use this class for non List-compatible types.");
1693  static_assert(internal::RankInfo<T>::map_rank > 0,
1694  "Cannot use this class for non Map-compatible types.");
1695  return std_cxx14::make_unique<Patterns::Map>(
1698  0,
1699  std::numeric_limits<unsigned int>::max(),
1700  internal::default_list_separator[internal::RankInfo<T>::list_rank - 1],
1701  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
1702  }
1703 
1704  static std::string to_string(const T &t,
1705  const std::unique_ptr<Patterns::PatternBase>
1706  &pattern = Convert<T>::to_pattern())
1707  {
1708  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1709  AssertThrow(p, ExcMessage("I need a Map pattern to convert a string to "
1710  "a Map compatbile type."));
1711  auto key_p = p->get_key_pattern().clone();
1712  auto val_p = p->get_value_pattern().clone();
1713  std::vector<std::string> vec(t.size());
1714 
1715  unsigned int i = 0;
1716  for (const auto &ti : t)
1717  vec[i++] =
1718  Convert<typename T::key_type>::to_string(ti.first, key_p) +
1719  p->get_key_value_separator() +
1721 
1722  std::string s;
1723  if (vec.size() > 0)
1724  s = vec[0];
1725  for (unsigned int i = 1; i < vec.size(); ++i)
1726  s += p->get_separator() + " " + vec[i];
1727 
1728  AssertThrow(p->match(s), ExcNoMatch(s, *p));
1729  return s;
1730  }
1731 
1732  static T to_value(const std::string &s,
1733  const std::unique_ptr<Patterns::PatternBase> &pattern =
1735  {
1736 
1737  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1738 
1739  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1740  AssertThrow(p, ExcMessage("I need a Map pattern to convert a "
1741  "string to a Map compatible type."));
1742 
1743  auto key_p = p->get_key_pattern().clone();
1744  auto val_p = p->get_value_pattern().clone();
1745  T t;
1746 
1747  auto v = Utilities::split_string_list(s, p->get_separator());
1748  for (const auto &str : v)
1749  {
1750  auto key_val =
1751  Utilities::split_string_list(str, p->get_key_value_separator());
1752  AssertDimension(key_val.size(), 2);
1753  t.insert(std::make_pair(
1754  Convert<typename T::key_type>::to_value(key_val[0], key_p),
1756  }
1757 
1758  return t;
1759  }
1760  };
1761 
1762  // Tensors
1763  template <int rank, int dim, class Number>
1764  struct Convert<Tensor<rank, dim, Number>>
1765  {
1766  typedef Tensor<rank, dim, Number> T;
1767  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1768  {
1769  static_assert(internal::RankInfo<T>::list_rank > 0,
1770  "Cannot use this class for non List-compatible types.");
1771  return std_cxx14::make_unique<Patterns::List>(
1773  dim,
1774  dim,
1775  internal::default_list_separator[internal::RankInfo<T>::list_rank - 1]);
1776  }
1777 
1778  static std::string to_string(const T &t,
1779  const std::unique_ptr<Patterns::PatternBase>
1780  &pattern = Convert<T>::to_pattern())
1781  {
1782 
1783  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1784  AssertThrow(p,ExcMessage("I need a List pattern to convert a string "
1785  "to a List compatbile type."));
1786  auto base_p = p->get_base_pattern().clone();
1787  std::vector<std::string> vec(dim);
1788 
1789  for (unsigned int i = 0; i < dim; ++i)
1790  vec[i] = Convert<typename T::value_type>::to_string(t[i], base_p);
1791 
1792  std::string s;
1793  if (vec.size() > 0)
1794  s = vec[0];
1795  for (unsigned int i = 1; i < vec.size(); ++i)
1796  s += p->get_separator() + " " + vec[i];
1797 
1798  AssertThrow(p->match(s), ExcNoMatch(s, *p));
1799  return s;
1800  }
1801 
1802  static T to_value(const std::string &s,
1803  const std::unique_ptr<Patterns::PatternBase> &pattern =
1805  {
1806 
1807  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1808 
1809  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1810  AssertThrow(p,ExcMessage("I need a List pattern to convert a string "
1811  "to a List compatbile type."));
1812 
1813  auto base_p = p->get_base_pattern().clone();
1814  T t;
1815 
1816  auto v = Utilities::split_string_list(s, p->get_separator());
1817  unsigned int i = 0;
1818  for (const auto &str : v)
1819  t[i++] = Convert<typename T::value_type>::to_value(str, base_p);
1820 
1821  return t;
1822  }
1823  };
1824 
1825  // Points
1826  template <int dim, class Number>
1827  struct Convert<Point<dim, Number>>
1828  {
1829 
1830  typedef Point<dim, Number> T;
1831 
1832  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1833  {
1834  return Convert<Tensor<1, dim, Number>>::to_pattern();
1835  }
1836 
1837  static std::string to_string(const T &t,
1838  const std::unique_ptr<Patterns::PatternBase>
1839  &pattern = Convert<T>::to_pattern())
1840  {
1841  return Convert<Tensor<1, dim, Number>>::to_string(
1842  Tensor<1, dim, Number>(t), pattern);
1843  }
1844 
1845  static T to_value(const std::string &s,
1846  const std::unique_ptr<Patterns::PatternBase> &pattern =
1848  {
1849  return T(Convert<Tensor<1, dim, Number>>::to_value(s, pattern));
1850  }
1851  };
1852 
1853  // Complex numbers
1854  template <class Number>
1855  struct Convert<std::complex<Number>>
1856  {
1857  typedef std::complex<Number> T;
1858 
1859  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1860  {
1861  static_assert(internal::RankInfo<T>::list_rank > 0,
1862  "Cannot use this class for non List-compatible types.");
1863  return std_cxx14::make_unique<Patterns::List>(
1865  2,
1866  2,
1867  internal::default_list_separator[internal::RankInfo<T>::list_rank - 1]);
1868  }
1869 
1870  static std::string to_string(const T &t,
1871  const std::unique_ptr<Patterns::PatternBase>
1872  &pattern = Convert<T>::to_pattern())
1873  {
1874 
1875  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1876  AssertThrow(p,ExcMessage("I need a List pattern to convert a string "
1877  "to a List compatbile type."));
1878 
1879  auto base_p = p->get_base_pattern().clone();
1880  std::string s =
1881  Convert<typename T::value_type>::to_string(t.real(), base_p) +
1882  p->get_separator() + " " +
1884 
1885  AssertThrow(pattern->match(s), ExcNoMatch(s, *p));
1886  return s;
1887  }
1888 
1892  static T to_value(const std::string &s,
1893  const std::unique_ptr<Patterns::PatternBase> &pattern =
1895  {
1896 
1897  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1898 
1899  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1900  AssertThrow(p,ExcMessage("I need a List pattern to convert a string "
1901  "to a List compatbile type."));
1902 
1903  auto base_p = p->get_base_pattern().clone();
1904 
1905  auto v = Utilities::split_string_list(s, p->get_separator());
1906  AssertDimension(v.size(), 2);
1909  return t;
1910  }
1911  };
1912 
1913  // Strings
1914  template <>
1915  struct Convert<std::string>
1916  {
1917  typedef std::string T;
1918 
1919  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1920  {
1921  return std_cxx14::make_unique<Patterns::Anything>();
1922  }
1923 
1924  static std::string to_string(const T &t,
1925  const std::unique_ptr<Patterns::PatternBase>
1926  &pattern = Convert<T>::to_pattern())
1927  {
1928  AssertThrow(pattern->match(t), ExcNoMatch(t, *pattern));
1929  return t;
1930  }
1931 
1932  static T to_value(const std::string &s,
1933  const std::unique_ptr<Patterns::PatternBase> &pattern =
1935  {
1936  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1937  return s;
1938  }
1939  };
1940 
1941  // Pairs
1942  template <class Key, class Value>
1943  struct Convert<std::pair<Key,Value>>
1944  {
1945  typedef std::pair<Key,Value> T;
1946 
1947  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1948  {
1949  static_assert(internal::RankInfo<T>::map_rank > 0,
1950  "Cannot use this class for non Map-compatible types.");
1951  return std_cxx14::make_unique<Patterns::Map>(
1954  1, 1,
1955  // We keep the same list separator of the previous level, as this is
1956  // a map with only 1 possible entry
1957  internal::default_list_separator[internal::RankInfo<T>::list_rank],
1958  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
1959  }
1960 
1961  static std::string to_string(const T &t,
1962  const std::unique_ptr<Patterns::PatternBase>
1963  &pattern = Convert<T>::to_pattern())
1964  {
1965  std::unordered_map<Key, Value> m;
1966  m.insert(t);
1967  std:: string s = Convert<decltype(m)>::to_string(m, pattern);
1968  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
1969  return s;
1970  }
1971 
1972  static T to_value(const std::string &s,
1973  const std::unique_ptr<Patterns::PatternBase> &pattern =
1975  {
1976  std::unordered_map<Key, Value> m;
1977  m = Convert<decltype(m)>::to_value(s, pattern);
1978  return *m.begin();
1979  }
1980  };
1981 
1982  // Tuples
1983  template <class... Args>
1984  struct Convert<std::tuple<Args...>>
1985  {
1986  typedef std::tuple<Args...> T;
1987 
1988  static std::unique_ptr<Patterns::PatternBase> to_pattern()
1989  {
1990  static_assert(internal::RankInfo<T>::map_rank > 0,
1991  "Cannot use this class for non tuple-compatible types.");
1992  return std_cxx14::make_unique<Patterns::Tuple>(
1993  internal::default_map_separator[internal::RankInfo<T>::map_rank-1],
1995  }
1996 
1997  static std::string to_string(const T &t,
1998  const std::unique_ptr<Patterns::PatternBase>
1999  &pattern = Convert<T>::to_pattern())
2000  {
2001  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2002  AssertThrow(p,ExcMessage("I need a Tuple pattern to convert a tuple "
2003  "to a string."));
2004 
2005  const auto string_array = Convert<T>::to_string_internal_2(t,*p);
2006  std::string str;
2007  for (unsigned int i=0; i< string_array.size(); ++i)
2008  str += (i ? " " + p->get_separator() + " " : "") +string_array[i];
2009  AssertThrow(p->match(str), ExcNoMatch(str, *p));
2010  return str;
2011  }
2012 
2013  static T to_value(const std::string &s,
2014  const std::unique_ptr<Patterns::PatternBase> &pattern =
2016  {
2017  AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern));
2018 
2019  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2020  AssertThrow(p,ExcMessage("I need a Tuple pattern to convert a string "
2021  "to a tuple type."));
2022 
2023  auto v = Utilities::split_string_list(s, p->get_separator());
2024 
2025  return Convert<T>::to_value_internal_2(v,*p);
2026  }
2027 
2028  private:
2029  template<std::size_t... I>
2030  static
2031  std::array<std::string, std::tuple_size<T>::value>
2032  to_string_internal_1(const T &t,
2033  const Patterns::Tuple &pattern,
2034  std_cxx14::index_sequence<I...>)
2035  {
2036  std::array<std::string, std::tuple_size<T>::value> a
2037  = {{
2038  Convert<typename std::tuple_element<I,T>::type>::
2039  to_string(std::get<I>(t), pattern.get_pattern(I).clone())...
2040  }
2041  };
2042  return a;
2043  }
2044 
2045  static
2046  std::array<std::string, std::tuple_size<T>::value>
2047  to_string_internal_2(const T &t,
2048  const Patterns::Tuple &pattern)
2049  {
2050  return Convert<T>::to_string_internal_1(t, pattern,
2051  std_cxx14::make_index_sequence<std::tuple_size<T>::value> {});
2052  }
2053 
2054  template<std::size_t... I>
2055  static
2056  T to_value_internal_1(const std::vector<std::string> &s,
2057  const Patterns::Tuple &pattern,
2058  std_cxx14::index_sequence<I...>)
2059  {
2060  return std::make_tuple(Convert<typename std::tuple_element<I,T>::type>::
2061  to_value(s[I], pattern.get_pattern(I).clone())...);
2062  }
2063 
2064  static
2065  T to_value_internal_2(const std::vector<std::string> &s,
2066  const Patterns::Tuple &pattern)
2067  {
2068  return Convert<T>::to_value_internal_1(s, pattern,
2069  std_cxx14::make_index_sequence<std::tuple_size<T>::value> {});
2070  }
2071  };
2072 
2073  // Utility function with default Pattern
2074  template<typename T>
2075  std::string to_string(const T &t)
2076  {
2077  return Convert<T>::to_string(t);
2078  }
2079 
2080  // Utility function with default Pattern
2081  template<typename T>
2082  void to_value(const std::string &s, T &t)
2083  {
2084  t = Convert<T>::to_value(s);
2085  }
2086  }
2087 }
2088 
2089 
2090 DEAL_II_NAMESPACE_CLOSE
2091 
2092 #endif
const std::string & get_separator() const
Definition: patterns.cc:657
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:283
std::size_t memory_consumption() const
Definition: patterns.cc:743
const std::string & get_separator() const
Definition: patterns.cc:1189
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:219
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:526
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:358
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
void to_value(const std::string &s, T &t)
Definition: patterns.h:2082
static std::unique_ptr< FileName > create(const std::string &description)
Definition: patterns.cc:1512
std::string sequence
Definition: patterns.h:405
const double upper_bound
Definition: patterns.h:341
static const char * description_init
Definition: patterns.h:346
static const char * description_init
Definition: patterns.h:1080
static std::unique_ptr< Tuple > create(const std::string &description)
Definition: patterns.cc:1137
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:1402
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1381
const PatternBase & get_value_pattern() const
Definition: patterns.cc:990
const std::string separator
Definition: patterns.h:835
static T to_value(const std::string &s, const std::unique_ptr< Patterns::PatternBase > &p=Convert< T >::to_pattern())=delete
std::size_t memory_consumption() const
Definition: patterns.cc:1318
const std::string separator
Definition: patterns.h:663
static std::unique_ptr< List > create(const std::string &description)
Definition: patterns.cc:752
std::unique_ptr< PatternBase > pattern
Definition: patterns.h:509
static std::unique_ptr< Patterns::PatternBase > to_pattern()=delete
static const unsigned int max_int_value
Definition: patterns.h:555
virtual std::unique_ptr< PatternBase > clone() const =0
static const char * description_init
Definition: patterns.h:674
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:1541
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:557
STL namespace.
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:916
static const int max_int_value
Definition: patterns.h:193
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
const std::string & get_separator() const
Definition: patterns.cc:997
const unsigned int max_elements
Definition: patterns.h:658
static ::ExceptionBase & ExcCommasNotAllowed(int arg1)
static const char * description_init
Definition: patterns.h:918
Definition: point.h:104
FileType file_type
Definition: patterns.h:1067
static std::unique_ptr< Anything > create(const std::string &description)
Definition: patterns.cc:1444
Tuple(const std::vector< std::unique_ptr< PatternBase > > &patterns, const std::string &separator=":")
Definition: patterns.cc:1013
static const int min_int_value
Definition: patterns.h:186
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:592
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
const double lower_bound
Definition: patterns.h:333
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1437
FileName(const FileType type=input)
Definition: patterns.cc:1457
static const char * description_init
Definition: patterns.h:529
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char * description_init
Definition: patterns.h:957
static std::unique_ptr< DirectoryName > create(const std::string &description)
Definition: patterns.cc:1582
static const char * description_init
Definition: patterns.h:410
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:346
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1276
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1353
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:830
const PatternBase & get_key_pattern() const
Definition: patterns.cc:983
Double(const double lower_bound=min_double_value, const double upper_bound=max_double_value)
Definition: patterns.cc:348
#define Assert(cond, exc)
Definition: exceptions.h:1142
List(const PatternBase &base_pattern, const unsigned int min_elements=0, const unsigned int max_elements=max_int_value, const std::string &separator=",")
Definition: patterns.cc:630
MultipleSelection(const std::string &seq)
Definition: patterns.cc:1199
virtual std::size_t memory_consumption() const
Definition: patterns.cc:189
static const char * description_init
Definition: patterns.h:252
static std::unique_ptr< Map > create(const std::string &description)
Definition: patterns.cc:936
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
static const char * description_init
Definition: patterns.h:840
std::unique_ptr< PatternBase > key_pattern
Definition: patterns.h:647
const PatternBase & get_base_pattern() const
Definition: patterns.cc:664
static std::unique_ptr< Double > create(const std::string &description)
Definition: patterns.cc:474
virtual ~PatternBase()=default
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1470
std::string to_string(const T &t)
Definition: patterns.h:2075
std::size_t memory_consumption() const
Definition: patterns.cc:599
static const double min_double_value
Definition: patterns.h:279
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:864
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
Definition: patterns.cc:137
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:835
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:304
static const char * description_init
Definition: patterns.h:1134
const std::string & get_key_value_separator() const
Definition: patterns.cc:1003
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:690
virtual bool match(const std::string &test_string) const =0
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:241
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:736
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:1212
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:1047
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:467
static const char * description_init
Definition: patterns.h:1002
std::size_t memory_consumption() const
Definition: patterns.cc:925
static const double max_double_value
Definition: patterns.h:285
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1065
const PatternBase & get_pattern(const unsigned int &i) const
Definition: patterns.cc:1182
virtual std::string description(const OutputStyle style=Machine) const =0
Definition: mpi.h:53
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:671
static std::unique_ptr< MultipleSelection > create(const std::string &description)
Definition: patterns.cc:1326
Integer(const int lower_bound=min_int_value, const int upper_bound=max_int_value)
Definition: patterns.cc:210
static std::unique_ptr< Bool > create(const std::string &description)
Definition: patterns.cc:1388
static std::unique_ptr< Selection > create(const std::string &description)
Definition: patterns.cc:607
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1311
const int upper_bound
Definition: patterns.h:247
Selection(const std::string &seq)
Definition: patterns.cc:515
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1505
static ::ExceptionBase & ExcNotImplemented()
Map(const PatternBase &key_pattern, const PatternBase &value_pattern, const unsigned int min_elements=0, const unsigned int max_elements=max_int_value, const std::string &separator=",", const std::string &key_value_separator=":")
Definition: patterns.cc:795
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:1463
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1575
const unsigned int min_elements
Definition: patterns.h:653
static ::ExceptionBase & ExcNoMatch(std::string arg1, Patterns::PatternBase &arg2)
static const unsigned int max_int_value
Definition: patterns.h:429
const int lower_bound
Definition: patterns.h:239
const std::string separator
Definition: patterns.h:524
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1548
const std::string key_value_separator
Definition: patterns.h:669
const unsigned int max_elements
Definition: patterns.h:519
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:1409
virtual std::unique_ptr< PatternBase > clone() const
Definition: patterns.cc:1121
virtual bool match(const std::string &test_string) const
Definition: patterns.cc:357
const unsigned int min_elements
Definition: patterns.h:514
static std::unique_ptr< Integer > create(const std::string &description)
Definition: patterns.cc:311
virtual std::string description(const OutputStyle style=Machine) const
Definition: patterns.cc:380
std::size_t memory_consumption() const
Definition: patterns.cc:1128
static std::string to_string(const T &s, const std::unique_ptr< Patterns::PatternBase > &p=Convert< T >::to_pattern())=delete