diff options
-rw-r--r-- | include/salticidae/util.h | 45 | ||||
-rw-r--r-- | src/util.cpp | 22 |
2 files changed, 55 insertions, 12 deletions
diff --git a/include/salticidae/util.h b/include/salticidae/util.h index de63146..ab052de 100644 --- a/include/salticidae/util.h +++ b/include/salticidae/util.h @@ -34,6 +34,8 @@ #include <getopt.h> #include <event2/event.h> +#include "salticidae/ref.h" + namespace salticidae { void sec2tv(double t, struct timeval &tv); @@ -144,12 +146,19 @@ class Config { virtual void append(const std::string &) { throw SalticidaeError("undefined OptVal behavior: append"); } + virtual ~OptVal() = default; }; + using optval_t = RcObj<OptVal>; + class OptValFlag: public OptVal { bool val; public: + template<typename... Args> + static RcObj<OptValFlag> create(Args... args) { + return new OptValFlag(args...); + } OptValFlag() = default; OptValFlag(bool val): val(val) {} void switch_on() override { val = true; } @@ -159,6 +168,10 @@ class Config { class OptValStr: public OptVal { std::string val; public: + template<typename... Args> + static RcObj<OptValStr> create(Args... args) { + return new OptValStr(args...); + } OptValStr() = default; OptValStr(const std::string &val): val(val) {} void set_val(const std::string &strval) override { @@ -170,6 +183,10 @@ class Config { class OptValInt: public OptVal { int val; public: + template<typename... Args> + static RcObj<OptValInt> create(Args... args) { + return new OptValInt(args...); + } OptValInt() = default; OptValInt(int val): val(val) {} void set_val(const std::string &strval) override { @@ -186,6 +203,10 @@ class Config { class OptValDouble: public OptVal { double val; public: + template<typename... Args> + static RcObj<OptValDouble> create(Args... args) { + return new OptValDouble(args...); + } OptValDouble() = default; OptValDouble(double val): val(val) {} void set_val(const std::string &strval) override { @@ -203,6 +224,10 @@ class Config { using strvec_t = std::vector<std::string>; strvec_t val; public: + template<typename... Args> + static RcObj<OptValStrVec> create(Args... args) { + return new OptValStrVec(args...); + } OptValStrVec() = default; OptValStrVec(const strvec_t &val): val(val) {} void append(const std::string &strval) override { @@ -214,13 +239,16 @@ class Config { private: struct Opt { std::string optname; - OptVal *optval; + std::string optdoc; + optval_t optval; Action action; struct option opt; - Opt(const std::string &optname, OptVal *optval, Action action, int idx); + Opt(const std::string &optname, const std::string &optdoc, + const optval_t &optval, Action action, int idx); Opt(Opt &&other): optname(std::move(other.optname)), - optval(other.optval), + optdoc(std::move(other.optdoc)), + optval(std::move(other.optval)), action(other.action), opt(other.opt) { opt.name = this->optname.c_str(); } }; @@ -228,24 +256,27 @@ class Config { std::unordered_map<std::string, Opt> conf; std::vector<Opt *> getopt_order; std::string conf_fname; - OptValStr opt_val_conf; + RcObj<OptValStr> opt_val_conf; int conf_idx; + void update(const std::string &optname, const char *optval); void update(Opt &opt, const char *optval); public: Config(const std::string &conf_fname): conf_fname(conf_fname), - opt_val_conf(this->conf_fname) { + opt_val_conf(new OptValStr(this->conf_fname)) { conf_idx = getopt_order.size(); - add_opt("conf", opt_val_conf, SET_VAL); + add_opt("conf", opt_val_conf, SET_VAL, "load options from a file"); } ~Config() {} - void add_opt(const std::string &optname, OptVal &optval, Action action); + void add_opt(const std::string &optname, const optval_t &optval, Action action, + const std::string &optdoc = ""); bool load(const std::string &fname); size_t parse(int argc, char **argv); + void print_help(FILE *output = stderr); }; class Event { diff --git a/src/util.cpp b/src/util.cpp index a1086f8..580306c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -134,20 +134,23 @@ void ElapsedTime::stop(bool show_info) { elapsed_sec, cpu_elapsed_sec); } -Config::Opt::Opt(const std::string &optname, OptVal *optval, Action action, int idx): \ - optname(optname), optval(optval), action(action) { +Config::Opt::Opt(const std::string &optname, const std::string &optdoc, + const optval_t &optval, Action action, int idx): + optname(optname), optdoc(optdoc), optval(optval), action(action) { opt.name = this->optname.c_str(); opt.has_arg = action == SWITCH_ON ? no_argument : required_argument; opt.flag = nullptr; opt.val = idx; } -void Config::add_opt(const std::string &optname, OptVal &optval, Action action) { +void Config::add_opt(const std::string &optname, const optval_t &optval, Action action, + const std::string &optdoc) { if (conf.count(optname)) throw SalticidaeError("option name already exists"); auto it = conf.insert( std::make_pair(optname, - Opt(optname, &optval, action, getopt_order.size()))).first; + Opt(optname, optdoc, + optval, action, getopt_order.size()))).first; getopt_order.push_back(&it->second); } @@ -219,7 +222,7 @@ size_t Config::parse(int argc, char **argv) { update(*getopt_order[id], optarg); if (id == conf_idx) { - auto &fname = opt_val_conf.get(); + auto &fname = opt_val_conf->get(); if (load(fname)) SALTICIDAE_LOG_INFO("loading extra configuration from %s", fname.c_str()); else @@ -229,6 +232,15 @@ size_t Config::parse(int argc, char **argv) { return optind; } +void Config::print_help(FILE *output) { + for (auto opt: getopt_order) + { + fprintf(output, "--%s\t\t%s\n", + opt->optname.c_str(), + opt->optdoc.c_str()); + } +} + std::vector<std::string> split(const std::string &s, const std::string &delim) { std::vector<std::string> res; size_t lastpos = 0; |