1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved. 2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be 3*1a96fba6SXin Li // found in the LICENSE file. 4*1a96fba6SXin Li 5*1a96fba6SXin Li // This is a helper class for dealing with command line flags. It uses 6*1a96fba6SXin Li // base/command_line.h to parse flags from argv, but provides an API similar 7*1a96fba6SXin Li // to gflags. Command line arguments with either '-' or '--' prefixes are 8*1a96fba6SXin Li // treated as flags. Flags can optionally have a value set using an '=' 9*1a96fba6SXin Li // delimeter, e.g. "--flag=value". An argument of "--" will terminate flag 10*1a96fba6SXin Li // parsing, so that any subsequent arguments will be treated as non-flag 11*1a96fba6SXin Li // arguments, regardless of prefix. Non-flag arguments are outside the scope 12*1a96fba6SXin Li // of this class, and can instead be accessed through the GetArgs() function 13*1a96fba6SXin Li // of the base::CommandLine singleton after FlagHelper initialization. 14*1a96fba6SXin Li // 15*1a96fba6SXin Li // The FlagHelper class will automatically take care of the --help flag, as 16*1a96fba6SXin Li // well as aborting the program when unknown flags are passed to the 17*1a96fba6SXin Li // application and when passed in parameters cannot be correctly parsed to 18*1a96fba6SXin Li // their respective types. Developers define flags at compile time using the 19*1a96fba6SXin Li // following macros from within main(): 20*1a96fba6SXin Li // 21*1a96fba6SXin Li // DEFINE_bool(name, default_value, help) 22*1a96fba6SXin Li // DEFINE_int32(name, default_value, help) 23*1a96fba6SXin Li // DEFINE_uint32(name, default_value, help) 24*1a96fba6SXin Li // DEFINE_int64(name, default_value, help) 25*1a96fba6SXin Li // DEFINE_uint64(name, default_value, help) 26*1a96fba6SXin Li // DEFINE_double(name, default_value, help) 27*1a96fba6SXin Li // DEFINE_string(name, default_value, help) 28*1a96fba6SXin Li // 29*1a96fba6SXin Li // Using the macro will create a scoped variable of the appropriate type 30*1a96fba6SXin Li // with the name FLAGS_<name>, that can be used to access the flag's 31*1a96fba6SXin Li // value within the program. Here is an example of how the FlagHelper 32*1a96fba6SXin Li // class is to be used: 33*1a96fba6SXin Li // 34*1a96fba6SXin Li // -- 35*1a96fba6SXin Li // 36*1a96fba6SXin Li // #include <brillo/flag_helper.h> 37*1a96fba6SXin Li // #include <stdio.h> 38*1a96fba6SXin Li // 39*1a96fba6SXin Li // int main(int argc, char** argv) { 40*1a96fba6SXin Li // DEFINE_int32(example, 0, "Example int flag"); 41*1a96fba6SXin Li // brillo::FlagHelper::Init(argc, argv, "Test application."); 42*1a96fba6SXin Li // 43*1a96fba6SXin Li // printf("You passed in %d to --example command line flag\n", 44*1a96fba6SXin Li // FLAGS_example); 45*1a96fba6SXin Li // return 0; 46*1a96fba6SXin Li // } 47*1a96fba6SXin Li // 48*1a96fba6SXin Li // -- 49*1a96fba6SXin Li // 50*1a96fba6SXin Li // In order to update the FLAGS_xxxx values from their defaults to the 51*1a96fba6SXin Li // values passed in to the command line, Init(...) must be called after 52*1a96fba6SXin Li // all the DEFINE_xxxx macros have instantiated the variables. 53*1a96fba6SXin Li 54*1a96fba6SXin Li #ifndef LIBBRILLO_BRILLO_FLAG_HELPER_H_ 55*1a96fba6SXin Li #define LIBBRILLO_BRILLO_FLAG_HELPER_H_ 56*1a96fba6SXin Li 57*1a96fba6SXin Li #include <map> 58*1a96fba6SXin Li #include <memory> 59*1a96fba6SXin Li #include <string> 60*1a96fba6SXin Li 61*1a96fba6SXin Li #include <base/command_line.h> 62*1a96fba6SXin Li #include <base/macros.h> 63*1a96fba6SXin Li #include <brillo/brillo_export.h> 64*1a96fba6SXin Li 65*1a96fba6SXin Li namespace brillo { 66*1a96fba6SXin Li 67*1a96fba6SXin Li // The corresponding class representation of a command line flag, used 68*1a96fba6SXin Li // to keep track of pointers to the FLAGS_xxxx variables so that they 69*1a96fba6SXin Li // can be updated. 70*1a96fba6SXin Li class Flag { 71*1a96fba6SXin Li public: 72*1a96fba6SXin Li Flag(const char* name, 73*1a96fba6SXin Li const char* default_value, 74*1a96fba6SXin Li const char* help, 75*1a96fba6SXin Li bool visible); 76*1a96fba6SXin Li virtual ~Flag() = default; 77*1a96fba6SXin Li 78*1a96fba6SXin Li // Sets the associated FLAGS_xxxx value, taking into account the flag type 79*1a96fba6SXin Li virtual bool SetValue(const std::string& value) = 0; 80*1a96fba6SXin Li 81*1a96fba6SXin Li // Returns the type of the flag as a char array, for use in the help message 82*1a96fba6SXin Li virtual const char* GetType() const = 0; 83*1a96fba6SXin Li 84*1a96fba6SXin Li const char* name_; 85*1a96fba6SXin Li const char* default_value_; 86*1a96fba6SXin Li const char* help_; 87*1a96fba6SXin Li bool visible_; 88*1a96fba6SXin Li }; 89*1a96fba6SXin Li 90*1a96fba6SXin Li class BRILLO_EXPORT BoolFlag final : public Flag { 91*1a96fba6SXin Li public: 92*1a96fba6SXin Li BoolFlag(const char* name, 93*1a96fba6SXin Li bool* value, 94*1a96fba6SXin Li bool* no_value, 95*1a96fba6SXin Li const char* default_value, 96*1a96fba6SXin Li const char* help, 97*1a96fba6SXin Li bool visible); 98*1a96fba6SXin Li bool SetValue(const std::string& value) override; 99*1a96fba6SXin Li 100*1a96fba6SXin Li const char* GetType() const override; 101*1a96fba6SXin Li 102*1a96fba6SXin Li private: 103*1a96fba6SXin Li bool* value_; 104*1a96fba6SXin Li bool* no_value_; 105*1a96fba6SXin Li }; 106*1a96fba6SXin Li 107*1a96fba6SXin Li class BRILLO_EXPORT Int32Flag final : public Flag { 108*1a96fba6SXin Li public: 109*1a96fba6SXin Li Int32Flag(const char* name, 110*1a96fba6SXin Li int* value, 111*1a96fba6SXin Li const char* default_value, 112*1a96fba6SXin Li const char* help, 113*1a96fba6SXin Li bool visible); 114*1a96fba6SXin Li bool SetValue(const std::string& value) override; 115*1a96fba6SXin Li 116*1a96fba6SXin Li const char* GetType() const override; 117*1a96fba6SXin Li 118*1a96fba6SXin Li private: 119*1a96fba6SXin Li int* value_; 120*1a96fba6SXin Li }; 121*1a96fba6SXin Li 122*1a96fba6SXin Li class BRILLO_EXPORT UInt32Flag final : public Flag { 123*1a96fba6SXin Li public: 124*1a96fba6SXin Li UInt32Flag(const char* name, 125*1a96fba6SXin Li uint32_t* value, 126*1a96fba6SXin Li const char* default_value, 127*1a96fba6SXin Li const char* help, 128*1a96fba6SXin Li bool visible); 129*1a96fba6SXin Li bool SetValue(const std::string& value) override; 130*1a96fba6SXin Li 131*1a96fba6SXin Li const char* GetType() const override; 132*1a96fba6SXin Li 133*1a96fba6SXin Li private: 134*1a96fba6SXin Li uint32_t* value_; 135*1a96fba6SXin Li }; 136*1a96fba6SXin Li 137*1a96fba6SXin Li class BRILLO_EXPORT Int64Flag final : public Flag { 138*1a96fba6SXin Li public: 139*1a96fba6SXin Li Int64Flag(const char* name, 140*1a96fba6SXin Li int64_t* value, 141*1a96fba6SXin Li const char* default_value, 142*1a96fba6SXin Li const char* help, 143*1a96fba6SXin Li bool visible); 144*1a96fba6SXin Li bool SetValue(const std::string& value) override; 145*1a96fba6SXin Li 146*1a96fba6SXin Li const char* GetType() const override; 147*1a96fba6SXin Li 148*1a96fba6SXin Li private: 149*1a96fba6SXin Li int64_t* value_; 150*1a96fba6SXin Li }; 151*1a96fba6SXin Li 152*1a96fba6SXin Li class BRILLO_EXPORT UInt64Flag final : public Flag { 153*1a96fba6SXin Li public: 154*1a96fba6SXin Li UInt64Flag(const char* name, 155*1a96fba6SXin Li uint64_t* value, 156*1a96fba6SXin Li const char* default_value, 157*1a96fba6SXin Li const char* help, 158*1a96fba6SXin Li bool visible); 159*1a96fba6SXin Li bool SetValue(const std::string& value) override; 160*1a96fba6SXin Li 161*1a96fba6SXin Li const char* GetType() const override; 162*1a96fba6SXin Li 163*1a96fba6SXin Li private: 164*1a96fba6SXin Li uint64_t* value_; 165*1a96fba6SXin Li }; 166*1a96fba6SXin Li 167*1a96fba6SXin Li class BRILLO_EXPORT DoubleFlag final : public Flag { 168*1a96fba6SXin Li public: 169*1a96fba6SXin Li DoubleFlag(const char* name, 170*1a96fba6SXin Li double* value, 171*1a96fba6SXin Li const char* default_value, 172*1a96fba6SXin Li const char* help, 173*1a96fba6SXin Li bool visible); 174*1a96fba6SXin Li bool SetValue(const std::string& value) override; 175*1a96fba6SXin Li 176*1a96fba6SXin Li const char* GetType() const override; 177*1a96fba6SXin Li 178*1a96fba6SXin Li private: 179*1a96fba6SXin Li double* value_; 180*1a96fba6SXin Li }; 181*1a96fba6SXin Li 182*1a96fba6SXin Li class BRILLO_EXPORT StringFlag final : public Flag { 183*1a96fba6SXin Li public: 184*1a96fba6SXin Li StringFlag(const char* name, 185*1a96fba6SXin Li std::string* value, 186*1a96fba6SXin Li const char* default_value, 187*1a96fba6SXin Li const char* help, 188*1a96fba6SXin Li bool visible); 189*1a96fba6SXin Li bool SetValue(const std::string& value) override; 190*1a96fba6SXin Li 191*1a96fba6SXin Li const char* GetType() const override; 192*1a96fba6SXin Li 193*1a96fba6SXin Li private: 194*1a96fba6SXin Li std::string* value_; 195*1a96fba6SXin Li }; 196*1a96fba6SXin Li 197*1a96fba6SXin Li // The following macros are to be used from within main() to create 198*1a96fba6SXin Li // scoped FLAGS_xxxx variables for easier access to command line flag 199*1a96fba6SXin Li // values. FLAGS_noxxxx variables are also created, which are used to 200*1a96fba6SXin Li // set bool flags to false. Creating the FLAGS_noxxxx variables here 201*1a96fba6SXin Li // will also ensure a compiler error will be thrown if another flag 202*1a96fba6SXin Li // is created with a conflicting name. 203*1a96fba6SXin Li #define DEFINE_type(type, classtype, name, value, help) \ 204*1a96fba6SXin Li type FLAGS_##name = value; \ 205*1a96fba6SXin Li brillo::FlagHelper::GetInstance()->AddFlag(std::unique_ptr<brillo::Flag>( \ 206*1a96fba6SXin Li new brillo::classtype(#name, &FLAGS_##name, #value, help, true))); 207*1a96fba6SXin Li 208*1a96fba6SXin Li #define DEFINE_int32(name, value, help) \ 209*1a96fba6SXin Li DEFINE_type(int, Int32Flag, name, value, help) 210*1a96fba6SXin Li #define DEFINE_uint32(name, value, help) \ 211*1a96fba6SXin Li DEFINE_type(uint32_t, UInt32Flag, name, value, help) 212*1a96fba6SXin Li #define DEFINE_int64(name, value, help) \ 213*1a96fba6SXin Li DEFINE_type(int64_t, Int64Flag, name, value, help) 214*1a96fba6SXin Li #define DEFINE_uint64(name, value, help) \ 215*1a96fba6SXin Li DEFINE_type(uint64_t, UInt64Flag, name, value, help) 216*1a96fba6SXin Li #define DEFINE_double(name, value, help) \ 217*1a96fba6SXin Li DEFINE_type(double, DoubleFlag, name, value, help) 218*1a96fba6SXin Li #define DEFINE_string(name, value, help) \ 219*1a96fba6SXin Li DEFINE_type(std::string, StringFlag, name, value, help) 220*1a96fba6SXin Li 221*1a96fba6SXin Li // Due to the FLAGS_no##name variables, can't re-use the same DEFINE_type macro 222*1a96fba6SXin Li // for defining bool flags 223*1a96fba6SXin Li #define DEFINE_bool(name, value, help) \ 224*1a96fba6SXin Li bool FLAGS_##name = value; \ 225*1a96fba6SXin Li bool FLAGS_no##name = !(value); \ 226*1a96fba6SXin Li brillo::FlagHelper::GetInstance()->AddFlag( \ 227*1a96fba6SXin Li std::unique_ptr<brillo::Flag>(new brillo::BoolFlag( \ 228*1a96fba6SXin Li #name, &FLAGS_##name, &FLAGS_no##name, #value, help, true))); \ 229*1a96fba6SXin Li brillo::FlagHelper::GetInstance()->AddFlag( \ 230*1a96fba6SXin Li std::unique_ptr<brillo::Flag>(new brillo::BoolFlag( \ 231*1a96fba6SXin Li "no" #name, &FLAGS_no##name, &FLAGS_##name, #value, help, false))); 232*1a96fba6SXin Li 233*1a96fba6SXin Li // The FlagHelper class is a singleton class used for registering command 234*1a96fba6SXin Li // line flags and pointers to their associated scoped variables, so that 235*1a96fba6SXin Li // the variables can be updated once the command line arguments have been 236*1a96fba6SXin Li // parsed by base::CommandLine. 237*1a96fba6SXin Li class BRILLO_EXPORT FlagHelper final { 238*1a96fba6SXin Li public: 239*1a96fba6SXin Li // The singleton accessor function. 240*1a96fba6SXin Li static FlagHelper* GetInstance(); 241*1a96fba6SXin Li 242*1a96fba6SXin Li // Resets the singleton object. Developers shouldn't ever need to use this, 243*1a96fba6SXin Li // however it is required to be run at the end of every unit test to prevent 244*1a96fba6SXin Li // Flag definitions from carrying over from previous tests. 245*1a96fba6SXin Li static void ResetForTesting(); 246*1a96fba6SXin Li 247*1a96fba6SXin Li // Initializes the base::CommandLine class, then calls UpdateFlagValues(). 248*1a96fba6SXin Li static void Init(int argc, const char* const* argv, std::string help_usage); 249*1a96fba6SXin Li 250*1a96fba6SXin Li // Only to be used for running unit tests. set_command_line_for_testing(base::CommandLine * command_line)251*1a96fba6SXin Li void set_command_line_for_testing(base::CommandLine* command_line) { 252*1a96fba6SXin Li command_line_ = command_line; 253*1a96fba6SXin Li } 254*1a96fba6SXin Li 255*1a96fba6SXin Li // Checks all the parsed command line flags. This iterates over the switch 256*1a96fba6SXin Li // map from base::CommandLine, and finds the corresponding Flag in order to 257*1a96fba6SXin Li // update the FLAGS_xxxx values to the parsed value. If the --help flag is 258*1a96fba6SXin Li // passed in, it outputs a help message and exits the program. If an unknown 259*1a96fba6SXin Li // flag is passed in, it outputs an error message and exits the program with 260*1a96fba6SXin Li // exit code EX_USAGE. 261*1a96fba6SXin Li void UpdateFlagValues(); 262*1a96fba6SXin Li 263*1a96fba6SXin Li // Adds a flag to be tracked and updated once the command line is actually 264*1a96fba6SXin Li // parsed. This function is an implementation detail, and is not meant 265*1a96fba6SXin Li // to be used directly by developers. Developers should instead use the 266*1a96fba6SXin Li // DEFINE_xxxx macros to register a command line flag. 267*1a96fba6SXin Li void AddFlag(std::unique_ptr<Flag> flag); 268*1a96fba6SXin Li 269*1a96fba6SXin Li // Sets the usage message, which is prepended to the --help message. 270*1a96fba6SXin Li void SetUsageMessage(std::string help_usage); 271*1a96fba6SXin Li 272*1a96fba6SXin Li private: 273*1a96fba6SXin Li FlagHelper(); 274*1a96fba6SXin Li ~FlagHelper(); 275*1a96fba6SXin Li 276*1a96fba6SXin Li // Generates a help message from the Usage Message and registered flags. 277*1a96fba6SXin Li std::string GetHelpMessage() const; 278*1a96fba6SXin Li 279*1a96fba6SXin Li std::string help_usage_; 280*1a96fba6SXin Li std::map<std::string, std::unique_ptr<Flag>> defined_flags_; 281*1a96fba6SXin Li 282*1a96fba6SXin Li // base::CommandLine object for parsing the command line switches. This 283*1a96fba6SXin Li // object isn't owned by this class, so don't need to delete it in the 284*1a96fba6SXin Li // destructor. 285*1a96fba6SXin Li base::CommandLine* command_line_; 286*1a96fba6SXin Li 287*1a96fba6SXin Li DISALLOW_COPY_AND_ASSIGN(FlagHelper); 288*1a96fba6SXin Li }; 289*1a96fba6SXin Li 290*1a96fba6SXin Li } // namespace brillo 291*1a96fba6SXin Li 292*1a96fba6SXin Li #endif // LIBBRILLO_BRILLO_FLAG_HELPER_H_ 293