Commit 9c415944 authored by Dominik Charousset's avatar Dominik Charousset

Port option_value to new config_value interface

parent ed6dc95f
...@@ -26,12 +26,14 @@ ...@@ -26,12 +26,14 @@
#include <functional> #include <functional>
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/error.hpp"
#include "caf/message.hpp"
#include "caf/variant.hpp"
#include "caf/config_value.hpp" #include "caf/config_value.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/error.hpp"
#include "caf/message.hpp"
#include "caf/static_visitor.hpp" #include "caf/static_visitor.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
...@@ -42,13 +44,13 @@ extern const char* type_name_visitor_tbl[]; ...@@ -42,13 +44,13 @@ extern const char* type_name_visitor_tbl[];
/// Helper class to generate config readers for different input types. /// Helper class to generate config readers for different input types.
class config_option { class config_option {
public: public:
using config_reader_sink = std::function<void (size_t, config_value&, using config_reader_sink = std::function<bool (size_t, config_value&,
optional<std::ostream&>)>; optional<std::ostream&>)>;
using legal_types = detail::type_list<bool, float, double, std::string, using legal_types = detail::type_list<bool, float, double, std::string,
atom_value, int8_t, uint8_t, int16_t, atom_value, int8_t, uint8_t, int16_t,
uint16_t, int32_t, uint32_t, int64_t, uint16_t, int32_t, uint32_t, int64_t,
uint64_t, duration>; uint64_t, timespan>;
config_option(const char* cat, const char* nm, const char* expl); config_option(const char* cat, const char* nm, const char* expl);
...@@ -95,12 +97,14 @@ public: ...@@ -95,12 +97,14 @@ public:
return type_name_visitor_tbl[static_cast<size_t>(index)]; return type_name_visitor_tbl[static_cast<size_t>(index)];
} }
const char* operator()(const std::vector<config_value>&) { template <class U>
const char* operator()(const std::vector<U>&) {
return "a list"; return "a list";
} }
const char* operator()(const std::map<std::string, config_value>&) { template <class K, class V>
return "a map"; const char* operator()(const std::map<K, V>&) {
return "a dictionary";
} }
const char* operator()(const timespan&) { const char* operator()(const timespan&) {
...@@ -123,48 +127,6 @@ public: ...@@ -123,48 +127,6 @@ public:
}; };
protected: protected:
template <class T, class U>
static bool assign_config_value(T& x, U& y) {
x = std::move(y);
return true;
}
// Catches any integer type that is smaller than int64_t.
template <class T>
static typename std::enable_if<sizeof(T) < sizeof(int64_t), bool>::type
assign_config_value(T& x, int64_t& y) {
if (y < static_cast<int64_t>(std::numeric_limits<T>::lowest())
|| y > static_cast<int64_t>(std::numeric_limits<T>::max()))
return false;
x = static_cast<T>(y);
return true;
}
// Catches size_t and uint64_t (yes, they differ on some compilers).
template <class T>
static typename std::enable_if<std::is_unsigned<T>::value
&& sizeof(T) == sizeof(int64_t), bool>::type
assign_config_value(T& x, int64_t& y) {
if (y < 0)
return false;
x = static_cast<uint64_t>(y);
return true;
}
static bool assign_config_value(float& x, double& y) {
if (y < static_cast<double>(std::numeric_limits<float>::lowest())
|| y > static_cast<double>(std::numeric_limits<float>::max()))
return false;
x = static_cast<float>(y);
return true;
}
template <class T>
static bool assign_config_value(std::vector<T>&,
std::vector<config_value>&) {
// TODO: implement me
}
void report_type_error(size_t ln, config_value& x, const char* expected, void report_type_error(size_t ln, config_value& x, const char* expected,
optional<std::ostream&> out); optional<std::ostream&> out);
...@@ -175,67 +137,9 @@ private: ...@@ -175,67 +137,9 @@ private:
char short_name_; char short_name_;
}; };
template <class T,
bool IsInsertable = detail::can_insert_elements<T>()
&& !std::is_same<T, std::string>::value>
class config_option_impl : public config_option {
public:
config_option_impl(T& ref, const char* ctg, const char* nm, const char* xp)
: config_option(ctg, nm, xp),
ref_(ref) {
// nop
}
std::string to_string() const override {
return deep_to_string(ref_);
}
message::cli_arg to_cli_arg(bool use_caf_prefix) override {
std::string argname;
if (use_caf_prefix)
argname = "caf#";
if (strcmp(category(), "global") != 0) {
argname += category();
argname += ".";
}
argname += name();
if (short_name() != '\0') {
argname += ',';
argname += short_name();
}
return {std::move(argname), explanation(), ref_};
}
config_reader_sink to_sink() override {
return [=](size_t ln, config_value& x, optional<std::ostream&> errors) {
// the INI parser accepts all integers as int64_t
// and all floating point numbers as doubles
using cfg_type =
typename std::conditional<
std::is_integral<T>::value && !std::is_same<bool, T>::value,
int64_t,
typename std::conditional<
std::is_floating_point<T>::value,
double,
T
>::type
>::type;
if (get_if<cfg_type>(&x) && assign_config_value(ref_, get<cfg_type>(x)))
return;
type_name_visitor tnv;
report_type_error(ln, x, tnv(ref_), errors);
};
}
private:
T& ref_;
};
template <class T> template <class T>
class config_option_impl<T, true> : public config_option { class config_option_impl : public config_option {
public: public:
using value_type = typename T::value_type;
config_option_impl(T& ref, const char* ctg, const char* nm, const char* xp) config_option_impl(T& ref, const char* ctg, const char* nm, const char* xp)
: config_option(ctg, nm, xp), : config_option(ctg, nm, xp),
ref_(ref) { ref_(ref) {
...@@ -264,26 +168,14 @@ public: ...@@ -264,26 +168,14 @@ public:
config_reader_sink to_sink() override { config_reader_sink to_sink() override {
return [=](size_t ln, config_value& x, optional<std::ostream&> errors) { return [=](size_t ln, config_value& x, optional<std::ostream&> errors) {
// the INI parser accepts all integers as int64_t auto res = get_if<T>(&x);
// and all floating point numbers as doubles if (res) {
using cfg_type = ref_ = *res;
typename std::conditional< return true;
std::is_integral<value_type>::value &&
!std::is_same<bool, value_type>::value,
int64_t,
typename std::conditional<
std::is_floating_point<value_type>::value,
double,
value_type
>::type
>::type;
value_type tmp;
if (get_if<cfg_type>(&x) && assign_config_value(tmp, get<cfg_type>(x))) {
ref_.insert(ref_.end(), std::move(tmp));
return;
} }
type_name_visitor tnv; type_name_visitor tnv;
report_type_error(ln, x, tnv(tmp), errors); report_type_error(ln, x, tnv(ref_), errors);
return false;
}; };
} }
......
...@@ -34,7 +34,7 @@ struct parse_ini_t { ...@@ -34,7 +34,7 @@ struct parse_ini_t {
/// Denotes an optional error output stream /// Denotes an optional error output stream
using opt_err = optional<std::ostream&>; using opt_err = optional<std::ostream&>;
/// Denotes a callback for consuming configuration values. /// Denotes a callback for consuming configuration values.
using config_consumer = std::function<void (size_t, std::string, using config_consumer = std::function<bool (size_t, std::string,
config_value&, opt_err)>; config_value&, opt_err)>;
/// Parse the given input stream as INI formatted data and /// Parse the given input stream as INI formatted data and
......
...@@ -339,6 +339,9 @@ struct message::cli_arg { ...@@ -339,6 +339,9 @@ struct message::cli_arg {
/// Creates a CLI argument storing its matched argument in `dest`. /// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string nstr, std::string tstr, atom_value& arg); cli_arg(std::string nstr, std::string tstr, atom_value& arg);
/// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string nstr, std::string tstr, timespan& arg);
/// Creates a CLI argument storing its matched argument in `dest`. /// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string nstr, std::string tstr, std::string& arg); cli_arg(std::string nstr, std::string tstr, std::string& arg);
......
...@@ -56,23 +56,24 @@ public: ...@@ -56,23 +56,24 @@ public:
sinks_.emplace(x->full_name(), x->to_sink()); sinks_.emplace(x->full_name(), x->to_sink());
} }
void operator()(size_t ln, const std::string& name, config_value& cv, bool operator()(size_t ln, const std::string& name, config_value& cv,
optional<std::ostream&> out) { optional<std::ostream&> out) {
auto i = sinks_.find(name); auto i = sinks_.find(name);
if (i != sinks_.end()) { if (i != sinks_.end()) {
(i->second)(ln, cv, none); (i->second)(ln, cv, none);
return; return true;
} }
// check whether this is an individual actor config // check whether this is an individual actor config
if (name.compare(0, actor_conf_prefix_size, actor_conf_prefix) == 0) { if (name.compare(0, actor_conf_prefix_size, actor_conf_prefix) == 0) {
auto substr = name.substr(actor_conf_prefix_size); auto substr = name.substr(actor_conf_prefix_size);
named_actor_sink_(ln, substr, cv); named_actor_sink_(ln, substr, cv);
return; return true;
} }
if (out) if (out)
*out << "error in line " << ln *out << "error in line " << ln
<< R"(: unrecognized parameter name ")" << name << R"(")" << R"(: unrecognized parameter name ")" << name << R"(")"
<< std::endl; << std::endl;
return false;
} }
private: private:
......
...@@ -520,6 +520,22 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, atom_value& arg) ...@@ -520,6 +520,22 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, atom_value& arg)
// nop // nop
} }
message::cli_arg::cli_arg(std::string nstr, std::string tstr, timespan& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
fun([&arg](const std::string& str) -> bool {
int64_t count;
std::istringstream iss{str};
if (iss >> count) {
arg = timespan{count};
return true;
}
return false;
}),
flag(nullptr) {
// nop
}
message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::string& arg) message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::string& arg)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)), text(std::move(tstr)),
......
This diff is collapsed.
...@@ -129,6 +129,7 @@ struct fixture { ...@@ -129,6 +129,7 @@ struct fixture {
message_visitor mv; message_visitor mv;
anon_send(config_server, put_atom::value, anon_send(config_server, put_atom::value,
std::move(key), visit(mv, value)); std::move(key), visit(mv, value));
return true;
}; };
load_impl(consume, str); load_impl(consume, str);
} }
...@@ -137,6 +138,7 @@ struct fixture { ...@@ -137,6 +138,7 @@ struct fixture {
auto consume = [&](size_t, std::string key, config_value& value, auto consume = [&](size_t, std::string key, config_value& value,
optional<std::ostream&>) { optional<std::ostream&>) {
values.emplace(std::move(key), std::move(value)); values.emplace(std::move(key), std::move(value));
return true;
}; };
load_impl(consume, str); load_impl(consume, str);
} }
......
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