Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/ConfigSettings.cpp
5654 views
1
#include <cstdint>
2
#include "Common/Data/Format/IniFile.h"
3
#include "Common/Net/URL.h"
4
#include "Common/Log.h"
5
#include "Common/StringUtils.h"
6
7
#include "Core/ConfigSettings.h"
8
#include "Core/ConfigValues.h"
9
#include "Core/Config.h"
10
11
bool ConfigSetting::PerGame(void *ptr) {
12
return g_Config.IsGameSpecific() && g_Config.getPtrLUT().count(ptr) > 0 && g_Config.getPtrLUT()[ptr].second->PerGame();
13
}
14
15
bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *section, bool applyDefaultIfMissing) const {
16
char *owner = (char *)configBlock;
17
_dbg_assert_msg_(offset_ >= 0 && offset_ < configBlock->Size(), "offset: %d size: %d", (int)offset_, (int)configBlock->Size());
18
19
switch (type_) {
20
case Type::TYPE_BOOL:
21
{
22
bool *target = (bool *)(owner + offset_);
23
if (!section || !section->Get(iniKey_, target)) {
24
if (applyDefaultIfMissing) {
25
*target = defaultCallback_.b ? defaultCallback_.b() : default_.b;
26
}
27
return false;
28
}
29
return true;
30
}
31
case Type::TYPE_INT:
32
{
33
int *target = (int *)(owner + offset_);
34
if (translateFrom_ && section) {
35
std::string value;
36
if (section->Get(iniKey_, &value)) {
37
*((int *)(owner + offset_)) = translateFrom_(value);
38
return true;
39
}
40
}
41
if (!section || !section->Get(iniKey_, target)) {
42
if (applyDefaultIfMissing) {
43
*target = defaultCallback_.i ? defaultCallback_.i() : default_.i;
44
}
45
return false;
46
}
47
return true;
48
}
49
case Type::TYPE_UINT32:
50
{
51
uint32_t *target = (uint32_t *)(owner + offset_);
52
if (!section || !section->Get(iniKey_, target)) {
53
if (applyDefaultIfMissing) {
54
*target = defaultCallback_.u ? defaultCallback_.u() : default_.u;
55
}
56
return false;
57
}
58
return true;
59
}
60
case Type::TYPE_UINT64:
61
{
62
uint64_t *target = (uint64_t *)(owner + offset_);
63
if (!section || !section->Get(iniKey_, target)) {
64
if (applyDefaultIfMissing) {
65
*target = defaultCallback_.lu ? defaultCallback_.lu() : default_.lu;
66
}
67
return false;
68
}
69
return true;
70
}
71
case Type::TYPE_FLOAT:
72
{
73
float *target = (float *)(owner + offset_);
74
if (!section || !section->Get(iniKey_, target)) {
75
if (applyDefaultIfMissing) {
76
*target = defaultCallback_.f ? defaultCallback_.f() : default_.f;
77
}
78
return false;
79
}
80
return true;
81
}
82
case Type::TYPE_STRING:
83
{
84
std::string *target = (std::string *)(owner + offset_);
85
if (!section || !section->Get(iniKey_, target)) {
86
if (applyDefaultIfMissing) {
87
if (defaultCallback_.s) {
88
*target = defaultCallback_.s();
89
} else if (default_.s) {
90
*target = default_.s;
91
} else {
92
target->clear();
93
}
94
}
95
return false;
96
}
97
return true;
98
}
99
case Type::TYPE_STRING_VECTOR:
100
{
101
// No support for callbacks for these yet. that's not an issue.
102
std::vector<std::string> *ptr = (std::vector<std::string> *)(owner + offset_);
103
if (!section || !section->Get(iniKey_, ptr)) {
104
if (applyDefaultIfMissing && default_.v) {
105
CopyStrings(ptr, *default_.v);
106
}
107
return false;
108
}
109
MakeUnique(*ptr);
110
return true;
111
}
112
case Type::TYPE_TOUCH_POS:
113
{
114
ConfigTouchPos defaultTouchPos = defaultCallback_.touchPos ? defaultCallback_.touchPos() : default_.touchPos;
115
116
ConfigTouchPos *touchPos = ((ConfigTouchPos *)(owner + offset_));
117
if (!section || (!section->Get(iniKey_, &touchPos->x) && applyDefaultIfMissing)) {
118
touchPos->x = defaultTouchPos.x;
119
}
120
if (!section || (!section->Get(ini2_, &touchPos->y) && applyDefaultIfMissing)) {
121
touchPos->y = defaultTouchPos.y;
122
}
123
if (!section || (!section->Get(ini3_, &touchPos->scale) && applyDefaultIfMissing)) {
124
touchPos->scale = defaultTouchPos.scale;
125
}
126
if (ini4_ && section && section->Get(ini4_, &touchPos->show)) {
127
// do nothing, succeeded.
128
} else if (applyDefaultIfMissing) {
129
touchPos->show = defaultTouchPos.show;
130
}
131
return true;
132
}
133
case Type::TYPE_PATH:
134
{
135
Path *target = (Path *)(owner + offset_);
136
std::string tmp;
137
if (!section || !section->Get(iniKey_, &tmp)) {
138
if (applyDefaultIfMissing) {
139
if (defaultCallback_.p) {
140
*target = defaultCallback_.p();
141
} else {
142
*target = Path(default_.p);
143
}
144
}
145
return false;
146
}
147
*target = Path(tmp);
148
return true;
149
}
150
case Type::TYPE_CUSTOM_BUTTON:
151
{
152
ConfigCustomButton defaultCustomButton = defaultCallback_.customButton ? defaultCallback_.customButton() : default_.customButton;
153
154
ConfigCustomButton *customButton = ((ConfigCustomButton *)(owner + offset_));
155
if (!section || (!section->Get(iniKey_, &customButton->key) && applyDefaultIfMissing)) {
156
customButton->key = defaultCustomButton.key;
157
}
158
if (!section || (!section->Get(ini2_, &customButton->image) && applyDefaultIfMissing)) {
159
customButton->image = defaultCustomButton.image;
160
}
161
if (!section || (!section->Get(ini3_, &customButton->shape) && applyDefaultIfMissing)) {
162
customButton->shape = defaultCustomButton.shape;
163
}
164
if (!section || (!section->Get(ini4_, &customButton->toggle) && applyDefaultIfMissing)) {
165
customButton->toggle = defaultCustomButton.toggle;
166
}
167
if (!section || (!section->Get(ini5_, &customButton->repeat) && applyDefaultIfMissing)) {
168
customButton->repeat = defaultCustomButton.repeat;
169
}
170
return true;
171
}
172
default:
173
_dbg_assert_msg_(false, "Get%.*s): Unexpected ini setting type: %d", STR_VIEW(iniKey_), (int)type_);
174
return false;
175
}
176
}
177
178
void ConfigSetting::WriteToIniSection(const ConfigBlock *configBlock, Section *section) const {
179
if (!SaveSetting()) {
180
return;
181
}
182
_dbg_assert_(section);
183
_dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size());
184
185
const char *owner = (const char *)configBlock;
186
switch (type_) {
187
case Type::TYPE_BOOL:
188
return section->Set(iniKey_, *(const bool *)(owner + offset_));
189
case Type::TYPE_INT:
190
if (translateTo_) {
191
int *ptr_i = (int *)(owner + offset_);
192
std::string value = translateTo_(*ptr_i);
193
return section->Set(iniKey_, value);
194
}
195
return section->Set(iniKey_, *(const int *)(owner + offset_));
196
case Type::TYPE_UINT32:
197
return section->Set(iniKey_, *(const uint32_t *)(owner + offset_));
198
case Type::TYPE_UINT64:
199
return section->Set(iniKey_, *(const uint64_t *)(owner + offset_));
200
case Type::TYPE_FLOAT:
201
return section->Set(iniKey_, *(const float *)(owner + offset_));
202
case Type::TYPE_STRING:
203
return section->Set(iniKey_, *(const std::string *)(owner + offset_));
204
case Type::TYPE_STRING_VECTOR:
205
return section->Set(iniKey_, *(const std::vector<std::string> *)(owner + offset_));
206
case Type::TYPE_PATH:
207
{
208
Path *path = (Path *)(owner + offset_);
209
return section->Set(iniKey_, path->ToString());
210
}
211
case Type::TYPE_TOUCH_POS:
212
{
213
const ConfigTouchPos *touchPos = (const ConfigTouchPos *)(owner + offset_);
214
section->Set(iniKey_, touchPos->x);
215
section->Set(ini2_, touchPos->y);
216
section->Set(ini3_, touchPos->scale);
217
if (ini4_) {
218
section->Set(ini4_, touchPos->show);
219
}
220
return;
221
}
222
case Type::TYPE_CUSTOM_BUTTON:
223
{
224
const ConfigCustomButton *customButton = (const ConfigCustomButton *)(owner + offset_);
225
section->Set(iniKey_, customButton->key);
226
section->Set(ini2_, customButton->image);
227
section->Set(ini3_, customButton->shape);
228
section->Set(ini4_, customButton->toggle);
229
section->Set(ini5_, customButton->repeat);
230
return;
231
}
232
default:
233
_dbg_assert_msg_(false, "Set%.*s): Unexpected ini setting type: %d", STR_VIEW(iniKey_), (int)type_);
234
return;
235
}
236
}
237
238
bool ConfigSetting::RestoreToDefault(ConfigBlock *configBlock, bool log) const {
239
// If the block supports resetting itself, don't allow per-setting resets. Shake them out with this assert.
240
_dbg_assert_(!configBlock->CanResetToDefault());
241
_dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size());
242
243
const char *owner = (const char *)configBlock;
244
switch (type_) {
245
case Type::TYPE_BOOL:
246
{
247
bool *ptr_b = (bool *)(owner + offset_);
248
const bool origValue = *ptr_b;
249
*ptr_b = defaultCallback_.b ? defaultCallback_.b() : default_.b;
250
if (*ptr_b != origValue) {
251
if (log) {
252
INFO_LOG(Log::System, "Restored %.*s from %s to default %s", STR_VIEW(iniKey_),
253
origValue ? "true" : "false",
254
*ptr_b ? "true" : "false");
255
}
256
return true;
257
}
258
break;
259
}
260
case Type::TYPE_INT:
261
{
262
int *ptr_i = (int *)(owner + offset_);
263
const int origValue = *ptr_i;
264
*ptr_i = defaultCallback_.i ? defaultCallback_.i() : default_.i;
265
if (*ptr_i != origValue) {
266
if (log) {
267
INFO_LOG(Log::System, "Restored %.*s from %d to default %d", STR_VIEW(iniKey_),
268
origValue, *ptr_i);
269
}
270
return true;
271
}
272
break;
273
}
274
case Type::TYPE_UINT32:
275
{
276
uint32_t *ptr_u = (uint32_t *)(owner + offset_);
277
const uint32_t origValue = *ptr_u;
278
*ptr_u = defaultCallback_.u ? defaultCallback_.u() : default_.u;
279
if (*ptr_u != origValue) {
280
if (log) {
281
INFO_LOG(Log::System, "Restored %.*s from %u to default %u", STR_VIEW(iniKey_),
282
origValue, *ptr_u);
283
}
284
return true;
285
}
286
break;
287
}
288
case Type::TYPE_UINT64:
289
{
290
uint64_t *ptr_lu = (uint64_t *)(owner + offset_);
291
const uint64_t origValue = *ptr_lu;
292
*ptr_lu = defaultCallback_.lu ? defaultCallback_.lu() : default_.lu;
293
if (*ptr_lu != origValue) {
294
if (log) {
295
INFO_LOG(Log::System, "Restored %.*s from %llu to default %llu", STR_VIEW(iniKey_),
296
(unsigned long long)origValue, (unsigned long long)(*ptr_lu));
297
}
298
return true;
299
}
300
break;
301
}
302
case Type::TYPE_FLOAT:
303
{
304
float *ptr_f = (float *)(owner + offset_);
305
const float origValue = *ptr_f;
306
*ptr_f = defaultCallback_.f ? defaultCallback_.f() : default_.f;
307
if (*ptr_f != origValue) {
308
if (log) {
309
INFO_LOG(Log::System, "Restored %.*s from %f to default %f", STR_VIEW(iniKey_),
310
origValue, *ptr_f);
311
}
312
return true;
313
}
314
break;
315
}
316
case Type::TYPE_STRING:
317
{
318
std::string *ptr_s = (std::string *)(owner + offset_);
319
const std::string origValue = *ptr_s;
320
if (defaultCallback_.s) {
321
*ptr_s = defaultCallback_.s();
322
} else if (default_.s != nullptr) {
323
*ptr_s = default_.s;
324
} else {
325
*ptr_s = "";
326
}
327
if (*ptr_s != origValue) {
328
if (log) {
329
INFO_LOG(Log::System, "Restored %.*s from \"%s\" to default \"%s\"", STR_VIEW(iniKey_),
330
origValue.c_str(), ptr_s->c_str());
331
}
332
return true;
333
}
334
break;
335
}
336
case Type::TYPE_STRING_VECTOR:
337
{
338
std::vector<std::string> *ptr_vec = (std::vector<std::string> *)(owner + offset_);
339
CopyStrings(ptr_vec, *default_.v);
340
break;
341
}
342
case Type::TYPE_TOUCH_POS:
343
{
344
ConfigTouchPos *ptr_touchPos = (ConfigTouchPos *)(owner + offset_);
345
*ptr_touchPos = defaultCallback_.touchPos ? defaultCallback_.touchPos() : default_.touchPos;
346
break;
347
}
348
case Type::TYPE_PATH:
349
{
350
Path *ptr_path = (Path *)(owner + offset_);
351
if (defaultCallback_.p) {
352
*ptr_path = defaultCallback_.p();
353
break;
354
} else if (default_.p) {
355
*ptr_path = Path(default_.p);
356
} else {
357
ptr_path->clear();
358
}
359
break;
360
}
361
case Type::TYPE_CUSTOM_BUTTON:
362
{
363
ConfigCustomButton *ptr_customButton = (ConfigCustomButton *)(owner + offset_);
364
*ptr_customButton = defaultCallback_.customButton ? defaultCallback_.customButton() : default_.customButton;
365
break;
366
}
367
default:
368
_dbg_assert_msg_(false, "RestoreToDefault(%.*s): Unexpected ini setting type: %d", STR_VIEW(iniKey_), (int)type_);
369
break;
370
}
371
return false;
372
}
373
374
// Might be used to copy individual settings from defaulted blocks. Didn't end up using this for now.
375
void ConfigSetting::CopyFromBlock(const ConfigBlock *other) {
376
_dbg_assert_(offset_ >= 0 && offset_ < other->Size());
377
378
const char *otherOwner = (const char *)other;
379
const char *thisOwner = (const char *)this;
380
switch (type_) {
381
case Type::TYPE_BOOL: *(bool *)(thisOwner + offset_) = *(const bool *)(otherOwner + offset_); break;
382
case Type::TYPE_INT: *(int *)(thisOwner + offset_) = *(const int *)(otherOwner + offset_); break;
383
case Type::TYPE_UINT32: *(uint32_t *)(thisOwner + offset_) = *(const uint32_t *)(otherOwner + offset_); break;
384
case Type::TYPE_UINT64: *(uint64_t *)(thisOwner + offset_) = *(const uint64_t *)(otherOwner + offset_); break;
385
case Type::TYPE_FLOAT: *(float *)(thisOwner + offset_) = *(const float *)(otherOwner + offset_); break;
386
case Type::TYPE_STRING: *(std::string *)(thisOwner + offset_) = *(const std::string *)(otherOwner + offset_); break;
387
case Type::TYPE_STRING_VECTOR: *(std::vector<std::string> *)(thisOwner + offset_) = *(const std::vector<std::string> *)(otherOwner + offset_); break;
388
case Type::TYPE_PATH: *(Path *)(thisOwner + offset_) = *(const Path *)(otherOwner + offset_); break;
389
case Type::TYPE_TOUCH_POS: *(ConfigTouchPos *)(thisOwner + offset_) = *(const ConfigTouchPos *)(otherOwner + offset_); break;
390
case Type::TYPE_CUSTOM_BUTTON: *(ConfigCustomButton *)(thisOwner + offset_) = *(const ConfigCustomButton *)(otherOwner + offset_); break;
391
default:
392
_dbg_assert_msg_(false, "CopyFromBlock(%.*s): Unexpected setting type: %d", STR_VIEW(iniKey_), (int)type_);
393
return;
394
}
395
}
396
397
void ConfigSetting::ReportSetting(const ConfigBlock *configBlock, UrlEncoder &data, const std::string &prefix) const {
398
if (!Report())
399
return;
400
401
_dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size());
402
const char *owner = (const char *)configBlock;
403
const std::string key = join(prefix, iniKey_);
404
405
switch (type_) {
406
case Type::TYPE_BOOL: return data.Add(key, *(const bool *)(owner + offset_));
407
case Type::TYPE_INT: return data.Add(key, *(const int *)(owner + offset_));
408
case Type::TYPE_UINT32: return data.Add(key, *(const uint32_t *)(owner + offset_));
409
case Type::TYPE_UINT64: return data.Add(key, *(const uint64_t *)(owner + offset_));
410
case Type::TYPE_FLOAT: return data.Add(key, *(const float *)(owner + offset_));
411
case Type::TYPE_STRING: return data.Add(key, *(const std::string *)(owner + offset_));
412
case Type::TYPE_STRING_VECTOR: return data.Add(key, *(const std::vector<std::string> *)(owner + offset_));
413
case Type::TYPE_PATH: return data.Add(key, ((const Path *)(owner + offset_))->ToString());
414
case Type::TYPE_TOUCH_POS: return; // Doesn't report.
415
case Type::TYPE_CUSTOM_BUTTON: return; // Doesn't report.
416
default:
417
_dbg_assert_msg_(false, "Report(%s): Unexpected ini setting type: %d", key.c_str(), (int)type_);
418
return;
419
}
420
}
421
422