15#ifndef dealii_patterns_h
16#define dealii_patterns_h
30#include <boost/archive/basic_archive.hpp>
31#include <boost/core/demangle.hpp>
32#include <boost/property_tree/ptree_fwd.hpp>
33#include <boost/property_tree/ptree_serialization.hpp>
34#include <boost/serialization/split_member.hpp>
47#include <unordered_map>
48#include <unordered_set>
52#ifdef DEAL_II_WITH_MAGIC_ENUM
53# include <magic_enum.hpp>
94 match(
const std::string &test_string)
const = 0;
136 virtual std::unique_ptr<PatternBase>
161 std::unique_ptr<PatternBase>
229 match(
const std::string &test_string)
const override;
244 virtual std::unique_ptr<PatternBase>
245 clone()
const override;
252 static std::unique_ptr<Integer>
325 match(
const std::string &test_string)
const override;
340 virtual std::unique_ptr<PatternBase>
341 clone()
const override;
350 static std::unique_ptr<Double>
399 match(
const std::string &test_string)
const override;
414 virtual std::unique_ptr<PatternBase>
415 clone()
const override;
429 static std::unique_ptr<Selection>
499 match(
const std::string &test_string)
const override;
513 virtual std::unique_ptr<PatternBase>
514 clone()
const override;
521 static std::unique_ptr<List>
542 <<
"The values " << arg1 <<
" and " << arg2
543 <<
" do not form a valid range.");
622 match(
const std::string &test_string)
const override;
636 virtual std::unique_ptr<PatternBase>
637 clone()
const override;
644 static std::unique_ptr<Map>
689 <<
"The values " << arg1 <<
" and " << arg2
690 <<
" do not form a valid range.");
785 Tuple(
const std::vector<std::unique_ptr<PatternBase>> &
patterns,
793 Tuple(
const std::vector<std::unique_ptr<PatternBase>> &
patterns,
804 template <
class... PatternTypes>
814 template <
class... PatternTypes>
835 match(
const std::string &test_string)
const override;
849 virtual std::unique_ptr<PatternBase>
850 clone()
const override;
857 static std::unique_ptr<Tuple>
883 std::vector<std::unique_ptr<PatternBase>>
patterns;
920 match(
const std::string &test_string)
const override;
935 virtual std::unique_ptr<PatternBase>
936 clone()
const override;
943 static std::unique_ptr<MultipleSelection>
964 <<
"A comma was found at position " << arg1
965 <<
" of your input string, but commas are not allowed here.");
1004 virtual std::unique_ptr<PatternBase>
1005 clone()
const override;
1012 static std::unique_ptr<Bool>
1039 match(
const std::string &test_string)
const override;
1053 virtual std::unique_ptr<PatternBase>
1054 clone()
const override;
1061 static std::unique_ptr<Anything>
1116 match(
const std::string &test_string)
const override;
1130 virtual std::unique_ptr<PatternBase>
1131 clone()
const override;
1143 static std::unique_ptr<FileName>
1179 match(
const std::string &test_string)
const override;
1193 virtual std::unique_ptr<PatternBase>
1194 clone()
const override;
1201 static std::unique_ptr<DirectoryName>
1301 template <
class T,
class Enable =
void>
1313 static std::unique_ptr<Patterns::PatternBase>
1364 template <
typename T>
1393 template <
typename T>
1395 to_value(
const std::string &s, T &t);
1408 <<
"The string \"" << arg1
1409 <<
"\" does not match the pattern \"" << arg2 <<
"\"");
1418 template <
class... PatternTypes>
1421 Tuple(
std::string(separator), ps...)
1426 template <
class... PatternTypes>
1428 : separator(separator)
1431 "Not all of the input arguments of this function "
1432 "are derived from PatternBase");
1433 static_assert(
sizeof...(ps) > 0,
1434 "The number of PatternTypes must be greater than zero!");
1435 const auto pattern_pointers = {(
static_cast<const PatternBase *
>(&ps))...};
1436 for (
const auto p : pattern_pointers)
1442 template <
class... PatternTypes>
1478 template <
class T,
class Enable =
void>
1490 template <
typename Dummy = T>
1491 static std::enable_if_t<std::is_same_v<Dummy, T> &&
1492 std::is_same_v<T, bool>,
1493 std::unique_ptr<Patterns::PatternBase>>
1496 return std::make_unique<Patterns::Bool>();
1499 template <
typename Dummy = T>
1500 static std::enable_if_t<std::is_same_v<Dummy, T> &&
1501 !std::is_same_v<T, bool> &&
1502 std::is_integral_v<T>,
1503 std::unique_ptr<Patterns::PatternBase>>
1506 return std::make_unique<Patterns::Integer>(
1507 std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
1510 template <
typename Dummy = T>
1511 static std::enable_if_t<std::is_same_v<Dummy, T> &&
1512 !std::is_same_v<T, bool> &&
1513 std::is_floating_point_v<T>,
1514 std::unique_ptr<Patterns::PatternBase>>
1517 return std::make_unique<Patterns::Double>(
1518 std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
1525 std::stringstream str;
1526 if (std::is_same_v<T, unsigned char> ||
1527 std::is_same_v<T, signed char> || std::is_same_v<T, char>)
1528 str << static_cast<int>(value);
1529 else if (std::is_same_v<T, bool>)
1530 str << (static_cast<bool>(value) ?
"true" :
"false");
1543 if (std::is_same_v<T, bool>)
1544 value = (s ==
"true");
1547 std::istringstream is(s);
1548 if (std::is_same_v<T, unsigned char> ||
1549 std::is_same_v<T, signed char> || std::is_same_v<T, char>)
1567 ExcMessage(
"Failed to convert from \"" + s +
"\" to the type \"" +
1568 boost::core::demangle(
typeid(T).name()) +
"\""));
1577 {
",",
";",
"|",
"%"}};
1579 {
":",
"=",
"@",
"#"}};
1582 template <
typename T>
1585 template <
typename... Args>
1588 template <
typename... Args>
1591 template <
typename... Args>
1594 template <
typename... Args>
1597 template <
typename... Args>
1600 template <
typename... Args>
1603 template <
typename... Args>
1608 template <
typename T>
1611 template <
class Key,
class T,
class Compare,
class Allocator>
1615 template <
class Key,
class T,
class Compare,
class Allocator>
1619 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
1621 std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type
1623 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
1625 std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
1632 template <
typename T>
1639 template <
typename T>
1656 template <
class T1,
class T2,
class... Types>
1671 template <
class T1,
class T2,
class... Types>
1693 max_list_rank<typename T::key_type, typename T::mapped_type>() + 1;
1695 max_map_rank<typename T::key_type, typename T::mapped_type>() + 1;
1699 template <
int rank,
int dim,
class Number>
1706 template <
int dim,
class Number>
1711 template <
class Number>
1735 template <
class Key,
class Value>
1745 template <
class... Types>
1753 template <
class T, std::
size_t N>
1763 struct Convert<T,
std::enable_if_t<is_list_compatible<T>::value>>
1765 static std::unique_ptr<Patterns::PatternBase>
1769 "Cannot use this class for non List-compatible types.");
1770 return std::make_unique<Patterns::List>(
1773 std::numeric_limits<unsigned int>::max(),
1785 ExcMessage(
"I need a List pattern to convert a "
1786 "string to a List type."));
1787 auto base_p = p->get_base_pattern().clone();
1788 std::vector<std::string> vec(t.size());
1791 t.cbegin(), t.cend(), vec.begin(), [&base_p](
const auto &entry) {
1792 return Convert<typename T::value_type>::to_string(entry, *base_p);
1798 for (
unsigned int i = 1; i < vec.size(); ++i)
1799 s += p->get_separator() +
" " + vec[i];
1813 ExcMessage(
"I need a List pattern to convert a string "
1814 "to a List type."));
1816 auto base_p = p->get_base_pattern().clone();
1820 for (
const auto &str : v)
1763 struct Convert<T,
std::enable_if_t<is_list_compatible<T>::value>> {
…};
1832 static std::unique_ptr<Patterns::PatternBase>
1836 "Cannot use this class for non List-compatible types.");
1838 "Cannot use this class for non Map-compatible types.");
1839 return std::make_unique<Patterns::Map>(
1843 std::numeric_limits<unsigned int>::max(),
1854 const auto *p =
dynamic_cast<const Patterns::Map *
>(&pattern);
1856 ExcMessage(
"I need a Map pattern to convert a string to "
1857 "a Map compatible type."));
1858 auto key_p = p->get_key_pattern().clone();
1859 auto val_p = p->get_value_pattern().clone();
1860 std::vector<std::string> vec(t.size());
1863 for (
const auto &ti : t)
1866 p->get_key_value_separator() +
1872 for (
unsigned int i = 1; i < vec.size(); ++i)
1873 s += p->get_separator() +
" " + vec[i];
1885 const auto *p =
dynamic_cast<const Patterns::Map *
>(&pattern);
1887 ExcMessage(
"I need a Map pattern to convert a "
1888 "string to a Map compatible type."));
1890 auto key_p = p->get_key_pattern().clone();
1891 auto val_p = p->get_value_pattern().clone();
1895 for (
const auto &str : v)
1900 t.insert(std::make_pair(
1910 template <
typename ValueType, std::
size_t N>
1913 using T = std::array<ValueType, N>;
1915 static std::unique_ptr<Patterns::PatternBase>
1919 "Cannot use this class for non List-compatible types.");
1920 return std::make_unique<Patterns::List>(
1935 ExcMessage(
"I need a List pattern to convert a "
1936 "string to a std::array."));
1937 auto base_p = p->get_base_pattern().clone();
1938 std::vector<std::string> vec(t.size());
1941 t.cbegin(), t.cend(), vec.begin(), [&base_p](
const auto &entry) {
1942 return Convert<typename T::value_type>::to_string(entry, *base_p);
1948 for (
unsigned int i = 1; i < vec.size(); ++i)
1949 s += p->get_separator() +
" " + vec[i];
1963 ExcMessage(
"I need a List pattern to convert a string "
1964 "to a std::array."));
1966 auto base_p = p->get_base_pattern().clone();
1971 for (
unsigned int i = 0; i < N; ++i)
1978 template <
int rank,
int dim,
class Number>
1982 static std::unique_ptr<Patterns::PatternBase>
1986 "Cannot use this class for non List-compatible types.");
1987 return std::make_unique<Patterns::List>(
2002 ExcMessage(
"I need a List pattern to convert a string "
2003 "to a List compatible type."));
2004 auto base_p = p->get_base_pattern().clone();
2005 std::vector<std::string> vec(dim);
2007 for (
unsigned int i = 0; i < dim; ++i)
2013 for (
unsigned int i = 1; i < vec.size(); ++i)
2014 s += p->get_separator() +
" " + vec[i];
2028 ExcMessage(
"I need a List pattern to convert a string "
2029 "to a List compatible type."));
2031 auto base_p = p->get_base_pattern().clone();
2036 for (
const auto &str : v)
2044 template <
int dim,
class Number>
2049 static std::unique_ptr<Patterns::PatternBase>
2076 using T = std::unique_ptr<FunctionParser<dim>>;
2078 static std::unique_ptr<Patterns::PatternBase>
2082 "Cannot use this class for non List-compatible types.");
2084 return std::make_unique<Patterns::List>(
2099 ExcMessage(
"I need a List pattern to convert a string "
2100 "to a List compatible type."));
2102 const auto &expressions = t->get_expressions();
2103 if (expressions.empty())
2104 return std::string();
2106 std::string s = expressions[0];
2107 for (
unsigned int i = 1; i < expressions.size(); ++i)
2108 s = s + p->get_separator() + expressions[i];
2122 ExcMessage(
"I need a List pattern to convert a string "
2123 "to a List compatible type."));
2125 const auto expressions =
2128 T t = std::make_unique<FunctionParser<dim>>(expressions.size());
2129 const std::string var =
2132 t->initialize(var, expressions, constants,
true);
2143 static std::unique_ptr<Patterns::PatternBase>
2154 std::vector<bool> mask(t.
size());
2155 for (
unsigned int i = 0; i < t.
size(); ++i)
2171 template <
class Number>
2174 using T = std::complex<Number>;
2176 static std::unique_ptr<Patterns::PatternBase>
2180 "Cannot use this class for non List-compatible types.");
2181 return std::make_unique<Patterns::List>(
2196 ExcMessage(
"I need a List pattern to convert a string "
2197 "to a List compatible type."));
2199 auto base_p = p->get_base_pattern().clone();
2202 p->get_separator() +
" " +
2220 ExcMessage(
"I need a List pattern to convert a string "
2221 "to a List compatible type."));
2223 auto base_p = p->get_base_pattern().clone();
2237 using T = std::string;
2239 static std::unique_ptr<Patterns::PatternBase>
2242 return std::make_unique<Patterns::Anything>();
2264 template <
class Key,
class Value>
2267 using T = std::pair<Key, Value>;
2269 static std::unique_ptr<Patterns::PatternBase>
2273 "Cannot use this class for non Map-compatible types.");
2274 return std::make_unique<Patterns::Tuple>(
2285 std::tuple<Key, Value> m(t);
2295 std::tuple<Key, Value> m;
2297 return std::make_pair(std::get<0>(m), std::get<1>(m));
2302 template <
class... Args>
2305 using T = std::tuple<Args...>;
2307 static std::unique_ptr<Patterns::PatternBase>
2311 "Cannot use this class for non tuple-compatible types.");
2312 return std::make_unique<Patterns::Tuple>(
2324 ExcMessage(
"I need a Tuple pattern to convert a tuple "
2329 for (
unsigned int i = 0; i < string_array.size(); ++i)
2331 (i != 0u ?
" " + p->get_separator() +
" " :
"") + string_array[i];
2344 ExcMessage(
"I need a Tuple pattern to convert a string "
2345 "to a tuple type."));
2353 template <std::size_t... U>
2354 static std::array<std::string, std::tuple_size<T>::value>
2357 std::index_sequence<U...>)
2359 std::array<std::string, std::tuple_size<T>::value> a = {
2365 static std::array<std::string, std::tuple_size<T>::value>
2369 t, pattern, std::make_index_sequence<std::tuple_size<T>::value>{});
2372 template <std::size_t... U>
2376 std::index_sequence<U...>)
2378 return std::make_tuple(
2388 s, pattern, std::make_index_sequence<std::tuple_size<T>::value>{});
2392#ifdef DEAL_II_WITH_MAGIC_ENUM
2395 struct Convert<T, typename
std::enable_if<std::is_enum<T>::value>::type>
2397 static std::unique_ptr<Patterns::PatternBase>
2400 const auto n = magic_enum::enum_names<T>();
2401 std::vector<std::string> names = {n.begin(), n.end()};
2402 const auto selection =
2419 const auto values = magic_enum::enum_values<T>();
2420 std::vector<std::string> names;
2421 for (
const auto &v :
values)
2422 if (magic_enum::bitwise_operators::operator&(
value, v) == v)
2423 names.push_back(
std::string(magic_enum::enum_name(v)));
2429 const ::Patterns::PatternBase &p = *
to_pattern())
2434 std::vector<std::string> value_names;
2437 for (
const auto &name : value_names)
2439 auto v = magic_enum::enum_cast<T>(name);
2442 magic_enum::bitwise_operators::operator|(value, v.value());
2450 template <
typename T>
2458 template <
typename T>
unsigned int size() const
std::map< std::string, double > ConstMap
static std::string default_variable_names()
static std::unique_ptr< Anything > create(const std::string &description)
virtual bool match(const std::string &test_string) const override
static const char * description_init
virtual std::string description(const OutputStyle style=Machine) const override
virtual std::unique_ptr< PatternBase > clone() const override
virtual std::string description(const OutputStyle style=Machine) const override
static const char * description_init
virtual std::unique_ptr< PatternBase > clone() const override
static std::unique_ptr< Bool > create(const std::string &description)
virtual std::unique_ptr< PatternBase > clone() const override
static const char * description_init
virtual std::string description(const OutputStyle style=Machine) const override
static std::unique_ptr< DirectoryName > create(const std::string &description)
virtual bool match(const std::string &test_string) const override
static std::unique_ptr< Double > create(const std::string &description)
static const char * description_init
virtual std::unique_ptr< PatternBase > clone() const override
static const double max_double_value
static const double min_double_value
virtual std::string description(const OutputStyle style=Machine) const override
virtual bool match(const std::string &test_string) const override
virtual bool match(const std::string &test_string) const override
static const char * description_init
virtual std::unique_ptr< PatternBase > clone() const override
static std::unique_ptr< FileName > create(const std::string &description)
virtual std::string description(const OutputStyle style=Machine) const override
static std::unique_ptr< Integer > create(const std::string &description)
static const char * description_init
virtual std::unique_ptr< PatternBase > clone() const override
static const int min_int_value
virtual std::string description(const OutputStyle style=Machine) const override
virtual bool match(const std::string &test_string) const override
static const int max_int_value
const unsigned int max_elements
static const char * description_init
const unsigned int min_elements
std::unique_ptr< PatternBase > pattern
const std::string separator
std::size_t memory_consumption() const override
static std::unique_ptr< List > create(const std::string &description)
virtual std::string description(const OutputStyle style=Machine) const override
const PatternBase & get_base_pattern() const
virtual bool match(const std::string &test_string) const override
const std::string & get_separator() const
static const unsigned int max_int_value
virtual std::unique_ptr< PatternBase > clone() const override
static std::unique_ptr< Map > create(const std::string &description)
std::unique_ptr< PatternBase > value_pattern
const unsigned int min_elements
const PatternBase & get_key_pattern() const
virtual bool match(const std::string &test_string) const override
const unsigned int max_elements
virtual std::unique_ptr< PatternBase > clone() const override
const PatternBase & get_value_pattern() const
const std::string & get_separator() const
virtual std::string description(const OutputStyle style=Machine) const override
static const unsigned int max_int_value
std::unique_ptr< PatternBase > key_pattern
const std::string separator
std::size_t memory_consumption() const override
static const char * description_init
const std::string & get_key_value_separator() const
const std::string key_value_separator
static std::unique_ptr< MultipleSelection > create(const std::string &description)
virtual bool match(const std::string &test_string) const override
virtual std::unique_ptr< PatternBase > clone() const override
static const char * description_init
std::size_t memory_consumption() const override
virtual std::string description(const OutputStyle style=Machine) const override
virtual std::size_t memory_consumption() const
virtual std::unique_ptr< PatternBase > clone() const =0
virtual std::string description(const OutputStyle style=Machine) const =0
virtual bool match(const std::string &test_string) const =0
virtual ~PatternBase()=default
static const char * description_init
virtual std::string description(const OutputStyle style=Machine) const override
virtual std::unique_ptr< PatternBase > clone() const override
virtual bool match(const std::string &test_string) const override
static std::unique_ptr< Selection > create(const std::string &description)
std::size_t memory_consumption() const override
virtual bool match(const std::string &test_string) const override
std::size_t memory_consumption() const override
static std::unique_ptr< Tuple > create(const std::string &description)
std::vector< std::unique_ptr< PatternBase > > patterns
virtual std::unique_ptr< PatternBase > clone() const override
Tuple(const Patterns &...patterns)
const std::string separator
static const char * description_init
Tuple(const std::vector< std::unique_ptr< PatternBase > > &patterns, const std::string &separator=":")
const std::string & get_separator() const
const PatternBase & get_pattern(const unsigned int i) const
virtual std::string description(const OutputStyle style=Machine) const override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
static ::ExceptionBase & ExcNoMatch(std::string arg1, std::string arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcCommasNotAllowed(int arg1)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::string escape(const std::string &input, const PatternBase::OutputStyle style)
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)