settings_enums: More aggressively use macros

This lets us define an enum and all the textual representations
of its values in one swing. All for the price of some ugly macros.
This commit is contained in:
lat9nq 2023-06-20 23:25:39 -04:00
parent 02c48a80f6
commit 7ffbffe170
1 changed files with 149 additions and 351 deletions

View File

@ -3,15 +3,72 @@
#pragma once #pragma once
#include <map>
#include <string> #include <string>
#include <type_traits> #include <utility>
#include <typeindex> #include <vector>
#include <typeinfo>
#include "common/common_types.h" #include "common/common_types.h"
namespace Settings { namespace Settings {
template <typename T>
struct Canonicalization {
static constexpr std::vector<std::pair<std::string, u32>> Get();
};
#define PAIR_45(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
#define PAIR_44(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_45(N, __VA_ARGS__))
#define PAIR_43(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_44(N, __VA_ARGS__))
#define PAIR_42(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_43(N, __VA_ARGS__))
#define PAIR_41(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_42(N, __VA_ARGS__))
#define PAIR_40(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_41(N, __VA_ARGS__))
#define PAIR_39(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_40(N, __VA_ARGS__))
#define PAIR_38(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_39(N, __VA_ARGS__))
#define PAIR_37(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_38(N, __VA_ARGS__))
#define PAIR_36(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_37(N, __VA_ARGS__))
#define PAIR_35(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_36(N, __VA_ARGS__))
#define PAIR_34(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_35(N, __VA_ARGS__))
#define PAIR_33(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_34(N, __VA_ARGS__))
#define PAIR_32(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_33(N, __VA_ARGS__))
#define PAIR_31(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_32(N, __VA_ARGS__))
#define PAIR_30(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_31(N, __VA_ARGS__))
#define PAIR_29(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_30(N, __VA_ARGS__))
#define PAIR_28(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_29(N, __VA_ARGS__))
#define PAIR_27(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_28(N, __VA_ARGS__))
#define PAIR_26(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_27(N, __VA_ARGS__))
#define PAIR_25(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_26(N, __VA_ARGS__))
#define PAIR_24(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_25(N, __VA_ARGS__))
#define PAIR_23(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_24(N, __VA_ARGS__))
#define PAIR_22(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_23(N, __VA_ARGS__))
#define PAIR_21(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_22(N, __VA_ARGS__))
#define PAIR_20(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_21(N, __VA_ARGS__))
#define PAIR_19(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_20(N, __VA_ARGS__))
#define PAIR_18(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_19(N, __VA_ARGS__))
#define PAIR_17(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_18(N, __VA_ARGS__))
#define PAIR_16(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_17(N, __VA_ARGS__))
#define PAIR_15(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_16(N, __VA_ARGS__))
#define PAIR_14(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_15(N, __VA_ARGS__))
#define PAIR_13(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_14(N, __VA_ARGS__))
#define PAIR_12(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_13(N, __VA_ARGS__))
#define PAIR_11(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_12(N, __VA_ARGS__))
#define PAIR_10(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_11(N, __VA_ARGS__))
#define PAIR_9(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_10(N, __VA_ARGS__))
#define PAIR_8(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_9(N, __VA_ARGS__))
#define PAIR_7(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_8(N, __VA_ARGS__))
#define PAIR_6(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_7(N, __VA_ARGS__))
#define PAIR_5(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_6(N, __VA_ARGS__))
#define PAIR_4(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_5(N, __VA_ARGS__))
#define PAIR_3(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_4(N, __VA_ARGS__))
#define PAIR_2(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_3(N, __VA_ARGS__))
#define PAIR_1(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_2(N, __VA_ARGS__))
#define PAIR(N, X, ...) {#X, static_cast<u32>(N::X)} __VA_OPT__(, PAIR_1(N, __VA_ARGS__))
#define ENUM(NAME, ...) \
enum class NAME : u32 { __VA_ARGS__ }; \
template <> \
constexpr std::vector<std::pair<std::string, u32>> Canonicalization<NAME>::Get() { \
return {PAIR(NAME, __VA_ARGS__)}; \
}
enum class AudioEngine : u32 { enum class AudioEngine : u32 {
Auto, Auto,
Cubeb, Cubeb,
@ -19,380 +76,121 @@ enum class AudioEngine : u32 {
Null, Null,
}; };
enum class AudioMode : u32 { template <>
Mono, constexpr std::vector<std::pair<std::string, u32>> Canonicalization<AudioEngine>::Get() {
Stereo, return {
Surround,
};
enum class Language : u32 {
Japanese,
EnglishAmerican,
French,
German,
Italian,
Spanish,
Chinese,
Korean,
Dutch,
Portuguese,
Russian,
Taiwanese,
EnglishBritish,
FrenchCanadian,
SpanishLatin,
ChineseSimplified,
ChineseTraditional,
PortugueseBrazilian,
};
enum class Region : u32 {
Japan,
Usa,
Europe,
Australia,
China,
Korea,
Taiwan,
};
enum class TimeZone : u32 {
Auto,
Default,
CET,
CST6CDT,
Cuba,
EET,
Egypt,
Eire,
EST,
EST5EDT,
GB,
GBEire,
GMT,
GMTPlusZero,
GMTMinusZero,
GMTZero,
Greenwich,
Hongkong,
HST,
Iceland,
Iran,
Israel,
Jamaica,
Japan,
Kwajalein,
Libya,
MET,
MST,
MST7MDT,
Navajo,
NZ,
NZCHAT,
Poland,
Portugal,
PRC,
PST8PDT,
ROC,
ROK,
Singapore,
Turkey,
UCT,
Universal,
UTC,
W_SU,
WET,
Zulu,
};
enum class AnisotropyMode : u32 {
Automatic = 0,
Default = 1,
X2 = 2,
X4 = 3,
X8 = 4,
X16 = 5,
};
enum class AstcDecodeMode : u32 {
Cpu = 0,
Gpu = 1,
CpuAsynchronous = 2,
};
enum class AstcRecompression : u32 {
Uncompressed = 0,
Bc1 = 1,
Bc3 = 2,
};
enum class VSyncMode : u32 {
Immediate = 0,
Mailbox = 1,
Fifo = 2,
FifoRelaxed = 3,
};
enum class RendererBackend : u32 {
OpenGL = 0,
Vulkan = 1,
Null = 2,
};
enum class ShaderBackend : u32 {
Glsl = 0,
Glasm = 1,
SpirV = 2,
};
enum class GpuAccuracy : u32 {
Normal = 0,
High = 1,
Extreme = 2,
};
enum class CpuAccuracy : u32 {
Auto = 0,
Accurate = 1,
Unsafe = 2,
Paranoid = 3,
};
enum class FullscreenMode : u32 {
Borderless = 0,
Exclusive = 1,
};
enum class NvdecEmulation : u32 {
Off = 0,
Cpu = 1,
Gpu = 2,
};
enum class ResolutionSetup : u32 {
Res1_2X = 0,
Res3_4X = 1,
Res1X = 2,
Res3_2X = 3,
Res2X = 4,
Res3X = 5,
Res4X = 6,
Res5X = 7,
Res6X = 8,
Res7X = 9,
Res8X = 10,
};
enum class ScalingFilter : u32 {
NearestNeighbor = 0,
Bilinear = 1,
Bicubic = 2,
Gaussian = 3,
ScaleForce = 4,
Fsr = 5,
LastFilter = Fsr,
};
enum class AntiAliasing : u32 {
None = 0,
Fxaa = 1,
Smaa = 2,
LastAA = Smaa,
};
enum class AspectRatio : u32 {
R16_9,
R4_3,
R21_9,
R16_10,
Stretch,
};
#define X(ENUM, NAME) \
{ (#NAME), static_cast<u32>(ENUM::NAME) }
static const std::map<std::type_index, std::map<std::string, u32>> canonicalizations = {
{typeid(AudioEngine),
{
{"auto", static_cast<u32>(AudioEngine::Auto)}, {"auto", static_cast<u32>(AudioEngine::Auto)},
{"cubeb", static_cast<u32>(AudioEngine::Cubeb)}, {"cubeb", static_cast<u32>(AudioEngine::Cubeb)},
{"sdl2", static_cast<u32>(AudioEngine::Sdl2)}, {"sdl2", static_cast<u32>(AudioEngine::Sdl2)},
{"null", static_cast<u32>(AudioEngine::Null)}, {"null", static_cast<u32>(AudioEngine::Null)},
}}, };
{typeid(AudioMode), }
{
X(AudioMode, Mono),
X(AudioMode, Stereo),
X(AudioMode, Surround),
}},
{typeid(Language),
{
X(Language, Japanese),
X(Language, EnglishAmerican),
X(Language, French),
X(Language, German),
X(Language, Italian),
X(Language, Spanish),
X(Language, Chinese),
X(Language, Korean),
X(Language, Dutch),
X(Language, Portuguese),
X(Language, Russian),
X(Language, Taiwanese),
X(Language, EnglishBritish),
X(Language, FrenchCanadian),
X(Language, SpanishLatin),
X(Language, ChineseSimplified),
X(Language, ChineseTraditional),
X(Language, PortugueseBrazilian),
}},
{typeid(Region),
{
X(Region, Japan),
X(Region, Usa),
X(Region, Europe),
X(Region, Australia),
X(Region, China),
X(Region, Korea),
X(Region, Taiwan),
}},
{typeid(TimeZone),
{
X(TimeZone, Auto), X(TimeZone, Default), X(TimeZone, CET),
X(TimeZone, CST6CDT), X(TimeZone, Cuba), X(TimeZone, EET),
X(TimeZone, Egypt), X(TimeZone, Eire), X(TimeZone, EST5EDT),
X(TimeZone, GB), X(TimeZone, GBEire), X(TimeZone, GMT),
X(TimeZone, GMTPlusZero), X(TimeZone, GMTMinusZero), X(TimeZone, GMTZero),
X(TimeZone, Greenwich), X(TimeZone, Hongkong), X(TimeZone, HST),
X(TimeZone, Iceland), X(TimeZone, Iran), X(TimeZone, Israel),
X(TimeZone, Jamaica), X(TimeZone, Japan), X(TimeZone, Kwajalein),
X(TimeZone, Libya), X(TimeZone, MET), X(TimeZone, MST),
X(TimeZone, MST7MDT), X(TimeZone, Navajo), X(TimeZone, NZ),
X(TimeZone, NZCHAT), X(TimeZone, Poland), X(TimeZone, Portugal),
X(TimeZone, PRC), X(TimeZone, ROC), X(TimeZone, ROK),
X(TimeZone, Singapore), X(TimeZone, Turkey), X(TimeZone, UCT),
X(TimeZone, Universal), X(TimeZone, UTC), X(TimeZone, W_SU),
X(TimeZone, WET), X(TimeZone, Zulu),
}},
{typeid(AnisotropyMode),
{
X(AnisotropyMode, Automatic),
X(AnisotropyMode, Default),
X(AnisotropyMode, X2),
X(AnisotropyMode, X4),
X(AnisotropyMode, X8),
X(AnisotropyMode, X16),
}},
{typeid(AstcDecodeMode),
{
X(AstcDecodeMode, Cpu),
X(AstcDecodeMode, Gpu),
X(AstcDecodeMode, CpuAsynchronous),
}},
{typeid(AstcRecompression),
{
X(AstcRecompression, Uncompressed),
X(AstcRecompression, Bc1),
X(AstcRecompression, Bc3),
}},
{typeid(VSyncMode),
{
X(VSyncMode, Immediate),
X(VSyncMode, Mailbox),
X(VSyncMode, Fifo),
X(VSyncMode, FifoRelaxed),
}},
{typeid(RendererBackend),
{
X(RendererBackend, OpenGL),
X(RendererBackend, Vulkan),
X(RendererBackend, Null),
}},
{typeid(ShaderBackend),
{
X(ShaderBackend, Glsl),
X(ShaderBackend, Glasm),
X(ShaderBackend, SpirV),
}},
{typeid(GpuAccuracy),
{
X(GpuAccuracy, Normal),
X(GpuAccuracy, High),
X(GpuAccuracy, Extreme),
}},
{typeid(CpuAccuracy),
{
X(CpuAccuracy, Auto),
X(CpuAccuracy, Accurate),
X(CpuAccuracy, Unsafe),
X(CpuAccuracy, Paranoid),
}},
{typeid(FullscreenMode),
{
X(FullscreenMode, Borderless),
X(FullscreenMode, Exclusive),
}},
{typeid(NvdecEmulation),
{
X(NvdecEmulation, Off),
X(NvdecEmulation, Cpu),
X(NvdecEmulation, Gpu),
}},
{typeid(ResolutionSetup),
{
X(ResolutionSetup, Res1_2X),
X(ResolutionSetup, Res3_4X),
X(ResolutionSetup, Res1X),
X(ResolutionSetup, Res3_2X),
X(ResolutionSetup, Res2X),
X(ResolutionSetup, Res3X),
X(ResolutionSetup, Res4X),
X(ResolutionSetup, Res5X),
X(ResolutionSetup, Res6X),
X(ResolutionSetup, Res7X),
X(ResolutionSetup, Res8X),
}},
{typeid(ScalingFilter),
{
X(ScalingFilter, NearestNeighbor),
X(ScalingFilter, Bilinear),
X(ScalingFilter, Bicubic),
X(ScalingFilter, Gaussian),
X(ScalingFilter, ScaleForce),
X(ScalingFilter, Fsr),
}},
{typeid(AntiAliasing),
{
X(AntiAliasing, None),
X(AntiAliasing, Fxaa),
X(AntiAliasing, Smaa),
}},
{typeid(AspectRatio),
{
X(AspectRatio, R16_9),
X(AspectRatio, R4_3),
X(AspectRatio, R21_9),
X(AspectRatio, R16_10),
X(AspectRatio, Stretch),
}}};
#undef X ENUM(AudioMode, Mono, Stereo, Surround);
static const std::string invalid_string{"(invalid setting)"}; ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch,
Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin,
ChineseSimplified, ChineseTraditional, PortugueseBrazilian);
ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan);
ENUM(TimeZone, Auto, Default, CET, CST6CDT, Cuba, EET, Egypt, Eire, EST, EST5EDT, GB, GBEire, GMT,
GMTPlusZero, GMTMinusZero, GMTZero, Greenwich, Hongkong, HST, Iceland, Iran, Israel, Jamaica,
Japan, Kwajalein, Libya, MET, MST, MST7MDT, Navajo, NZ, NZCHAT, Poland, Portugal, PRC, PST8PDT,
ROC, ROK, Singapore, Turkey, UCT, Universal, UTC, W_SU, WET, Zulu);
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
ENUM(RendererBackend, OpenGL, Vulkan, Null);
ENUM(ShaderBackend, Glsl, Glasm, SpirV);
ENUM(GpuAccuracy, Normal, High, Extreme);
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
ENUM(FullscreenMode, Borderless, Exclusive);
ENUM(NvdecEmulation, Off, Cpu, Gpu);
ENUM(ResolutionSetup, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X,
Res8X);
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, LastFilter);
ENUM(AntiAliasing, None, Fxaa, Smaa, LastAA);
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
template <typename Type> template <typename Type>
const std::string& CanonicalizeEnum(Type id) { constexpr std::string CanonicalizeEnum(Type id) {
auto& group = canonicalizations.at(typeid(Type)); const auto group = Canonicalization<Type>::Get();
for (auto& [name, value] : group) { for (auto& [name, value] : group) {
if (static_cast<Type>(value) == id) { if (static_cast<Type>(value) == id) {
return name; return name;
} }
} }
return invalid_string; return "unknown";
} }
template <typename Type> template <typename Type>
static Type ToEnum(const std::string& canonicalization) { constexpr Type ToEnum(const std::string& canonicalization) {
return static_cast<Type>(canonicalizations.at(typeid(Type)).at(canonicalization)); const auto group = Canonicalization<Type>::Get();
for (auto& [name, value] : group) {
if (name == canonicalization) {
return static_cast<Type>(value);
}
}
return {};
} }
} // namespace Settings } // namespace Settings
#undef ENUM
#undef PAIR
#undef PAIR_1
#undef PAIR_2
#undef PAIR_3
#undef PAIR_4
#undef PAIR_5
#undef PAIR_6
#undef PAIR_7
#undef PAIR_8
#undef PAIR_9
#undef PAIR_10
#undef PAIR_12
#undef PAIR_13
#undef PAIR_14
#undef PAIR_15
#undef PAIR_16
#undef PAIR_17
#undef PAIR_18
#undef PAIR_19
#undef PAIR_20
#undef PAIR_22
#undef PAIR_23
#undef PAIR_24
#undef PAIR_25
#undef PAIR_26
#undef PAIR_27
#undef PAIR_28
#undef PAIR_29
#undef PAIR_30
#undef PAIR_32
#undef PAIR_33
#undef PAIR_34
#undef PAIR_35
#undef PAIR_36
#undef PAIR_37
#undef PAIR_38
#undef PAIR_39
#undef PAIR_40
#undef PAIR_42
#undef PAIR_43
#undef PAIR_44
#undef PAIR_45