1/*
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
26#include <assert.h>
27
28#include "webrtc/base/checks.h"
29#include "webrtc/base/common.h"
30
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
39  // flag is defined via: DEFINE_bool(flag, "false", "some comment");.
40  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};
69
70
71// Each flag can be accessed programmatically via a Flag object.
72class Flag {
73 public:
74  enum Type { BOOL, INT, FLOAT, STRING };
75
76  // Internal use only.
77  Flag(const char* file, const char* name, const char* comment,
78       Type type, void* variable, FlagValue default_);
79
80  // General flag information
81  const char* file() const  { return file_; }
82  const char* name() const  { return name_; }
83  const char* comment() const  { return comment_; }
84
85  // Flag type
86  Type type() const  { return type_; }
87
88  // Flag variables
89  bool* bool_variable() const {
90    assert(type_ == BOOL);
91    return &variable_->b;
92  }
93
94  int* int_variable() const {
95    assert(type_ == INT);
96    return &variable_->i;
97  }
98
99  double* float_variable() const {
100    assert(type_ == FLOAT);
101    return &variable_->f;
102  }
103
104  const char** string_variable() const {
105    assert(type_ == STRING);
106    return &variable_->s;
107  }
108
109  // Default values
110  bool bool_default() const {
111    assert(type_ == BOOL);
112    return default_.b;
113  }
114
115  int int_default() const {
116    assert(type_ == INT);
117    return default_.i;
118  }
119
120  double float_default() const {
121    assert(type_ == FLOAT);
122    return default_.f;
123  }
124
125  const char* string_default() const {
126    assert(type_ == STRING);
127    return default_.s;
128  }
129
130  // Resets a flag to its default value
131  void SetToDefault();
132
133  // Iteration support
134  Flag* next() const  { return next_; }
135
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
154
155// Internal use only.
156#define DEFINE_FLAG(type, c_type, name, default, comment) \
157  /* define and initialize the flag */                    \
158  c_type FLAG_##name = (default);                         \
159  /* register the flag */                                 \
160  static rtc::Flag Flag_##name(__FILE__, #name, (comment),      \
161                               rtc::Flag::type, &FLAG_##name,   \
162                               rtc::FlagValue::New_##type(default))
163
164
165// Internal use only.
166#define DECLARE_FLAG(c_type, name)              \
167  /* declare the external flag */               \
168  extern c_type FLAG_##name
169
170
171// Use the following macros to define a new flag:
172#define DEFINE_bool(name, default, comment) \
173  DEFINE_FLAG(BOOL, bool, name, default, comment)
174#define DEFINE_int(name, default, comment) \
175  DEFINE_FLAG(INT, int, name, default, comment)
176#define DEFINE_float(name, default, comment) \
177  DEFINE_FLAG(FLOAT, double, name, default, comment)
178#define DEFINE_string(name, default, comment) \
179  DEFINE_FLAG(STRING, const char*, name, default, comment)
180
181
182// Use the following macros to declare a flag defined elsewhere:
183#define DECLARE_bool(name)  DECLARE_FLAG(bool, name)
184#define DECLARE_int(name)  DECLARE_FLAG(int, name)
185#define DECLARE_float(name)  DECLARE_FLAG(double, name)
186#define DECLARE_string(name)  DECLARE_FLAG(const char*, name)
187
188
189// The global list of all flags.
190class FlagList {
191 public:
192  FlagList();
193
194  // The NULL-terminated list of all flags. Traverse with Flag::next().
195  static Flag* list()  { return list_; }
196
197  // If file != NULL, prints information for all flags defined in file;
198  // otherwise prints information for all flags in all files. The current
199  // flag value is only printed if print_current_value is set.
200  static void Print(const char* file, bool print_current_value);
201
202  // Lookup a flag by name. Returns the matching flag or NULL.
203  static Flag* Lookup(const char* name);
204
205  // Helper function to parse flags: Takes an argument arg and splits it into
206  // a flag name and flag value (or NULL if they are missing). is_bool is set
207  // if the arg started with "-no" or "--no". The buffer may be used to NUL-
208  // terminate the name, it must be large enough to hold any possible name.
209  static void SplitArgument(const char* arg,
210                            char* buffer, int buffer_size,
211                            const char** name, const char** value,
212                            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_; }
258  char **argv() { return argv_; }
259 private:
260  int argc_;
261  char **argv_;
262
263 private:
264  DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments);
265};
266#endif  // WEBRTC_WIN
267
268}  // namespace rtc
269
270#endif  // SHARED_COMMANDLINEFLAGS_FLAGS_H__
271