Use StringToEnumValueConverter and enumValueToString more
authorMark Abraham <mark.j.abraham@gmail.com>
Mon, 22 Mar 2021 09:49:30 +0000 (09:49 +0000)
committerAndrey Alekseenko <al42and@gmail.com>
Mon, 22 Mar 2021 09:49:30 +0000 (09:49 +0000)
Follow up from MR 1213

src/gromacs/fileio/readinp.h
src/gromacs/gmxpreprocess/gpp_atomtype.cpp
src/gromacs/gmxpreprocess/pdb2top.cpp
src/gromacs/gmxpreprocess/tests/topdirs.cpp
src/gromacs/gmxpreprocess/topdirs.cpp
src/gromacs/gmxpreprocess/topdirs.h
src/gromacs/gmxpreprocess/topio.cpp
src/gromacs/gmxpreprocess/toppush.cpp
src/gromacs/gmxpreprocess/toputil.cpp

index 9330e99eb848860f7711140b0862637c82a68a85..3fd3db59f962a38f564378e578d4f6f68c63f842 100644 (file)
@@ -192,7 +192,13 @@ EnumType getEnum(std::vector<t_inpfile>* inp, const char* name, warninp* wi)
         return defaultEnumValue;
     }
 
-    // Check if option string can be mapped to a valid enum value
+    // Check if option string can be mapped to a valid enum value.
+    //
+    // Note that this cannot be replaced with
+    // StringToEnumValueConverter until all instantiations of this
+    // function have a matching enumValueToString, and all of the
+    // latter are in the same namespace. Currently some of those
+    // function declarations are in gmx namespace and some are not.
     const auto* optionString = (*inp)[ii].value_.c_str();
     for (auto enumValue : gmx::EnumerationWrapper<EnumType>{})
     {
index cc1b00fd78cf361b3fccd724fcd81e55dc213cf6..429de6bd30245ec78a588539bdcc910f2b0689c4 100644 (file)
@@ -221,7 +221,7 @@ std::optional<int> PreprocessingAtomTypes::setType(int                      nt,
 
 void PreprocessingAtomTypes::printTypes(FILE* out)
 {
-    fprintf(out, "[ %s ]\n", dir2str(Directive::d_atomtypes));
+    fprintf(out, "[ %s ]\n", enumValueToString(Directive::d_atomtypes));
     fprintf(out,
             "; %6s  %8s  %8s  %8s  %12s  %12s\n",
             "type",
index 1199f4f15cdd92d7b3820f6d72324192649c9691..a7526c5210fe7d0a93686a0b03e55ab2840a8048 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
  * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
- * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -652,7 +652,7 @@ static void print_top_water(FILE* out, const char* ffdir, const char* water)
 
 static void print_top_system(FILE* out, const char* title)
 {
-    fprintf(out, "[ %s ]\n", dir2str(Directive::d_system));
+    fprintf(out, "[ %s ]\n", enumValueToString(Directive::d_system));
     fprintf(out, "; Name\n");
     fprintf(out, "%s\n\n", title[0] ? title : "Protein");
 }
@@ -683,7 +683,7 @@ void print_top_mols(FILE*                            out,
 
     if (!mols.empty())
     {
-        fprintf(out, "[ %s ]\n", dir2str(Directive::d_molecules));
+        fprintf(out, "[ %s ]\n", enumValueToString(Directive::d_molecules));
         fprintf(out, "; %-15s %5s\n", "Compound", "#mols");
         for (const auto& mol : mols)
         {
@@ -707,7 +707,7 @@ void write_top(FILE*                                   out,
 {
     if (at && atype && cgnr)
     {
-        fprintf(out, "[ %s ]\n", dir2str(Directive::d_moleculetype));
+        fprintf(out, "[ %s ]\n", enumValueToString(Directive::d_moleculetype));
         fprintf(out, "; %-15s %5s\n", "Name", "nrexcl");
         fprintf(out, "%-15s %5d\n\n", molname ? molname : "Protein", nrexcl);
 
index cd1fa35119ba87e165bb665bbe115c6ab7d63058..cfc7d306b97609815b1e454dc257109e19ab298d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -54,7 +54,7 @@ TEST(TopDirTests, NamesArrayHasCorrectSize)
         // If the enumeration is extended, but there is no matching
         // name, then at least one element will be value initialized,
         // ie. to nullptr, which this test will catch.
-        auto name = dir2str(d);
+        auto name = enumValueToString(d);
         EXPECT_NE(name, nullptr);
     }
 }
index 475afeea73f47456681b9433a8f4d2036340d623..ea66de5f80e4495c3bf6695161ee7c9b6c4e824c 100644 (file)
 #include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringtoenumvalueconverter.h"
 
-/* Must correspond to the Directive enum in grompp_impl.h */
-static gmx::EnumerationArray<Directive, const char*> directive_names = {
-    { "defaults",
-      "atomtypes",
-      "bondtypes",
-      "constrainttypes",
-      "pairtypes",
-      "angletypes",
-      "dihedraltypes",
-      "nonbond_params",
-      "implicit_genborn_params",
-      "implicit_surface_params",
-      "cmaptypes",
-      /* All the directives above can not appear after moleculetype */
-      "moleculetype",
-      "atoms",
-      "virtual_sites1",
-      "virtual_sites2",
-      "virtual_sites3",
-      "virtual_sites4",
-      "virtual_sitesn",
-      "bonds",
-      "exclusions",
-      "pairs",
-      "pairs_nb",
-      "angles",
-      "dihedrals",
-      "constraints",
-      "settles",
-      "polarization",
-      "water_polarization",
-      "thole_polarization",
-      "system",
-      "molecules",
-      "position_restraints",
-      "angle_restraints",
-      "angle_restraints_z",
-      "distance_restraints",
-      "orientation_restraints",
-      "dihedral_restraints",
-      "cmap",
-      "intermolecular_interactions",
-      "maxdirs",
-      "invalid",
-      "none" }
-};
+const char* enumValueToString(Directive d)
+{
+    /* Must correspond to the Directive enum in topdirs.h */
+    static constexpr gmx::EnumerationArray<Directive, const char*> directiveNames = {
+        "defaults",
+        "atomtypes",
+        "bondtypes",
+        "constrainttypes",
+        "pairtypes",
+        "angletypes",
+        "dihedraltypes",
+        "nonbond_params",
+        "implicit_genborn_params",
+        "implicit_surface_params",
+        "cmaptypes",
+        /* All the directives above can not appear after moleculetype */
+        "moleculetype",
+        "atoms",
+        "virtual_sites1",
+        "virtual_sites2",
+        "virtual_sites3",
+        "virtual_sites4",
+        "virtual_sitesn",
+        "bonds",
+        "exclusions",
+        "pairs",
+        "pairs_nb",
+        "angles",
+        "dihedrals",
+        "constraints",
+        "settles",
+        "polarization",
+        "water_polarization",
+        "thole_polarization",
+        "system",
+        "molecules",
+        "position_restraints",
+        "angle_restraints",
+        "angle_restraints_z",
+        "distance_restraints",
+        "orientation_restraints",
+        "dihedral_restraints",
+        "cmap",
+        "intermolecular_interactions",
+        "maxdirs",
+        "invalid",
+        "none"
+    };
+    return directiveNames[d];
+}
 
 int ifunc_index(Directive d, int type)
 {
@@ -239,39 +244,50 @@ int ifunc_index(Directive d, int type)
         case Directive::d_orientation_restraints: return F_ORIRES;
         case Directive::d_dihedral_restraints: return F_DIHRES;
         default:
-            gmx_fatal(FARGS, "invalid directive %s in ifunc_index (%s:%d)", dir2str(d), __FILE__, __LINE__);
+            gmx_fatal(FARGS, "invalid directive %s in ifunc_index (%s:%d)", enumValueToString(d), __FILE__, __LINE__);
     }
 }
 
-const char* dir2str(Directive d)
+enum class DeprecatedDirectives : int
+{
+    d_dummies1,
+    d_dummies2,
+    d_dummies3,
+    d_dummies4,
+    d_dummiesn,
+    Count
+};
+
+static const char* enumValueToString(DeprecatedDirectives d)
 {
-    int index = static_cast<int>(d);
-    return directive_names[index];
+    static constexpr gmx::EnumerationArray<DeprecatedDirectives, const char*> directiveNames = {
+        "dummies1", "dummies2", "dummies3", "dummies4", "dummiesn"
+    };
+    return directiveNames[d];
 }
 
 Directive str2dir(char* dstr)
 {
-    char buf[STRLEN], *ptr;
+    static const gmx::StringToEnumValueConverter<Directive, enumValueToString, gmx::StringCompareType::CaseAndDashInsensitive> s_converter;
 
-    /* Hack to be able to read old topologies */
-    if (gmx_strncasecmp_min(dstr, "dummies", 7) == 0)
+    if (std::optional<Directive> d = s_converter.valueFrom(dstr); d.has_value())
     {
-        sprintf(buf, "virtual_sites%s", dstr + 7);
-        ptr = buf;
-    }
-    else
-    {
-        ptr = dstr;
+        return d.value();
     }
+    // Also handle deprecated directives that have modern replacements, like
+    // "dummies*" -> "virtual_sites*"
 
-    for (auto d : gmx::EnumerationWrapper<Directive>())
+    static const gmx::StringToEnumValueConverter<DeprecatedDirectives, enumValueToString, gmx::StringCompareType::CaseAndDashInsensitive>
+            s_converterForDeprecated;
+
+    if (std::optional<DeprecatedDirectives> d = s_converterForDeprecated.valueFrom(dstr); d.has_value())
     {
-        if (gmx_strcasecmp_min(ptr, dir2str(static_cast<Directive>(d))) == 0)
-        {
-            return static_cast<Directive>(d);
-        }
+        static constexpr gmx::EnumerationArray<DeprecatedDirectives, Directive> s_deprecatedDirectiveToDirective = {
+            Directive::d_vsites1, Directive::d_vsites2, Directive::d_vsites3,
+            Directive::d_vsites4, Directive::d_vsitesn,
+        };
+        return s_deprecatedDirectiveToDirective[d.value()];
     }
-
     return Directive::d_invalid;
 }
 
index 202cd23b11ef3d5b2ff5526f54c7c28294b6fec2..d904e6fcd1b4f005c636702b7420fc020c995952 100644 (file)
@@ -86,6 +86,8 @@ enum class Directive : int
     Count
 };
 
+const char* enumValueToString(Directive d);
+
 struct DirStack
 {
     Directive d;
@@ -94,8 +96,6 @@ struct DirStack
 
 int ifunc_index(Directive d, int type);
 
-const char* dir2str(Directive d);
-
 Directive str2dir(char* dstr);
 
 void DS_Init(DirStack** DS);
index 578d85406410b759101334073b62b49ab382af22..42cfc075836347fa21d5c110ccd1d7fd1822d5b5 100644 (file)
@@ -581,7 +581,7 @@ static char** read_topol(const char*                           infile,
                             gmx_fatal(FARGS,
                                       "%s\nInvalid order for directive %s",
                                       cpp_error(&handle, eCPP_SYNTAX),
-                                      dir2str(newd));
+                                      enumValueToString(newd));
                             /* d = Directive::d_invalid; */
                         }
 
index 42fd101db5d585326613a8d3574a51c45123308b..59b8d799881491626c9bd4db5e58eda9f58e435c 100644 (file)
@@ -1986,10 +1986,10 @@ void push_bond(Directive                         d,
                     "in a part belonging to a different molecule than you intended to.\n"
                     "In that case move the \"%s\" section to the right molecule.",
                     aa[i],
-                    dir2str(d),
+                    enumValueToString(d),
                     at->nr,
-                    dir2str(d),
-                    dir2str(d));
+                    enumValueToString(d),
+                    enumValueToString(d));
             warning_error_and_exit(wi, message, FARGS);
         }
         for (int j = i + 1; (j < nral); j++)
@@ -1998,7 +1998,8 @@ void push_bond(Directive                         d,
                        "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
             if (aa[i] == aa[j])
             {
-                auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
+                auto message = gmx::formatString(
+                        "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
                 if (ftype == F_ANGRES)
                 {
                     /* Since the angle restraints uses 2 pairs of atoms to
@@ -2378,10 +2379,10 @@ void push_cmap(Directive                         d,
                     "in a part belonging to a different molecule than you intended to.\n"
                     "In that case move the \"%s\" section to the right molecule.",
                     aa[i],
-                    dir2str(d),
+                    enumValueToString(d),
                     at->nr,
-                    dir2str(d),
-                    dir2str(d));
+                    enumValueToString(d),
+                    enumValueToString(d));
             warning_error_and_exit(wi, message, FARGS);
         }
 
@@ -2389,7 +2390,8 @@ void push_cmap(Directive                         d,
         {
             if (aa[i] == aa[j])
             {
-                auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
+                auto message = gmx::formatString(
+                        "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
                 warning_error(wi, message);
             }
         }
@@ -2441,7 +2443,8 @@ void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms*
     ptr += n;
     if (ret == 0)
     {
-        auto message = gmx::formatString("Expected an atom index in section \"%s\"", dir2str(d));
+        auto message =
+                gmx::formatString("Expected an atom index in section \"%s\"", enumValueToString(d));
         warning_error_and_exit(wi, message, FARGS);
     }
 
@@ -2498,8 +2501,8 @@ void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms*
 
     if (nj == 0)
     {
-        auto message =
-                gmx::formatString("Expected more than one atom index in section \"%s\"", dir2str(d));
+        auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
+                                         enumValueToString(d));
         warning_error_and_exit(wi, message, FARGS);
     }
 
index eb5b53d5a75b7fa4e21815a06c357540185eee40..88dfc9c112ce19be900d6db6c772e7db25954f2d 100644 (file)
@@ -130,7 +130,7 @@ static void print_bt(FILE*                                   out,
     nrfp = NRFP(ftype);
 
     /* header */
-    fprintf(out, "[ %s ]\n", dir2str(d));
+    fprintf(out, "[ %s ]\n", enumValueToString(d));
     fprintf(out, "; ");
     if (!bDih)
     {
@@ -209,7 +209,7 @@ void print_excl(FILE* out, int natoms, t_excls excls[])
 
     if (have_excl)
     {
-        fprintf(out, "[ %s ]\n", dir2str(Directive::d_exclusions));
+        fprintf(out, "[ %s ]\n", enumValueToString(Directive::d_exclusions));
         fprintf(out, "; %4s    %s\n", "i", "excluded from i");
         for (i = 0; i < natoms; i++)
         {
@@ -251,7 +251,7 @@ void print_atoms(FILE* out, PreprocessingAtomTypes* atype, t_atoms* at, int* cgn
     const char* as;
     double      qres, qtot;
 
-    as = dir2str(Directive::d_atoms);
+    as = enumValueToString(Directive::d_atoms);
     fprintf(out, "[ %s ]\n", as);
     fprintf(out,
             "; %4s %10s %6s %7s%6s %6s %10s %10s %6s %10s %10s\n",