From: Joel Rosdahl Date: Mon, 17 Jul 2023 07:06:05 +0000 (+0200) Subject: refactor: Improve std::filesystem wrappers X-Git-Tag: v4.9~113 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fecb79ed27ceb025f34a002e961bdc5d0f40eb6f;p=thirdparty%2Fccache.git refactor: Improve std::filesystem wrappers I couldn't figure out how to make the templated versions support both path current_path(); and void current_path(const path& p); so using preprocessor macros instead. --- diff --git a/src/util/filesystem.hpp b/src/util/filesystem.hpp index 7f1202c25..45c2d0add 100644 --- a/src/util/filesystem.hpp +++ b/src/util/filesystem.hpp @@ -27,50 +27,97 @@ namespace util::filesystem { using directory_iterator = std::filesystem::directory_iterator; using path = std::filesystem::path; -#define DEFINE_FS_WRAPPER(name_, fnspec_) \ - template \ - nonstd::expected \ - name_(Args&&... args) \ +// Define wrapper with no parameters returning non-void result. +#define DEF_WRAP_0_R(name_, r_) \ + inline nonstd::expected name_() \ { \ - std::error_code ec; \ - if constexpr (std::is_same::value) { \ - std::filesystem::name_(std::forward(args)..., ec); \ - if (ec) { \ - return nonstd::make_unexpected(ec); \ - } \ - return {}; \ - } else { \ - auto result = std::filesystem::name_(std::forward(args)..., ec); \ - if (ec) { \ - return nonstd::make_unexpected(ec); \ - } \ - return result; \ + std::error_code ec_; \ + auto result_ = std::filesystem::name_(ec_); \ + if (ec_) { \ + return nonstd::make_unexpected(ec_); \ } \ + return result_; \ } -#define DEFINE_FS_PREDICATE_WRAPPER(name_, fnspec_) \ - template bool name_(Args&&... args) \ +// Define wrapper with one parameter returning non-void result. +#define DEF_WRAP_1_R(name_, r_, t1_, p1_) \ + inline nonstd::expected name_(t1_ p1_) \ { \ - std::error_code ec; \ - auto result = std::filesystem::name_(std::forward(args)..., ec); \ - return !ec && result; \ + std::error_code ec_; \ + auto result_ = std::filesystem::name_(p1_, ec_); \ + if (ec_) { \ + return nonstd::make_unexpected(ec_); \ + } \ + return result_; \ + } + +// Define predicate wrapper with one parameter. Returns true if there's no error +// and the wrapped function returned true. +#define DEF_WRAP_1_P(name_, r_, t1_, p1_) \ + inline r_ name_(t1_ p1_) \ + { \ + std::error_code ec_; \ + auto result_ = std::filesystem::name_(p1_, ec_); \ + return !ec_ && result_; \ + } + +// Define wrapper with one parameter returning void. +#define DEF_WRAP_1_V(name_, r_, t1_, p1_) \ + inline nonstd::expected name_(t1_ p1_) \ + { \ + std::error_code ec_; \ + std::filesystem::name_(p1_, ec_); \ + if (ec_) { \ + return nonstd::make_unexpected(ec_); \ + } \ + return {}; \ } -DEFINE_FS_WRAPPER(canonical, (path{})) -DEFINE_FS_WRAPPER(create_directories, (path{})) -DEFINE_FS_WRAPPER(create_directory, (path{})) -DEFINE_FS_WRAPPER(create_hard_link, (path{}, path{})) -DEFINE_FS_WRAPPER(current_path, ()) -DEFINE_FS_WRAPPER(read_symlink, (path{})) -DEFINE_FS_WRAPPER(remove, (path{})) -DEFINE_FS_WRAPPER(remove_all, (path{})) -DEFINE_FS_WRAPPER(temp_directory_path, ()) - -DEFINE_FS_PREDICATE_WRAPPER(exists, (path{})) -DEFINE_FS_PREDICATE_WRAPPER(is_directory, (path{})) - -#undef DEFINE_FS_PREDICATE_WRAPPER -#undef DEFINE_FS_WRAPPER +// Define wrapper with one parameter returning non-void result. +#define DEF_WRAP_1_R(name_, r_, t1_, p1_) \ + inline nonstd::expected name_(t1_ p1_) \ + { \ + std::error_code ec_; \ + auto result_ = std::filesystem::name_(p1_, ec_); \ + if (ec_) { \ + return nonstd::make_unexpected(ec_); \ + } \ + return result_; \ + } + +// Define wrapper with two parameters returning void. +#define DEF_WRAP_2_V(name_, r_, t1_, p1_, t2_, p2_) \ + inline nonstd::expected name_(t1_ p1_, t2_ p2_) \ + { \ + std::error_code ec_; \ + std::filesystem::name_(p1_, p2_, ec_); \ + if (ec_) { \ + return nonstd::make_unexpected(ec_); \ + } \ + return {}; \ + } + +// clang-format off + +// name, ret, pt1, pn1, pt2, pn2 +DEF_WRAP_1_R(canonical, path, const path&, p) +DEF_WRAP_1_R(create_directories, bool, const path&, p) +DEF_WRAP_1_R(create_directory, bool, const path&, p) +DEF_WRAP_2_V(create_hard_link, void, const path&, target, const path&, link) +DEF_WRAP_0_R(current_path, path) +DEF_WRAP_1_P(exists, bool, const path&, p) +DEF_WRAP_1_P(is_directory, bool, const path&, p) +DEF_WRAP_1_R(read_symlink, path, const path&, p) +DEF_WRAP_1_R(remove, bool, const path&, p) +DEF_WRAP_1_R(remove_all, std::uintmax_t, const path&, p) +DEF_WRAP_0_R(temp_directory_path, path) + +// clang-format on + +#undef DEF_WRAP_0_R +#undef DEF_WRAP_1_R +#undef DEF_WRAP_1_P +#undef DEF_WRAP_1_V +#undef DEF_WRAP_2_V } // namespace util::filesystem