Commit f6ae028a authored by Dominik Charousset's avatar Dominik Charousset

Simplify config_option interface

parent 3f59e8d4
...@@ -36,11 +36,10 @@ public: ...@@ -36,11 +36,10 @@ public:
/// Custom vtable-like struct for delegating to type-specific functions and /// Custom vtable-like struct for delegating to type-specific functions and
/// storing type-specific information shared by several config options. /// storing type-specific information shared by several config options.
struct meta_state { struct meta_state {
/// Checks whether a value matches the option's type. /// Performs a type check on the config value and then stores the converted
error (*check)(const config_value&); /// value in the given storage location unless the storage pointer was set
/// to `nullptr`.
/// Stores a value in the given location. error (*store)(void*, const config_value&);
void (*store)(void*, const config_value&);
/// Tries to extract a value from the given location. Exists for backward /// Tries to extract a value from the given location. Exists for backward
/// compatibility only and will get removed with CAF 0.17. /// compatibility only and will get removed with CAF 0.17.
...@@ -89,12 +88,9 @@ public: ...@@ -89,12 +88,9 @@ public:
/// Returns the full name for this config option as "<category>.<long name>". /// Returns the full name for this config option as "<category>.<long name>".
string_view full_name() const noexcept; string_view full_name() const noexcept;
/// Checks whether `x` holds a legal value for this option. /// Performs a type check for `x` and then stores `x` in this option unless it
error check(const config_value& x) const; /// is stateless.
error store(const config_value& x) const;
/// Stores `x` in this option unless it is stateless.
/// @pre `check(x) == none`.
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.
string_view type_name() const noexcept; string_view type_name() const noexcept;
......
...@@ -30,20 +30,17 @@ ...@@ -30,20 +30,17 @@
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
namespace caf { namespace caf::detail {
namespace detail {
template <class T> template <class T>
error check_impl(const config_value& x) { error store_impl(void* ptr, const config_value& x) {
if (holds_alternative<T>(x)) if (holds_alternative<T>(x)) {
if (ptr)
*static_cast<T*>(ptr) = get<T>(x);
return none; return none;
} else {
return make_error(pec::type_mismatch); return make_error(pec::type_mismatch);
} }
template <class T>
void store_impl(void* ptr, const config_value& x) {
*static_cast<T*>(ptr) = get<T>(x);
} }
template <class T> template <class T>
...@@ -68,8 +65,8 @@ expected<config_value> parse_impl(T* ptr, string_view str) { ...@@ -68,8 +65,8 @@ expected<config_value> parse_impl(T* ptr, string_view str) {
return config_value{trait::convert(*ptr)}; return config_value{trait::convert(*ptr)};
} }
CAF_CORE_EXPORT expected<config_value> CAF_CORE_EXPORT expected<config_value> parse_impl(std::string* ptr,
parse_impl(std::string* ptr, string_view str); string_view str);
template <class T> template <class T>
expected<config_value> parse_impl_delegate(void* ptr, string_view str) { expected<config_value> parse_impl_delegate(void* ptr, string_view str) {
...@@ -79,13 +76,15 @@ expected<config_value> parse_impl_delegate(void* ptr, string_view str) { ...@@ -79,13 +76,15 @@ expected<config_value> parse_impl_delegate(void* ptr, string_view str) {
template <class T> template <class T>
config_option::meta_state* option_meta_state_instance() { config_option::meta_state* option_meta_state_instance() {
using trait = detail::config_value_access_t<T>; using trait = detail::config_value_access_t<T>;
static config_option::meta_state obj{check_impl<T>, store_impl<T>, static config_option::meta_state obj{store_impl<T>, get_impl<T>,
get_impl<T>, parse_impl_delegate<T>, parse_impl_delegate<T>,
trait::type_name()}; trait::type_name()};
return &obj; return &obj;
} }
} // namespace detail } // namespace caf::detail
namespace caf {
/// Creates a config option that synchronizes with `storage`. /// Creates a config option that synchronizes with `storage`.
template <class T> template <class T>
......
...@@ -340,11 +340,10 @@ actor_system_config& actor_system_config::set_impl(string_view name, ...@@ -340,11 +340,10 @@ actor_system_config& actor_system_config::set_impl(string_view name,
if (opt == nullptr) { if (opt == nullptr) {
std::cerr << "*** failed to set config parameter " << name std::cerr << "*** failed to set config parameter " << name
<< ": invalid name" << std::endl; << ": invalid name" << std::endl;
} else if (auto err = opt->check(value)) { } else if (auto err = opt->store(value)) {
std::cerr << "*** failed to set config parameter " << name << ": " std::cerr << "*** failed to set config parameter " << name << ": "
<< to_string(err) << std::endl; << to_string(err) << std::endl;
} else { } else {
opt->store(value);
auto category = opt->category(); auto category = opt->category();
if (category == "global") if (category == "global")
content[opt->long_name()] = std::move(value); content[opt->long_name()] = std::move(value);
......
...@@ -128,16 +128,9 @@ string_view config_option::full_name() const noexcept { ...@@ -128,16 +128,9 @@ string_view config_option::full_name() const noexcept {
return buf_slice(buf_[0] == '?' ? 1 : 0, long_name_separator_); return buf_slice(buf_[0] == '?' ? 1 : 0, long_name_separator_);
} }
error config_option::check(const config_value& x) const { error config_option::store(const config_value& x) const {
CAF_ASSERT(meta_->check != nullptr);
return meta_->check(x);
}
void config_option::store(const config_value& x) const {
if (value_ != nullptr) {
CAF_ASSERT(meta_->store != nullptr); CAF_ASSERT(meta_->store != nullptr);
meta_->store(value_, x); return meta_->store(value_, x);
}
} }
string_view config_option::type_name() const noexcept { string_view config_option::type_name() const noexcept {
......
...@@ -156,16 +156,11 @@ void merge_into_place(settings& src, settings& dst) { ...@@ -156,16 +156,11 @@ void merge_into_place(settings& src, settings& dst) {
} // namespace } // namespace
pec config_consumer::value_impl(config_value&& x) { pec config_consumer::value_impl(config_value&& x) {
// See whether there's a config_option associated to this key and perform a // Sync with config option object if available.
// type check if necessary. if (options_ != nullptr)
const config_option* opt; if (auto opt = options_->qualified_name_lookup(category_, current_key_))
if (options_ == nullptr) { if (auto err = opt->store(x))
opt = nullptr;
} else {
opt = options_->qualified_name_lookup(category_, current_key_);
if (opt && opt->check(x) != none)
return pec::type_mismatch; return pec::type_mismatch;
}
// Insert / replace value in the map. // Insert / replace value in the map.
if (auto dict = get_if<settings>(&x)) { if (auto dict = get_if<settings>(&x)) {
// Merge values into the destination, because it can already contain any // Merge values into the destination, because it can already contain any
...@@ -178,13 +173,6 @@ pec config_consumer::value_impl(config_value&& x) { ...@@ -178,13 +173,6 @@ pec config_consumer::value_impl(config_value&& x) {
} else { } else {
cfg_->insert_or_assign(current_key_, std::move(x)); cfg_->insert_or_assign(current_key_, std::move(x));
} }
// Sync with config option if needed.
if (opt) {
if (auto i = cfg_->find(current_key_); i != cfg_->end())
opt->store(i->second);
else
return pec::invalid_state;
}
return pec::success; return pec::success;
} }
......
...@@ -67,28 +67,33 @@ namespace { ...@@ -67,28 +67,33 @@ namespace {
using meta_state = config_option::meta_state; using meta_state = config_option::meta_state;
void bool_store_neg(void* ptr, const config_value& x) { error bool_store_neg(void* ptr, const config_value& x) {
if (holds_alternative<bool>(x)) {
if (ptr)
*static_cast<bool*>(ptr) = !get<bool>(x); *static_cast<bool*>(ptr) = !get<bool>(x);
return none;
} else {
return make_error(pec::type_mismatch);
}
} }
config_value bool_get_neg(const void* ptr) { config_value bool_get_neg(const void* ptr) {
return config_value{!*static_cast<const bool*>(ptr)}; return config_value{!*static_cast<const bool*>(ptr)};
} }
meta_state bool_neg_meta{detail::check_impl<bool>, bool_store_neg, bool_get_neg, meta_state bool_neg_meta{bool_store_neg, bool_get_neg, nullptr,
nullptr,
detail::config_value_access_t<bool>::type_name()}; detail::config_value_access_t<bool>::type_name()};
error check_timespan(const config_value& x) {
if (holds_alternative<timespan>(x))
return none;
return make_error(pec::type_mismatch);
}
template <uint64_t Denominator> template <uint64_t Denominator>
void store_timespan(void* ptr, const config_value& x) { error store_timespan(void* ptr, const config_value& x) {
if (holds_alternative<timespan>(x)) {
if (ptr)
*static_cast<size_t*>(ptr) = static_cast<size_t>(get<timespan>(x).count()) *static_cast<size_t*>(ptr) = static_cast<size_t>(get<timespan>(x).count())
/ Denominator; / Denominator;
return none;
} else {
return make_error(pec::type_mismatch);
}
} }
template <uint64_t Denominator> template <uint64_t Denominator>
config_value get_timespan(const void* ptr) { config_value get_timespan(const void* ptr) {
...@@ -97,12 +102,10 @@ config_value get_timespan(const void* ptr) { ...@@ -97,12 +102,10 @@ config_value get_timespan(const void* ptr) {
return config_value{val}; return config_value{val};
} }
meta_state us_res_meta{check_timespan, store_timespan<1000>, get_timespan<1000>, meta_state us_res_meta{store_timespan<1000>, get_timespan<1000>, nullptr,
nullptr,
detail::config_value_access_t<timespan>::type_name()}; detail::config_value_access_t<timespan>::type_name()};
meta_state ms_res_meta{check_timespan, store_timespan<1000000>, meta_state ms_res_meta{store_timespan<1000000>, get_timespan<1000000>, nullptr,
get_timespan<1000000>, nullptr,
detail::config_value_access_t<timespan>::type_name()}; detail::config_value_access_t<timespan>::type_name()};
} // namespace } // namespace
......
...@@ -51,8 +51,7 @@ optional<T> read(string_view arg) { ...@@ -51,8 +51,7 @@ optional<T> read(string_view arg) {
auto co = make_config_option<T>(category, name, explanation); auto co = make_config_option<T>(category, name, explanation);
auto res = co.parse(arg); auto res = co.parse(arg);
if (res && holds_alternative<T>(*res)) { if (res && holds_alternative<T>(*res)) {
if (co.check(*res) != none) if (auto err = co.store(*res); !err)
CAF_ERROR("co.parse() produced the wrong type!");
return get<T>(*res); return get<T>(*res);
} }
return none; return none;
......
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