Add file wrapper
This commit is contained in:
parent
46389de61f
commit
d4e6d72a18
|
@ -16,7 +16,7 @@ set(INCLUDES "")
|
|||
set(SOURCES "")
|
||||
set(IMGUI_SOURCES "")
|
||||
set(DEFINITIONS "")
|
||||
# imgui include because <GH ISSUE LINK HERE>
|
||||
# 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)
|
||||
|
|
39
config.cpp
39
config.cpp
|
@ -1,29 +1,13 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#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<FILE, decltype(&fclose_and_log)> 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<Config>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<FILE, decltype(&fclose_and_log)> 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;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue