blob: 6ca50b5cea2ca80fe779f344fb4d80108c6ec441 [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
11
12// Originally comes from shared/commandlineflags/flags.h
13
14// Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros,
15// where xxx is the flag type. Flags are referred to via FLAG_yyy,
16// where yyy is the flag name. For intialization and iteration of flags,
17// see the FlagList class. For full programmatic access to any
18// flag, see the Flag class.
19//
20// The implementation only relies and basic C++ functionality
21// and needs no special library or STL support.
22
23#ifndef WEBRTC_BASE_FLAGS_H__
24#define WEBRTC_BASE_FLAGS_H__
25
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026#include "webrtc/base/checks.h"
27#include "webrtc/base/common.h"
kwiberg4485ffb2016-04-26 08:14:39 -070028#include "webrtc/base/constructormagic.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +000030namespace rtc {
31
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032// Internal use only.
33union FlagValue {
34 // Note: Because in C++ non-bool values are silently converted into
35 // bool values ('bool b = "false";' results in b == true!), we pass
36 // and int argument to New_BOOL as this appears to be safer - sigh.
37 // In particular, it prevents the (not uncommon!) bug where a bool
38 // flag is defined via: DEFINE_bool(flag, "false", "some comment");.
39 static FlagValue New_BOOL(int b) {
40 FlagValue v;
41 v.b = (b != 0);
42 return v;
43 }
44
45 static FlagValue New_INT(int i) {
46 FlagValue v;
47 v.i = i;
48 return v;
49 }
50
51 static FlagValue New_FLOAT(float f) {
52 FlagValue v;
53 v.f = f;
54 return v;
55 }
56
57 static FlagValue New_STRING(const char* s) {
58 FlagValue v;
59 v.s = s;
60 return v;
61 }
62
63 bool b;
64 int i;
65 double f;
66 const char* s;
67};
68
69
70// Each flag can be accessed programmatically via a Flag object.
71class Flag {
72 public:
73 enum Type { BOOL, INT, FLOAT, STRING };
74
75 // Internal use only.
76 Flag(const char* file, const char* name, const char* comment,
77 Type type, void* variable, FlagValue default_);
78
79 // General flag information
80 const char* file() const { return file_; }
81 const char* name() const { return name_; }
82 const char* comment() const { return comment_; }
83
84 // Flag type
85 Type type() const { return type_; }
86
87 // Flag variables
88 bool* bool_variable() const {
kwiberg22487b22016-09-13 01:17:10 -070089 RTC_DCHECK_EQ(BOOL, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000090 return &variable_->b;
91 }
henrikg3c089d72015-09-16 05:37:44 -070092
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000093 int* int_variable() const {
kwiberg22487b22016-09-13 01:17:10 -070094 RTC_DCHECK_EQ(INT, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095 return &variable_->i;
96 }
henrikg3c089d72015-09-16 05:37:44 -070097
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000098 double* float_variable() const {
kwiberg22487b22016-09-13 01:17:10 -070099 RTC_DCHECK_EQ(FLOAT, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000100 return &variable_->f;
101 }
henrikg3c089d72015-09-16 05:37:44 -0700102
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000103 const char** string_variable() const {
kwiberg22487b22016-09-13 01:17:10 -0700104 RTC_DCHECK_EQ(STRING, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000105 return &variable_->s;
106 }
107
108 // Default values
109 bool bool_default() const {
kwiberg22487b22016-09-13 01:17:10 -0700110 RTC_DCHECK_EQ(BOOL, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000111 return default_.b;
112 }
henrikg3c089d72015-09-16 05:37:44 -0700113
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000114 int int_default() const {
kwiberg22487b22016-09-13 01:17:10 -0700115 RTC_DCHECK_EQ(INT, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116 return default_.i;
117 }
henrikg3c089d72015-09-16 05:37:44 -0700118
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119 double float_default() const {
kwiberg22487b22016-09-13 01:17:10 -0700120 RTC_DCHECK_EQ(FLOAT, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000121 return default_.f;
122 }
henrikg3c089d72015-09-16 05:37:44 -0700123
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124 const char* string_default() const {
kwiberg22487b22016-09-13 01:17:10 -0700125 RTC_DCHECK_EQ(STRING, type_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000126 return default_.s;
127 }
128
129 // Resets a flag to its default value
130 void SetToDefault();
131
132 // Iteration support
133 Flag* next() const { return next_; }
134
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
153
154// Internal use only.
155#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 */ \
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +0000159 static rtc::Flag Flag_##name(__FILE__, #name, (comment), \
160 rtc::Flag::type, &FLAG_##name, \
161 rtc::FlagValue::New_##type(default))
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000162
163
164// Internal use only.
165#define DECLARE_FLAG(c_type, name) \
166 /* declare the external flag */ \
167 extern c_type FLAG_##name
168
169
170// Use the following macros to define a new flag:
171#define DEFINE_bool(name, default, comment) \
172 DEFINE_FLAG(BOOL, bool, name, default, comment)
173#define DEFINE_int(name, default, comment) \
174 DEFINE_FLAG(INT, int, name, default, comment)
175#define DEFINE_float(name, default, comment) \
176 DEFINE_FLAG(FLOAT, double, name, default, comment)
177#define DEFINE_string(name, default, comment) \
178 DEFINE_FLAG(STRING, const char*, name, default, comment)
179
180
181// Use the following macros to declare a flag defined elsewhere:
182#define DECLARE_bool(name) DECLARE_FLAG(bool, name)
183#define DECLARE_int(name) DECLARE_FLAG(int, name)
184#define DECLARE_float(name) DECLARE_FLAG(double, name)
185#define DECLARE_string(name) DECLARE_FLAG(const char*, name)
186
187
188// The global list of all flags.
189class FlagList {
190 public:
191 FlagList();
192
193 // The NULL-terminated list of all flags. Traverse with Flag::next().
194 static Flag* list() { return list_; }
195
196 // If file != NULL, prints information for all flags defined in file;
197 // otherwise prints information for all flags in all files. The current
198 // flag value is only printed if print_current_value is set.
199 static void Print(const char* file, bool print_current_value);
200
201 // Lookup a flag by name. Returns the matching flag or NULL.
202 static Flag* Lookup(const char* name);
203
204 // Helper function to parse flags: Takes an argument arg and splits it into
205 // a flag name and flag value (or NULL if they are missing). is_bool is set
206 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
207 // terminate the name, it must be large enough to hold any possible name.
208 static void SplitArgument(const char* arg,
209 char* buffer, int buffer_size,
210 const char** name, const char** value,
211 bool* is_bool);
212
213 // Set the flag values by parsing the command line. If remove_flags
214 // is set, the flags and associated values are removed from (argc,
215 // argv). Returns 0 if no error occurred. Otherwise, returns the
216 // argv index > 0 for the argument where an error occurred. In that
217 // case, (argc, argv) will remain unchanged indepdendent of the
218 // remove_flags value, and no assumptions about flag settings should
219 // be made.
220 //
221 // The following syntax for flags is accepted (both '-' and '--' are ok):
222 //
223 // --flag (bool flags only)
224 // --noflag (bool flags only)
225 // --flag=value (non-bool flags only, no spaces around '=')
226 // --flag value (non-bool flags only)
227 static int SetFlagsFromCommandLine(int* argc,
228 const char** argv,
229 bool remove_flags);
230 static inline int SetFlagsFromCommandLine(int* argc,
231 char** argv,
232 bool remove_flags) {
233 return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
234 remove_flags);
235 }
236
237 // Registers a new flag. Called during program initialization. Not
238 // thread-safe.
239 static void Register(Flag* flag);
240
241 private:
242 static Flag* list_;
243};
244
245#if defined(WEBRTC_WIN)
246// A helper class to translate Windows command line arguments into UTF8,
247// which then allows us to just pass them to the flags system.
248// This encapsulates all the work of getting the command line and translating
249// it to an array of 8-bit strings; all you have to do is create one of these,
250// and then call argc() and argv().
251class WindowsCommandLineArguments {
252 public:
253 WindowsCommandLineArguments();
254 ~WindowsCommandLineArguments();
255
256 int argc() { return argc_; }
257 char **argv() { return argv_; }
258 private:
259 int argc_;
260 char **argv_;
261
262 private:
henrikg3c089d72015-09-16 05:37:44 -0700263 RTC_DISALLOW_COPY_AND_ASSIGN(WindowsCommandLineArguments);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000264};
henrikg3c089d72015-09-16 05:37:44 -0700265#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000266
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +0000267} // namespace rtc
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268
269#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H__