Home | History | Annotate | Download | only in base
      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 
     31 namespace rtc {
     32 
     33 // Internal use only.
     34 union 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.
     72 class 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.
    190 class 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().
    252 class 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   RTC_DISALLOW_COPY_AND_ASSIGN(WindowsCommandLineArguments);
    265 };
    266 #endif  // WEBRTC_WIN
    267 
    268 }  // namespace rtc
    269 
    270 #endif  // SHARED_COMMANDLINEFLAGS_FLAGS_H__
    271