Skip to content

Commit 023fe33

Browse files
AlaiaLcodebot
authored andcommitted
cli11: added free functions that allow to write one option in more than one parameter
1 parent 41329fa commit 023fe33

File tree

1 file changed

+108
-15
lines changed

1 file changed

+108
-15
lines changed

include/srsran/support/cli11_utils.h

Lines changed: 108 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,99 @@
1515

1616
namespace srsran {
1717

18-
/// \brief Parse string into optional type.
18+
/// \brief Adds a subcommand to the given application using the given subcommand name and description.
19+
///
20+
/// If the subcommand already exists in the application, returns a pointer to it.
21+
///
22+
/// \param app Application where the subcommand will be created.
23+
/// \param name Subcommand name.
24+
/// \param desc Human readable description of the subcommand.
25+
/// \return A pointer to the subcommand added to the application.
26+
CLI::App* add_subcommand(CLI::App& app, const std::string& name, const std::string& desc)
27+
{
28+
CLI::App* subcommand = app.get_subcommand(name);
29+
if (subcommand) {
30+
return subcommand;
31+
}
32+
33+
return app.add_subcommand(name, desc)->configurable();
34+
}
35+
36+
/// \brief Adds an option to the given application.
37+
///
38+
/// This function adds an option to the given application using the given parameters. If the option is already present
39+
/// in the application, it is removed and a new option is added that will call the callback of the deleted callback and
40+
/// the conversion of the result for the given parameter. By doing this, it allows to add multiple parameters for one
41+
/// option, so one option will be present in the configuration but the result will be written in all the parameters
42+
/// registered for that option.
43+
///
44+
/// \param app Application where the option will be created.
45+
/// \param option_name Option name.
46+
/// \param param Parameter where the option value will be stored after parsing.
47+
/// \param desc Human readable description of the option.
48+
/// \return A pointer to the option added to the application.
49+
template <typename T>
50+
CLI::Option* add_option(CLI::App& app, const std::string& option_name, T& param, const std::string& desc)
51+
{
52+
auto opt = app.get_option_no_throw(option_name);
53+
if (!opt) {
54+
return app.add_option(option_name, param, desc);
55+
}
56+
57+
// Option was found. Get the callback and create new option.
58+
auto callbck = opt->get_callback();
59+
app.remove_option(opt);
60+
61+
return app
62+
.add_option(
63+
option_name,
64+
[&param, callback = std::move(callbck)](const CLI::results_t& res) {
65+
callback(res);
66+
return CLI::detail::lexical_conversion<T, T>(res, param);
67+
},
68+
desc)
69+
->run_callback_for_default();
70+
}
71+
72+
/// \brief Adds an option function to the given application.
73+
///
74+
/// This function adds an option function to the given application using the given parameters. If the option is already
75+
/// present in the application, it is removed and a new option is added that will contain the given function and deleted
76+
/// callback as function. By doing this, it allows to add multiple parameters for one option, so one option will be
77+
/// present in the configuration and the all the functions registered for that option will be called.
78+
///
79+
/// \param app Application where the option will be created.
80+
/// \param option_name Option name.
81+
/// \param func Function to execute during parsing.
82+
/// \param desc Human readable description of the option.
83+
/// \return A pointer to the option added to the application.
84+
template <typename T>
85+
CLI::Option* add_option_function(CLI::App& app,
86+
const std::string& option_name,
87+
const std::function<void(const T&)>& func,
88+
const std::string& desc)
89+
{
90+
auto opt = app.get_option_no_throw(option_name);
91+
if (!opt) {
92+
return app.add_option_function<T>(option_name, func, desc);
93+
}
94+
95+
// Option was found. Get the callback and create new option.
96+
auto callbck = opt->get_callback();
97+
app.remove_option(opt);
98+
99+
return app
100+
.add_option_function<T>(
101+
option_name,
102+
[func, callback = std::move(callbck)](const std::string& value) {
103+
func(value);
104+
callback({value});
105+
},
106+
desc)
107+
->run_callback_for_default();
108+
}
109+
110+
/// Parse string into optional type.
19111
template <typename T>
20112
bool lexical_cast(const std::string& in, srsran::optional<T>& output)
21113
{
@@ -29,25 +121,26 @@ bool lexical_cast(const std::string& in, srsran::optional<T>& output)
29121
return true;
30122
}
31123

32-
/// \brief Parsing an integer with additional option "auto" into an optional of an enum type.
124+
/// Parsing an integer with additional option "auto" into an optional of an enum type.
33125
template <typename Param>
34126
void add_auto_enum_option(CLI::App& app,
35127
const std::string& option_name,
36128
optional<Param>& param,
37129
const std::string& desc)
38130
{
39-
app.add_option_function<std::string>(
40-
option_name,
41-
[&param](const std::string& in) -> void {
42-
if (in.empty() or in == "auto") {
43-
return;
44-
}
45-
std::stringstream ss(in);
46-
std::underlying_type_t<Param> val;
47-
ss >> val;
48-
param = (Param)val;
49-
},
50-
desc)
131+
add_option_function<std::string>(
132+
app,
133+
option_name,
134+
[&param](const std::string& in) -> void {
135+
if (in.empty() or in == "auto") {
136+
return;
137+
}
138+
std::stringstream ss(in);
139+
std::underlying_type_t<Param> val;
140+
ss >> val;
141+
param = (Param)val;
142+
},
143+
desc)
51144
->check([](const std::string& in_str) -> std::string {
52145
if (in_str == "auto" or in_str.empty()) {
53146
return "";
@@ -59,4 +152,4 @@ void add_auto_enum_option(CLI::App& app,
59152
->default_str("auto");
60153
}
61154

62-
} // namespace srsran
155+
} // namespace srsran

0 commit comments

Comments
 (0)