| // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This is a helper class for dealing with command line flags. It uses |
| // base/command_line.h to parse flags from argv, but provides an API similar |
| // to gflags. Command line arguments with either '-' or '--' prefixes are |
| // treated as flags. Flags can optionally have a value set using an '=' |
| // delimeter, e.g. "--flag=value". An argument of "--" will terminate flag |
| // parsing, so that any subsequent arguments will be treated as non-flag |
| // arguments, regardless of prefix. Non-flag arguments are outside the scope |
| // of this class, and can instead be accessed through the GetArgs() function |
| // of the base::CommandLine singleton after FlagHelper initialization. |
| // |
| // The FlagHelper class will automatically take care of the --help flag, as |
| // well as aborting the program when unknown flags are passed to the |
| // application and when passed in parameters cannot be correctly parsed to |
| // their respective types. Developers define flags at compile time using the |
| // following macros from within main(): |
| // |
| // DEFINE_bool(name, default_value, help) |
| // DEFINE_int32(name, default_value, help) |
| // DEFINE_uint32(name, default_value, help) |
| // DEFINE_int64(name, default_value, help) |
| // DEFINE_uint64(name, default_value, help) |
| // DEFINE_double(name, default_value, help) |
| // DEFINE_string(name, default_value, help) |
| // |
| // Using the macro will create a scoped variable of the appropriate type |
| // with the name FLAGS_<name>, that can be used to access the flag's |
| // value within the program. Here is an example of how the FlagHelper |
| // class is to be used: |
| // |
| // -- |
| // |
| // #include <brillo/flag_helper.h> |
| // #include <stdio.h> |
| // |
| // int main(int argc, char** argv) { |
| // DEFINE_int32(example, 0, "Example int flag"); |
| // brillo::FlagHelper::Init(argc, argv, "Test application."); |
| // |
| // printf("You passed in %d to --example command line flag\n", |
| // FLAGS_example); |
| // return 0; |
| // } |
| // |
| // -- |
| // |
| // In order to update the FLAGS_xxxx values from their defaults to the |
| // values passed in to the command line, Init(...) must be called after |
| // all the DEFINE_xxxx macros have instantiated the variables. |
| |
| #ifndef LIBBRILLO_BRILLO_FLAG_HELPER_H_ |
| #define LIBBRILLO_BRILLO_FLAG_HELPER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include <base/command_line.h> |
| #include <base/macros.h> |
| #include <brillo/brillo_export.h> |
| |
| namespace brillo { |
| |
| // The corresponding class representation of a command line flag, used |
| // to keep track of pointers to the FLAGS_xxxx variables so that they |
| // can be updated. |
| class Flag { |
| public: |
| Flag(const char* name, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| virtual ~Flag() = default; |
| |
| // Sets the associated FLAGS_xxxx value, taking into account the flag type |
| virtual bool SetValue(const std::string& value) = 0; |
| |
| // Returns the type of the flag as a char array, for use in the help message |
| virtual const char* GetType() const = 0; |
| |
| const char* name_; |
| const char* default_value_; |
| const char* help_; |
| bool visible_; |
| }; |
| |
| class BRILLO_EXPORT BoolFlag final : public Flag { |
| public: |
| BoolFlag(const char* name, |
| bool* value, |
| bool* no_value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| bool* value_; |
| bool* no_value_; |
| }; |
| |
| class BRILLO_EXPORT Int32Flag final : public Flag { |
| public: |
| Int32Flag(const char* name, |
| int* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| int* value_; |
| }; |
| |
| class BRILLO_EXPORT UInt32Flag final : public Flag { |
| public: |
| UInt32Flag(const char* name, |
| uint32_t* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| uint32_t* value_; |
| }; |
| |
| class BRILLO_EXPORT Int64Flag final : public Flag { |
| public: |
| Int64Flag(const char* name, |
| int64_t* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| int64_t* value_; |
| }; |
| |
| class BRILLO_EXPORT UInt64Flag final : public Flag { |
| public: |
| UInt64Flag(const char* name, |
| uint64_t* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| uint64_t* value_; |
| }; |
| |
| class BRILLO_EXPORT DoubleFlag final : public Flag { |
| public: |
| DoubleFlag(const char* name, |
| double* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| double* value_; |
| }; |
| |
| class BRILLO_EXPORT StringFlag final : public Flag { |
| public: |
| StringFlag(const char* name, |
| std::string* value, |
| const char* default_value, |
| const char* help, |
| bool visible); |
| bool SetValue(const std::string& value) override; |
| |
| const char* GetType() const override; |
| |
| private: |
| std::string* value_; |
| }; |
| |
| // The following macros are to be used from within main() to create |
| // scoped FLAGS_xxxx variables for easier access to command line flag |
| // values. FLAGS_noxxxx variables are also created, which are used to |
| // set bool flags to false. Creating the FLAGS_noxxxx variables here |
| // will also ensure a compiler error will be thrown if another flag |
| // is created with a conflicting name. |
| #define DEFINE_type(type, classtype, name, value, help) \ |
| type FLAGS_##name = value; \ |
| brillo::FlagHelper::GetInstance()->AddFlag(std::unique_ptr<brillo::Flag>( \ |
| new brillo::classtype(#name, &FLAGS_##name, #value, help, true))); |
| |
| #define DEFINE_int32(name, value, help) \ |
| DEFINE_type(int, Int32Flag, name, value, help) |
| #define DEFINE_uint32(name, value, help) \ |
| DEFINE_type(uint32_t, UInt32Flag, name, value, help) |
| #define DEFINE_int64(name, value, help) \ |
| DEFINE_type(int64_t, Int64Flag, name, value, help) |
| #define DEFINE_uint64(name, value, help) \ |
| DEFINE_type(uint64_t, UInt64Flag, name, value, help) |
| #define DEFINE_double(name, value, help) \ |
| DEFINE_type(double, DoubleFlag, name, value, help) |
| #define DEFINE_string(name, value, help) \ |
| DEFINE_type(std::string, StringFlag, name, value, help) |
| |
| // Due to the FLAGS_no##name variables, can't re-use the same DEFINE_type macro |
| // for defining bool flags |
| #define DEFINE_bool(name, value, help) \ |
| bool FLAGS_##name = value; \ |
| bool FLAGS_no##name = !value; \ |
| brillo::FlagHelper::GetInstance()->AddFlag( \ |
| std::unique_ptr<brillo::Flag>(new brillo::BoolFlag( \ |
| #name, &FLAGS_##name, &FLAGS_no##name, #value, help, true))); \ |
| brillo::FlagHelper::GetInstance()->AddFlag( \ |
| std::unique_ptr<brillo::Flag>(new brillo::BoolFlag( \ |
| "no" #name, &FLAGS_no##name, &FLAGS_##name, #value, help, false))); |
| |
| // The FlagHelper class is a singleton class used for registering command |
| // line flags and pointers to their associated scoped variables, so that |
| // the variables can be updated once the command line arguments have been |
| // parsed by base::CommandLine. |
| class BRILLO_EXPORT FlagHelper final { |
| public: |
| // The singleton accessor function. |
| static FlagHelper* GetInstance(); |
| |
| // Resets the singleton object. Developers shouldn't ever need to use this, |
| // however it is required to be run at the end of every unit test to prevent |
| // Flag definitions from carrying over from previous tests. |
| static void ResetForTesting(); |
| |
| // Initializes the base::CommandLine class, then calls UpdateFlagValues(). |
| static void Init(int argc, const char* const* argv, std::string help_usage); |
| |
| // Only to be used for running unit tests. |
| void set_command_line_for_testing(base::CommandLine* command_line) { |
| command_line_ = command_line; |
| } |
| |
| // Checks all the parsed command line flags. This iterates over the switch |
| // map from base::CommandLine, and finds the corresponding Flag in order to |
| // update the FLAGS_xxxx values to the parsed value. If the --help flag is |
| // passed in, it outputs a help message and exits the program. If an unknown |
| // flag is passed in, it outputs an error message and exits the program with |
| // exit code EX_USAGE. |
| void UpdateFlagValues(); |
| |
| // Adds a flag to be tracked and updated once the command line is actually |
| // parsed. This function is an implementation detail, and is not meant |
| // to be used directly by developers. Developers should instead use the |
| // DEFINE_xxxx macros to register a command line flag. |
| void AddFlag(std::unique_ptr<Flag> flag); |
| |
| // Sets the usage message, which is prepended to the --help message. |
| void SetUsageMessage(std::string help_usage); |
| |
| private: |
| FlagHelper(); |
| FlagHelper(const FlagHelper&) = delete; |
| FlagHelper& operator=(const FlagHelper&) = delete; |
| |
| ~FlagHelper(); |
| |
| // Generates a help message from the Usage Message and registered flags. |
| std::string GetHelpMessage() const; |
| |
| std::string help_usage_; |
| std::map<std::string, std::unique_ptr<Flag>> defined_flags_; |
| |
| // base::CommandLine object for parsing the command line switches. This |
| // object isn't owned by this class, so don't need to delete it in the |
| // destructor. |
| base::CommandLine* command_line_; |
| }; |
| |
| } // namespace brillo |
| |
| #endif // LIBBRILLO_BRILLO_FLAG_HELPER_H_ |