summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Config
diff options
context:
space:
mode:
authorMerryMage <MerryMage@users.noreply.github.com>2017-10-29 19:11:15 +0000
committerMerryMage <MerryMage@users.noreply.github.com>2017-11-15 18:04:40 +0000
commit4c24629b9551cab8af653a2bbcbe6d1639b3edb2 (patch)
tree95f17ded4d887ad4df99463e49078c5de0377aa4 /Source/Core/Common/Config
parentf3b52c07d74d528a81c818d86c12981a6028f351 (diff)
Config: Flatten structures
Originally, Layer contained a std::map of Sections, which containted a std::map containing the (key, value) pairs. Here we flattern this structure so that only one std::map is required, reducing the number of indirections required and vastly simplifying the code.
Diffstat (limited to 'Source/Core/Common/Config')
-rw-r--r--Source/Core/Common/Config/Config.cpp2
-rw-r--r--Source/Core/Common/Config/Config.h1
-rw-r--r--Source/Core/Common/Config/Layer.cpp99
-rw-r--r--Source/Core/Common/Config/Layer.h79
-rw-r--r--Source/Core/Common/Config/Section.cpp249
-rw-r--r--Source/Core/Common/Config/Section.h99
6 files changed, 112 insertions, 417 deletions
diff --git a/Source/Core/Common/Config/Config.cpp b/Source/Core/Common/Config/Config.cpp
index abb2304749..a3504f80d2 100644
--- a/Source/Core/Common/Config/Config.cpp
+++ b/Source/Core/Common/Config/Config.cpp
@@ -133,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 69eac72203..3536f5677c 100644
--- a/Source/Core/Common/Config/Config.h
+++ b/Source/Core/Common/Config/Config.h
@@ -12,7 +12,6 @@
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Enums.h"
#include "Common/Config/Layer.h"
-#include "Common/Config/Section.h"
namespace Config
{
diff --git a/Source/Core/Common/Config/Layer.cpp b/Source/Core/Common/Config/Layer.cpp
index a3912281f5..d4f9e7c633 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,56 +75,44 @@ Layer::~Layer()
Save();
}
-bool Layer::Exists(System system, const std::string& section_name, const std::string& key)
-{
- Section* section = GetSection(system, section_name);
- if (!section)
- return false;
- return section->Exists(key);
-}
-
-bool Layer::DeleteKey(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->Delete(key);
+ const auto iter = m_map.find(location);
+ return iter != m_map.end() && iter->second.has_value();
}
-Section* Layer::GetSection(System system, const std::string& section_name)
+bool Layer::DeleteKey(const ConfigLocation& location)
{
- 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;
+ bool had_value = m_map[location].has_value();
+ m_map[location].reset();
+ return had_value;
}
-Section* Layer::GetOrCreateSection(System system, const std::string& section_name)
+void Layer::DeleteAllKeys()
{
- Section* section = GetSection(system, section_name);
- if (!section)
+ m_is_dirty = true;
+ for (auto& pair : m_map)
{
- m_sections[system].emplace_back(std::make_unique<Section>(m_layer, system, section_name));
- section = m_sections[system].back().get();
+ pair.second.reset();
}
- return section;
}
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();
}
@@ -98,22 +123,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(); });
- });
+ return m_map;
}
}
diff --git a/Source/Core/Common/Config/Layer.h b/Source/Core/Common/Config/Layer.h
index ac5b5c3e78..eb2a6bafca 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
{
@@ -41,32 +70,40 @@ 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;
}
// Explicit load and save of layers
@@ -77,11 +114,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;
};
-} // namespace Config
+}
diff --git a/Source/Core/Common/Config/Section.cpp b/Source/Core/Common/Config/Section.cpp
deleted file mode 100644
index 12adff2b1f..0000000000
--- a/Source/Core/Common/Config/Section.cpp
+++ /dev/null
@@ -1,249 +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;
-}
-}
diff --git a/Source/Core/Common/Config/Section.h b/Source/Core/Common/Config/Section.h
deleted file mode 100644
index 592b791722..0000000000
--- a/Source/Core/Common/Config/Section.h
+++ /dev/null
@@ -1,99 +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;
-};
-}