xref: /aosp_15_r20/external/libbrillo/brillo/flag_helper.h (revision 1a96fba65179ea7d3f56207137718607415c5953)
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