[Branch,~jesse-barker/libmatrix/trunk] Rev 37: Util: Update split() to treat the delimiter more flexibly, so that if there is

Message ID 20120501230310.11085.37681.launchpad@ackee.canonical.com
State Accepted
Headers show

Commit Message

Jesse Barker May 1, 2012, 11:03 p.m.
------------------------------------------------------------
revno: 37
committer: Jesse Barker <jesse.barker@linaro.org>
branch nick: trunk
timestamp: Tue 2012-05-01 15:58:28 -0700
message:
  Util: Update split() to treat the delimiter more flexibly, so that if there is
  whitespace or consecutive delimiters, the elements come out cleanly.
modified:
  util.cc
  util.h


--
lp:libmatrix
https://code.launchpad.net/~jesse-barker/libmatrix/trunk

You are subscribed to branch lp:libmatrix.
To unsubscribe from this branch go to https://code.launchpad.net/~jesse-barker/libmatrix/trunk/+edit-subscription

Patch

=== modified file 'util.cc'
--- util.cc	2012-01-27 21:58:38 +0000
+++ util.cc	2012-05-01 22:58:28 +0000
@@ -22,21 +22,46 @@ 
 #include "log.h"
 #include "util.h"
 
-/**
- * Splits a string using a delimiter
- *
- * @param s the string to split
- * @param delim the delimitir to use
- * @param elems the string vector to populate
- */
+using std::string;
+using std::vector;
+
 void
-Util::split(const std::string &s, char delim, std::vector<std::string> &elems)
+Util::split(const string& src, char delim, vector<string>& elementVec)
 {
-    std::stringstream ss(s);
-
-    std::string item;
-    while(std::getline(ss, item, delim))
-        elems.push_back(item);
+    if (src.empty())
+    {
+        return;
+    }
+    // Initialize our delimiter string based upon the caller's plus a space
+    // to allow for more flexibility.
+    string delimiter(" ");
+    delimiter += delim;
+    // Starting index into the string of the first token (by definition, if
+    // we're parsing a string, there is at least one token).
+    string::size_type startPos(0);
+    // string::find_first_of() looks for any character in the string provided,
+    // it is not treated as a sub-string, so regardless of where the space or
+    // comma is or how many there are, the result is the same.
+    string str(src);
+    string::size_type endPos = str.find_first_of(delimiter);
+    while (endPos != string::npos)
+    {
+        // Push back the current element starting at startPos for
+        // (endPos - startPos) characters.  std::string takes care of
+        // terminators, etc.
+        elementVec.push_back(string(str, startPos, endPos - startPos));
+        // Index of the next element after any delimiter characters.  Same
+        // caveat applies to find_first_not_of() that applies to
+        // find_first_of(); endPos tells it where to start the search. 
+        string::size_type nextPos = str.find_first_not_of(delimiter, endPos);
+        // Erase the part of the string we've already parsed.
+        str = str.erase(startPos, nextPos - startPos);
+        // Look for the next delimiter.  If there isn't one, we bail out.
+        endPos = str.find_first_of(delimiter);
+    }
+    // Regardless of whether we initially had one element or many, 'str' now
+    // only contains one.
+    elementVec.push_back(str);
 }
 
 uint64_t

=== modified file 'util.h'
--- util.h	2012-01-27 21:58:38 +0000
+++ util.h	2012-05-01 22:58:28 +0000
@@ -24,7 +24,23 @@ 
 #endif
 
 struct Util {
+    /**
+     * split() - Splits a string into elements separated by a delimiter
+     *
+     * @s:     the string to split
+     * @delim: the delimiter to use
+     * @elems: the string vector to populate
+     *
+     * Splits @s into a vector of string elements, delimited by @delim, that
+     * get returned in @elems.  The handling of @delim allows for spaces on
+     * either side of the delimiter or even multiple consecutive delimiters
+     * with no elements between.  As long as @s is non-empty, there will be
+     * at least one element in @elems.
+     */
     static void split(const std::string &s, char delim, std::vector<std::string> &elems);
+    /**
+     * get_timestamp_us() - Returns the current time in microseconds
+     */
     static uint64_t get_timestamp_us();
     static std::istream *get_resource(const std::string &path);
     static void list_files(const std::string& dirName, std::vector<std::string>& fileVec);
@@ -44,7 +60,7 @@ 
     fromString(const std::string& asString)
     {
         std::stringstream ss(asString);
-        T retVal;
+        T retVal = T();
         ss >> retVal;
         return retVal;
     }