• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2006, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 // Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros,
29 // where xxx is the flag type. Flags are referred to via FLAG_yyy,
30 // where yyy is the flag name. For intialization and iteration of flags,
31 // see the FlagList class. For full programmatic access to any
32 // flag, see the Flag class.
33 //
34 // The implementation only relies and basic C++ functionality
35 // and needs no special library or STL support.
36 
37 #ifndef TALK_BASE_FLAGS_H__
38 #define TALK_BASE_FLAGS_H__
39 
40 #include <assert.h>
41 
42 #include "talk/base/checks.h"
43 #include "talk/base/common.h"
44 
45 // Internal use only.
46 union FlagValue {
47   // Note: Because in C++ non-bool values are silently converted into
48   // bool values ('bool b = "false";' results in b == true!), we pass
49   // and int argument to New_BOOL as this appears to be safer - sigh.
50   // In particular, it prevents the (not uncommon!) bug where a bool
51   // flag is defined via: DEFINE_bool(flag, "false", "some comment");.
New_BOOL(int b)52   static FlagValue New_BOOL(int b) {
53     FlagValue v;
54     v.b = (b != 0);
55     return v;
56   }
57 
New_INT(int i)58   static FlagValue New_INT(int i) {
59     FlagValue v;
60     v.i = i;
61     return v;
62   }
63 
New_FLOAT(float f)64   static FlagValue New_FLOAT(float f) {
65     FlagValue v;
66     v.f = f;
67     return v;
68   }
69 
New_STRING(const char * s)70   static FlagValue New_STRING(const char* s) {
71     FlagValue v;
72     v.s = s;
73     return v;
74   }
75 
76   bool b;
77   int i;
78   double f;
79   const char* s;
80 };
81 
82 
83 // Each flag can be accessed programmatically via a Flag object.
84 class Flag {
85  public:
86   enum Type { BOOL, INT, FLOAT, STRING };
87 
88   // Internal use only.
89   Flag(const char* file, const char* name, const char* comment,
90        Type type, void* variable, FlagValue default_);
91 
92   // General flag information
file()93   const char* file() const  { return file_; }
name()94   const char* name() const  { return name_; }
comment()95   const char* comment() const  { return comment_; }
96 
97   // Flag type
type()98   Type type() const  { return type_; }
99 
100   // Flag variables
bool_variable()101   bool* bool_variable() const {
102     assert(type_ == BOOL);
103     return &variable_->b;
104   }
105 
int_variable()106   int* int_variable() const {
107     assert(type_ == INT);
108     return &variable_->i;
109   }
110 
float_variable()111   double* float_variable() const {
112     assert(type_ == FLOAT);
113     return &variable_->f;
114   }
115 
string_variable()116   const char** string_variable() const {
117     assert(type_ == STRING);
118     return &variable_->s;
119   }
120 
121   // Default values
bool_default()122   bool bool_default() const {
123     assert(type_ == BOOL);
124     return default_.b;
125   }
126 
int_default()127   int int_default() const {
128     assert(type_ == INT);
129     return default_.i;
130   }
131 
float_default()132   double float_default() const {
133     assert(type_ == FLOAT);
134     return default_.f;
135   }
136 
string_default()137   const char* string_default() const {
138     assert(type_ == STRING);
139     return default_.s;
140   }
141 
142   // Resets a flag to its default value
143   void SetToDefault();
144 
145   // Iteration support
next()146   Flag* next() const  { return next_; }
147 
148   // Prints flag information. The current flag value is only printed
149   // if print_current_value is set.
150   void Print(bool print_current_value);
151 
152  private:
153   const char* file_;
154   const char* name_;
155   const char* comment_;
156 
157   Type type_;
158   FlagValue* variable_;
159   FlagValue default_;
160 
161   Flag* next_;
162 
163   friend class FlagList;  // accesses next_
164 };
165 
166 
167 // Internal use only.
168 #define DEFINE_FLAG(type, c_type, name, default, comment) \
169   /* define and initialize the flag */                    \
170   c_type FLAG_##name = (default);                         \
171   /* register the flag */                                 \
172   static Flag Flag_##name(__FILE__, #name, (comment),   \
173                           Flag::type, &FLAG_##name,       \
174                           FlagValue::New_##type(default))
175 
176 
177 // Internal use only.
178 #define DECLARE_FLAG(c_type, name)              \
179   /* declare the external flag */               \
180   extern c_type FLAG_##name
181 
182 
183 // Use the following macros to define a new flag:
184 #define DEFINE_bool(name, default, comment) \
185   DEFINE_FLAG(BOOL, bool, name, default, comment)
186 #define DEFINE_int(name, default, comment) \
187   DEFINE_FLAG(INT, int, name, default, comment)
188 #define DEFINE_float(name, default, comment) \
189   DEFINE_FLAG(FLOAT, double, name, default, comment)
190 #define DEFINE_string(name, default, comment) \
191   DEFINE_FLAG(STRING, const char*, name, default, comment)
192 
193 
194 // Use the following macros to declare a flag defined elsewhere:
195 #define DECLARE_bool(name)  DECLARE_FLAG(bool, name)
196 #define DECLARE_int(name)  DECLARE_FLAG(int, name)
197 #define DECLARE_float(name)  DECLARE_FLAG(double, name)
198 #define DECLARE_string(name)  DECLARE_FLAG(const char*, name)
199 
200 
201 // The global list of all flags.
202 class FlagList {
203  public:
204   FlagList();
205 
206   // The NULL-terminated list of all flags. Traverse with Flag::next().
list()207   static Flag* list()  { return list_; }
208 
209   // If file != NULL, prints information for all flags defined in file;
210   // otherwise prints information for all flags in all files. The current
211   // flag value is only printed if print_current_value is set.
212   static void Print(const char* file, bool print_current_value);
213 
214   // Lookup a flag by name. Returns the matching flag or NULL.
215   static Flag* Lookup(const char* name);
216 
217   // Helper function to parse flags: Takes an argument arg and splits it into
218   // a flag name and flag value (or NULL if they are missing). is_bool is set
219   // if the arg started with "-no" or "--no". The buffer may be used to NUL-
220   // terminate the name, it must be large enough to hold any possible name.
221   static void SplitArgument(const char* arg,
222                             char* buffer, int buffer_size,
223                             const char** name, const char** value,
224                             bool* is_bool);
225 
226   // Set the flag values by parsing the command line. If remove_flags
227   // is set, the flags and associated values are removed from (argc,
228   // argv). Returns 0 if no error occurred. Otherwise, returns the
229   // argv index > 0 for the argument where an error occurred. In that
230   // case, (argc, argv) will remain unchanged indepdendent of the
231   // remove_flags value, and no assumptions about flag settings should
232   // be made.
233   //
234   // The following syntax for flags is accepted (both '-' and '--' are ok):
235   //
236   //   --flag        (bool flags only)
237   //   --noflag      (bool flags only)
238   //   --flag=value  (non-bool flags only, no spaces around '=')
239   //   --flag value  (non-bool flags only)
240   static int SetFlagsFromCommandLine(int* argc,
241                                      const char** argv,
242                                      bool remove_flags);
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)243   static inline int SetFlagsFromCommandLine(int* argc,
244                                             char** argv,
245                                             bool remove_flags) {
246     return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
247                                    remove_flags);
248   }
249 
250   // Registers a new flag. Called during program initialization. Not
251   // thread-safe.
252   static void Register(Flag* flag);
253 
254  private:
255   static Flag* list_;
256 };
257 
258 #ifdef WIN32
259 // A helper class to translate Windows command line arguments into UTF8,
260 // which then allows us to just pass them to the flags system.
261 // This encapsulates all the work of getting the command line and translating
262 // it to an array of 8-bit strings; all you have to do is create one of these,
263 // and then call argc() and argv().
264 class WindowsCommandLineArguments {
265  public:
266   WindowsCommandLineArguments();
267   ~WindowsCommandLineArguments();
268 
argc()269   int argc() { return argc_; }
argv()270   char **argv() { return argv_; }
271  private:
272   int argc_;
273   char **argv_;
274 
275  private:
276   DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments);
277 };
278 #endif  // WIN32
279 
280 
281 #endif  // SHARED_COMMANDLINEFLAGS_FLAGS_H__
282