Commit 176f6140 authored by Dominik Charousset's avatar Dominik Charousset

Add type name access to config_value

parent ca3be93f
...@@ -47,23 +47,24 @@ public: ...@@ -47,23 +47,24 @@ public:
// -- member types ----------------------------------------------------------- // -- member types -----------------------------------------------------------
using T0 = int64_t; using integer = int64_t;
using T1 = bool; using boolean = bool;
using T2 = double; using real = double;
using T3 = atom_value; using atom = atom_value;
using T4 = timespan; using timespan = caf::timespan;
using T5 = std::string; using string = std::string;
using T6 = std::vector<config_value>; using list = std::vector<config_value>;
using T7 = std::map<std::string, config_value>; using dictionary = std::map<std::string, config_value>;
using types = detail::type_list<T0, T1, T2, T3, T4, T5, T6, T7>; using types = detail::type_list<integer, boolean, real, atom, timespan,
string, list, dictionary>;
using variant_type = detail::tl_apply_t<types, variant>; using variant_type = detail::tl_apply_t<types, variant>;
...@@ -104,6 +105,18 @@ public: ...@@ -104,6 +105,18 @@ public:
/// calling `convert_to_list` if needed. /// calling `convert_to_list` if needed.
void append(config_value x); void append(config_value x);
/// Returns a human-readable type name of the current value.
const char* type_name() const noexcept;
/// Returns a human-readable type name for `T`.
template <class T>
static const char* type_name_of() noexcept {
using namespace detail;
static constexpr auto index = tl_index_of<types, T>::value;
static_assert(index != -1, "T is not a valid config value type");
return type_name_at_index(static_cast<size_t>(index));
}
/// Returns the underlying variant. /// Returns the underlying variant.
inline variant_type& get_data() { inline variant_type& get_data() {
return data_; return data_;
...@@ -115,21 +128,29 @@ public: ...@@ -115,21 +128,29 @@ public:
} }
private: private:
// -- properties -------------------------------------------------------------
static const char* type_name_at_index(size_t index) noexcept;
// -- auto conversion of related types --------------------------------------- // -- auto conversion of related types ---------------------------------------
inline void set(bool x) { inline void set(bool x) {
data_ = x; data_ = x;
} }
inline void set(float x) {
data_ = static_cast<double>(x);
}
inline void set(const char* x) { inline void set(const char* x) {
data_ = std::string{x}; data_ = std::string{x};
} }
template <class T> template <class T>
detail::enable_if_t< detail::enable_if_t<
detail::is_one_of<detail::decay_t<T>, T2, T3, T4, T5, T6, T7>::value> detail::is_one_of<T, real, atom, timespan, string, list, dictionary>::value>
set(T&& x) { set(T x) {
data_ = std::forward<T>(x); data_ = std::move(x);
} }
template <class T> template <class T>
...@@ -137,15 +158,6 @@ private: ...@@ -137,15 +158,6 @@ private:
data_ = static_cast<int64_t>(x); data_ = static_cast<int64_t>(x);
} }
inline void convert(timespan x) {
data_ = x;
}
template <class Rep, class Ratio>
void convert(std::chrono::duration<Rep, Ratio> x) {
data_ = std::chrono::duration_cast<timespan>(x);
}
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
variant_type data_; variant_type data_;
......
...@@ -23,12 +23,27 @@ ...@@ -23,12 +23,27 @@
namespace caf { namespace caf {
namespace {
const char* type_names[] {
"integer",
"boolean",
"real",
"atom",
"timespan",
"string",
"list",
"dictionary",
};
} // namespace <anonymous>
config_value::~config_value() { config_value::~config_value() {
// nop // nop
} }
void config_value::convert_to_list() { void config_value::convert_to_list() {
if (holds_alternative<T6>(data_)) if (holds_alternative<list>(data_))
return; return;
using std::swap; using std::swap;
config_value tmp; config_value tmp;
...@@ -38,7 +53,15 @@ void config_value::convert_to_list() { ...@@ -38,7 +53,15 @@ void config_value::convert_to_list() {
void config_value::append(config_value x) { void config_value::append(config_value x) {
convert_to_list(); convert_to_list();
get<T6>(data_).emplace_back(std::move(x)); get<list>(data_).emplace_back(std::move(x));
}
const char* config_value::type_name() const noexcept {
return type_name_at_index(data_.index());
}
const char* config_value::type_name_at_index(size_t index) noexcept {
return type_names[index];
} }
bool operator<(const config_value& x, const config_value& y) { bool operator<(const config_value& x, const config_value& y) {
......
...@@ -33,28 +33,33 @@ ...@@ -33,28 +33,33 @@
using namespace std; using namespace std;
using namespace caf; using namespace caf;
struct tostring_visitor : static_visitor<string> { namespace {
template <class T>
inline string operator()(const T& value) { using list = config_value::list;
return to_string(value);
} using dictionary = config_value::dictionary;
};
} // namespace <anonymous>
CAF_TEST(default_constructed) { CAF_TEST(default_constructed) {
config_value x; config_value x;
CAF_CHECK_EQUAL(holds_alternative<int64_t>(x), true); CAF_CHECK_EQUAL(holds_alternative<int64_t>(x), true);
CAF_CHECK_EQUAL(get<int64_t>(x), 0); CAF_CHECK_EQUAL(get<int64_t>(x), 0);
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<int64_t>());
} }
CAF_TEST(list) { CAF_TEST(list) {
auto x = make_config_value_list(1, 2, 3); auto x = make_config_value_list(1, 2, 3);
CAF_CHECK_EQUAL(to_string(x), "[1, 2, 3]"); CAF_CHECK_EQUAL(to_string(x), "[1, 2, 3]");
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<list>());
} }
CAF_TEST(convert_to_list) { CAF_TEST(convert_to_list) {
config_value x{int64_t{42}}; config_value x{int64_t{42}};
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<int64_t>());
CAF_CHECK_EQUAL(to_string(x), "42"); CAF_CHECK_EQUAL(to_string(x), "42");
x.convert_to_list(); x.convert_to_list();
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<list>());
CAF_CHECK_EQUAL(to_string(x), "[42]"); CAF_CHECK_EQUAL(to_string(x), "[42]");
x.convert_to_list(); x.convert_to_list();
CAF_CHECK_EQUAL(to_string(x), "[42]"); CAF_CHECK_EQUAL(to_string(x), "[42]");
...@@ -70,12 +75,13 @@ CAF_TEST(append) { ...@@ -70,12 +75,13 @@ CAF_TEST(append) {
} }
CAF_TEST(maps) { CAF_TEST(maps) {
std::map<std::string, config_value> xs; dictionary xs;
xs["num"] = int64_t{42}; xs["num"] = int64_t{42};
xs["atm"] = atom("hello"); xs["atm"] = atom("hello");
xs["str"] = string{"foobar"}; xs["str"] = string{"foobar"};
xs["dur"] = timespan{100}; xs["dur"] = timespan{100};
config_value x{xs}; config_value x{xs};
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<dictionary>());
CAF_CHECK_EQUAL( CAF_CHECK_EQUAL(
to_string(x), to_string(x),
R"([("atm", 'hello'), ("dur", 100ns), ("num", 42), ("str", "foobar")])"); R"([("atm", 'hello'), ("dur", 100ns), ("num", 42), ("str", "foobar")])");
......
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