#pragma once #include #include #include #include #include "Paths.h" #include "Events.h" namespace Artifact { namespace Events { struct SettingChanged { std::string key; std::optional value; }; } class Settings: public EventTarget { const Path path; std::unordered_map data; public: Settings(); Settings(Path path); void reload(); void save(); template T get(std::string & key, const T & fallback = {}) { auto it = data.find(key); if (it == data.end()) { return fallback; } const std::string & str = it->second; if constexpr (std::is_same_v) { return str; } if constexpr (std::is_same_v) { std::string lower = str; std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c){ return static_cast(std::tolower(c)); }); if (lower == "true" || lower == "1" || lower == "yes" || lower == "on") { return true; } if (lower == "false" || lower == "0" || lower == "no" || lower == "off") { return false; } return fallback; } std::istringstream iss(str); T value; if (iss >> value) { return value; } return fallback; } template void set(const std::string & key, const T & value) { std::ostringstream oss; oss << std::boolalpha << value; data[key] = oss.str(); dispatch(Events::SettingChanged { .key = key, .value = value }); } void reset(const std::string & key) { data.erase(key); dispatch(Events::SettingChanged { .key = key, .value = std::nullopt }); } void clear() { data.clear(); } }; }