// Copyright 2016 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #pragma once #include #include #include #include #include #include #include "Common/Config/ConfigInfo.h" #include "Common/Config/Enums.h" #include "Common/StringUtil.h" namespace Config { namespace detail { std::string ValueToString(u16 value); std::string ValueToString(u32 value); std::string ValueToString(float value); std::string ValueToString(double value); std::string ValueToString(int value); std::string ValueToString(bool value); std::string ValueToString(const std::string& value); template ::value>* = nullptr> std::string ValueToString(T value) { return ValueToString(static_cast>(value)); } template ::value>* = nullptr> std::optional TryParse(const std::string& str_value) { T value; if (!::TryParse(str_value, &value)) return std::nullopt; return value; } template ::value>* = nullptr> std::optional TryParse(const std::string& str_value) { const auto result = TryParse>(str_value); if (result) return static_cast(*result); return {}; } template <> inline std::optional TryParse(const std::string& str_value) { return str_value; } } template struct ConfigInfo; class Layer; using LayerMap = std::map>; class ConfigLayerLoader { public: explicit ConfigLayerLoader(LayerType layer); virtual ~ConfigLayerLoader(); virtual void Load(Layer* config_layer) = 0; virtual void Save(Layer* config_layer) = 0; LayerType GetLayer() const; private: const LayerType m_layer; }; class Section { public: using iterator = LayerMap::iterator; Section(iterator begin_, iterator end_) : m_begin(begin_), m_end(end_) {} iterator begin() const { return m_begin; } iterator end() const { return m_end; } private: iterator m_begin; iterator m_end; }; class ConstSection { public: using iterator = LayerMap::const_iterator; ConstSection(iterator begin_, iterator end_) : m_begin(begin_), m_end(end_) {} iterator begin() const { return m_begin; } iterator end() const { return m_end; } private: iterator m_begin; iterator m_end; }; class Layer { public: explicit Layer(LayerType layer); explicit Layer(std::unique_ptr loader); virtual ~Layer(); // Convenience functions bool Exists(const ConfigLocation& location) const; bool DeleteKey(const ConfigLocation& location); void DeleteAllKeys(); template T Get(const ConfigInfo& config_info) { return Get(config_info.location).value_or(config_info.default_value); } template std::optional Get(const ConfigLocation& location) { const std::optional& str_value = m_map[location]; if (!str_value) return std::nullopt; return detail::TryParse(*str_value); } template void Set(const ConfigInfo& config_info, const std::common_type_t& value) { Set(config_info.location, value); } template void Set(const ConfigLocation& location, const T& value) { const std::string new_value = detail::ValueToString(value); std::optional& current_value = m_map[location]; if (current_value == new_value) return; m_is_dirty = true; current_value = new_value; } Section GetSection(System system, const std::string& section); ConstSection GetSection(System system, const std::string& section) const; // Explicit load and save of layers void Load(); void Save(); LayerType GetLayer() const; const LayerMap& GetLayerMap() const; protected: bool m_is_dirty = false; LayerMap m_map; const LayerType m_layer; std::unique_ptr m_loader; }; }