Home | History | Annotate | Download | only in base
      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