Repository: AMReX-Codes/amrex — pull request #4552 (cpp)
Title: ParmParse: Add parser support for bool

Close #4535 

Resolved issues:
title: `bool` support in `queryAddWithParser`
body: Currently, `ParmParse::queryAddWithParser` does not support `bool` types. It would be very useful and consistent if added / completed for this.

Hints:

Fix patch:
diff --git a/Src/Base/AMReX_ParmParse.H b/Src/Base/AMReX_ParmParse.H
index 0e2aa7d37f3..c7ec4728b6d 100644
--- a/Src/Base/AMReX_ParmParse.H
+++ b/Src/Base/AMReX_ParmParse.H
@@ -1108,6 +1108,7 @@ public:
      * scalar. The return value indicates whether it's found. Note that
      * queryWithParser will be used recursively for unresolved symbols.
      */
+    int queryWithParser (const char* name, bool& ref) const;
     int queryWithParser (const char* name, int& ref) const;
     int queryWithParser (const char* name, long& ref) const;
     int queryWithParser (const char* name, long long& ref) const;
@@ -1120,12 +1121,14 @@ public:
      * symbols. If the number of elements in the input does not equal to
      * `nvals`, it's a runtime error.
      */
+    int queryarrWithParser (const char* name, int nvals, bool* ref) const;
     int queryarrWithParser (const char* name, int nvals, int* ref) const;
     int queryarrWithParser (const char* name, int nvals, long* ref) const;
     int queryarrWithParser (const char* name, int nvals, long long* ref) const;
     int queryarrWithParser (const char* name, int nvals, float* ref) const;
     int queryarrWithParser (const char* name, int nvals, double* ref) const;
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
@@ -1146,7 +1149,8 @@ public:
      * scalar. If not, the value in `ref` will be added to the ParmParse
      * database. The return value indicates whether it's found.
      */
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
@@ -1165,7 +1169,8 @@ public:
      * to parse the entire list of empty space separated values as a single
      * scalar. If not, it's a runtime error.
      */
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
@@ -1183,7 +1188,8 @@ public:
      * error. If the number of elements does not equal to `nvals`, it's also
      * a runtime error.
      */
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
@@ -1201,7 +1207,8 @@ public:
      * error. If the number of elements does not equal to `nvals`, it's also
      * a runtime error.
      */
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
@@ -1219,7 +1226,8 @@ public:
      *
      * For unknown symbols, ParmParse database will be queried.
      */
-    template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
+    template <typename T, std::enable_if_t<std::is_same_v<T,bool> ||
+                                           std::is_same_v<T,int> ||
                                            std::is_same_v<T,long> ||
                                            std::is_same_v<T,long long> ||
                                            std::is_same_v<T,float> ||
diff --git a/Src/Base/AMReX_ParmParse.cpp b/Src/Base/AMReX_ParmParse.cpp
index 7a41f187bc2..098ad89c9a7 100644
--- a/Src/Base/AMReX_ParmParse.cpp
+++ b/Src/Base/AMReX_ParmParse.cpp
@@ -718,7 +718,8 @@ squeryval (const ParmParse::Table& table,
     bool ok = is(valname, ref);
     if ( !ok )
     {
-        if constexpr (std::is_same_v<T,int> ||
+        if constexpr (std::is_same_v<T,bool> ||
+                      std::is_same_v<T,int> ||
                       std::is_same_v<T,long> ||
                       std::is_same_v<T,long long> ||
                       std::is_same_v<T,float> ||
@@ -1011,14 +1012,16 @@ bool squeryWithParser (const ParmParse::Table& table,
                        const std::string&      name,
                        T&                      ref);
 
-template <typename T, typename PARSER_t = std::conditional_t<std::is_integral_v<T>,
+template <typename T, typename PARSER_t = std::conditional_t<std::is_integral_v<T>
+                                                             && !std::is_same_v<bool,T>,
                                                              IParser, Parser>>
 PARSER_t
 pp_make_parser (std::string const& func, Vector<std::string> const& vars,
                 ParmParse::Table const& table, std::string const& parser_prefix,
                 bool use_querywithparser)
 {
-    using value_t =  std::conditional_t<std::is_integral_v<T>, long long, double>;
+    using value_t =  std::conditional_t<std::is_integral_v<T> && !std::is_same_v<bool,T>,
+                                        long long, double>;
 
     std::vector<std::string> prefixes;
     prefixes.reserve(3);
@@ -2048,6 +2051,12 @@ bool squeryarrWithParser (const ParmParse::Table& table,
 }
 }
 
+int
+ParmParse::queryWithParser (const char* name, bool& ref) const
+{
+    return squeryWithParser(*m_table,m_parser_prefix,prefixedName(name),ref);
+}
+
 int
 ParmParse::queryWithParser (const char* name, int& ref) const
 {
@@ -2078,6 +2087,12 @@ ParmParse::queryWithParser (const char* name, double& ref) const
     return squeryWithParser(*m_table,m_parser_prefix,prefixedName(name),ref);
 }
 
+int
+ParmParse::queryarrWithParser (const char* name, int nvals, bool* ref) const
+{
+    return squeryarrWithParser(*m_table,m_parser_prefix,prefixedName(name),nvals,ref);
+}
+
 int
 ParmParse::queryarrWithParser (const char* name, int nvals, int* ref) const
 {


Test patch:
diff --git a/Tests/ParmParse/inputs b/Tests/ParmParse/inputs
index c7b5af019b7..d109fa5579a 100644
--- a/Tests/ParmParse/inputs
+++ b/Tests/ParmParse/inputs
@@ -63,6 +63,11 @@ ny = nx
 
 do_this = 1
 
+# query bool with parser
+my_value = 10
+my_threshold = 3
+my_bool_flag = "(my_threshold < my_value) and (my_value < 100)"
+
 # queryline and getline
 my_string_line = a  b c
 
diff --git a/Tests/ParmParse/main.cpp b/Tests/ParmParse/main.cpp
index a367b1acaaa..1752d7f4833 100644
--- a/Tests/ParmParse/main.cpp
+++ b/Tests/ParmParse/main.cpp
@@ -143,6 +143,14 @@ int main(int argc, char* argv[])
         pp.queryAsDouble("do_that", o_do_that);
         AMREX_ALWAYS_ASSERT(!o_do_that.has_value());
     }
+    {
+        ParmParse pp;
+        bool my_bool_flag_1 = false;
+        bool my_bool_flag_2 = false;
+        pp.queryAddWithParser("my_bool_flag", my_bool_flag_1);
+        pp.query("my_bool_flag", my_bool_flag_2);
+        AMREX_ALWAYS_ASSERT(my_bool_flag_1 && my_bool_flag_2);
+    }
     {
         ParmParse pp;
         std::string line;