diff --git a/include/blt/app.h b/include/blt/app.h index 68bbe92..4e9b7f7 100644 --- a/include/blt/app.h +++ b/include/blt/app.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "traits.h" #include #include @@ -22,31 +22,63 @@ namespace blt::graphics { class Settings { public: - typedef std::variant property_t; + typedef std::variant property_t; Settings() = default; + Settings(std::initializer_list> default_properties){ + for (const auto& v : default_properties) + setProperty(v.first, v.second); + } ~Settings() = default; - [[nodiscard]] const property_t* getProperty(properties_t property) const { + [[nodiscard]] inline const property_t* getProperty(properties_t property) const { if (values.size() <= static_cast(property)) return nullptr; return &values[static_cast(property)]; } template - [[nodiscard]] const T* getProperty(properties_t property) const { + [[nodiscard]] inline const T* getProperty(properties_t property) const { if ((int)values.size() <= static_cast(property)) return nullptr; return &get(values[static_cast(property)]); } - void setProperty(properties_t property, property_t value) { + inline void setProperty(properties_t property, property_t value) { if (values.capacity() <= static_cast(property)) values.resize(static_cast(property) * 2); values[static_cast(property)] = std::move(value); } + + bool save(std::ofstream& out); + bool load(std::ifstream& in); private: std::vector values; + // handles saving of the variant's value + class property_saver { + private: + std::ofstream& out; + public: + explicit property_saver(std::ofstream& out): out(out){} + inline void operator()(int32_t i) { + out << i; + } + inline void operator()(int64_t l){ + out << l; + out << "l"; + } + inline void operator()(float f){ + out << f; + out << "f"; + } + inline void operator()(bool b){ + out << b; + out << "b"; + } + inline void operator()(const std::string& s) { + out << s; + } + }; }; } \ No newline at end of file diff --git a/src/parks/app.cpp b/src/parks/app.cpp index cb52487..f7d5d71 100644 --- a/src/parks/app.cpp +++ b/src/parks/app.cpp @@ -1,5 +1,69 @@ #include "blt/app.h" +#include +#include namespace blt::graphics { - + + bool Settings::save(std::ofstream& out) { + BLT_DEBUG("Saving settings"); + out << "# Warning: this file does not allow for comments or any form of manual modification!\n"; + out << "# All comments will be ignored, however changes will be accepted assuming the application is not running.\n"; + property_saver saver(out); + try { + for (size_t i = 0; i < values.size(); i++) { + out << static_cast(i); + out << " = "; + std::visit(saver, values[i]); + out << '\n'; + } + } catch (std::exception& e){ + BLT_ERROR("Error in settings save (%s)!", e.what()); + return false; + } + return true; + } + + bool Settings::load(std::ifstream& in) { + BLT_DEBUG("Loading settings"); + try { + size_t currentLine = 0; + while(!(in.eof() || in.fail())){ + currentLine++; + std::string line; + std::getline(in, line); + blt::string::trim(line); + + if (line.starts_with('#') || line.empty()) + continue; + + auto propertyToValue = blt::string::split(line, "="); + for (auto& s : propertyToValue) + blt::string::trim(s); + + if (propertyToValue.size() < 2) { + BLT_WARN("Improperly formed key = value pair! Ignoring line %d ('%s')", currentLine, line.c_str()); + continue; + } + + auto property = static_cast(std::stoi(propertyToValue[0])); + auto& value = propertyToValue[1]; + + if (std::any_of(value.begin(), value.end(), ::isdigit)){ + if (value.ends_with('l')) { + setProperty(property, std::stoll(value.substr(0, value.size()-1))); + } else if (value.ends_with('f')) { + setProperty(property, std::stof(value.substr(0, value.size()-1))); + } else if (value.ends_with('b')) { + setProperty(property, static_cast(std::stoi(value.substr(0, value.size()-1)))); + } else + setProperty(property, std::stoi(value)); + } else + setProperty(property, value); + } + } catch (std::exception& e){ + BLT_ERROR("Error in settings load (%s)!", e.what()); + return false; + } + return true; + } } \ No newline at end of file