finish settings

settings can now be saved / loaded at runtime

settings is part of blt::graphics due to it's singular usage, TODO: is to add this to blt
main
Brett 2023-08-01 22:14:04 -04:00
parent 9f94b167d3
commit f5bff5661d
2 changed files with 102 additions and 6 deletions

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <iostream> #include <fstream>
#include "traits.h" #include "traits.h"
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -22,31 +22,63 @@ namespace blt::graphics {
class Settings { class Settings {
public: public:
typedef std::variant<int32_t, float, bool, std::string> property_t; typedef std::variant<int32_t, int64_t, float, bool, std::string> property_t;
Settings() = default; Settings() = default;
Settings(std::initializer_list<std::pair<properties_t, property_t>> default_properties){
for (const auto& v : default_properties)
setProperty(v.first, v.second);
}
~Settings() = default; ~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<int>(property)) if (values.size() <= static_cast<int>(property))
return nullptr; return nullptr;
return &values[static_cast<int>(property)]; return &values[static_cast<int>(property)];
} }
template<typename T> template<typename T>
[[nodiscard]] const T* getProperty(properties_t property) const { [[nodiscard]] inline const T* getProperty(properties_t property) const {
if ((int)values.size() <= static_cast<int>(property)) if ((int)values.size() <= static_cast<int>(property))
return nullptr; return nullptr;
return &get<T>(values[static_cast<int>(property)]); return &get<T>(values[static_cast<int>(property)]);
} }
void setProperty(properties_t property, property_t value) { inline void setProperty(properties_t property, property_t value) {
if (values.capacity() <= static_cast<int>(property)) if (values.capacity() <= static_cast<int>(property))
values.resize(static_cast<int>(property) * 2); values.resize(static_cast<int>(property) * 2);
values[static_cast<int>(property)] = std::move(value); values[static_cast<int>(property)] = std::move(value);
} }
bool save(std::ofstream& out);
bool load(std::ifstream& in);
private: private:
std::vector<property_t> values; std::vector<property_t> 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;
}
};
}; };
} }

View File

@ -1,5 +1,69 @@
#include "blt/app.h" #include "blt/app.h"
#include <blt/std/string.h>
#include <algorithm>
namespace blt::graphics { 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<int>(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<properties_t>(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<bool>(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;
}
} }