Merge "Add absl-like StringReplace."

This commit is contained in:
Elliott Hughes 2019-11-19 15:28:24 +00:00 committed by Gerrit Code Review
commit 43f9d5f34a
3 changed files with 67 additions and 0 deletions

View file

@ -85,5 +85,10 @@ inline bool ConsumeSuffix(std::string_view* s, std::string_view suffix) {
return true;
}
// Replaces `from` with `to` in `s`, once if `all == false`, or as many times as
// there are matches if `all == true`.
[[nodiscard]] std::string StringReplace(std::string_view s, std::string_view from,
std::string_view to, bool all);
} // namespace base
} // namespace android

View file

@ -116,5 +116,24 @@ bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs) {
return lhs.size() == rhs.size() && strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
std::string StringReplace(std::string_view s, std::string_view from, std::string_view to,
bool all) {
if (from.empty()) return std::string(s);
std::string result;
std::string_view::size_type start_pos = 0;
do {
std::string_view::size_type pos = s.find(from, start_pos);
if (pos == std::string_view::npos) break;
result.append(s.data() + start_pos, pos - start_pos);
result.append(to.data(), to.size());
start_pos = pos + from.size();
} while (all);
result.append(s.data() + start_pos, s.size() - start_pos);
return result;
}
} // namespace base
} // namespace android

View file

@ -311,3 +311,46 @@ TEST(strings, ConsumeSuffix) {
ASSERT_TRUE(android::base::ConsumeSuffix(&s, ".bar"));
ASSERT_EQ("foo", s);
}
TEST(strings, StringReplace_false) {
// No change.
ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "z", "Z", false));
ASSERT_EQ("", android::base::StringReplace("", "z", "Z", false));
ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "", "Z", false));
// Equal lengths.
ASSERT_EQ("Abcabc", android::base::StringReplace("abcabc", "a", "A", false));
ASSERT_EQ("aBcabc", android::base::StringReplace("abcabc", "b", "B", false));
ASSERT_EQ("abCabc", android::base::StringReplace("abcabc", "c", "C", false));
// Longer replacement.
ASSERT_EQ("foobcabc", android::base::StringReplace("abcabc", "a", "foo", false));
ASSERT_EQ("afoocabc", android::base::StringReplace("abcabc", "b", "foo", false));
ASSERT_EQ("abfooabc", android::base::StringReplace("abcabc", "c", "foo", false));
// Shorter replacement.
ASSERT_EQ("xxyz", android::base::StringReplace("abcxyz", "abc", "x", false));
ASSERT_EQ("axyz", android::base::StringReplace("abcxyz", "bcx", "x", false));
ASSERT_EQ("abcx", android::base::StringReplace("abcxyz", "xyz", "x", false));
}
TEST(strings, StringReplace_true) {
// No change.
ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "z", "Z", true));
ASSERT_EQ("", android::base::StringReplace("", "z", "Z", true));
ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "", "Z", true));
// Equal lengths.
ASSERT_EQ("AbcAbc", android::base::StringReplace("abcabc", "a", "A", true));
ASSERT_EQ("aBcaBc", android::base::StringReplace("abcabc", "b", "B", true));
ASSERT_EQ("abCabC", android::base::StringReplace("abcabc", "c", "C", true));
// Longer replacement.
ASSERT_EQ("foobcfoobc", android::base::StringReplace("abcabc", "a", "foo", true));
ASSERT_EQ("afoocafooc", android::base::StringReplace("abcabc", "b", "foo", true));
ASSERT_EQ("abfooabfoo", android::base::StringReplace("abcabc", "c", "foo", true));
// Shorter replacement.
ASSERT_EQ("xxyzx", android::base::StringReplace("abcxyzabc", "abc", "x", true));
ASSERT_EQ("<xx>", android::base::StringReplace("<abcabc>", "abc", "x", true));
}