Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_Enum.H
Go to the documentation of this file.
1#ifndef AMREX_ENUM_H_
2#define AMREX_ENUM_H_
3
4#include <AMReX_String.H>
5
6#include <algorithm>
7#include <array>
8#include <stdexcept>
9#include <string>
10#include <string_view>
11#include <type_traits>
12#include <utility>
13#include <vector>
14
15template <typename T>
16using amrex_enum_traits = decltype(amrex_get_enum_traits(std::declval<T>()));
17
18namespace amrex
19{
20 template <typename T, typename ET = amrex_enum_traits<T>,
21 std::enable_if_t<ET::value,int> = 0>
22 std::vector<std::pair<std::string,T>> getEnumNameValuePairs ()
23 {
24 auto tmp = amrex::split(std::string(ET::enum_names), ",");
25 std::vector<std::pair<std::string,T>> r;
26 r.reserve(tmp.size());
27 int next_value = 0;
28 for (auto const& item : tmp) {
29 auto const& kv = amrex::split(item, "=");
30 if (kv.size() == 1) {
31 r.emplace_back(amrex::trim(kv[0]), static_cast<T>(next_value));
32 ++next_value;
33 } else if (kv.size() == 2) {
34 auto const& value_string = amrex::trim(kv[1]);
35 auto it = std::find_if(r.begin(), r.end(),
36 [&] (auto const& x) -> bool
37 { return x.first == value_string; });
38 auto this_value = it->second;
39 r.emplace_back(amrex::trim(kv[0]), this_value);
40 next_value = static_cast<int>(this_value) + 1;
41 } else {
42 std::string error_msg("amrex::getEnumNameIntPairs: AMREX_ENUM(");
43 error_msg.append(ET::class_name).append(", ").append(ET::enum_names)
44 .append(").");
45 throw std::runtime_error(error_msg);
46 }
47 }
48 return r;
49 }
50
51 template <typename T, typename ET = amrex_enum_traits<T>,
52 std::enable_if_t<ET::value,int> = 0>
53 T getEnum (std::string_view const& s)
54 {
55 auto const& kv = getEnumNameValuePairs<T>();
56 auto it = std::find_if(kv.begin(), kv.end(),
57 [&] (auto const& x) -> bool
58 { return x.first == s; });
59 if (it != kv.end()) {
60 return it->second;
61 } else {
62 std::string error_msg("amrex::getEnum: Unknown enum: ");
63 error_msg.append(s).append(" in AMREX_ENUM(").append(ET::class_name)
64 .append(", ").append(ET::enum_names).append(").");
65 throw std::runtime_error(error_msg);
66 return T();
67 }
68 }
69
70 template <typename T, typename ET = amrex_enum_traits<T>,
71 std::enable_if_t<ET::value,int> = 0>
72 T getEnumCaseInsensitive (std::string_view const& s)
73 {
74 auto const& kv = getEnumNameValuePairs<T>();
75 std::string ls = amrex::toLower(std::string(s));
76 auto it = std::find_if(kv.begin(), kv.end(),
77 [&] (auto const& x) -> bool
78 { return amrex::toLower(x.first) == ls; });
79 if (it != kv.end()) {
80 return it->second;
81 } else {
82 std::string error_msg("amrex::getEnumCaseInsensitive: Unknown enum: ");
83 error_msg.append(s).append(" in AMREX_ENUM(").append(ET::class_name)
84 .append(", ").append(ET::enum_names).append(").");
85 throw std::runtime_error(error_msg);
86 return T();
87 }
88 }
89
90 template <typename T, typename ET = amrex_enum_traits<T>,
91 std::enable_if_t<ET::value,int> = 0>
92 std::string getEnumNameString (T const& v)
93 {
94 auto const& kv = getEnumNameValuePairs<T>();
95 auto it = std::find_if(kv.begin(), kv.end(),
96 [&] (auto const& x) -> bool
97 { return x.second == v; });
98 if (it != kv.end()) {
99 return it->first;
100 } else {
101 std::string error_msg("amrex::getEnum: Unknown enum value: ");
102 error_msg.append(std::to_string(static_cast<int>(v)))
103 .append(" in AMREX_ENUM(").append(ET::class_name).append(", ")
104 .append(ET::enum_names).append(").");
105 throw std::runtime_error(error_msg);
106 return std::string();
107 }
108 }
109
110 template <typename T, typename ET = amrex_enum_traits<T>,
111 std::enable_if_t<ET::value,int> = 0>
112 std::vector<std::string> getEnumNameStrings ()
113 {
114 auto r = amrex::split(std::string(ET::enum_names), ",");
115 for (auto& s : r) {
116 auto found = s.find('=');
117 if (found != std::string::npos) {
118 s.erase(found);
119 }
120 s = amrex::trim(s);
121 }
122 return r;
123 }
124
125 template <typename T, typename ET = amrex_enum_traits<T>,
126 std::enable_if_t<ET::value,int> = 0>
127 std::string getEnumClassName ()
128 {
129 return std::string(ET::class_name);
130 }
131}
132
133#define AMREX_ENUM(CLASS, ...) \
134 enum class CLASS : int { __VA_ARGS__ }; \
135 struct CLASS##_EnumTraits { \
136 using enum_class_t = CLASS; \
137 static constexpr bool value = true; \
138 static constexpr std::string_view class_name{#CLASS}; \
139 static constexpr std::string_view enum_names{#__VA_ARGS__}; \
140 }; \
141 CLASS##_EnumTraits amrex_get_enum_traits(CLASS)
142
143#endif
decltype(amrex_get_enum_traits(std::declval< T >())) amrex_enum_traits
Definition AMReX_Enum.H:16
Definition AMReX_Amr.cpp:49
std::string getEnumClassName()
Definition AMReX_Enum.H:127
std::string getEnumNameString(T const &v)
Definition AMReX_Enum.H:92
std::string trim(std::string s, std::string const &space)
Definition AMReX_String.cpp:25
std::string toLower(std::string s)
Converts all characters of the string into lower case based on std::locale.
Definition AMReX_String.cpp:11
T getEnum(std::string_view const &s)
Definition AMReX_Enum.H:53
T getEnumCaseInsensitive(std::string_view const &s)
Definition AMReX_Enum.H:72
std::vector< std::string > getEnumNameStrings()
Definition AMReX_Enum.H:112
std::vector< std::string > split(std::string const &s, std::string const &sep)
Split a string using given tokens in sep.
Definition AMReX_String.cpp:42
std::vector< std::pair< std::string, T > > getEnumNameValuePairs()
Definition AMReX_Enum.H:22