diff --git a/benchmark/bench_misc.cpp b/benchmark/bench_misc.cpp index 1674e9ba9..558a70c41 100644 --- a/benchmark/bench_misc.cpp +++ b/benchmark/bench_misc.cpp @@ -223,13 +223,15 @@ class CreateFileBench : public Benchmark { } } void tear_down() override { - auto status = td::walk_path("A/", [&](CSlice path, bool is_dir) { - if (is_dir) { - rmdir(path).ignore(); - } else { - unlink(path).ignore(); - } - }); + td::walk_path("A/", + [&](CSlice path, bool is_dir) { + if (is_dir) { + rmdir(path).ignore(); + } else { + unlink(path).ignore(); + } + }) + .ignore(); } }; @@ -245,19 +247,23 @@ class WalkPathBench : public Benchmark { } void run(int n) override { int cnt = 0; - auto status = td::walk_path("A/", [&](CSlice path, bool is_dir) { - stat(path).ok(); - cnt++; - }); + td::walk_path("A/", + [&](CSlice path, bool is_dir) { + stat(path).ok(); + cnt++; + }) + .ignore(); } void tear_down() override { - auto status = td::walk_path("A/", [&](CSlice path, bool is_dir) { - if (is_dir) { - rmdir(path).ignore(); - } else { - unlink(path).ignore(); - } - }); + td::walk_path("A/", + [&](CSlice path, bool is_dir) { + if (is_dir) { + rmdir(path).ignore(); + } else { + unlink(path).ignore(); + } + }) + .ignore(); } }; diff --git a/benchmark/rmdir.cpp b/benchmark/rmdir.cpp index f1676baa6..38e0d0b7f 100644 --- a/benchmark/rmdir.cpp +++ b/benchmark/rmdir.cpp @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) { auto status = td::walk_path(dir, [&](td::CSlice path, bool is_dir) { cnt++; LOG(INFO) << path << " " << is_dir; - // if (is_dir) { + //if (is_dir) { // td::rmdir(path); //} else { // td::unlink(path); diff --git a/tdutils/td/utils/port/path.cpp b/tdutils/td/utils/port/path.cpp index 44c1d622f..ec3cf2244 100644 --- a/tdutils/td/utils/port/path.cpp +++ b/tdutils/td/utils/port/path.cpp @@ -67,7 +67,7 @@ Status mkpath(CSlice path, int32 mode) { } Status rmrf(CSlice path) { - return walk_path(path, [&](CSlice path, bool is_dir) { + return walk_path(path, [](CSlice path, bool is_dir) { if (is_dir) { return rmdir(path); } else { diff --git a/tdutils/td/utils/port/path.h b/tdutils/td/utils/port/path.h index 9fef36109..72f6ad9fc 100644 --- a/tdutils/td/utils/port/path.h +++ b/tdutils/td/utils/port/path.h @@ -16,8 +16,6 @@ #include "td/utils/Slice.h" #include "td/utils/Status.h" -#include - #if TD_PORT_POSIX #include #include @@ -50,23 +48,23 @@ Result> mkstemp(CSlice dir) TD_WARN_UNUSED_RESULT; Result mkdtemp(CSlice dir, Slice prefix) TD_WARN_UNUSED_RESULT; template -Status walk_path(CSlice path, Func &&func) TD_WARN_UNUSED_RESULT; +Status walk_path(CSlice path, const Func &func) TD_WARN_UNUSED_RESULT; #if TD_PORT_POSIX // TODO move details somewhere else namespace detail { template -Status walk_path_dir(string &path, FileFd fd, Func &&func) TD_WARN_UNUSED_RESULT; +Status walk_path_dir(string &path, FileFd fd, const Func &func) TD_WARN_UNUSED_RESULT; template -Status walk_path_dir(string &path, Func &&func) TD_WARN_UNUSED_RESULT; +Status walk_path_dir(string &path, const Func &func) TD_WARN_UNUSED_RESULT; template -Status walk_path_file(string &path, Func &&func) TD_WARN_UNUSED_RESULT; +Status walk_path_file(string &path, const Func &func) TD_WARN_UNUSED_RESULT; template -Status walk_path(string &path, Func &&func) TD_WARN_UNUSED_RESULT; +Status walk_path(string &path, const Func &func) TD_WARN_UNUSED_RESULT; template -Status walk_path_subdir(string &path, DIR *dir, Func &&func) { +Status walk_path_subdir(string &path, DIR *dir, const Func &func) { while (true) { errno = 0; auto *entry = readdir(dir); @@ -77,7 +75,7 @@ Status walk_path_subdir(string &path, DIR *dir, Func &&func) { if (entry == nullptr) { return Status::OK(); } - Slice name = Slice(&*entry->d_name); + Slice name = Slice(static_cast(entry->d_name)); if (name == "." || name == "..") { continue; } @@ -92,15 +90,15 @@ Status walk_path_subdir(string &path, DIR *dir, Func &&func) { Status status; #ifdef DT_DIR if (entry->d_type == DT_UNKNOWN) { - status = walk_path(path, std::forward(func)); + status = walk_path(path, func); } else if (entry->d_type == DT_DIR) { - status = walk_path_dir(path, std::forward(func)); + status = walk_path_dir(path, func); } else if (entry->d_type == DT_REG) { - status = walk_path_file(path, std::forward(func)); + status = walk_path_file(path, func); } #else #warning "Slow walk_path" - status = walk_path(path, std::forward(func)); + status = walk_path(path, func); #endif if (status.is_error()) { return status; @@ -109,55 +107,54 @@ Status walk_path_subdir(string &path, DIR *dir, Func &&func) { } template -Status walk_path_dir(string &path, DIR *subdir, Func &&func) { +Status walk_path_dir(string &path, DIR *subdir, const Func &func) { SCOPE_EXIT { closedir(subdir); }; - TRY_STATUS(walk_path_subdir(path, subdir, std::forward(func))); - std::forward(func)(path, true); + TRY_STATUS(walk_path_subdir(path, subdir, func)); + func(path, true); return Status::OK(); } template -Status walk_path_dir(string &path, FileFd fd, Func &&func) { +Status walk_path_dir(string &path, FileFd fd, const Func &func) { auto native_fd = fd.move_as_native_fd(); auto *subdir = fdopendir(native_fd.fd()); if (subdir == nullptr) { - auto error = OS_ERROR("fdopendir"); - return error; + return OS_ERROR("fdopendir"); } native_fd.release(); - return walk_path_dir(path, subdir, std::forward(func)); + return walk_path_dir(path, subdir, func); } template -Status walk_path_dir(string &path, Func &&func) { +Status walk_path_dir(string &path, const Func &func) { auto *subdir = opendir(path.c_str()); if (subdir == nullptr) { return OS_ERROR(PSLICE() << tag("opendir", path)); } - return walk_path_dir(path, subdir, std::forward(func)); + return walk_path_dir(path, subdir, func); } template -Status walk_path_file(string &path, Func &&func) { - std::forward(func)(path, false); +Status walk_path_file(string &path, const Func &func) { + func(path, false); return Status::OK(); } template -Status walk_path(string &path, Func &&func) { +Status walk_path(string &path, const Func &func) { TRY_RESULT(fd, FileFd::open(path, FileFd::Read)); auto stat = fd.stat(); bool is_dir = stat.is_dir_; bool is_reg = stat.is_reg_; if (is_dir) { - return walk_path_dir(path, std::move(fd), std::forward(func)); + return walk_path_dir(path, std::move(fd), func); } fd.close(); if (is_reg) { - return walk_path_file(path, std::forward(func)); + return walk_path_file(path, func); } return Status::OK(); @@ -165,11 +162,11 @@ Status walk_path(string &path, Func &&func) { } // namespace detail template -Status walk_path(CSlice path, Func &&func) { +Status walk_path(CSlice path, const Func &func) { string curr_path; curr_path.reserve(PATH_MAX + 10); curr_path = path.c_str(); - return detail::walk_path(curr_path, std::forward(func)); + return detail::walk_path(curr_path, func); } #endif @@ -178,7 +175,7 @@ Status walk_path(CSlice path, Func &&func) { namespace detail { template -Status walk_path_dir(const std::wstring &dir_name, Func &&func) { +Status walk_path_dir(const std::wstring &dir_name, const Func &func) { std::wstring name = dir_name + L"\\*"; WIN32_FIND_DATA file_data; @@ -196,7 +193,6 @@ Status walk_path_dir(const std::wstring &dir_name, Func &&func) { if (file_data.cFileName[0] != '.') { if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { TRY_STATUS(walk_path_dir(full_name, func)); - func(entry_name, true); } else { func(entry_name, false); } @@ -205,23 +201,26 @@ Status walk_path_dir(const std::wstring &dir_name, Func &&func) { if (status == 0) { auto last_error = GetLastError(); if (last_error == ERROR_NO_MORE_FILES) { - return Status::OK(); + break; } return OS_ERROR("FindNextFileW"); } } + TRY_RESULT(entry_name, from_wstring(dir_name)); + func(entry_name, true); + return Status::OK(); } } // namespace detail template -Status walk_path(CSlice path, Func &&func) { +Status walk_path(CSlice path, const Func &func) { TRY_RESULT(wpath, to_wstring(path)); Slice path_slice = path; while (!path_slice.empty() && (path_slice.back() == '/' || path_slice.back() == '\\')) { path_slice.remove_suffix(1); wpath.pop_back(); } - return detail::walk_path_dir(wpath.c_str(), std::forward(func)); + return detail::walk_path_dir(wpath.c_str(), func); } #endif diff --git a/tdutils/test/port.cpp b/tdutils/test/port.cpp index cd0c2bf54..326978d54 100644 --- a/tdutils/test/port.cpp +++ b/tdutils/test/port.cpp @@ -17,14 +17,21 @@ TEST(Port, files) { CSlice main_dir = "test_dir"; rmrf(main_dir).ignore(); ASSERT_TRUE(FileFd::open(main_dir, FileFd::Write).is_error()); + ASSERT_TRUE(walk_path(main_dir, [](CSlice name, bool is_directory) { + UNREACHABLE(); + }).is_error()); mkdir(main_dir).ensure(); mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "A").ensure(); mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B").ensure(); + mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B" << TD_DIR_SLASH << "D").ensure(); mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "C").ensure(); ASSERT_TRUE(FileFd::open(main_dir, FileFd::Write).is_error()); std::string fd_path = PSTRING() << main_dir << TD_DIR_SLASH << "t.txt"; + std::string fd2_path = PSTRING() << main_dir << TD_DIR_SLASH << "C" << TD_DIR_SLASH << "t2.txt"; auto fd = FileFd::open(fd_path, FileFd::Write | FileFd::CreateNew).move_as_ok(); + auto fd2 = FileFd::open(fd2_path, FileFd::Write | FileFd::CreateNew).move_as_ok(); + fd2.close(); int cnt = 0; const int ITER_COUNT = 1000; @@ -32,13 +39,13 @@ TEST(Port, files) { walk_path(main_dir, [&](CSlice name, bool is_directory) { if (!is_directory) { - ASSERT_EQ(fd_path, name); + ASSERT_TRUE(name == fd_path || name == fd2_path); } cnt++; }) .ensure(); } - ASSERT_EQ(4 * ITER_COUNT, cnt); + ASSERT_EQ(7 * ITER_COUNT, cnt); ASSERT_EQ(0u, fd.get_size()); ASSERT_EQ(12u, fd.write("Hello world!").move_as_ok());