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

Reduce state in config_option

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