1 #ifndef ERF_INPUTS_NAME_H_
2 #define ERF_INPUTS_NAME_H_
5 #include <AMReX_ParmParse.H>
6 #include <AMReX_Print.H>
13 #include <unordered_map>
20 std::string trim_copy (std::string s)
22 auto b = s.find_first_not_of(
" \t\r");
23 if (b == std::string::npos)
return "";
25 auto e = s.find_last_not_of(
" \t\r");
26 return s.substr(b, e - b + 1);
41 std::unordered_map<std::string, EntryInfo>
seen;
56 const char* prefix = std::getenv(
"AMREX_INPUTS_FILE_PREFIX");
57 if (prefix ==
nullptr || prefix[0] == 0) {
return name; }
58 std::string
p(prefix);
59 if (
p.back() !=
'/') {
p +=
'/'; }
67 inline std::vector<std::string>
70 std::vector<std::string> vals;
72 while (i < rhs.size()) {
73 if (rhs[i] ==
' ' || rhs[i] ==
'\t' || rhs[i] ==
'\r') { ++i;
continue; }
75 auto e = rhs.find(
'"', i + 1);
76 if (e == std::string::npos) { e = rhs.size(); }
77 vals.push_back(rhs.substr(i + 1, e - i - 1));
80 auto e = rhs.find_first_of(
" \t\r", i);
81 if (e == std::string::npos) { e = rhs.size(); }
82 vals.push_back(rhs.substr(i, e - i));
98 if (first.
includes.size() <= includes.size()) {
return false; }
99 for (std::size_t n = 0; n < includes.size(); ++n) {
100 if (first.
includes[n] != includes[n]) {
return false; }
118 std::ifstream ifs(
name);
120 if (!ifs.is_open()) {
121 state.
error =
"Could not open inputs file: " +
name;
125 auto canonical = std::filesystem::weakly_canonical(
name, ec);
126 if (ec) { canonical = std::filesystem::absolute(
name); }
128 if (f == canonical) {
129 state.
error =
"The inputs file " +
name +
" includes itself (FILE = ...)";
137 static const std::regex if_regex(R
"(^\s*#\s*if\s+\(?\s*AMREX_SPACEDIM\s*(>|<|==|>=|<=|!=)\s*([1-3])\s*\)?\s*$)");
138 static const std::regex elif_regex(R
"(^\s*#\s*elif\s+\(?\s*AMREX_SPACEDIM\s*(>|<|==|>=|<=|!=)\s*([1-3])\s*\)?\s*$)");
139 static const std::regex else_regex(R
"(^\s*#\s*else\s*$)");
140 static const std::regex endif_regex(R
"(^\s*#\s*endif\s*$)");
141 static const std::regex if_gpu_regex(R
"(^\s*#\s*ifdef\s+AMREX_USE_GPU\s*$)");
142 static const std::regex if_not_gpu_regex(R
"(^\s*#\s*ifndef\s+AMREX_USE_GPU\s*$)");
143 static const std::regex table_regex(R
"(^\[\s*([A-Za-z][A-Za-z0-9_.\-]*)\s*\]$)");
145 constexpr
bool use_gpu =
true;
147 constexpr
bool use_gpu =
false;
149 auto dim_true = [] (
const std::smatch& sm) {
150 const std::string op = sm[1].str();
151 const int dim = std::stoi(sm[2].str());
152 return (op ==
"<" && AMREX_SPACEDIM < dim) || (op ==
">" && AMREX_SPACEDIM > dim) ||
153 (op ==
"==" && AMREX_SPACEDIM == dim) || (op ==
"<=" && AMREX_SPACEDIM <= dim) ||
154 (op ==
">=" && AMREX_SPACEDIM >= dim) || (op ==
"!=" && AMREX_SPACEDIM != dim);
156 std::vector<bool> region_on;
157 std::vector<bool> region_had;
163 while (std::getline(ifs, line))
168 if (std::regex_match(line, if_gpu_regex) || std::regex_match(line, if_not_gpu_regex)) {
169 const bool r = std::regex_match(line, if_gpu_regex) ? use_gpu : !use_gpu;
170 region_on.push_back(r); region_had.push_back(r);
172 }
else if (std::regex_match(line, sm, if_regex)) {
173 const bool r = dim_true(sm);
174 region_on.push_back(r); region_had.push_back(r);
176 }
else if (!region_on.empty() && std::regex_match(line, sm, elif_regex)) {
177 const bool r = !region_had.back() && dim_true(sm);
178 region_on.back() = r;
179 if (r) { region_had.back() =
true; }
181 }
else if (!region_on.empty() && std::regex_match(line, else_regex)) {
182 region_on.back() = !region_had.back();
183 region_had.back() =
true;
185 }
else if (!region_on.empty() && std::regex_match(line, endif_regex)) {
186 region_on.pop_back(); region_had.pop_back();
190 for (
bool r : region_on) {
if (!r) { skip =
true; } }
191 if (skip) {
continue; }
194 auto hash_pos = line.find(
'#');
195 if (hash_pos != std::string::npos) {
196 line = line.substr(0, hash_pos);
199 line = trim_copy(line);
202 if (line.empty())
continue;
205 if (std::regex_match(line, sm, table_regex)) {
211 auto eq_pos = line.find(
'=');
212 if (eq_pos == std::string::npos)
continue;
214 const std::string def = trim_copy(line.substr(0, eq_pos));
215 const std::string value = trim_copy(line.substr(eq_pos + 1));
220 if (def == amrex::ParmParse::FileKeyword && vals.size() == 1) {
223 if (!state.
error.empty()) {
break; }
228 if (def == amrex::ParmParse::UnsetKeyword) {
229 for (
const auto& k : vals) { state.
seen.erase(k); }
233 const std::string key = table.empty() ? def : table +
"." + def;
234 auto it = state.
seen.find(key);
236 if (it == state.
seen.end())
249 <<
"\nDuplicate input detected:\n"
250 <<
" Key : " << key <<
"\n"
251 <<
" First line : " << it->second.line_number <<
" of " << it->second.file <<
"\n"
252 <<
" Value : " << it->second.value <<
"\n"
253 <<
" Second line : " << line_number <<
" of " <<
name <<
"\n"
254 <<
" Value : " << value <<
"\n";
277 if (!state.
error.empty()) {
278 amrex::Abort(state.
error);
282 amrex::Abort(
"Duplicate inputs detected in inputs file");
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:105
@ p
Definition: ERF_WSM6.H:280
Definition: ERF_InputsName.H:32
std::vector< int > includes
Definition: ERF_InputsName.H:37
std::string file
Definition: ERF_InputsName.H:33
std::string value
Definition: ERF_InputsName.H:35
int line_number
Definition: ERF_InputsName.H:34