diff options
| author | Hannes Schulze <haschu0103@outlook.de> | 2025-02-04 23:11:08 +0100 |
|---|---|---|
| committer | Hannes Schulze <haschu0103@outlook.de> | 2025-02-04 23:11:08 +0100 |
| commit | 79553ab1fa3d707612e80dd03bf95ca65fa0c411 (patch) | |
| tree | f44bec41548d569cfca43c44e0e4ffa7b72ed4ed /app/mac/impl/file-browser-posix.cc | |
| parent | 9c45e9c7df1efa5bc1c8e73b6eaef4726b828d3e (diff) | |
refactor file browser
Diffstat (limited to 'app/mac/impl/file-browser-posix.cc')
| -rw-r--r-- | app/mac/impl/file-browser-posix.cc | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/app/mac/impl/file-browser-posix.cc b/app/mac/impl/file-browser-posix.cc new file mode 100644 index 0000000..4c717fd --- /dev/null +++ b/app/mac/impl/file-browser-posix.cc @@ -0,0 +1,129 @@ +#include "impl/file-browser-posix.hh" +#include <string> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +namespace nes::app::mac +{ + file_browser_posix::file_browser_posix() + { + reopen_directory(path_.get_path()); + } + + file_browser_posix::~file_browser_posix() + { + if (it_) { closedir(it_); } + } + + auto file_browser_posix::seek(u32 const pos) -> void + { + if (it_pos_ > pos) + { + reopen_directory(path_.get_path()); + } + + while (it_pos_ < pos) + { + if (!read_next(nullptr)) { break; } + } + } + + auto file_browser_posix::read_next(item* out_item) -> bool + { + if (!it_) { return false; } + + while (true) + { + errno = 0; + auto const entry = readdir(it_); + if (!entry) + { + if (errno) { perror("file_browser_posix: readdir"); } + return false; + } + + auto const name = std::string_view{ entry->d_name }; + if (name.length() > max_name_length) { continue; } + if (name[0] == '.') { continue; } + + auto type = item_type::directory; + if (entry->d_type == DT_DIR) { type = item_type::directory; } + else if (entry->d_type == DT_REG) { type = item_type::file; } + else { continue; } + + it_pos_ += 1; + if (out_item) { *out_item = item{ type, name }; } + return true; + } + } + + auto file_browser_posix::navigate_up() -> status + { + auto new_path = path_; + if (auto const s = new_path.pop(); s != status::success) { return s; } + if (auto const s = reopen_directory(new_path.get_path()); s != status::success) { return s; } + path_ = new_path; + return status::success; + } + + auto file_browser_posix::navigate(std::string_view const item) -> status + { + auto new_path = path_; + if (auto const s = new_path.push(item); s != status::success) { return s; } + if (auto const s = reopen_directory(new_path.get_path()); s != status::success) { return s; } + path_ = new_path; + return status::success; + } + + auto file_browser_posix::load(std::string_view const item, span<u8> const buffer, u32* out_length) -> status + { + auto file_path = path_; + if (auto const s = file_path.push(item); s != status::success) { return s; } + + auto const file_path_str = std::string{ file_path.get_path() }; + auto const fd = open(file_path_str.c_str(), O_RDONLY); + if (fd == -1) + { + perror("file_browser_posix: open"); + return status::error_system_error; + } + + auto const res = read(fd, buffer.get_data(), buffer.get_length()); + if (res < 0) + { + perror("file_browser_posix: read"); + close(fd); + return status::error_system_error; + } + if (out_length) { *out_length = static_cast<u32>(res); } + + auto remaining = char{}; + if (read(fd, &remaining, 1) != 0) + { + // File was too long. + close(fd); + return status::error_invalid_ines_data; + } + + close(fd); + + return status::success; + } + + auto file_browser_posix::reopen_directory(std::string_view const path) -> status + { + auto const path_str = std::string{ path }; + auto const new_it = opendir(path_str.c_str()); + if (!new_it) + { + perror("file_browser_posix: opendir"); + return status::error_system_error; + } + + if (it_) { closedir(it_); } + it_ = new_it; + it_pos_ = 0; + return status::success; + } +} // namespace nes::app::mac
\ No newline at end of file |
