From adc0848a23e6b086b6f4135a9f45ba70d475b9cd Mon Sep 17 00:00:00 2001 From: Riyyi Date: Thu, 11 Feb 2021 01:31:14 +0100 Subject: [PATCH] Implement nlohmann::json arbitrary type conversion for settings --- inferno/src/inferno/io/file.cpp | 28 ++++------ inferno/src/inferno/io/file.h | 14 ++--- inferno/src/inferno/settings.cpp | 87 +++++++++++++++++++------------- inferno/src/inferno/settings.h | 16 ++++-- 4 files changed, 79 insertions(+), 66 deletions(-) diff --git a/inferno/src/inferno/io/file.cpp b/inferno/src/inferno/io/file.cpp index 2a23784..5ba6142 100644 --- a/inferno/src/inferno/io/file.cpp +++ b/inferno/src/inferno/io/file.cpp @@ -9,28 +9,18 @@ namespace Inferno { std::shared_ptr File::raw(const std::string& path) { // Create input stream object and open file - std::ifstream ifstream(path); - ASSERT(ifstream.is_open(), "File could not open '{}'", path); - - // Check if file exists - if (!ifstream.is_open()) { - return nullptr; - } + std::ifstream file(path); + ASSERT(file.is_open(), "File could not open '{}'", path); // Get length of the file - int32_t length = File::length(path, ifstream); - - // Check for valid file length - if (length == -1) { - return nullptr; - } + int32_t length = File::length(path, file); // Allocate memory filled with zeros auto buffer = std::shared_ptr(new char[length + 1]); // Fill buffer with file contents - ifstream.read(buffer.get(), length); - ifstream.close(); + file.read(buffer.get(), length); + file.close(); // Null termination buffer[length] = '\0'; @@ -44,11 +34,11 @@ namespace Inferno { return std::string(raw(path).get()); } - int32_t File::length(const std::string& path, std::ifstream& ifstream) + int32_t File::length(const std::string& path, std::ifstream& file) { - ifstream.seekg(0, std::ios::end); - int32_t length = ifstream.tellg(); - ifstream.seekg(0, std::ios::beg); + file.seekg(0, std::ios::end); + int32_t length = file.tellg(); + file.seekg(0, std::ios::beg); ASSERT(length != -1, "File could not determine length '{}'", path); return length; diff --git a/inferno/src/inferno/io/file.h b/inferno/src/inferno/io/file.h index d522219..d078843 100644 --- a/inferno/src/inferno/io/file.h +++ b/inferno/src/inferno/io/file.h @@ -16,29 +16,29 @@ namespace Inferno { public: static std::shared_ptr raw(const std::string& path); static std::string read(const std::string& path); - static int32_t length(const std::string& path, std::ifstream& ifstream); + static int32_t length(const std::string& path, std::ifstream& file); template - static void ioRead(T& t, const std::string& path) + static void ioRead(T* t, const std::string& path) { std::ifstream file(path); - ASSERT(file.is_open(), "File could not open! {}", path.c_str()); + ASSERT(file.is_open(), "File could not open '{}'", path); if (file.is_open()) { - file >> t; + file >> *t; file.close(); } } template - static void ioWrite(T& t, const std::string& path) + static void ioWrite(T* t, const std::string& path) { std::ofstream file (path); - ASSERT(file.is_open(), "File could not open! {}", path.c_str()); + ASSERT(file.is_open(), "File could not open! {}", path); if (file.is_open()) { // Write file with single tabs, nicely formatted - file << std::setfill ('\t') << std::setw(1) << t << std::endl; + file << std::setfill ('\t') << std::setw(1) << *t << std::endl; file.close(); } } diff --git a/inferno/src/inferno/settings.cpp b/inferno/src/inferno/settings.cpp index 973557c..44e6a6c 100644 --- a/inferno/src/inferno/settings.cpp +++ b/inferno/src/inferno/settings.cpp @@ -5,67 +5,82 @@ #include "inferno/io/log.h" #include "inferno/settings.h" #include "inferno/util/json.h" +#include "inferno/window.h" namespace Inferno { - const char* Settings::m_path = "assets/settings.json"; - SettingsProperties Settings::m_properties = {}; + const char* Settings::m_path { "assets/settings.json" }; + SettingsProperties Settings::m_properties {}; void Settings::initialize() { - Settings::update(); + Settings::load(); info() << "Settings initialized"; } - void Settings::update() + void Settings::destroy() { - nlohmann::json json; - Settings::load(json); + } - if (!Json::hasProperty(json, "window")) { - warn() << "Settings has no window section, using default values"; - return; + void Settings::load() + { + json object; + + try { + File::ioRead(&object, m_path); + } + catch (...) { + warn() << "Settings invalid formatting, using default values"; } - auto window = json["window"]; - auto title = Json::parseStringProperty(window, "title", false); - auto width = Json::parseUnsignedProperty(window, "width", false); - auto height = Json::parseUnsignedProperty(window, "height", false); - auto fullscreen = Json::parseStringProperty(window, "fullscreen", false); - auto vsync = Json::parseBoolProperty(window, "vsync", false); - - if (title) m_properties.window.title = title.value(); - if (width) m_properties.window.width = width.value(); - if (height) m_properties.window.height = height.value(); - if (fullscreen) m_properties.window.fullscreen = fullscreen.value(); - if (vsync) m_properties.window.vsync = vsync.value(); + auto settings = Json::getPropertyValue(object, json::value_t::object); + if (settings) { + m_properties = settings.value(); + } } - void Settings::destroy() + bool Settings::save() { + json object = m_properties; + File::ioWrite(&object, m_path); + info() << "Settings saved"; + + return true; } - bool Settings::load(nlohmann::json& json) +// ----------------------------------------- + + void to_json(json& object, const SettingsProperties& settings) { - File::ioRead(json, m_path); + object = json { + { "window", settings.window } + }; + } - return true; + void from_json(const json& object, SettingsProperties& settings) + { + if (Json::hasProperty(object, "window")) object.at("window").get_to(settings.window); } - bool Settings::save() + void to_json(json& object, const WindowProperties& window) { - nlohmann::json json; - json["window"]["title"] = m_properties.window.title; - json["window"]["width"] = m_properties.window.width; - json["window"]["height"] = m_properties.window.height; - json["window"]["fullscreen"] = m_properties.window.fullscreen; - json["window"]["vsync"] = m_properties.window.vsync; - - File::ioWrite(json, m_path); - info() << "Settings saved"; + object = json { + { "title", window.title }, + { "width", window.width }, + { "height", window.height }, + { "fullscreen", window.fullscreen }, + { "vsync", window.vsync }, + }; + } - return true; + void from_json(const json& object, WindowProperties& window) + { + if (Json::hasProperty(object, "title")) object.at("title").get_to(window.title); + if (Json::hasProperty(object, "width")) object.at("width").get_to(window.width); + if (Json::hasProperty(object, "height")) object.at("height").get_to(window.height); + if (Json::hasProperty(object, "fullscreen")) object.at("fullscreen").get_to(window.fullscreen); + if (Json::hasProperty(object, "vsync")) object.at("vsync").get_to(window.vsync); } } diff --git a/inferno/src/inferno/settings.h b/inferno/src/inferno/settings.h index d68a370..78038a8 100644 --- a/inferno/src/inferno/settings.h +++ b/inferno/src/inferno/settings.h @@ -1,8 +1,7 @@ #ifndef SETTINGS_H #define SETTINGS_H -#include "nlohmann/json.hpp" - +#include "inferno/util/json.h" #include "inferno/window.h" namespace Inferno { @@ -14,10 +13,9 @@ namespace Inferno { class Settings { public: static void initialize(); - static void update(); static void destroy(); - static bool load(nlohmann::json& json); + static void load(); static bool save(); static inline SettingsProperties& get() { return m_properties; } @@ -27,6 +25,16 @@ namespace Inferno { static SettingsProperties m_properties; }; +// ----------------------------------------- + + // nlohmann::json arbitrary type conversion functions + + void to_json(json& object, const SettingsProperties& settings); + void from_json(const json& object, SettingsProperties& settings); + + void to_json(json& object, const WindowProperties& window); + void from_json(const json& object, WindowProperties& window); + } #endif // SETTINGS_H