blob: 33f6e5bda1dbda54c6df8e5f268fd860fd4768ad [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2006 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000011// Originally comes from shared/commandlineflags/flags.h
12
13// Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros,
14// where xxx is the flag type. Flags are referred to via FLAG_yyy,
15// where yyy is the flag name. For intialization and iteration of flags,
16// see the FlagList class. For full programmatic access to any
17// flag, see the Flag class.
18//
19// The implementation only relies and basic C++ functionality
20// and needs no special library or STL support.
21
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#ifndef RTC_BASE_FLAGS_H_
23#define RTC_BASE_FLAGS_H_
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020024
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "rtc_base/checks.h"
26#include "rtc_base/constructormagic.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020027
28namespace rtc {
29
30// Internal use only.
31union FlagValue {
32 // Note: Because in C++ non-bool values are silently converted into
33 // bool values ('bool b = "false";' results in b == true!), we pass
34 // and int argument to New_BOOL as this appears to be safer - sigh.
35 // In particular, it prevents the (not uncommon!) bug where a bool
36 // flag is defined via: DEFINE_bool(flag, "false", "some comment");.
37 static FlagValue New_BOOL(int b) {
38 FlagValue v;
39 v.b = (b != 0);
40 return v;
41 }
42
43 static FlagValue New_INT(int i) {
44 FlagValue v;
45 v.i = i;
46 return v;
47 }
48
49 static FlagValue New_FLOAT(float f) {
50 FlagValue v;
51 v.f = f;
52 return v;
53 }
54
55 static FlagValue New_STRING(const char* s) {
56 FlagValue v;
57 v.s = s;
58 return v;
59 }
60
61 bool b;
62 int i;
63 double f;
64 const char* s;
65};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000066
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020067// Each flag can be accessed programmatically via a Flag object.
68class Flag {
69 public:
70 enum Type { BOOL, INT, FLOAT, STRING };
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000071
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020072 // Internal use only.
Yves Gerey665174f2018-06-19 15:03:05 +020073 Flag(const char* file,
74 const char* name,
75 const char* comment,
76 Type type,
77 void* variable,
78 FlagValue default_);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020079
80 // General flag information
Yves Gerey665174f2018-06-19 15:03:05 +020081 const char* file() const { return file_; }
82 const char* name() const { return name_; }
83 const char* comment() const { return comment_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020084
85 // Flag type
Yves Gerey665174f2018-06-19 15:03:05 +020086 Type type() const { return type_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020087
88 // Flag variables
89 bool* bool_variable() const {
90 RTC_DCHECK_EQ(BOOL, type_);
91 return &variable_->b;
92 }
93
94 int* int_variable() const {
95 RTC_DCHECK_EQ(INT, type_);
96 return &variable_->i;
97 }
98
99 double* float_variable() const {
100 RTC_DCHECK_EQ(FLOAT, type_);
101 return &variable_->f;
102 }
103
104 const char** string_variable() const {
105 RTC_DCHECK_EQ(STRING, type_);
106 return &variable_->s;
107 }
108
109 // Default values
110 bool bool_default() const {
111 RTC_DCHECK_EQ(BOOL, type_);
112 return default_.b;
113 }
114
115 int int_default() const {
116 RTC_DCHECK_EQ(INT, type_);
117 return default_.i;
118 }
119
120 double float_default() const {
121 RTC_DCHECK_EQ(FLOAT, type_);
122 return default_.f;
123 }
124
125 const char* string_default() const {
126 RTC_DCHECK_EQ(STRING, type_);
127 return default_.s;
128 }
129
130 // Resets a flag to its default value
131 void SetToDefault();
132
133 // Iteration support
Yves Gerey665174f2018-06-19 15:03:05 +0200134 Flag* next() const { return next_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200135
136 // Prints flag information. The current flag value is only printed
137 // if print_current_value is set.
138 void Print(bool print_current_value);
139
140 private:
141 const char* file_;
142 const char* name_;
143 const char* comment_;
144
145 Type type_;
146 FlagValue* variable_;
147 FlagValue default_;
148
149 Flag* next_;
150
151 friend class FlagList; // accesses next_
152};
153
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200154// Internal use only.
Yves Gerey665174f2018-06-19 15:03:05 +0200155#define DEFINE_FLAG(type, c_type, name, default, comment) \
156 /* define and initialize the flag */ \
157 c_type FLAG_##name = (default); \
158 /* register the flag */ \
159 static rtc::Flag Flag_##name(__FILE__, #name, (comment), rtc::Flag::type, \
160 &FLAG_##name, \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200161 rtc::FlagValue::New_##type(default))
162
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200163// Internal use only.
Yves Gerey665174f2018-06-19 15:03:05 +0200164#define DECLARE_FLAG(c_type, name) \
165 /* declare the external flag */ \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200166 extern c_type FLAG_##name
167
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200168// Use the following macros to define a new flag:
169#define DEFINE_bool(name, default, comment) \
170 DEFINE_FLAG(BOOL, bool, name, default, comment)
171#define DEFINE_int(name, default, comment) \
172 DEFINE_FLAG(INT, int, name, default, comment)
173#define DEFINE_float(name, default, comment) \
174 DEFINE_FLAG(FLOAT, double, name, default, comment)
175#define DEFINE_string(name, default, comment) \
176 DEFINE_FLAG(STRING, const char*, name, default, comment)
177
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200178// Use the following macros to declare a flag defined elsewhere:
Yves Gerey665174f2018-06-19 15:03:05 +0200179#define DECLARE_bool(name) DECLARE_FLAG(bool, name)
180#define DECLARE_int(name) DECLARE_FLAG(int, name)
181#define DECLARE_float(name) DECLARE_FLAG(double, name)
182#define DECLARE_string(name) DECLARE_FLAG(const char*, name)
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200183
184// The global list of all flags.
185class FlagList {
186 public:
187 FlagList();
188
189 // The null-terminated list of all flags. Traverse with Flag::next().
Yves Gerey665174f2018-06-19 15:03:05 +0200190 static Flag* list() { return list_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200191
192 // If file != nullptr, prints information for all flags defined in file;
193 // otherwise prints information for all flags in all files. The current flag
194 // value is only printed if print_current_value is set.
195 static void Print(const char* file, bool print_current_value);
196
197 // Lookup a flag by name. Returns the matching flag or null.
198 static Flag* Lookup(const char* name);
199
200 // Helper function to parse flags: Takes an argument arg and splits it into
201 // a flag name and flag value (or null if they are missing). is_bool is set
202 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
203 // terminate the name, it must be large enough to hold any possible name.
204 static void SplitArgument(const char* arg,
Yves Gerey665174f2018-06-19 15:03:05 +0200205 char* buffer,
206 int buffer_size,
207 const char** name,
208 const char** value,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200209 bool* is_bool);
210
211 // Set the flag values by parsing the command line. If remove_flags
212 // is set, the flags and associated values are removed from (argc,
213 // argv). Returns 0 if no error occurred. Otherwise, returns the
214 // argv index > 0 for the argument where an error occurred. In that
215 // case, (argc, argv) will remain unchanged indepdendent of the
216 // remove_flags value, and no assumptions about flag settings should
217 // be made.
218 //
219 // The following syntax for flags is accepted (both '-' and '--' are ok):
220 //
221 // --flag (bool flags only)
222 // --noflag (bool flags only)
223 // --flag=value (non-bool flags only, no spaces around '=')
224 // --flag value (non-bool flags only)
225 static int SetFlagsFromCommandLine(int* argc,
226 const char** argv,
227 bool remove_flags);
228 static inline int SetFlagsFromCommandLine(int* argc,
229 char** argv,
230 bool remove_flags) {
231 return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
232 remove_flags);
233 }
234
235 // Registers a new flag. Called during program initialization. Not
236 // thread-safe.
237 static void Register(Flag* flag);
238
239 private:
240 static Flag* list_;
241};
242
243#if defined(WEBRTC_WIN)
244// A helper class to translate Windows command line arguments into UTF8,
245// which then allows us to just pass them to the flags system.
246// This encapsulates all the work of getting the command line and translating
247// it to an array of 8-bit strings; all you have to do is create one of these,
248// and then call argc() and argv().
249class WindowsCommandLineArguments {
250 public:
251 WindowsCommandLineArguments();
252 ~WindowsCommandLineArguments();
253
254 int argc() { return argc_; }
Yves Gerey665174f2018-06-19 15:03:05 +0200255 char** argv() { return argv_; }
256
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200257 private:
258 int argc_;
Yves Gerey665174f2018-06-19 15:03:05 +0200259 char** argv_;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200260
261 private:
262 RTC_DISALLOW_COPY_AND_ASSIGN(WindowsCommandLineArguments);
263};
264#endif // WEBRTC_WIN
265
266} // namespace rtc
267
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200268#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H_