Function to split delimited strings
authorTeemu Murtola <teemu.murtola@gmail.com>
Fri, 29 Jul 2016 04:15:43 +0000 (07:15 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Mon, 1 Aug 2016 05:26:26 +0000 (07:26 +0200)
Add a function to split a string at given non-whitespace delimiters, and
tests for it.  Will be used for subsequent work on KeyValueTree.

Change-Id: I28f2658e7c9b32565c02b16600b2e09b444415f4

src/gromacs/utility/stringutil.cpp
src/gromacs/utility/stringutil.h
src/gromacs/utility/tests/stringutil.cpp

index 53ae62cd59a6878efb05f237ae24e41a30bf9370..a6286559aac4ca8dca04382fca1198b4afb2823a 100644 (file)
@@ -197,6 +197,25 @@ std::vector<std::string> splitString(const std::string &str)
     return result;
 }
 
+std::vector<std::string> splitDelimitedString(const std::string &str, char delim)
+{
+    std::vector<std::string> result;
+    size_t                   currPos = 0;
+    const size_t             len     = str.length();
+    if (len > 0)
+    {
+        size_t nextDelim;
+        do
+        {
+            nextDelim = str.find(delim, currPos);
+            result.push_back(str.substr(currPos, nextDelim - currPos));
+            currPos = nextDelim < len ? nextDelim + 1 : len;
+        }
+        while (currPos < len || nextDelim < len);
+    }
+    return result;
+}
+
 namespace
 {
 
index fca596f2b2be1a7b1d10279da63efb0839508e4a..592d517c7332731c16eff2e046b5d2252fbe1bb9 100644 (file)
@@ -343,6 +343,19 @@ static inline const char *boolToString(bool value)
  * separator.
  */
 std::vector<std::string> splitString(const std::string &str);
+/*! \brief
+ * Splits a string to tokens separated by a given delimiter.
+ *
+ * \param[in] str   String to process.
+ * \param[in] delim Delimiter to use for splitting.
+ * \returns   \p str split into tokens at delimiter.
+ * \throws    std::bad_alloc if out of memory.
+ *
+ * Unlike splitString(), consencutive delimiters will generate empty tokens, as
+ * will leading or trailing delimiters.
+ * Empty input will return an empty vector.
+ */
+std::vector<std::string> splitDelimitedString(const std::string &str, char delim);
 
 /*! \brief
  * Replace all occurrences of a string with another string.
index 7145fdb109a48cddf46ce992ad2fa340e5fce318..08a844d53bca90124447e143d1aa9edddb8e1ecb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016, 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.
@@ -126,6 +126,18 @@ TEST(StringUtilityTest, SplitString)
     EXPECT_THAT(gmx::splitString("   "), IsEmpty());
 }
 
+TEST(StringUtilityTest, SplitDelimitedString)
+{
+    using ::testing::ElementsAre;
+    using ::testing::IsEmpty;
+    EXPECT_THAT(gmx::splitDelimitedString("foo;bar", ';'), ElementsAre("foo", "bar"));
+    EXPECT_THAT(gmx::splitDelimitedString(";foo;bar;", ';'), ElementsAre("", "foo", "bar", ""));
+    EXPECT_THAT(gmx::splitDelimitedString("foo;;bar", ';'), ElementsAre("foo", "", "bar"));
+    EXPECT_THAT(gmx::splitDelimitedString("foo", ';'), ElementsAre("foo"));
+    EXPECT_THAT(gmx::splitDelimitedString(";", ';'), ElementsAre("", ""));
+    EXPECT_THAT(gmx::splitDelimitedString("", ';'), IsEmpty());
+}
+
 /********************************************************************
  * Tests for formatString()
  */