Open Lighting Architecture 0.10.9
Loading...
Searching...
No Matches
FlagsPrivate.h
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 * FlagsPrivate.h
17 * Command line flag (option) handling.
18 * Copyright (C) 2013 Simon Newton
19 */
20
29#ifndef INCLUDE_OLA_BASE_FLAGSPRIVATE_H_
30#define INCLUDE_OLA_BASE_FLAGSPRIVATE_H_
31
32#include <getopt.h>
33#include <string.h>
34#include <ola/StringUtils.h>
35#include <ola/base/Macro.h>
36#include <map>
37#include <sstream>
38#include <string>
39#include <utility>
40#include <vector>
41
42namespace ola {
43
53 public:
54 virtual ~FlagInterface() {}
55
59 virtual const char* name() const = 0;
60
64 virtual char short_opt() const = 0;
65
69 virtual bool has_arg() const = 0;
70
74 virtual const char* arg_type() const = 0;
75
79 virtual std::string help() const = 0;
80
86 virtual bool present() const = 0;
87
93 virtual bool SetValue(const std::string &input) = 0;
94};
95
99class BaseFlag : public FlagInterface {
100 public:
107 BaseFlag(const char *arg_type, const char *short_opt, const char *help)
108 : m_arg_type(arg_type),
109 m_short_opt(short_opt[0]),
110 m_help(help),
111 m_present(false) {
112 }
113
114 char short_opt() const { return m_short_opt; }
115 const char* arg_type() const { return m_arg_type; }
116 std::string help() const { return m_help; }
117 bool present() const { return m_present; }
118
122 void MarkAsPresent() { m_present = true; }
123
124 protected:
125 void ReplaceUnderscoreWithHyphen(char *input);
126 const char* NewCanonicalName(const char *name);
127
128 private:
129 const char *m_arg_type;
130 char m_short_opt;
131 const char *m_help;
132 bool m_present;
133};
134
139template <typename T>
140class Flag : public BaseFlag {
141 public:
152 Flag(const char *name, const char *arg_type, const char *short_opt,
153 T default_value, const char *help,
154 OLA_UNUSED const bool has_arg)
156 m_name(name),
157 m_default(default_value),
158 m_value(default_value) {
159 m_name = NewCanonicalName(name);
160 }
161
162 ~Flag() {
163 delete[] m_name;
164 }
165
166 const char *name() const { return m_name; }
167 bool has_arg() const { return true; }
168 bool default_value() const { return m_default; }
169
170 operator T() const { return m_value; }
171
172 Flag &operator=(T v) {
173 m_value = v;
174 return *this;
175 }
176
177 bool SetValue(const std::string &input);
178
179 private:
180 const char *m_name;
181 T m_default;
182 T m_value;
183
184 Flag(const Flag &) = delete;
185 const Flag &operator=(const Flag &) = delete;
186};
187
191template<>
192class Flag<bool> : public BaseFlag {
193 public:
194 Flag(const char *name, const char *arg_type, const char *short_opt,
195 bool default_value, const char *help, const bool has_arg)
197 m_name(name),
198 m_default(default_value),
199 m_value(default_value),
200 m_has_arg(has_arg) {
201 if (!has_arg && default_value) {
202 // prefix the long option with 'no'
203 size_t prefix_size = strlen(NO_PREFIX);
204 size_t name_size = strlen(name);
205 char* new_name = new char[prefix_size + name_size + 1];
206 memcpy(new_name, NO_PREFIX, prefix_size);
207 memcpy(new_name + prefix_size, name, name_size);
208 new_name[prefix_size + name_size] = 0;
209 ReplaceUnderscoreWithHyphen(new_name);
210 m_name = new_name;
211 } else {
212 m_name = NewCanonicalName(name);
213 }
214 }
215
216 ~Flag() {
217 delete[] m_name;
218 }
219
220 const char *name() const { return m_name; }
221 bool has_arg() const { return m_has_arg; }
222 bool default_value() const { return m_default; }
223
224 operator bool() const { return m_value; }
225
226 Flag &operator=(bool v) {
227 m_value = v;
228 return *this;
229 }
230
231 bool SetValue(const std::string &input) {
233 if (m_has_arg) {
234 return ola::StringToBoolTolerant(input, &m_value);
235 } else {
236 m_value = !m_default;
237 return true;
238 }
239 }
240
241 private:
242 const char *m_name;
243 bool m_default;
244 bool m_value;
245 bool m_has_arg;
246
247 static const char NO_PREFIX[];
248
249 Flag(const Flag &) = delete;
250 const Flag &operator=(const Flag &) = delete;
251};
252
256template<>
257class Flag<std::string> : public BaseFlag {
258 public:
259 Flag(const char *name, const char *arg_type, const char *short_opt,
260 std::string default_value, const char *help,
261 OLA_UNUSED const bool has_arg)
263 m_name(name),
264 m_default(default_value),
265 m_value(default_value) {
266 m_name = NewCanonicalName(name);
267 }
268
269 ~Flag() {
270 delete[] m_name;
271 }
272
273 const char *name() const { return m_name; }
274 bool has_arg() const { return true; }
275 std::string default_value() const { return m_default; }
276 const char* arg_type() const { return "string"; }
277
278 operator const char*() const { return m_value.c_str(); }
279 operator std::string() const { return m_value; }
280 std::string str() const { return m_value; }
281
282 Flag &operator=(const std::string &v) {
283 m_value = v;
284 return *this;
285 }
286
287 bool SetValue(const std::string &input) {
289 m_value = input;
290 return true;
291 }
292
293 private:
294 const char *m_name;
295 std::string m_default;
296 std::string m_value;
297
298 Flag(const Flag &) = delete;
299 const Flag &operator=(const Flag &) = delete;
300};
301
305template <typename T>
306bool Flag<T>::SetValue(const std::string &input) {
307 MarkAsPresent();
308 return ola::StringToInt(input, &m_value, true);
309}
310
311
317 public:
318 FlagRegistry() {}
319
320 void RegisterFlag(FlagInterface *flag);
321 void ParseFlags(int *argc, char **argv);
322
323 void SetFirstLine(const std::string &help);
324 void SetDescription(const std::string &help);
325 void DisplayUsage();
326 void DisplayVersion();
327 void GenManPage();
328
329 private:
330 typedef std::map<std::string, FlagInterface*> LongOpts;
331 typedef std::map<char, FlagInterface*> ShortOpts;
332 typedef std::map<int, FlagInterface*> FlagMap;
333 // <flag, description>
334 typedef std::pair<std::string, std::string> OptionPair;
335
336 LongOpts m_long_opts;
337 ShortOpts m_short_opts;
338 std::string m_argv0;
339 std::string m_first_line;
340 std::string m_description;
341
342 std::string GetShortOptsString() const;
343 struct option *GetLongOpts(FlagMap *flag_map);
344 void PrintFlags(std::vector<std::string> *lines);
345 void PrintManPageFlags(std::vector<OptionPair> *lines);
346
347 FlagRegistry(const FlagRegistry &) = delete;
348 const FlagRegistry &operator=(const FlagRegistry &) = delete;
349};
350
355
360 public:
361 explicit FlagRegisterer(FlagInterface *flag) {
362 GetRegistry()->RegisterFlag(flag);
363 }
364
365 FlagRegisterer(FlagInterface *flag, char *short_opt) {
366 *short_opt = flag->short_opt();
367 GetRegistry()->RegisterFlag(flag);
368 }
369
370 private:
371 FlagRegisterer(const FlagRegisterer &) = delete;
372 const FlagRegisterer &operator=(const FlagRegisterer &) = delete;
373};
374
377} // namespace ola
378
386#define DECLARE_flag(type, name) \
387 namespace ola_flags { extern ola::Flag<type> FLAGS_##name; } \
388 using ola_flags::FLAGS_##name;
389
393#define DEFINE_flag(type, name, short_opt, default_value, help_str, \
394 has_arg) \
395 namespace ola_flags { \
396 ola::Flag<type> FLAGS_##name(#name, #type, #short_opt, default_value, \
397 help_str, has_arg); \
398 ola::FlagRegisterer flag_registerer_##name(&FLAGS_##name); \
399 } \
400 using ola_flags::FLAGS_##name
401
405#define DEFINE_flag_with_short(type, name, short_opt, default_value, help_str, \
406 has_arg) \
407 namespace ola_flags { char flag_short_##short_opt = 0; } \
408 namespace ola_flags { \
409 ola::Flag<type> FLAGS_##name(#name, #type, #short_opt, default_value, \
410 help_str, has_arg); \
411 ola::FlagRegisterer flag_registerer_##name( \
412 &FLAGS_##name, &flag_short_##short_opt); \
413 } \
414 using ola_flags::FLAGS_##name
415
421#endif // INCLUDE_OLA_BASE_FLAGSPRIVATE_H_
Helper macros.
#define OLA_UNUSED
Mark unused arguments & types.
Definition Macro.h:63
Various string utility functions.
The common implementation.
Definition FlagsPrivate.h:99
std::string help() const
Get the flag help string.
Definition FlagsPrivate.h:116
BaseFlag(const char *arg_type, const char *short_opt, const char *help)
Create a new BaseFlag.
Definition FlagsPrivate.h:107
char short_opt() const
Get the flag short option.
Definition FlagsPrivate.h:114
bool present() const
Check if the flag was present on the command line. Good for switching behaviour when a flag is used.
Definition FlagsPrivate.h:117
const char * arg_type() const
Get the flag argument type.
Definition FlagsPrivate.h:115
void MarkAsPresent()
Set that the flag was present on the command line.
Definition FlagsPrivate.h:122
const char * name() const
Get the flag name.
Definition FlagsPrivate.h:220
bool has_arg() const
Whether the flag requires an argument.
Definition FlagsPrivate.h:221
bool SetValue(const std::string &input)
Set the flag value.
Definition FlagsPrivate.h:231
const char * arg_type() const
Get the flag argument type.
Definition FlagsPrivate.h:276
const char * name() const
Get the flag name.
Definition FlagsPrivate.h:273
bool has_arg() const
Whether the flag requires an argument.
Definition FlagsPrivate.h:274
bool SetValue(const std::string &input)
Set the flag value.
Definition FlagsPrivate.h:287
A templated Flag class.
Definition FlagsPrivate.h:140
bool has_arg() const
Whether the flag requires an argument.
Definition FlagsPrivate.h:167
const char * name() const
Get the flag name.
Definition FlagsPrivate.h:166
Flag(const char *name, const char *arg_type, const char *short_opt, T default_value, const char *help, const bool has_arg)
Create a new Flag.
Definition FlagsPrivate.h:152
The interface for the Flag classes.
Definition FlagsPrivate.h:52
virtual const char * arg_type() const =0
Get the flag argument type.
virtual bool SetValue(const std::string &input)=0
Set the flag value.
virtual bool present() const =0
Check if the flag was present on the command line. Good for switching behaviour when a flag is used.
virtual char short_opt() const =0
Get the flag short option.
virtual const char * name() const =0
Get the flag name.
virtual std::string help() const =0
Get the flag help string.
virtual bool has_arg() const =0
Whether the flag requires an argument.
This class is responsible for registering a flag.
Definition FlagsPrivate.h:359
This class holds all the flags, and is responsible for parsing the command line.
Definition FlagsPrivate.h:316
FlagRegistry * GetRegistry()
Get the global FlagRegistry.
bool SetValue(const std::string &input)
Used to set the value of a flag.
Definition FlagsPrivate.h:306
The namespace containing all OLA symbols.
Definition Credentials.cpp:44
bool StringToBoolTolerant(const string &value, bool *output)
Convert a string to a bool in a tolerant way.
Definition StringUtils.cpp:136
bool StringToInt(const string &value, unsigned int *output, bool strict)
Convert a string to a unsigned int.
Definition StringUtils.cpp:155