Layer.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2016 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <map>
  5. #include <memory>
  6. #include <optional>
  7. #include <string>
  8. #include <type_traits>
  9. #include <vector>
  10. #include "Common/Config/ConfigInfo.h"
  11. #include "Common/Config/Enums.h"
  12. #include "Common/StringUtil.h"
  13. namespace Config
  14. {
  15. namespace detail
  16. {
  17. template <typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
  18. std::optional<T> TryParse(const std::string& str_value)
  19. {
  20. T value;
  21. if (!::TryParse(str_value, &value))
  22. return std::nullopt;
  23. return value;
  24. }
  25. template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
  26. std::optional<T> TryParse(const std::string& str_value)
  27. {
  28. const auto result = TryParse<std::underlying_type_t<T>>(str_value);
  29. if (result)
  30. return static_cast<T>(*result);
  31. return {};
  32. }
  33. template <>
  34. inline std::optional<std::string> TryParse(const std::string& str_value)
  35. {
  36. return str_value;
  37. }
  38. } // namespace detail
  39. template <typename T>
  40. class Info;
  41. class Layer;
  42. using LayerMap = std::map<Location, std::optional<std::string>>;
  43. class ConfigLayerLoader
  44. {
  45. public:
  46. explicit ConfigLayerLoader(LayerType layer);
  47. virtual ~ConfigLayerLoader();
  48. virtual void Load(Layer* config_layer) = 0;
  49. virtual void Save(Layer* config_layer) = 0;
  50. LayerType GetLayer() const;
  51. private:
  52. const LayerType m_layer;
  53. };
  54. class Section
  55. {
  56. public:
  57. using iterator = LayerMap::iterator;
  58. Section(iterator begin_, iterator end_) : m_begin(begin_), m_end(end_) {}
  59. iterator begin() const { return m_begin; }
  60. iterator end() const { return m_end; }
  61. private:
  62. iterator m_begin;
  63. iterator m_end;
  64. };
  65. class ConstSection
  66. {
  67. public:
  68. using iterator = LayerMap::const_iterator;
  69. ConstSection(iterator begin_, iterator end_) : m_begin(begin_), m_end(end_) {}
  70. iterator begin() const { return m_begin; }
  71. iterator end() const { return m_end; }
  72. private:
  73. iterator m_begin;
  74. iterator m_end;
  75. };
  76. class Layer
  77. {
  78. public:
  79. explicit Layer(LayerType layer);
  80. explicit Layer(std::unique_ptr<ConfigLayerLoader> loader);
  81. virtual ~Layer();
  82. // Convenience functions
  83. bool Exists(const Location& location) const;
  84. bool DeleteKey(const Location& location);
  85. void DeleteAllKeys();
  86. template <typename T>
  87. T Get(const Info<T>& config_info) const
  88. {
  89. return Get<T>(config_info.GetLocation()).value_or(config_info.GetDefaultValue());
  90. }
  91. template <typename T>
  92. std::optional<T> Get(const Location& location) const
  93. {
  94. const auto iter = m_map.find(location);
  95. if (iter == m_map.end() || !iter->second.has_value())
  96. return std::nullopt;
  97. return detail::TryParse<T>(*iter->second);
  98. }
  99. template <typename T>
  100. bool Set(const Info<T>& config_info, const std::common_type_t<T>& value)
  101. {
  102. return Set(config_info.GetLocation(), value);
  103. }
  104. template <typename T>
  105. bool Set(const Location& location, const T& value)
  106. {
  107. return Set(location, ValueToString(value));
  108. }
  109. bool Set(const Location& location, std::string new_value)
  110. {
  111. const auto iter = m_map.find(location);
  112. if (iter != m_map.end() && iter->second == new_value)
  113. return false;
  114. m_is_dirty = true;
  115. m_map.insert_or_assign(location, std::move(new_value));
  116. return true;
  117. }
  118. void MarkAsDirty() { m_is_dirty = true; }
  119. Section GetSection(System system, const std::string& section);
  120. ConstSection GetSection(System system, const std::string& section) const;
  121. // Explicit load and save of layers
  122. void Load();
  123. void Save();
  124. LayerType GetLayer() const;
  125. const LayerMap& GetLayerMap() const;
  126. protected:
  127. bool m_is_dirty = false;
  128. LayerMap m_map;
  129. const LayerType m_layer;
  130. std::unique_ptr<ConfigLayerLoader> m_loader;
  131. };
  132. } // namespace Config