diff options
| author | Leo Lam <leolino.lam@gmail.com> | 2017-11-17 15:01:56 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-17 15:01:56 +0100 |
| commit | 84ca9a4aec0048e5ac01caea8f8be9210eb947f6 (patch) | |
| tree | 9bc42cfe376101b040527ee254a527f05320a853 /Source/Core/Common/Config | |
| parent | 1e33fd0d3540e288f124c1c41891a768103f6290 (diff) | |
| parent | 37419b9a579fbcb1633caa9295a39da405e93904 (diff) | |
Merge pull request #6154 from MerryMage/config-cleanup
Cleanup implementation of onion configuration
Diffstat (limited to 'Source/Core/Common/Config')
| -rw-r--r-- | Source/Core/Common/Config/Config.cpp | 25 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Config.h | 27 | ||||
| -rw-r--r-- | Source/Core/Common/Config/ConfigInfo.cpp | 35 | ||||
| -rw-r--r-- | Source/Core/Common/Config/ConfigInfo.h | 30 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Enums.h | 1 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Layer.cpp | 139 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Layer.h | 112 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Section.cpp | 296 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Section.h | 113 |
9 files changed, 218 insertions, 560 deletions
diff --git a/Source/Core/Common/Config/Config.cpp b/Source/Core/Common/Config/Config.cpp index 339155dbe3..a3504f80d2 100644 --- a/Source/Core/Common/Config/Config.cpp +++ b/Source/Core/Common/Config/Config.cpp @@ -17,11 +17,6 @@ static std::list<ConfigChangedCallback> s_callbacks; void InvokeConfigChangedCallbacks(); -Section* GetOrCreateSection(System system, const std::string& section_name) -{ - return s_layers[LayerType::Meta]->GetOrCreateSection(system, section_name); -} - Layers* GetLayers() { return &s_layers; @@ -83,8 +78,6 @@ void Init() { // These layers contain temporary values ClearCurrentRunLayer(); - // This layer always has to exist - s_layers[LayerType::Meta] = std::make_unique<RecursiveLayer>(); } void Shutdown() @@ -129,26 +122,10 @@ const std::string& GetLayerName(LayerType layer) {LayerType::Movie, "Movie"}, {LayerType::CommandLine, "Command Line"}, {LayerType::CurrentRun, "Current Run"}, - {LayerType::Meta, "Top"}, }; return layer_to_name.at(layer); } -bool ConfigLocation::operator==(const ConfigLocation& other) const -{ - return std::tie(system, section, key) == std::tie(other.system, other.section, other.key); -} - -bool ConfigLocation::operator!=(const ConfigLocation& other) const -{ - return !(*this == other); -} - -bool ConfigLocation::operator<(const ConfigLocation& other) const -{ - return std::tie(system, section, key) < std::tie(other.system, other.section, other.key); -} - LayerType GetActiveLayerForConfig(const ConfigLocation& config) { for (auto layer : SEARCH_ORDER) @@ -156,7 +133,7 @@ LayerType GetActiveLayerForConfig(const ConfigLocation& config) if (!LayerExists(layer)) continue; - if (GetLayer(layer)->Exists(config.system, config.section, config.key)) + if (GetLayer(layer)->Exists(config)) return layer; } diff --git a/Source/Core/Common/Config/Config.h b/Source/Core/Common/Config/Config.h index 905960ed4a..3536f5677c 100644 --- a/Source/Core/Common/Config/Config.h +++ b/Source/Core/Common/Config/Config.h @@ -9,36 +9,15 @@ #include <memory> #include <string> +#include "Common/Config/ConfigInfo.h" #include "Common/Config/Enums.h" #include "Common/Config/Layer.h" -#include "Common/Config/Section.h" namespace Config { -struct ConfigLocation -{ - System system; - std::string section; - std::string key; - - bool operator==(const ConfigLocation& other) const; - bool operator!=(const ConfigLocation& other) const; - bool operator<(const ConfigLocation& other) const; -}; - -template <typename T> -struct ConfigInfo -{ - ConfigLocation location; - T default_value; -}; - using Layers = std::map<LayerType, std::unique_ptr<Layer>>; using ConfigChangedCallback = std::function<void()>; -// Common function used for getting configuration -Section* GetOrCreateSection(System system, const std::string& section_name); - // Layer management Layers* GetLayers(); void AddLayer(std::unique_ptr<Layer> layer); @@ -66,13 +45,15 @@ LayerType GetActiveLayerForConfig(const ConfigLocation&); template <typename T> T Get(LayerType layer, const ConfigInfo<T>& info) { + if (layer == LayerType::Meta) + return Get(info); return GetLayer(layer)->Get(info); } template <typename T> T Get(const ConfigInfo<T>& info) { - return Get(LayerType::Meta, info); + return GetLayer(GetActiveLayerForConfig(info.location))->Get(info); } template <typename T> diff --git a/Source/Core/Common/Config/ConfigInfo.cpp b/Source/Core/Common/Config/ConfigInfo.cpp new file mode 100644 index 0000000000..47d2e25c84 --- /dev/null +++ b/Source/Core/Common/Config/ConfigInfo.cpp @@ -0,0 +1,35 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <cstring> + +#include "Common/CommonFuncs.h" +#include "Common/Config/ConfigInfo.h" + +namespace Config +{ +bool ConfigLocation::operator==(const ConfigLocation& other) const +{ + return system == other.system && strcasecmp(section.c_str(), other.section.c_str()) == 0 && + strcasecmp(key.c_str(), other.key.c_str()) == 0; +} + +bool ConfigLocation::operator!=(const ConfigLocation& other) const +{ + return !(*this == other); +} + +bool ConfigLocation::operator<(const ConfigLocation& other) const +{ + if (system != other.system) + return system < other.system; + + const int section_compare = strcasecmp(section.c_str(), other.section.c_str()); + if (section_compare != 0) + return section_compare < 0; + + const int key_compare = strcasecmp(key.c_str(), other.key.c_str()); + return key_compare < 0; +} +} diff --git a/Source/Core/Common/Config/ConfigInfo.h b/Source/Core/Common/Config/ConfigInfo.h new file mode 100644 index 0000000000..fc36ecee03 --- /dev/null +++ b/Source/Core/Common/Config/ConfigInfo.h @@ -0,0 +1,30 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> + +#include "Common/Config/Enums.h" + +namespace Config +{ +struct ConfigLocation +{ + System system; + std::string section; + std::string key; + + bool operator==(const ConfigLocation& other) const; + bool operator!=(const ConfigLocation& other) const; + bool operator<(const ConfigLocation& other) const; +}; + +template <typename T> +struct ConfigInfo +{ + ConfigLocation location; + T default_value; +}; +} diff --git a/Source/Core/Common/Config/Enums.h b/Source/Core/Common/Config/Enums.h index 9ffd9688c2..a5b62f812d 100644 --- a/Source/Core/Common/Config/Enums.h +++ b/Source/Core/Common/Config/Enums.h @@ -34,7 +34,6 @@ enum class System }; constexpr std::array<LayerType, 7> SEARCH_ORDER{{ - // Skip the meta layer LayerType::CurrentRun, LayerType::CommandLine, LayerType::Movie, LayerType::Netplay, LayerType::LocalGame, LayerType::GlobalGame, LayerType::Base, }}; diff --git a/Source/Core/Common/Config/Layer.cpp b/Source/Core/Common/Config/Layer.cpp index b613c4366b..5a5c4b5f59 100644 --- a/Source/Core/Common/Config/Layer.cpp +++ b/Source/Core/Common/Config/Layer.cpp @@ -8,10 +8,47 @@ #include "Common/Config/Config.h" #include "Common/Config/Layer.h" -#include "Common/Config/Section.h" namespace Config { +namespace detail +{ +std::string ValueToString(u16 value) +{ + return StringFromFormat("0x%04x", value); +} + +std::string ValueToString(u32 value) +{ + return StringFromFormat("0x%08x", value); +} + +std::string ValueToString(float value) +{ + return StringFromFormat("%#.9g", value); +} + +std::string ValueToString(double value) +{ + return StringFromFormat("%#.17g", value); +} + +std::string ValueToString(int value) +{ + return std::to_string(value); +} + +std::string ValueToString(bool value) +{ + return StringFromBool(value); +} + +std::string ValueToString(const std::string& value) +{ + return value; +} +} + ConfigLayerLoader::ConfigLayerLoader(LayerType layer) : m_layer(layer) { } @@ -38,64 +75,56 @@ Layer::~Layer() Save(); } -bool Layer::Exists(System system, const std::string& section_name, const std::string& key) +bool Layer::Exists(const ConfigLocation& location) const { - Section* section = GetSection(system, section_name); - if (!section) - return false; - return section->Exists(key); + const auto iter = m_map.find(location); + return iter != m_map.end() && iter->second.has_value(); } -bool Layer::DeleteKey(System system, const std::string& section_name, const std::string& key) +bool Layer::DeleteKey(const ConfigLocation& location) { - Section* section = GetSection(system, section_name); - if (!section) - return false; - return section->Delete(key); + m_is_dirty = true; + bool had_value = m_map[location].has_value(); + m_map[location].reset(); + return had_value; } -Section* Layer::GetSection(System system, const std::string& section_name) +void Layer::DeleteAllKeys() { - for (auto& section : m_sections[system]) - if (!strcasecmp(section->m_name.c_str(), section_name.c_str())) - return section.get(); - return nullptr; + m_is_dirty = true; + for (auto& pair : m_map) + { + pair.second.reset(); + } } -Section* Layer::GetOrCreateSection(System system, const std::string& section_name) +Section Layer::GetSection(System system, const std::string& section) { - Section* section = GetSection(system, section_name); - if (!section) - { - if (m_layer == LayerType::Meta) - { - m_sections[system].emplace_back( - std::make_unique<RecursiveSection>(m_layer, system, section_name)); - } - else - { - m_sections[system].emplace_back(std::make_unique<Section>(m_layer, system, section_name)); - } - section = m_sections[system].back().get(); - } - return section; + return Section{m_map.lower_bound(ConfigLocation{system, section, ""}), + m_map.lower_bound(ConfigLocation{system, section + '\001', ""})}; +} + +ConstSection Layer::GetSection(System system, const std::string& section) const +{ + return ConstSection{m_map.lower_bound(ConfigLocation{system, section, ""}), + m_map.lower_bound(ConfigLocation{system, section + '\001', ""})}; } void Layer::Load() { if (m_loader) m_loader->Load(this); - ClearDirty(); + m_is_dirty = false; InvokeConfigChangedCallbacks(); } void Layer::Save() { - if (!m_loader || !IsDirty()) + if (!m_loader || !m_is_dirty) return; m_loader->Save(this); - ClearDirty(); + m_is_dirty = false; InvokeConfigChangedCallbacks(); } @@ -106,44 +135,6 @@ LayerType Layer::GetLayer() const const LayerMap& Layer::GetLayerMap() const { - return m_sections; -} - -bool Layer::IsDirty() const -{ - return std::any_of(m_sections.begin(), m_sections.end(), [](const auto& system) { - return std::any_of(system.second.begin(), system.second.end(), - [](const auto& section) { return section->IsDirty(); }); - }); -} - -void Layer::ClearDirty() -{ - std::for_each(m_sections.begin(), m_sections.end(), [](auto& system) { - std::for_each(system.second.begin(), system.second.end(), - [](auto& section) { section->ClearDirty(); }); - }); -} - -RecursiveLayer::RecursiveLayer() : Layer(LayerType::Meta) -{ -} - -Section* RecursiveLayer::GetSection(System system, const std::string& section_name) -{ - // Always queries backwards recursively, so it doesn't matter if it exists or not on this layer - return GetOrCreateSection(system, section_name); -} - -Section* RecursiveLayer::GetOrCreateSection(System system, const std::string& section_name) -{ - Section* section = Layer::GetSection(system, section_name); - if (!section) - { - m_sections[system].emplace_back( - std::make_unique<RecursiveSection>(m_layer, system, section_name)); - section = m_sections[system].back().get(); - } - return section; + return m_map; } } diff --git a/Source/Core/Common/Config/Layer.h b/Source/Core/Common/Config/Layer.h index edbb706081..8e56ae308a 100644 --- a/Source/Core/Common/Config/Layer.h +++ b/Source/Core/Common/Config/Layer.h @@ -6,18 +6,47 @@ #include <map> #include <memory> +#include <optional> #include <string> #include <vector> +#include "Common/Config/ConfigInfo.h" #include "Common/Config/Enums.h" -#include "Common/Config/Section.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 <typename T> +std::optional<T> TryParse(const std::string& str_value) +{ + T value; + if (!::TryParse(str_value, &value)) + return std::nullopt; + return value; +} + +template <> +inline std::optional<std::string> TryParse(const std::string& str_value) +{ + return str_value; +} +} + template <typename T> struct ConfigInfo; -using LayerMap = std::map<System, std::vector<std::unique_ptr<Section>>>; +class Layer; +using LayerMap = std::map<ConfigLocation, std::optional<std::string>>; class ConfigLayerLoader { @@ -33,6 +62,30 @@ 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: @@ -41,34 +94,45 @@ public: virtual ~Layer(); // Convenience functions - bool Exists(System system, const std::string& section_name, const std::string& key); - bool DeleteKey(System system, const std::string& section_name, const std::string& key); + bool Exists(const ConfigLocation& location) const; + bool DeleteKey(const ConfigLocation& location); + void DeleteAllKeys(); + template <typename T> - bool GetIfExists(System system, const std::string& section_name, const std::string& key, T* value) + T Get(const ConfigInfo<T>& config_info) { - if (Exists(system, section_name, key)) - return GetOrCreateSection(system, section_name)->Get(key, value); - - return false; + return Get<T>(config_info.location).value_or(config_info.default_value); } - virtual Section* GetSection(System system, const std::string& section_name); - virtual Section* GetOrCreateSection(System system, const std::string& section_name); - template <typename T> - T Get(const ConfigInfo<T>& config_info) + std::optional<T> Get(const ConfigLocation& location) { - return GetOrCreateSection(config_info.location.system, config_info.location.section) - ->template Get<T>(config_info.location.key, config_info.default_value); + const std::optional<std::string>& str_value = m_map[location]; + if (!str_value) + return std::nullopt; + return detail::TryParse<T>(*str_value); } template <typename T> void Set(const ConfigInfo<T>& config_info, const T& value) { - GetOrCreateSection(config_info.location.system, config_info.location.section) - ->Set(config_info.location.key, value); + Set<T>(config_info.location, value); } + template <typename T> + void Set(const ConfigLocation& location, const T& value) + { + const std::string new_value = detail::ValueToString(value); + std::optional<std::string>& 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(); @@ -77,19 +141,9 @@ public: const LayerMap& GetLayerMap() const; protected: - bool IsDirty() const; - void ClearDirty(); - - LayerMap m_sections; + bool m_is_dirty = false; + LayerMap m_map; const LayerType m_layer; std::unique_ptr<ConfigLayerLoader> m_loader; }; - -class RecursiveLayer final : public Layer -{ -public: - RecursiveLayer(); - Section* GetSection(System system, const std::string& section_name) override; - Section* GetOrCreateSection(System system, const std::string& section_name) override; -}; } diff --git a/Source/Core/Common/Config/Section.cpp b/Source/Core/Common/Config/Section.cpp deleted file mode 100644 index bb9fcef0e3..0000000000 --- a/Source/Core/Common/Config/Section.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include <cstddef> -#include <map> -#include <memory> - -#include "Common/Assert.h" -#include "Common/Config/Config.h" -#include "Common/Config/Layer.h" -#include "Common/Config/Section.h" -#include "Common/StringUtil.h" - -namespace Config -{ -const std::string& Section::NULL_STRING = ""; - -Section::Section(LayerType layer, System system, const std::string& name) - : m_layer(layer), m_system(system), m_name(name) -{ -} - -bool Section::Exists(const std::string& key) const -{ - return m_values.find(key) != m_values.end(); -} - -bool Section::Delete(const std::string& key) -{ - auto it = m_values.find(key); - if (it == m_values.end()) - return false; - - m_values.erase(it); - - m_deleted_keys.push_back(key); - m_dirty = true; - return true; -} - -void Section::Set(const std::string& key, const std::string& value) -{ - auto it = m_values.find(key); - if (it != m_values.end() && it->second != value) - { - it->second = value; - m_dirty = true; - } - else if (it == m_values.end()) - { - m_values[key] = value; - m_dirty = true; - } -} - -void Section::Set(const std::string& key, u16 newValue) -{ - Section::Set(key, StringFromFormat("0x%04x", newValue)); -} - -void Section::Set(const std::string& key, u32 newValue) -{ - Section::Set(key, StringFromFormat("0x%08x", newValue)); -} - -void Section::Set(const std::string& key, float newValue) -{ - Section::Set(key, StringFromFormat("%#.9g", newValue)); -} - -void Section::Set(const std::string& key, double newValue) -{ - Section::Set(key, StringFromFormat("%#.17g", newValue)); -} - -void Section::Set(const std::string& key, int newValue) -{ - Section::Set(key, std::to_string(newValue)); -} - -void Section::Set(const std::string& key, bool newValue) -{ - Section::Set(key, StringFromBool(newValue)); -} - -void Section::Set(const std::string& key, const std::string& newValue, - const std::string& defaultValue) -{ - if (newValue != defaultValue) - Set(key, newValue); - else - Delete(key); -} - -void Section::SetLines(const std::vector<std::string>& lines) -{ - m_lines = lines; - m_dirty = true; -} - -bool Section::Get(const std::string& key, std::string* value, - const std::string& default_value) const -{ - const auto& it = m_values.find(key); - if (it != m_values.end()) - { - *value = it->second; - return true; - } - else if (&default_value != &NULL_STRING) - { - *value = default_value; - return true; - } - - return false; -} - -bool Section::Get(const std::string& key, int* value, int defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -bool Section::Get(const std::string& key, u16* value, u16 defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -bool Section::Get(const std::string& key, u32* value, u32 defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -bool Section::Get(const std::string& key, bool* value, bool defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -bool Section::Get(const std::string& key, float* value, float defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -bool Section::Get(const std::string& key, double* value, double defaultValue) const -{ - std::string temp; - bool retval = Get(key, &temp); - - if (retval && TryParse(temp, value)) - return true; - - *value = defaultValue; - return false; -} - -// Return a list of all lines in a section -bool Section::GetLines(std::vector<std::string>* lines, const bool remove_comments) const -{ - lines->clear(); - - for (std::string line : m_lines) - { - line = StripSpaces(line); - - if (remove_comments) - { - size_t commentPos = line.find('#'); - if (commentPos == 0) - { - continue; - } - - if (commentPos != std::string::npos) - { - line = StripSpaces(line.substr(0, commentPos)); - } - } - - lines->push_back(line); - } - - return true; -} - -bool Section::HasLines() const -{ - return !m_lines.empty(); -} - -const std::string& Section::GetName() const -{ - return m_name; -} - -const SectionValueMap& Section::GetValues() const -{ - return m_values; -} - -const std::vector<std::string>& Section::GetDeletedKeys() const -{ - return m_deleted_keys; -} - -bool Section::IsDirty() const -{ - return m_dirty; -} -void Section::ClearDirty() -{ - m_dirty = false; -} - -RecursiveSection::RecursiveSection(LayerType layer, System system, const std::string& name) - : Section(layer, system, name) -{ -} - -bool RecursiveSection::Exists(const std::string& key) const -{ - auto layers_it = Config::GetLayers()->find(LayerType::Meta); - do - { - const Section* layer_section = layers_it->second->GetSection(m_system, m_name); - if (layer_section && layer_section->Exists(key)) - { - return true; - } - } while (--layers_it != Config::GetLayers()->end()); - - return false; -} - -bool RecursiveSection::Get(const std::string& key, std::string* value, - const std::string& default_value) const -{ - for (auto layer_id : SEARCH_ORDER) - { - auto layers_it = Config::GetLayers()->find(layer_id); - if (layers_it == Config::GetLayers()->end()) - continue; - - const Section* layer_section = layers_it->second->GetSection(m_system, m_name); - if (layer_section && layer_section->Exists(key)) - { - return layer_section->Get(key, value, default_value); - } - } - - return Section::Get(key, value, default_value); -} - -void RecursiveSection::Set(const std::string& key, const std::string& value) -{ - // The RecursiveSection can't set since it is used to recursively get values from the layer - // map. - // It is only a part of the meta layer, and the meta layer isn't allowed to set any values. - _assert_msg_(COMMON, false, "Don't try to set values here!"); -} -} diff --git a/Source/Core/Common/Config/Section.h b/Source/Core/Common/Config/Section.h deleted file mode 100644 index 948ebd67d4..0000000000 --- a/Source/Core/Common/Config/Section.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include <map> -#include <string> -#include <vector> - -// XXX: Purely for case insensitive compare -#include "Common/CommonTypes.h" -#include "Common/Config/Enums.h" -#include "Common/IniFile.h" - -namespace Config -{ -class Layer; -class ConfigLayerLoader; - -using SectionValueMap = std::map<std::string, std::string, CaseInsensitiveStringCompare>; - -class Section -{ - friend Layer; - friend ConfigLayerLoader; - -public: - Section(LayerType layer, System system, const std::string& name); - virtual ~Section() = default; - - virtual bool Exists(const std::string& key) const; - bool Delete(const std::string& key); - - // Setters - virtual void Set(const std::string& key, const std::string& value); - - void Set(const std::string& key, u16 newValue); - void Set(const std::string& key, u32 newValue); - void Set(const std::string& key, float newValue); - void Set(const std::string& key, double newValue); - void Set(const std::string& key, int newValue); - void Set(const std::string& key, bool newValue); - - // Setters with default values - void Set(const std::string& key, const std::string& newValue, const std::string& defaultValue); - template <typename T> - void Set(const std::string& key, T newValue, const T defaultValue) - { - if (newValue != defaultValue) - Set(key, newValue); - else - Delete(key); - } - - // Getters - virtual bool Get(const std::string& key, std::string* value, - const std::string& default_value = NULL_STRING) const; - - bool Get(const std::string& key, int* value, int defaultValue = 0) const; - bool Get(const std::string& key, u16* value, u16 defaultValue = 0) const; - bool Get(const std::string& key, u32* value, u32 defaultValue = 0) const; - bool Get(const std::string& key, bool* value, bool defaultValue = false) const; - bool Get(const std::string& key, float* value, float defaultValue = 0.0f) const; - bool Get(const std::string& key, double* value, double defaultValue = 0.0) const; - - template <typename T> - T Get(const std::string& key, const T& default_value) const - { - T value; - Get(key, &value, default_value); - return value; - } - - // Section chunk - void SetLines(const std::vector<std::string>& lines); - // XXX: Add to recursive layer - virtual bool GetLines(std::vector<std::string>* lines, const bool remove_comments = true) const; - virtual bool HasLines() const; - const std::string& GetName() const; - const SectionValueMap& GetValues() const; - const std::vector<std::string>& GetDeletedKeys() const; - bool IsDirty() const; - void ClearDirty(); - -protected: - bool m_dirty = false; - - LayerType m_layer; - System m_system; - const std::string m_name; - static const std::string& NULL_STRING; - - SectionValueMap m_values; - std::vector<std::string> m_deleted_keys; - - std::vector<std::string> m_lines; -}; - -// Only to be used with the meta-layer -class RecursiveSection final : public Section -{ -public: - RecursiveSection(LayerType layer, System system, const std::string& name); - - bool Exists(const std::string& key) const override; - - bool Get(const std::string& key, std::string* value, - const std::string& default_value = NULL_STRING) const override; - - void Set(const std::string& key, const std::string& value) override; -}; -} |
