Fuchsia OS > Guides > Syslog has this example:
#include "src/lib/fsl/syslogger/init.h"
#include "src/lib/fxl/command_line.h"
int main(int argc, char** argv) {
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
fsl::InitLoggerFromCommandLine(command_line, {"my_program"});
}
Fuchsia OS > Reference does not have FXL listed:
A search of the Fuchsia Project site has one additional example that has fxl::CommandLineFromArgcArgv()
.
Where do I find arguments, return value and other details on fxl::CommandLineFromArgcArgv()
?
The fxl
API is not documented as part of the official Fuchsia reference (yet).
From the readme in the fxl
directory (link):
In an ideal world, FXL wouldn‘t exist and we could use the C++ standard library’s building blocks. [...] We‘d like to keep FXL small and focused on the problem of “fixing” the C++ standard library, which means you probably shouldn’t put your thing in FXL unless it is related to a particular deficiency of the C++ standard library.
Based on this statement, it seems fxl
is not set up as a long-term project, but rather is meant to become empty/obsolete, when the C++ standard library has been sufficiently adapted. It is possible that documentation effort has been limited for this reason.
We have to rely on the documentation provided directly in the header (link):
// Builds a |CommandLine| from the usual argc/argv.
inline CommandLine CommandLineFromArgcArgv(int argc, const char* const* argv)
The CommandLine
class is defined in the same header. According to the comments, it distinguishes between optional and positional args. Optional arguments are of the form --key=value
or --key
(with no value), but not --key value
. The positional arguments begin with the first argument not of this form (or the special --
separator).
The CommandLine
member functions are:
Accessing the program name (from argv[0]
):
bool has_argv0() const;
const std::string& argv0() const;
Accessing the optional and positional arguments (Option
being a simple struct with members std::string name
/ std::string value
):
const std::vector<Option>& options() const;
const std::vector<std::string>& positional_args() const;
Comparison:
bool operator==(const CommandLine& other) const;
bool operator!=(const CommandLine& other) const;
Accessing optional arguments:
bool HasOption(StringView name, size_t* index = nullptr) const;
bool GetOptionValue(StringView name, std::string* value) const;
std::vector<StringView> GetOptionValues(StringView name) const;
std::string GetOptionValueWithDefault(StringView name, StringView default_value) const;
We can write the following example program (uses structured-binding syntax):
#include <iostream>
#include "src/lib/fxl/command_line.h"
int main(int argc, char** argv) {
const auto cl = fxl::CommandLineFromArgcArgv(argc, argv);
std::cout << "Program name = " << cl.argv0() << std::endl;
std::cout << "Optional: " << cl.options().size() << std::endl;
for (const auto& [name,value] : cl.options()) {
std::cout << name << " -> " << value << std::endl;
}
std::cout << "Positional: " << cl.positional_args().size() << std::endl;
for (const auto& arg : cl.positional_args()) {
std::cout << arg << std::endl;
}
return 0;
}
After compiling the program (based on this answer), we can get the following output (demonstrating how first positional argument filename
turns all following arguments into positional arguments):
$ hello_world_cpp --k1=v1 --k2 --k3=v3 filename --k4=v4
Program name = hello_world_cpp
Optional: 3
k1 -> v1
k2 ->
k3 -> v3
Positional: 2
filename
--k4=v4
Demonstrating --
as a separator:
$ hello_world_cpp --k1=v1 -- --k2=v2
Program name = hello_world_cpp
Optional: 1
k1=v1
Positional: 1
--k2=v2
We could do simple argument parsing using HasOption
:
size_t index;
if (cl.HasOption("key", &index)) {
handle_key(cl.options.at(index).value);
}
Adding this to our program and calling it with --key=abc
would then pass abc
to handle_key
.