blob: e152e2a97966ad35a4a9eac5cdf46bcc41ce2b68 [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
27#if defined(WEBRTC_WIN)
Steve Anton10542f22019-01-11 09:11:00 -080028#include "rtc_base/constructor_magic.h"
Yves Gerey2e00abc2018-10-05 15:39:24 +020029#endif
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020030
31namespace rtc {
32
33// Internal use only.
34union FlagValue {
35 // Note: Because in C++ non-bool values are silently converted into
36 // bool values ('bool b = "false";' results in b == true!), we pass
37 // and int argument to New_BOOL as this appears to be safer - sigh.
38 // In particular, it prevents the (not uncommon!) bug where a bool
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020039 // flag is defined via: WEBRTC_DEFINE_bool(flag, "false", "some comment");.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020040 static FlagValue New_BOOL(int b) {
41 FlagValue v;
42 v.b = (b != 0);
43 return v;
44 }
45
46 static FlagValue New_INT(int i) {
47 FlagValue v;
48 v.i = i;
49 return v;
50 }
51
52 static FlagValue New_FLOAT(float f) {
53 FlagValue v;
54 v.f = f;
55 return v;
56 }
57
58 static FlagValue New_STRING(const char* s) {
59 FlagValue v;
60 v.s = s;
61 return v;
62 }
63
64 bool b;
65 int i;
66 double f;
67 const char* s;
68};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020070// Each flag can be accessed programmatically via a Flag object.
71class Flag {
72 public:
73 enum Type { BOOL, INT, FLOAT, STRING };
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000074
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020075 // Internal use only.
Yves Gerey665174f2018-06-19 15:03:05 +020076 Flag(const char* file,
77 const char* name,
78 const char* comment,
79 Type type,
80 void* variable,
81 FlagValue default_);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020082
83 // General flag information
Yves Gerey665174f2018-06-19 15:03:05 +020084 const char* file() const { return file_; }
85 const char* name() const { return name_; }
86 const char* comment() const { return comment_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020087
88 // Flag type
Yves Gerey665174f2018-06-19 15:03:05 +020089 Type type() const { return type_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020090
91 // Flag variables
92 bool* bool_variable() const {
93 RTC_DCHECK_EQ(BOOL, type_);
94 return &variable_->b;
95 }
96
97 int* int_variable() const {
98 RTC_DCHECK_EQ(INT, type_);
99 return &variable_->i;
100 }
101
102 double* float_variable() const {
103 RTC_DCHECK_EQ(FLOAT, type_);
104 return &variable_->f;
105 }
106
107 const char** string_variable() const {
108 RTC_DCHECK_EQ(STRING, type_);
109 return &variable_->s;
110 }
111
112 // Default values
113 bool bool_default() const {
114 RTC_DCHECK_EQ(BOOL, type_);
115 return default_.b;
116 }
117
118 int int_default() const {
119 RTC_DCHECK_EQ(INT, type_);
120 return default_.i;
121 }
122
123 double float_default() const {
124 RTC_DCHECK_EQ(FLOAT, type_);
125 return default_.f;
126 }
127
128 const char* string_default() const {
129 RTC_DCHECK_EQ(STRING, type_);
130 return default_.s;
131 }
132
133 // Resets a flag to its default value
134 void SetToDefault();
135
136 // Iteration support
Yves Gerey665174f2018-06-19 15:03:05 +0200137 Flag* next() const { return next_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200138
139 // Prints flag information. The current flag value is only printed
140 // if print_current_value is set.
141 void Print(bool print_current_value);
142
143 private:
144 const char* file_;
145 const char* name_;
146 const char* comment_;
147
148 Type type_;
149 FlagValue* variable_;
150 FlagValue default_;
151
152 Flag* next_;
153
154 friend class FlagList; // accesses next_
155};
156
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200157// Internal use only.
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200158#define WEBRTC_DEFINE_FLAG(type, c_type, name, default, comment) \
Yves Gerey665174f2018-06-19 15:03:05 +0200159 /* define and initialize the flag */ \
160 c_type FLAG_##name = (default); \
161 /* register the flag */ \
162 static rtc::Flag Flag_##name(__FILE__, #name, (comment), rtc::Flag::type, \
163 &FLAG_##name, \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200164 rtc::FlagValue::New_##type(default))
165
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200166// Internal use only.
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200167#define WEBRTC_DECLARE_FLAG(c_type, name) \
168 /* declare the external flag */ \
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200169 extern c_type FLAG_##name
170
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200171// Use the following macros to define a new flag:
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200172#define WEBRTC_DEFINE_bool(name, default, comment) \
173 WEBRTC_DEFINE_FLAG(BOOL, bool, name, default, comment)
174#define WEBRTC_DEFINE_int(name, default, comment) \
175 WEBRTC_DEFINE_FLAG(INT, int, name, default, comment)
176#define WEBRTC_DEFINE_float(name, default, comment) \
177 WEBRTC_DEFINE_FLAG(FLOAT, double, name, default, comment)
178#define WEBRTC_DEFINE_string(name, default, comment) \
179 WEBRTC_DEFINE_FLAG(STRING, const char*, name, default, comment)
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200180
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200181// Use the following macros to declare a flag defined elsewhere:
Mirko Bonadei2dfa9982018-10-18 11:35:32 +0200182#define WEBRTC_DECLARE_bool(name) WEBRTC_DECLARE_FLAG(bool, name)
183#define WEBRTC_DECLARE_int(name) WEBRTC_DECLARE_FLAG(int, name)
184#define WEBRTC_DECLARE_float(name) WEBRTC_DECLARE_FLAG(double, name)
185#define WEBRTC_DECLARE_string(name) WEBRTC_DECLARE_FLAG(const char*, name)
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200186
187// The global list of all flags.
188class FlagList {
189 public:
190 FlagList();
191
192 // The null-terminated list of all flags. Traverse with Flag::next().
Yves Gerey665174f2018-06-19 15:03:05 +0200193 static Flag* list() { return list_; }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200194
195 // If file != nullptr, prints information for all flags defined in file;
196 // otherwise prints information for all flags in all files. The current flag
197 // value is only printed if print_current_value is set.
198 static void Print(const char* file, bool print_current_value);
199
200 // Lookup a flag by name. Returns the matching flag or null.
201 static Flag* Lookup(const char* name);
202
203 // Helper function to parse flags: Takes an argument arg and splits it into
204 // a flag name and flag value (or null if they are missing). is_bool is set
205 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
206 // terminate the name, it must be large enough to hold any possible name.
207 static void SplitArgument(const char* arg,
Yves Gerey665174f2018-06-19 15:03:05 +0200208 char* buffer,
209 int buffer_size,
210 const char** name,
211 const char** value,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200212 bool* is_bool);
213
214 // Set the flag values by parsing the command line. If remove_flags
215 // is set, the flags and associated values are removed from (argc,
216 // argv). Returns 0 if no error occurred. Otherwise, returns the
217 // argv index > 0 for the argument where an error occurred. In that
218 // case, (argc, argv) will remain unchanged indepdendent of the
219 // remove_flags value, and no assumptions about flag settings should
220 // be made.
221 //
222 // The following syntax for flags is accepted (both '-' and '--' are ok):
223 //
224 // --flag (bool flags only)
225 // --noflag (bool flags only)
226 // --flag=value (non-bool flags only, no spaces around '=')
227 // --flag value (non-bool flags only)
228 static int SetFlagsFromCommandLine(int* argc,
229 const char** argv,
230 bool remove_flags);
231 static inline int SetFlagsFromCommandLine(int* argc,
232 char** argv,
233 bool remove_flags) {
234 return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
235 remove_flags);
236 }
237
238 // Registers a new flag. Called during program initialization. Not
239 // thread-safe.
240 static void Register(Flag* flag);
241
242 private:
243 static Flag* list_;
244};
245
246#if defined(WEBRTC_WIN)
247// A helper class to translate Windows command line arguments into UTF8,
248// which then allows us to just pass them to the flags system.
249// This encapsulates all the work of getting the command line and translating
250// it to an array of 8-bit strings; all you have to do is create one of these,
251// and then call argc() and argv().
252class WindowsCommandLineArguments {
253 public:
254 WindowsCommandLineArguments();
255 ~WindowsCommandLineArguments();
256
257 int argc() { return argc_; }
Yves Gerey665174f2018-06-19 15:03:05 +0200258 char** argv() { return argv_; }
259
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200260 private:
261 int argc_;
Yves Gerey665174f2018-06-19 15:03:05 +0200262 char** argv_;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200263
264 private:
265 RTC_DISALLOW_COPY_AND_ASSIGN(WindowsCommandLineArguments);
266};
267#endif // WEBRTC_WIN
268
269} // namespace rtc
270
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200271#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H_