Update string Split API.

Return a new vector rather than appending to the parameter.

Delimiters are also a string rather than a character. Split on any
character in the string.

Change-Id: I039b332ace5578590df9e7ca0e8fa3db28db30a3
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
index 5ddfbbd..ab56aad 100644
--- a/base/include/base/strings.h
+++ b/base/include/base/strings.h
@@ -23,10 +23,15 @@
 namespace android {
 namespace base {
 
-// Splits a string using the given separator character into a vector of strings.
-// Empty strings will be omitted.
-void Split(const std::string& s, char separator,
-           std::vector<std::string>* result);
+// Splits a string into a vector of strings.
+//
+// The string is split at each occurence of a character in delimiters.
+//
+// Empty splits will be omitted. I.e. Split("a,,b", ",") -> {"a", "b"}
+//
+// The empty string is not a valid delimiter list.
+std::vector<std::string> Split(const std::string& s,
+                               const std::string& delimiters);
 
 // Trims whitespace off both ends of the given string.
 std::string Trim(const std::string& s);
diff --git a/base/logging.cpp b/base/logging.cpp
index 3d6c0c2..5b70c7d 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -108,8 +108,7 @@
     return;
   }
 
-  std::vector<std::string> specs;
-  Split(tags, ' ', &specs);
+  std::vector<std::string> specs = Split(tags, " ");
   for (size_t i = 0; i < specs.size(); ++i) {
     // "tag-pattern:[vdiwefs]"
     std::string spec(specs[i]);
diff --git a/base/strings.cpp b/base/strings.cpp
index 224a46f..5f7eccc 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -16,27 +16,39 @@
 
 #include "base/strings.h"
 
+#include <stdlib.h>
+
 #include <string>
 #include <vector>
 
 namespace android {
 namespace base {
 
-void Split(const std::string& s, char separator,
-           std::vector<std::string>* result) {
-  const char* p = s.data();
-  const char* end = p + s.size();
-  while (p != end) {
-    if (*p == separator) {
-      ++p;
-    } else {
-      const char* start = p;
-      while (++p != end && *p != separator) {
-        // Skip to the next occurrence of the separator.
-      }
-      result->push_back(std::string(start, p - start));
-    }
+#define CHECK_NE(a, b) \
+  if ((a) == (b)) abort();
+
+std::vector<std::string> Split(const std::string& s,
+                               const std::string& delimiters) {
+  CHECK_NE(delimiters.size(), 0U);
+
+  std::vector<std::string> split;
+  if (s.size() == 0) {
+    // Split("", d) returns {} rather than {""}.
+    return split;
   }
+
+  size_t base = 0;
+  size_t found;
+  do {
+    found = s.find_first_of(delimiters, base);
+    if (found != base) {
+      split.push_back(s.substr(base, found - base));
+    }
+
+    base = found + 1;
+  } while (found != s.npos);
+
+  return split;
 }
 
 std::string Trim(const std::string& s) {
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 824598d..1bf07a1 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -22,21 +22,18 @@
 #include <vector>
 
 TEST(strings, split_empty) {
-  std::vector<std::string> parts;
-  android::base::Split("", '\0', &parts);
+  std::vector<std::string> parts = android::base::Split("", ",");
   ASSERT_EQ(0U, parts.size());
 }
 
 TEST(strings, split_single) {
-  std::vector<std::string> parts;
-  android::base::Split("foo", ',', &parts);
+  std::vector<std::string> parts = android::base::Split("foo", ",");
   ASSERT_EQ(1U, parts.size());
   ASSERT_EQ("foo", parts[0]);
 }
 
 TEST(strings, split_simple) {
-  std::vector<std::string> parts;
-  android::base::Split("foo,bar,baz", ',', &parts);
+  std::vector<std::string> parts = android::base::Split("foo,bar,baz", ",");
   ASSERT_EQ(3U, parts.size());
   ASSERT_EQ("foo", parts[0]);
   ASSERT_EQ("bar", parts[1]);
@@ -44,8 +41,30 @@
 }
 
 TEST(strings, split_with_empty_part) {
-  std::vector<std::string> parts;
-  android::base::Split("foo,,bar", ',', &parts);
+  std::vector<std::string> parts = android::base::Split("foo,,bar", ",");
+  ASSERT_EQ(2U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+}
+
+TEST(strings, split_null_char) {
+  std::vector<std::string> parts =
+      android::base::Split(std::string("foo\0bar", 7), std::string("\0", 1));
+  ASSERT_EQ(2U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+}
+
+TEST(strings, split_any) {
+  std::vector<std::string> parts = android::base::Split("foo:bar,baz", ",:");
+  ASSERT_EQ(3U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+  ASSERT_EQ("baz", parts[2]);
+}
+
+TEST(strings, split_any_with_empty_part) {
+  std::vector<std::string> parts = android::base::Split("foo:,bar", ",:");
   ASSERT_EQ(2U, parts.size());
   ASSERT_EQ("foo", parts[0]);
   ASSERT_EQ("bar", parts[1]);