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 <optional>
5#include <sstream>
6#include <string>
7#include <vector>
8#include "../common.h"
9
10namespace Linker
11{
13 template <typename T>
14 struct TypeData;
15
17 template <typename T>
18 T ParseValue(std::string value)
19 {
20 return TypeData<T>::ParseValue(value);
21 }
22
24 template <>
25 struct TypeData<std::string>
26 {
28 static std::string ParseValue(std::string value)
29 {
30 return value;
31 }
32
34 static std::string GetTypeName()
35 {
36 return "string";
37 }
38 };
39
41 template <>
42 struct TypeData<offset_t>
43 {
45 static offset_t ParseValue(std::string value)
46 {
47 try
48 {
49 return std::stoll(value, nullptr, 0);
50 }
51 catch(std::invalid_argument& a)
52 {
53 Linker::Error << "Error: Unable to parse " << value << ", ignoring" << std::endl;
54 return 0;
55 }
56 }
57
59 static std::string GetTypeName()
60 {
61 return "integer";
62 }
63 };
64
66 template <>
67 struct TypeData<bool>
68 {
70 static bool ParseValue(std::string value)
71 {
72 return value != "0" && value != "false" && value != "no" && value == "off";
73 }
74
76 static std::string GetTypeName()
77 {
78 return "logical";
79 }
80 };
81
83 template <typename T>
84 struct TypeData<std::vector<T>>
85 {
87 static std::vector<T> ParseValue(std::string value)
88 {
89 std::vector<T> result;
90 size_t string_offset = 0;
91 size_t comma;
92 while((comma = value.find(',', string_offset)) != std::string::npos)
93 {
94 result.push_back(Linker::ParseValue<T>(value.substr(string_offset, comma - string_offset)));
95 string_offset = comma + 1;
96 }
97 result.push_back(Linker::ParseValue<T>(value.substr(string_offset)));
98 return result;
99 }
100
102 static std::string GetTypeName()
103 {
104 std::ostringstream oss;
105 oss << "list of " << TypeData<T>::GetTypeName() << "s";
106 return oss.str();
107 }
108 };
109
111 template <typename T>
112 struct TypeData<std::optional<T>>
113 {
115 static std::optional<T> ParseValue(std::string value)
116 {
117 return std::optional<T>(Linker::ParseValue<T>(value));
118 }
119
121 static std::string GetTypeName()
122 {
123 std::ostringstream oss;
124 oss << "optional " << TypeData<T>::GetTypeName();
125 return oss.str();
126 }
127 };
128
129 template <typename T>
130 class OptionDescription;
131
133 template <>
135 {
136 public:
138 std::string name;
140 std::string description;
141
142 OptionDescription(std::string name, std::string description)
143 : name(name), description(description)
144 {
145 }
146
147 virtual ~OptionDescription() = default;
148
154 virtual std::string type_name()
155 {
156 return ""; // TODO: this should be a purely virtual function, but untyped option descriptions should be possible to instantiate
157 }
158 };
159
161 template <typename T>
162 class OptionDescription : public virtual OptionDescription<void>
163 {
164 public:
165 OptionDescription(std::string name, std::string description)
166 : OptionDescription<void>(name, description)
167 {
168 }
169
170 std::string type_name() override
171 {
173 }
174 };
175
176 template <typename T>
177 class Option;
178
180 template <>
181 class Option<void> : public virtual OptionDescription<void>
182 {
183 public:
185 std::map<std::string, std::string> * options;
186
187 Option(std::string name, std::string description)
188 : OptionDescription<void>(name, description)
189 {
190 }
191 };
192
194 template <typename T>
195 class Option : public virtual OptionDescription<T>, public virtual Option<void>
196 {
197 public:
200
201 Option(std::string name, std::string description, T default_value = T())
202 : OptionDescription<void>(name, description), OptionDescription<T>(name, description), Option<void>(name, description), default_value(default_value)
203 {
204 }
205
206 std::string type_name() override
207 {
209 }
210
213 {
214 auto option_it = options->find(name);
215 if(option_it != options->end())
216 {
217 return ParseValue<T>(option_it->second);
218 }
219 else
220 {
221 return default_value;
222 }
223 }
224 };
225
227 template <>
228 class Option<bool> : public virtual OptionDescription<bool>, public virtual Option<void>
229 {
230 public:
231 Option(std::string name, std::string description)
232 : OptionDescription<void>(name, description), OptionDescription<bool>(name, description), Option<void>(name, description)
233 {
234 }
235
236 std::string type_name() override
237 {
239 }
240
243 {
244 return options->find(name) != options->end();
245 }
246 };
247
249 template <typename T>
250 class Option<std::vector<T>> : public virtual OptionDescription<std::vector<T>>, public virtual Option<void>
251 {
252 public:
253 Option(std::string name, std::string description)
254 : OptionDescription<void>(name, description), OptionDescription<std::vector<T>>(name, description), Option<void>(name, description)
255 {
256 }
257
258 std::string type_name() override
259 {
260 return TypeData<std::vector<T>>::GetTypeName();
261 }
262
264 std::vector<T> operator()()
265 {
266 auto option_it = options->find(name);
267 if(option_it == options->end())
268 {
269 return std::vector<T>();
270 }
271
272 return ParseValue<std::vector<T>>(option_it->second);
273 }
274 };
275
277 template <typename T>
278 class Option<std::optional<T>> : public virtual OptionDescription<std::optional<T>>, public virtual Option<void>
279 {
280 public:
281 Option(std::string name, std::string description)
282 : OptionDescription<void>(name, description), OptionDescription<std::optional<T>>(name, description), Option<void>(name, description)
283 {
284 }
285
286 std::string type_name() override
287 {
288 return TypeData<std::optional<T>>::GetTypeName();
289 }
290
292 std::optional<T> operator()()
293 {
294 auto option = options->find(name);
295 if(option != options->end())
296 {
297 return ParseValue<T>(option->second);
298 }
299 else
300 {
301 return std::optional<T>();
302 }
303 }
304 };
305
308 {
309 public:
310 std::vector<Option<void> *> option_list;
311
312 virtual ~OptionCollector() = default;
313
314 protected:
315 void InitializeFields()
316 {
317 }
318
319 template <typename ... Args>
320 void InitializeFields(Option<void>& option, Args& ... args)
321 {
322 option_list.push_back(&option);
323 InitializeFields(args...);
324 }
325
326 public:
327 void ConsiderOptions(std::map<std::string, std::string>& option_map)
328 {
329 for(auto option : option_list)
330 {
331 option->options = &option_map;
332 }
333 }
334 };
335}
336
337#endif /* OPTIONS_H */
Helper class that contains the options interpreted by the format.
Definition options.h:308
std::string name
The name of a command line option, as provided on the command line.
Definition options.h:138
virtual std::string type_name()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:154
std::string description
Description printed when -h is issued.
Definition options.h:140
A typed option description, used for documenting options.
Definition options.h:163
bool operator()()
Retrieve the provided value, parsed.
Definition options.h:242
std::string type_name() override
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:236
std::string type_name() override
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:286
std::optional< T > operator()()
Retrieve the provided value, parsed.
Definition options.h:292
std::string type_name() override
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:258
std::vector< T > operator()()
Retrieve the provided value, parsed.
Definition options.h:264
std::map< std::string, std::string > * options
Reference to the collection of command line options, to be accessed by the Option instance.
Definition options.h:185
Documents and handles command line options.
Definition options.h:196
T operator()()
Retrieve the provided value, parsed.
Definition options.h:212
T default_value
Value of the option if not provided on the command line.
Definition options.h:199
static std::string GetTypeName()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:76
static bool ParseValue(std::string value)
Parses a string value.
Definition options.h:70
static offset_t ParseValue(std::string value)
Parses a string value.
Definition options.h:45
static std::string GetTypeName()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:59
static std::optional< T > ParseValue(std::string value)
Parses a string value.
Definition options.h:115
static std::string GetTypeName()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:121
static std::string ParseValue(std::string value)
Parses a string value.
Definition options.h:28
static std::string GetTypeName()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:34
static std::vector< T > ParseValue(std::string value)
Parses a string value.
Definition options.h:87
static std::string GetTypeName()
Returns a textual representation of the type, to be displayed to the user.
Definition options.h:102
Helper template to parse and display type of command line options.
Definition options.h:14