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 29 // Originally comes from shared/commandlineflags/flags.h 30 31 // Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros, 32 // where xxx is the flag type. Flags are referred to via FLAG_yyy, 33 // where yyy is the flag name. For intialization and iteration of flags, 34 // see the FlagList class. For full programmatic access to any 35 // flag, see the Flag class. 36 // 37 // The implementation only relies and basic C++ functionality 38 // and needs no special library or STL support. 39 40 #ifndef TALK_BASE_FLAGS_H__ 41 #define TALK_BASE_FLAGS_H__ 42 43 #include <assert.h> 44 45 #include "talk/base/checks.h" 46 #include "talk/base/common.h" 47 48 // Internal use only. 49 union FlagValue { 50 // Note: Because in C++ non-bool values are silently converted into 51 // bool values ('bool b = "false";' results in b == true!), we pass 52 // and int argument to New_BOOL as this appears to be safer - sigh. 53 // In particular, it prevents the (not uncommon!) bug where a bool 54 // flag is defined via: DEFINE_bool(flag, "false", "some comment");. 55 static FlagValue New_BOOL(int b) { 56 FlagValue v; 57 v.b = (b != 0); 58 return v; 59 } 60 61 static FlagValue New_INT(int i) { 62 FlagValue v; 63 v.i = i; 64 return v; 65 } 66 67 static FlagValue New_FLOAT(float f) { 68 FlagValue v; 69 v.f = f; 70 return v; 71 } 72 73 static FlagValue New_STRING(const char* s) { 74 FlagValue v; 75 v.s = s; 76 return v; 77 } 78 79 bool b; 80 int i; 81 double f; 82 const char* s; 83 }; 84 85 86 // Each flag can be accessed programmatically via a Flag object. 87 class Flag { 88 public: 89 enum Type { BOOL, INT, FLOAT, STRING }; 90 91 // Internal use only. 92 Flag(const char* file, const char* name, const char* comment, 93 Type type, void* variable, FlagValue default_); 94 95 // General flag information 96 const char* file() const { return file_; } 97 const char* name() const { return name_; } 98 const char* comment() const { return comment_; } 99 100 // Flag type 101 Type type() const { return type_; } 102 103 // Flag variables 104 bool* bool_variable() const { 105 assert(type_ == BOOL); 106 return &variable_->b; 107 } 108 109 int* int_variable() const { 110 assert(type_ == INT); 111 return &variable_->i; 112 } 113 114 double* float_variable() const { 115 assert(type_ == FLOAT); 116 return &variable_->f; 117 } 118 119 const char** string_variable() const { 120 assert(type_ == STRING); 121 return &variable_->s; 122 } 123 124 // Default values 125 bool bool_default() const { 126 assert(type_ == BOOL); 127 return default_.b; 128 } 129 130 int int_default() const { 131 assert(type_ == INT); 132 return default_.i; 133 } 134 135 double float_default() const { 136 assert(type_ == FLOAT); 137 return default_.f; 138 } 139 140 const char* string_default() const { 141 assert(type_ == STRING); 142 return default_.s; 143 } 144 145 // Resets a flag to its default value 146 void SetToDefault(); 147 148 // Iteration support 149 Flag* next() const { return next_; } 150 151 // Prints flag information. The current flag value is only printed 152 // if print_current_value is set. 153 void Print(bool print_current_value); 154 155 private: 156 const char* file_; 157 const char* name_; 158 const char* comment_; 159 160 Type type_; 161 FlagValue* variable_; 162 FlagValue default_; 163 164 Flag* next_; 165 166 friend class FlagList; // accesses next_ 167 }; 168 169 170 // Internal use only. 171 #define DEFINE_FLAG(type, c_type, name, default, comment) \ 172 /* define and initialize the flag */ \ 173 c_type FLAG_##name = (default); \ 174 /* register the flag */ \ 175 static Flag Flag_##name(__FILE__, #name, (comment), \ 176 Flag::type, &FLAG_##name, \ 177 FlagValue::New_##type(default)) 178 179 180 // Internal use only. 181 #define DECLARE_FLAG(c_type, name) \ 182 /* declare the external flag */ \ 183 extern c_type FLAG_##name 184 185 186 // Use the following macros to define a new flag: 187 #define DEFINE_bool(name, default, comment) \ 188 DEFINE_FLAG(BOOL, bool, name, default, comment) 189 #define DEFINE_int(name, default, comment) \ 190 DEFINE_FLAG(INT, int, name, default, comment) 191 #define DEFINE_float(name, default, comment) \ 192 DEFINE_FLAG(FLOAT, double, name, default, comment) 193 #define DEFINE_string(name, default, comment) \ 194 DEFINE_FLAG(STRING, const char*, name, default, comment) 195 196 197 // Use the following macros to declare a flag defined elsewhere: 198 #define DECLARE_bool(name) DECLARE_FLAG(bool, name) 199 #define DECLARE_int(name) DECLARE_FLAG(int, name) 200 #define DECLARE_float(name) DECLARE_FLAG(double, name) 201 #define DECLARE_string(name) DECLARE_FLAG(const char*, name) 202 203 204 // The global list of all flags. 205 class FlagList { 206 public: 207 FlagList(); 208 209 // The NULL-terminated list of all flags. Traverse with Flag::next(). 210 static Flag* list() { return list_; } 211 212 // If file != NULL, prints information for all flags defined in file; 213 // otherwise prints information for all flags in all files. The current 214 // flag value is only printed if print_current_value is set. 215 static void Print(const char* file, bool print_current_value); 216 217 // Lookup a flag by name. Returns the matching flag or NULL. 218 static Flag* Lookup(const char* name); 219 220 // Helper function to parse flags: Takes an argument arg and splits it into 221 // a flag name and flag value (or NULL if they are missing). is_bool is set 222 // if the arg started with "-no" or "--no". The buffer may be used to NUL- 223 // terminate the name, it must be large enough to hold any possible name. 224 static void SplitArgument(const char* arg, 225 char* buffer, int buffer_size, 226 const char** name, const char** value, 227 bool* is_bool); 228 229 // Set the flag values by parsing the command line. If remove_flags 230 // is set, the flags and associated values are removed from (argc, 231 // argv). Returns 0 if no error occurred. Otherwise, returns the 232 // argv index > 0 for the argument where an error occurred. In that 233 // case, (argc, argv) will remain unchanged indepdendent of the 234 // remove_flags value, and no assumptions about flag settings should 235 // be made. 236 // 237 // The following syntax for flags is accepted (both '-' and '--' are ok): 238 // 239 // --flag (bool flags only) 240 // --noflag (bool flags only) 241 // --flag=value (non-bool flags only, no spaces around '=') 242 // --flag value (non-bool flags only) 243 static int SetFlagsFromCommandLine(int* argc, 244 const char** argv, 245 bool remove_flags); 246 static inline int SetFlagsFromCommandLine(int* argc, 247 char** argv, 248 bool remove_flags) { 249 return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv), 250 remove_flags); 251 } 252 253 // Registers a new flag. Called during program initialization. Not 254 // thread-safe. 255 static void Register(Flag* flag); 256 257 private: 258 static Flag* list_; 259 }; 260 261 #ifdef WIN32 262 // A helper class to translate Windows command line arguments into UTF8, 263 // which then allows us to just pass them to the flags system. 264 // This encapsulates all the work of getting the command line and translating 265 // it to an array of 8-bit strings; all you have to do is create one of these, 266 // and then call argc() and argv(). 267 class WindowsCommandLineArguments { 268 public: 269 WindowsCommandLineArguments(); 270 ~WindowsCommandLineArguments(); 271 272 int argc() { return argc_; } 273 char **argv() { return argv_; } 274 private: 275 int argc_; 276 char **argv_; 277 278 private: 279 DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments); 280 }; 281 #endif // WIN32 282 283 284 #endif // SHARED_COMMANDLINEFLAGS_FLAGS_H__ 285