From 6b9dfe9ddfcd21258ddf7ede1dd8ca71a21c5e3c Mon Sep 17 00:00:00 2001 From: Weiqun Zhang Date: Wed, 11 Sep 2024 11:38:55 -0700 Subject: [PATCH] Add ParmParse::query_enum_sloppy that can ignore characters The characters in the `ignores` argument will be ignored as if they don't exist in the value part of `name = value`. --- Src/Base/AMReX_ParmParse.H | 63 ++++++++++++++++++++++++++++++++++++++ Tests/Enum/inputs | 3 +- Tests/Enum/main.cpp | 4 +++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/Src/Base/AMReX_ParmParse.H b/Src/Base/AMReX_ParmParse.H index 42e62a05ab..26e577b5fb 100644 --- a/Src/Base/AMReX_ParmParse.H +++ b/Src/Base/AMReX_ParmParse.H @@ -1365,6 +1365,69 @@ public: } } + /** + * \brief. Query enum value using given name. + * + * Here T is an enum class defined by AMREX_ENUM. The return value + * indicates if `name` is found. An exception is thrown, if the found + * string associated with the name cannot be case-insensitively + * converted to an enumerator (i.e., the found string, not `name`, does + * not case-insensitively match any names in the definition of T). If + * there are multiple matches, the first one is used. Characters in + * `ignores` will be ignored as if they don't exist in the value part of + * ParamParse entries (e.g., `name = value`). + */ + template , + std::enable_if_t = 0> + int query_enum_sloppy (const char* name, T& ref, std::string_view const& ignores, + int ival = FIRST) const + { + std::string s; + int exist = this->query(name, s, ival); + if (exist) { + try { + s.erase(std::remove_if(s.begin(), s.end(), + [&] (auto const& c) { + return ignores.find(c) != ignores.npos; }), + s.end()); + ref = amrex::getEnumCaseInsensitive(s); + } catch (...) { + if (amrex::Verbose() > 0) { + amrex::Print() << "amrex::ParmParse::query_enum_sloppy (input name: " + << this->prefixedName(name) << "):\n"; + } + throw; + } + } + return exist; + } + + /** + * \brief. Get enum value using given name. + * + * Here T is an enum class defined by AMREX_ENUM. It's a runtime error, + * if `name` is not found. An exception is thrown, if the found string + * associated with the name cannot be case-insensitively converted to an + * enumerator (i.e., the found string, not `name`, does not + * case-insensitively match any names in the definition of T). If there + * are multiple matches, the first one is used. Characters in `ignores` + * will be ignored as if they don't exist in the value part of + * ParamParse entries (e.g., `name = value`). + */ + template , + std::enable_if_t = 0> + void get_enum_sloppy (const char* name, T& ref, std::string_view const& ignores, + int ival = FIRST) const + { + int exist = this->query_enum_sloppy(name, ref, ignores, ival); + if (!exist) { + std::string msg("get_enum_sloppy(\""); + msg.append(name).append("\",").append(amrex::getEnumClassName()) + .append("&) failed."); + amrex::Abort(msg); + } + } + //! Remove given name from the table. int remove (const char* name); diff --git a/Tests/Enum/inputs b/Tests/Enum/inputs index 0972043658..7799bb3ddc 100644 --- a/Tests/Enum/inputs +++ b/Tests/Enum/inputs @@ -4,7 +4,6 @@ color2 = green color3 = blue color4 = greenxxx color5 = Blue +color6 = G-r-e-e.n colors = cyan yellow orange - - diff --git a/Tests/Enum/main.cpp b/Tests/Enum/main.cpp index b0647836e4..19ff70d25a 100644 --- a/Tests/Enum/main.cpp +++ b/Tests/Enum/main.cpp @@ -134,6 +134,10 @@ int main (int argc, char* argv[]) ParmParse pp; pp.query_enum_case_insensitive("color5", my_blue); AMREX_ALWAYS_ASSERT(my_blue == MyColor2::blue); + + auto my_green = MyColor2::red; + pp.query_enum_sloppy("color6", my_green, "-."); + AMREX_ALWAYS_ASSERT(my_green == MyColor2::green); } amrex::Finalize();