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