blob: 61a95ffd532cd439ad8e0df8e87f2ad4253218de [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"
Yves Gerey2e00abc2018-10-05 15:39:24 +020026
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020027namespace rtc {
28
29// Internal use only.
30union FlagValue {
31 // Note: Because in C++ non-bool values are silently converted into
32 // bool values ('bool b = "false";' results in b == true!), we pass
33 // and int argument to New_BOOL as this appears to be safer - sigh.
34 // In particular, it prevents the (not uncommon!) bug where a bool
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020035 // flag is defined via: WEBRTC_DEFINE_bool(flag, "false", "some comment");.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020036 static FlagValue New_BOOL(int b) {
37 FlagValue v;
38 v.b = (b != 0);
39 return v;
40 }
41
42 static FlagValue New_INT(int i) {
43 FlagValue v;
44 v.i = i;
45 return v;
46 }
47
48 static FlagValue New_FLOAT(float f) {
49 FlagValue v;
50 v.f = f;
51 return v;
52 }
53
54 static FlagValue New_STRING(const char* s) {
55 FlagValue v;
56 v.s = s;
57 return v;
58 }
59
60 bool b;
61 int i;
62 double f;
63 const char* s;
64};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020066// Each flag can be accessed programmatically via a Flag object.
67class Flag {
68 public:
69 enum Type { BOOL, INT, FLOAT, STRING };
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020071 // Internal use only.
Yves Gerey665174f2018-06-19 15:03:05 +020072 Flag(const char* file,
73 const char* name,
74 const char* comment,
75 Type type,
76 void* variable,
77 FlagValue default_);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020078
79 // General flag information
Yves Gerey665174f2018-06-19 15:03:05 +020080 const char* file() const { return file_; }
81 const char* name() const { return name_; }
82 const char* comment() const { return comment_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020083
84 // Flag type
Yves Gerey665174f2018-06-19 15:03:05 +020085 Type type() const { return type_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020086
87 // Flag variables
88 bool* bool_variable() const {
89 RTC_DCHECK_EQ(BOOL, type_);
90 return &variable_->b;
91 }
92
93 int* int_variable() const {
94 RTC_DCHECK_EQ(INT, type_);
95 return &variable_->i;
96 }
97
98 double* float_variable() const {
99 RTC_DCHECK_EQ(FLOAT, type_);
100 return &variable_->f;
101 }
102
103 const char** string_variable() const {
104 RTC_DCHECK_EQ(STRING, type_);
105 return &variable_->s;
106 }
107
108 // Default values
109 bool bool_default() const {
110 RTC_DCHECK_EQ(BOOL, type_);
111 return default_.b;
112 }
113
114 int int_default() const {
115 RTC_DCHECK_EQ(INT, type_);
116 return default_.i;
117 }
118
119 double float_default() const {
120 RTC_DCHECK_EQ(FLOAT, type_);
121 return default_.f;
122 }
123
124 const char* string_default() const {
125 RTC_DCHECK_EQ(STRING, type_);
126 return default_.s;
127 }
128
129 // Resets a flag to its default value
130 void SetToDefault();
131
132 // Iteration support
Yves Gerey665174f2018-06-19 15:03:05 +0200133 Flag* next() const { return next_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200134
135 // Prints flag information. The current flag value is only printed
136 // if print_current_value is set.
137 void Print(bool print_current_value);
138
139 private:
140 const char* file_;
141 const char* name_;
142 const char* comment_;
143
144 Type type_;
145 FlagValue* variable_;
146 FlagValue default_;
147
148 Flag* next_;
149
150 friend class FlagList; // accesses next_
151};
152
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200153// Internal use only.
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200154#define WEBRTC_DEFINE_FLAG(type, c_type, name, default, comment) \
Yves Gerey665174f2018-06-19 15:03:05 +0200155 /* define and initialize the flag */ \
156 c_type FLAG_##name = (default); \
157 /* register the flag */ \
158 static rtc::Flag Flag_##name(__FILE__, #name, (comment), rtc::Flag::type, \
159 &FLAG_##name, \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200160 rtc::FlagValue::New_##type(default))
161
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200162// Internal use only.
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200163#define WEBRTC_DECLARE_FLAG(c_type, name) \
164 /* declare the external flag */ \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200165 extern c_type FLAG_##name
166
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200167// Use the following macros to define a new flag:
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200168#define WEBRTC_DEFINE_bool(name, default, comment) \
169 WEBRTC_DEFINE_FLAG(BOOL, bool, name, default, comment)
170#define WEBRTC_DEFINE_int(name, default, comment) \
171 WEBRTC_DEFINE_FLAG(INT, int, name, default, comment)
172#define WEBRTC_DEFINE_float(name, default, comment) \
173 WEBRTC_DEFINE_FLAG(FLOAT, double, name, default, comment)
174#define WEBRTC_DEFINE_string(name, default, comment) \
175 WEBRTC_DEFINE_FLAG(STRING, const char*, name, default, comment)
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200176
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200177// Use the following macros to declare a flag defined elsewhere:
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200178#define WEBRTC_DECLARE_bool(name) WEBRTC_DECLARE_FLAG(bool, name)
179#define WEBRTC_DECLARE_int(name) WEBRTC_DECLARE_FLAG(int, name)
180#define WEBRTC_DECLARE_float(name) WEBRTC_DECLARE_FLAG(double, name)
181#define WEBRTC_DECLARE_string(name) WEBRTC_DECLARE_FLAG(const char*, name)
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200182
183// The global list of all flags.
184class FlagList {
185 public:
186 FlagList();
187
188 // The null-terminated list of all flags. Traverse with Flag::next().
Yves Gerey665174f2018-06-19 15:03:05 +0200189 static Flag* list() { return list_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200190
191 // If file != nullptr, prints information for all flags defined in file;
192 // otherwise prints information for all flags in all files. The current flag
193 // value is only printed if print_current_value is set.
194 static void Print(const char* file, bool print_current_value);
195
196 // Lookup a flag by name. Returns the matching flag or null.
197 static Flag* Lookup(const char* name);
198
199 // Helper function to parse flags: Takes an argument arg and splits it into
200 // a flag name and flag value (or null if they are missing). is_bool is set
201 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
202 // terminate the name, it must be large enough to hold any possible name.
203 static void SplitArgument(const char* arg,
Yves Gerey665174f2018-06-19 15:03:05 +0200204 char* buffer,
205 int buffer_size,
206 const char** name,
207 const char** value,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200208 bool* is_bool);
209
210 // Set the flag values by parsing the command line. If remove_flags
211 // is set, the flags and associated values are removed from (argc,
212 // argv). Returns 0 if no error occurred. Otherwise, returns the
213 // argv index > 0 for the argument where an error occurred. In that
214 // case, (argc, argv) will remain unchanged indepdendent of the
215 // remove_flags value, and no assumptions about flag settings should
216 // be made.
217 //
218 // The following syntax for flags is accepted (both '-' and '--' are ok):
219 //
220 // --flag (bool flags only)
221 // --noflag (bool flags only)
222 // --flag=value (non-bool flags only, no spaces around '=')
223 // --flag value (non-bool flags only)
224 static int SetFlagsFromCommandLine(int* argc,
225 const char** argv,
226 bool remove_flags);
227 static inline int SetFlagsFromCommandLine(int* argc,
228 char** argv,
229 bool remove_flags) {
230 return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
231 remove_flags);
232 }
233
234 // Registers a new flag. Called during program initialization. Not
235 // thread-safe.
236 static void Register(Flag* flag);
237
238 private:
239 static Flag* list_;
240};
241
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200242} // namespace rtc
243
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200244#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H_