Commit 8f4112be authored by Dominik Charousset's avatar Dominik Charousset Committed by Hauke Goldhammer

Add convenience function for C-style arg remainder

parent 065ad856
...@@ -185,9 +185,20 @@ public: ...@@ -185,9 +185,20 @@ public:
/// and instead return from `main` immediately. /// and instead return from `main` immediately.
bool cli_helptext_printed; bool cli_helptext_printed;
/// Stores the content of `argv[0]` from the arguments passed to `parse`.
std::string program_name;
/// Stores CLI arguments that were not consumed by CAF. /// Stores CLI arguments that were not consumed by CAF.
string_list remainder; string_list remainder;
/// Returns the remainder including the program name (`argv[0]`) suitable for
/// passing the returned pair of arguments to C-style functions that usually
/// accept `(argc, argv)` input as passed to `main`. This function creates the
/// necessary buffers lazily on first call.
/// @note The returned pointer remains valid only as long as the
/// `actor_system_config` object exists.
std::pair<int, char**> c_args_remainder();
// -- caf-run parameters ----------------------------------------------------- // -- caf-run parameters -----------------------------------------------------
/// Stores whether this node was started in slave mode. /// Stores whether this node was started in slave mode.
...@@ -317,6 +328,9 @@ protected: ...@@ -317,6 +328,9 @@ protected:
config_option_set custom_options_; config_option_set custom_options_;
private: private:
std::vector<char*> c_args_remainder_;
std::vector<char> c_args_remainder_buf_;
actor_system_config& set_impl(string_view name, config_value value); actor_system_config& set_impl(string_view name, config_value value);
error extract_config_file_path(string_list& args); error extract_config_file_path(string_list& args);
......
...@@ -53,6 +53,7 @@ actor_system_config::~actor_system_config() { ...@@ -53,6 +53,7 @@ actor_system_config::~actor_system_config() {
actor_system_config::actor_system_config() actor_system_config::actor_system_config()
: cli_helptext_printed(false), : cli_helptext_printed(false),
program_name("unknown-caf-app"),
slave_mode(false), slave_mode(false),
config_file_path(default_config_file), config_file_path(default_config_file),
slave_mode_fun(nullptr) { slave_mode_fun(nullptr) {
...@@ -187,18 +188,45 @@ settings actor_system_config::dump_content() const { ...@@ -187,18 +188,45 @@ settings actor_system_config::dump_content() const {
error actor_system_config::parse(int argc, char** argv, error actor_system_config::parse(int argc, char** argv,
const char* config_file_cstr) { const char* config_file_cstr) {
string_list args; string_list args;
if (argc > 1) if (argc > 0) {
args.assign(argv + 1, argv + argc); program_name = argv[0];
if (argc > 1)
args.assign(argv + 1, argv + argc);
}
return parse(std::move(args), config_file_cstr); return parse(std::move(args), config_file_cstr);
} }
error actor_system_config::parse(int argc, char** argv, std::istream& conf) { error actor_system_config::parse(int argc, char** argv, std::istream& conf) {
string_list args; string_list args;
if (argc > 1) if (argc > 0) {
args.assign(argv + 1, argv + argc); program_name = argv[0];
if (argc > 1)
args.assign(argv + 1, argv + argc);
}
return parse(std::move(args), conf); return parse(std::move(args), conf);
} }
std::pair<int, char**> actor_system_config::c_args_remainder() {
if (c_args_remainder_.empty()) {
c_args_remainder_buf_.assign(program_name.begin(), program_name.end());
c_args_remainder_buf_.emplace_back('\0');
for (const auto& arg : remainder) {
c_args_remainder_buf_.insert(c_args_remainder_buf_.end(), //
arg.begin(), arg.end());
c_args_remainder_buf_.emplace_back('\0');
}
auto ptr = c_args_remainder_buf_.data();
auto end = ptr + c_args_remainder_buf_.size();
auto advance_ptr = [&ptr] {
while (*ptr++ != '\0')
; // nop
};
for (; ptr != end; advance_ptr())
c_args_remainder_.emplace_back(ptr);
}
return {static_cast<int>(c_args_remainder_.size()), c_args_remainder_.data()};
}
namespace { namespace {
struct config_iter { struct config_iter {
......
...@@ -85,6 +85,9 @@ CAF_TEST(parsing - without CLI arguments) { ...@@ -85,6 +85,9 @@ CAF_TEST(parsing - without CLI arguments) {
parse(text); parse(text);
CAF_CHECK(cfg.remainder.empty()); CAF_CHECK(cfg.remainder.empty());
CAF_CHECK_EQUAL(get_or(cfg, "foo.bar", ""), "hello"); CAF_CHECK_EQUAL(get_or(cfg, "foo.bar", ""), "hello");
auto [argc, argv] = cfg.c_args_remainder();
CAF_REQUIRE_EQUAL(argc, 1);
CAF_CHECK_EQUAL(argv[0], cfg.program_name);
} }
CAF_TEST(parsing - without CLI cfg.remainder) { CAF_TEST(parsing - without CLI cfg.remainder) {
...@@ -111,11 +114,15 @@ CAF_TEST(parsing - without CLI cfg.remainder) { ...@@ -111,11 +114,15 @@ CAF_TEST(parsing - without CLI cfg.remainder) {
CAF_TEST(parsing - with CLI cfg.remainder) { CAF_TEST(parsing - with CLI cfg.remainder) {
auto text = "foo{\nbar=\"hello\"}"; auto text = "foo{\nbar=\"hello\"}";
options("?foo").add<std::string>("bar,b", "some string parameter"); options("?foo").add<std::string>("bar,b", "some string parameter");
CAF_MESSAGE("valid cfg.remainder");
parse(text, {"-b", "test", "hello", "world"}); parse(text, {"-b", "test", "hello", "world"});
CAF_REQUIRE_EQUAL(cfg.remainder.size(), 2u);
CAF_CHECK_EQUAL(get_or(cfg, "foo.bar", ""), "test"); CAF_CHECK_EQUAL(get_or(cfg, "foo.bar", ""), "test");
CAF_CHECK_EQUAL(cfg.remainder, string_list({"hello", "world"})); CAF_CHECK_EQUAL(cfg.remainder, string_list({"hello", "world"}));
CAF_MESSAGE("invalid cfg.remainder"); auto [argc, argv] = cfg.c_args_remainder();
CAF_REQUIRE_EQUAL(argc, 3);
CAF_CHECK_EQUAL(argv[0], cfg.program_name);
CAF_CHECK_EQUAL(argv[1], cfg.remainder[0]);
CAF_CHECK_EQUAL(argv[2], cfg.remainder[1]);
} }
CAF_TEST(file input overrides defaults but CLI args always win) { CAF_TEST(file input overrides defaults but CLI args always win) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment