RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
options.h
1#ifndef OPTIONS_H
2#define OPTIONS_H
3
4#include <sstream>
5
6namespace Linker
7{
8 template <typename T>
9 struct TypeData;
10
11 template <typename T>
12 T ParseValue(std::string value)
13 {
14 return TypeData<T>::ParseValue(value);
15 }
16
17 template <>
18 struct TypeData<std::string>
19 {
20 static std::string ParseValue(std::string value)
21 {
22 return value;
23 }
24
25 static std::string GetTypeName()
26 {
27 return "string";
28 }
29 };
30
31 template <>
32 struct TypeData<offset_t>
33 {
34 static offset_t ParseValue(std::string value)
35 {
36 try
37 {
38 return std::stoll(value, nullptr, 0);
39 }
40 catch(std::invalid_argument& a)
41 {
42 Linker::Error << "Error: Unable to parse " << value << ", ignoring" << std::endl;
43 return 0;
44 }
45 }
46
47 static std::string GetTypeName()
48 {
49 return "integer";
50 }
51 };
52
53 template <>
54 struct TypeData<bool>
55 {
56 static bool ParseValue(std::string value)
57 {
58 return value != "0" && value != "false" && value != "no" && value == "off";
59 }
60
61 static std::string GetTypeName()
62 {
63 return "logical";
64 }
65 };
66
67 template <typename T>
68 struct TypeData<std::vector<T>>
69 {
70 static std::vector<T> ParseValue(std::string value)
71 {
72 std::vector<T> result;
73 size_t string_offset = 0;
74 size_t comma;
75 while((comma = value.find(',', string_offset)) != std::string::npos)
76 {
77 result.push_back(Linker::ParseValue<T>(value.substr(string_offset, comma - string_offset)));
78 string_offset = comma + 1;
79 }
80 result.push_back(Linker::ParseValue<T>(value.substr(string_offset)));
81 return result;
82 }
83
84 static std::string GetTypeName()
85 {
86 std::ostringstream oss;
87 oss << "list of " << TypeData<T>::GetTypeName() << "s";
88 return oss.str();
89 }
90 };
91
92 template <typename T>
93 struct TypeData<std::optional<T>>
94 {
95 static std::optional<T> ParseValue(std::string value)
96 {
97 return std::optional<T>(Linker::ParseValue<T>(value));
98 }
99
100 static std::string GetTypeName()
101 {
102 std::ostringstream oss;
103 oss << "optional " << TypeData<T>::GetTypeName();
104 return oss.str();
105 }
106 };
107
108 template <typename T>
109 class Option;
110
111 template <>
112 class Option<void>
113 {
114 public:
115 std::map<std::string, std::string> * options;
116
117 std::string name;
118 std::string description;
119
120 Option(std::string name, std::string description)
121 : name(name), description(description)
122 {
123 }
124
125 virtual std::string type_name() = 0;
126
127 virtual ~Option() = default;
128 };
129
130 template <typename T>
131 class Option : public Option<void>
132 {
133 public:
134 T default_value;
135
136 Option(std::string name, std::string description, T default_value = T())
137 : Option<void>(name, description), default_value(default_value)
138 {
139 }
140
141 std::string type_name() override
142 {
144 }
145
146 T operator()()
147 {
148 auto option_it = options->find(name);
149 if(option_it != options->end())
150 {
151 return ParseValue<T>(option_it->second);
152 }
153 else
154 {
155 return default_value;
156 }
157 }
158 };
159
160 template <>
161 class Option<bool> : public Option<void>
162 {
163 public:
164 Option(std::string name, std::string description)
165 : Option<void>(name, description)
166 {
167 }
168
169 std::string type_name() override
170 {
172 }
173
174 bool operator()()
175 {
176 return options->find(name) != options->end();
177 }
178 };
179
180 template <typename T>
181 class Option<std::vector<T>> : public Option<void>
182 {
183 public:
184 Option(std::string name, std::string description)
185 : Option<void>(name, description)
186 {
187 }
188
189 std::string type_name() override
190 {
191 return TypeData<std::vector<T>>::GetTypeName();
192 }
193
194 std::vector<T> operator()()
195 {
196 auto option_it = options->find(name);
197 if(option_it == options->end())
198 {
199 return std::vector<T>();
200 }
201
202 return ParseValue<std::vector<T>>(option_it->second);
203 }
204 };
205
206 template <typename T>
207 class Option<std::optional<T>> : public Option<void>
208 {
209 public:
210 Option(std::string name, std::string description)
211 : Option<void>(name, description)
212 {
213 }
214
215 std::string type_name() override
216 {
217 return TypeData<std::optional<T>>::GetTypeName();
218 }
219
220 std::optional<T> operator()()
221 {
222 auto option = options->find(name);
223 if(option != options->end())
224 {
225 return ParseValue<T>(option->second);
226 }
227 else
228 {
229 return std::optional<T>();
230 }
231 }
232 };
233
235 {
236 public:
237 std::vector<Option<void> *> option_list;
238
239 virtual ~OptionCollector() = default;
240
241 protected:
242 void InitializeFields()
243 {
244 }
245
246 template <typename ... Args>
247 void InitializeFields(Option<void>& option, Args ... args)
248 {
249 option_list.push_back(&option);
250 InitializeFields(args...);
251 }
252
253 public:
254 void ConsiderOptions(std::map<std::string, std::string>& option_map)
255 {
256 for(auto option : option_list)
257 {
258 option->options = &option_map;
259 }
260 }
261 };
262}
263
264#endif /* OPTIONS_H */
Definition options.h:235
Definition options.h:132
Definition options.h:9