From 0a23a5ef50e6c5dc7935e0d29811a944896c9a94 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Feb 2021 15:59:57 +0300 Subject: [PATCH] Rewrite fs::get_parent_dir Don't analyse full path if possible. --- Utilities/File.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index daf6907860..dd50049f0e 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -322,12 +322,53 @@ std::shared_ptr fs::set_virtual_device(const std::string& name, std::string fs::get_parent_dir(const std::string& path) { - // Get (basically) processed path - const auto real_path = fs::escape_path(path); + std::string_view result = path; - const auto pos = real_path.find_last_of(delim); + // Number of path components to remove + usz to_remove = 1; - return real_path.substr(0, pos == umax ? 0 : pos); + while (to_remove--) + { + // Trim contiguous delimiters at the end + if (usz sz = result.find_last_not_of(delim) + 1) + { + result = result.substr(0, sz); + } + else + { + return "/"; + } + + const auto elem = result.substr(result.find_last_of(delim) + 1); + + if (elem.empty() || elem.size() == result.size()) + { + break; + } + + if (elem == ".") + { + to_remove += 1; + } + + if (elem == "..") + { + to_remove += 2; + } + + result.remove_suffix(elem.size()); + } + + if (usz sz = result.find_last_not_of(delim) + 1) + { + result = result.substr(0, sz); + } + else + { + return "/"; + } + + return std::string{result}; } bool fs::stat(const std::string& path, stat_t& info)