16 #ifndef dealii_patterns_h 17 #define dealii_patterns_h 20 #include <deal.II/base/config.h> 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> 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> 44 #include <type_traits> 45 #include <unordered_map> 46 #include <unordered_set> 50 DEAL_II_NAMESPACE_OPEN
84 match(
const std::string &test_string)
const = 0;
126 virtual std::unique_ptr<PatternBase>
151 std::unique_ptr<PatternBase>
211 Integer(
const int lower_bound = min_int_value,
212 const int upper_bound = max_int_value);
219 match(
const std::string &test_string)
const override;
234 virtual std::unique_ptr<PatternBase>
235 clone()
const override;
242 static std::unique_ptr<Integer>
307 Double(
const double lower_bound = min_double_value,
308 const double upper_bound = max_double_value);
315 match(
const std::string &test_string)
const override;
330 virtual std::unique_ptr<PatternBase>
331 clone()
const override;
340 static std::unique_ptr<Double>
389 match(
const std::string &test_string)
const override;
404 virtual std::unique_ptr<PatternBase>
405 clone()
const override;
419 static std::unique_ptr<Selection>
420 create(
const std::string &description);
462 const unsigned int min_elements = 0,
463 const unsigned int max_elements = max_int_value,
464 const std::string &separator =
",");
471 get_separator()
const;
477 get_base_pattern()
const;
489 match(
const std::string &test_string)
const override;
503 virtual std::unique_ptr<PatternBase>
504 clone()
const override;
511 static std::unique_ptr<List>
532 <<
"The values " << arg1 <<
" and " << arg2
533 <<
" do not form a valid range.");
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 =
":");
612 match(
const std::string &test_string)
const override;
626 virtual std::unique_ptr<PatternBase>
627 clone()
const override;
634 static std::unique_ptr<Map>
648 get_key_pattern()
const;
654 get_value_pattern()
const;
660 get_separator()
const;
666 get_key_value_separator()
const;
679 <<
"The values " << arg1 <<
" and " << arg2
680 <<
" do not form a valid range.");
688 std::unique_ptr<PatternBase> value_pattern;
777 Tuple(
const std::vector<std::unique_ptr<PatternBase>> &patterns,
778 const std::string & separator =
":");
785 Tuple(
const std::vector<std::unique_ptr<PatternBase>> &patterns,
786 const char * separator);
796 template <
class... PatternTypes>
797 Tuple(
const std::string &separator,
const PatternTypes &... patterns);
806 template <
class... PatternTypes>
807 Tuple(
const char *separator,
const PatternTypes &... patterns);
815 Tuple(
const Patterns &... patterns);
820 Tuple(
const Tuple &other);
827 match(
const std::string &test_string)
const override;
841 virtual std::unique_ptr<PatternBase>
842 clone()
const override;
849 static std::unique_ptr<Tuple>
850 create(
const std::string &description);
863 get_pattern(
const unsigned int &i)
const;
869 get_separator()
const;
875 std::vector<std::unique_ptr<PatternBase>>
patterns;
912 match(
const std::string &test_string)
const override;
927 virtual std::unique_ptr<PatternBase>
928 clone()
const override;
935 static std::unique_ptr<MultipleSelection>
936 create(
const std::string &description);
956 <<
"A comma was found at position " << arg1
957 <<
" of your input string, but commas are not allowed here.");
996 virtual std::unique_ptr<PatternBase>
997 clone()
const override;
1004 static std::unique_ptr<Bool>
1005 create(
const std::string &description);
1031 match(
const std::string &test_string)
const override;
1045 virtual std::unique_ptr<PatternBase>
1046 clone()
const override;
1053 static std::unique_ptr<Anything>
1054 create(
const std::string &description);
1108 match(
const std::string &test_string)
const override;
1122 virtual std::unique_ptr<PatternBase>
1123 clone()
const override;
1135 static std::unique_ptr<FileName>
1171 match(
const std::string &test_string)
const override;
1185 virtual std::unique_ptr<PatternBase>
1186 clone()
const override;
1193 static std::unique_ptr<DirectoryName>
1194 create(
const std::string &description);
1296 template <
class T,
class Enable =
void>
1308 static std::unique_ptr<Patterns::PatternBase>
1309 to_pattern() =
delete;
1323 const std::unique_ptr<Patterns::PatternBase> &p =
1337 const std::unique_ptr<Patterns::PatternBase> &p =
1361 template <
typename T>
1392 template <
typename T>
1394 to_value(
const std::string &s, T &t);
1407 <<
"The string " << arg1 <<
" does not match the pattern \"" 1417 template <
class... PatternTypes>
1420 Tuple(
std::string(separator), ps...)
1425 template <
class... PatternTypes>
1427 : separator(separator)
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)
1441 template <
class... PatternTypes>
1479 template <
class T,
class Enable =
void>
1482 static constexpr
int list_rank = 0;
1483 static constexpr
int map_rank = 0;
1490 typename std::enable_if<std::is_arithmetic<T>::value>::type>
1492 static std::unique_ptr<Patterns::PatternBase>
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());
1511 const std::unique_ptr<Patterns::PatternBase> &p =
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)
1518 else if (std::is_same<T, bool>::value)
1519 str << (value ?
"true" :
"false");
1528 const std::unique_ptr<Patterns::PatternBase> &p =
1533 if (std::is_same<T, bool>::value)
1534 value = (s ==
"true");
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)
1558 ExcMessage(
"Failed to convert from \"" + s +
"\" to the type \"" +
1559 boost::core::demangle(
typeid(T).name()) +
"\""));
1567 const std::array<std::string, 4> default_list_separator{
1568 {
",",
";",
"|",
"%"}};
1569 const std::array<std::string, 4> default_map_separator{
1570 {
":",
"=",
"@",
"#"}};
1573 template <
typename T>
1574 struct is_list_compatible : std::false_type
1576 template <
typename T, std::
size_t N>
1577 struct is_list_compatible<std::array<T, N>> : std::true_type
1579 template <
typename... Args>
1580 struct is_list_compatible<std::vector<Args...>> : std::true_type
1582 template <
typename... Args>
1583 struct is_list_compatible<std::deque<Args...>> : std::true_type
1585 template <
typename... Args>
1586 struct is_list_compatible<std::list<Args...>> : std::true_type
1588 template <
typename... Args>
1589 struct is_list_compatible<std::set<Args...>> : std::true_type
1591 template <
typename... Args>
1592 struct is_list_compatible<std::multiset<Args...>> : std::true_type
1594 template <
typename... Args>
1595 struct is_list_compatible<std::unordered_set<Args...>> : std::true_type
1597 template <
typename... Args>
1598 struct is_list_compatible<std::unordered_multiset<Args...>>
1602 template <
typename T>
1603 struct is_map_compatible : std::false_type
1605 template <
class Key,
class T,
class Compare,
class Allocator>
1606 struct is_map_compatible<std::map<Key, T, Compare, Allocator>>
1609 template <
class Key,
class T,
class Compare,
class Allocator>
1610 struct is_map_compatible<std::multimap<Key, T, Compare, Allocator>>
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
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>>
1626 template <
typename T>
1627 struct is_list_compatible
1629 static constexpr
bool const value =
1630 internal::is_list_compatible<typename std::decay<T>::type>::value;
1633 template <
typename T>
1634 struct is_map_compatible
1636 static constexpr
bool const value =
1637 internal::is_map_compatible<typename std::decay<T>::type>::value;
1650 template <
class T1,
class T2,
class... Types>
1655 max_list_rank<T2, Types...>());
1666 template <
class T1,
class T2,
class... Types>
1671 max_map_rank<T2, Types...>());
1678 typename std::enable_if<is_list_compatible<T>::value>::type>
1680 static constexpr
int list_rank =
1682 static constexpr
int map_rank =
1690 typename std::enable_if<is_map_compatible<T>::value>::type>
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;
1699 template <
int rank,
int dim,
class Number>
1700 struct RankInfo<Tensor<rank, dim, Number>>
1706 template <
int dim,
class Number>
1711 template <
class Number>
1712 struct RankInfo<std::complex<Number>>
1718 template <
class Key,
class Value>
1719 struct RankInfo<std::pair<Key, Value>>
1721 static constexpr
int list_rank =
1723 static constexpr
int map_rank =
1729 template <
class... Types>
1730 struct RankInfo<std::tuple<Types...>>
1732 static constexpr
int list_rank = max_list_rank<Types...>();
1733 static constexpr
int map_rank = max_map_rank<Types...>() + 1;
1740 typename std::enable_if<is_list_compatible<T>::value>::type>
1742 static std::unique_ptr<Patterns::PatternBase>
1746 "Cannot use this class for non List-compatible types.");
1747 return std_cxx14::make_unique<Patterns::List>(
1750 std::numeric_limits<unsigned int>::max(),
1757 const std::unique_ptr<Patterns::PatternBase> &pattern =
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());
1768 for (
const auto &ti : t)
1774 for (
unsigned int i = 1; i < vec.size(); ++i)
1775 s += p->get_separator() +
" " + vec[i];
1783 const std::unique_ptr<Patterns::PatternBase> &pattern =
1790 ExcMessage(
"I need a List pattern to convert a string " 1791 "to a List type."));
1793 auto base_p = p->get_base_pattern().clone();
1797 for (
const auto &str : v)
1808 typename std::enable_if<is_map_compatible<T>::value>::type>
1810 static std::unique_ptr<Patterns::PatternBase>
1814 "Cannot use this class for non List-compatible types.");
1816 "Cannot use this class for non Map-compatible types.");
1817 return std_cxx14::make_unique<Patterns::Map>(
1821 std::numeric_limits<unsigned int>::max(),
1829 const std::unique_ptr<Patterns::PatternBase> &pattern =
1832 auto p =
dynamic_cast<const Patterns::Map *
>(pattern.get());
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());
1841 for (
const auto &ti : t)
1844 p->get_key_value_separator() +
1850 for (
unsigned int i = 1; i < vec.size(); ++i)
1851 s += p->get_separator() +
" " + vec[i];
1859 const std::unique_ptr<Patterns::PatternBase> &pattern =
1864 auto p =
dynamic_cast<const Patterns::Map *
>(pattern.get());
1866 ExcMessage(
"I need a Map pattern to convert a " 1867 "string to a Map compatible type."));
1869 auto key_p = p->get_key_pattern().clone();
1870 auto val_p = p->get_value_pattern().clone();
1874 for (
const auto &str : v)
1879 t.insert(std::make_pair(
1889 template <
int rank,
int dim,
class Number>
1890 struct Convert<Tensor<rank, dim, Number>>
1893 static std::unique_ptr<Patterns::PatternBase>
1897 "Cannot use this class for non List-compatible types.");
1898 return std_cxx14::make_unique<Patterns::List>(
1908 const std::unique_ptr<Patterns::PatternBase> &pattern =
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);
1918 for (
unsigned int i = 0; i < dim; ++i)
1924 for (
unsigned int i = 1; i < vec.size(); ++i)
1925 s += p->get_separator() +
" " + vec[i];
1933 const std::unique_ptr<Patterns::PatternBase> &pattern =
1940 ExcMessage(
"I need a List pattern to convert a string " 1941 "to a List compatbile type."));
1943 auto base_p = p->get_base_pattern().clone();
1948 for (
const auto &str : v)
1956 template <
int dim,
class Number>
1957 struct Convert<Point<dim, Number>>
1961 static std::unique_ptr<Patterns::PatternBase>
1969 const std::unique_ptr<Patterns::PatternBase> &pattern =
1978 const std::unique_ptr<Patterns::PatternBase> &pattern =
1986 template <
class Number>
1987 struct Convert<std::complex<Number>>
1989 using T = std::complex<Number>;
1991 static std::unique_ptr<Patterns::PatternBase>
1995 "Cannot use this class for non List-compatible types.");
1996 return std_cxx14::make_unique<Patterns::List>(
2006 const std::unique_ptr<Patterns::PatternBase> &pattern =
2011 ExcMessage(
"I need a List pattern to convert a string " 2012 "to a List compatbile type."));
2014 auto base_p = p->get_base_pattern().clone();
2017 p->get_separator() +
" " +
2029 const std::unique_ptr<Patterns::PatternBase> &pattern =
2036 ExcMessage(
"I need a List pattern to convert a string " 2037 "to a List compatbile type."));
2039 auto base_p = p->get_base_pattern().clone();
2053 using T = std::string;
2055 static std::unique_ptr<Patterns::PatternBase>
2058 return std_cxx14::make_unique<Patterns::Anything>();
2063 const std::unique_ptr<Patterns::PatternBase> &pattern =
2072 const std::unique_ptr<Patterns::PatternBase> &pattern =
2081 template <
class Key,
class Value>
2082 struct Convert<std::pair<Key, Value>>
2084 using T = std::pair<Key, Value>;
2086 static std::unique_ptr<Patterns::PatternBase>
2090 "Cannot use this class for non Map-compatible types.");
2091 return std_cxx14::make_unique<Patterns::Map>(
2104 const std::unique_ptr<Patterns::PatternBase> &pattern =
2107 std::unordered_map<Key, Value> m;
2116 const std::unique_ptr<Patterns::PatternBase> &pattern =
2119 std::unordered_map<Key, Value> m;
2126 template <
class... Args>
2127 struct Convert<std::tuple<Args...>>
2129 using T = std::tuple<Args...>;
2131 static std::unique_ptr<Patterns::PatternBase>
2135 "Cannot use this class for non tuple-compatible types.");
2136 return std_cxx14::make_unique<Patterns::Tuple>(
2143 const std::unique_ptr<Patterns::PatternBase> &pattern =
2148 ExcMessage(
"I need a Tuple pattern to convert a tuple " 2153 for (
unsigned int i = 0; i < string_array.size(); ++i)
2154 str += (i ?
" " + p->get_separator() +
" " :
"") + string_array[i];
2161 const std::unique_ptr<Patterns::PatternBase> &pattern =
2168 ExcMessage(
"I need a Tuple pattern to convert a string " 2169 "to a tuple type."));
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,
2181 std_cxx14::index_sequence<I...>)
2183 std::array<std::string, std::tuple_size<T>::value> a = {
2189 static std::array<std::string, std::tuple_size<T>::value>
2195 std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2198 template <std::size_t... I>
2200 to_value_internal_1(
const std::vector<std::string> &s,
2202 std_cxx14::index_sequence<I...>)
2204 return std::make_tuple(
2210 to_value_internal_2(
const std::vector<std::string> &s,
2216 std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2221 template <
typename T>
2229 template <
typename T>
2239 DEAL_II_NAMESPACE_CLOSE
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertDimension(dim1, dim2)
static const char * description_init
static const char * description_init
const std::string separator
const std::string separator
std::unique_ptr< PatternBase > pattern
static const unsigned int max_int_value
virtual std::unique_ptr< PatternBase > clone() const =0
static const char * description_init
static const int max_int_value
#define AssertThrow(cond, exc)
const unsigned int max_elements
static const char * description_init
static const int min_int_value
static const char * description_init
static::ExceptionBase & ExcMessage(std::string arg1)
static const char * description_init
static const char * description_init
#define DeclException1(Exception1, type1, outsequence)
std::vector< std::unique_ptr< PatternBase > > patterns
#define Assert(cond, exc)
static const char * description_init
static const char * description_init
std::unique_ptr< PatternBase > key_pattern
virtual ~PatternBase()=default
static const double min_double_value
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
static const char * description_init
virtual bool match(const std::string &test_string) const =0
static const char * description_init
virtual std::size_t memory_consumption() const
static const double max_double_value
static::ExceptionBase & ExcNoMatch(std::string arg1, const Patterns::PatternBase *arg2)
virtual std::string description(const OutputStyle style=Machine) const =0
static::ExceptionBase & ExcNotImplemented()
Tuple(const std::vector< std::unique_ptr< PatternBase >> &patterns, const std::string &separator=":")
const PatternBase & get_pattern(const unsigned int &i) const
const unsigned int min_elements
static const unsigned int max_int_value
const std::string separator
const std::string key_value_separator
const unsigned int max_elements
const unsigned int min_elements