yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
flag.h
Go to the documentation of this file.
1#ifndef YAZE_UTIL_FLAG_H_
2#define YAZE_UTIL_FLAG_H_
3
4#include <memory>
5#include <sstream>
6#include <stdexcept>
7#include <string>
8#include <unordered_map>
9#include <vector>
10
11namespace yaze {
12namespace util {
13
14// Base interface for all flags.
15class IFlag {
16 public:
17 virtual ~IFlag() = default;
18
19 // Returns the full name (e.g. "--count") used for this flag.
20 virtual const std::string& name() const = 0;
21
22 // Returns help text describing how to use this flag.
23 virtual const std::string& help() const = 0;
24
25 // Parses a string value into the underlying type.
26 virtual void ParseValue(const std::string& text) = 0;
27};
28
29template <typename T>
30class Flag : public IFlag {
31 public:
32 Flag(const std::string& name, const T& default_value,
33 const std::string& help_text)
34 : name_(name),
35 value_(default_value),
36 default_(default_value),
37 help_(help_text) {}
38
39 const std::string& name() const override { return name_; }
40 const std::string& help() const override { return help_; }
41
42 // Attempts to parse a string into type T using a stringstream.
43 void ParseValue(const std::string& text) override {
44 std::stringstream ss(text);
45 T parsed;
46 if (!(ss >> parsed)) {
47 throw std::runtime_error("Failed to parse flag: " + name_);
48 }
49 value_ = parsed;
50 }
51
52 // Returns the current (parsed or default) value of the flag.
53 const T& Get() const { return value_; }
54
55 private:
56 std::string name_;
59 std::string help_;
60};
61
63 public:
64 // Registers a flag in the global registry.
65 // The return type is a pointer to the newly created flag.
66 template <typename T>
67 Flag<T>* RegisterFlag(const std::string& name, const T& default_value,
68 const std::string& help_text) {
69 auto flag = std::make_unique<Flag<T>>(name, default_value, help_text);
70 Flag<T>* raw_ptr =
71 flag.get(); // We keep a non-owning pointer to use later.
72 flags_[name] = std::move(flag);
73 return raw_ptr;
74 }
75
76 // Returns a shared interface pointer if found, otherwise nullptr.
77 IFlag* GetFlag(const std::string& name) const {
78 auto it = flags_.find(name);
79 if (it == flags_.end()) {
80 return nullptr;
81 }
82 return it->second.get();
83 }
84
85 // Returns all registered flags for iteration, help text, etc.
86 std::vector<IFlag*> AllFlags() const {
87 std::vector<IFlag*> result;
88 result.reserve(flags_.size());
89 for (auto const& kv : flags_) {
90 result.push_back(kv.second.get());
91 }
92 return result;
93 }
94
95 private:
96 std::unordered_map<std::string, std::unique_ptr<IFlag>> flags_;
97};
98
100 // Guaranteed to be initialized once per process.
101 static FlagRegistry* registry = new FlagRegistry();
102 return registry;
103}
104
105#define DECLARE_FLAG(type, name) extern yaze::util::Flag<type>* FLAGS_##name
106
107// Defines a global Flag<type>* FLAGS_<name> and registers it.
108#define DEFINE_FLAG(type, name, default_val, help_text) \
109 yaze::util::Flag<type>* FLAGS_##name = \
110 yaze::util::global_flag_registry()->RegisterFlag<type>( \
111 "--" #name, (default_val), (help_text))
112
113// Retrieves the current value of a declared flag.
114#define FLAG_VALUE(name) (FLAGS_##name->Get())
115
117 public:
118 explicit FlagParser(FlagRegistry* registry) : registry_(registry) {}
119
120 // Parses flags out of the given command line arguments.
121 void Parse(int argc, char** argv) {
122 std::vector<std::string> tokens;
123 for (int i = 0; i < argc; i++) {
124 tokens.push_back(argv[i]);
125 }
126 Parse(&tokens);
127 }
128
129 // Parses flags out of the given token list. Recognizes forms:
130 // --flag=value or --flag value
131 // Any token not recognized as a flag is left in `leftover`.
132 void Parse(std::vector<std::string>* tokens);
133
134 private:
136
137 // Checks if there is an '=' sign in the token, extracting flag name and
138 // value. e.g. "--count=42" -> flag_name = "--count", value_string = "42"
139 // returns true if '=' was found
140 bool ExtractFlagAndValue(const std::string& token, std::string* flag_name,
141 std::string* value_string) {
142 const size_t eq_pos = token.find('=');
143 if (eq_pos == std::string::npos) {
144 return false;
145 }
146 *flag_name = token.substr(0, eq_pos);
147 *value_string = token.substr(eq_pos + 1);
148 return true;
149 }
150};
151
152} // namespace util
153} // namespace yaze
154
155#endif // YAZE_UTIL_FLAG_H_
FlagRegistry * registry_
Definition flag.h:135
bool ExtractFlagAndValue(const std::string &token, std::string *flag_name, std::string *value_string)
Definition flag.h:140
void Parse(int argc, char **argv)
Definition flag.h:121
FlagParser(FlagRegistry *registry)
Definition flag.h:118
Flag< T > * RegisterFlag(const std::string &name, const T &default_value, const std::string &help_text)
Definition flag.h:67
IFlag * GetFlag(const std::string &name) const
Definition flag.h:77
std::vector< IFlag * > AllFlags() const
Definition flag.h:86
std::unordered_map< std::string, std::unique_ptr< IFlag > > flags_
Definition flag.h:96
Flag(const std::string &name, const T &default_value, const std::string &help_text)
Definition flag.h:32
const std::string & name() const override
Definition flag.h:39
void ParseValue(const std::string &text) override
Definition flag.h:43
const std::string & help() const override
Definition flag.h:40
std::string help_
Definition flag.h:59
std::string name_
Definition flag.h:56
const T & Get() const
Definition flag.h:53
virtual void ParseValue(const std::string &text)=0
virtual ~IFlag()=default
virtual const std::string & name() const =0
virtual const std::string & help() const =0
FlagRegistry * global_flag_registry()
Definition flag.h:99
Main namespace for the application.
Definition controller.cc:18