Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe807fd9 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

[incfs] Optimize path::join for appending

Append path strings to the first argument if it's an rvalue

Bug: 183435580
Test: atest libincfs-test service.incremental_test
Change-Id: I52c4a1f0e4ad3547aeccac96a3393323e3be9adb
parent cb1cc4f5
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -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() == '/') {
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;
    }
+15 −5
Original line number Diff line number Diff line
@@ -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
+20 −0
Original line number Diff line number Diff line
@@ -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