1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <functional>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Enums.h"
#include "Common/Config/Layer.h"
namespace Config
{
struct ConfigChangedCallbackID
{
size_t id = std::numeric_limits<size_t>::max();
bool operator==(const ConfigChangedCallbackID&) const = default;
};
using ConfigChangedCallback = std::function<void()>;
// Layer management
void AddLayer(std::unique_ptr<ConfigLayerLoader> loader);
std::shared_ptr<Layer> GetLayer(LayerType layer);
void RemoveLayer(LayerType layer);
// Returns an ID that should be passed to RemoveConfigChangedCallback() when the callback is no
// longer needed. The callback may be called from any thread.
[[nodiscard]] ConfigChangedCallbackID AddConfigChangedCallback(ConfigChangedCallback func);
void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id);
void OnConfigChanged();
// Returns the number of times the config has changed in the current execution of the program
u64 GetConfigVersion();
// Explicit load and save of layers
void Load();
void Save();
void Init();
void Shutdown();
void ClearCurrentRunLayer();
const std::string& GetSystemName(System system);
std::optional<System> GetSystemFromName(const std::string& system);
const std::string& GetLayerName(LayerType layer);
LayerType GetActiveLayerForConfig(const Location&);
std::optional<std::string> GetAsString(const Location&);
template <typename T>
T Get(LayerType layer, const Info<T>& info)
{
if (layer == LayerType::Meta)
return Get(info);
return GetLayer(layer)->Get(info);
}
template <typename T>
T Get(const Layer* game_layer, const Info<T>& setting)
{
if (game_layer != nullptr)
return game_layer->Get(setting);
return Get(setting);
}
template <typename T>
T Get(const Info<T>& info)
{
CachedValue<T> cached = info.GetCachedValue();
const u64 config_version = GetConfigVersion();
if (cached.config_version < config_version)
{
cached.value = GetUncached(info);
cached.config_version = config_version;
info.TryToSetCachedValue(cached);
}
return std::move(cached.value);
}
template <typename T>
T GetUncached(const Info<T>& info)
{
const std::optional<std::string> str = GetAsString(info.GetLocation());
if (!str)
return info.GetDefaultValue();
return detail::TryParse<T>(*str).value_or(info.GetDefaultValue());
}
template <typename T>
T GetBase(const Info<T>& info)
{
return Get(LayerType::Base, info);
}
template <typename T>
LayerType GetActiveLayerForConfig(const Info<T>& info)
{
return GetActiveLayerForConfig(info.GetLocation());
}
template <typename InfoT, typename ValueT>
void Set(LayerType layer, const InfoT& info, const ValueT& value)
{
if (GetLayer(layer)->Set(info, value))
OnConfigChanged();
}
template <typename InfoT, typename ValueT>
void SetBase(const Info<InfoT>& info, const ValueT& value)
{
Set(LayerType::Base, info, value);
}
template <typename InfoT, typename ValueT>
void SetCurrent(const Info<InfoT>& info, const ValueT& value)
{
Set(LayerType::CurrentRun, info, value);
}
template <typename InfoT, typename ValueT>
void SetBaseOrCurrent(const Info<InfoT>& info, const ValueT& value)
{
if (GetActiveLayerForConfig(info) == LayerType::Base)
Set(LayerType::Base, info, value);
else
Set(LayerType::CurrentRun, info, value);
}
template <typename T>
void DeleteKey(LayerType layer, const Info<T>& info)
{
if (GetLayer(layer)->DeleteKey(info.GetLocation()))
OnConfigChanged();
}
// Used to defer OnConfigChanged until after the completion of many config changes.
class ConfigChangeCallbackGuard
{
public:
ConfigChangeCallbackGuard();
~ConfigChangeCallbackGuard();
ConfigChangeCallbackGuard(const ConfigChangeCallbackGuard&) = delete;
ConfigChangeCallbackGuard& operator=(const ConfigChangeCallbackGuard&) = delete;
};
} // namespace Config
|