Commit 896f0105 authored by Dominik Charousset's avatar Dominik Charousset

Reduce state in config_option

parent 7478c1eb
......@@ -29,18 +29,20 @@ class config_option {
public:
// -- member types -----------------------------------------------------------
/// Custom vtable-like struct for delegating to type-specific functions.
struct vtbl_type {
/// Custom vtable-like struct for delegating to type-specific functions and
/// storing type-specific information shared by several config options.
struct meta_state {
error (*check)(const config_value&);
void (*store)(void*, const config_value&);
std::string (*type_name)();
std::string type_name;
bool is_flag;
};
// -- constructors, destructors, and assignment operators --------------------
/// Constructs a config option.
config_option(std::string category, const char* name, std::string description,
bool is_flag, const vtbl_type& vtbl, void* storage = nullptr);
const meta_state* meta, void* storage = nullptr);
config_option(config_option&&) = default;
......@@ -65,10 +67,6 @@ public:
return description_;
}
inline bool is_flag() const noexcept {
return is_flag_;
}
/// Returns the full name for this config option as "<category>.<long name>".
std::string full_name() const;
......@@ -80,15 +78,17 @@ public:
void store(const config_value& x) const;
/// Returns a human-readable representation of this option's expected type.
std::string type_name() const;
const std::string& type_name() const noexcept;
/// Returns whether this config option stores a boolean flag.
bool is_flag() const noexcept;
private:
std::string category_;
std::string long_name_;
std::string short_names_;
std::string description_;
bool is_flag_;
vtbl_type vtbl_;
const meta_state* meta_;
mutable void* value_;
};
......
......@@ -29,25 +29,24 @@ namespace caf {
template <class T>
config_option make_config_option(const char* category, const char* name,
const char* description) {
config_option::vtbl_type vtbl{
static config_option::meta_state meta{
[](const config_value& x) -> error {
if (holds_alternative<T>(x))
return none;
return make_error(pec::type_mismatch);
},
nullptr,
[] {
return detail::type_name<T>();
}
detail::type_name<T>(),
false
};
return {category, name, description, false, vtbl};
return {category, name, description, &meta};
}
/// Creates a config option that synchronizes with `storage`.
template <class T>
config_option make_config_option(T& storage, const char* category,
const char* name, const char* description) {
config_option::vtbl_type vtbl{
static config_option::meta_state meta{
[](const config_value& x) -> error {
if (holds_alternative<T>(x))
return none;
......@@ -56,11 +55,10 @@ config_option make_config_option(T& storage, const char* category,
[](void* ptr, const config_value& x) {
*static_cast<T*>(ptr) = get<T>(x);
},
[] {
return detail::type_name<T>();
}
detail::type_name<T>(),
false
};
return {category, name, description, false, vtbl, &storage};
return {category, name, description, &meta, &storage};
}
// -- backward compatbility, do not use for new code ! -------------------------
......
......@@ -45,16 +45,15 @@ string get_short_names(const char* name) {
namespace caf {
config_option::config_option(string category, const char* name,
string description, bool is_flag,
const vtbl_type& vtbl, void* value)
string description, const meta_state* meta,
void* value)
: category_(move(category)),
long_name_(get_long_name(name)),
short_names_(get_short_names(name)),
description_(move(description)),
is_flag_(is_flag),
vtbl_(vtbl),
meta_(meta),
value_(value) {
// nop
CAF_ASSERT(meta_ != nullptr);
}
string config_option::full_name() const {
......@@ -65,20 +64,23 @@ string config_option::full_name() const {
}
error config_option::check(const config_value& x) const {
CAF_ASSERT(vtbl_.check != nullptr);
return vtbl_.check(x);
CAF_ASSERT(meta_->check != nullptr);
return meta_->check(x);
}
void config_option::store(const config_value& x) const {
if (value_ != nullptr) {
CAF_ASSERT(vtbl_.store != nullptr);
vtbl_.store(value_, x);
CAF_ASSERT(meta_->store != nullptr);
meta_->store(value_, x);
}
}
std::string config_option::type_name() const {
CAF_ASSERT(vtbl_.type_name != nullptr);
return vtbl_.type_name();
const std::string& config_option::type_name() const noexcept {
return meta_->type_name;
}
bool config_option::is_flag() const noexcept {
return meta_->is_flag;
}
} // namespace caf
......@@ -22,7 +22,7 @@ namespace caf {
namespace {
using vtbl_type = config_option::vtbl_type;
using meta_state = config_option::meta_state;
error bool_check(const config_value& x) {
if (holds_alternative<bool>(x))
......@@ -38,33 +38,30 @@ void bool_store_neg(void* ptr, const config_value& x) {
*static_cast<bool*>(ptr) = !get<bool>(x);
}
std::string bool_name() {
return detail::type_name<bool>();
}
constexpr vtbl_type bool_vtbl{bool_check, bool_store, bool_name};
meta_state bool_meta{bool_check, bool_store, detail::type_name<bool>(), true};
constexpr vtbl_type bool_neg_vtbl{bool_check, bool_store_neg, bool_name};
meta_state bool_neg_meta{bool_check, bool_store_neg, detail::type_name<bool>(),
true};
} // namespace anonymous
config_option make_negated_config_option(bool& storage, const char* category,
const char* name,
const char* description) {
return {category, name, description, true, bool_neg_vtbl, &storage};
return {category, name, description, &bool_neg_meta, &storage};
}
template <>
config_option make_config_option<bool>(const char* category, const char* name,
const char* description) {
return {category, name, description, true, bool_vtbl};
return {category, name, description, &bool_meta};
}
template <>
config_option make_config_option<bool>(bool& storage, const char* category,
const char* name,
const char* description) {
return {category, name, description, true, bool_vtbl, &storage};
return {category, name, description, &bool_meta, &storage};
}
} // namespace caf
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