From 53b883d015c08eab0530728fc4782987dc7b39f0 Mon Sep 17 00:00:00 2001 From: Tim Stack Date: Tue, 21 May 2024 23:45:48 -0700 Subject: [PATCH] [internal] remove ghc::filesystem --- src/CMakeLists.txt | 6 - src/Makefile.am | 6 - src/archive_manager.cc | 9 +- src/archive_manager.hh | 18 +- src/base/fs_util.cc | 41 +- src/base/fs_util.hh | 43 +- src/base/paths.cc | 24 +- src/base/paths.hh | 6 +- src/base/piper.file.cc | 2 +- src/base/piper.file.hh | 4 +- src/command_executor.cc | 12 +- src/command_executor.hh | 4 +- src/curl_looper.cc | 4 +- src/dump_internals.cc | 4 +- src/file_collection.cc | 10 +- src/file_converter_manager.cc | 15 +- src/file_converter_manager.hh | 4 +- src/file_format.cc | 2 +- src/file_format.hh | 8 +- src/file_options.cc | 4 +- src/file_options.hh | 6 +- src/files_sub_source.cc | 6 +- src/fstat_vtab.cc | 6 +- src/ghc/filesystem.hpp | 6049 --------------------------------- src/ghc/fs_fwd.hpp | 38 - src/ghc/fs_impl.hpp | 35 - src/ghc/fs_std.hpp | 60 - src/ghc/fs_std_fwd.hpp | 63 - src/ghc/fs_std_impl.hpp | 46 - src/line_buffer.cc | 34 +- src/lnav.cc | 22 +- src/lnav.hh | 6 +- src/lnav.management_cli.cc | 12 +- src/lnav_commands.cc | 8 +- src/lnav_config.cc | 24 +- src/lnav_config.hh | 6 +- src/log.annotate.cc | 4 +- src/log_actions.cc | 4 +- src/log_format.cc | 2 +- src/log_format_ext.hh | 2 +- src/log_format_loader.cc | 20 +- src/log_format_loader.hh | 12 +- src/logfile.cc | 10 +- src/logfile.hh | 16 +- src/logfile_fwd.hh | 2 + src/md2attr_line.cc | 8 +- src/md2attr_line.hh | 6 +- src/piper.looper.cc | 23 +- src/piper.looper.hh | 12 +- src/readline_callbacks.cc | 2 +- src/readline_curses.cc | 21 +- src/readline_possibilities.cc | 2 +- src/regex101.client.cc | 4 +- src/regex101.import.cc | 8 +- src/regex101.import.hh | 8 +- src/session.export.cc | 16 +- src/static_file_vtab.cc | 12 +- src/tailer/drive_tailer.cc | 22 +- src/tailer/tailer.looper.cc | 68 +- src/tailer/tailer.looper.hh | 8 +- src/text_anonymizer.cc | 10 +- src/text_format.cc | 28 +- src/text_format.hh | 4 +- src/unique_path.hh | 14 +- src/url_handler.cc | 2 +- src/url_loader.hh | 6 +- src/view_curses.cc | 2 +- src/yajlpp/yajlpp.cc | 6 +- test/drive_data_scanner.cc | 2 +- test/drive_doc_discovery.cc | 2 +- test/drive_logfile.cc | 2 +- test/lnav_doctests.cc | 6 +- test/scripty.cc | 10 +- test/test_cli.sh | 1 + test/test_top_status.cc | 2 +- 75 files changed, 382 insertions(+), 6654 deletions(-) delete mode 100644 src/ghc/filesystem.hpp delete mode 100644 src/ghc/fs_fwd.hpp delete mode 100644 src/ghc/fs_impl.hpp delete mode 100644 src/ghc/fs_std.hpp delete mode 100644 src/ghc/fs_std_fwd.hpp delete mode 100644 src/ghc/fs_std_impl.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 06ec6fdb..ef5db6fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -647,12 +647,6 @@ add_library( mapbox/variant.hpp mapbox/variant_io.hpp mapbox/variant_visitor.hpp - ghc/filesystem.hpp - ghc/fs_fwd.hpp - ghc/fs_impl.hpp - ghc/fs_std.hpp - ghc/fs_std_fwd.hpp - ghc/fs_std_impl.hpp ww898/cp_utf8.hpp log_level_re.cc diff --git a/src/Makefile.am b/src/Makefile.am index ff43ae00..c72a68d9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -379,12 +379,6 @@ noinst_HEADERS = \ xpath_vtab.hh \ xterm_mouse.hh \ spookyhash/SpookyV2.h \ - ghc/filesystem.hpp \ - ghc/fs_fwd.hpp \ - ghc/fs_impl.hpp \ - ghc/fs_std.hpp \ - ghc/fs_std_fwd.hpp \ - ghc/fs_std_impl.hpp \ ww898/cp_utf8.hpp nodist_libdiag_a_SOURCES = \ diff --git a/src/archive_manager.cc b/src/archive_manager.cc index ee86cea3..fb814d9b 100644 --- a/src/archive_manager.cc +++ b/src/archive_manager.cc @@ -52,7 +52,7 @@ #include "fmt/format.h" #include "hasher.hh" -namespace fs = ghc::filesystem; +namespace fs = std::filesystem; namespace archive_manager { @@ -269,7 +269,9 @@ extract(const std::string& filename, const extract_cb& cb) } } if (file_count > 0) { - fs::last_write_time(done_path, std::chrono::system_clock::now()); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; + fs::last_write_time(done_path, now); log_info("%s: archive has already been extracted!", done_path.c_str()); return Ok(); @@ -399,7 +401,8 @@ void cleanup_cache() { (void) std::async(std::launch::async, []() { - auto now = std::chrono::system_clock::now(); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; auto cache_path = archive_cache_path(); const auto& cfg = injector::get(); std::vector to_remove; diff --git a/src/archive_manager.hh b/src/archive_manager.hh index 949e5b73..bbdb27f1 100644 --- a/src/archive_manager.hh +++ b/src/archive_manager.hh @@ -39,28 +39,28 @@ #include "base/file_range.hh" #include "base/result.h" -#include "ghc/filesystem.hpp" +#include #include "mapbox/variant.hpp" namespace archive_manager { struct extract_progress { - extract_progress(ghc::filesystem::path path, ssize_t total) + extract_progress(std::filesystem::path path, ssize_t total) : ep_path(std::move(path)), ep_total_size(total) { } - const ghc::filesystem::path ep_path; + const std::filesystem::path ep_path; const ssize_t ep_total_size; std::atomic ep_out_size{0}; }; using extract_cb - = std::function; + = std::function; struct archive_info { struct entry { - ghc::filesystem::path e_name; + std::filesystem::path e_name; const char* e_mode; time_t e_mtime; std::optional e_size; @@ -73,9 +73,9 @@ struct unknown_file {}; using describe_result = mapbox::util::variant; Result describe( - const ghc::filesystem::path& filename); + const std::filesystem::path& filename); -ghc::filesystem::path filename_to_tmp_path(const std::string& filename); +std::filesystem::path filename_to_tmp_path(const std::string& filename); using walk_result_t = Result; @@ -90,8 +90,8 @@ using walk_result_t = Result; walk_result_t walk_archive_files( const std::string& filename, const extract_cb& cb, - const std::function&); + const std::function&); void cleanup_cache(); diff --git a/src/base/fs_util.cc b/src/base/fs_util.cc index a56ef502..5f6ef2f7 100644 --- a/src/base/fs_util.cc +++ b/src/base/fs_util.cc @@ -27,6 +27,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "fs_util.hh" #include @@ -41,7 +43,7 @@ namespace lnav { namespace filesystem { std::string -escape_path(const ghc::filesystem::path& p) +escape_path(const std::filesystem::path& p) { auto p_str = p.string(); std::string retval; @@ -70,8 +72,8 @@ escape_path(const ghc::filesystem::path& p) return retval; } -Result -realpath(const ghc::filesystem::path& path) +Result +realpath(const std::filesystem::path& path) { char resolved[PATH_MAX]; auto rc = ::realpath(path.c_str(), resolved); @@ -80,11 +82,11 @@ realpath(const ghc::filesystem::path& path) return Err(std::string(strerror(errno))); } - return Ok(ghc::filesystem::path(resolved)); + return Ok(std::filesystem::path(resolved)); } Result -create_file(const ghc::filesystem::path& path, int flags, mode_t mode) +create_file(const std::filesystem::path& path, int flags, mode_t mode) { auto fd = openp(path, flags | O_CREAT, mode); @@ -98,7 +100,7 @@ create_file(const ghc::filesystem::path& path, int flags, mode_t mode) } Result -open_file(const ghc::filesystem::path& path, int flags) +open_file(const std::filesystem::path& path, int flags) { auto fd = openp(path, flags); @@ -111,8 +113,8 @@ open_file(const ghc::filesystem::path& path, int flags) return Ok(auto_fd(fd)); } -Result, std::string> -open_temp_file(const ghc::filesystem::path& pattern) +Result, std::string> +open_temp_file(const std::filesystem::path& pattern) { auto pattern_str = pattern.string(); char pattern_copy[pattern_str.size() + 1]; @@ -126,14 +128,14 @@ open_temp_file(const ghc::filesystem::path& pattern) strerror(errno))); } - return Ok(std::make_pair(ghc::filesystem::path(pattern_copy), auto_fd(fd))); + return Ok(std::make_pair(std::filesystem::path(pattern_copy), auto_fd(fd))); } Result -read_file(const ghc::filesystem::path& path) +read_file(const std::filesystem::path& path) { try { - ghc::filesystem::ifstream file_stream(path); + std::ifstream file_stream(path); if (!file_stream) { return Err(std::string(strerror(errno))); @@ -149,7 +151,7 @@ read_file(const ghc::filesystem::path& path) } Result -write_file(const ghc::filesystem::path& path, +write_file(const std::filesystem::path& path, const string_fragment& content, std::set options) { @@ -175,11 +177,11 @@ write_file(const ghc::filesystem::path& path, std::error_code ec; if (options.count(write_file_options::backup_existing)) { - if (ghc::filesystem::exists(path, ec)) { + if (std::filesystem::exists(path, ec)) { auto backup_path = path; backup_path += ".bak"; - ghc::filesystem::rename(path, backup_path, ec); + std::filesystem::rename(path, backup_path, ec); if (ec) { return Err( fmt::format(FMT_STRING("unable to backup file {}: {}"), @@ -191,7 +193,7 @@ write_file(const ghc::filesystem::path& path, } } - ghc::filesystem::rename(tmp_pair.first, path, ec); + std::filesystem::rename(tmp_pair.first, path, ec); if (ec) { return Err( fmt::format(FMT_STRING("unable to move temporary file {}: {}"), @@ -203,7 +205,7 @@ write_file(const ghc::filesystem::path& path, } std::string -build_path(const std::vector& paths) +build_path(const std::vector& paths) { return paths | lnav::itertools::map([](const auto& path) { return path.string(); }) @@ -220,7 +222,7 @@ build_path(const std::vector& paths) } Result -stat_file(const ghc::filesystem::path& path) +stat_file(const std::filesystem::path& path) { struct stat retval; @@ -233,7 +235,8 @@ stat_file(const ghc::filesystem::path& path) strerror(errno))); } -file_lock::file_lock(const ghc::filesystem::path& archive_path) +file_lock:: +file_lock(const std::filesystem::path& archive_path) { auto lock_path = archive_path; @@ -252,7 +255,7 @@ file_lock::file_lock(const ghc::filesystem::path& archive_path) namespace fmt { auto -formatter::format(const ghc::filesystem::path& p, +formatter::format(const std::filesystem::path& p, format_context& ctx) -> decltype(ctx.out()) const { diff --git a/src/base/fs_util.hh b/src/base/fs_util.hh index 380bfda5..e5102746 100644 --- a/src/base/fs_util.hh +++ b/src/base/fs_util.hh @@ -30,13 +30,16 @@ #ifndef lnav_fs_util_hh #define lnav_fs_util_hh +#include #include #include #include #include +#include +#include + #include "auto_fd.hh" -#include "ghc/filesystem.hpp" #include "intern_string.hh" #include "result.h" @@ -51,57 +54,57 @@ is_glob(const std::string& fn) || fn.find('[') != std::string::npos); } -std::string escape_path(const ghc::filesystem::path& p); +std::string escape_path(const std::filesystem::path& p); inline int -statp(const ghc::filesystem::path& path, struct stat* buf) +statp(const std::filesystem::path& path, struct stat* buf) { return stat(path.c_str(), buf); } inline int -openp(const ghc::filesystem::path& path, int flags) +openp(const std::filesystem::path& path, int flags) { return open(path.c_str(), flags); } inline int -openp(const ghc::filesystem::path& path, int flags, mode_t mode) +openp(const std::filesystem::path& path, int flags, mode_t mode) { return open(path.c_str(), flags, mode); } -Result realpath( - const ghc::filesystem::path& path); +Result realpath( + const std::filesystem::path& path); -Result create_file(const ghc::filesystem::path& path, +Result create_file(const std::filesystem::path& path, int flags, mode_t mode); -Result open_file(const ghc::filesystem::path& path, +Result open_file(const std::filesystem::path& path, int flags); -Result stat_file(const ghc::filesystem::path& path); +Result stat_file(const std::filesystem::path& path); -Result, std::string> open_temp_file( - const ghc::filesystem::path& pattern); +Result, std::string> open_temp_file( + const std::filesystem::path& pattern); -Result read_file(const ghc::filesystem::path& path); +Result read_file(const std::filesystem::path& path); enum class write_file_options { backup_existing, }; struct write_file_result { - std::optional wfr_backup_path; + std::optional wfr_backup_path; }; Result write_file( - const ghc::filesystem::path& path, + const std::filesystem::path& path, const string_fragment& content, std::set options = {}); -std::string build_path(const std::vector& paths); +std::string build_path(const std::vector& paths); class file_lock { public: @@ -136,7 +139,7 @@ public: void unlock() const { lockf(this->lh_fd, F_ULOCK, 0); } - explicit file_lock(const ghc::filesystem::path& archive_path); + explicit file_lock(const std::filesystem::path& archive_path); auto_fd lh_fd; }; @@ -146,9 +149,9 @@ public: namespace fmt { template<> -struct formatter : formatter { - auto format(const ghc::filesystem::path& p, - format_context& ctx) -> decltype(ctx.out()) const; +struct formatter : formatter { + auto format(const std::filesystem::path& p, format_context& ctx) + -> decltype(ctx.out()) const; }; } // namespace fmt diff --git a/src/base/paths.cc b/src/base/paths.cc index ca53a070..9e7d1aa0 100644 --- a/src/base/paths.cc +++ b/src/base/paths.cc @@ -34,6 +34,8 @@ # include #endif +#include + #include "fmt/format.h" #include "paths.hh" @@ -76,7 +78,7 @@ windows_to_unix_file_path(char* input) } #endif -ghc::filesystem::path +std::filesystem::path dotlnav() { #ifdef __CYGWIN__ @@ -87,26 +89,26 @@ dotlnav() auto xdg_config_home = getenv("XDG_CONFIG_HOME"); if (home_env != nullptr) { - auto home_path = ghc::filesystem::path(home_env); + auto home_path = std::filesystem::path(home_env); - if (ghc::filesystem::is_directory(home_path)) { + if (std::filesystem::is_directory(home_path)) { auto home_lnav = home_path / ".lnav"; - if (ghc::filesystem::is_directory(home_lnav)) { + if (std::filesystem::is_directory(home_lnav)) { return home_lnav; } if (xdg_config_home != nullptr) { - auto xdg_path = ghc::filesystem::path(xdg_config_home); + auto xdg_path = std::filesystem::path(xdg_config_home); - if (ghc::filesystem::is_directory(xdg_path)) { + if (std::filesystem::is_directory(xdg_path)) { return xdg_path / "lnav"; } } auto home_config = home_path / ".config"; - if (ghc::filesystem::is_directory(home_config)) { + if (std::filesystem::is_directory(home_config)) { return home_config / "lnav"; } @@ -114,16 +116,16 @@ dotlnav() } } - return ghc::filesystem::current_path(); + return std::filesystem::current_path(); } -ghc::filesystem::path +std::filesystem::path workdir() { auto subdir_name = fmt::format(FMT_STRING("lnav-user-{}-work"), getuid()); - auto tmp_path = ghc::filesystem::temp_directory_path(); + auto tmp_path = std::filesystem::temp_directory_path(); - return tmp_path / ghc::filesystem::path(subdir_name); + return tmp_path / std::filesystem::path(subdir_name); } } // namespace paths diff --git a/src/base/paths.hh b/src/base/paths.hh index 6c43a2a1..13292bf9 100644 --- a/src/base/paths.hh +++ b/src/base/paths.hh @@ -30,7 +30,7 @@ #ifndef lnav_paths_hh #define lnav_paths_hh -#include "ghc/filesystem.hpp" +#include namespace lnav { namespace paths { @@ -48,9 +48,9 @@ char* windows_to_unix_file_path(char* input); * @param sub The path to the file in the '.lnav' directory. * @return The full path */ -ghc::filesystem::path dotlnav(); +std::filesystem::path dotlnav(); -ghc::filesystem::path workdir(); +std::filesystem::path workdir(); } // namespace paths } // namespace lnav diff --git a/src/base/piper.file.cc b/src/base/piper.file.cc index 099845ec..17e5adf1 100644 --- a/src/base/piper.file.cc +++ b/src/base/piper.file.cc @@ -42,7 +42,7 @@ namespace piper { const char HEADER_MAGIC[4] = {'L', 0, 'N', 1}; -const ghc::filesystem::path& +const std::filesystem::path& storage_path() { static auto INSTANCE = lnav::paths::workdir() / "piper"; diff --git a/src/base/piper.file.hh b/src/base/piper.file.hh index 57a4d778..89607181 100644 --- a/src/base/piper.file.hh +++ b/src/base/piper.file.hh @@ -39,7 +39,7 @@ #include "auto_mem.hh" #include "base/intern_string.hh" -#include "ghc/filesystem.hpp" +#include #include "mapbox/variant_io.hpp" #include "time_util.hh" @@ -76,7 +76,7 @@ struct header { } }; -const ghc::filesystem::path& storage_path(); +const std::filesystem::path& storage_path(); constexpr size_t HEADER_SIZE = 8; extern const char HEADER_MAGIC[4]; diff --git a/src/command_executor.cc b/src/command_executor.cc index 9a87b122..58002d01 100644 --- a/src/command_executor.cc +++ b/src/command_executor.cc @@ -603,10 +603,10 @@ multiline_executor::final() } static Result -execute_file_contents(exec_context& ec, const ghc::filesystem::path& path) +execute_file_contents(exec_context& ec, const std::filesystem::path& path) { - static const ghc::filesystem::path stdin_path("-"); - static const ghc::filesystem::path dev_stdin_path("/dev/stdin"); + static const std::filesystem::path stdin_path("-"); + static const std::filesystem::path dev_stdin_path("/dev/stdin"); std::string retval; FILE* file; @@ -715,13 +715,13 @@ execute_file(exec_context& ec, const std::string& path_and_args) } else if (errno != ENOENT) { open_error = strerror(errno); } else { - auto script_path = ghc::filesystem::path(script_name); + auto script_path = std::filesystem::path(script_name); if (!script_path.is_absolute()) { script_path = ec.ec_path_stack.back() / script_path; } - if (ghc::filesystem::is_regular_file(script_path)) { + if (std::filesystem::is_regular_file(script_path)) { struct script_metadata meta; meta.sm_path = script_path; @@ -1066,7 +1066,7 @@ pipe_callback(exec_context& ec, const std::string& cmdline, auto_fd& fd) }); } std::error_code errc; - ghc::filesystem::create_directories(lnav::paths::workdir(), errc); + std::filesystem::create_directories(lnav::paths::workdir(), errc); auto open_temp_res = lnav::filesystem::open_temp_file(lnav::paths::workdir() / "exec.XXXXXX"); if (open_temp_res.isErr()) { diff --git a/src/command_executor.hh b/src/command_executor.hh index ba567c68..ecc8d889 100644 --- a/src/command_executor.hh +++ b/src/command_executor.hh @@ -41,7 +41,7 @@ #include "base/lnav.console.hh" #include "db_sub_source.hh" #include "fmt/format.h" -#include "ghc/filesystem.hpp" +#include #include "help_text.hh" #include "shlex.resolver.hh" #include "vis_line.hh" @@ -301,7 +301,7 @@ struct exec_context { std::stack> ec_local_vars; std::vector ec_provenance; std::map ec_global_vars; - std::vector ec_path_stack; + std::vector ec_path_stack; std::vector ec_source; help_text* ec_current_help{nullptr}; diff --git a/src/curl_looper.cc b/src/curl_looper.cc index db97c40e..ac2345ba 100644 --- a/src/curl_looper.cc +++ b/src/curl_looper.cc @@ -191,7 +191,9 @@ curl_request::complete(CURLcode result) return -1; } -curl_looper::curl_looper() : cl_curl_multi(curl_multi_cleanup) +curl_looper:: +curl_looper() + : cl_curl_multi(curl_multi_cleanup) { this->cl_curl_multi.reset(curl_multi_init()); } diff --git a/src/dump_internals.cc b/src/dump_internals.cc index fe4904d7..4c8bd9a1 100644 --- a/src/dump_internals.cc +++ b/src/dump_internals.cc @@ -61,7 +61,7 @@ dump_internals(const char* internals_dir) execute_examples(); - auto cmd_ref_path = ghc::filesystem::path(internals_dir) / "cmd-ref.rst"; + auto cmd_ref_path = std::filesystem::path(internals_dir) / "cmd-ref.rst"; auto cmd_file = std::unique_ptr( fopen(cmd_ref_path.c_str(), "w+"), fclose); @@ -78,7 +78,7 @@ dump_internals(const char* internals_dir) } } - auto sql_ref_path = ghc::filesystem::path(internals_dir) / "sql-ref.rst"; + auto sql_ref_path = std::filesystem::path(internals_dir) / "sql-ref.rst"; auto sql_file = std::unique_ptr( fopen(sql_ref_path.c_str(), "w+"), fclose); std::set unique_sql_help; diff --git a/src/file_collection.cc b/src/file_collection.cc index c693e348..29a4744d 100644 --- a/src/file_collection.cc +++ b/src/file_collection.cc @@ -162,7 +162,7 @@ file_collection::regenerate_unique_file_names() safe::ReadAccess errs(*this->fc_name_to_errors); for (const auto& pair : *errs) { - auto path = ghc::filesystem::path(pair.first).filename().string(); + auto path = std::filesystem::path(pair.first).filename().string(); if (path.length() > this->fc_largest_path_length) { this->fc_largest_path_length = path.length(); @@ -182,7 +182,7 @@ file_collection::regenerate_unique_file_names() case file_format_t::ARCHIVE: case file_format_t::MULTIPLEXED: case file_format_t::SQLITE_DB: { - auto bn = ghc::filesystem::path(pair.first).filename().string(); + auto bn = std::filesystem::path(pair.first).filename().string(); if (bn.length() > this->fc_largest_path_length) { this->fc_largest_path_length = bn.length(); } @@ -307,7 +307,9 @@ file_collection::watch_logfile(const std::string& filename, int rc; auto filename_key = loo.loo_filename.empty() ? filename : loo.loo_filename; - if (this->fc_closed_files.count(filename)) { + if (this->fc_closed_files.count(filename) + || this->fc_closed_files.count(filename_key)) + { return std::nullopt; } @@ -464,7 +466,7 @@ file_collection::watch_logfile(const std::string& filename, }, [&filename, &retval](const auto& tmp_path, const auto& entry) { - auto arc_path = ghc::filesystem::relative( + auto arc_path = std::filesystem::relative( entry.path(), tmp_path); auto custom_name = filename / arc_path; bool is_visible = true; diff --git a/src/file_converter_manager.cc b/src/file_converter_manager.cc index 6f016522..028a269a 100644 --- a/src/file_converter_manager.cc +++ b/src/file_converter_manager.cc @@ -44,7 +44,7 @@ namespace file_converter_manager { -static const ghc::filesystem::path& +static const std::filesystem::path& cache_dir() { static auto INSTANCE = lnav::paths::workdir() / "conversion"; @@ -57,7 +57,7 @@ convert(const external_file_format& eff, const std::string& filename) { log_info("attempting to convert file -- %s", filename.c_str()); - ghc::filesystem::create_directories(cache_dir()); + std::filesystem::create_directories(cache_dir()); auto outfile = TRY(lnav::filesystem::open_temp_file( cache_dir() / fmt::format(FMT_STRING("{}.XXXXXX"), eff.eff_format_name))); @@ -160,14 +160,15 @@ cleanup() { (void) std::async(std::launch::async, []() { const auto& cfg = injector::get(); - auto now = std::chrono::system_clock::now(); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; auto cache_path = cache_dir(); - std::vector to_remove; + std::vector to_remove; for (const auto& entry : - ghc::filesystem::directory_iterator(cache_path)) + std::filesystem::directory_iterator(cache_path)) { - auto mtime = ghc::filesystem::last_write_time(entry.path()); + auto mtime = std::filesystem::last_write_time(entry.path()); auto exp_time = mtime + cfg.c_ttl; if (now < exp_time) { continue; @@ -178,7 +179,7 @@ cleanup() for (auto& entry : to_remove) { log_debug("removing conversion: %s", entry.c_str()); - ghc::filesystem::remove_all(entry); + std::filesystem::remove_all(entry); } }); } diff --git a/src/file_converter_manager.hh b/src/file_converter_manager.hh index 281f195a..c27edd5e 100644 --- a/src/file_converter_manager.hh +++ b/src/file_converter_manager.hh @@ -37,13 +37,13 @@ #include "base/auto_pid.hh" #include "base/result.h" #include "file_format.hh" -#include "ghc/filesystem.hpp" +#include namespace file_converter_manager { struct convert_result { auto_pid cr_child; - ghc::filesystem::path cr_destination; + std::filesystem::path cr_destination; std::shared_ptr> cr_error_queue; }; diff --git a/src/file_format.cc b/src/file_format.cc index 53598d0b..c946c8c4 100644 --- a/src/file_format.cc +++ b/src/file_format.cc @@ -40,7 +40,7 @@ #include "line_buffer.hh" file_format_t -detect_file_format(const ghc::filesystem::path& filename) +detect_file_format(const std::filesystem::path& filename) { auto describe_res = archive_manager::describe(filename); if (describe_res.isOk() diff --git a/src/file_format.hh b/src/file_format.hh index 32f4cafe..b9fa9be3 100644 --- a/src/file_format.hh +++ b/src/file_format.hh @@ -35,7 +35,7 @@ #include #include "fmt/format.h" -#include "ghc/filesystem.hpp" +#include enum class file_format_t : int { UNKNOWN, @@ -48,13 +48,13 @@ enum class file_format_t : int { struct external_file_format { std::string eff_format_name; std::string eff_converter; - ghc::filesystem::path eff_source_path; + std::filesystem::path eff_source_path; }; -file_format_t detect_file_format(const ghc::filesystem::path& filename); +file_format_t detect_file_format(const std::filesystem::path& filename); std::optional detect_mime_type( - const ghc::filesystem::path& filename); + const std::filesystem::path& filename); namespace fmt { template<> diff --git a/src/file_options.cc b/src/file_options.cc index 88aa7cc4..6af1a462 100644 --- a/src/file_options.cc +++ b/src/file_options.cc @@ -115,9 +115,9 @@ file_options_collection::match(const std::string& path) const } std::optional> -file_options_hier::match(const ghc::filesystem::path& path) const +file_options_hier::match(const std::filesystem::path& path) const { - static const auto ROOT_PATH = ghc::filesystem::path("/"); + static const auto ROOT_PATH = std::filesystem::path("/"); auto lookup_path = path.parent_path(); diff --git a/src/file_options.hh b/src/file_options.hh index 48971db7..b76e08f6 100644 --- a/src/file_options.hh +++ b/src/file_options.hh @@ -35,7 +35,7 @@ #include "base/lnav.console.hh" #include "base/result.h" #include "date/tz.h" -#include "ghc/filesystem.hpp" +#include #include "mapbox/variant.hpp" #include "safe/safe.h" #include "yajlpp/yajlpp.hh" @@ -66,12 +66,12 @@ struct file_options_collection { }; struct file_options_hier { - std::map + std::map foh_path_to_collection; size_t foh_generation{0}; std::optional> match( - const ghc::filesystem::path& path) const; + const std::filesystem::path& path) const; }; using safe_file_options_hier = safe::Safe; diff --git a/src/files_sub_source.cc b/src/files_sub_source.cc index 4f2fff24..c009159f 100644 --- a/src/files_sub_source.cc +++ b/src/files_sub_source.cc @@ -268,7 +268,7 @@ files_sub_source::text_value_for_line(textview_curses& tc, if (line < errs->size()) { auto iter = std::next(errs->begin(), line); - auto path = ghc::filesystem::path(iter->first); + auto path = std::filesystem::path(iter->first); auto fn = fmt::to_string(path.filename()); truncate_to(fn, filename_width); @@ -293,7 +293,7 @@ files_sub_source::text_value_for_line(textview_curses& tc, if (line < fc.fc_other_files.size()) { auto iter = std::next(fc.fc_other_files.begin(), line); - auto path = ghc::filesystem::path(iter->first); + auto path = std::filesystem::path(iter->first); auto fn = fmt::to_string(path); truncate_to(fn, filename_width); @@ -322,7 +322,7 @@ files_sub_source::text_value_for_line(textview_curses& tc, const auto& lf = fc.fc_files[line]; auto ld_opt = lnav_data.ld_log_source.find_data(lf); - auto fn = fmt::to_string(ghc::filesystem::path(lf->get_unique_path())); + auto fn = fmt::to_string(std::filesystem::path(lf->get_unique_path())); char start_time[64] = "", end_time[64] = ""; std::vector file_notes; diff --git a/src/fstat_vtab.cc b/src/fstat_vtab.cc index ac885470..6916d029 100644 --- a/src/fstat_vtab.cc +++ b/src/fstat_vtab.cc @@ -41,7 +41,7 @@ #include "base/lnav_log.hh" #include "bound_tags.hh" #include "config.h" -#include "ghc/filesystem.hpp" +#include #include "sql_help.hh" #include "sql_util.hh" #include "vtab_module.hh" @@ -338,7 +338,7 @@ CREATE TABLE fstat ( SQLITE_TRANSIENT); break; case FSTAT_COL_DATA: { - auto fs_path = ghc::filesystem::path{path}; + auto fs_path = std::filesystem::path{path}; if (!vc.c_error.empty()) { sqlite3_result_null(ctx); } else if (S_ISREG(vc.c_stat.st_mode)) { @@ -370,7 +370,7 @@ CREATE TABLE fstat ( to_sqlite(ctx, blob_auto_buffer{std::move(buffer)}); } } else if (S_ISLNK(vc.c_stat.st_mode)) { - auto link_path = ghc::filesystem::read_symlink(fs_path); + auto link_path = std::filesystem::read_symlink(fs_path); to_sqlite(ctx, link_path.string()); } else { diff --git a/src/ghc/filesystem.hpp b/src/ghc/filesystem.hpp deleted file mode 100644 index 9540b440..00000000 --- a/src/ghc/filesystem.hpp +++ /dev/null @@ -1,6049 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17/C++20 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// -// To dynamically select std::filesystem where available on most platforms, -// you could use: -// -// #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) -// #if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) -// #define GHC_USE_STD_FS -// #include -// namespace fs = std::filesystem; -// #endif -// #endif -// #ifndef GHC_USE_STD_FS -// #include -// namespace fs = ghc::filesystem; -// #endif -// -//--------------------------------------------------------------------------------------- -#ifndef GHC_FILESYSTEM_H -#define GHC_FILESYSTEM_H - -// #define BSD manifest constant only in -// sys/param.h -#ifndef _WIN32 -#include -#endif - -#ifndef GHC_OS_DETECTED -#if defined(__APPLE__) && defined(__MACH__) -#define GHC_OS_MACOS -#elif defined(__linux__) -#define GHC_OS_LINUX -#if defined(__ANDROID__) -#define GHC_OS_ANDROID -#endif -#elif defined(_WIN64) -#define GHC_OS_WINDOWS -#define GHC_OS_WIN64 -#elif defined(_WIN32) -#define GHC_OS_WINDOWS -#define GHC_OS_WIN32 -#elif defined(__CYGWIN__) -#define GHC_OS_CYGWIN -#elif defined(__sun) && defined(__SVR4) -#define GHC_OS_SOLARIS -#elif defined(__svr4__) -#define GHC_OS_SYS5R4 -#elif defined(BSD) -#define GHC_OS_BSD -#elif defined(__EMSCRIPTEN__) -#define GHC_OS_WEB -#include -#elif defined(__QNX__) -#define GHC_OS_QNX -#else -#error "Operating system currently not supported!" -#endif -#define GHC_OS_DETECTED -#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -#if _MSVC_LANG == 201703L -#define GHC_FILESYSTEM_RUNNING_CPP17 -#else -#define GHC_FILESYSTEM_RUNNING_CPP20 -#endif -#elif (defined(__cplusplus) && __cplusplus >= 201703L) -#if __cplusplus == 201703L -#define GHC_FILESYSTEM_RUNNING_CPP17 -#else -#define GHC_FILESYSTEM_RUNNING_CPP20 -#endif -#endif -#endif - -#if defined(GHC_FILESYSTEM_IMPLEMENTATION) -#define GHC_EXPAND_IMPL -#define GHC_INLINE -#ifdef GHC_OS_WINDOWS -#ifndef GHC_FS_API -#define GHC_FS_API -#endif -#ifndef GHC_FS_API_CLASS -#define GHC_FS_API_CLASS -#endif -#else -#ifndef GHC_FS_API -#define GHC_FS_API __attribute__((visibility("default"))) -#endif -#ifndef GHC_FS_API_CLASS -#define GHC_FS_API_CLASS __attribute__((visibility("default"))) -#endif -#endif -#elif defined(GHC_FILESYSTEM_FWD) -#define GHC_INLINE -#ifdef GHC_OS_WINDOWS -#ifndef GHC_FS_API -#define GHC_FS_API extern -#endif -#ifndef GHC_FS_API_CLASS -#define GHC_FS_API_CLASS -#endif -#else -#ifndef GHC_FS_API -#define GHC_FS_API extern -#endif -#ifndef GHC_FS_API_CLASS -#define GHC_FS_API_CLASS -#endif -#endif -#else -#define GHC_EXPAND_IMPL -#define GHC_INLINE inline -#ifndef GHC_FS_API -#define GHC_FS_API -#endif -#ifndef GHC_FS_API_CLASS -#define GHC_FS_API_CLASS -#endif -#endif - -#ifdef GHC_EXPAND_IMPL - -#ifdef GHC_OS_WINDOWS -#include -// additional includes -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef GHC_OS_ANDROID -#include -#if __ANDROID_API__ < 12 -#include -#endif -#include -#define statvfs statfs -#else -#include -#endif -#ifdef GHC_OS_CYGWIN -#include -#endif -#if !defined(__ANDROID__) || __ANDROID_API__ >= 26 -#include -#endif -#endif -#ifdef GHC_OS_MACOS -#include -#endif - -#if defined(__cpp_impl_three_way_comparison) && defined(__has_include) -#if __has_include() -#define GHC_HAS_THREEWAY_COMP -#include -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else // GHC_EXPAND_IMPL - -#if defined(__cpp_impl_three_way_comparison) && defined(__has_include) -#if __has_include() -#define GHC_HAS_THREEWAY_COMP -#include -#endif -#endif -#include -#include -#include -#include -#include -#include -#include -#ifdef GHC_OS_WINDOWS -#include -#endif -#endif // GHC_EXPAND_IMPL - -// After standard library includes. -// Standard library support for std::string_view. -#if defined(__cpp_lib_string_view) -#define GHC_HAS_STD_STRING_VIEW -#elif defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 4000) && (__cplusplus >= 201402) -#define GHC_HAS_STD_STRING_VIEW -#elif defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 7) && (__cplusplus >= 201703) -#define GHC_HAS_STD_STRING_VIEW -#elif defined(_MSC_VER) && (_MSC_VER >= 1910 && _MSVC_LANG >= 201703) -#define GHC_HAS_STD_STRING_VIEW -#endif - -// Standard library support for std::experimental::string_view. -#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 3700 && _LIBCPP_VERSION < 7000) && (__cplusplus >= 201402) -#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW -#elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402) -#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW -#elif defined(__GLIBCXX__) && defined(_GLIBCXX_USE_DUAL_ABI) && (__cplusplus >= 201402) -// macro _GLIBCXX_USE_DUAL_ABI is always defined in libstdc++ from gcc-5 and newer -#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW -#endif - -#if defined(GHC_HAS_STD_STRING_VIEW) -#include -#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) -#include -#endif - -#if !defined(GHC_OS_WINDOWS) && !defined(PATH_MAX) -#define PATH_MAX 4096 -#endif - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp): -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Enforce C++17 API where possible when compiling for C++20, handles the following cases: -// * fs::path::u8string() returns std::string instead of std::u8string -// #define GHC_FILESYSTEM_ENFORCE_CPP17_API -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories -// configure LWG conformance () -#define LWG_2682_BEHAVIOUR -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular -// file with that name, it is superseded by P1164R1, so only activate if really needed -// #define LWG_2935_BEHAVIOUR -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// LWG #2936 enables new element wise (more expensive) path comparison -// * if this->root_name().native().compare(p.root_name().native()) != 0 return result -// * if this->has_root_directory() and !p.has_root_directory() return -1 -// * if !this->has_root_directory() and p.has_root_directory() return -1 -// * else result of element wise comparison of path iteration where first comparison is != 0 or 0 -// if all comparisons are 0 (on Windows this implementation does case-insensitive root_name() -// comparison) -#define LWG_2936_BEHAVIOUR -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2) -#define LWG_2937_BEHAVIOUR -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the Windows -// version defaults to std::wstring storage backend. Still all std::string will be interpreted -// as UTF-8 encoded. With this define you can enforce the old behavior on Windows, using -// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This -// needs more conversions, so it is (and was before v1.5) slower, bot might help keeping source -// homogeneous in a multi-platform project. -// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found, -// instead of replacing them with the unicode replacement character (U+FFFD). -// #define GHC_RAISE_UNICODE_ERRORS -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Automatic prefix windows path with "\\?\" if they would break the MAX_PATH length. -// instead of replacing them with the unicode replacement character (U+FFFD). -#ifndef GHC_WIN_DISABLE_AUTO_PREFIXES -#define GHC_WIN_AUTO_PREFIX_LONG_PATH -#endif // GHC_WIN_DISABLE_AUTO_PREFIXES -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch) -#define GHC_FILESYSTEM_VERSION 10512L - -#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)) -#define GHC_WITH_EXCEPTIONS -#endif -#if !defined(GHC_WITH_EXCEPTIONS) && defined(GHC_RAISE_UNICODE_ERRORS) -#error "Can't raise unicode errors with exception support disabled" -#endif - -namespace ghc { -namespace filesystem { - -#if defined(GHC_HAS_CUSTOM_STRING_VIEW) -#define GHC_WITH_STRING_VIEW -#elif defined(GHC_HAS_STD_STRING_VIEW) -#define GHC_WITH_STRING_VIEW -using std::basic_string_view; -#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) -#define GHC_WITH_STRING_VIEW -using std::experimental::basic_string_view; -#endif - -// temporary existing exception type for yet unimplemented parts -class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error -{ -public: - not_implemented_exception() - : std::logic_error("function not implemented yet.") - { - } -}; - -template -class path_helper_base -{ -public: - using value_type = char_type; -#ifdef GHC_OS_WINDOWS - static constexpr value_type preferred_separator = '\\'; -#else - static constexpr value_type preferred_separator = '/'; -#endif -}; - -#if __cplusplus < 201703L -template -constexpr char_type path_helper_base::preferred_separator; -#endif - -#ifdef GHC_OS_WINDOWS -class path; -namespace detail { -bool has_executable_extension(const path& p); -} -#endif - -// [fs.class.path] class path -class GHC_FS_API_CLASS path -#if defined(GHC_OS_WINDOWS) && !defined(GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE) -#define GHC_USE_WCHAR_T -#define GHC_NATIVEWP(p) p.c_str() -#define GHC_PLATFORM_LITERAL(str) L##str - : private path_helper_base -{ -public: - using path_helper_base::value_type; -#else -#define GHC_NATIVEWP(p) p.wstring().c_str() -#define GHC_PLATFORM_LITERAL(str) str - : private path_helper_base -{ -public: - using path_helper_base::value_type; -#endif - using string_type = std::basic_string; - using path_helper_base::preferred_separator; - - // [fs.enum.path.format] enumeration format - /// The path format in which the constructor argument is given. - enum format { - generic_format, ///< The generic format, internally used by - ///< ghc::filesystem::path with slashes - native_format, ///< The format native to the current platform this code - ///< is build for - auto_format, ///< Try to auto-detect the format, fallback to native - }; - - template - struct _is_basic_string : std::false_type - { - }; - template - struct _is_basic_string> : std::true_type - { - }; - template - struct _is_basic_string, std::allocator>> : std::true_type - { - }; -#ifdef GHC_WITH_STRING_VIEW - template - struct _is_basic_string> : std::true_type - { - }; - template - struct _is_basic_string>> : std::true_type - { - }; -#endif - - template - using path_type = typename std::enable_if::value, path>::type; - template -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) - using path_from_string = - typename std::enable_if<_is_basic_string::value || std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || - std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || - std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || - std::is_same::type>::value, - path>::type; - template - using path_type_EcharT = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value, path>::type; -#else - using path_from_string = - typename std::enable_if<_is_basic_string::value || std::is_same::type>::value || std::is_same::type>::value || - std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || - std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value, - path>::type; - template - using path_type_EcharT = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, path>::type; -#endif - // [fs.path.construct] constructors and destructor - path() noexcept; - path(const path& p); - path(path&& p) noexcept; - path(string_type&& source, format fmt = auto_format); - template > - path(const Source& source, format fmt = auto_format); - template - path(InputIterator first, InputIterator last, format fmt = auto_format); -#ifdef GHC_WITH_EXCEPTIONS - template > - path(const Source& source, const std::locale& loc, format fmt = auto_format); - template - path(InputIterator first, InputIterator last, const std::locale& loc, format fmt = auto_format); -#endif - ~path(); - - // [fs.path.assign] assignments - path& operator=(const path& p); - path& operator=(path&& p) noexcept; - path& operator=(string_type&& source); - path& assign(string_type&& source); - template - path& operator=(const Source& source); - template - path& assign(const Source& source); - template - path& assign(InputIterator first, InputIterator last); - - // [fs.path.append] appends - path& operator/=(const path& p); - template - path& operator/=(const Source& source); - template - path& append(const Source& source); - template - path& append(InputIterator first, InputIterator last); - - // [fs.path.concat] concatenation - path& operator+=(const path& x); - path& operator+=(const string_type& x); -#ifdef GHC_WITH_STRING_VIEW - path& operator+=(basic_string_view x); -#endif - path& operator+=(const value_type* x); - path& operator+=(value_type x); - template - path_from_string& operator+=(const Source& x); - template - path_type_EcharT& operator+=(EcharT x); - template - path& concat(const Source& x); - template - path& concat(InputIterator first, InputIterator last); - - // [fs.path.modifiers] modifiers - void clear() noexcept; - path& make_preferred(); - path& remove_filename(); - path& replace_filename(const path& replacement); - path& replace_extension(const path& replacement = path()); - void swap(path& rhs) noexcept; - - // [fs.path.native.obs] native format observers - const string_type& native() const noexcept; - const value_type* c_str() const noexcept; - operator string_type() const; - template , class Allocator = std::allocator> - std::basic_string string(const Allocator& a = Allocator()) const; - std::string string() const; - std::wstring wstring() const; -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) - std::u8string u8string() const; -#else - std::string u8string() const; -#endif - std::u16string u16string() const; - std::u32string u32string() const; - - // [fs.path.generic.obs] generic format observers - template , class Allocator = std::allocator> - std::basic_string generic_string(const Allocator& a = Allocator()) const; - std::string generic_string() const; - std::wstring generic_wstring() const; -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) - std::u8string generic_u8string() const; -#else - std::string generic_u8string() const; -#endif - std::u16string generic_u16string() const; - std::u32string generic_u32string() const; - - // [fs.path.compare] compare - int compare(const path& p) const noexcept; - int compare(const string_type& s) const; -#ifdef GHC_WITH_STRING_VIEW - int compare(basic_string_view s) const; -#endif - int compare(const value_type* s) const; - - // [fs.path.decompose] decomposition - path root_name() const; - path root_directory() const; - path root_path() const; - path relative_path() const; - path parent_path() const; - path filename() const; - path stem() const; - path extension() const; - - // [fs.path.query] query - bool empty() const noexcept; - bool has_root_name() const; - bool has_root_directory() const; - bool has_root_path() const; - bool has_relative_path() const; - bool has_parent_path() const; - bool has_filename() const; - bool has_stem() const; - bool has_extension() const; - bool is_absolute() const; - bool is_relative() const; - - // [fs.path.gen] generation - path lexically_normal() const; - path lexically_relative(const path& base) const; - path lexically_proximate(const path& base) const; - - // [fs.path.itr] iterators - class iterator; - using const_iterator = iterator; - iterator begin() const; - iterator end() const; - -private: - using impl_value_type = value_type; - using impl_string_type = std::basic_string; - friend class directory_iterator; - void append_name(const value_type* name); - static constexpr impl_value_type generic_separator = '/'; - template - class input_iterator_range - { - public: - typedef InputIterator iterator; - typedef InputIterator const_iterator; - typedef typename InputIterator::difference_type difference_type; - - input_iterator_range(const InputIterator& first, const InputIterator& last) - : _first(first) - , _last(last) - { - } - - InputIterator begin() const { return _first; } - InputIterator end() const { return _last; } - - private: - InputIterator _first; - InputIterator _last; - }; - friend void swap(path& lhs, path& rhs) noexcept; - friend size_t hash_value(const path& p) noexcept; - friend path canonical(const path& p, std::error_code& ec); - friend bool create_directories(const path& p, std::error_code& ec) noexcept; - string_type::size_type root_name_length() const noexcept; - void postprocess_path_with_format(format fmt); - void check_long_path(); - impl_string_type _path; -#ifdef GHC_OS_WINDOWS - void handle_prefixes(); - friend bool detail::has_executable_extension(const path& p); -#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH - string_type::size_type _prefixLength{0}; -#else // GHC_WIN_AUTO_PREFIX_LONG_PATH - static const string_type::size_type _prefixLength{0}; -#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH -#else - static const string_type::size_type _prefixLength{0}; -#endif -}; - -// [fs.path.nonmember] path non-member functions -GHC_FS_API void swap(path& lhs, path& rhs) noexcept; -GHC_FS_API size_t hash_value(const path& p) noexcept; -#ifdef GHC_HAS_THREEWAY_COMP -GHC_FS_API std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; -#endif -GHC_FS_API bool operator==(const path& lhs, const path& rhs) noexcept; -GHC_FS_API bool operator!=(const path& lhs, const path& rhs) noexcept; -GHC_FS_API bool operator<(const path& lhs, const path& rhs) noexcept; -GHC_FS_API bool operator<=(const path& lhs, const path& rhs) noexcept; -GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept; -GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept; -GHC_FS_API path operator/(const path& lhs, const path& rhs); - -// [fs.path.io] path inserter and extractor -template -std::basic_ostream& operator<<(std::basic_ostream& os, const path& p); -template -std::basic_istream& operator>>(std::basic_istream& is, path& p); - -// [pfs.path.factory] path factory functions -template > -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) -[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]] -#endif -path u8path(const Source& source); -template -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) -[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]] -#endif -path u8path(InputIterator first, InputIterator last); - -// [fs.class.filesystem_error] class filesystem_error -class GHC_FS_API_CLASS filesystem_error : public std::system_error -{ -public: - filesystem_error(const std::string& what_arg, std::error_code ec); - filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec); - filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec); - const path& path1() const noexcept; - const path& path2() const noexcept; - const char* what() const noexcept override; - -private: - std::string _what_arg; - std::error_code _ec; - path _p1, _p2; -}; - -class GHC_FS_API_CLASS path::iterator -{ -public: - using value_type = const path; - using difference_type = std::ptrdiff_t; - using pointer = const path*; - using reference = const path&; - using iterator_category = std::bidirectional_iterator_tag; - - iterator(); - iterator(const path& p, const impl_string_type::const_iterator& pos); - iterator& operator++(); - iterator operator++(int); - iterator& operator--(); - iterator operator--(int); - bool operator==(const iterator& other) const; - bool operator!=(const iterator& other) const; - reference operator*() const; - pointer operator->() const; - -private: - friend class path; - impl_string_type::const_iterator increment(const impl_string_type::const_iterator& pos) const; - impl_string_type::const_iterator decrement(const impl_string_type::const_iterator& pos) const; - void updateCurrent(); - impl_string_type::const_iterator _first; - impl_string_type::const_iterator _last; - impl_string_type::const_iterator _prefix; - impl_string_type::const_iterator _root; - impl_string_type::const_iterator _iter; - path _current; -}; - -struct space_info -{ - uintmax_t capacity; - uintmax_t free; - uintmax_t available; -}; - -// [fs.enum] enumerations -// [fs.enum.file_type] -enum class file_type { - none, - not_found, - regular, - directory, - symlink, - block, - character, - fifo, - socket, - unknown, -}; - -// [fs.enum.perms] -enum class perms : uint16_t { - none = 0, - - owner_read = 0400, - owner_write = 0200, - owner_exec = 0100, - owner_all = 0700, - - group_read = 040, - group_write = 020, - group_exec = 010, - group_all = 070, - - others_read = 04, - others_write = 02, - others_exec = 01, - others_all = 07, - - all = 0777, - set_uid = 04000, - set_gid = 02000, - sticky_bit = 01000, - - mask = 07777, - unknown = 0xffff -}; - -// [fs.enum.perm.opts] -enum class perm_options : uint16_t { - replace = 3, - add = 1, - remove = 2, - nofollow = 4, -}; - -// [fs.enum.copy.opts] -enum class copy_options : uint16_t { - none = 0, - - skip_existing = 1, - overwrite_existing = 2, - update_existing = 4, - - recursive = 8, - - copy_symlinks = 0x10, - skip_symlinks = 0x20, - - directories_only = 0x40, - create_symlinks = 0x80, -#ifndef GHC_OS_WEB - create_hard_links = 0x100 -#endif -}; - -// [fs.enum.dir.opts] -enum class directory_options : uint16_t { - none = 0, - follow_directory_symlink = 1, - skip_permission_denied = 2, -}; - -// [fs.class.file_status] class file_status -class GHC_FS_API_CLASS file_status -{ -public: - // [fs.file_status.cons] constructors and destructor - file_status() noexcept; - explicit file_status(file_type ft, perms prms = perms::unknown) noexcept; - file_status(const file_status&) noexcept; - file_status(file_status&&) noexcept; - ~file_status(); - // assignments: - file_status& operator=(const file_status&) noexcept; - file_status& operator=(file_status&&) noexcept; - // [fs.file_status.mods] modifiers - void type(file_type ft) noexcept; - void permissions(perms prms) noexcept; - // [fs.file_status.obs] observers - file_type type() const noexcept; - perms permissions() const noexcept; - friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } - -private: - file_type _type; - perms _perms; -}; - -using file_time_type = std::chrono::time_point; - -// [fs.class.directory_entry] Class directory_entry -class GHC_FS_API_CLASS directory_entry -{ -public: - // [fs.dir.entry.cons] constructors and destructor - directory_entry() noexcept = default; - directory_entry(const directory_entry&) = default; - directory_entry(directory_entry&&) noexcept = default; -#ifdef GHC_WITH_EXCEPTIONS - explicit directory_entry(const path& p); -#endif - directory_entry(const path& p, std::error_code& ec); - ~directory_entry(); - - // assignments: - directory_entry& operator=(const directory_entry&) = default; - directory_entry& operator=(directory_entry&&) noexcept = default; - - // [fs.dir.entry.mods] modifiers -#ifdef GHC_WITH_EXCEPTIONS - void assign(const path& p); - void replace_filename(const path& p); - void refresh(); -#endif - void assign(const path& p, std::error_code& ec); - void replace_filename(const path& p, std::error_code& ec); - void refresh(std::error_code& ec) noexcept; - - // [fs.dir.entry.obs] observers - const filesystem::path& path() const noexcept; - operator const filesystem::path&() const noexcept; -#ifdef GHC_WITH_EXCEPTIONS - bool exists() const; - bool is_block_file() const; - bool is_character_file() const; - bool is_directory() const; - bool is_fifo() const; - bool is_other() const; - bool is_regular_file() const; - bool is_socket() const; - bool is_symlink() const; - uintmax_t file_size() const; - file_time_type last_write_time() const; - file_status status() const; - file_status symlink_status() const; -#endif - bool exists(std::error_code& ec) const noexcept; - bool is_block_file(std::error_code& ec) const noexcept; - bool is_character_file(std::error_code& ec) const noexcept; - bool is_directory(std::error_code& ec) const noexcept; - bool is_fifo(std::error_code& ec) const noexcept; - bool is_other(std::error_code& ec) const noexcept; - bool is_regular_file(std::error_code& ec) const noexcept; - bool is_socket(std::error_code& ec) const noexcept; - bool is_symlink(std::error_code& ec) const noexcept; - uintmax_t file_size(std::error_code& ec) const noexcept; - file_time_type last_write_time(std::error_code& ec) const noexcept; - file_status status(std::error_code& ec) const noexcept; - file_status symlink_status(std::error_code& ec) const noexcept; - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS - uintmax_t hard_link_count() const; -#endif - uintmax_t hard_link_count(std::error_code& ec) const noexcept; -#endif - -#ifdef GHC_HAS_THREEWAY_COMP - std::strong_ordering operator<=>(const directory_entry& rhs) const noexcept; -#endif - bool operator<(const directory_entry& rhs) const noexcept; - bool operator==(const directory_entry& rhs) const noexcept; - bool operator!=(const directory_entry& rhs) const noexcept; - bool operator<=(const directory_entry& rhs) const noexcept; - bool operator>(const directory_entry& rhs) const noexcept; - bool operator>=(const directory_entry& rhs) const noexcept; - -private: - friend class directory_iterator; -#ifdef GHC_WITH_EXCEPTIONS - file_type status_file_type() const; -#endif - file_type status_file_type(std::error_code& ec) const noexcept; - filesystem::path _path; - file_status _status; - file_status _symlink_status; - uintmax_t _file_size = static_cast(-1); -#ifndef GHC_OS_WINDOWS - uintmax_t _hard_link_count = static_cast(-1); -#endif - time_t _last_write_time = 0; -}; - -// [fs.class.directory.iterator] Class directory_iterator -class GHC_FS_API_CLASS directory_iterator -{ -public: - class GHC_FS_API_CLASS proxy - { - public: - const directory_entry& operator*() const& noexcept { return _dir_entry; } - directory_entry operator*() && noexcept { return std::move(_dir_entry); } - - private: - explicit proxy(const directory_entry& dir_entry) - : _dir_entry(dir_entry) - { - } - friend class directory_iterator; - friend class recursive_directory_iterator; - directory_entry _dir_entry; - }; - using iterator_category = std::input_iterator_tag; - using value_type = directory_entry; - using difference_type = std::ptrdiff_t; - using pointer = const directory_entry*; - using reference = const directory_entry&; - - // [fs.dir.itr.members] member functions - directory_iterator() noexcept; -#ifdef GHC_WITH_EXCEPTIONS - explicit directory_iterator(const path& p); - directory_iterator(const path& p, directory_options options); -#endif - directory_iterator(const path& p, std::error_code& ec) noexcept; - directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept; - directory_iterator(const directory_iterator& rhs); - directory_iterator(directory_iterator&& rhs) noexcept; - ~directory_iterator(); - directory_iterator& operator=(const directory_iterator& rhs); - directory_iterator& operator=(directory_iterator&& rhs) noexcept; - const directory_entry& operator*() const; - const directory_entry* operator->() const; -#ifdef GHC_WITH_EXCEPTIONS - directory_iterator& operator++(); -#endif - directory_iterator& increment(std::error_code& ec) noexcept; - - // other members as required by [input.iterators] -#ifdef GHC_WITH_EXCEPTIONS - proxy operator++(int) - { - proxy p{**this}; - ++*this; - return p; - } -#endif - bool operator==(const directory_iterator& rhs) const; - bool operator!=(const directory_iterator& rhs) const; - -private: - friend class recursive_directory_iterator; - class impl; - std::shared_ptr _impl; -}; - -// [fs.dir.itr.nonmembers] directory_iterator non-member functions -GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept; -GHC_FS_API directory_iterator end(const directory_iterator&) noexcept; - -// [fs.class.re.dir.itr] class recursive_directory_iterator -class GHC_FS_API_CLASS recursive_directory_iterator -{ -public: - using iterator_category = std::input_iterator_tag; - using value_type = directory_entry; - using difference_type = std::ptrdiff_t; - using pointer = const directory_entry*; - using reference = const directory_entry&; - - // [fs.rec.dir.itr.members] constructors and destructor - recursive_directory_iterator() noexcept; -#ifdef GHC_WITH_EXCEPTIONS - explicit recursive_directory_iterator(const path& p); - recursive_directory_iterator(const path& p, directory_options options); -#endif - recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept; - recursive_directory_iterator(const path& p, std::error_code& ec) noexcept; - recursive_directory_iterator(const recursive_directory_iterator& rhs); - recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; - ~recursive_directory_iterator(); - - // [fs.rec.dir.itr.members] observers - directory_options options() const; - int depth() const; - bool recursion_pending() const; - - const directory_entry& operator*() const; - const directory_entry* operator->() const; - - // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator& - recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs); - recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept; -#ifdef GHC_WITH_EXCEPTIONS - recursive_directory_iterator& operator++(); -#endif - recursive_directory_iterator& increment(std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS - void pop(); -#endif - void pop(std::error_code& ec); - void disable_recursion_pending(); - - // other members as required by [input.iterators] -#ifdef GHC_WITH_EXCEPTIONS - directory_iterator::proxy operator++(int) - { - directory_iterator::proxy proxy{**this}; - ++*this; - return proxy; - } -#endif - bool operator==(const recursive_directory_iterator& rhs) const; - bool operator!=(const recursive_directory_iterator& rhs) const; - -private: - struct recursive_directory_iterator_impl - { - directory_options _options; - bool _recursion_pending; - std::stack _dir_iter_stack; - recursive_directory_iterator_impl(directory_options options, bool recursion_pending) - : _options(options) - , _recursion_pending(recursion_pending) - { - } - }; - std::shared_ptr _impl; -}; - -// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions -GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; -GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept; - -// [fs.op.funcs] filesystem operations -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API path absolute(const path& p); -GHC_FS_API path canonical(const path& p); -GHC_FS_API void copy(const path& from, const path& to); -GHC_FS_API void copy(const path& from, const path& to, copy_options options); -GHC_FS_API bool copy_file(const path& from, const path& to); -GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option); -GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink); -GHC_FS_API bool create_directories(const path& p); -GHC_FS_API bool create_directory(const path& p); -GHC_FS_API bool create_directory(const path& p, const path& attributes); -GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink); -GHC_FS_API void create_symlink(const path& to, const path& new_symlink); -GHC_FS_API path current_path(); -GHC_FS_API void current_path(const path& p); -GHC_FS_API bool exists(const path& p); -GHC_FS_API bool equivalent(const path& p1, const path& p2); -GHC_FS_API uintmax_t file_size(const path& p); -GHC_FS_API bool is_block_file(const path& p); -GHC_FS_API bool is_character_file(const path& p); -GHC_FS_API bool is_directory(const path& p); -GHC_FS_API bool is_empty(const path& p); -GHC_FS_API bool is_fifo(const path& p); -GHC_FS_API bool is_other(const path& p); -GHC_FS_API bool is_regular_file(const path& p); -GHC_FS_API bool is_socket(const path& p); -GHC_FS_API bool is_symlink(const path& p); -GHC_FS_API file_time_type last_write_time(const path& p); -GHC_FS_API void last_write_time(const path& p, file_time_type new_time); -GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace); -GHC_FS_API path proximate(const path& p, const path& base = current_path()); -GHC_FS_API path read_symlink(const path& p); -GHC_FS_API path relative(const path& p, const path& base = current_path()); -GHC_FS_API bool remove(const path& p); -GHC_FS_API uintmax_t remove_all(const path& p); -GHC_FS_API void rename(const path& from, const path& to); -GHC_FS_API void resize_file(const path& p, uintmax_t size); -GHC_FS_API space_info space(const path& p); -GHC_FS_API file_status status(const path& p); -GHC_FS_API file_status symlink_status(const path& p); -GHC_FS_API path temp_directory_path(); -GHC_FS_API path weakly_canonical(const path& p); -#endif -GHC_FS_API path absolute(const path& p, std::error_code& ec); -GHC_FS_API path canonical(const path& p, std::error_code& ec); -GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept; -GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept; -GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept; -GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept; -GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept; -GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept; -GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; -GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; -GHC_FS_API path current_path(std::error_code& ec); -GHC_FS_API void current_path(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool exists(file_status s) noexcept; -GHC_FS_API bool exists(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept; -GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_block_file(file_status s) noexcept; -GHC_FS_API bool is_block_file(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_character_file(file_status s) noexcept; -GHC_FS_API bool is_character_file(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_directory(file_status s) noexcept; -GHC_FS_API bool is_directory(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_empty(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_fifo(file_status s) noexcept; -GHC_FS_API bool is_fifo(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_other(file_status s) noexcept; -GHC_FS_API bool is_other(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_regular_file(file_status s) noexcept; -GHC_FS_API bool is_regular_file(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_socket(file_status s) noexcept; -GHC_FS_API bool is_socket(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool is_symlink(file_status s) noexcept; -GHC_FS_API bool is_symlink(const path& p, std::error_code& ec) noexcept; -GHC_FS_API file_time_type last_write_time(const path& p, std::error_code& ec) noexcept; -GHC_FS_API void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept; -GHC_FS_API void permissions(const path& p, perms prms, std::error_code& ec) noexcept; -GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept; -GHC_FS_API path proximate(const path& p, std::error_code& ec); -GHC_FS_API path proximate(const path& p, const path& base, std::error_code& ec); -GHC_FS_API path read_symlink(const path& p, std::error_code& ec); -GHC_FS_API path relative(const path& p, std::error_code& ec); -GHC_FS_API path relative(const path& p, const path& base, std::error_code& ec); -GHC_FS_API bool remove(const path& p, std::error_code& ec) noexcept; -GHC_FS_API uintmax_t remove_all(const path& p, std::error_code& ec) noexcept; -GHC_FS_API void rename(const path& from, const path& to, std::error_code& ec) noexcept; -GHC_FS_API void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept; -GHC_FS_API space_info space(const path& p, std::error_code& ec) noexcept; -GHC_FS_API file_status status(const path& p, std::error_code& ec) noexcept; -GHC_FS_API bool status_known(file_status s) noexcept; -GHC_FS_API file_status symlink_status(const path& p, std::error_code& ec) noexcept; -GHC_FS_API path temp_directory_path(std::error_code& ec) noexcept; -GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept; - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link); -GHC_FS_API uintmax_t hard_link_count(const path& p); -#endif -GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept; -GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; -#endif - -// Non-C++17 add-on std::fstream wrappers with path -template > -class basic_filebuf : public std::basic_filebuf -{ -public: - basic_filebuf() {} - ~basic_filebuf() override {} - basic_filebuf(const basic_filebuf&) = delete; - const basic_filebuf& operator=(const basic_filebuf&) = delete; - basic_filebuf* open(const path& p, std::ios_base::openmode mode) - { -#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__) - return std::basic_filebuf::open(p.wstring().c_str(), mode) ? this : 0; -#else - return std::basic_filebuf::open(p.string().c_str(), mode) ? this : 0; -#endif - } -}; - -template > -class basic_ifstream : public std::basic_ifstream -{ -public: - basic_ifstream() {} -#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__) - explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in) - : std::basic_ifstream(p.wstring().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream::open(p.wstring().c_str(), mode); } -#else - explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in) - : std::basic_ifstream(p.string().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream::open(p.string().c_str(), mode); } -#endif - basic_ifstream(const basic_ifstream&) = delete; - const basic_ifstream& operator=(const basic_ifstream&) = delete; - ~basic_ifstream() override {} -}; - -template > -class basic_ofstream : public std::basic_ofstream -{ -public: - basic_ofstream() {} -#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__) - explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out) - : std::basic_ofstream(p.wstring().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream::open(p.wstring().c_str(), mode); } -#else - explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out) - : std::basic_ofstream(p.string().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream::open(p.string().c_str(), mode); } -#endif - basic_ofstream(const basic_ofstream&) = delete; - const basic_ofstream& operator=(const basic_ofstream&) = delete; - ~basic_ofstream() override {} -}; - -template > -class basic_fstream : public std::basic_fstream -{ -public: - basic_fstream() {} -#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__) - explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : std::basic_fstream(p.wstring().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream::open(p.wstring().c_str(), mode); } -#else - explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) - : std::basic_fstream(p.string().c_str(), mode) - { - } - void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream::open(p.string().c_str(), mode); } -#endif - basic_fstream(const basic_fstream&) = delete; - const basic_fstream& operator=(const basic_fstream&) = delete; - ~basic_fstream() override {} -}; - -typedef basic_filebuf filebuf; -typedef basic_filebuf wfilebuf; -typedef basic_ifstream ifstream; -typedef basic_ifstream wifstream; -typedef basic_ofstream ofstream; -typedef basic_ofstream wofstream; -typedef basic_fstream fstream; -typedef basic_fstream wfstream; - -class GHC_FS_API_CLASS u8arguments -{ -public: - u8arguments(int& argc, char**& argv); - ~u8arguments() - { - _refargc = _argc; - _refargv = _argv; - } - - bool valid() const { return _isvalid; } - -private: - int _argc; - char** _argv; - int& _refargc; - char**& _refargv; - bool _isvalid; -#ifdef GHC_OS_WINDOWS - std::vector _args; - std::vector _argp; -#endif -}; - -//------------------------------------------------------------------------------------------------- -// Implementation -//------------------------------------------------------------------------------------------------- - -namespace detail { -enum utf8_states_t { S_STRT = 0, S_RJCT = 8 }; -GHC_FS_API void appendUTF8(std::string& str, uint32_t unicode); -GHC_FS_API bool is_surrogate(uint32_t c); -GHC_FS_API bool is_high_surrogate(uint32_t c); -GHC_FS_API bool is_low_surrogate(uint32_t c); -GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint); -enum class portable_error { - none = 0, - exists, - not_found, - not_supported, - not_implemented, - invalid_argument, - is_a_directory, -}; -GHC_FS_API std::error_code make_error_code(portable_error err); -#ifdef GHC_OS_WINDOWS -GHC_FS_API std::error_code make_system_error(uint32_t err = 0); -#else -GHC_FS_API std::error_code make_system_error(int err = 0); - -template -struct has_d_type : std::false_type{}; - -template -struct has_d_type : std::true_type {}; - -template -GHC_INLINE file_type file_type_from_dirent_impl(const T&, std::false_type) -{ - return file_type::none; -} - -template -GHC_INLINE file_type file_type_from_dirent_impl(const T& t, std::true_type) -{ - switch (t.d_type) { -#ifdef DT_BLK - case DT_BLK: - return file_type::block; -#endif -#ifdef DT_CHR - case DT_CHR: - return file_type::character; -#endif -#ifdef DT_DIR - case DT_DIR: - return file_type::directory; -#endif -#ifdef DT_FIFO - case DT_FIFO: - return file_type::fifo; -#endif -#ifdef DT_LNK - case DT_LNK: - return file_type::symlink; -#endif -#ifdef DT_REG - case DT_REG: - return file_type::regular; -#endif -#ifdef DT_SOCK - case DT_SOCK: - return file_type::socket; -#endif -#ifdef DT_UNKNOWN - case DT_UNKNOWN: - return file_type::none; -#endif - default: - return file_type::unknown; - } -} - -template -GHC_INLINE file_type file_type_from_dirent(const T& t) -{ - return file_type_from_dirent_impl(t, has_d_type{}); -} -#endif -} // namespace detail - -namespace detail { - -#ifdef GHC_EXPAND_IMPL - -GHC_INLINE std::error_code make_error_code(portable_error err) -{ -#ifdef GHC_OS_WINDOWS - switch (err) { - case portable_error::none: - return std::error_code(); - case portable_error::exists: - return std::error_code(ERROR_ALREADY_EXISTS, std::system_category()); - case portable_error::not_found: - return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category()); - case portable_error::not_supported: - return std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); - case portable_error::not_implemented: - return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category()); - case portable_error::invalid_argument: - return std::error_code(ERROR_INVALID_PARAMETER, std::system_category()); - case portable_error::is_a_directory: -#ifdef ERROR_DIRECTORY_NOT_SUPPORTED - return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category()); -#else - return std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); -#endif - } -#else - switch (err) { - case portable_error::none: - return std::error_code(); - case portable_error::exists: - return std::error_code(EEXIST, std::system_category()); - case portable_error::not_found: - return std::error_code(ENOENT, std::system_category()); - case portable_error::not_supported: - return std::error_code(ENOTSUP, std::system_category()); - case portable_error::not_implemented: - return std::error_code(ENOSYS, std::system_category()); - case portable_error::invalid_argument: - return std::error_code(EINVAL, std::system_category()); - case portable_error::is_a_directory: - return std::error_code(EISDIR, std::system_category()); - } -#endif - return std::error_code(); -} - -#ifdef GHC_OS_WINDOWS -GHC_INLINE std::error_code make_system_error(uint32_t err) -{ - return std::error_code(err ? static_cast(err) : static_cast(::GetLastError()), std::system_category()); -} -#else -GHC_INLINE std::error_code make_system_error(int err) -{ - return std::error_code(err ? err : errno, std::system_category()); -} -#endif - -#endif // GHC_EXPAND_IMPL - -template -using EnableBitmask = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, Enum>::type; -} // namespace detail - -template -constexpr detail::EnableBitmask operator&(Enum X, Enum Y) -{ - using underlying = typename std::underlying_type::type; - return static_cast(static_cast(X) & static_cast(Y)); -} - -template -constexpr detail::EnableBitmask operator|(Enum X, Enum Y) -{ - using underlying = typename std::underlying_type::type; - return static_cast(static_cast(X) | static_cast(Y)); -} - -template -constexpr detail::EnableBitmask operator^(Enum X, Enum Y) -{ - using underlying = typename std::underlying_type::type; - return static_cast(static_cast(X) ^ static_cast(Y)); -} - -template -constexpr detail::EnableBitmask operator~(Enum X) -{ - using underlying = typename std::underlying_type::type; - return static_cast(~static_cast(X)); -} - -template -detail::EnableBitmask& operator&=(Enum& X, Enum Y) -{ - X = X & Y; - return X; -} - -template -detail::EnableBitmask& operator|=(Enum& X, Enum Y) -{ - X = X | Y; - return X; -} - -template -detail::EnableBitmask& operator^=(Enum& X, Enum Y) -{ - X = X ^ Y; - return X; -} - -#ifdef GHC_EXPAND_IMPL - -namespace detail { - -GHC_INLINE bool in_range(uint32_t c, uint32_t lo, uint32_t hi) -{ - return (static_cast(c - lo) < (hi - lo + 1)); -} - -GHC_INLINE bool is_surrogate(uint32_t c) -{ - return in_range(c, 0xd800, 0xdfff); -} - -GHC_INLINE bool is_high_surrogate(uint32_t c) -{ - return (c & 0xfffffc00) == 0xd800; -} - -GHC_INLINE bool is_low_surrogate(uint32_t c) -{ - return (c & 0xfffffc00) == 0xdc00; -} - -GHC_INLINE void appendUTF8(std::string& str, uint32_t unicode) -{ - if (unicode <= 0x7f) { - str.push_back(static_cast(unicode)); - } - else if (unicode >= 0x80 && unicode <= 0x7ff) { - str.push_back(static_cast((unicode >> 6) + 192)); - str.push_back(static_cast((unicode & 0x3f) + 128)); - } - else if ((unicode >= 0x800 && unicode <= 0xd7ff) || (unicode >= 0xe000 && unicode <= 0xffff)) { - str.push_back(static_cast((unicode >> 12) + 224)); - str.push_back(static_cast(((unicode & 0xfff) >> 6) + 128)); - str.push_back(static_cast((unicode & 0x3f) + 128)); - } - else if (unicode >= 0x10000 && unicode <= 0x10ffff) { - str.push_back(static_cast((unicode >> 18) + 240)); - str.push_back(static_cast(((unicode & 0x3ffff) >> 12) + 128)); - str.push_back(static_cast(((unicode & 0xfff) >> 6) + 128)); - str.push_back(static_cast((unicode & 0x3f) + 128)); - } - else { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal code point for unicode character.", str, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - appendUTF8(str, 0xfffd); -#endif - } -} - -// Thanks to Bjoern Hoehrmann (https://bjoern.hoehrmann.de/utf-8/decoder/dfa/) -// and Taylor R Campbell for the ideas to this DFA approach of UTF-8 decoding; -// Generating debugging and shrinking my own DFA from scratch was a day of fun! -GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint) -{ - static const uint32_t utf8_state_info[] = { - // encoded states - 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u, 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u, 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu, 0x99999999u, - 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u, - }; - uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf; - codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment); - return state == S_RJCT ? static_cast(S_RJCT) : static_cast((utf8_state_info[category + 16] >> (state << 2)) & 0xf); -} - -GHC_INLINE bool validUtf8(const std::string& utf8String) -{ - std::string::const_iterator iter = utf8String.begin(); - unsigned utf8_state = S_STRT; - std::uint32_t codepoint = 0; - while (iter < utf8String.end()) { - if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_RJCT) { - return false; - } - } - if (utf8_state) { - return false; - } - return true; -} - -} // namespace detail - -#endif - -namespace detail { - -template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 1)>::type* = nullptr> -inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - return StringType(utf8String.begin(), utf8String.end(), alloc); -} - -template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 2)>::type* = nullptr> -inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - StringType result(alloc); - result.reserve(utf8String.length()); - auto iter = utf8String.cbegin(); - unsigned utf8_state = S_STRT; - std::uint32_t codepoint = 0; - while (iter < utf8String.cend()) { - if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_STRT) { - if (codepoint <= 0xffff) { - result += static_cast(codepoint); - } - else { - codepoint -= 0x10000; - result += static_cast((codepoint >> 10) + 0xd800); - result += static_cast((codepoint & 0x3ff) + 0xdc00); - } - codepoint = 0; - } - else if (utf8_state == S_RJCT) { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - result += static_cast(0xfffd); - utf8_state = S_STRT; - codepoint = 0; -#endif - } - } - if (utf8_state) { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - result += static_cast(0xfffd); -#endif - } - return result; -} - -template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 4)>::type* = nullptr> -inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - StringType result(alloc); - result.reserve(utf8String.length()); - auto iter = utf8String.cbegin(); - unsigned utf8_state = S_STRT; - std::uint32_t codepoint = 0; - while (iter < utf8String.cend()) { - if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_STRT) { - result += static_cast(codepoint); - codepoint = 0; - } - else if (utf8_state == S_RJCT) { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - result += static_cast(0xfffd); - utf8_state = S_STRT; - codepoint = 0; -#endif - } - } - if (utf8_state) { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - result += static_cast(0xfffd); -#endif - } - return result; -} - -template -inline StringType fromUtf8(const charT (&utf8String)[N]) -{ -#ifdef GHC_WITH_STRING_VIEW - return fromUtf8(basic_string_view(utf8String, N - 1)); -#else - return fromUtf8(std::basic_string(utf8String, N - 1)); -#endif -} - -template ::value && (sizeof(typename strT::value_type) == 1), int>::type size = 1> -inline std::string toUtf8(const strT& unicodeString) -{ - return std::string(unicodeString.begin(), unicodeString.end()); -} - -template ::value && (sizeof(typename strT::value_type) == 2), int>::type size = 2> -inline std::string toUtf8(const strT& unicodeString) -{ - std::string result; - for (auto iter = unicodeString.begin(); iter != unicodeString.end(); ++iter) { - char32_t c = *iter; - if (is_surrogate(c)) { - ++iter; - if (iter != unicodeString.end() && is_high_surrogate(c) && is_low_surrogate(*iter)) { - appendUTF8(result, (char32_t(c) << 10) + *iter - 0x35fdc00); - } - else { -#ifdef GHC_RAISE_UNICODE_ERRORS - throw filesystem_error("Illegal code point for unicode character.", result, std::make_error_code(std::errc::illegal_byte_sequence)); -#else - appendUTF8(result, 0xfffd); - if (iter == unicodeString.end()) { - break; - } -#endif - } - } - else { - appendUTF8(result, c); - } - } - return result; -} - -template ::value && (sizeof(typename strT::value_type) == 4), int>::type size = 4> -inline std::string toUtf8(const strT& unicodeString) -{ - std::string result; - for (auto c : unicodeString) { - appendUTF8(result, static_cast(c)); - } - return result; -} - -template -inline std::string toUtf8(const charT* unicodeString) -{ -#ifdef GHC_WITH_STRING_VIEW - return toUtf8(basic_string_view>(unicodeString)); -#else - return toUtf8(std::basic_string>(unicodeString)); -#endif -} - -#ifdef GHC_USE_WCHAR_T -template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 1), bool>::type = false> -inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - auto temp = toUtf8(wString); - return StringType(temp.begin(), temp.end(), alloc); -} - -template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 2), bool>::type = false> -inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - return StringType(wString.begin(), wString.end(), alloc); -} - -template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 4), bool>::type = false> -inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) -{ - auto temp = toUtf8(wString); - return fromUtf8(temp, alloc); -} - -template ::value && (sizeof(typename strT::value_type) == 1), bool>::type = false> -inline std::wstring toWChar(const strT& unicodeString) -{ - return fromUtf8(unicodeString); -} - -template ::value && (sizeof(typename strT::value_type) == 2), bool>::type = false> -inline std::wstring toWChar(const strT& unicodeString) -{ - return std::wstring(unicodeString.begin(), unicodeString.end()); -} - -template ::value && (sizeof(typename strT::value_type) == 4), bool>::type = false> -inline std::wstring toWChar(const strT& unicodeString) -{ - auto temp = toUtf8(unicodeString); - return fromUtf8(temp); -} - -template -inline std::wstring toWChar(const charT* unicodeString) -{ -#ifdef GHC_WITH_STRING_VIEW - return toWChar(basic_string_view>(unicodeString)); -#else - return toWChar(std::basic_string>(unicodeString)); -#endif -} -#endif // GHC_USE_WCHAR_T - -} // namespace detail - -#ifdef GHC_EXPAND_IMPL - -namespace detail { - -template ::value, bool>::type = true> -GHC_INLINE bool startsWith(const strT& what, const strT& with) -{ - return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin()); -} - -template ::value, bool>::type = true> -GHC_INLINE bool endsWith(const strT& what, const strT& with) -{ - return with.length() <= what.length() && what.compare(what.length() - with.length(), with.size(), with) == 0; -} - -} // namespace detail - -GHC_INLINE void path::check_long_path() -{ -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) { - postprocess_path_with_format(native_format); - } -#endif -} - -GHC_INLINE void path::postprocess_path_with_format(path::format fmt) -{ -#ifdef GHC_RAISE_UNICODE_ERRORS - if (!detail::validUtf8(_path)) { - path t; - t._path = _path; - throw filesystem_error("Illegal byte sequence for unicode character.", t, std::make_error_code(std::errc::illegal_byte_sequence)); - } -#endif - switch (fmt) { -#ifdef GHC_OS_WINDOWS - case path::native_format: - case path::auto_format: - case path::generic_format: - for (auto& c : _path) { - if (c == generic_separator) { - c = preferred_separator; - } - } -#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH - if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) { - _path = GHC_PLATFORM_LITERAL("\\\\?\\") + _path; - } -#endif - handle_prefixes(); - break; -#else - case path::auto_format: - case path::native_format: - case path::generic_format: - // nothing to do - break; -#endif - } - if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator) { - impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast(_prefixLength) + 2, _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; }); - _path.erase(new_end, _path.end()); - } - else { - impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast(_prefixLength), _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; }); - _path.erase(new_end, _path.end()); - } -} - -#endif // GHC_EXPAND_IMPL - -template -inline path::path(const Source& source, format fmt) -#ifdef GHC_USE_WCHAR_T - : _path(detail::toWChar(source)) -#else - : _path(detail::toUtf8(source)) -#endif -{ - postprocess_path_with_format(fmt); -} - -template -inline path u8path(const Source& source) -{ - return path(source); -} -template -inline path u8path(InputIterator first, InputIterator last) -{ - return path(first, last); -} - -template -inline path::path(InputIterator first, InputIterator last, format fmt) - : path(std::basic_string::value_type>(first, last), fmt) -{ - // delegated -} - -#ifdef GHC_EXPAND_IMPL - -namespace detail { - -GHC_INLINE bool equals_simple_insensitive(const path::value_type* str1, const path::value_type* str2) -{ -#ifdef GHC_OS_WINDOWS -#ifdef __GNUC__ - while (::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2++)) { - if (*str1++ == 0) - return true; - } - return false; -#else // __GNUC__ -#ifdef GHC_USE_WCHAR_T - return 0 == ::_wcsicmp(str1, str2); -#else // GHC_USE_WCHAR_T - return 0 == ::_stricmp(str1, str2); -#endif // GHC_USE_WCHAR_T -#endif // __GNUC__ -#else // GHC_OS_WINDOWS - return 0 == ::strcasecmp(str1, str2); -#endif // GHC_OS_WINDOWS -} - -GHC_INLINE int compare_simple_insensitive(const path::value_type* str1, size_t len1, const path::value_type* str2, size_t len2) -{ - while (len1 > 0 && len2 > 0 && ::tolower(static_cast(*str1)) == ::tolower(static_cast(*str2))) { - --len1; - --len2; - ++str1; - ++str2; - } - if (len1 && len2) { - return *str1 < *str2 ? -1 : 1; - } - if (len1 == 0 && len2 == 0) { - return 0; - } - return len1 == 0 ? -1 : 1; -} - -GHC_INLINE const char* strerror_adapter(char* gnu, char*) -{ - return gnu; -} - -GHC_INLINE const char* strerror_adapter(int posix, char* buffer) -{ - if (posix) { - return "Error in strerror_r!"; - } - return buffer; -} - -template -GHC_INLINE std::string systemErrorText(ErrorNumber code = 0) -{ -#if defined(GHC_OS_WINDOWS) - LPVOID msgBuf; - DWORD dw = code ? static_cast(code) : ::GetLastError(); - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL); - std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf)); - LocalFree(msgBuf); - return msg; -#else - char buffer[512]; - return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer); -#endif -} - -#ifdef GHC_OS_WINDOWS -using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, DWORD); -using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); - -GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool to_directory, std::error_code& ec) -{ - std::error_code tec; - auto fs = status(target_name, tec); - if ((fs.type() == file_type::directory && !to_directory) || (fs.type() == file_type::regular && to_directory)) { - ec = detail::make_error_code(detail::portable_error::not_supported); - return; - } -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-function-type" -#endif - static CreateSymbolicLinkW_fp api_call = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW")); -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif - if (api_call) { - if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) { - auto result = ::GetLastError(); - if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 3 : 2) != 0) { - return; - } - ec = detail::make_system_error(result); - } - } - else { - ec = detail::make_system_error(ERROR_NOT_SUPPORTED); - } -} - -GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec) -{ -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-function-type" -#endif - static CreateHardLinkW_fp api_call = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW")); -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif - if (api_call) { - if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) { - ec = detail::make_system_error(); - } - } - else { - ec = detail::make_system_error(ERROR_NOT_SUPPORTED); - } -} - -GHC_INLINE path getFullPathName(const wchar_t* p, std::error_code& ec) -{ - ULONG size = ::GetFullPathNameW(p, 0, 0, 0); - if (size) { - std::vector buf(size, 0); - ULONG s2 = GetFullPathNameW(p, size, buf.data(), nullptr); - if (s2 && s2 < size) { - return path(std::wstring(buf.data(), s2)); - } - } - ec = detail::make_system_error(); - return path(); -} - -#else -GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec) -{ - if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) { - ec = detail::make_system_error(); - } -} - -#ifndef GHC_OS_WEB -GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec) -{ - if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) { - ec = detail::make_system_error(); - } -} -#endif -#endif - -template -GHC_INLINE file_status file_status_from_st_mode(T mode) -{ -#ifdef GHC_OS_WINDOWS - file_type ft = file_type::unknown; - if ((mode & _S_IFDIR) == _S_IFDIR) { - ft = file_type::directory; - } - else if ((mode & _S_IFREG) == _S_IFREG) { - ft = file_type::regular; - } - else if ((mode & _S_IFCHR) == _S_IFCHR) { - ft = file_type::character; - } - perms prms = static_cast(mode & 0xfff); - return file_status(ft, prms); -#else - file_type ft = file_type::unknown; - if (S_ISDIR(mode)) { - ft = file_type::directory; - } - else if (S_ISREG(mode)) { - ft = file_type::regular; - } - else if (S_ISCHR(mode)) { - ft = file_type::character; - } - else if (S_ISBLK(mode)) { - ft = file_type::block; - } - else if (S_ISFIFO(mode)) { - ft = file_type::fifo; - } - else if (S_ISLNK(mode)) { - ft = file_type::symlink; - } - else if (S_ISSOCK(mode)) { - ft = file_type::socket; - } - perms prms = static_cast(mode & 0xfff); - return file_status(ft, prms); -#endif -} - -#ifdef GHC_OS_WINDOWS - -class unique_handle -{ -public: - typedef HANDLE element_type; - - unique_handle() noexcept - : _handle(INVALID_HANDLE_VALUE) - { - } - explicit unique_handle(element_type h) noexcept - : _handle(h) - { - } - unique_handle(unique_handle&& u) noexcept - : _handle(u.release()) - { - } - ~unique_handle() { reset(); } - unique_handle& operator=(unique_handle&& u) noexcept - { - reset(u.release()); - return *this; - } - element_type get() const noexcept { return _handle; } - explicit operator bool() const noexcept { return _handle != INVALID_HANDLE_VALUE; } - element_type release() noexcept - { - element_type tmp = _handle; - _handle = INVALID_HANDLE_VALUE; - return tmp; - } - void reset(element_type h = INVALID_HANDLE_VALUE) noexcept - { - element_type tmp = _handle; - _handle = h; - if (tmp != INVALID_HANDLE_VALUE) { - CloseHandle(tmp); - } - } - void swap(unique_handle& u) noexcept { std::swap(_handle, u._handle); } - -private: - element_type _handle; -}; - -#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE -typedef struct _REPARSE_DATA_BUFFER -{ - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union - { - struct - { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct - { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct - { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - } DUMMYUNIONNAME; -} REPARSE_DATA_BUFFER; -#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE -#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) -#endif -#endif - -template -struct free_deleter -{ - void operator()(T* p) const { std::free(p); } -}; - -GHC_INLINE std::unique_ptr> getReparseData(const path& p, std::error_code& ec) -{ - unique_handle file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0)); - if (!file) { - ec = detail::make_system_error(); - return nullptr; - } - - std::unique_ptr> reparseData(reinterpret_cast(std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE))); - ULONG bufferUsed; - if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) { - return reparseData; - } - else { - ec = detail::make_system_error(); - } - return nullptr; -} -#endif - -GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec) -{ -#ifdef GHC_OS_WINDOWS - path result; - auto reparseData = detail::getReparseData(p, ec); - if (!ec) { - if (reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag)) { - switch (reparseData->ReparseTag) { - case IO_REPARSE_TAG_SYMLINK: { - auto printName = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR)); - auto substituteName = - std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); - if (detail::endsWith(substituteName, printName) && detail::startsWith(substituteName, std::wstring(L"\\??\\"))) { - result = printName; - } - else { - result = substituteName; - } - if (reparseData->SymbolicLinkReparseBuffer.Flags & 0x1 /*SYMLINK_FLAG_RELATIVE*/) { - result = p.parent_path() / result; - } - break; - } - case IO_REPARSE_TAG_MOUNT_POINT: - result = detail::getFullPathName(GHC_NATIVEWP(p), ec); - // result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); - break; - default: - break; - } - } - } - return result; -#else - size_t bufferSize = 256; - while (true) { - std::vector buffer(bufferSize, static_cast(0)); - auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size()); - if (rc < 0) { - ec = detail::make_system_error(); - return path(); - } - else if (rc < static_cast(bufferSize)) { - return path(std::string(buffer.data(), static_cast(rc))); - } - bufferSize *= 2; - } - return path(); -#endif -} - -#ifdef GHC_OS_WINDOWS -GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft) -{ - ULARGE_INTEGER ull; - ull.LowPart = ft.dwLowDateTime; - ull.HighPart = ft.dwHighDateTime; - return static_cast(ull.QuadPart / 10000000ULL - 11644473600ULL); -} - -GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft) -{ - LONGLONG ll; - ll = Int32x32To64(t, 10000000) + 116444736000000000; - ft.dwLowDateTime = static_cast(ll); - ft.dwHighDateTime = static_cast(ll >> 32); -} - -template -GHC_INLINE uintmax_t hard_links_from_INFO(const INFO* info) -{ - return static_cast(-1); -} - -template <> -GHC_INLINE uintmax_t hard_links_from_INFO(const BY_HANDLE_FILE_INFORMATION* info) -{ - return info->nNumberOfLinks; -} - -template -GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*) -{ - return 0; -} - -template <> -GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info) -{ - return info->dwReserved0; -} - -template -GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr) -{ - file_type ft = file_type::unknown; - if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) { - if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) { - ft = file_type::symlink; - } - } - else { - if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - auto reparseData = detail::getReparseData(p, ec); - if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - ft = file_type::symlink; - } - } - } - if (ft == file_type::unknown) { - if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - ft = file_type::directory; - } - else { - ft = file_type::regular; - } - } - perms prms = perms::owner_read | perms::group_read | perms::others_read; - if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { - prms = prms | perms::owner_write | perms::group_write | perms::others_write; - } - if (has_executable_extension(p)) { - prms = prms | perms::owner_exec | perms::group_exec | perms::others_exec; - } - if (sz) { - *sz = static_cast(info->nFileSizeHigh) << (sizeof(info->nFileSizeHigh) * 8) | info->nFileSizeLow; - } - if (lwt) { - *lwt = detail::timeFromFILETIME(info->ftLastWriteTime); - } - return file_status(ft, prms); -} - -#endif - -GHC_INLINE bool is_not_found_error(std::error_code& ec) -{ -#ifdef GHC_OS_WINDOWS - return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME; -#else - return ec.value() == ENOENT || ec.value() == ENOTDIR; -#endif -} - -GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr) noexcept -{ -#ifdef GHC_OS_WINDOWS - file_status fs; - WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { - ec = detail::make_system_error(); - } - else { - ec.clear(); - fs = detail::status_from_INFO(p, &attr, ec, sz, lwt); - if (nhl) { - *nhl = 0; - } - } - if (detail::is_not_found_error(ec)) { - return file_status(file_type::not_found); - } - return ec ? file_status(file_type::none) : fs; -#else - (void)sz; - (void)nhl; - (void)lwt; - struct ::stat fs; - auto result = ::lstat(p.c_str(), &fs); - if (result == 0) { - ec.clear(); - file_status f_s = detail::file_status_from_st_mode(fs.st_mode); - return f_s; - } - ec = detail::make_system_error(); - if (detail::is_not_found_error(ec)) { - return file_status(file_type::not_found, perms::unknown); - } - return file_status(file_type::none); -#endif -} - -GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status* sls = nullptr, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr, int recurse_count = 0) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - if (recurse_count > 16) { - ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/); - return file_status(file_type::unknown); - } - WIN32_FILE_ATTRIBUTE_DATA attr; - if (!::GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { - ec = detail::make_system_error(); - } - else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - auto reparseData = detail::getReparseData(p, ec); - if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - path target = resolveSymlink(p, ec); - file_status result; - if (!ec && !target.empty()) { - if (sls) { - *sls = status_from_INFO(p, &attr, ec); - } - return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1); - } - return file_status(file_type::unknown); - } - } - if (ec) { - if (detail::is_not_found_error(ec)) { - return file_status(file_type::not_found); - } - return file_status(file_type::none); - } - if (nhl) { - *nhl = 0; - } - return detail::status_from_INFO(p, &attr, ec, sz, lwt); -#else - (void)recurse_count; - struct ::stat st; - auto result = ::lstat(p.c_str(), &st); - if (result == 0) { - ec.clear(); - file_status fs = detail::file_status_from_st_mode(st.st_mode); - if (sls) { - *sls = fs; - } - if (fs.type() == file_type::symlink) { - result = ::stat(p.c_str(), &st); - if (result == 0) { - fs = detail::file_status_from_st_mode(st.st_mode); - } - else { - ec = detail::make_system_error(); - if (detail::is_not_found_error(ec)) { - return file_status(file_type::not_found, perms::unknown); - } - return file_status(file_type::none); - } - } - if (sz) { - *sz = static_cast(st.st_size); - } - if (nhl) { - *nhl = st.st_nlink; - } - if (lwt) { - *lwt = st.st_mtime; - } - return fs; - } - else { - ec = detail::make_system_error(); - if (detail::is_not_found_error(ec)) { - return file_status(file_type::not_found, perms::unknown); - } - return file_status(file_type::none); - } -#endif -} - -} // namespace detail - -GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv) - : _argc(argc) - , _argv(argv) - , _refargc(argc) - , _refargv(argv) - , _isvalid(false) -{ -#ifdef GHC_OS_WINDOWS - LPWSTR* p; - p = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - _args.reserve(static_cast(argc)); - _argp.reserve(static_cast(argc)); - for (size_t i = 0; i < static_cast(argc); ++i) { - _args.push_back(detail::toUtf8(std::wstring(p[i]))); - _argp.push_back((char*)_args[i].data()); - } - argv = _argp.data(); - ::LocalFree(p); - _isvalid = true; -#else - std::setlocale(LC_ALL, ""); -#if defined(__ANDROID__) && __ANDROID_API__ < 26 - _isvalid = true; -#else - if (detail::equals_simple_insensitive(::nl_langinfo(CODESET), "UTF-8")) { - _isvalid = true; - } -#endif -#endif -} - -//----------------------------------------------------------------------------- -// [fs.path.construct] constructors and destructor - -GHC_INLINE path::path() noexcept {} - -GHC_INLINE path::path(const path& p) - : _path(p._path) -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - , _prefixLength(p._prefixLength) -#endif -{ -} - -GHC_INLINE path::path(path&& p) noexcept - : _path(std::move(p._path)) -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - , _prefixLength(p._prefixLength) -#endif -{ -} - -GHC_INLINE path::path(string_type&& source, format fmt) - : _path(std::move(source)) -{ - postprocess_path_with_format(fmt); -} - -#endif // GHC_EXPAND_IMPL - -#ifdef GHC_WITH_EXCEPTIONS -template -inline path::path(const Source& source, const std::locale& loc, format fmt) - : path(source, fmt) -{ - std::string locName = loc.name(); - if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) { - throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported)); - } -} - -template -inline path::path(InputIterator first, InputIterator last, const std::locale& loc, format fmt) - : path(std::basic_string::value_type>(first, last), fmt) -{ - std::string locName = loc.name(); - if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) { - throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported)); - } -} -#endif - -#ifdef GHC_EXPAND_IMPL - -GHC_INLINE path::~path() {} - -//----------------------------------------------------------------------------- -// [fs.path.assign] assignments - -GHC_INLINE path& path::operator=(const path& p) -{ - _path = p._path; -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - _prefixLength = p._prefixLength; -#endif - return *this; -} - -GHC_INLINE path& path::operator=(path&& p) noexcept -{ - _path = std::move(p._path); -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - _prefixLength = p._prefixLength; -#endif - return *this; -} - -GHC_INLINE path& path::operator=(path::string_type&& source) -{ - return assign(source); -} - -GHC_INLINE path& path::assign(path::string_type&& source) -{ - _path = std::move(source); - postprocess_path_with_format(native_format); - return *this; -} - -#endif // GHC_EXPAND_IMPL - -template -inline path& path::operator=(const Source& source) -{ - return assign(source); -} - -template -inline path& path::assign(const Source& source) -{ -#ifdef GHC_USE_WCHAR_T - _path.assign(detail::toWChar(source)); -#else - _path.assign(detail::toUtf8(source)); -#endif - postprocess_path_with_format(native_format); - return *this; -} - -template <> -inline path& path::assign(const path& source) -{ - _path = source._path; -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - _prefixLength = source._prefixLength; -#endif - return *this; -} - -template -inline path& path::assign(InputIterator first, InputIterator last) -{ - _path.assign(first, last); - postprocess_path_with_format(native_format); - return *this; -} - -#ifdef GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.path.append] appends - -GHC_INLINE path& path::operator/=(const path& p) -{ - if (p.empty()) { - // was: if ((!has_root_directory() && is_absolute()) || has_filename()) - if (!_path.empty() && _path[_path.length() - 1] != preferred_separator && _path[_path.length() - 1] != ':') { - _path += preferred_separator; - } - return *this; - } - if ((p.is_absolute() && (_path != root_name()._path || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) { - assign(p); - return *this; - } - if (p.has_root_directory()) { - assign(root_name()); - } - else if ((!has_root_directory() && is_absolute()) || has_filename()) { - _path += preferred_separator; - } - auto iter = p.begin(); - bool first = true; - if (p.has_root_name()) { - ++iter; - } - while (iter != p.end()) { - if (!first && !(!_path.empty() && _path[_path.length() - 1] == preferred_separator)) { - _path += preferred_separator; - } - first = false; - _path += (*iter++).native(); - } - check_long_path(); - return *this; -} - -GHC_INLINE void path::append_name(const value_type* name) -{ - if (_path.empty()) { - this->operator/=(path(name)); - } - else { - if (_path.back() != path::preferred_separator) { - _path.push_back(path::preferred_separator); - } - _path += name; - check_long_path(); - } -} - -#endif // GHC_EXPAND_IMPL - -template -inline path& path::operator/=(const Source& source) -{ - return append(source); -} - -template -inline path& path::append(const Source& source) -{ - return this->operator/=(path(source)); -} - -template <> -inline path& path::append(const path& p) -{ - return this->operator/=(p); -} - -template -inline path& path::append(InputIterator first, InputIterator last) -{ - std::basic_string::value_type> part(first, last); - return append(part); -} - -#ifdef GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.path.concat] concatenation - -GHC_INLINE path& path::operator+=(const path& x) -{ - return concat(x._path); -} - -GHC_INLINE path& path::operator+=(const string_type& x) -{ - return concat(x); -} - -#ifdef GHC_WITH_STRING_VIEW -GHC_INLINE path& path::operator+=(basic_string_view x) -{ - return concat(x); -} -#endif - -GHC_INLINE path& path::operator+=(const value_type* x) -{ -#ifdef GHC_WITH_STRING_VIEW - basic_string_view part(x); -#else - string_type part(x); -#endif - return concat(part); -} - -GHC_INLINE path& path::operator+=(value_type x) -{ -#ifdef GHC_OS_WINDOWS - if (x == generic_separator) { - x = preferred_separator; - } -#endif - if (_path.empty() || _path.back() != preferred_separator) { - _path += x; - } - check_long_path(); - return *this; -} - -#endif // GHC_EXPAND_IMPL - -template -inline path::path_from_string& path::operator+=(const Source& x) -{ - return concat(x); -} - -template -inline path::path_type_EcharT& path::operator+=(EcharT x) -{ -#ifdef GHC_WITH_STRING_VIEW - basic_string_view part(&x, 1); -#else - std::basic_string part(1, x); -#endif - concat(part); - return *this; -} - -template -inline path& path::concat(const Source& x) -{ - path p(x); - _path += p._path; - postprocess_path_with_format(native_format); - return *this; -} -template -inline path& path::concat(InputIterator first, InputIterator last) -{ - _path.append(first, last); - postprocess_path_with_format(native_format); - return *this; -} - -#ifdef GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.path.modifiers] modifiers -GHC_INLINE void path::clear() noexcept -{ - _path.clear(); -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - _prefixLength = 0; -#endif -} - -GHC_INLINE path& path::make_preferred() -{ - // as this filesystem implementation only uses generic_format - // internally, this must be a no-op - return *this; -} - -GHC_INLINE path& path::remove_filename() -{ - if (has_filename()) { - _path.erase(_path.size() - filename()._path.size()); - } - return *this; -} - -GHC_INLINE path& path::replace_filename(const path& replacement) -{ - remove_filename(); - return append(replacement); -} - -GHC_INLINE path& path::replace_extension(const path& replacement) -{ - if (has_extension()) { - _path.erase(_path.size() - extension()._path.size()); - } - if (!replacement.empty() && replacement._path[0] != '.') { - _path += '.'; - } - return concat(replacement); -} - -GHC_INLINE void path::swap(path& rhs) noexcept -{ - _path.swap(rhs._path); -#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - std::swap(_prefixLength, rhs._prefixLength); -#endif -} - -//----------------------------------------------------------------------------- -// [fs.path.native.obs] native format observers -GHC_INLINE const path::string_type& path::native() const noexcept -{ - return _path; -} - -GHC_INLINE const path::value_type* path::c_str() const noexcept -{ - return native().c_str(); -} - -GHC_INLINE path::operator path::string_type() const -{ - return native(); -} - -#endif // GHC_EXPAND_IMPL - -template -inline std::basic_string path::string(const Allocator& a) const -{ -#ifdef GHC_USE_WCHAR_T - return detail::fromWChar>(_path, a); -#else - return detail::fromUtf8>(_path, a); -#endif -} - -#ifdef GHC_EXPAND_IMPL - -GHC_INLINE std::string path::string() const -{ -#ifdef GHC_USE_WCHAR_T - return detail::toUtf8(native()); -#else - return native(); -#endif -} - -GHC_INLINE std::wstring path::wstring() const -{ -#ifdef GHC_USE_WCHAR_T - return native(); -#else - return detail::fromUtf8(native()); -#endif -} - -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) -GHC_INLINE std::u8string path::u8string() const -{ -#ifdef GHC_USE_WCHAR_T - return std::u8string(reinterpret_cast(detail::toUtf8(native()).c_str())); -#else - return std::u8string(reinterpret_cast(c_str())); -#endif -} -#else -GHC_INLINE std::string path::u8string() const -{ -#ifdef GHC_USE_WCHAR_T - return detail::toUtf8(native()); -#else - return native(); -#endif -} -#endif - -GHC_INLINE std::u16string path::u16string() const -{ - // TODO: optimize - return detail::fromUtf8(string()); -} - -GHC_INLINE std::u32string path::u32string() const -{ - // TODO: optimize - return detail::fromUtf8(string()); -} - -#endif // GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.path.generic.obs] generic format observers -template -inline std::basic_string path::generic_string(const Allocator& a) const -{ -#ifdef GHC_OS_WINDOWS -#ifdef GHC_USE_WCHAR_T - auto result = detail::fromWChar, path::string_type>(_path, a); -#else - auto result = detail::fromUtf8>(_path, a); -#endif - for (auto& c : result) { - if (c == preferred_separator) { - c = generic_separator; - } - } - return result; -#else - return detail::fromUtf8>(_path, a); -#endif -} - -#ifdef GHC_EXPAND_IMPL - -GHC_INLINE std::string path::generic_string() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return _path; -#endif -} - -GHC_INLINE std::wstring path::generic_wstring() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return detail::fromUtf8(_path); -#endif -} // namespace filesystem - -#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) -GHC_INLINE std::u8string path::generic_u8string() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return std::u8string(reinterpret_cast(_path.c_str())); -#endif -} -#else -GHC_INLINE std::string path::generic_u8string() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return _path; -#endif -} -#endif - -GHC_INLINE std::u16string path::generic_u16string() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return detail::fromUtf8(_path); -#endif -} - -GHC_INLINE std::u32string path::generic_u32string() const -{ -#ifdef GHC_OS_WINDOWS - return generic_string(); -#else - return detail::fromUtf8(_path); -#endif -} - -//----------------------------------------------------------------------------- -// [fs.path.compare] compare -GHC_INLINE int path::compare(const path& p) const noexcept -{ -#ifdef LWG_2936_BEHAVIOUR - auto rnl1 = root_name_length(); - auto rnl2 = p.root_name_length(); -#ifdef GHC_OS_WINDOWS - auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); -#else - auto rnc = _path.compare(0, rnl1, p._path, 0, (std::min(rnl1, rnl2))); -#endif - if (rnc) { - return rnc; - } - bool hrd1 = has_root_directory(), hrd2 = p.has_root_directory(); - if (hrd1 != hrd2) { - return hrd1 ? 1 : -1; - } - if (hrd1) { - ++rnl1; - ++rnl2; - } - auto iter1 = _path.begin() + static_cast(rnl1); - auto iter2 = p._path.begin() + static_cast(rnl2); - while (iter1 != _path.end() && iter2 != p._path.end() && *iter1 == *iter2) { - ++iter1; - ++iter2; - } - if (iter1 == _path.end()) { - return iter2 == p._path.end() ? 0 : -1; - } - if (iter2 == p._path.end()) { - return 1; - } - if (*iter1 == preferred_separator) { - return -1; - } - if (*iter2 == preferred_separator) { - return 1; - } - return *iter1 < *iter2 ? -1 : 1; -#else // LWG_2936_BEHAVIOUR -#ifdef GHC_OS_WINDOWS - auto rnl1 = root_name_length(); - auto rnl2 = p.root_name_length(); - auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); - if (rnc) { - return rnc; - } - return _path.compare(rnl1, std::string::npos, p._path, rnl2, std::string::npos); -#else - return _path.compare(p._path); -#endif -#endif -} - -GHC_INLINE int path::compare(const string_type& s) const -{ - return compare(path(s)); -} - -#ifdef GHC_WITH_STRING_VIEW -GHC_INLINE int path::compare(basic_string_view s) const -{ - return compare(path(s)); -} -#endif - -GHC_INLINE int path::compare(const value_type* s) const -{ - return compare(path(s)); -} - -//----------------------------------------------------------------------------- -// [fs.path.decompose] decomposition -#ifdef GHC_OS_WINDOWS -GHC_INLINE void path::handle_prefixes() -{ -#if defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) - _prefixLength = 0; - if (_path.length() >= 6 && _path[2] == '?' && std::toupper(static_cast(_path[4])) >= 'A' && std::toupper(static_cast(_path[4])) <= 'Z' && _path[5] == ':') { - if (detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\"))) || detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\??\\")))) { - _prefixLength = 4; - } - } -#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH -} -#endif - -GHC_INLINE path::string_type::size_type path::root_name_length() const noexcept -{ -#ifdef GHC_OS_WINDOWS - if (_path.length() >= _prefixLength + 2 && std::toupper(static_cast(_path[_prefixLength])) >= 'A' && std::toupper(static_cast(_path[_prefixLength])) <= 'Z' && _path[_prefixLength + 1] == ':') { - return 2; - } -#endif - if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator && std::isprint(_path[_prefixLength + 2])) { - impl_string_type::size_type pos = _path.find(preferred_separator, _prefixLength + 3); - if (pos == impl_string_type::npos) { - return _path.length(); - } - else { - return pos; - } - } - return 0; -} - -GHC_INLINE path path::root_name() const -{ - return path(_path.substr(_prefixLength, root_name_length()), native_format); -} - -GHC_INLINE path path::root_directory() const -{ - if (has_root_directory()) { - static const path _root_dir(std::string(1, preferred_separator), native_format); - return _root_dir; - } - return path(); -} - -GHC_INLINE path path::root_path() const -{ - return path(root_name().string() + root_directory().string(), native_format); -} - -GHC_INLINE path path::relative_path() const -{ - auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); - return path(_path.substr((std::min)(rootPathLen, _path.length())), generic_format); -} - -GHC_INLINE path path::parent_path() const -{ - auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); - if (rootPathLen < _path.length()) { - if (empty()) { - return path(); - } - else { - auto piter = end(); - auto iter = piter.decrement(_path.end()); - if (iter > _path.begin() + static_cast(rootPathLen) && *iter != preferred_separator) { - --iter; - } - return path(_path.begin(), iter, native_format); - } - } - else { - return *this; - } -} - -GHC_INLINE path path::filename() const -{ - return !has_relative_path() ? path() : path(*--end()); -} - -GHC_INLINE path path::stem() const -{ - impl_string_type fn = filename().native(); - if (fn != "." && fn != "..") { - impl_string_type::size_type pos = fn.rfind('.'); - if (pos != impl_string_type::npos && pos > 0) { - return path{fn.substr(0, pos), native_format}; - } - } - return path{fn, native_format}; -} - -GHC_INLINE path path::extension() const -{ - if (has_relative_path()) { - auto iter = end(); - const auto& fn = *--iter; - impl_string_type::size_type pos = fn._path.rfind('.'); - if (pos != std::string::npos && pos > 0) { - return path(fn._path.substr(pos), native_format); - } - } - return path(); -} - -#ifdef GHC_OS_WINDOWS -namespace detail { -GHC_INLINE bool has_executable_extension(const path& p) -{ - if (p.has_relative_path()) { - auto iter = p.end(); - const auto& fn = *--iter; - auto pos = fn._path.find_last_of('.'); - if (pos == std::string::npos || pos == 0 || fn._path.length() - pos != 3) { - return false; - } - const path::value_type* ext = fn._path.c_str() + pos + 1; - if (detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("exe")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("cmd")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("bat")) || - detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("com"))) { - return true; - } - } - return false; -} -} // namespace detail -#endif - -//----------------------------------------------------------------------------- -// [fs.path.query] query -GHC_INLINE bool path::empty() const noexcept -{ - return _path.empty(); -} - -GHC_INLINE bool path::has_root_name() const -{ - return root_name_length() > 0; -} - -GHC_INLINE bool path::has_root_directory() const -{ - auto rootLen = _prefixLength + root_name_length(); - return (_path.length() > rootLen && _path[rootLen] == preferred_separator); -} - -GHC_INLINE bool path::has_root_path() const -{ - return has_root_name() || has_root_directory(); -} - -GHC_INLINE bool path::has_relative_path() const -{ - auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); - return rootPathLen < _path.length(); -} - -GHC_INLINE bool path::has_parent_path() const -{ - return !parent_path().empty(); -} - -GHC_INLINE bool path::has_filename() const -{ - return has_relative_path() && !filename().empty(); -} - -GHC_INLINE bool path::has_stem() const -{ - return !stem().empty(); -} - -GHC_INLINE bool path::has_extension() const -{ - return !extension().empty(); -} - -GHC_INLINE bool path::is_absolute() const -{ -#ifdef GHC_OS_WINDOWS - return has_root_name() && has_root_directory(); -#else - return has_root_directory(); -#endif -} - -GHC_INLINE bool path::is_relative() const -{ - return !is_absolute(); -} - -//----------------------------------------------------------------------------- -// [fs.path.gen] generation -GHC_INLINE path path::lexically_normal() const -{ - path dest; - bool lastDotDot = false; - for (string_type s : *this) { - if (s == ".") { - dest /= ""; - continue; - } - else if (s == ".." && !dest.empty()) { - auto root = root_path(); - if (dest == root) { - continue; - } - else if (*(--dest.end()) != "..") { - if (dest._path.back() == preferred_separator) { - dest._path.pop_back(); - } - dest.remove_filename(); - continue; - } - } - if (!(s.empty() && lastDotDot)) { - dest /= s; - } - lastDotDot = s == ".."; - } - if (dest.empty()) { - dest = "."; - } - return dest; -} - -GHC_INLINE path path::lexically_relative(const path& base) const -{ - if (root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory())) { - return path(); - } - const_iterator a = begin(), b = base.begin(); - while (a != end() && b != base.end() && *a == *b) { - ++a; - ++b; - } - if (a == end() && b == base.end()) { - return path("."); - } - int count = 0; - for (const auto& element : input_iterator_range(b, base.end())) { - if (element != "." && element != "" && element != "..") { - ++count; - } - else if (element == "..") { - --count; - } - } - if (count < 0) { - return path(); - } - path result; - for (int i = 0; i < count; ++i) { - result /= ".."; - } - for (const auto& element : input_iterator_range(a, end())) { - result /= element; - } - return result; -} - -GHC_INLINE path path::lexically_proximate(const path& base) const -{ - path result = lexically_relative(base); - return result.empty() ? *this : result; -} - -//----------------------------------------------------------------------------- -// [fs.path.itr] iterators -GHC_INLINE path::iterator::iterator() {} - -GHC_INLINE path::iterator::iterator(const path& p, const impl_string_type::const_iterator& pos) - : _first(p._path.begin()) - , _last(p._path.end()) - , _prefix(_first + static_cast(p._prefixLength)) - , _root(p.has_root_directory() ? _first + static_cast(p._prefixLength + p.root_name_length()) : _last) - , _iter(pos) -{ - if (pos != _last) { - updateCurrent(); - } -} - -GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(const path::impl_string_type::const_iterator& pos) const -{ - path::impl_string_type::const_iterator i = pos; - bool fromStart = i == _first || i == _prefix; - if (i != _last) { - if (fromStart && i == _first && _prefix > _first) { - i = _prefix; - } - else if (*i++ == preferred_separator) { - // we can only sit on a slash if it is a network name or a root - if (i != _last && *i == preferred_separator) { - if (fromStart && !(i + 1 != _last && *(i + 1) == preferred_separator)) { - // leadind double slashes detected, treat this and the - // following until a slash as one unit - i = std::find(++i, _last, preferred_separator); - } - else { - // skip redundant slashes - while (i != _last && *i == preferred_separator) { - ++i; - } - } - } - } - else { - if (fromStart && i != _last && *i == ':') { - ++i; - } - else { - i = std::find(i, _last, preferred_separator); - } - } - } - return i; -} - -GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(const path::impl_string_type::const_iterator& pos) const -{ - path::impl_string_type::const_iterator i = pos; - if (i != _first) { - --i; - // if this is now the root slash or the trailing slash, we are done, - // else check for network name - if (i != _root && (pos != _last || *i != preferred_separator)) { -#ifdef GHC_OS_WINDOWS - static const impl_string_type seps = GHC_PLATFORM_LITERAL("\\:"); - i = std::find_first_of(std::reverse_iterator(i), std::reverse_iterator(_first), seps.begin(), seps.end()).base(); - if (i > _first && *i == ':') { - i++; - } -#else - i = std::find(std::reverse_iterator(i), std::reverse_iterator(_first), preferred_separator).base(); -#endif - // Now we have to check if this is a network name - if (i - _first == 2 && *_first == preferred_separator && *(_first + 1) == preferred_separator) { - i -= 2; - } - } - } - return i; -} - -GHC_INLINE void path::iterator::updateCurrent() -{ - if ((_iter == _last) || (_iter != _first && _iter != _last && (*_iter == preferred_separator && _iter != _root) && (_iter + 1 == _last))) { - _current.clear(); - } - else { - _current.assign(_iter, increment(_iter)); - } -} - -GHC_INLINE path::iterator& path::iterator::operator++() -{ - _iter = increment(_iter); - while (_iter != _last && // we didn't reach the end - _iter != _root && // this is not a root position - *_iter == preferred_separator && // we are on a separator - (_iter + 1) != _last // the slash is not the last char - ) { - ++_iter; - } - updateCurrent(); - return *this; -} - -GHC_INLINE path::iterator path::iterator::operator++(int) -{ - path::iterator i{*this}; - ++(*this); - return i; -} - -GHC_INLINE path::iterator& path::iterator::operator--() -{ - _iter = decrement(_iter); - updateCurrent(); - return *this; -} - -GHC_INLINE path::iterator path::iterator::operator--(int) -{ - auto i = *this; - --(*this); - return i; -} - -GHC_INLINE bool path::iterator::operator==(const path::iterator& other) const -{ - return _iter == other._iter; -} - -GHC_INLINE bool path::iterator::operator!=(const path::iterator& other) const -{ - return _iter != other._iter; -} - -GHC_INLINE path::iterator::reference path::iterator::operator*() const -{ - return _current; -} - -GHC_INLINE path::iterator::pointer path::iterator::operator->() const -{ - return &_current; -} - -GHC_INLINE path::iterator path::begin() const -{ - return iterator(*this, _path.begin()); -} - -GHC_INLINE path::iterator path::end() const -{ - return iterator(*this, _path.end()); -} - -//----------------------------------------------------------------------------- -// [fs.path.nonmember] path non-member functions -GHC_INLINE void swap(path& lhs, path& rhs) noexcept -{ - swap(lhs._path, rhs._path); -} - -GHC_INLINE size_t hash_value(const path& p) noexcept -{ - return std::hash()(p.generic_string()); -} - -#ifdef GHC_HAS_THREEWAY_COMP -GHC_INLINE std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) <=> 0; -} -#endif - -GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) == 0; -} - -GHC_INLINE bool operator!=(const path& lhs, const path& rhs) noexcept -{ - return !(lhs == rhs); -} - -GHC_INLINE bool operator<(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) < 0; -} - -GHC_INLINE bool operator<=(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) <= 0; -} - -GHC_INLINE bool operator>(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) > 0; -} - -GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept -{ - return lhs.compare(rhs) >= 0; -} - -GHC_INLINE path operator/(const path& lhs, const path& rhs) -{ - path result(lhs); - result /= rhs; - return result; -} - -#endif // GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.path.io] path inserter and extractor -template -inline std::basic_ostream& operator<<(std::basic_ostream& os, const path& p) -{ - os << "\""; - auto ps = p.string(); - for (auto c : ps) { - if (c == '"' || c == '\\') { - os << '\\'; - } - os << c; - } - os << "\""; - return os; -} - -template -inline std::basic_istream& operator>>(std::basic_istream& is, path& p) -{ - std::basic_string tmp; - charT c; - is >> c; - if (c == '"') { - auto sf = is.flags(); - is >> std::noskipws; - while (is) { - auto c2 = is.get(); - if (is) { - if (c2 == '\\') { - c2 = is.get(); - if (is) { - tmp += static_cast(c2); - } - } - else if (c2 == '"') { - break; - } - else { - tmp += static_cast(c2); - } - } - } - if ((sf & std::ios_base::skipws) == std::ios_base::skipws) { - is >> std::skipws; - } - p = path(tmp); - } - else { - is >> tmp; - p = path(static_cast(c) + tmp); - } - return is; -} - -#ifdef GHC_EXPAND_IMPL - -//----------------------------------------------------------------------------- -// [fs.class.filesystem_error] Class filesystem_error -GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec) - : std::system_error(ec, what_arg) - , _what_arg(what_arg) - , _ec(ec) -{ -} - -GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec) - : std::system_error(ec, what_arg) - , _what_arg(what_arg) - , _ec(ec) - , _p1(p1) -{ - if (!_p1.empty()) { - _what_arg += ": '" + _p1.string() + "'"; - } -} - -GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec) - : std::system_error(ec, what_arg) - , _what_arg(what_arg) - , _ec(ec) - , _p1(p1) - , _p2(p2) -{ - if (!_p1.empty()) { - _what_arg += ": '" + _p1.string() + "'"; - } - if (!_p2.empty()) { - _what_arg += ", '" + _p2.string() + "'"; - } -} - -GHC_INLINE const path& filesystem_error::path1() const noexcept -{ - return _p1; -} - -GHC_INLINE const path& filesystem_error::path2() const noexcept -{ - return _p2; -} - -GHC_INLINE const char* filesystem_error::what() const noexcept -{ - return _what_arg.c_str(); -} - -//----------------------------------------------------------------------------- -// [fs.op.funcs] filesystem operations -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path absolute(const path& p) -{ - std::error_code ec; - path result = absolute(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE path absolute(const path& p, std::error_code& ec) -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - if (p.empty()) { - return absolute(current_path(ec), ec) / ""; - } - ULONG size = ::GetFullPathNameW(GHC_NATIVEWP(p), 0, 0, 0); - if (size) { - std::vector buf(size, 0); - ULONG s2 = GetFullPathNameW(GHC_NATIVEWP(p), size, buf.data(), nullptr); - if (s2 && s2 < size) { - path result = path(std::wstring(buf.data(), s2)); - if (p.filename() == ".") { - result /= "."; - } - return result; - } - } - ec = detail::make_system_error(); - return path(); -#else - path base = current_path(ec); - if (!ec) { - if (p.empty()) { - return base / p; - } - if (p.has_root_name()) { - if (p.has_root_directory()) { - return p; - } - else { - return p.root_name() / base.root_directory() / base.relative_path() / p.relative_path(); - } - } - else { - if (p.has_root_directory()) { - return base.root_name() / p; - } - else { - return base / p; - } - } - } - ec = detail::make_system_error(); - return path(); -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path canonical(const path& p) -{ - std::error_code ec; - auto result = canonical(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE path canonical(const path& p, std::error_code& ec) -{ - if (p.empty()) { - ec = detail::make_error_code(detail::portable_error::not_found); - return path(); - } - path work = p.is_absolute() ? p : absolute(p, ec); - path result; - - auto fs = status(work, ec); - if (ec) { - return path(); - } - if (fs.type() == file_type::not_found) { - ec = detail::make_error_code(detail::portable_error::not_found); - return path(); - } - bool redo; - do { - auto rootPathLen = work._prefixLength + work.root_name_length() + (work.has_root_directory() ? 1 : 0); - redo = false; - result.clear(); - for (auto pe : work) { - if (pe.empty() || pe == ".") { - continue; - } - else if (pe == "..") { - result = result.parent_path(); - continue; - } - else if ((result / pe).string().length() <= rootPathLen) { - result /= pe; - continue; - } - auto sls = symlink_status(result / pe, ec); - if (ec) { - return path(); - } - if (is_symlink(sls)) { - redo = true; - auto target = read_symlink(result / pe, ec); - if (ec) { - return path(); - } - if (target.is_absolute()) { - result = target; - continue; - } - else { - result /= target; - continue; - } - } - else { - result /= pe; - } - } - work = result; - } while (redo); - ec.clear(); - return result; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void copy(const path& from, const path& to) -{ - copy(from, to, copy_options::none); -} - -GHC_INLINE void copy(const path& from, const path& to, copy_options options) -{ - std::error_code ec; - copy(from, to, options, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); - } -} -#endif - -GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept -{ - copy(from, to, copy_options::none, ec); -} - -GHC_INLINE void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept -{ - std::error_code tec; - file_status fs_from, fs_to; - ec.clear(); - if ((options & (copy_options::skip_symlinks | copy_options::copy_symlinks | copy_options::create_symlinks)) != copy_options::none) { - fs_from = symlink_status(from, ec); - } - else { - fs_from = status(from, ec); - } - if (!exists(fs_from)) { - if (!ec) { - ec = detail::make_error_code(detail::portable_error::not_found); - } - return; - } - if ((options & (copy_options::skip_symlinks | copy_options::create_symlinks)) != copy_options::none) { - fs_to = symlink_status(to, tec); - } - else { - fs_to = status(to, tec); - } - if (is_other(fs_from) || is_other(fs_to) || (is_directory(fs_from) && is_regular_file(fs_to)) || (exists(fs_to) && equivalent(from, to, ec))) { - ec = detail::make_error_code(detail::portable_error::invalid_argument); - } - else if (is_symlink(fs_from)) { - if ((options & copy_options::skip_symlinks) == copy_options::none) { - if (!exists(fs_to) && (options & copy_options::copy_symlinks) != copy_options::none) { - copy_symlink(from, to, ec); - } - else { - ec = detail::make_error_code(detail::portable_error::invalid_argument); - } - } - } - else if (is_regular_file(fs_from)) { - if ((options & copy_options::directories_only) == copy_options::none) { - if ((options & copy_options::create_symlinks) != copy_options::none) { - create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec); - } -#ifndef GHC_OS_WEB - else if ((options & copy_options::create_hard_links) != copy_options::none) { - create_hard_link(from, to, ec); - } -#endif - else if (is_directory(fs_to)) { - copy_file(from, to / from.filename(), options, ec); - } - else { - copy_file(from, to, options, ec); - } - } - } -#ifdef LWG_2682_BEHAVIOUR - else if (is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) { - ec = detail::make_error_code(detail::portable_error::is_a_directory); - } -#endif - else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) { - if (!exists(fs_to)) { - create_directory(to, from, ec); - if (ec) { - return; - } - } - for (auto iter = directory_iterator(from, ec); iter != directory_iterator(); iter.increment(ec)) { - if (!ec) { - copy(iter->path(), to / iter->path().filename(), options | static_cast(0x8000), ec); - } - if (ec) { - return; - } - } - } - return; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool copy_file(const path& from, const path& to) -{ - return copy_file(from, to, copy_options::none); -} - -GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option) -{ - std::error_code ec; - auto result = copy_file(from, to, option, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); - } - return result; -} -#endif - -GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept -{ - return copy_file(from, to, copy_options::none, ec); -} - -GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept -{ - std::error_code tecf, tect; - auto sf = status(from, tecf); - auto st = status(to, tect); - bool overwrite = false; - ec.clear(); - if (!is_regular_file(sf)) { - ec = tecf; - return false; - } - if (exists(st) && (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none)) { - ec = tect ? tect : detail::make_error_code(detail::portable_error::exists); - return false; - } - if (exists(st)) { - if ((options & copy_options::update_existing) == copy_options::update_existing) { - auto from_time = last_write_time(from, ec); - if (ec) { - ec = detail::make_system_error(); - return false; - } - auto to_time = last_write_time(to, ec); - if (ec) { - ec = detail::make_system_error(); - return false; - } - if (from_time <= to_time) { - return false; - } - } - overwrite = true; - } -#ifdef GHC_OS_WINDOWS - if (!::CopyFileW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), !overwrite)) { - ec = detail::make_system_error(); - return false; - } - return true; -#else - std::vector buffer(16384, '\0'); - int in = -1, out = -1; - if ((in = ::open(from.c_str(), O_RDONLY)) < 0) { - ec = detail::make_system_error(); - return false; - } - int mode = O_CREAT | O_WRONLY | O_TRUNC; - if (!overwrite) { - mode |= O_EXCL; - } - if ((out = ::open(to.c_str(), mode, static_cast(sf.permissions() & perms::all))) < 0) { - ec = detail::make_system_error(); - ::close(in); - return false; - } - ssize_t br, bw; - while ((br = ::read(in, buffer.data(), buffer.size())) > 0) { - ssize_t offset = 0; - do { - if ((bw = ::write(out, buffer.data() + offset, static_cast(br))) > 0) { - br -= bw; - offset += bw; - } - else if (bw < 0) { - ec = detail::make_system_error(); - ::close(in); - ::close(out); - return false; - } - } while (br); - } - ::close(in); - ::close(out); - return true; -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink) -{ - std::error_code ec; - copy_symlink(existing_symlink, new_symlink, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), existing_symlink, new_symlink, ec); - } -} -#endif - -GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept -{ - ec.clear(); - auto to = read_symlink(existing_symlink, ec); - if (!ec) { - if (exists(to, ec) && is_directory(to, ec)) { - create_directory_symlink(to, new_symlink, ec); - } - else { - create_symlink(to, new_symlink, ec); - } - } -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool create_directories(const path& p) -{ - std::error_code ec; - auto result = create_directories(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE bool create_directories(const path& p, std::error_code& ec) noexcept -{ - path current; - ec.clear(); - bool didCreate = false; - auto rootPathLen = p._prefixLength + p.root_name_length() + (p.has_root_directory() ? 1 : 0); - current = p.native().substr(0, rootPathLen); - path folders(p._path.substr(rootPathLen)); - for (path::string_type part : folders) { - current /= part; - std::error_code tec; - auto fs = status(current, tec); - if (tec && fs.type() != file_type::not_found) { - ec = tec; - return false; - } - if (!exists(fs)) { - create_directory(current, ec); - if (ec) { - std::error_code tmp_ec; - if (is_directory(current, tmp_ec)) { - ec.clear(); - } - else { - return false; - } - } - didCreate = true; - } -#ifndef LWG_2935_BEHAVIOUR - else if (!is_directory(fs)) { - ec = detail::make_error_code(detail::portable_error::exists); - return false; - } -#endif - } - return didCreate; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool create_directory(const path& p) -{ - std::error_code ec; - auto result = create_directory(p, path(), ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE bool create_directory(const path& p, std::error_code& ec) noexcept -{ - return create_directory(p, path(), ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool create_directory(const path& p, const path& attributes) -{ - std::error_code ec; - auto result = create_directory(p, attributes, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept -{ - std::error_code tec; - ec.clear(); - auto fs = status(p, tec); -#ifdef LWG_2935_BEHAVIOUR - if (status_known(fs) && exists(fs)) { - return false; - } -#else - if (status_known(fs) && exists(fs) && is_directory(fs)) { - return false; - } -#endif -#ifdef GHC_OS_WINDOWS - if (!attributes.empty()) { - if (!::CreateDirectoryExW(GHC_NATIVEWP(attributes), GHC_NATIVEWP(p), NULL)) { - ec = detail::make_system_error(); - return false; - } - } - else if (!::CreateDirectoryW(GHC_NATIVEWP(p), NULL)) { - ec = detail::make_system_error(); - return false; - } -#else - ::mode_t attribs = static_cast(perms::all); - if (!attributes.empty()) { - struct ::stat fileStat; - if (::stat(attributes.c_str(), &fileStat) != 0) { - ec = detail::make_system_error(); - return false; - } - attribs = fileStat.st_mode; - } - if (::mkdir(p.c_str(), attribs) != 0) { - ec = detail::make_system_error(); - return false; - } -#endif - return true; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink) -{ - std::error_code ec; - create_directory_symlink(to, new_symlink, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec); - } -} -#endif - -GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept -{ - detail::create_symlink(to, new_symlink, true, ec); -} - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link) -{ - std::error_code ec; - create_hard_link(to, new_hard_link, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), to, new_hard_link, ec); - } -} -#endif - -GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept -{ - detail::create_hardlink(to, new_hard_link, ec); -} -#endif - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void create_symlink(const path& to, const path& new_symlink) -{ - std::error_code ec; - create_symlink(to, new_symlink, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec); - } -} -#endif - -GHC_INLINE void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept -{ - detail::create_symlink(to, new_symlink, false, ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path current_path() -{ - std::error_code ec; - auto result = current_path(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), ec); - } - return result; -} -#endif - -GHC_INLINE path current_path(std::error_code& ec) -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - DWORD pathlen = ::GetCurrentDirectoryW(0, 0); - std::unique_ptr buffer(new wchar_t[size_t(pathlen) + 1]); - if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) { - ec = detail::make_system_error(); - return path(); - } - return path(std::wstring(buffer.get()), path::native_format); -#else - size_t pathlen = static_cast(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX))); - std::unique_ptr buffer(new char[pathlen + 1]); - if (::getcwd(buffer.get(), pathlen) == nullptr) { - ec = detail::make_system_error(); - return path(); - } - return path(buffer.get()); -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void current_path(const path& p) -{ - std::error_code ec; - current_path(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } -} -#endif - -GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - if (!::SetCurrentDirectoryW(GHC_NATIVEWP(p))) { - ec = detail::make_system_error(); - } -#else - if (::chdir(p.string().c_str()) == -1) { - ec = detail::make_system_error(); - } -#endif -} - -GHC_INLINE bool exists(file_status s) noexcept -{ - return status_known(s) && s.type() != file_type::not_found; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool exists(const path& p) -{ - return exists(status(p)); -} -#endif - -GHC_INLINE bool exists(const path& p, std::error_code& ec) noexcept -{ - file_status s = status(p, ec); - if (status_known(s)) { - ec.clear(); - } - return exists(s); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool equivalent(const path& p1, const path& p2) -{ - std::error_code ec; - bool result = equivalent(p1, p2, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec); - } - return result; -} -#endif - -GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - detail::unique_handle file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - auto e1 = ::GetLastError(); - detail::unique_handle file2(::CreateFileW(GHC_NATIVEWP(p2), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - if (!file1 || !file2) { -#ifdef LWG_2937_BEHAVIOUR - ec = detail::make_system_error(e1 ? e1 : ::GetLastError()); -#else - if (file1 == file2) { - ec = detail::make_system_error(e1 ? e1 : ::GetLastError()); - } -#endif - return false; - } - BY_HANDLE_FILE_INFORMATION inf1, inf2; - if (!::GetFileInformationByHandle(file1.get(), &inf1)) { - ec = detail::make_system_error(); - return false; - } - if (!::GetFileInformationByHandle(file2.get(), &inf2)) { - ec = detail::make_system_error(); - return false; - } - return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow && - inf1.nFileSizeHigh == inf2.nFileSizeHigh && inf1.nFileSizeLow == inf2.nFileSizeLow && inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber; -#else - struct ::stat s1, s2; - auto rc1 = ::stat(p1.c_str(), &s1); - auto e1 = errno; - auto rc2 = ::stat(p2.c_str(), &s2); - if (rc1 || rc2) { -#ifdef LWG_2937_BEHAVIOUR - ec = detail::make_system_error(e1 ? e1 : errno); -#else - if (rc1 && rc2) { - ec = detail::make_system_error(e1 ? e1 : errno); - } -#endif - return false; - } - return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime; -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE uintmax_t file_size(const path& p) -{ - std::error_code ec; - auto result = file_size(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { - ec = detail::make_system_error(); - return static_cast(-1); - } - return static_cast(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow; -#else - struct ::stat fileStat; - if (::stat(p.c_str(), &fileStat) == -1) { - ec = detail::make_system_error(); - return static_cast(-1); - } - return static_cast(fileStat.st_size); -#endif -} - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE uintmax_t hard_link_count(const path& p) -{ - std::error_code ec; - auto result = hard_link_count(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - uintmax_t result = static_cast(-1); - detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - BY_HANDLE_FILE_INFORMATION inf; - if (!file) { - ec = detail::make_system_error(); - } - else { - if (!::GetFileInformationByHandle(file.get(), &inf)) { - ec = detail::make_system_error(); - } - else { - result = inf.nNumberOfLinks; - } - } - return result; -#else - uintmax_t result = 0; - file_status fs = detail::status_ex(p, ec, nullptr, nullptr, &result, nullptr); - if (fs.type() == file_type::not_found) { - ec = detail::make_error_code(detail::portable_error::not_found); - } - return ec ? static_cast(-1) : result; -#endif -} -#endif - -GHC_INLINE bool is_block_file(file_status s) noexcept -{ - return s.type() == file_type::block; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_block_file(const path& p) -{ - return is_block_file(status(p)); -} -#endif - -GHC_INLINE bool is_block_file(const path& p, std::error_code& ec) noexcept -{ - return is_block_file(status(p, ec)); -} - -GHC_INLINE bool is_character_file(file_status s) noexcept -{ - return s.type() == file_type::character; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_character_file(const path& p) -{ - return is_character_file(status(p)); -} -#endif - -GHC_INLINE bool is_character_file(const path& p, std::error_code& ec) noexcept -{ - return is_character_file(status(p, ec)); -} - -GHC_INLINE bool is_directory(file_status s) noexcept -{ - return s.type() == file_type::directory; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_directory(const path& p) -{ - return is_directory(status(p)); -} -#endif - -GHC_INLINE bool is_directory(const path& p, std::error_code& ec) noexcept -{ - return is_directory(status(p, ec)); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_empty(const path& p) -{ - if (is_directory(p)) { - return directory_iterator(p) == directory_iterator(); - } - else { - return file_size(p) == 0; - } -} -#endif - -GHC_INLINE bool is_empty(const path& p, std::error_code& ec) noexcept -{ - auto fs = status(p, ec); - if (ec) { - return false; - } - if (is_directory(fs)) { - directory_iterator iter(p, ec); - if (ec) { - return false; - } - return iter == directory_iterator(); - } - else { - auto sz = file_size(p, ec); - if (ec) { - return false; - } - return sz == 0; - } -} - -GHC_INLINE bool is_fifo(file_status s) noexcept -{ - return s.type() == file_type::fifo; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_fifo(const path& p) -{ - return is_fifo(status(p)); -} -#endif - -GHC_INLINE bool is_fifo(const path& p, std::error_code& ec) noexcept -{ - return is_fifo(status(p, ec)); -} - -GHC_INLINE bool is_other(file_status s) noexcept -{ - return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_other(const path& p) -{ - return is_other(status(p)); -} -#endif - -GHC_INLINE bool is_other(const path& p, std::error_code& ec) noexcept -{ - return is_other(status(p, ec)); -} - -GHC_INLINE bool is_regular_file(file_status s) noexcept -{ - return s.type() == file_type::regular; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_regular_file(const path& p) -{ - return is_regular_file(status(p)); -} -#endif - -GHC_INLINE bool is_regular_file(const path& p, std::error_code& ec) noexcept -{ - return is_regular_file(status(p, ec)); -} - -GHC_INLINE bool is_socket(file_status s) noexcept -{ - return s.type() == file_type::socket; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_socket(const path& p) -{ - return is_socket(status(p)); -} -#endif - -GHC_INLINE bool is_socket(const path& p, std::error_code& ec) noexcept -{ - return is_socket(status(p, ec)); -} - -GHC_INLINE bool is_symlink(file_status s) noexcept -{ - return s.type() == file_type::symlink; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool is_symlink(const path& p) -{ - return is_symlink(symlink_status(p)); -} -#endif - -GHC_INLINE bool is_symlink(const path& p, std::error_code& ec) noexcept -{ - return is_symlink(symlink_status(p, ec)); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_time_type last_write_time(const path& p) -{ - std::error_code ec; - auto result = last_write_time(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE file_time_type last_write_time(const path& p, std::error_code& ec) noexcept -{ - time_t result = 0; - ec.clear(); - file_status fs = detail::status_ex(p, ec, nullptr, nullptr, nullptr, &result); - return ec ? (file_time_type::min)() : std::chrono::system_clock::from_time_t(result); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void last_write_time(const path& p, file_time_type new_time) -{ - std::error_code ec; - last_write_time(p, new_time, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } -} -#endif - -GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept -{ - ec.clear(); - auto d = new_time.time_since_epoch(); -#ifdef GHC_OS_WINDOWS - detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)); - FILETIME ft; - auto tt = std::chrono::duration_cast(d).count() * 10 + 116444736000000000; - ft.dwLowDateTime = static_cast(tt); - ft.dwHighDateTime = static_cast(tt >> 32); - if (!::SetFileTime(file.get(), 0, 0, &ft)) { - ec = detail::make_system_error(); - } -#elif defined(GHC_OS_MACOS) -#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300 - struct ::stat fs; - if (::stat(p.c_str(), &fs) == 0) { - struct ::timeval tv[2]; - tv[0].tv_sec = fs.st_atimespec.tv_sec; - tv[0].tv_usec = static_cast(fs.st_atimespec.tv_nsec / 1000); - tv[1].tv_sec = std::chrono::duration_cast(d).count(); - tv[1].tv_usec = static_cast(std::chrono::duration_cast(d).count() % 1000000); - if (::utimes(p.c_str(), tv) == 0) { - return; - } - } - ec = detail::make_system_error(); - return; -#else - struct ::timespec times[2]; - times[0].tv_sec = 0; - times[0].tv_nsec = UTIME_OMIT; - times[1].tv_sec = std::chrono::duration_cast(d).count(); - times[1].tv_nsec = 0; // std::chrono::duration_cast(d).count() % 1000000000; - if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { - ec = detail::make_system_error(); - } - return; -#endif -#endif -#else -#ifndef UTIME_OMIT -#define UTIME_OMIT ((1l << 30) - 2l) -#endif - struct ::timespec times[2]; - times[0].tv_sec = 0; - times[0].tv_nsec = UTIME_OMIT; - times[1].tv_sec = static_cast(std::chrono::duration_cast(d).count()); - times[1].tv_nsec = static_cast(std::chrono::duration_cast(d).count() % 1000000000); -#if defined(__ANDROID_API__) && __ANDROID_API__ < 12 - if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { -#else - if (::utimensat((int)AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { -#endif - ec = detail::make_system_error(); - } - return; -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void permissions(const path& p, perms prms, perm_options opts) -{ - std::error_code ec; - permissions(p, prms, opts, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } -} -#endif - -GHC_INLINE void permissions(const path& p, perms prms, std::error_code& ec) noexcept -{ - permissions(p, prms, perm_options::replace, ec); -} - -GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept -{ - if (static_cast(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) { - ec = detail::make_error_code(detail::portable_error::invalid_argument); - return; - } - auto fs = symlink_status(p, ec); - if ((opts & perm_options::replace) != perm_options::replace) { - if ((opts & perm_options::add) == perm_options::add) { - prms = fs.permissions() | prms; - } - else { - prms = fs.permissions() & ~prms; - } - } -#ifdef GHC_OS_WINDOWS -#ifdef __GNUC__ - auto oldAttr = GetFileAttributesW(GHC_NATIVEWP(p)); - if (oldAttr != INVALID_FILE_ATTRIBUTES) { - DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY; - if (oldAttr == newAttr || SetFileAttributesW(GHC_NATIVEWP(p), newAttr)) { - return; - } - } - ec = detail::make_system_error(); -#else - int mode = 0; - if ((prms & perms::owner_read) == perms::owner_read) { - mode |= _S_IREAD; - } - if ((prms & perms::owner_write) == perms::owner_write) { - mode |= _S_IWRITE; - } - if (::_wchmod(p.wstring().c_str(), mode) != 0) { - ec = detail::make_system_error(); - } -#endif -#else - if ((opts & perm_options::nofollow) != perm_options::nofollow) { - if (::chmod(p.c_str(), static_cast(prms)) != 0) { - ec = detail::make_system_error(); - } - } -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path proximate(const path& p, std::error_code& ec) -{ - auto cp = current_path(ec); - if (!ec) { - return proximate(p, cp, ec); - } - return path(); -} -#endif - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path proximate(const path& p, const path& base) -{ - return weakly_canonical(p).lexically_proximate(weakly_canonical(base)); -} -#endif - -GHC_INLINE path proximate(const path& p, const path& base, std::error_code& ec) -{ - return weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec)); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path read_symlink(const path& p) -{ - std::error_code ec; - auto result = read_symlink(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE path read_symlink(const path& p, std::error_code& ec) -{ - file_status fs = symlink_status(p, ec); - if (fs.type() != file_type::symlink) { - ec = detail::make_error_code(detail::portable_error::invalid_argument); - return path(); - } - auto result = detail::resolveSymlink(p, ec); - return ec ? path() : result; -} - -GHC_INLINE path relative(const path& p, std::error_code& ec) -{ - return relative(p, current_path(ec), ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path relative(const path& p, const path& base) -{ - return weakly_canonical(p).lexically_relative(weakly_canonical(base)); -} -#endif - -GHC_INLINE path relative(const path& p, const path& base, std::error_code& ec) -{ - return weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec)); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool remove(const path& p) -{ - std::error_code ec; - auto result = remove(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS -#ifdef GHC_USE_WCHAR_T - auto cstr = p.c_str(); -#else - std::wstring np = detail::fromUtf8(p.u8string()); - auto cstr = np.c_str(); -#endif - DWORD attr = GetFileAttributesW(cstr); - if (attr == INVALID_FILE_ATTRIBUTES) { - auto error = ::GetLastError(); - if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { - return false; - } - ec = detail::make_system_error(error); - } - else if (attr & FILE_ATTRIBUTE_READONLY) { - auto new_attr = attr & ~static_cast(FILE_ATTRIBUTE_READONLY); - if (!SetFileAttributesW(cstr, new_attr)) { - auto error = ::GetLastError(); - ec = detail::make_system_error(error); - } - } - if (!ec) { - if (attr & FILE_ATTRIBUTE_DIRECTORY) { - if (!RemoveDirectoryW(cstr)) { - ec = detail::make_system_error(); - } - } - else { - if (!DeleteFileW(cstr)) { - ec = detail::make_system_error(); - } - } - } -#else - if (::remove(p.c_str()) == -1) { - auto error = errno; - if (error == ENOENT) { - return false; - } - ec = detail::make_system_error(); - } -#endif - return ec ? false : true; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE uintmax_t remove_all(const path& p) -{ - std::error_code ec; - auto result = remove_all(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE uintmax_t remove_all(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); - uintmax_t count = 0; - if (p == "/") { - ec = detail::make_error_code(detail::portable_error::not_supported); - return static_cast(-1); - } - std::error_code tec; - auto fs = symlink_status(p, tec); - if (exists(fs) && is_directory(fs)) { - for (auto iter = directory_iterator(p, ec); iter != directory_iterator(); iter.increment(ec)) { - if (ec && !detail::is_not_found_error(ec)) { - break; - } - bool is_symlink_result = iter->is_symlink(ec); - if (ec) - return static_cast(-1); - if (!is_symlink_result && iter->is_directory(ec)) { - count += remove_all(iter->path(), ec); - if (ec) { - return static_cast(-1); - } - } - else { - if (!ec) { - remove(iter->path(), ec); - } - if (ec) { - return static_cast(-1); - } - ++count; - } - } - } - if (!ec) { - if (remove(p, ec)) { - ++count; - } - } - if (ec) { - return static_cast(-1); - } - return count; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void rename(const path& from, const path& to) -{ - std::error_code ec; - rename(from, to, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); - } -} -#endif - -GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - if (from != to) { - if (!MoveFileExW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), (DWORD)MOVEFILE_REPLACE_EXISTING)) { - ec = detail::make_system_error(); - } - } -#else - if (from != to) { - if (::rename(from.c_str(), to.c_str()) != 0) { - ec = detail::make_system_error(); - } - } -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void resize_file(const path& p, uintmax_t size) -{ - std::error_code ec; - resize_file(p, size, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } -} -#endif - -GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - LARGE_INTEGER lisize; - lisize.QuadPart = static_cast(size); - if (lisize.QuadPart < 0) { -#ifdef ERROR_FILE_TOO_LARGE - ec = detail::make_system_error(ERROR_FILE_TOO_LARGE); -#else - ec = detail::make_system_error(223); -#endif - return; - } - detail::unique_handle file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)); - if (!file) { - ec = detail::make_system_error(); - } - else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) { - ec = detail::make_system_error(); - } -#else - if (::truncate(p.c_str(), static_cast(size)) != 0) { - ec = detail::make_system_error(); - } -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE space_info space(const path& p) -{ - std::error_code ec; - auto result = space(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - ULARGE_INTEGER freeBytesAvailableToCaller = {{ 0, 0 }}; - ULARGE_INTEGER totalNumberOfBytes = {{ 0, 0 }}; - ULARGE_INTEGER totalNumberOfFreeBytes = {{ 0, 0 }}; - if (!GetDiskFreeSpaceExW(GHC_NATIVEWP(p), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { - ec = detail::make_system_error(); - return {static_cast(-1), static_cast(-1), static_cast(-1)}; - } - return {static_cast(totalNumberOfBytes.QuadPart), static_cast(totalNumberOfFreeBytes.QuadPart), static_cast(freeBytesAvailableToCaller.QuadPart)}; -#else - struct ::statvfs sfs; - if (::statvfs(p.c_str(), &sfs) != 0) { - ec = detail::make_system_error(); - return {static_cast(-1), static_cast(-1), static_cast(-1)}; - } - return {static_cast(sfs.f_blocks) * static_cast(sfs.f_frsize), static_cast(sfs.f_bfree) * static_cast(sfs.f_frsize), static_cast(sfs.f_bavail) * static_cast(sfs.f_frsize)}; -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_status status(const path& p) -{ - std::error_code ec; - auto result = status(p, ec); - if (result.type() == file_type::none) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE file_status status(const path& p, std::error_code& ec) noexcept -{ - return detail::status_ex(p, ec); -} - -GHC_INLINE bool status_known(file_status s) noexcept -{ - return s.type() != file_type::none; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_status symlink_status(const path& p) -{ - std::error_code ec; - auto result = symlink_status(p, ec); - if (result.type() == file_type::none) { - throw filesystem_error(detail::systemErrorText(ec.value()), ec); - } - return result; -} -#endif - -GHC_INLINE file_status symlink_status(const path& p, std::error_code& ec) noexcept -{ - return detail::symlink_status_ex(p, ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path temp_directory_path() -{ - std::error_code ec; - path result = temp_directory_path(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), ec); - } - return result; -} -#endif - -GHC_INLINE path temp_directory_path(std::error_code& ec) noexcept -{ - ec.clear(); -#ifdef GHC_OS_WINDOWS - wchar_t buffer[512]; - auto rc = GetTempPathW(511, buffer); - if (!rc || rc > 511) { - ec = detail::make_system_error(); - return path(); - } - return path(std::wstring(buffer)); -#else - static const char* temp_vars[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr}; - const char* temp_path = nullptr; - for (auto temp_name = temp_vars; *temp_name != nullptr; ++temp_name) { - temp_path = std::getenv(*temp_name); - if (temp_path) { - return path(temp_path); - } - } - return path("/tmp"); -#endif -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE path weakly_canonical(const path& p) -{ - std::error_code ec; - auto result = weakly_canonical(p, ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); - } - return result; -} -#endif - -GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept -{ - path result; - ec.clear(); - bool scan = true; - for (auto pe : p) { - if (scan) { - std::error_code tec; - if (exists(result / pe, tec)) { - result /= pe; - } - else { - if (ec) { - return path(); - } - scan = false; - if (!result.empty()) { - result = canonical(result, ec) / pe; - if (ec) { - break; - } - } - else { - result /= pe; - } - } - } - else { - result /= pe; - } - } - if (scan) { - if (!result.empty()) { - result = canonical(result, ec); - } - } - return ec ? path() : result.lexically_normal(); -} - -//----------------------------------------------------------------------------- -// [fs.class.file_status] class file_status -// [fs.file_status.cons] constructors and destructor -GHC_INLINE file_status::file_status() noexcept - : file_status(file_type::none) -{ -} - -GHC_INLINE file_status::file_status(file_type ft, perms prms) noexcept - : _type(ft) - , _perms(prms) -{ -} - -GHC_INLINE file_status::file_status(const file_status& other) noexcept - : _type(other._type) - , _perms(other._perms) -{ -} - -GHC_INLINE file_status::file_status(file_status&& other) noexcept - : _type(other._type) - , _perms(other._perms) -{ -} - -GHC_INLINE file_status::~file_status() {} - -// assignments: -GHC_INLINE file_status& file_status::operator=(const file_status& rhs) noexcept -{ - _type = rhs._type; - _perms = rhs._perms; - return *this; -} - -GHC_INLINE file_status& file_status::operator=(file_status&& rhs) noexcept -{ - _type = rhs._type; - _perms = rhs._perms; - return *this; -} - -// [fs.file_status.mods] modifiers -GHC_INLINE void file_status::type(file_type ft) noexcept -{ - _type = ft; -} - -GHC_INLINE void file_status::permissions(perms prms) noexcept -{ - _perms = prms; -} - -// [fs.file_status.obs] observers -GHC_INLINE file_type file_status::type() const noexcept -{ - return _type; -} - -GHC_INLINE perms file_status::permissions() const noexcept -{ - return _perms; -} - -//----------------------------------------------------------------------------- -// [fs.class.directory_entry] class directory_entry -// [fs.dir.entry.cons] constructors and destructor -// directory_entry::directory_entry() noexcept = default; -// directory_entry::directory_entry(const directory_entry&) = default; -// directory_entry::directory_entry(directory_entry&&) noexcept = default; -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE directory_entry::directory_entry(const filesystem::path& p) - : _path(p) - , _file_size(static_cast(-1)) -#ifndef GHC_OS_WINDOWS - , _hard_link_count(static_cast(-1)) -#endif - , _last_write_time(0) -{ - refresh(); -} -#endif - -GHC_INLINE directory_entry::directory_entry(const filesystem::path& p, std::error_code& ec) - : _path(p) - , _file_size(static_cast(-1)) -#ifndef GHC_OS_WINDOWS - , _hard_link_count(static_cast(-1)) -#endif - , _last_write_time(0) -{ - refresh(ec); -} - -GHC_INLINE directory_entry::~directory_entry() {} - -// assignments: -// directory_entry& directory_entry::operator=(const directory_entry&) = default; -// directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default; - -// [fs.dir.entry.mods] directory_entry modifiers -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void directory_entry::assign(const filesystem::path& p) -{ - _path = p; - refresh(); -} -#endif - -GHC_INLINE void directory_entry::assign(const filesystem::path& p, std::error_code& ec) -{ - _path = p; - refresh(ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p) -{ - _path.replace_filename(p); - refresh(); -} -#endif - -GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p, std::error_code& ec) -{ - _path.replace_filename(p); - refresh(ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void directory_entry::refresh() -{ - std::error_code ec; - refresh(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec); - } -} -#endif - -GHC_INLINE void directory_entry::refresh(std::error_code& ec) noexcept -{ -#ifdef GHC_OS_WINDOWS - _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, nullptr, &_last_write_time); -#else - _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, &_hard_link_count, &_last_write_time); -#endif -} - -// [fs.dir.entry.obs] directory_entry observers -GHC_INLINE const filesystem::path& directory_entry::path() const noexcept -{ - return _path; -} - -GHC_INLINE directory_entry::operator const filesystem::path&() const noexcept -{ - return _path; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_type directory_entry::status_file_type() const -{ - return _status.type() != file_type::none ? _status.type() : filesystem::status(path()).type(); -} -#endif - -GHC_INLINE file_type directory_entry::status_file_type(std::error_code& ec) const noexcept -{ - if (_status.type() != file_type::none) { - ec.clear(); - return _status.type(); - } - return filesystem::status(path(), ec).type(); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::exists() const -{ - return status_file_type() != file_type::not_found; -} -#endif - -GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept -{ - return status_file_type(ec) != file_type::not_found; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_block_file() const -{ - return status_file_type() == file_type::block; -} -#endif -GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::block; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_character_file() const -{ - return status_file_type() == file_type::character; -} -#endif - -GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::character; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_directory() const -{ - return status_file_type() == file_type::directory; -} -#endif - -GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::directory; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_fifo() const -{ - return status_file_type() == file_type::fifo; -} -#endif - -GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::fifo; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_other() const -{ - auto ft = status_file_type(); - return ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(); -} -#endif - -GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept -{ - auto ft = status_file_type(ec); - bool other = ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(ec); - return !ec && other; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_regular_file() const -{ - return status_file_type() == file_type::regular; -} -#endif - -GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::regular; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_socket() const -{ - return status_file_type() == file_type::socket; -} -#endif - -GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept -{ - return status_file_type(ec) == file_type::socket; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE bool directory_entry::is_symlink() const -{ - return _symlink_status.type() != file_type::none ? _symlink_status.type() == file_type::symlink : filesystem::is_symlink(symlink_status()); -} -#endif - -GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept -{ - if (_symlink_status.type() != file_type::none) { - ec.clear(); - return _symlink_status.type() == file_type::symlink; - } - return filesystem::is_symlink(symlink_status(ec)); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE uintmax_t directory_entry::file_size() const -{ - if (_file_size != static_cast(-1)) { - return _file_size; - } - return filesystem::file_size(path()); -} -#endif - -GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept -{ - if (_file_size != static_cast(-1)) { - ec.clear(); - return _file_size; - } - return filesystem::file_size(path(), ec); -} - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE uintmax_t directory_entry::hard_link_count() const -{ -#ifndef GHC_OS_WINDOWS - if (_hard_link_count != static_cast(-1)) { - return _hard_link_count; - } -#endif - return filesystem::hard_link_count(path()); -} -#endif - -GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept -{ -#ifndef GHC_OS_WINDOWS - if (_hard_link_count != static_cast(-1)) { - ec.clear(); - return _hard_link_count; - } -#endif - return filesystem::hard_link_count(path(), ec); -} -#endif - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_time_type directory_entry::last_write_time() const -{ - if (_last_write_time != 0) { - return std::chrono::system_clock::from_time_t(_last_write_time); - } - return filesystem::last_write_time(path()); -} -#endif - -GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec) const noexcept -{ - if (_last_write_time != 0) { - ec.clear(); - return std::chrono::system_clock::from_time_t(_last_write_time); - } - return filesystem::last_write_time(path(), ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_status directory_entry::status() const -{ - if (_status.type() != file_type::none && _status.permissions() != perms::unknown) { - return _status; - } - return filesystem::status(path()); -} -#endif - -GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept -{ - if (_status.type() != file_type::none && _status.permissions() != perms::unknown) { - ec.clear(); - return _status; - } - return filesystem::status(path(), ec); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE file_status directory_entry::symlink_status() const -{ - if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) { - return _symlink_status; - } - return filesystem::symlink_status(path()); -} -#endif - -GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept -{ - if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) { - ec.clear(); - return _symlink_status; - } - return filesystem::symlink_status(path(), ec); -} - -#ifdef GHC_HAS_THREEWAY_COMP -GHC_INLINE std::strong_ordering directory_entry::operator<=>(const directory_entry& rhs) const noexcept -{ - return _path <=> rhs._path; -} -#endif - -GHC_INLINE bool directory_entry::operator<(const directory_entry& rhs) const noexcept -{ - return _path < rhs._path; -} - -GHC_INLINE bool directory_entry::operator==(const directory_entry& rhs) const noexcept -{ - return _path == rhs._path; -} - -GHC_INLINE bool directory_entry::operator!=(const directory_entry& rhs) const noexcept -{ - return _path != rhs._path; -} - -GHC_INLINE bool directory_entry::operator<=(const directory_entry& rhs) const noexcept -{ - return _path <= rhs._path; -} - -GHC_INLINE bool directory_entry::operator>(const directory_entry& rhs) const noexcept -{ - return _path > rhs._path; -} - -GHC_INLINE bool directory_entry::operator>=(const directory_entry& rhs) const noexcept -{ - return _path >= rhs._path; -} - -//----------------------------------------------------------------------------- -// [fs.class.directory_iterator] class directory_iterator - -#ifdef GHC_OS_WINDOWS -class directory_iterator::impl -{ -public: - impl(const path& p, directory_options options) - : _base(p) - , _options(options) - , _dirHandle(INVALID_HANDLE_VALUE) - { - if (!_base.empty()) { - ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW)); - if ((_dirHandle = FindFirstFileW(GHC_NATIVEWP((_base / "*")), &_findData)) != INVALID_HANDLE_VALUE) { - if (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..") { - increment(_ec); - } - else { - _dir_entry._path = _base / std::wstring(_findData.cFileName); - copyToDirEntry(_ec); - } - } - else { - auto error = ::GetLastError(); - _base = filesystem::path(); - if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) { - _ec = detail::make_system_error(); - } - } - } - } - impl(const impl& other) = delete; - ~impl() - { - if (_dirHandle != INVALID_HANDLE_VALUE) { - FindClose(_dirHandle); - _dirHandle = INVALID_HANDLE_VALUE; - } - } - void increment(std::error_code& ec) - { - if (_dirHandle != INVALID_HANDLE_VALUE) { - do { - if (FindNextFileW(_dirHandle, &_findData)) { - _dir_entry._path = _base; -#ifdef GHC_USE_WCHAR_T - _dir_entry._path.append_name(_findData.cFileName); -#else -#ifdef GHC_RAISE_UNICODE_ERRORS - try { - _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str()); - } - catch (filesystem_error& fe) { - ec = fe.code(); - return; - } -#else - _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str()); -#endif -#endif - copyToDirEntry(ec); - } - else { - auto err = ::GetLastError(); - if (err != ERROR_NO_MORE_FILES) { - _ec = ec = detail::make_system_error(err); - } - FindClose(_dirHandle); - _dirHandle = INVALID_HANDLE_VALUE; - _dir_entry._path.clear(); - break; - } - } while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L".."); - } - else { - ec = _ec; - } - } - void copyToDirEntry(std::error_code& ec) - { - if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - _dir_entry._status = detail::status_ex(_dir_entry._path, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time); - } - else { - _dir_entry._status = detail::status_from_INFO(_dir_entry._path, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time); - _dir_entry._symlink_status = _dir_entry._status; - } - if (ec) { - if (_dir_entry._status.type() != file_type::none && _dir_entry._symlink_status.type() != file_type::none) { - ec.clear(); - } - else { - _dir_entry._file_size = static_cast(-1); - _dir_entry._last_write_time = 0; - } - } - } - path _base; - directory_options _options; - WIN32_FIND_DATAW _findData; - HANDLE _dirHandle; - directory_entry _dir_entry; - std::error_code _ec; -}; -#else -// POSIX implementation -class directory_iterator::impl -{ -public: - impl(const path& path, directory_options options) - : _base(path) - , _options(options) - , _dir(nullptr) - , _entry(nullptr) - { - if (!path.empty()) { - _dir = ::opendir(path.native().c_str()); - if (!_dir) { - auto error = errno; - _base = filesystem::path(); - if ((error != EACCES && error != EPERM) || (options & directory_options::skip_permission_denied) == directory_options::none) { - _ec = detail::make_system_error(); - } - } - else { - increment(_ec); - } - } - } - impl(const impl& other) = delete; - ~impl() - { - if (_dir) { - ::closedir(_dir); - } - } - void increment(std::error_code& ec) - { - if (_dir) { - bool skip; - do { - skip = false; - errno = 0; - _entry = ::readdir(_dir); - if (_entry) { - _dir_entry._path = _base; - _dir_entry._path.append_name(_entry->d_name); - copyToDirEntry(); - if (ec && (ec.value() == EACCES || ec.value() == EPERM) && (_options & directory_options::skip_permission_denied) == directory_options::skip_permission_denied) { - ec.clear(); - skip = true; - } - } - else { - ::closedir(_dir); - _dir = nullptr; - _dir_entry._path.clear(); - if (errno) { - ec = detail::make_system_error(); - } - break; - } - } while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0); - } - } - - void copyToDirEntry() - { - _dir_entry._symlink_status.permissions(perms::unknown); - auto ft = detail::file_type_from_dirent(*_entry); - _dir_entry._symlink_status.type(ft); - if (ft != file_type::symlink) { - _dir_entry._status = _dir_entry._symlink_status; - } - else { - _dir_entry._status.type(file_type::none); - _dir_entry._status.permissions(perms::unknown); - } - _dir_entry._file_size = static_cast(-1); - _dir_entry._hard_link_count = static_cast(-1); - _dir_entry._last_write_time = 0; - } - path _base; - directory_options _options; - DIR* _dir; - struct ::dirent* _entry; - directory_entry _dir_entry; - std::error_code _ec; -}; -#endif - -// [fs.dir.itr.members] member functions -GHC_INLINE directory_iterator::directory_iterator() noexcept - : _impl(new impl(path(), directory_options::none)) -{ -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE directory_iterator::directory_iterator(const path& p) - : _impl(new impl(p, directory_options::none)) -{ - if (_impl->_ec) { - throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec); - } - _impl->_ec.clear(); -} - -GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options) - : _impl(new impl(p, options)) -{ - if (_impl->_ec) { - throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec); - } -} -#endif - -GHC_INLINE directory_iterator::directory_iterator(const path& p, std::error_code& ec) noexcept - : _impl(new impl(p, directory_options::none)) -{ - if (_impl->_ec) { - ec = _impl->_ec; - } -} - -GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept - : _impl(new impl(p, options)) -{ - if (_impl->_ec) { - ec = _impl->_ec; - } -} - -GHC_INLINE directory_iterator::directory_iterator(const directory_iterator& rhs) - : _impl(rhs._impl) -{ -} - -GHC_INLINE directory_iterator::directory_iterator(directory_iterator&& rhs) noexcept - : _impl(std::move(rhs._impl)) -{ -} - -GHC_INLINE directory_iterator::~directory_iterator() {} - -GHC_INLINE directory_iterator& directory_iterator::operator=(const directory_iterator& rhs) -{ - _impl = rhs._impl; - return *this; -} - -GHC_INLINE directory_iterator& directory_iterator::operator=(directory_iterator&& rhs) noexcept -{ - _impl = std::move(rhs._impl); - return *this; -} - -GHC_INLINE const directory_entry& directory_iterator::operator*() const -{ - return _impl->_dir_entry; -} - -GHC_INLINE const directory_entry* directory_iterator::operator->() const -{ - return &_impl->_dir_entry; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE directory_iterator& directory_iterator::operator++() -{ - std::error_code ec; - _impl->increment(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_entry._path, ec); - } - return *this; -} -#endif - -GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec) noexcept -{ - _impl->increment(ec); - return *this; -} - -GHC_INLINE bool directory_iterator::operator==(const directory_iterator& rhs) const -{ - return _impl->_dir_entry._path == rhs._impl->_dir_entry._path; -} - -GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) const -{ - return _impl->_dir_entry._path != rhs._impl->_dir_entry._path; -} - -// [fs.dir.itr.nonmembers] directory_iterator non-member functions - -GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept -{ - return iter; -} - -GHC_INLINE directory_iterator end(const directory_iterator&) noexcept -{ - return directory_iterator(); -} - -//----------------------------------------------------------------------------- -// [fs.class.rec.dir.itr] class recursive_directory_iterator - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept - : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) -{ - _impl->_dir_iter_stack.push(directory_iterator()); -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p) - : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) -{ - _impl->_dir_iter_stack.push(directory_iterator(p)); -} - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options) - : _impl(new recursive_directory_iterator_impl(options, true)) -{ - _impl->_dir_iter_stack.push(directory_iterator(p, options)); -} -#endif - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept - : _impl(new recursive_directory_iterator_impl(options, true)) -{ - _impl->_dir_iter_stack.push(directory_iterator(p, options, ec)); -} - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, std::error_code& ec) noexcept - : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) -{ - _impl->_dir_iter_stack.push(directory_iterator(p, ec)); -} - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const recursive_directory_iterator& rhs) - : _impl(rhs._impl) -{ -} - -GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept - : _impl(std::move(rhs._impl)) -{ -} - -GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {} - -// [fs.rec.dir.itr.members] observers -GHC_INLINE directory_options recursive_directory_iterator::options() const -{ - return _impl->_options; -} - -GHC_INLINE int recursive_directory_iterator::depth() const -{ - return static_cast(_impl->_dir_iter_stack.size() - 1); -} - -GHC_INLINE bool recursive_directory_iterator::recursion_pending() const -{ - return _impl->_recursion_pending; -} - -GHC_INLINE const directory_entry& recursive_directory_iterator::operator*() const -{ - return *(_impl->_dir_iter_stack.top()); -} - -GHC_INLINE const directory_entry* recursive_directory_iterator::operator->() const -{ - return &(*(_impl->_dir_iter_stack.top())); -} - -// [fs.rec.dir.itr.members] modifiers recursive_directory_iterator& -GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(const recursive_directory_iterator& rhs) -{ - _impl = rhs._impl; - return *this; -} - -GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(recursive_directory_iterator&& rhs) noexcept -{ - _impl = std::move(rhs._impl); - return *this; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator++() -{ - std::error_code ec; - increment(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec); - } - return *this; -} -#endif - -GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept -{ - bool isSymLink = (*this)->is_symlink(ec); - bool isDir = !ec && (*this)->is_directory(ec); - if (isSymLink && detail::is_not_found_error(ec)) { - ec.clear(); - } - if (!ec) { - if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) { - _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec)); - } - else { - _impl->_dir_iter_stack.top().increment(ec); - } - if (!ec) { - while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()) { - _impl->_dir_iter_stack.pop(); - _impl->_dir_iter_stack.top().increment(ec); - } - } - else if (!_impl->_dir_iter_stack.empty()) { - _impl->_dir_iter_stack.pop(); - } - _impl->_recursion_pending = true; - } - return *this; -} - -#ifdef GHC_WITH_EXCEPTIONS -GHC_INLINE void recursive_directory_iterator::pop() -{ - std::error_code ec; - pop(ec); - if (ec) { - throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec); - } -} -#endif - -GHC_INLINE void recursive_directory_iterator::pop(std::error_code& ec) -{ - if (depth() == 0) { - *this = recursive_directory_iterator(); - } - else { - do { - _impl->_dir_iter_stack.pop(); - _impl->_dir_iter_stack.top().increment(ec); - } while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()); - } -} - -GHC_INLINE void recursive_directory_iterator::disable_recursion_pending() -{ - _impl->_recursion_pending = false; -} - -// other members as required by [input.iterators] -GHC_INLINE bool recursive_directory_iterator::operator==(const recursive_directory_iterator& rhs) const -{ - return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top(); -} - -GHC_INLINE bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& rhs) const -{ - return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top(); -} - -// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions -GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept -{ - return iter; -} - -GHC_INLINE recursive_directory_iterator end(const recursive_directory_iterator&) noexcept -{ - return recursive_directory_iterator(); -} - -#endif // GHC_EXPAND_IMPL - -} // namespace filesystem -} // namespace ghc - -// cleanup some macros -#undef GHC_INLINE -#undef GHC_EXPAND_IMPL - -#endif // GHC_FILESYSTEM_H diff --git a/src/ghc/fs_fwd.hpp b/src/ghc/fs_fwd.hpp deleted file mode 100644 index 31188d16..00000000 --- a/src/ghc/fs_fwd.hpp +++ /dev/null @@ -1,38 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// fs_fwd.hpp - The forwarding header for the header/implementation seperated usage of -// ghc::filesystem. -// This file can be include at any place, where ghc::filesystem api is needed while -// not bleeding implementation details (e.g. system includes) into the global namespace, -// as long as one cpp includes fs_impl.hpp to deliver the matching implementations. -//--------------------------------------------------------------------------------------- -#ifndef GHC_FILESYSTEM_FWD_H -#define GHC_FILESYSTEM_FWD_H -#define GHC_FILESYSTEM_FWD -#include -#endif // GHC_FILESYSTEM_FWD_H diff --git a/src/ghc/fs_impl.hpp b/src/ghc/fs_impl.hpp deleted file mode 100644 index 92e3eaef..00000000 --- a/src/ghc/fs_impl.hpp +++ /dev/null @@ -1,35 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// fs_impl.hpp - The implementation header for the header/implementation seperated usage of -// ghc::filesystem. -// This file can be used to hide the implementation of ghc::filesystem into a single cpp. -// The cpp has to include this before including fs_fwd.hpp directly or via a different -// header to work. -//--------------------------------------------------------------------------------------- -#define GHC_FILESYSTEM_IMPLEMENTATION -#include diff --git a/src/ghc/fs_std.hpp b/src/ghc/fs_std.hpp deleted file mode 100644 index c9492fdc..00000000 --- a/src/ghc/fs_std.hpp +++ /dev/null @@ -1,60 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// fs_std.hpp - The dynamic switching header that includes std::filesystem if detected -// or ghc::filesystem if not, and makes the resulting API available in the -// namespace fs. -//--------------------------------------------------------------------------------------- -#ifndef GHC_FILESYSTEM_STD_H -#define GHC_FILESYSTEM_STD_H -#if defined(__APPLE__) -#include -#endif -#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) -#if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) -#define GHC_USE_STD_FS -#include -namespace fs { -using namespace std::filesystem; -using ifstream = std::ifstream; -using ofstream = std::ofstream; -using fstream = std::fstream; -} -#endif -#endif -#ifndef GHC_USE_STD_FS -//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE -#include -namespace fs { -using namespace ghc::filesystem; -using ifstream = ghc::filesystem::ifstream; -using ofstream = ghc::filesystem::ofstream; -using fstream = ghc::filesystem::fstream; -} -#endif -#endif // GHC_FILESYSTEM_STD_H - diff --git a/src/ghc/fs_std_fwd.hpp b/src/ghc/fs_std_fwd.hpp deleted file mode 100644 index 163c956a..00000000 --- a/src/ghc/fs_std_fwd.hpp +++ /dev/null @@ -1,63 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// fs_std_fwd.hpp - The forwarding header for the header/implementation seperated usage of -// ghc::filesystem that uses std::filesystem if it detects it. -// This file can be include at any place, where fs::filesystem api is needed while -// not bleeding implementation details (e.g. system includes) into the global namespace, -// as long as one cpp includes fs_std_impl.hpp to deliver the matching implementations. -//--------------------------------------------------------------------------------------- -#ifndef GHC_FILESYSTEM_STD_FWD_H -#define GHC_FILESYSTEM_STD_FWD_H -#if defined(__APPLE__) -#include -#endif -#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) -#if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) -#define GHC_USE_STD_FS -#include -namespace fs { -using namespace std::filesystem; -using ifstream = std::ifstream; -using ofstream = std::ofstream; -using fstream = std::fstream; -} -#endif -#endif -#ifndef GHC_USE_STD_FS -//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE -#define GHC_FILESYSTEM_FWD -#include -namespace fs { -using namespace ghc::filesystem; -using ifstream = ghc::filesystem::ifstream; -using ofstream = ghc::filesystem::ofstream; -using fstream = ghc::filesystem::fstream; -} -#endif -#endif // GHC_FILESYSTEM_STD_FWD_H - diff --git a/src/ghc/fs_std_impl.hpp b/src/ghc/fs_std_impl.hpp deleted file mode 100644 index 7042edca..00000000 --- a/src/ghc/fs_std_impl.hpp +++ /dev/null @@ -1,46 +0,0 @@ -//--------------------------------------------------------------------------------------- -// -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 -// -//--------------------------------------------------------------------------------------- -// -// Copyright (c) 2018, Steffen Schümann -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -//--------------------------------------------------------------------------------------- -// fs_std_impl.hpp - The implementation header for the header/implementation seperated usage of -// ghc::filesystem that does nothing if std::filesystem is detected. -// This file can be used to hide the implementation of ghc::filesystem into a single cpp. -// The cpp has to include this before including fs_std_fwd.hpp directly or via a different -// header to work. -//--------------------------------------------------------------------------------------- -#if defined(__APPLE__) -#include -#endif -#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) -#if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) -#define GHC_USE_STD_FS -#endif -#endif -#ifndef GHC_USE_STD_FS -//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE -#define GHC_FILESYSTEM_IMPLEMENTATION -#include -#endif diff --git a/src/line_buffer.cc b/src/line_buffer.cc index 8d6eafb3..7960bafc 100644 --- a/src/line_buffer.cc +++ b/src/line_buffer.cc @@ -135,7 +135,8 @@ private: #define Z_BUFSIZE 65536U #define SYNCPOINT_SIZE (1024 * 1024) -line_buffer::gz_indexed::gz_indexed() +line_buffer::gz_indexed:: +gz_indexed() { if ((this->inbuf = auto_mem::malloc(Z_BUFSIZE)) == NULL) { throw std::bad_alloc(); @@ -364,12 +365,14 @@ line_buffer::gz_indexed::read(void* buf, size_t offset, size_t size) return bytes; } -line_buffer::line_buffer() +line_buffer:: +line_buffer() { ensure(this->invariant()); } -line_buffer::~line_buffer() +line_buffer::~ +line_buffer() { if (this->lb_loader_future.valid()) { this->lb_loader_future.wait(); @@ -1312,8 +1315,8 @@ line_buffer::get_available() static_cast(this->lb_buffer.size())}; } -line_buffer::gz_indexed::indexDict::indexDict(const z_stream& s, - const file_size_t size) +line_buffer::gz_indexed::indexDict:: +indexDict(const z_stream& s, const file_size_t size) { assert((s.data_type & GZ_END_OF_BLOCK_MASK)); assert(!(s.data_type & GZ_END_OF_FILE_MASK)); @@ -1374,7 +1377,7 @@ line_buffer::quiesce() } } -static ghc::filesystem::path +static std::filesystem::path line_buffer_cache_path() { return lnav::paths::workdir() / "buffer-cache"; @@ -1405,7 +1408,7 @@ line_buffer::enable_cache() .to_string(); auto cache_dir = line_buffer_cache_path() / cached_base_name.substr(0, 2); - ghc::filesystem::create_directories(cache_dir); + std::filesystem::create_directories(cache_dir); auto cached_file_name = fmt::format(FMT_STRING("{}.bin"), cached_base_name); auto cached_file_path = cache_dir / cached_file_name; @@ -1418,14 +1421,14 @@ line_buffer::enable_cache() auto fl = lnav::filesystem::file_lock(cached_file_path); auto guard = lnav::filesystem::file_lock::guard(&fl); - if (ghc::filesystem::exists(cached_done_path)) { + if (std::filesystem::exists(cached_done_path)) { log_info("%d:using existing cache file"); auto open_res = lnav::filesystem::open_file(cached_file_path, O_RDWR); if (open_res.isOk()) { this->lb_cached_fd = open_res.unwrap(); return; } - ghc::filesystem::remove(cached_done_path); + std::filesystem::remove(cached_done_path); } auto create_res = lnav::filesystem::create_file( @@ -1470,18 +1473,19 @@ void line_buffer::cleanup_cache() { (void) std::async(std::launch::async, []() { - auto now = std::chrono::system_clock::now(); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; auto cache_path = line_buffer_cache_path(); - std::vector to_remove; + std::vector to_remove; std::error_code ec; for (const auto& cache_subdir : - ghc::filesystem::directory_iterator(cache_path, ec)) + std::filesystem::directory_iterator(cache_path, ec)) { for (const auto& entry : - ghc::filesystem::directory_iterator(cache_subdir, ec)) + std::filesystem::directory_iterator(cache_subdir, ec)) { - auto mtime = ghc::filesystem::last_write_time(entry.path()); + auto mtime = std::filesystem::last_write_time(entry.path()); auto exp_time = mtime + 1h; if (now < exp_time) { continue; @@ -1493,7 +1497,7 @@ line_buffer::cleanup_cache() for (auto& entry : to_remove) { log_debug("removing compressed file cache: %s", entry.c_str()); - ghc::filesystem::remove_all(entry, ec); + std::filesystem::remove_all(entry, ec); } }); } diff --git a/src/lnav.cc b/src/lnav.cc index 32b0babd..f6e9d887 100644 --- a/src/lnav.cc +++ b/src/lnav.cc @@ -319,7 +319,7 @@ static bool append_default_files() { bool retval = true; - auto cwd = ghc::filesystem::current_path(); + auto cwd = std::filesystem::current_path(); for (const auto& path : DEFAULT_FILES) { if (access(path.c_str(), R_OK) == 0) { @@ -2135,7 +2135,9 @@ print_user_msgs(std::vector error_list, if (warning_count > 0 && !mf.mf_print_warnings && !(lnav_data.ld_flags & LNF_HEADLESS) - && (std::chrono::system_clock::now() - lnav_data.ld_last_dot_lnav_time + && (std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()} + - lnav_data.ld_last_dot_lnav_time > 24h)) { lnav::console::print( @@ -2239,7 +2241,7 @@ main(int argc, char* argv[]) curr_tz, }, }; - options_hier->foh_path_to_collection.emplace(ghc::filesystem::path("/"), + options_hier->foh_path_to_collection.emplace(std::filesystem::path("/"), options_coll); } catch (const std::runtime_error& e) { log_error("failed to setup tz: %s", e.what()); @@ -2260,7 +2262,7 @@ main(int argc, char* argv[]) auto dot_lnav_path = lnav::paths::dotlnav(); std::error_code last_write_ec; lnav_data.ld_last_dot_lnav_time - = ghc::filesystem::last_write_time(dot_lnav_path, last_write_ec); + = std::filesystem::last_write_time(dot_lnav_path, last_write_ec); ensure_dotlnav(); @@ -2625,7 +2627,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' } if (endswith(file_path, ".sql")) { - auto sql_path = ghc::filesystem::path(file_path); + auto sql_path = std::filesystem::path(file_path); auto read_res = lnav::filesystem::read_file(sql_path); if (read_res.isErr()) { lnav::console::print( @@ -2675,8 +2677,8 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' } auto file_type = file_type_result.unwrap(); - auto src_path = ghc::filesystem::path(file_path); - ghc::filesystem::path dst_name; + auto src_path = std::filesystem::path(file_path); + std::filesystem::path dst_name; if (file_type == config_file_type::CONFIG) { dst_name = src_path.filename(); } else { @@ -3031,7 +3033,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' file_loc = file_path_str.substr(hash_index); file_path_without_trailer = file_path_str.substr(0, hash_index); } - auto file_path = ghc::filesystem::path( + auto file_path = std::filesystem::path( stat(file_path_without_trailer.c_str(), &st) == 0 ? file_path_without_trailer : file_path_str); @@ -3207,7 +3209,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' } std::optional stdin_url; - ghc::filesystem::path stdin_dir; + std::filesystem::path stdin_dir; if (load_stdin && !isatty(STDIN_FILENO) && !is_dev_null(STDIN_FILENO) && !exec_stdin) { @@ -3555,7 +3557,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' { file_size_t stdin_size = 0; for (const auto& ent : - ghc::filesystem::directory_iterator(stdin_dir)) + std::filesystem::directory_iterator(stdin_dir)) { stdin_size += ent.file_size(); } diff --git a/src/lnav.hh b/src/lnav.hh index fe4e9f1d..bb1f4527 100644 --- a/src/lnav.hh +++ b/src/lnav.hh @@ -82,7 +82,7 @@ typedef enum { } lnav_status_t; using ppid_time_pair_t = std::pair; -using session_pair_t = std::pair; +using session_pair_t = std::pair; class input_state_tracker : public log_state_dumper { public: @@ -164,7 +164,7 @@ struct lnav_data_t { std::list ld_commands; bool ld_cmd_init_done; bool ld_session_loaded; - std::vector ld_config_paths; + std::vector ld_config_paths; file_collection ld_active_files; std::list ld_child_pollers; std::list> ld_files_to_front; @@ -261,7 +261,7 @@ struct lnav_data_t { lnav::func::scoped_cb ld_status_refresher; - ghc::filesystem::file_time_type ld_last_dot_lnav_time; + std::filesystem::file_time_type ld_last_dot_lnav_time; }; struct static_service {}; diff --git a/src/lnav.management_cli.cc b/src/lnav.management_cli.cc index d2662752..fcbb0d03 100644 --- a/src/lnav.management_cli.cc +++ b/src/lnav.management_cli.cc @@ -669,7 +669,7 @@ struct subcmd_format_t { auto ppath = regex101::patch_path(validate_res.unwrap(), en.re_permalink); - if (ghc::filesystem::exists(ppath)) { + if (std::filesystem::exists(ppath)) { return { console::user_message::error( attr_line_t("cannot delete regex101 entry " @@ -772,7 +772,7 @@ struct subcmd_piper_t { static perform_result_t list_action(const subcmd_piper_t&) { static const intern_string_t SRC = intern_string::lookup("piper"); - static const auto DOT_HEADER = ghc::filesystem::path(".header"); + static const auto DOT_HEADER = std::filesystem::path(".header"); struct item { lnav::piper::header i_header; @@ -784,7 +784,7 @@ struct subcmd_piper_t { std::vector items; std::error_code ec; - for (const auto& instance_dir : ghc::filesystem::directory_iterator( + for (const auto& instance_dir : std::filesystem::directory_iterator( lnav::piper::storage_path(), ec)) { if (!instance_dir.is_directory()) { @@ -798,7 +798,7 @@ struct subcmd_piper_t { instance_dir.path().filename().string()); file_size_t total_size{0}; auto hdr_path = instance_dir / DOT_HEADER; - if (ghc::filesystem::exists(hdr_path)) { + if (std::filesystem::exists(hdr_path)) { auto hdr_read_res = lnav::filesystem::read_file(hdr_path); if (hdr_read_res.isOk()) { auto parse_res @@ -822,7 +822,7 @@ struct subcmd_piper_t { } for (const auto& entry : - ghc::filesystem::directory_iterator(instance_dir.path())) + std::filesystem::directory_iterator(instance_dir.path())) { if (entry.path().filename() == DOT_HEADER) { continue; @@ -1007,7 +1007,7 @@ struct subcmd_piper_t { { std::error_code ec; - ghc::filesystem::remove_all(lnav::piper::storage_path(), ec); + std::filesystem::remove_all(lnav::piper::storage_path(), ec); if (ec) { return { lnav::console::user_message::error( diff --git a/src/lnav_commands.cc b/src/lnav_commands.cc index dd21b47f..80b824e2 100644 --- a/src/lnav_commands.cc +++ b/src/lnav_commands.cc @@ -385,7 +385,7 @@ com_set_file_timezone(exec_context& ec, const auto* tz = date::locate_zone(split_args[1]); auto pattern = split_args.size() == 2 ? line_pair->first->get_filename() - : ghc::filesystem::path(split_args[2]); + : std::filesystem::path(split_args[2]); if (!ec.ec_dry_run) { static auto& safe_options_hier @@ -485,7 +485,7 @@ com_set_file_timezone_prompt(exec_context& ec, const std::string& cmdline) log_error("cannot get timezones: %s", e.what()); } } - auto arg_path = ghc::filesystem::path(pattern_arg); + auto arg_path = std::filesystem::path(pattern_arg); auto arg_parent = lnav::filesystem::escape_path(arg_path.parent_path()); if (!endswith(arg_parent, "/")) { arg_parent += "/"; @@ -3342,7 +3342,7 @@ com_open(exec_context& ec, std::string cmdline, std::vector& args) fn_str); } } else { - auto fn = ghc::filesystem::path(fn_str); + auto fn = std::filesystem::path(fn_str); auto detect_res = detect_file_format(fn); attr_line_t al; attr_line_builder alb(al); @@ -3542,7 +3542,7 @@ com_close(exec_context& ec, std::string cmdline, std::vector& args) } auto* tc = *lnav_data.ld_view_stack.top(); - std::vector> actual_path_v; + std::vector> actual_path_v; std::vector fn_v; if (args.size() > 1) { diff --git a/src/lnav_config.cc b/src/lnav_config.cc index e951a4c7..f3bd4f3a 100644 --- a/src/lnav_config.cc +++ b/src/lnav_config.cc @@ -168,9 +168,9 @@ ensure_dotlnav() if (glob(crash_glob.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) { std::error_code ec; for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) { - auto crash_file = ghc::filesystem::path(gl->gl_pathv[lpc]); + auto crash_file = std::filesystem::path(gl->gl_pathv[lpc]); - ghc::filesystem::rename( + std::filesystem::rename( crash_file, crash_dir_path / crash_file.filename(), ec); } } @@ -241,11 +241,11 @@ install_from_git(const std::string& repo) auto git_cmd = fork_res.unwrap(); if (git_cmd.in_child()) { - if (ghc::filesystem::is_directory(local_formats_path)) { + if (std::filesystem::is_directory(local_formats_path)) { fmt::print("Updating format repo: {}\n", repo); log_perror(chdir(local_formats_path.c_str())); execlp("git", "git", "pull", nullptr); - } else if (ghc::filesystem::is_directory(local_configs_path)) { + } else if (std::filesystem::is_directory(local_configs_path)) { fmt::print("Updating config repo: {}\n", repo); log_perror(chdir(local_configs_path.c_str())); execlp("git", "git", "pull", nullptr); @@ -266,12 +266,12 @@ install_from_git(const std::string& repo) return false; } - if (ghc::filesystem::is_directory(local_formats_path) - || ghc::filesystem::is_directory(local_configs_path)) + if (std::filesystem::is_directory(local_formats_path) + || std::filesystem::is_directory(local_configs_path)) { return false; } - if (!ghc::filesystem::is_directory(local_staging_path)) { + if (!std::filesystem::is_directory(local_staging_path)) { auto um = lnav::console::user_message::error( attr_line_t("failed to install git repo: ") @@ -293,7 +293,7 @@ install_from_git(const std::string& repo) if (glob(config_path.c_str(), 0, nullptr, gl.inout()) == 0) { for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) { - auto file_path = ghc::filesystem::path{gl->gl_pathv[lpc]}; + auto file_path = std::filesystem::path{gl->gl_pathv[lpc]}; if (file_path.extension() == ".lnav") { found_lnav_file += 1; @@ -380,7 +380,7 @@ update_installs_from_git() if (glob(git_formats.c_str(), 0, nullptr, gl.inout()) == 0) { for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) { auto git_dir - = ghc::filesystem::path(gl->gl_pathv[lpc]).parent_path(); + = std::filesystem::path(gl->gl_pathv[lpc]).parent_path(); printf("Updating formats in %s\n", git_dir.c_str()); auto pull_cmd = fmt::format(FMT_STRING("cd '{}' && git pull"), @@ -1723,7 +1723,7 @@ public: static active_key_map_listener KEYMAP_LISTENER; Result -detect_config_file_type(const ghc::filesystem::path& path) +detect_config_file_type(const std::filesystem::path& path) { static const char* id_path[] = {"$schema", nullptr}; @@ -1758,7 +1758,7 @@ detect_config_file_type(const ghc::filesystem::path& path) static void load_config_from(_lnav_config& lconfig, - const ghc::filesystem::path& path, + const std::filesystem::path& path, std::vector& errors) { yajlpp_parse_context ypc(intern_string::lookup(path.string()), @@ -1856,7 +1856,7 @@ load_default_configs(struct _lnav_config& config_obj, } void -load_config(const std::vector& extra_paths, +load_config(const std::vector& extra_paths, std::vector& errors) { auto user_config = lnav::paths::dotlnav() / "config.json"; diff --git a/src/lnav_config.hh b/src/lnav_config.hh index 4a6aba60..e5b89ae0 100644 --- a/src/lnav_config.hh +++ b/src/lnav_config.hh @@ -45,7 +45,7 @@ #include "base/result.h" #include "external_opener.cfg.hh" #include "file_vtab.cfg.hh" -#include "ghc/filesystem.hpp" +#include #include "lnav_config_fwd.hh" #include "log.annotate.cfg.hh" #include "log_level.hh" @@ -144,9 +144,9 @@ enum class config_file_type { }; Result detect_config_file_type( - const ghc::filesystem::path& path); + const std::filesystem::path& path); -void load_config(const std::vector& extra_paths, +void load_config(const std::vector& extra_paths, std::vector& errors); void reset_config(const std::string& path); diff --git a/src/log.annotate.cc b/src/log.annotate.cc index 3b4ffcbe..4517a614 100644 --- a/src/log.annotate.cc +++ b/src/log.annotate.cc @@ -258,10 +258,10 @@ apply(vis_line_t vl, std::vector annos) nullptr, }; - std::vector path_v; + std::vector path_v; auto src_path - = ghc::filesystem::path( + = std::filesystem::path( iter->second.a_handler.pp_location.sl_source.to_string()) .parent_path(); path_v.push_back(src_path); diff --git a/src/log_actions.cc b/src/log_actions.cc index 02a3c915..b6a6e6a8 100644 --- a/src/log_actions.cc +++ b/src/log_actions.cc @@ -134,10 +134,10 @@ action_delegate::execute_action(const std::string& action_name) std::move(out_pipe.read_end()), false, lnav::filesystem::open_temp_file( - ghc::filesystem::temp_directory_path() + std::filesystem::temp_directory_path() / "lnav.action.XXXXXX") .map([](auto pair) { - ghc::filesystem::remove(pair.first); + std::filesystem::remove(pair.first); return pair; }) diff --git a/src/log_format.cc b/src/log_format.cc index a4c9c005..f0a464ed 100644 --- a/src/log_format.cc +++ b/src/log_format.cc @@ -2632,7 +2632,7 @@ using safe_format_header_expressions = safe::Safe; static safe_format_header_expressions format_header_exprs; std::optional -detect_mime_type(const ghc::filesystem::path& filename) +detect_mime_type(const std::filesystem::path& filename) { uint8_t buffer[1024]; size_t buffer_size = 0; diff --git a/src/log_format_ext.hh b/src/log_format_ext.hh index 1d3f76be..d025c750 100644 --- a/src/log_format_ext.hh +++ b/src/log_format_ext.hh @@ -322,7 +322,7 @@ public: GRAPH_ORDERED_FORMATS; std::set elf_source_path; - std::vector elf_format_source_order; + std::vector elf_format_source_order; std::map elf_format_sources; std::list elf_collision; factory_container elf_filename_pcre; diff --git a/src/log_format_loader.cc b/src/log_format_loader.cc index c3544793..ebc2623e 100644 --- a/src/log_format_loader.cc +++ b/src/log_format_loader.cc @@ -69,7 +69,7 @@ static log_formats_map_t LOG_FORMATS; struct loader_userdata { yajlpp_parse_context* ud_parse_context{nullptr}; std::string ud_file_schema; - ghc::filesystem::path ud_format_path; + std::filesystem::path ud_format_path; std::vector* ud_format_names{nullptr}; std::vector* ud_errors{nullptr}; }; @@ -1221,7 +1221,7 @@ format_error_reporter(const yajlpp_parse_context& ypc, } std::vector -load_format_file(const ghc::filesystem::path& filename, +load_format_file(const std::filesystem::path& filename, std::vector& errors) { std::vector retval; @@ -1310,7 +1310,7 @@ load_format_file(const ghc::filesystem::path& filename, } static void -load_from_path(const ghc::filesystem::path& path, +load_from_path(const std::filesystem::path& path, std::vector& errors) { auto format_path = path / "formats/*/*.json"; @@ -1319,7 +1319,7 @@ load_from_path(const ghc::filesystem::path& path, log_info("loading formats from path: %s", format_path.c_str()); if (glob(format_path.c_str(), 0, nullptr, gl.inout()) == 0) { for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) { - auto filepath = ghc::filesystem::path(gl->gl_pathv[lpc]); + auto filepath = std::filesystem::path(gl->gl_pathv[lpc]); if (startswith(filepath.filename().string(), "config.")) { log_info(" not loading config as format: %s", @@ -1343,7 +1343,7 @@ load_from_path(const ghc::filesystem::path& path, } void -load_formats(const std::vector& extra_paths, +load_formats(const std::vector& extra_paths, std::vector& errors) { auto default_source = lnav::paths::dotlnav() / "default"; @@ -1479,7 +1479,7 @@ load_formats(const std::vector& extra_paths, static void exec_sql_in_path(sqlite3* db, const std::map& global_vars, - const ghc::filesystem::path& path, + const std::filesystem::path& path, std::vector& errors) { auto format_path = path / "formats/*/*.sql"; @@ -1488,7 +1488,7 @@ exec_sql_in_path(sqlite3* db, log_info("executing SQL files in path: %s", format_path.c_str()); if (glob(format_path.c_str(), 0, nullptr, gl.inout()) == 0) { for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) { - auto filename = ghc::filesystem::path(gl->gl_pathv[lpc]); + auto filename = std::filesystem::path(gl->gl_pathv[lpc]); auto read_res = lnav::filesystem::read_file(filename); if (read_res.isOk()) { @@ -1511,7 +1511,7 @@ exec_sql_in_path(sqlite3* db, void load_format_extra(sqlite3* db, const std::map& global_vars, - const std::vector& extra_paths, + const std::vector& extra_paths, std::vector& errors) { for (const auto& extra_path : extra_paths) { @@ -1585,7 +1585,7 @@ extract_metadata_from_file(struct script_metadata& meta_inout) } static void -find_format_in_path(const ghc::filesystem::path& path, +find_format_in_path(const std::filesystem::path& path, available_scripts& scripts) { for (auto format_path : @@ -1612,7 +1612,7 @@ find_format_in_path(const ghc::filesystem::path& path, } void -find_format_scripts(const std::vector& extra_paths, +find_format_scripts(const std::vector& extra_paths, available_scripts& scripts) { for (const auto& extra_path : extra_paths) { diff --git a/src/log_format_loader.hh b/src/log_format_loader.hh index 161ac88c..e9806a54 100644 --- a/src/log_format_loader.hh +++ b/src/log_format_loader.hh @@ -39,16 +39,16 @@ #include "base/intern_string.hh" #include "base/lnav.console.hh" -#include "ghc/filesystem.hpp" +#include #include "shlex.resolver.hh" class log_vtab_manager; std::vector load_format_file( - const ghc::filesystem::path& filename, + const std::filesystem::path& filename, std::vector& errors); -void load_formats(const std::vector& extra_paths, +void load_formats(const std::vector& extra_paths, std::vector& errors); void load_format_vtabs(log_vtab_manager* vtab_manager, @@ -56,11 +56,11 @@ void load_format_vtabs(log_vtab_manager* vtab_manager, void load_format_extra(sqlite3* db, const std::map& global_vars, - const std::vector& extra_paths, + const std::vector& extra_paths, std::vector& errors); struct script_metadata { - ghc::filesystem::path sm_path; + std::filesystem::path sm_path; std::string sm_name; std::string sm_synopsis; std::string sm_description; @@ -72,7 +72,7 @@ struct available_scripts { std::map> as_scripts; }; -void find_format_scripts(const std::vector& extra_paths, +void find_format_scripts(const std::vector& extra_paths, available_scripts& scripts); extern const struct json_path_container format_handlers; diff --git a/src/logfile.cc b/src/logfile.cc index ee43efbe..082e0496 100644 --- a/src/logfile.cc +++ b/src/logfile.cc @@ -70,7 +70,7 @@ static const typed_json_path_container file_header_handlers }; Result, std::string> -logfile::open(ghc::filesystem::path filename, +logfile::open(std::filesystem::path filename, const logfile_open_options& loo, auto_fd fd) { @@ -79,7 +79,7 @@ logfile::open(ghc::filesystem::path filename, auto lf = std::shared_ptr(new logfile(std::move(filename), loo)); memset(&lf->lf_stat, 0, sizeof(lf->lf_stat)); - ghc::filesystem::path resolved_path; + std::filesystem::path resolved_path; if (!fd.has_value()) { auto rp_res = lnav::filesystem::realpath(lf->lf_filename); @@ -196,7 +196,7 @@ logfile::open(ghc::filesystem::path filename, return Ok(lf); } -logfile::logfile(ghc::filesystem::path filename, +logfile::logfile(std::filesystem::path filename, const logfile_open_options& loo) : lf_filename(std::move(filename)), lf_options(loo) { @@ -1297,7 +1297,7 @@ logfile::reobserve_from(iterator iter) } } -ghc::filesystem::path +std::filesystem::path logfile::get_path() const { return this->lf_filename; @@ -1420,7 +1420,7 @@ logfile::set_filename(const std::string& filename) { if (this->lf_filename != filename) { this->lf_filename = filename; - ghc::filesystem::path p(filename); + std::filesystem::path p(filename); this->lf_basename = p.filename(); } } diff --git a/src/logfile.hh b/src/logfile.hh index 9aca06a4..788e4d5e 100644 --- a/src/logfile.hh +++ b/src/logfile.hh @@ -49,7 +49,7 @@ #include "bookmarks.hh" #include "byte_array.hh" #include "file_options.hh" -#include "ghc/filesystem.hpp" +#include #include "line_buffer.hh" #include "log_format_fwd.hh" #include "logfile_fwd.hh" @@ -114,7 +114,7 @@ public: * descriptor needs to be seekable. */ static Result, std::string> open( - ghc::filesystem::path filename, + std::filesystem::path filename, const logfile_open_options& loo, auto_fd fd = auto_fd{}); @@ -122,13 +122,13 @@ public: const logfile_activity& get_activity() const { return this->lf_activity; } - std::optional get_actual_path() const + std::optional get_actual_path() const { return this->lf_actual_path; } /** @return The filename as given in the constructor. */ - const ghc::filesystem::path& get_filename() const + const std::filesystem::path& get_filename() const { return this->lf_filename; } @@ -371,7 +371,7 @@ public: return true; } - ghc::filesystem::path get_path() const override; + std::filesystem::path get_path() const override; enum class note_type { indexing_disabled, @@ -435,16 +435,16 @@ protected: void set_format_base_time(log_format* lf); private: - logfile(ghc::filesystem::path filename, const logfile_open_options& loo); + logfile(std::filesystem::path filename, const logfile_open_options& loo); bool file_options_have_changed(); - ghc::filesystem::path lf_filename; + std::filesystem::path lf_filename; logfile_open_options lf_options; logfile_activity lf_activity; bool lf_named_file{true}; bool lf_valid_filename{true}; - std::optional lf_actual_path; + std::optional lf_actual_path; std::string lf_basename; std::string lf_content_id; struct stat lf_stat {}; diff --git a/src/logfile_fwd.hh b/src/logfile_fwd.hh index 3c1792fa..66447b2b 100644 --- a/src/logfile_fwd.hh +++ b/src/logfile_fwd.hh @@ -35,6 +35,8 @@ #include #include +#include + #include "base/auto_fd.hh" #include "file_format.hh" #include "piper.looper.hh" diff --git a/src/md2attr_line.cc b/src/md2attr_line.cc index 4da2e034..04e56133 100644 --- a/src/md2attr_line.cc +++ b/src/md2attr_line.cc @@ -714,7 +714,7 @@ md2attr_line::to_attr_line(const pugi::xml_node& doc) if (img_alt) { link_label = img_alt.value(); } else if (img_src) { - link_label = ghc::filesystem::path(img_src.value()) + link_label = std::filesystem::path(img_src.value()) .filename() .string(); } else { @@ -726,14 +726,14 @@ md2attr_line::to_attr_line(const pugi::xml_node& doc) if (is_url(src_value)) { src_href = src_value; } else { - auto src_path = ghc::filesystem::path(src_value); + auto src_path = std::filesystem::path(src_value); std::error_code ec; if (src_path.is_relative() && this->ml_source_path) { src_path = this->ml_source_path.value().parent_path() / src_path; } - auto canon_path = ghc::filesystem::canonical(src_path, ec); + auto canon_path = std::filesystem::canonical(src_path, ec); if (!ec) { src_path = canon_path; } @@ -1074,7 +1074,7 @@ md2attr_line::append_url_footnote(std::string href_str) last_block.append(to_superscript(this->ml_footnotes.size() + 1)); this->ml_last_superscript_index = last_block.length(); if (this->ml_source_path && href_str.find(':') == std::string::npos) { - auto link_path = ghc::filesystem::absolute( + auto link_path = std::filesystem::absolute( this->ml_source_path.value().parent_path() / href_str); href_str = fmt::format(FMT_STRING("file://{}"), link_path.string()); diff --git a/src/md2attr_line.hh b/src/md2attr_line.hh index 809bcb20..9dfaab09 100644 --- a/src/md2attr_line.hh +++ b/src/md2attr_line.hh @@ -31,7 +31,7 @@ #define lnav_md2attr_line_hh #include "base/attr_line.hh" -#include "ghc/filesystem.hpp" +#include #include "md4cpp.hh" namespace pugi { @@ -42,7 +42,7 @@ class md2attr_line : public md4cpp::typed_event_handler { public: md2attr_line() { this->ml_blocks.resize(1); } - md2attr_line& with_source_path(std::optional path) + md2attr_line& with_source_path(std::optional path) { this->ml_source_path = path; return *this; @@ -83,7 +83,7 @@ private: void flush_footnotes(); attr_line_t to_attr_line(const pugi::xml_node& doc); - std::optional ml_source_path; + std::optional ml_source_path; std::vector ml_blocks; std::vector ml_list_stack; std::vector ml_tables; diff --git a/src/piper.looper.cc b/src/piper.looper.cc index 1f29bdf8..807903a2 100644 --- a/src/piper.looper.cc +++ b/src/piper.looper.cc @@ -189,7 +189,7 @@ environ_to_map() looper:: looper(std::string name, auto_fd stdout_fd, auto_fd stderr_fd, options opts) - : l_name(std::move(name)), l_cwd(ghc::filesystem::current_path().string()), + : l_name(std::move(name)), l_cwd(std::filesystem::current_path().string()), l_env(environ_to_map()), l_stdout(std::move(stdout_fd)), l_stderr(std::move(stderr_fd)), l_options(opts) { @@ -202,8 +202,8 @@ looper(std::string name, auto_fd stdout_fd, auto_fd stderr_fd, options opts) hasher().update(getmstime()).update(l_name).to_string(), count); count += 1; - } while (ghc::filesystem::exists(this->l_out_dir)); - ghc::filesystem::create_directories(this->l_out_dir); + } while (std::filesystem::exists(this->l_out_dir)); + std::filesystem::create_directories(this->l_out_dir); this->l_future = std::async(std::launch::async, [this]() { this->loop(); }); } @@ -638,7 +638,7 @@ looper::loop() / fmt::format(FMT_STRING("out.{}.{}"), os.os_hash_id, rotate_count % cfg.c_rotations); - ghc::filesystem::rename(tmp_path, out_path); + std::filesystem::rename(tmp_path, out_path); } ssize_t wrc; @@ -724,14 +724,15 @@ cleanup() { (void) std::async(std::launch::async, []() { const auto& cfg = injector::get(); - auto now = std::chrono::system_clock::now(); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; auto cache_path = storage_path(); - std::vector to_remove; + std::vector to_remove; for (const auto& cache_subdir : - ghc::filesystem::directory_iterator(cache_path)) + std::filesystem::directory_iterator(cache_path)) { - auto mtime = ghc::filesystem::last_write_time(cache_subdir.path()); + auto mtime = std::filesystem::last_write_time(cache_subdir.path()); auto exp_time = mtime + cfg.c_ttl; if (now < exp_time) { continue; @@ -740,9 +741,9 @@ cleanup() bool is_recent = false; for (const auto& entry : - ghc::filesystem::directory_iterator(cache_subdir)) + std::filesystem::directory_iterator(cache_subdir)) { - auto mtime = ghc::filesystem::last_write_time(entry.path()); + auto mtime = std::filesystem::last_write_time(entry.path()); auto exp_time = mtime + cfg.c_ttl; if (now < exp_time) { is_recent = true; @@ -756,7 +757,7 @@ cleanup() for (auto& entry : to_remove) { log_debug("removing piper directory: %s", entry.c_str()); - ghc::filesystem::remove_all(entry); + std::filesystem::remove_all(entry); } }); } diff --git a/src/piper.looper.hh b/src/piper.looper.hh index 6ff428bc..d1e6c90f 100644 --- a/src/piper.looper.hh +++ b/src/piper.looper.hh @@ -37,7 +37,7 @@ #include "base/auto_fd.hh" #include "base/piper.file.hh" #include "base/result.h" -#include "ghc/filesystem.hpp" +#include #include "safe/safe.h" #include "yajlpp/yajlpp_def.hh" @@ -79,9 +79,9 @@ public: std::string get_name() const { return this->l_name; } - ghc::filesystem::path get_out_dir() const { return this->l_out_dir; } + std::filesystem::path get_out_dir() const { return this->l_out_dir; } - ghc::filesystem::path get_out_pattern() const + std::filesystem::path get_out_pattern() const { return this->l_out_dir / "out.*"; } @@ -124,7 +124,7 @@ private: const std::string l_name; const std::string l_cwd; const std::map l_env; - ghc::filesystem::path l_out_dir; + std::filesystem::path l_out_dir; auto_fd l_stdout; auto_fd l_stderr; options l_options; @@ -144,12 +144,12 @@ public: std::string get_name() const { return this->h_looper->get_name(); } - ghc::filesystem::path get_out_dir() const + std::filesystem::path get_out_dir() const { return this->h_looper->get_out_dir(); } - ghc::filesystem::path get_out_pattern() const + std::filesystem::path get_out_pattern() const { return this->h_looper->get_out_pattern(); } diff --git a/src/readline_callbacks.cc b/src/readline_callbacks.cc index e9b3c517..03b7e2f4 100644 --- a/src/readline_callbacks.cc +++ b/src/readline_callbacks.cc @@ -1015,7 +1015,7 @@ rl_callback_int(readline_curses* rc, bool is_alt) case ln_mode_t::EXEC: { std::error_code errc; - ghc::filesystem::create_directories(lnav::paths::workdir(), errc); + std::filesystem::create_directories(lnav::paths::workdir(), errc); auto open_temp_res = lnav::filesystem::open_temp_file( lnav::paths::workdir() / "exec.XXXXXX"); diff --git a/src/readline_curses.cc b/src/readline_curses.cc index d1dee6a4..076182b1 100644 --- a/src/readline_curses.cc +++ b/src/readline_curses.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -640,9 +641,10 @@ readline_context::command_complete(int count, int key) return rl_insert(count, key); } -readline_context::readline_context(std::string name, - readline_context::command_map_t* commands, - bool case_sensitive) +readline_context:: +readline_context(std::string name, + readline_context::command_map_t* commands, + bool case_sensitive) : rc_name(std::move(name)), rc_case_sensitive(case_sensitive), rc_quote_chars("\"'"), rc_highlighter(nullptr) { @@ -723,8 +725,8 @@ readline_context::save() hs = nullptr; } -readline_curses::readline_curses( - std::shared_ptr supervisor) +readline_curses:: +readline_curses(std::shared_ptr supervisor) : pollable(supervisor, pollable::category::interactive), rc_focus(noop_func{}), rc_change(noop_func{}), rc_perform(noop_func{}), rc_alt_perform(noop_func{}), rc_timeout(noop_func{}), @@ -734,7 +736,8 @@ readline_curses::readline_curses( { } -readline_curses::~readline_curses() +readline_curses::~ +readline_curses() { this->rc_pty[RCF_MASTER].reset(); this->rc_command_pipe[RCF_MASTER].reset(); @@ -849,16 +852,16 @@ readline_curses::start() throw error(errno); } - auto slave_path = ghc::filesystem::path(slave_path_str); + auto slave_path = std::filesystem::path(slave_path_str); std::error_code ec; - if (!ghc::filesystem::exists(slave_path, ec)) { + if (!std::filesystem::exists(slave_path, ec)) { log_warning("ptsname_r() result does not exist -- %s", slave_path_str); #ifdef TIOCGPTN int ptn = 0; if (ioctl(this->rc_pty[RCF_MASTER], TIOCGPTN, &ptn) == 0) { snprintf( slave_path_str, sizeof(slave_path_str), "/dev/ttyp%d", ptn); - slave_path = ghc::filesystem::path(slave_path_str); + slave_path = std::filesystem::path(slave_path_str); log_warning("... trying %s", slave_path.c_str()); } #endif diff --git a/src/readline_possibilities.cc b/src/readline_possibilities.cc index 5a4e33e6..3d942e46 100644 --- a/src/readline_possibilities.cc +++ b/src/readline_possibilities.cc @@ -479,7 +479,7 @@ add_config_possibilities() visited.insert(named_cap.get_name().to_string()); } - ghc::filesystem::path path_obj(path); + std::filesystem::path path_obj(path); rc->add_possibility(ln_mode_t::COMMAND, named_cap.get_name().to_string(), path_obj.parent_path().filename().string()); diff --git a/src/regex101.client.cc b/src/regex101.client.cc index 5806b239..b19d09a9 100644 --- a/src/regex101.client.cc +++ b/src/regex101.client.cc @@ -34,7 +34,7 @@ #include "base/itertools.hh" #include "config.h" #include "curl_looper.hh" -#include "ghc/filesystem.hpp" +#include #include "yajlpp/yajlpp_def.hh" namespace regex101 { @@ -80,7 +80,7 @@ static const typed_json_path_container RESPONSE_HANDLERS = { yajlpp::property_handler("version").for_field(&upsert_response::cr_version), }; -static const ghc::filesystem::path REGEX101_BASE_URL +static const std::filesystem::path REGEX101_BASE_URL = "https://regex101.com/api/regex"; static const char* USER_AGENT = "lnav/" PACKAGE_VERSION; diff --git a/src/regex101.import.cc b/src/regex101.import.cc index c0e29845..1c42d1e9 100644 --- a/src/regex101.import.cc +++ b/src/regex101.import.cc @@ -47,7 +47,7 @@ static const std::set SUPPORTED_FLAVORS = { "pcre2", }; -Result +Result regex101::import(const std::string& url, const std::string& name, const std::string& pat_name) @@ -124,7 +124,7 @@ regex101::import(const std::string& url, auto format_path = lnav::paths::dotlnav() / "formats" / "installed" / format_filename; - if (ghc::filesystem::exists(format_path)) { + if (std::filesystem::exists(format_path)) { return Err(lnav::console::user_message::error( attr_line_t("unable to import: ") .append(lnav::roles::file(url))) @@ -270,7 +270,7 @@ regex101::import(const std::string& url, return Ok(format_path); } -ghc::filesystem::path +std::filesystem::path regex101::patch_path(const external_log_format* format, const std::string& permalink) { @@ -287,7 +287,7 @@ regex101::patch_path(const external_log_format* format, fmt::format(FMT_STRING("regex101-{}.json"), permalink)); } -Result +Result regex101::patch(const external_log_format* format, const std::string& pat_name, const regex101::client::entry& entry) diff --git a/src/regex101.import.hh b/src/regex101.import.hh index cabaa0b5..597c5d42 100644 --- a/src/regex101.import.hh +++ b/src/regex101.import.hh @@ -33,21 +33,21 @@ #include #include "base/lnav.console.hh" -#include "ghc/filesystem.hpp" +#include #include "log_format_ext.hh" #include "regex101.client.hh" namespace regex101 { -Result import( +Result import( const std::string& url, const std::string& name, const std::string& pat_name); -ghc::filesystem::path patch_path(const external_log_format* format, +std::filesystem::path patch_path(const external_log_format* format, const std::string& permalink); -Result patch( +Result patch( const external_log_format* format, const std::string& pat_name, const regex101::client::entry& entry); diff --git a/src/session.export.cc b/src/session.export.cc index 91287a69..3523abb2 100644 --- a/src/session.export.cc +++ b/src/session.export.cc @@ -113,14 +113,14 @@ struct from_sqlite { namespace lnav { namespace session { -static std::optional -find_container_dir(ghc::filesystem::path file_path) +static std::optional +find_container_dir(std::filesystem::path file_path) { - if (!ghc::filesystem::exists(file_path)) { + if (!std::filesystem::exists(file_path)) { return std::nullopt; } - std::optional dir_with_last_readme; + std::optional dir_with_last_readme; while (file_path.has_parent_path() && file_path != file_path.root_directory()) @@ -130,7 +130,7 @@ find_container_dir(ghc::filesystem::path file_path) std::error_code ec; for (const auto& entry : - ghc::filesystem::directory_iterator(parent, ec)) + std::filesystem::directory_iterator(parent, ec)) { if (!entry.is_regular_file()) { continue; @@ -281,12 +281,12 @@ SELECT content_id, format, time_offset FROM lnav_file } auto file_path_str = name_pair.first; - auto file_path = ghc::filesystem::path(file_path_str); + auto file_path = std::filesystem::path(file_path_str); auto container_path_opt = find_container_dir(file_path); if (container_path_opt) { auto container_parent = container_path_opt.value().parent_path(); auto file_container_path - = ghc::filesystem::relative(file_path, container_parent) + = std::filesystem::relative(file_path, container_parent) .string(); file_containers[container_parent.string()].push_back( file_container_path); @@ -474,7 +474,7 @@ SELECT content_id, format, time_offset FROM lnav_file } auto container_parent = container_path_opt.value().parent_path(); - auto file_container_path = ghc::filesystem::relative( + auto file_container_path = std::filesystem::relative( ld->get_file_ptr()->get_path(), container_parent); fmt::print(file, FMT_STRING(":hide-file */{}\n"), diff --git a/src/static_file_vtab.cc b/src/static_file_vtab.cc index a953a8d7..df95b286 100644 --- a/src/static_file_vtab.cc +++ b/src/static_file_vtab.cc @@ -37,7 +37,7 @@ #include "base/fs_util.hh" #include "base/lnav_log.hh" #include "config.h" -#include "ghc/filesystem.hpp" +#include #include "lnav.hh" #include "vtab_module.hh" @@ -49,7 +49,7 @@ struct static_file_vtab { }; struct static_file_info { - ghc::filesystem::path sfi_path; + std::filesystem::path sfi_path; }; struct sf_vtab_cursor { @@ -124,13 +124,13 @@ sfvt_destroy(sqlite3_vtab* p_vt) static int sfvt_next(sqlite3_vtab_cursor* cur); static void -find_static_files(sf_vtab_cursor* p_cur, const ghc::filesystem::path& dir) +find_static_files(sf_vtab_cursor* p_cur, const std::filesystem::path& dir) { auto& file_map = p_cur->vc_files; std::error_code ec; for (const auto& format_dir_entry : - ghc::filesystem::directory_iterator(dir, ec)) + std::filesystem::directory_iterator(dir, ec)) { if (!format_dir_entry.is_directory()) { continue; @@ -138,10 +138,10 @@ find_static_files(sf_vtab_cursor* p_cur, const ghc::filesystem::path& dir) auto format_static_files_dir = format_dir_entry.path() / "static-files"; log_debug("format static files: %s", format_static_files_dir.c_str()); for (const auto& static_file_entry : - ghc::filesystem::recursive_directory_iterator( + std::filesystem::recursive_directory_iterator( format_static_files_dir, ec)) { - auto rel_path = ghc::filesystem::relative(static_file_entry.path(), + auto rel_path = std::filesystem::relative(static_file_entry.path(), format_static_files_dir); file_map[rel_path.string()] = {static_file_entry.path()}; diff --git a/src/tailer/drive_tailer.cc b/src/tailer/drive_tailer.cc index 18ead430..7128c785 100644 --- a/src/tailer/drive_tailer.cc +++ b/src/tailer/drive_tailer.cc @@ -34,7 +34,7 @@ #include "base/auto_fd.hh" #include "base/auto_pid.hh" #include "config.h" -#include "ghc/filesystem.hpp" +#include #include "line_buffer.hh" #include "tailerpp.hh" @@ -102,7 +102,7 @@ main(int argc, char* const* argv) err_pipe.after_fork(child.in()); if (child.in_child()) { - auto this_exe = ghc::filesystem::path(argv[0]); + auto this_exe = std::filesystem::path(argv[0]); auto exe_dir = this_exe.parent_path(); auto tailer_exe = exe_dir / "tailer"; @@ -165,8 +165,8 @@ main(int argc, char* const* argv) pe.pe_path.c_str(), pe.pe_msg.c_str()); - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(pe.pe_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(pe.pe_path)) .relative_path(); printf("removing %s\n", remote_path.c_str()); @@ -177,8 +177,8 @@ main(int argc, char* const* argv) pob.pob_offset, pob.pob_length); - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(pob.pob_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(pob.pob_path)) .relative_path(); #if 0 auto local_path = tmppath / remote_path; @@ -196,7 +196,7 @@ main(int argc, char* const* argv) struct stat st; if (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) { - ghc::filesystem::remove_all(local_path); + std::filesystem::remove_all(local_path); send_packet(to_child.get(), TPT_NEED_BLOCK, TPPT_STRING, pob.pob_path.c_str(), @@ -222,7 +222,7 @@ main(int argc, char* const* argv) return; } } else if (bytes_read == -1) { - ghc::filesystem::remove_all(local_path); + std::filesystem::remove_all(local_path); } send_packet(to_child.get(), TPT_NEED_BLOCK, @@ -234,11 +234,11 @@ main(int argc, char* const* argv) #if 0 //printf("got a tail: %s %lld %ld\n", ptb.ptb_path.c_str(), // ptb.ptb_offset, ptb.ptb_bits.size()); - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(ptb.ptb_path)).relative_path(); + auto remote_path = std::filesystem::absolute( + std::filesystem::path(ptb.ptb_path)).relative_path(); auto local_path = tmppath / remote_path; - ghc::filesystem::create_directories(local_path.parent_path()); + std::filesystem::create_directories(local_path.parent_path()); auto fd = auto_fd( open(local_path.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0600)); diff --git a/src/tailer/tailer.looper.cc b/src/tailer/tailer.looper.cc index 9986653e..c0808b36 100644 --- a/src/tailer/tailer.looper.cc +++ b/src/tailer/tailer.looper.cc @@ -448,18 +448,18 @@ tailer::looper::host_tailer::for_host(const std::string& netloc) std::move(err_pipe.read_end()))); } -static ghc::filesystem::path +static std::filesystem::path remote_cache_path() { return lnav::paths::workdir() / "remotes"; } -ghc::filesystem::path +std::filesystem::path tailer::looper::host_tailer::tmp_path() { auto local_path = remote_cache_path(); - ghc::filesystem::create_directories(local_path); + std::filesystem::create_directories(local_path); auto_mem resolved_path; resolved_path = realpath(local_path.c_str(), nullptr); @@ -478,11 +478,12 @@ scrub_netloc(const std::string& netloc) return std::regex_replace(netloc, TO_SCRUB, "_"); } -tailer::looper::host_tailer::host_tailer(const std::string& netloc, - auto_pid child, - auto_fd to_child, - auto_fd from_child, - auto_fd err_from_child) +tailer::looper::host_tailer:: +host_tailer(const std::string& netloc, + auto_pid child, + auto_fd to_child, + auto_fd from_child, + auto_fd err_from_child) : isc::service(netloc), ht_netloc(netloc), ht_local_path(tmp_path() / scrub_netloc(netloc)), ht_error_reader([netloc, @@ -578,9 +579,9 @@ tailer::looper::host_tailer::loop_body() this->ht_cycle_count += 1; if (this->ht_cycle_count % TOUCH_FREQ == 0) { - auto now - = ghc::filesystem::file_time_type{std::chrono::system_clock::now()}; - ghc::filesystem::last_write_time(this->ht_local_path, now); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; + std::filesystem::last_write_time(this->ht_local_path, now); } auto& conn = this->ht_state.get(); @@ -648,14 +649,14 @@ tailer::looper::host_tailer::loop_body() } } - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(pe.pe_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(pe.pe_path)) .relative_path(); auto local_path = this->ht_local_path / remote_path; log_debug("removing %s", local_path.c_str()); this->ht_active_files.erase(local_path); - ghc::filesystem::remove_all(local_path); + std::filesystem::remove_all(local_path); if (conn.c_desired_paths.empty() && conn.c_child_paths.empty()) { @@ -706,8 +707,8 @@ tailer::looper::host_tailer::loop_body() update_tailer_description( this->ht_netloc, conn.c_desired_paths, this->ht_uname); - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(pob.pob_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(pob.pob_path)) .relative_path(); auto local_path = this->ht_local_path / remote_path; auto open_res @@ -769,7 +770,7 @@ tailer::looper::host_tailer::loop_body() if (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) { log_debug("path changed, sending need block"); - ghc::filesystem::remove_all(local_path); + std::filesystem::remove_all(local_path); send_packet(conn.ht_to_child.get(), TPT_NEED_BLOCK, TPPT_STRING, @@ -808,7 +809,7 @@ tailer::looper::host_tailer::loop_body() log_debug( "unable to read file, sending need block -- %s", strerror(errno)); - ghc::filesystem::remove_all(local_path); + std::filesystem::remove_all(local_path); break; } if (bytes_read == 0) { @@ -847,8 +848,8 @@ tailer::looper::host_tailer::loop_body() return std::move(this->ht_state); }, [&](const tailer::packet_tail_block& ptb) { - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(ptb.ptb_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(ptb.ptb_path)) .relative_path(); auto local_path = this->ht_local_path / remote_path; @@ -856,7 +857,7 @@ tailer::looper::host_tailer::loop_body() ptb.ptb_offset, ptb.ptb_bits.size(), local_path.c_str()); - ghc::filesystem::create_directories(local_path.parent_path()); + std::filesystem::create_directories(local_path.parent_path()); auto create_res = lnav::filesystem::create_file( local_path, O_WRONLY | O_APPEND | O_CREAT, 0600); @@ -869,10 +870,10 @@ tailer::looper::host_tailer::loop_body() ptb.ptb_bits.data(), ptb.ptb_bits.size(), ptb.ptb_offset); - auto mtime = ghc::filesystem::file_time_type{ + auto mtime = std::filesystem::file_time_type{ std::chrono::seconds{ptb.ptb_mtime}}; // XXX This isn't atomic with the write... - ghc::filesystem::last_write_time(local_path, mtime); + std::filesystem::last_write_time(local_path, mtime); } return std::move(this->ht_state); }, @@ -935,11 +936,11 @@ tailer::looper::host_tailer::loop_body() return std::move(this->ht_state); }, [&](const tailer::packet_link& pl) { - auto remote_path = ghc::filesystem::absolute( - ghc::filesystem::path(pl.pl_path)) + auto remote_path = std::filesystem::absolute( + std::filesystem::path(pl.pl_path)) .relative_path(); auto local_path = this->ht_local_path / remote_path; - auto remote_link_path = ghc::filesystem::path(pl.pl_link_value); + auto remote_link_path = std::filesystem::path(pl.pl_link_value); std::string link_path; if (remote_link_path.is_absolute()) { @@ -954,8 +955,8 @@ tailer::looper::host_tailer::loop_body() log_debug("symlinking %s -> %s", local_path.c_str(), link_path.c_str()); - ghc::filesystem::create_directories(local_path.parent_path()); - ghc::filesystem::remove_all(local_path); + std::filesystem::create_directories(local_path.parent_path()); + std::filesystem::remove_all(local_path); if (symlink(link_path.c_str(), local_path.c_str()) < 0) { log_error("symlink failed: %s", strerror(errno)); } @@ -1169,16 +1170,17 @@ void tailer::cleanup_cache() { (void) std::async(std::launch::async, []() { - auto now = std::chrono::system_clock::now(); + auto now = std::filesystem::file_time_type{ + std::chrono::system_clock::now().time_since_epoch()}; auto cache_path = remote_cache_path(); const auto& cfg = injector::get(); - std::vector to_remove; + std::vector to_remove; log_debug("cache-ttl %d", cfg.c_cache_ttl.count()); for (const auto& entry : - ghc::filesystem::directory_iterator(cache_path)) + std::filesystem::directory_iterator(cache_path)) { - auto mtime = ghc::filesystem::last_write_time(entry.path()); + auto mtime = std::filesystem::last_write_time(entry.path()); auto exp_time = mtime + cfg.c_cache_ttl; if (now < exp_time) { continue; @@ -1189,7 +1191,7 @@ tailer::cleanup_cache() for (auto& entry : to_remove) { log_debug("removing cached remote: %s", entry.c_str()); - ghc::filesystem::remove_all(entry); + std::filesystem::remove_all(entry); } }); } diff --git a/src/tailer/tailer.looper.hh b/src/tailer/tailer.looper.hh index 1bf84d90..3c66c034 100644 --- a/src/tailer/tailer.looper.hh +++ b/src/tailer/tailer.looper.hh @@ -38,7 +38,7 @@ #include "base/auto_pid.hh" #include "base/isc.hh" #include "base/network.tcp.hh" -#include "ghc/filesystem.hpp" +#include #include "mapbox/variant.hpp" namespace tailer { @@ -101,7 +101,7 @@ private: mstime_t current_time) const override; private: - static ghc::filesystem::path tmp_path(); + static std::filesystem::path tmp_path(); std::string get_display_path(const std::string& remote_path) const; @@ -125,8 +125,8 @@ private: const std::string ht_netloc; std::string ht_uname; - const ghc::filesystem::path ht_local_path; - std::set ht_active_files; + const std::filesystem::path ht_local_path; + std::set ht_active_files; std::vector ht_error_queue; std::thread ht_error_reader; state_v ht_state{disconnected()}; diff --git a/src/text_anonymizer.cc b/src/text_anonymizer.cc index 2770dc13..ff383de4 100644 --- a/src/text_anonymizer.cc +++ b/src/text_anonymizer.cc @@ -37,7 +37,7 @@ #include "config.h" #include "data_scanner.hh" #include "diseases-json.h" -#include "ghc/filesystem.hpp" +#include #include "hasher.hh" #include "pcrepp/pcre2pp.hh" #include "words-json.h" @@ -205,8 +205,8 @@ text_anonymizer::next(string_fragment line) cu, CURLUPART_PATH, url_part.out(), CURLU_URLDECODE) == CURLUE_OK) { - ghc::filesystem::path url_path(url_part.in()); - ghc::filesystem::path anon_path; + std::filesystem::path url_path(url_part.in()); + std::filesystem::path anon_path; for (const auto& comp : url_path) { if (comp == comp.root_path()) { @@ -290,8 +290,8 @@ text_anonymizer::next(string_fragment line) break; } case DT_PATH: { - ghc::filesystem::path inp_path(tok_res->to_string()); - ghc::filesystem::path anon_path; + std::filesystem::path inp_path(tok_res->to_string()); + std::filesystem::path anon_path; for (const auto& comp : inp_path) { auto comp_str = comp.string(); diff --git a/src/text_format.cc b/src/text_format.cc index fe00cbc9..2fd96be9 100644 --- a/src/text_format.cc +++ b/src/text_format.cc @@ -40,16 +40,16 @@ text_format_t detect_text_format(string_fragment sf, - std::optional path) + std::optional path) { - static const std::set FILTER_EXTS = { + static const std::set FILTER_EXTS = { ".bz2", ".gz", ".lzma", ".xz", ".zst", }; - static const auto C_EXTS = std::set{ + static const auto C_EXTS = std::set{ ".h", ".hh", ".hpp", @@ -58,17 +58,17 @@ detect_text_format(string_fragment sf, ".cpp", ".tpp", }; - static const auto PY_EXT = ghc::filesystem::path(".py"); - static const auto RS_EXT = ghc::filesystem::path(".rs"); - static const auto JAVA_EXT = ghc::filesystem::path(".java"); - static const auto TOML_EXT = ghc::filesystem::path(".toml"); - static const auto XML_EXT = ghc::filesystem::path(".xml"); - static const auto YAML_EXT = ghc::filesystem::path(".yaml"); - static const auto YML_EXT = ghc::filesystem::path(".yml"); - static const auto MAKEFILE_STEM = ghc::filesystem::path("Makefile"); - static const auto MD_EXT = ghc::filesystem::path(".md"); - static const auto MARKDOWN_EXT = ghc::filesystem::path(".markdown"); - static const auto SH_EXT = ghc::filesystem::path(".sh"); + static const auto PY_EXT = std::filesystem::path(".py"); + static const auto RS_EXT = std::filesystem::path(".rs"); + static const auto JAVA_EXT = std::filesystem::path(".java"); + static const auto TOML_EXT = std::filesystem::path(".toml"); + static const auto XML_EXT = std::filesystem::path(".xml"); + static const auto YAML_EXT = std::filesystem::path(".yaml"); + static const auto YML_EXT = std::filesystem::path(".yml"); + static const auto MAKEFILE_STEM = std::filesystem::path("Makefile"); + static const auto MD_EXT = std::filesystem::path(".md"); + static const auto MARKDOWN_EXT = std::filesystem::path(".markdown"); + static const auto SH_EXT = std::filesystem::path(".sh"); static const auto DIFF_MATCHERS = lnav::pcre2pp::code::from_const( R"(^--- .*\n\+\+\+ .*\n)", PCRE2_MULTILINE); diff --git a/src/text_format.hh b/src/text_format.hh index 8c8645a6..6a907de5 100644 --- a/src/text_format.hh +++ b/src/text_format.hh @@ -38,7 +38,7 @@ #include "base/intern_string.hh" #include "fmt/format.h" -#include "ghc/filesystem.hpp" +#include enum class text_format_t { TF_UNKNOWN, @@ -131,7 +131,7 @@ struct formatter : formatter { * @return The detected format. */ text_format_t detect_text_format(string_fragment sf, - std::optional path + std::optional path = std::nullopt); struct text_format_meta_t { diff --git a/src/unique_path.hh b/src/unique_path.hh index 01fa5679..7909d470 100644 --- a/src/unique_path.hh +++ b/src/unique_path.hh @@ -37,7 +37,7 @@ #include #include -#include "ghc/filesystem.hpp" +#include /** * A source of a path for the unique_path_generator. @@ -51,26 +51,26 @@ public: this->ups_unique_path = path; } - const ghc::filesystem::path& get_unique_path() const + const std::filesystem::path& get_unique_path() const { return this->ups_unique_path; } - virtual ghc::filesystem::path get_path() const = 0; + virtual std::filesystem::path get_path() const = 0; - const ghc::filesystem::path& get_path_prefix() const + const std::filesystem::path& get_path_prefix() const { return this->ups_prefix; } - void set_path_prefix(const ghc::filesystem::path& prefix) + void set_path_prefix(const std::filesystem::path& prefix) { this->ups_prefix = prefix; } private: - ghc::filesystem::path ups_prefix; - ghc::filesystem::path ups_unique_path; + std::filesystem::path ups_prefix; + std::filesystem::path ups_unique_path; }; /** diff --git a/src/url_handler.cc b/src/url_handler.cc index eb8824a2..2e4ae342 100644 --- a/src/url_handler.cc +++ b/src/url_handler.cc @@ -180,7 +180,7 @@ looper::open(std::string url) host_part_str = host_part; } - auto source_path = ghc::filesystem::path{ + auto source_path = std::filesystem::path{ proto_iter->second.p_handler.pp_location.sl_source.get()}; auto new_path = lnav::filesystem::build_path({ source_path.parent_path(), diff --git a/src/url_loader.hh b/src/url_loader.hh index bbe582f9..ce4108ab 100644 --- a/src/url_loader.hh +++ b/src/url_loader.hh @@ -45,7 +45,7 @@ public: url_loader(const std::string& url) : curl_request(url) { std::error_code errc; - ghc::filesystem::create_directories(lnav::paths::workdir(), errc); + std::filesystem::create_directories(lnav::paths::workdir(), errc); auto tmp_res = lnav::filesystem::open_temp_file(lnav::paths::workdir() / "url.XXXXXX"); if (tmp_res.isErr()) { @@ -63,7 +63,7 @@ public: curl_easy_setopt(this->cr_handle, CURLOPT_BUFFERSIZE, 128L * 1024L); } - ghc::filesystem::path get_path() const { return this->ul_path; } + std::filesystem::path get_path() const { return this->ul_path; } long complete(CURLcode result) { @@ -144,7 +144,7 @@ private: return retval; } - ghc::filesystem::path ul_path; + std::filesystem::path ul_path; auto_fd ul_fd; off_t ul_resume_offset{0}; }; diff --git a/src/view_curses.cc b/src/view_curses.cc index cf3046b2..c8a284fa 100644 --- a/src/view_curses.cc +++ b/src/view_curses.cc @@ -792,7 +792,7 @@ view_colors::to_attrs(const lnav_theme& lt, reporter(&sc.sc_color, lnav::console::user_message::warning("")); #endif } else { - auto role_class_path = ghc::filesystem::path(pp_sc.pp_path.to_string()); + auto role_class_path = std::filesystem::path(pp_sc.pp_path.to_string()); auto inner = role_class_path.filename().string(); auto outer = role_class_path.parent_path().filename().string(); diff --git a/src/yajlpp/yajlpp.cc b/src/yajlpp/yajlpp.cc index cc9defe6..b3e28445 100644 --- a/src/yajlpp/yajlpp.cc +++ b/src/yajlpp/yajlpp.cc @@ -36,7 +36,7 @@ #include "config.h" #include "fmt/format.h" -#include "ghc/filesystem.hpp" +#include #include "yajl/api/yajl_parse.h" #include "yajlpp_def.hh" @@ -1592,8 +1592,8 @@ dump_schema_to(const json_path_container& jpc, const char* internals_dir) { yajlpp_gen genner; yajlpp_gen_context ygc(genner, jpc); - auto internals_dir_path = ghc::filesystem::path(internals_dir); - auto schema_file_name = ghc::filesystem::path(jpc.jpc_schema_id).filename(); + auto internals_dir_path = std::filesystem::path(internals_dir); + auto schema_file_name = std::filesystem::path(jpc.jpc_schema_id).filename(); auto schema_path = internals_dir_path / schema_file_name; auto file = std::unique_ptr( fopen(schema_path.c_str(), "w+"), fclose); diff --git a/test/drive_data_scanner.cc b/test/drive_data_scanner.cc index b834ee06..f4390d77 100644 --- a/test/drive_data_scanner.cc +++ b/test/drive_data_scanner.cc @@ -74,7 +74,7 @@ main(int argc, char* argv[]) } { - std::vector paths; + std::vector paths; std::vector errors; load_formats(paths, errors); diff --git a/test/drive_doc_discovery.cc b/test/drive_doc_discovery.cc index d12f231f..3796267c 100644 --- a/test/drive_doc_discovery.cc +++ b/test/drive_doc_discovery.cc @@ -42,7 +42,7 @@ main(int argc, char* argv[]) fprintf(stderr, "error: expecting file to discover\n"); retval = EXIT_FAILURE; } else { - const auto fn = ghc::filesystem::path(argv[1]); + const auto fn = std::filesystem::path(argv[1]); auto read_res = lnav::filesystem::read_file(fn); if (read_res.isErr()) { fprintf(stderr, diff --git a/test/drive_logfile.cc b/test/drive_logfile.cc index 52f8baa7..1f1c1d9f 100644 --- a/test/drive_logfile.cc +++ b/test/drive_logfile.cc @@ -84,7 +84,7 @@ main(int argc, char* argv[]) { std::vector errors; - vector paths; + vector paths; getenv_opt("test_dir") | [&paths](auto value) { paths.template emplace_back(value); }; diff --git a/test/lnav_doctests.cc b/test/lnav_doctests.cc index 78acf8d2..d56c5fe0 100644 --- a/test/lnav_doctests.cc +++ b/test/lnav_doctests.cc @@ -210,11 +210,11 @@ TEST_CASE("ptime_roundtrip") class my_path_source : public unique_path_source { public: - explicit my_path_source(ghc::filesystem::path p) : mps_path(std::move(p)) {} + explicit my_path_source(std::filesystem::path p) : mps_path(std::move(p)) {} - ghc::filesystem::path get_path() const override { return this->mps_path; } + std::filesystem::path get_path() const override { return this->mps_path; } - ghc::filesystem::path mps_path; + std::filesystem::path mps_path; }; TEST_CASE("unique_path") diff --git a/test/scripty.cc b/test/scripty.cc index 23144d3e..55a87d25 100644 --- a/test/scripty.cc +++ b/test/scripty.cc @@ -71,6 +71,7 @@ #endif #include +#include #include #include #include @@ -81,7 +82,6 @@ #include "base/auto_mem.hh" #include "base/string_util.hh" #include "fmt/format.h" -#include "ghc/filesystem.hpp" #include "styling.hh" #include "termios_guard.hh" #include "ww898/cp_utf8.hpp" @@ -268,9 +268,9 @@ static struct { pid_t sd_child_pid{-1}; - ghc::filesystem::path sd_actual_name; + std::filesystem::path sd_actual_name; auto_mem sd_from_child{fclose}; - ghc::filesystem::path sd_expected_name; + std::filesystem::path sd_expected_name; deque sd_replay; } scripty_data; @@ -1123,8 +1123,8 @@ main(int argc, char* argv[]) scripty_data.sd_expected_name.c_str()); auto options - = ghc::filesystem::copy_options::overwrite_existing; - ghc::filesystem::copy_file(scripty_data.sd_actual_name, + = std::filesystem::copy_options::overwrite_existing; + std::filesystem::copy_file(scripty_data.sd_actual_name, scripty_data.sd_expected_name, options); } else { diff --git a/test/test_cli.sh b/test/test_cli.sh index 195f8bc5..e2eb7048 100644 --- a/test/test_cli.sh +++ b/test/test_cli.sh @@ -48,6 +48,7 @@ run_cap_test ${lnav_test} -m -I ${test_dir} config blame export TMPDIR="piper-tmp" rm -rf ./piper-tmp +mkdir piper-tmp run_cap_test ${lnav_test} -n -e 'echo hi' run_cap_test ${lnav_test} -m piper list diff --git a/test/test_top_status.cc b/test/test_top_status.cc index 769c3461..1b443342 100644 --- a/test/test_top_status.cc +++ b/test/test_top_status.cc @@ -64,7 +64,7 @@ main(int argc, char* argv[]) setenv("HOME", "/", 1); std::vector errors; - std::vector paths; + std::vector paths; load_config(paths, errors);