Merge "[incfs] Optimize path::join for appending" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d0980160a3
@@ -44,19 +44,20 @@ bool PathLess::operator()(std::string_view l, std::string_view r) const {
|
||||
PathCharsLess());
|
||||
}
|
||||
|
||||
static void preparePathComponent(std::string_view& path, bool trimFront) {
|
||||
if (trimFront) {
|
||||
while (!path.empty() && path.front() == '/') {
|
||||
path.remove_prefix(1);
|
||||
}
|
||||
static void preparePathComponent(std::string_view& path, bool trimAll) {
|
||||
// need to check for double front slash as a single one has a separate meaning in front
|
||||
while (!path.empty() && path.front() == '/' &&
|
||||
(trimAll || (path.size() > 1 && path[1] == '/'))) {
|
||||
path.remove_prefix(1);
|
||||
}
|
||||
while (!path.empty() && path.back() == '/') {
|
||||
// for the back we don't care about double-vs-single slash difference
|
||||
while (path.size() > !trimAll && path.back() == '/') {
|
||||
path.remove_suffix(1);
|
||||
}
|
||||
}
|
||||
|
||||
void details::append_next_path(std::string& target, std::string_view path) {
|
||||
preparePathComponent(path, true);
|
||||
preparePathComponent(path, !target.empty());
|
||||
if (path.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,15 +89,25 @@ std::optional<bool> isEmptyDir(std::string_view dir);
|
||||
bool startsWith(std::string_view path, std::string_view prefix);
|
||||
|
||||
template <class... Paths>
|
||||
std::string join(std::string_view first, std::string_view second, Paths&&... paths) {
|
||||
std::string result;
|
||||
std::string join(std::string&& first, std::string_view second, Paths&&... paths) {
|
||||
std::string& result = first;
|
||||
{
|
||||
using std::size;
|
||||
result.reserve(first.size() + second.size() + 1 + (sizeof...(paths) + ... + size(paths)));
|
||||
}
|
||||
result.assign(first);
|
||||
(details::append_next_path(result, second), ..., details::append_next_path(result, paths));
|
||||
return result;
|
||||
(details::append_next_path(result, second), ...,
|
||||
details::append_next_path(result, std::forward<Paths>(paths)));
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
template <class... Paths>
|
||||
std::string join(std::string_view first, std::string_view second, Paths&&... paths) {
|
||||
return path::join(std::string(), first, second, std::forward<Paths>(paths)...);
|
||||
}
|
||||
|
||||
template <class... Paths>
|
||||
std::string join(const char* first, std::string_view second, Paths&&... paths) {
|
||||
return path::join(std::string_view(first), second, std::forward<Paths>(paths)...);
|
||||
}
|
||||
|
||||
} // namespace android::incremental::path
|
||||
|
||||
@@ -40,4 +40,24 @@ TEST(Path, Comparator) {
|
||||
EXPECT_TRUE(!PathLess()("/a/b", "/a"));
|
||||
}
|
||||
|
||||
TEST(Path, Join) {
|
||||
EXPECT_STREQ("", path::join("", "").c_str());
|
||||
|
||||
EXPECT_STREQ("/", path::join("", "/").c_str());
|
||||
EXPECT_STREQ("/", path::join("/", "").c_str());
|
||||
EXPECT_STREQ("/", path::join("/", "/").c_str());
|
||||
EXPECT_STREQ("/", path::join("/"s, "/").c_str());
|
||||
EXPECT_STREQ("/", path::join("/"sv, "/").c_str());
|
||||
EXPECT_STREQ("/", path::join("/", "/", "/", "/", "/", "/", "/", "/", "/", "/").c_str());
|
||||
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/a/b/"s, "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/a/b/", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/", "a/b/", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/", "a/b", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/", "//a/b//", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("", "", "/", "//a/b//", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join(""s, "", "/", "//a/b//", "c", "d").c_str());
|
||||
EXPECT_STREQ("/a/b/c/d", path::join("/a/b", "", "", "/", "", "/", "/", "/c", "d").c_str());
|
||||
}
|
||||
|
||||
} // namespace android::incremental::path
|
||||
|
||||
Reference in New Issue
Block a user