2017-02-16 16:58:40 +01:00
|
|
|
// Copyright 2016 Dolphin Emulator Project
|
2021-07-05 03:22:19 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-02-16 16:58:40 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
2017-10-29 20:11:15 +01:00
|
|
|
#include <optional>
|
2017-02-16 16:58:40 +01:00
|
|
|
#include <string>
|
2018-05-11 22:38:44 +02:00
|
|
|
#include <type_traits>
|
2017-02-16 16:58:40 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2017-10-29 20:11:15 +01:00
|
|
|
#include "Common/Config/ConfigInfo.h"
|
2017-02-16 16:58:40 +01:00
|
|
|
#include "Common/Config/Enums.h"
|
2017-10-29 20:11:15 +01:00
|
|
|
#include "Common/StringUtil.h"
|
2017-02-16 16:58:40 +01:00
|
|
|
|
|
|
|
namespace Config
|
|
|
|
{
|
2017-10-29 20:11:15 +01:00
|
|
|
namespace detail
|
|
|
|
{
|
2018-05-11 22:38:44 +02:00
|
|
|
template <typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
|
2017-10-29 20:11:15 +01:00
|
|
|
std::optional<T> TryParse(const std::string& str_value)
|
|
|
|
{
|
|
|
|
T value;
|
|
|
|
if (!::TryParse(str_value, &value))
|
|
|
|
return std::nullopt;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2018-05-11 22:38:44 +02:00
|
|
|
template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
|
|
|
|
std::optional<T> TryParse(const std::string& str_value)
|
|
|
|
{
|
|
|
|
const auto result = TryParse<std::underlying_type_t<T>>(str_value);
|
|
|
|
if (result)
|
|
|
|
return static_cast<T>(*result);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2017-10-29 20:11:15 +01:00
|
|
|
template <>
|
|
|
|
inline std::optional<std::string> TryParse(const std::string& str_value)
|
|
|
|
{
|
|
|
|
return str_value;
|
|
|
|
}
|
2019-05-06 01:48:12 +02:00
|
|
|
} // namespace detail
|
2017-10-29 20:11:15 +01:00
|
|
|
|
2017-08-02 19:20:52 +02:00
|
|
|
template <typename T>
|
2020-09-20 13:58:17 +02:00
|
|
|
class Info;
|
2017-08-02 19:20:52 +02:00
|
|
|
|
2017-10-29 20:11:15 +01:00
|
|
|
class Layer;
|
2020-05-02 14:39:40 +02:00
|
|
|
using LayerMap = std::map<Location, std::optional<std::string>>;
|
2017-02-16 16:58:40 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2017-10-30 19:10:05 +01:00
|
|
|
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; }
|
2018-04-12 14:18:04 +02:00
|
|
|
|
2017-10-30 19:10:05 +01:00
|
|
|
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; }
|
2018-04-12 14:18:04 +02:00
|
|
|
|
2017-10-30 19:10:05 +01:00
|
|
|
private:
|
|
|
|
iterator m_begin;
|
|
|
|
iterator m_end;
|
|
|
|
};
|
|
|
|
|
2017-02-16 16:58:40 +01:00
|
|
|
class Layer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit Layer(LayerType layer);
|
|
|
|
explicit Layer(std::unique_ptr<ConfigLayerLoader> loader);
|
|
|
|
virtual ~Layer();
|
|
|
|
|
|
|
|
// Convenience functions
|
2020-05-02 14:39:40 +02:00
|
|
|
bool Exists(const Location& location) const;
|
|
|
|
bool DeleteKey(const Location& location);
|
2017-10-29 20:11:15 +01:00
|
|
|
void DeleteAllKeys();
|
|
|
|
|
2017-02-16 16:58:40 +01:00
|
|
|
template <typename T>
|
2020-05-02 14:39:40 +02:00
|
|
|
T Get(const Info<T>& config_info) const
|
2017-02-16 16:58:40 +01:00
|
|
|
{
|
2020-09-20 13:58:17 +02:00
|
|
|
return Get<T>(config_info.GetLocation()).value_or(config_info.GetDefaultValue());
|
2017-02-16 16:58:40 +01:00
|
|
|
}
|
|
|
|
|
2017-08-02 19:20:52 +02:00
|
|
|
template <typename T>
|
2020-05-02 14:39:40 +02:00
|
|
|
std::optional<T> Get(const Location& location) const
|
2017-08-02 19:20:52 +02:00
|
|
|
{
|
2019-07-30 18:43:54 +02:00
|
|
|
const auto iter = m_map.find(location);
|
|
|
|
if (iter == m_map.end() || !iter->second.has_value())
|
2017-10-29 20:11:15 +01:00
|
|
|
return std::nullopt;
|
2019-07-30 18:43:54 +02:00
|
|
|
return detail::TryParse<T>(*iter->second);
|
2017-08-02 19:20:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2021-02-26 00:14:00 +01:00
|
|
|
bool Set(const Info<T>& config_info, const std::common_type_t<T>& value)
|
2017-08-02 19:20:52 +02:00
|
|
|
{
|
2021-02-26 00:14:00 +01:00
|
|
|
return Set(config_info.GetLocation(), value);
|
2017-10-29 20:11:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2021-02-26 00:14:00 +01:00
|
|
|
bool Set(const Location& location, const T& value)
|
2017-10-29 20:11:15 +01:00
|
|
|
{
|
2021-02-26 00:14:00 +01:00
|
|
|
return Set(location, ValueToString(value));
|
2018-06-03 14:55:39 +02:00
|
|
|
}
|
|
|
|
|
2021-02-26 00:14:00 +01:00
|
|
|
bool Set(const Location& location, std::string new_value)
|
2018-06-03 14:55:39 +02:00
|
|
|
{
|
2019-07-30 18:43:54 +02:00
|
|
|
const auto iter = m_map.find(location);
|
|
|
|
if (iter != m_map.end() && iter->second == new_value)
|
2021-02-26 00:14:00 +01:00
|
|
|
return false;
|
2017-10-29 20:11:15 +01:00
|
|
|
m_is_dirty = true;
|
2019-07-30 18:43:54 +02:00
|
|
|
m_map.insert_or_assign(location, std::move(new_value));
|
2021-02-26 00:14:00 +01:00
|
|
|
return true;
|
2017-08-02 19:20:52 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 15:23:36 +01:00
|
|
|
void MarkAsDirty() { m_is_dirty = true; }
|
|
|
|
|
2017-10-30 19:10:05 +01:00
|
|
|
Section GetSection(System system, const std::string& section);
|
|
|
|
ConstSection GetSection(System system, const std::string& section) const;
|
|
|
|
|
2017-02-16 16:58:40 +01:00
|
|
|
// Explicit load and save of layers
|
|
|
|
void Load();
|
|
|
|
void Save();
|
|
|
|
|
|
|
|
LayerType GetLayer() const;
|
|
|
|
const LayerMap& GetLayerMap() const;
|
|
|
|
|
|
|
|
protected:
|
2017-10-29 20:11:15 +01:00
|
|
|
bool m_is_dirty = false;
|
|
|
|
LayerMap m_map;
|
2017-02-16 16:58:40 +01:00
|
|
|
const LayerType m_layer;
|
|
|
|
std::unique_ptr<ConfigLayerLoader> m_loader;
|
|
|
|
};
|
2019-05-06 01:48:12 +02:00
|
|
|
} // namespace Config
|