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

Add type name access to config_value

parent ca3be93f
......@@ -47,23 +47,24 @@ public:
// -- 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>;
......@@ -104,6 +105,18 @@ public:
/// calling `convert_to_list` if needed.
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.
inline variant_type& get_data() {
return data_;
......@@ -115,21 +128,29 @@ public:
}
private:
// -- properties -------------------------------------------------------------
static const char* type_name_at_index(size_t index) noexcept;
// -- auto conversion of related types ---------------------------------------
inline void set(bool x) {
data_ = x;
}
inline void set(float x) {
data_ = static_cast<double>(x);
}
inline void set(const char* x) {
data_ = std::string{x};
}
template <class T>
detail::enable_if_t<
detail::is_one_of<detail::decay_t<T>, T2, T3, T4, T5, T6, T7>::value>
set(T&& x) {
data_ = std::forward<T>(x);
detail::is_one_of<T, real, atom, timespan, string, list, dictionary>::value>
set(T x) {
data_ = std::move(x);
}
template <class T>
......@@ -137,15 +158,6 @@ private:
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 -------------------------------------------------------
variant_type data_;
......
......@@ -23,12 +23,27 @@
namespace caf {
namespace {
const char* type_names[] {
"integer",
"boolean",
"real",
"atom",
"timespan",
"string",
"list",
"dictionary",
};
} // namespace <anonymous>
config_value::~config_value() {
// nop
}
void config_value::convert_to_list() {
if (holds_alternative<T6>(data_))
if (holds_alternative<list>(data_))
return;
using std::swap;
config_value tmp;
......@@ -38,7 +53,15 @@ void config_value::convert_to_list() {
void config_value::append(config_value x) {
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) {
......
......@@ -33,28 +33,33 @@
using namespace std;
using namespace caf;
struct tostring_visitor : static_visitor<string> {
template <class T>
inline string operator()(const T& value) {
return to_string(value);
}
};
namespace {
using list = config_value::list;
using dictionary = config_value::dictionary;
} // namespace <anonymous>
CAF_TEST(default_constructed) {
config_value x;
CAF_CHECK_EQUAL(holds_alternative<int64_t>(x), true);
CAF_CHECK_EQUAL(get<int64_t>(x), 0);
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<int64_t>());
}
CAF_TEST(list) {
auto x = make_config_value_list(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) {
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");
x.convert_to_list();
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<list>());
CAF_CHECK_EQUAL(to_string(x), "[42]");
x.convert_to_list();
CAF_CHECK_EQUAL(to_string(x), "[42]");
......@@ -70,12 +75,13 @@ CAF_TEST(append) {
}
CAF_TEST(maps) {
std::map<std::string, config_value> xs;
dictionary xs;
xs["num"] = int64_t{42};
xs["atm"] = atom("hello");
xs["str"] = string{"foobar"};
xs["dur"] = timespan{100};
config_value x{xs};
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<dictionary>());
CAF_CHECK_EQUAL(
to_string(x),
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