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.
This commit is contained in:
MerryMage
2017-10-29 19:11:15 +00:00
parent f3b52c07d7
commit 4c24629b95
13 changed files with 220 additions and 551 deletions

View File

@ -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);
template <typename T>
bool GetIfExists(System system, const std::string& section_name, const std::string& key, T* value)
{
if (Exists(system, section_name, key))
return GetOrCreateSection(system, section_name)->Get(key, value);
return false;
}
virtual Section* GetSection(System system, const std::string& section_name);
virtual Section* GetOrCreateSection(System system, const std::string& section_name);
bool Exists(const ConfigLocation& location) const;
bool DeleteKey(const ConfigLocation& location);
void DeleteAllKeys();
template <typename T>
T Get(const ConfigInfo<T>& config_info)
{
return GetOrCreateSection(config_info.location.system, config_info.location.section)
->template Get<T>(config_info.location.key, config_info.default_value);
return Get<T>(config_info.location).value_or(config_info.default_value);
}
template <typename T>
std::optional<T> Get(const ConfigLocation& location)
{
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
}