OXYGENHUB
◆ main openmsx / src / settings / EnumSetting.hh
3.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef ENUMSETTING_HH
2
#define ENUMSETTING_HH
3
4
#include "Setting.hh"
5
6
#include <concepts>
7
#include <iterator>
8
#include <ranges>
9
#include <utility>
10
#include <vector>
11
12
namespace openmsx {
13
14
class TclObject;
15
16
// non-templatized base class
17
class EnumSettingBase
18
{
19
public:
20
	struct MapEntry {
21
		template<typename Enum>
22
		MapEntry(std::string_view name_, Enum value_)
23
			: name(name_), value(static_cast<int>(value_)) {}
24
25
		std::string name; // cannot be string_view because of the 'default_machine' setting
26
		int value;
27
	};
28
	using Map = std::vector<MapEntry>;
29
	[[nodiscard]] const auto& getMap() const { return baseMap; }
30
31
	explicit EnumSettingBase(Map&& m);
32
33
	[[nodiscard]] int fromStringBase(std::string_view str) const;
34
	[[nodiscard]] std::string_view toStringBase(int value) const;
35
36
	[[nodiscard]] auto getPossibleValues() const {
37
		return std::views::transform(baseMap,
38
			[](const auto& e) -> std::string_view { return e.name; });
39
	}
40
41
	void additionalInfoBase(TclObject& result) const;
42
	void tabCompletionBase(std::vector<std::string>& tokens) const;
43
44
private:
45
	Map baseMap;
46
};
47
48
template<typename T>
49
concept EnumSettingValue = requires(T t, int i) {
50
	static_cast<T>(i);
51
	static_cast<int>(t);
52
};
53
54
template<EnumSettingValue T> class EnumSetting final : public EnumSettingBase, public Setting
55
{
56
public:
57
	using Map = EnumSettingBase::Map;
58
59
	EnumSetting(CommandController& commandController, std::string_view name,
60
	            static_string_view description, T initialValue,
61
	            Map&& map_, Save save = Save::YES);
62
63
	[[nodiscard]] std::string_view getTypeString() const override;
64
	void additionalInfo(TclObject& result) const override;
65
	void tabCompletion(std::vector<std::string>& tokens) const override;
66
67
	[[nodiscard]] T getEnum() const noexcept;
68
	void setEnum(T e);
69
	[[nodiscard]] std::string_view getString() const;
70
71
private:
72
	std::string_view toString(T e) const;
73
};
74
75
76
//-------------
77
78
79
template<EnumSettingValue T>
80
EnumSetting<T>::EnumSetting(
81
		CommandController& commandController_, std::string_view name,
82
		static_string_view description_, T initialValue,
83
		Map&& map, Save save_)
84
	: EnumSettingBase(std::move(map))
85
	, Setting(commandController_, name, description_,
86
	          TclObject(EnumSettingBase::toStringBase(static_cast<int>(initialValue))), save_)
87
{
88
	setChecker([this](const TclObject& newValue) {
89
		(void)fromStringBase(newValue.getString()); // may throw
90
	});
91
	init();
92
}
93
94
template<EnumSettingValue T>
95
std::string_view EnumSetting<T>::getTypeString() const
96
{
97
	return "enumeration";
98
}
99
100
template<EnumSettingValue T>
101
void EnumSetting<T>::additionalInfo(TclObject& result) const
102
{
103
	additionalInfoBase(result);
104
}
105
106
template<EnumSettingValue T>
107
void EnumSetting<T>::tabCompletion(std::vector<std::string>& tokens) const
108
{
109
	tabCompletionBase(tokens);
110
}
111
112
template<EnumSettingValue T>
113
T EnumSetting<T>::getEnum() const noexcept
114
{
115
	return static_cast<T>(fromStringBase(getValue().getString()));
116
}
117
template<> inline bool EnumSetting<bool>::getEnum() const noexcept
118
{
119
	// _exactly_ the same functionality as above, but suppress VS warning
120
	return fromStringBase(getValue().getString()) != 0;
121
}
122
123
template<EnumSettingValue T>
124
void EnumSetting<T>::setEnum(T e)
125
{
126
	setValue(TclObject(toString(e)));
127
}
128
129
template<EnumSettingValue T>
130
std::string_view EnumSetting<T>::getString() const
131
{
132
	return getValue().getString();
133
}
134
135
template<EnumSettingValue T>
136
std::string_view EnumSetting<T>::toString(T e) const
137
{
138
	return toStringBase(static_cast<int>(e));
139
}
140
141
} // namespace openmsx
142
143
#endif