diff --git a/CMakeLists.txt b/CMakeLists.txt index cf34130..3158f5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(INCLUDES "") set(SOURCES "") set(IMGUI_SOURCES "") set(DEFINITIONS "") -# imgui include because +# imgui include because https://github.com/ocornut/imgui/issues/6184#issuecomment-1439570929 list(APPEND INCLUDES thirdparty thirdparty/imgui /usr/include/SDL2) list(APPEND SOURCES main.cpp event_loop.cpp logcat_thread.cpp logcat_entry.cpp log.cpp config.cpp filters.cpp misc.cpp pcre2_wrapper.cpp group_panel.cpp fragments/filters.cpp windows/logs.cpp windows/settings.cpp windows/main.cpp) diff --git a/config.cpp b/config.cpp index 5bcc46d..3b89fcf 100644 --- a/config.cpp +++ b/config.cpp @@ -1,29 +1,13 @@ #include -#include #include #include #include #include "log.h" +#include "file.h" #include "misc.h" #include "config.h" -static FILE* fopen_or_raise(const char* __restrict path, const char* __restrict mode, bool ignore_enoent) { - FILE* file = fopen(path, mode); - if (!file && !(ignore_enoent && errno == ENOENT)) { - throw_system_error(std::string("fopen(") + quote(path) + ')'); - } - return file; -} - -static void fclose_and_log(FILE* file) { - if (!fclose(file)) { - return; - } - log(std::string("Failed to close a file: fclose(): ") + strerror(errno)); -} - - std::string get_config_folder() { const char* path; @@ -76,13 +60,15 @@ void from_json(const nlohmann::json& j, Config& config) { Config load_config() { std::string config_file_path = get_config_file_path(); - std::unique_ptr config_file(fopen_or_raise(config_file_path.c_str(), "r", true), fclose_and_log); - - if (!config_file) { + try { + File config_file(config_file_path.c_str(), "r"); + return nlohmann::json::parse(config_file.get()); + } catch (const std::system_error& e) { + if (e.code().value() != ENOENT) { + throw; + } return Config(); } - - return nlohmann::json::parse(config_file.get()).get(); } @@ -98,10 +84,11 @@ void write_config(const Config& config) { std::string config_file_path = get_config_file_path(); std::string tmp_config_file_path = config_file_path + ".tmp"; - std::unique_ptr config_file(fopen_or_raise(tmp_config_file_path.c_str(), "w", false), fclose_and_log); - std::string str_config = nlohmann::json(config).dump(4); - fwrite(str_config.data(), sizeof(char), str_config.size(), config_file.get()); - config_file.reset(); + { + File config_file(tmp_config_file_path.c_str(), "w"); + std::string str_config = nlohmann::json(config).dump(4); + config_file.write(std::move(str_config)); + } if (!rename(tmp_config_file_path.c_str(), config_file_path.c_str())) { return; diff --git a/file.h b/file.h new file mode 100644 index 0000000..039c704 --- /dev/null +++ b/file.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +#include "../log.h" +#include "../misc.h" + +static void try_close(FILE* file); + +// Not usable for logcat thread! +class File { +public: + // https://stackoverflow.com/a/2173764 + File(const File&) = delete; + File& operator=(const File&) = delete; + + inline constexpr File(File&& other) { + try_close(this->_file); + this->_file = other._file; + other._file = nullptr; + } + inline constexpr File& operator=(File&& other) { + if (this == &other) { + return *this; + } + + try_close(this->_file); + this->_file = other._file; + other._file = nullptr; + + return *this; + } + + File(const char* __restrict path, const char* __restrict mode) { + this->_file = fopen(path, mode); + if (!this->_file) { + throw_system_error(std::string("fopen(") + quote(path) + ')'); + } + } + ~File() { + try_close(this->_file); + } + + void write(const char* data, size_t length) { + if (fwrite(data, 1, length, this->_file) != length) { + throw_system_error("fwrite()"); + } + } + inline constexpr void write(const std::string& str) { + this->write(str.data(), str.size()); + } + inline constexpr FILE* get() const noexcept { + return this->_file; + } + +protected: + FILE* _file = nullptr; +}; + +static void try_close(FILE* file) { + if (file && fclose(file)) { + log(std::string("Failed to close a file: fclose(): ") + strerror(errno)); + } +}