Split should have a matching Join, if only for convenient debugging output.
Change-Id: I68275a6410af706875f53540db4ef0242f414470
diff --git a/src/heap.cc b/src/heap.cc
index d9027d1..3a3ee5a 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -125,15 +125,10 @@
arg_vector.push_back(strdup("--base=0x60000000"));
- arg_vector.push_back(NULL);
-
- std::string command_line;
- for (size_t i = 0; i < arg_vector.size() - 1; i++) {
- command_line += arg_vector[i];
- command_line += " ";
- }
+ std::string command_line(Join(arg_vector, ' '));
LOG(INFO) << command_line;
+ arg_vector.push_back(NULL);
char** argv = &arg_vector[0];
// fork and exec dex2oat
diff --git a/src/utils.cc b/src/utils.cc
index 78f524f..201834c 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -635,22 +635,41 @@
return IsValidClassName(s, kDescriptor, '/');
}
-void Split(const std::string& s, char delim, std::vector<std::string>& result) {
+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 == delim) {
+ if (*p == separator) {
++p;
} else {
const char* start = p;
- while (++p != end && *p != delim) {
- // Skip to the next occurrence of the delimiter.
+ while (++p != end && *p != separator) {
+ // Skip to the next occurrence of the separator.
}
result.push_back(std::string(start, p - start));
}
}
}
+template <typename StringT>
+std::string Join(std::vector<StringT>& strings, char separator) {
+ if (strings.empty()) {
+ return "";
+ }
+
+ std::string result(strings[0]);
+ for (size_t i = 1; i < strings.size(); ++i) {
+ result += separator;
+ result += strings[i];
+ }
+ return result;
+}
+
+// Explicit instantiations.
+template std::string Join<std::string>(std::vector<std::string>& strings, char separator);
+template std::string Join<const char*>(std::vector<const char*>& strings, char separator);
+template std::string Join<char*>(std::vector<char*>& strings, char separator);
+
void SetThreadName(const char* threadName) {
ANNOTATE_THREAD_NAME(threadName); // For tsan.
diff --git a/src/utils.h b/src/utils.h
index 7807299..74a9802 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -256,9 +256,12 @@
return ns * 1000 * 1000;
}
-// Splits a string using the given delimiter character into a vector of
+// 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 delim, std::vector<std::string>& result);
+void Split(const std::string& s, char separator, std::vector<std::string>& result);
+
+// Joins a vector of strings into a single string, using the given separator.
+template <typename StringT> std::string Join(std::vector<StringT>& strings, char separator);
// Returns the calling thread's tid. (The C libraries don't expose this.)
pid_t GetTid();
diff --git a/src/utils_test.cc b/src/utils_test.cc
index 7f9f4b9..31fccc5 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -256,4 +256,42 @@
EXPECT_EQ(expected, actual);
}
+TEST_F(UtilsTest, Join) {
+ std::vector<std::string> strings;
+
+ strings.clear();
+ EXPECT_EQ("", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("foo");
+ EXPECT_EQ("foo", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("");
+ strings.push_back("foo");
+ EXPECT_EQ(":foo", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("foo");
+ strings.push_back("");
+ EXPECT_EQ("foo:", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("");
+ strings.push_back("foo");
+ strings.push_back("");
+ EXPECT_EQ(":foo:", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("foo");
+ strings.push_back("bar");
+ EXPECT_EQ("foo:bar", Join(strings, ':'));
+
+ strings.clear();
+ strings.push_back("foo");
+ strings.push_back("bar");
+ strings.push_back("baz");
+ EXPECT_EQ("foo:bar:baz", Join(strings, ':'));
+}
+
} // namespace art