diff options
-rw-r--r-- | include/filepath.h | 4 | ||||
-rw-r--r-- | rust/libnewsboat-ffi/src/filepath.rs | 5 | ||||
-rw-r--r-- | src/dirbrowserformaction.cpp | 31 | ||||
-rw-r--r-- | src/filebrowserformaction.cpp | 28 | ||||
-rw-r--r-- | src/filepath.cpp | 20 | ||||
-rw-r--r-- | test/filepath.cpp | 91 |
6 files changed, 144 insertions, 35 deletions
diff --git a/include/filepath.h b/include/filepath.h index be148b10..795a6dfb 100644 --- a/include/filepath.h +++ b/include/filepath.h @@ -64,6 +64,10 @@ public: bool operator==(const Filepath&) const; bool operator!=(const Filepath&) const; + bool operator<(const Filepath&) const; + bool operator<=(const Filepath&) const; + bool operator>(const Filepath&) const; + bool operator>=(const Filepath&) const; /// Returns the filepath as a string in locale encoding. /// diff --git a/rust/libnewsboat-ffi/src/filepath.rs b/rust/libnewsboat-ffi/src/filepath.rs index 65ed82b8..602c3fa2 100644 --- a/rust/libnewsboat-ffi/src/filepath.rs +++ b/rust/libnewsboat-ffi/src/filepath.rs @@ -19,6 +19,7 @@ mod bridged { fn create_empty() -> Box<PathBuf>; fn create(filepath: Vec<u8>) -> Box<PathBuf>; fn equals(lhs: &PathBuf, rhs: &PathBuf) -> bool; + fn less_than(lhs: &PathBuf, rhs: &PathBuf) -> bool; fn into_bytes(filepath: &PathBuf) -> Vec<u8>; fn display(filepath: &PathBuf) -> String; fn push(filepath: &mut PathBuf, component: &PathBuf); @@ -44,6 +45,10 @@ fn equals(lhs: &PathBuf, rhs: &PathBuf) -> bool { lhs.0 == rhs.0 } +fn less_than(lhs: &PathBuf, rhs: &PathBuf) -> bool { + lhs.0 < rhs.0 +} + fn into_bytes(filepath: &PathBuf) -> Vec<u8> { filepath.0.as_os_str().as_bytes().to_owned() } diff --git a/src/dirbrowserformaction.cpp b/src/dirbrowserformaction.cpp index 5c932d04..56f470da 100644 --- a/src/dirbrowserformaction.cpp +++ b/src/dirbrowserformaction.cpp @@ -1,5 +1,3 @@ -#define ENABLE_IMPLICIT_FILEPATH_CONVERSIONS - #include "dirbrowserformaction.h" #include <algorithm> @@ -177,31 +175,31 @@ void DirBrowserFormAction::update_title(const Filepath& working_directory) FmtStrFormatter fmt; fmt.register_fmt('N', PROGRAM_NAME); fmt.register_fmt('V', utils::program_version()); - fmt.register_fmt('f', working_directory); + fmt.register_fmt('f', working_directory.display()); set_title(fmt.do_format( cfg->get_configvalue("dirbrowser-title-format"), width)); } -std::vector<std::string> get_sorted_dirlist() +std::vector<Filepath> get_sorted_dirlist() { - std::vector<std::string> ret; + std::vector<Filepath> ret; - const std::string cwdtmp = utils::getcwd(); + const auto cwdtmp = utils::getcwd(); - DIR* dirp = ::opendir(cwdtmp.c_str()); + DIR* dirp = ::opendir(cwdtmp.to_locale_string().c_str()); if (dirp) { struct dirent* de = ::readdir(dirp); while (de) { if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { struct stat sb; - auto dpath = strprintf::fmt( - "%s/%s", cwdtmp, de->d_name); - if (::lstat(dpath.c_str(), &sb) == 0) { + auto entry = Filepath::from_locale_string(de->d_name); + const auto dpath = cwdtmp.join(entry); + if (::lstat(dpath.to_locale_string().c_str(), &sb) == 0) { const auto ftype = file_system::mode_to_filetype(sb.st_mode); if (ftype == file_system::FileType::Directory) { - ret.push_back(de->d_name); + ret.emplace_back(std::move(entry)); } } } @@ -213,8 +211,8 @@ std::vector<std::string> get_sorted_dirlist() std::sort(ret.begin(), ret.end()); - if (cwdtmp != "/") { - ret.insert(ret.begin(), ".."); + if (cwdtmp != Filepath::from_locale_string("/")) { + ret.emplace(ret.begin(), Filepath::from_locale_string("..")); } return ret; @@ -228,14 +226,11 @@ void DirBrowserFormAction::prepare() * in the current directory. */ if (do_redraw) { - const std::string cwdtmp = utils::getcwd(); - update_title(cwdtmp); - - std::vector<std::string> directories = get_sorted_dirlist(); + update_title(utils::getcwd()); id_at_position.clear(); lines.clear(); - for (std::string directory : directories) { + for (auto directory : get_sorted_dirlist()) { add_directory(id_at_position, directory); } diff --git a/src/filebrowserformaction.cpp b/src/filebrowserformaction.cpp index ba8884d3..e6e1f83c 100644 --- a/src/filebrowserformaction.cpp +++ b/src/filebrowserformaction.cpp @@ -1,5 +1,3 @@ -#define ENABLE_IMPLICIT_FILEPATH_CONVERSIONS - #include "filebrowserformaction.h" #include <algorithm> @@ -201,25 +199,25 @@ void FileBrowserFormAction::update_title(const Filepath& working_directory) FmtStrFormatter fmt; fmt.register_fmt('N', PROGRAM_NAME); fmt.register_fmt('V', utils::program_version()); - fmt.register_fmt('f', working_directory); + fmt.register_fmt('f', working_directory.display()); set_title(fmt.do_format( cfg->get_configvalue("filebrowser-title-format"), width)); } -std::vector<std::string> get_sorted_filelist() +std::vector<Filepath> get_sorted_filelist() { - std::vector<std::string> ret; + std::vector<Filepath> ret; - const std::string cwdtmp = utils::getcwd(); + const auto cwdtmp = utils::getcwd(); - DIR* dirp = ::opendir(cwdtmp.c_str()); + DIR* dirp = ::opendir(cwdtmp.to_locale_string().c_str()); if (dirp) { struct dirent* de = ::readdir(dirp); while (de) { if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { - ret.push_back(de->d_name); + ret.push_back(Filepath::from_locale_string(de->d_name)); } de = ::readdir(dirp); } @@ -228,8 +226,8 @@ std::vector<std::string> get_sorted_filelist() std::sort(ret.begin(), ret.end()); - if (cwdtmp != "/") { - ret.insert(ret.begin(), ".."); + if (cwdtmp != Filepath::from_locale_string("/")) { + ret.emplace(ret.begin(), Filepath::from_locale_string("..")); } return ret; @@ -243,18 +241,14 @@ void FileBrowserFormAction::prepare() * in the current directory. */ if (do_redraw) { - const std::string cwdtmp = utils::getcwd(); - update_title(cwdtmp); - - std::vector<std::string> files = get_sorted_filelist(); + update_title(utils::getcwd()); id_at_position.clear(); lines.clear(); - for (std::string filename : files) { + for (auto filename : get_sorted_filelist()) { add_file(id_at_position, filename); } - auto render_line = [this](std::uint32_t line, std::uint32_t width) -> StflRichText { (void)width; return lines[line]; @@ -295,7 +289,7 @@ void FileBrowserFormAction::init() const int status = ::chdir(save_path.c_str()); LOG(Level::DEBUG, "view::filebrowser: chdir(%s) = %i", save_path, status); - set_value("filenametext", default_filename); + set_value("filenametext", default_filename.to_locale_string()); // Set position to 0 and back to ensure that the text is visible draw_form(); diff --git a/src/filepath.cpp b/src/filepath.cpp index 6ff48526..caaf7da5 100644 --- a/src/filepath.cpp +++ b/src/filepath.cpp @@ -63,6 +63,26 @@ bool Filepath::operator!=(const Filepath& other) const return !(*this == other); } +bool Filepath::operator<(const Filepath& other) const +{ + return filepath::bridged::less_than(*rs_object, *other.rs_object); +} + +bool Filepath::operator<=(const Filepath& other) const +{ + return !(*this > other); +} + +bool Filepath::operator>(const Filepath& other) const +{ + return !(*this < other) && (*this != other); +} + +bool Filepath::operator>=(const Filepath& other) const +{ + return !(*this < other); +} + void Filepath::push(const Filepath& component) { filepath::bridged::push(*rs_object, *component.rs_object); diff --git a/test/filepath.cpp b/test/filepath.cpp index a0d05ba3..5d500489 100644 --- a/test/filepath.cpp +++ b/test/filepath.cpp @@ -206,3 +206,94 @@ TEST_CASE("Can extract the final component of the path (file or directory name)" REQUIRE(path.file_name().value() == Filepath::from_locale_string("one\x80two")); } } + +TEST_CASE("Can be ordered lexicographically", "[Filepath]") +{ + const auto root = Filepath::from_locale_string("/"); + const auto var_log = Filepath::from_locale_string("/var/log"); + const auto home_minoru = Filepath::from_locale_string("/home/minoru"); + const auto home_minoru_src_newsboat = + Filepath::from_locale_string("/home/minoru/src/newsboat"); + + SECTION("operator<") { + SECTION("Path to directory is less than the path to its subdirectory") { + REQUIRE(root < var_log); + REQUIRE(root < home_minoru); + REQUIRE(home_minoru < home_minoru_src_newsboat); + + REQUIRE_FALSE(home_minoru_src_newsboat < root); + } + + SECTION("Disparate paths are ordered lexicographically") { + REQUIRE(home_minoru < var_log); + REQUIRE(home_minoru_src_newsboat < var_log); + + REQUIRE_FALSE(home_minoru_src_newsboat < home_minoru); + } + } + + SECTION("operator>") { + SECTION("Path to subdirectory is greater than the path to its parent directory") { + REQUIRE(var_log > root); + REQUIRE(home_minoru > root); + REQUIRE(home_minoru_src_newsboat > home_minoru); + + REQUIRE_FALSE(root > home_minoru_src_newsboat); + } + + SECTION("Disparate paths are ordered lexicographically") { + REQUIRE(var_log > home_minoru); + REQUIRE(var_log > home_minoru_src_newsboat); + + REQUIRE_FALSE(home_minoru > home_minoru_src_newsboat); + } + } + + SECTION("operator<=") { + SECTION("Any path is less than or equal to itself") { + REQUIRE(root <= root); + REQUIRE(var_log <= var_log); + REQUIRE(home_minoru <= home_minoru); + REQUIRE(home_minoru_src_newsboat <= home_minoru_src_newsboat); + } + + SECTION("Path to directory is less than or equal to the path to its subdirectory") { + REQUIRE(root <= var_log); + REQUIRE(root <= home_minoru); + REQUIRE(home_minoru <= home_minoru_src_newsboat); + + REQUIRE_FALSE(home_minoru_src_newsboat <= root); + } + + SECTION("Disparate paths are ordered lexicographically") { + REQUIRE(home_minoru <= var_log); + REQUIRE(home_minoru_src_newsboat <= var_log); + + REQUIRE_FALSE(home_minoru_src_newsboat <= home_minoru); + } + } + + SECTION("operator>=") { + SECTION("Any path is greater than or equal to itself") { + REQUIRE(root >= root); + REQUIRE(var_log >= var_log); + REQUIRE(home_minoru >= home_minoru); + REQUIRE(home_minoru_src_newsboat >= home_minoru_src_newsboat); + } + + SECTION("Path to subdirectory is greater than or equal to the path to its parent directory") { + REQUIRE(var_log >= root); + REQUIRE(home_minoru >= root); + REQUIRE(home_minoru_src_newsboat >= home_minoru); + + REQUIRE_FALSE(root >= home_minoru_src_newsboat); + } + + SECTION("Disparate paths are ordered lexicographically") { + REQUIRE(var_log >= home_minoru); + REQUIRE(var_log >= home_minoru_src_newsboat); + + REQUIRE_FALSE(home_minoru >= home_minoru_src_newsboat); + } + } +} |