// 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 { 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; } } // namespace detail template struct Info; 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 Location& location) const; bool DeleteKey(const Location& location); void DeleteAllKeys(); template T Get(const Info& config_info) const { return Get(config_info.location).value_or(config_info.default_value); } template std::optional Get(const Location& location) const { const auto iter = m_map.find(location); if (iter == m_map.end() || !iter->second.has_value()) return std::nullopt; return detail::TryParse(*iter->second); } template void Set(const Info& config_info, const std::common_type_t& value) { Set(config_info.location, value); } template void Set(const Location& location, const T& value) { Set(location, ValueToString(value)); } void Set(const Location& location, std::string new_value) { const auto iter = m_map.find(location); if (iter != m_map.end() && iter->second == new_value) return; m_is_dirty = true; m_map.insert_or_assign(location, std::move(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; }; } // namespace Config