Introduce string comparison function
authorPaul Bauer <paul.bauer.q@gmail.com>
Mon, 21 Jan 2019 09:07:33 +0000 (10:07 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Wed, 23 Jan 2019 08:23:06 +0000 (09:23 +0100)
Added function to perform case insensitive string
comparison on std::string as input. Used some places in preprocessing as
showcases for the new function.

Change-Id: Ie128949883c05d0e7f951687bb4d51eca1d6f9d2

src/gromacs/gmxpreprocess/pdb2gmx.cpp
src/gromacs/topology/residuetypes.cpp
src/gromacs/utility/stringutil.cpp
src/gromacs/utility/stringutil.h

index d5826a0570e47543d54d4ebd0d4862cf55dc392c..4ec60422b5a393501197b4ade60aba134c9eca11 100644 (file)
@@ -103,7 +103,7 @@ static const char *res2bb_notermini(const char *name,
     int i;
 
     i = 0;
-    while (i < nrr && gmx_strcasecmp(name, rr[i].gmx) != 0)
+    while (i < nrr && !gmx::equalCaseInsensitive(name, rr[i].gmx))
     {
         i++;
     }
@@ -403,7 +403,7 @@ static void rename_pdbres(t_atoms *pdba, const char *oldnm, const char *newnm,
     for (i = 0; (i < pdba->nres); i++)
     {
         resnm = *pdba->resinfo[i].name;
-        if ((bFullCompare && (gmx_strcasecmp(resnm, oldnm) == 0)) ||
+        if ((bFullCompare && (gmx::equalCaseInsensitive(resnm, oldnm))) ||
             (!bFullCompare && strstr(resnm, oldnm) != nullptr))
         {
             /* Rename the residue name (not the rtp name) */
@@ -422,7 +422,7 @@ static void rename_bb(t_atoms *pdba, const char *oldnm, const char *newnm,
     {
         /* We have not set the rtp name yes, use the residue name */
         bbnm = *pdba->resinfo[i].name;
-        if ((bFullCompare && (gmx_strcasecmp(bbnm, oldnm) == 0)) ||
+        if ((bFullCompare && (gmx::equalCaseInsensitive(bbnm, oldnm))) ||
             (!bFullCompare && strstr(bbnm, oldnm) != nullptr))
         {
             /* Change the rtp builing block name */
@@ -719,7 +719,7 @@ static void sort_pdbatoms(t_restp restp[],
         atomnm = *pdba->atomname[i];
         rptr   = &restp[pdba->atom[i].resind];
         int j = std::find_if(rptr->atomname, rptr->atomname+rptr->natom,
-                             [&atomnm](char** it){return gmx_strcasecmp(atomnm, *it) == 0; })
+                             [&atomnm](char** it){return gmx::equalCaseInsensitive(atomnm, *it); })
             - rptr->atomname;
         if (j == rptr->natom)
         {
@@ -894,7 +894,7 @@ checkResidueTypeSanity(t_atoms     *pdba,
         for (int i = r0 + 1; i < r1; i++)
         {
             restype = rt->typeNameForIndexedResidue(*pdba->resinfo[i].name);
-            if (gmx_strcasecmp(restype.c_str(), restype0.c_str()))
+            if (!gmx::equalCaseInsensitive(restype, restype0))
             {
                 allResiduesHaveSameType = false;
                 residueString           = gmx::formatString("%s%d", *pdba->resinfo[i].name, pdba->resinfo[i].nr);
@@ -949,12 +949,14 @@ static void find_nc_ter(t_atoms *pdba, int r0, int r1, int *r_start, int *r_end,
     for (i = r0; i < r1 && *r_start == -1; i++)
     {
         p_startrestype = rt->typeNameForIndexedResidue(*pdba->resinfo[i].name);
-        if (!gmx_strcasecmp(p_startrestype.c_str(), "Protein") || !gmx_strcasecmp(p_startrestype.c_str(), "DNA") || !gmx_strcasecmp(p_startrestype.c_str(), "RNA") )
+        if (gmx::equalCaseInsensitive(p_startrestype, "Protein") ||
+            gmx::equalCaseInsensitive(p_startrestype, "DNA") ||
+            gmx::equalCaseInsensitive(p_startrestype, "RNA") )
         {
             printf("Identified residue %s%d as a starting terminus.\n", *pdba->resinfo[i].name, pdba->resinfo[i].nr);
             *r_start = i;
         }
-        else if (!gmx_strcasecmp(p_startrestype.c_str(), "Ion"))
+        else if (gmx::equalCaseInsensitive(p_startrestype, "Ion"))
         {
             if (ionNotes < 5)
             {
@@ -1003,11 +1005,11 @@ static void find_nc_ter(t_atoms *pdba, int r0, int r1, int *r_start, int *r_end,
         for (int i = *r_start; i < r1; i++)
         {
             std::string p_restype = rt->typeNameForIndexedResidue(*pdba->resinfo[i].name);
-            if (!gmx_strcasecmp(p_restype.c_str(), p_startrestype.c_str()) && endWarnings == 0)
+            if (!gmx::equalCaseInsensitive(p_restype, p_startrestype) && endWarnings == 0)
             {
                 *r_end = i;
             }
-            else if (!gmx_strcasecmp(p_startrestype.c_str(), "Ion"))
+            else if (gmx::equalCaseInsensitive(p_startrestype, "Ion"))
             {
                 if (ionNotes < 5)
                 {
@@ -1780,7 +1782,7 @@ int pdb2gmx::run()
         this_chainid       = ri->chainid;
         this_chainnumber   = ri->chainnum;
 
-        bWat_ = gmx_strcasecmp(*ri->name, watres) == 0;
+        bWat_ = gmx::equalCaseInsensitive(*ri->name, watres);
 
         if ((i == 0) || (this_chainnumber != prev_chainnumber) || (bWat_ != bPrevWat_))
         {
index e8123c46e8732dd978e3f8beaf2dadc437960c83..21cc485fe4689e8dab81180635429ac5dde77d75 100644 (file)
@@ -113,7 +113,7 @@ residueEntryByResidueName(gmx::ArrayRef<const ResidueTypeEntry> entries, const s
 {
     return std::find_if(entries.begin(), entries.end(),
                         [&residueName](const ResidueTypeEntry &old)
-                        { return gmx_strcasecmp(old.residueName.c_str(), residueName.c_str()) == 0; });
+                        { return gmx::equalCaseInsensitive(residueName, old.residueName); });
 }
 
 bool ResidueType::nameIndexedInResidueTypes(const std::string &residueName)
@@ -128,7 +128,7 @@ void ResidueType::addResidue(const std::string &residueName, const std::string &
 
     if (found != temp.end())
     {
-        if (gmx_strcasecmp(found->residueType.c_str(), residueType.c_str()))
+        if (!gmx::equalCaseInsensitive(found->residueType, residueType))
         {
             fprintf(stderr, "Warning: Residue '%s' already present with type '%s' in database, ignoring new type '%s'.\n",
                     residueName.c_str(), found->residueType.c_str(), residueType.c_str());
@@ -145,7 +145,7 @@ bool ResidueType::namedResidueHasType(const std::string &residueName, const std:
     gmx::ArrayRef<const ResidueTypeEntry> temp(impl_->entry);
     auto found = residueEntryByResidueName(temp, residueName);
     return  ((found != temp.end()) &&
-             (gmx_strcasecmp(residueType.c_str(), found->residueType.c_str()) == 0));
+             gmx::equalCaseInsensitive(residueType, found->residueType));
 }
 
 int ResidueType::numberOfEntries() const
index 70196a130e02840ccccc80629179be98fb3e32a1..42d2981859b28d02d3a5221e9a8decdefac509ed 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018,2019, 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.
@@ -314,6 +314,13 @@ replaceAllWords(const std::string &input, const std::string &from,
     return replaceInternal(input, from.c_str(), to.c_str(), true);
 }
 
+bool equalCaseInsensitive(const std::string &source, const std::string &target)
+{
+    return source.length() == target.length() &&
+           std::equal(source.begin(), source.end(), target.begin(),
+                      [](const char &s, const char &t)
+                      { return std::tolower(s) == std::tolower(t); });
+}
 
 /********************************************************************
  * TextLineWrapperSettings
index b3cca7e3e3c899575cb74d290048672e874823c2..6c83fc07241cd6c40208e53498d0c45af562ad6d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018,2019, 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.
@@ -430,6 +430,19 @@ std::string replaceAllWords(const std::string &input,
 std::string replaceAllWords(const std::string &input,
                             const std::string &from, const std::string &to);
 
+/*! \brief Return whether two strings are equal, ignoring case.
+ *
+ * Checks if two strings have the same length and if all characters
+ * in them match when compared case insensitive.
+ * Characters are converted by using std::tolower.
+ *
+ * \param[in] source Search string to compare against \p target.
+ * \param[in] target String to be matched to \p source.
+ * \returns True if the strings match.
+ */
+bool equalCaseInsensitive(const std::string &source,
+                          const std::string &target);
+
 class TextLineWrapper;
 
 /*! \brief