sandbox
Loading...
Searching...
No Matches
settings.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_CORE_SETTINGS_HPP_
3#define LIBSBX_CORE_SETTINGS_HPP_
4
5#include <any>
6#include <mutex>
7#include <optional>
8#include <stdexcept>
9#include <string_view>
10#include <string>
11#include <unordered_map>
12#include <variant>
13
14
15#include <libsbx/utility/hashed_string.hpp>
16
17#include <libsbx/memory/observer_ptr.hpp>
18
19namespace sbx::core {
20
21namespace prototype {
22
23template<std::default_initializable Type>
25 Type min{};
26 Type max{};
27}; // struct setting_range
28
29template<typename Type>
31 std::string_view name;
32 std::optional<setting_range<Type>> range{std::nullopt};
33}; // struct setting_key
34
35class settings {
36
37public:
38
39 template<typename Type>
40 static auto set(setting_key<Type> key, Type value) -> void {
41 auto lock = std::scoped_lock{_mutex};
42
43 _data[std::string{key.name}] = std::move(value);
44 }
45
46 template<typename Type>
47 static auto get(setting_key<Type> key) -> Type {
48 auto lock = std::scoped_lock{_mutex};
49
50 auto entry = _data.find(std::string{key.name});
51
52 if (entry == _data.end()) {
53 throw std::runtime_error("setting not found");
54 }
55
56 return std::any_cast<Type>(entry->second);
57 }
58
59 template<typename Type>
60 static Type get_or(setting_key<Type> key, const Type& fallback) {
61 auto lock = std::scoped_lock{_mutex};
62
63 auto entry = _data.find(std::string{key.name});
64
65 if (entry == _data.end()) {
66 return fallback;
67 }
68
69 return std::any_cast<Type>(entry->second);
70 }
71
72private:
73
74 static inline std::unordered_map<std::string, std::any> _data;
75 static inline std::mutex _mutex;
76
77}; // class settings
78
79}; // namespace prototype
80
81template<typename Type>
82concept setting_type = std::is_same_v<Type, bool> || std::is_same_v<Type, std::uint32_t> || std::is_same_v<Type, std::int32_t> || std::is_same_v<Type, std::float_t> || std::is_same_v<Type, std::string>;
83
84class settings {
85
86public:
87
88 using entry_type = std::variant<std::monostate, bool, std::uint32_t, std::int32_t, std::float_t, std::string>;
89
90 struct value_type {
91 entry_type entry;
92 entry_type min;
93 entry_type max;
94 };
95
96 struct group_entry {
98 value_type& value;
99 }; // struct group_entry
100
101 struct group {
103 std::vector<group_entry> entries;
104 }; // struct group
105
106 settings() = default;
107
108 template<setting_type Type>
109 auto set(const utility::hashed_string& key, const Type& value) -> void {
110 _settings[key] = value_type{value, std::monostate{}, std::monostate{}};
111 }
112
113 template<setting_type Type>
114 auto set(const utility::hashed_string& key, const Type& value, const Type& min, const Type& max) -> void {
115 _settings[key] = value_type{value, min, max};
116 }
117
118 template<setting_type Type>
119 auto get(const utility::hashed_string& key) const -> memory::observer_ptr<const Type> {
120 if (auto entry = _settings.find(key); entry != _settings.end()) {
121 return std::get_if<Type>(&entry->second.entry);
122 }
123
124 return nullptr;
125 }
126
127 // template<setting_type Type>
128 // auto get_or_set(const utility::hashed_string& key, const Type& default_value) -> memory::observer_ptr<const Type> {
129 // if (auto entry = _settings.find(key); entry != _settings.end()) {
130 // return std::get_if<Type>(&entry->second);
131 // }
132
133 // set(key, default_value);
134
135 // return get<Type>(key);
136 // }
137
138 template<typename Callable>
139 requires (std::is_invocable_v<Callable, const utility::hashed_string&, group&>)
140 auto for_each(Callable&& callable) -> void {
141 auto grouped = std::unordered_map<utility::hashed_string, group>{};
142
143 for (auto& [key, value] : _settings) {
144 const auto position = key.rfind("::");
145
146 const auto has_namespace = (position != utility::hashed_string::npos);
147
148 const auto group_name = has_namespace ? key.substr(0, position) : key;
149 const auto entry_name = has_namespace ? key.substr(position + 2u) : key;
150
151 grouped[group_name].name = group_name;
152 grouped[group_name].entries.emplace_back(group_entry{entry_name, value});
153 }
154
155 for (auto& [group_name, group] : grouped) {
156 std::invoke(callable, group_name, group);
157 }
158 }
159
160private:
161
162 std::unordered_map<utility::hashed_string, value_type> _settings;
163
164}; // class settings
165
166} // namespace sbx::core
167
168#endif // LIBSBX_CORE_SETTINGS_HPP_
Definition: settings.hpp:35
Definition: settings.hpp:84
Definition: hashed_string.hpp:17
Definition: settings.hpp:30
Definition: settings.hpp:24
Definition: settings.hpp:96
Definition: settings.hpp:101
Definition: settings.hpp:90