Unverified Commit 4466c76f authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #778

Add free function to set values in config_value dictionaries.
Close #769.
parents 5418edea f8931fc2
...@@ -530,6 +530,31 @@ T get_or(const actor_system_config& cfg, string_view name, ...@@ -530,6 +530,31 @@ T get_or(const actor_system_config& cfg, string_view name,
std::string get_or(const actor_system_config& cfg, string_view name, std::string get_or(const actor_system_config& cfg, string_view name,
const char* default_value); const char* default_value);
/// @private
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value);
/// @private
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value);
/// @private
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// @param dict Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template <class T>
void put(dictionary<config_value::dictionary>& dict, string_view key,
T&& value) {
config_value tmp{std::forward<T>(value)};
put_impl(dict, key, tmp);
}
/// @relates config_value /// @relates config_value
bool operator<(const config_value& x, const config_value& y); bool operator<(const config_value& x, const config_value& y);
......
...@@ -189,11 +189,11 @@ public: ...@@ -189,11 +189,11 @@ public:
iterator_bool_pair emplace(K&& key, T&& value) { iterator_bool_pair emplace(K&& key, T&& value) {
auto i = lower_bound(key); auto i = lower_bound(key);
if (i == end()) if (i == end())
return xs_.emplace(copy(std::forward<K>(key)), std::forward<T>(value)); return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)});
if (i->first == key) if (i->first == key)
return {i, false}; return {i, false};
return {xs_.emplace_hint(i, copy(std::forward<K>(key)), return {xs_.emplace_hint(i, copy(std::forward<K>(key)),
std::forward<T>(value)), V{std::forward<T>(value)}),
true}; true};
} }
...@@ -207,18 +207,18 @@ public: ...@@ -207,18 +207,18 @@ public:
template <class T> template <class T>
iterator_bool_pair insert(string_view key, T&& value) { iterator_bool_pair insert(string_view key, T&& value) {
return emplace(key, std::forward<T>(value)); return emplace(key, V{std::forward<T>(value)});
} }
template <class K, class T> template <class K, class T>
iterator emplace_hint(iterator hint, K&& key, T&& value) { iterator emplace_hint(iterator hint, K&& key, T&& value) {
if (hint == end() || hint->first > key) if (hint == end() || hint->first > key)
return xs_.emplace(copy(std::forward<K>(key)), std::forward<T>(value)) return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)})
.first; .first;
if (hint->first == key) if (hint->first == key)
return hint; return hint;
return xs_.emplace_hint(hint, copy(std::forward<K>(key)), return xs_.emplace_hint(hint, copy(std::forward<K>(key)),
std::forward<T>(value)); V{std::forward<T>(value)});
} }
template <class T> template <class T>
...@@ -230,12 +230,12 @@ public: ...@@ -230,12 +230,12 @@ public:
iterator_bool_pair insert_or_assign(string_view key, T&& value) { iterator_bool_pair insert_or_assign(string_view key, T&& value) {
auto i = lower_bound(key); auto i = lower_bound(key);
if (i == end()) if (i == end())
return xs_.emplace(copy(key), std::forward<T>(value)); return xs_.emplace(copy(key), V{std::forward<T>(value)});
if (i->first == key) { if (i->first == key) {
i->second = std::forward<T>(value); i->second = V{std::forward<T>(value)};
return {i, false}; return {i, false};
} }
return {xs_.emplace_hint(i, copy(key), std::forward<T>(value)), true}; return {xs_.emplace_hint(i, copy(key), V{std::forward<T>(value)}), true};
} }
template <class T> template <class T>
...@@ -247,7 +247,7 @@ public: ...@@ -247,7 +247,7 @@ public:
hint->second = std::forward<T>(value); hint->second = std::forward<T>(value);
return hint; return hint;
} }
return xs_.emplace_hint(hint, copy(key), std::forward<T>(value)); return xs_.emplace_hint(hint, copy(key), V{std::forward<T>(value)});
} }
// -- lookup ----------------------------------------------------------------- // -- lookup -----------------------------------------------------------------
......
...@@ -146,5 +146,49 @@ std::string get_or(const actor_system_config& cfg, string_view name, ...@@ -146,5 +146,49 @@ std::string get_or(const actor_system_config& cfg, string_view name,
return get_or(content(cfg), name, default_value); return get_or(content(cfg), name, default_value);
} }
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value) {
// Sanity check.
if (path.empty())
return;
// Navigate path.
auto last = path.end();
auto back = last - 1;
auto current = &dict;
// Resolve path by navigating the map-of-maps of create the necessary layout
// when needed.
for (auto i = path.begin(); i != back; ++i) {
auto iter = current->emplace(*i, config_value::dictionary{}).first;
if (auto val = get_if<config_value::dictionary>(&iter->second)) {
current = val;
} else {
iter->second = config_value::dictionary{};
current = &get<config_value::dictionary>(iter->second);
}
}
// Set key-value pair on the leaf.
current->insert_or_assign(*back, std::move(value));
}
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value) {
std::vector<string_view> path;
split(path, key, ".");
put_impl(dict, path, value);
}
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value) {
// Split the name into a path.
std::vector<string_view> path;
split(path, key, ".");
// Sanity check. At the very least, we need a category and a key.
if (path.size() < 2)
return;
auto category = path.front();
path.erase(path.begin());
put_impl(dict[category], path, value);
}
} // namespace caf } // namespace caf
...@@ -250,3 +250,17 @@ CAF_TEST(unsuccessful parsing) { ...@@ -250,3 +250,17 @@ CAF_TEST(unsuccessful parsing) {
CAF_CHECK_EQUAL(parse("{a=1,"), pec::unexpected_eof); CAF_CHECK_EQUAL(parse("{a=1,"), pec::unexpected_eof);
CAF_CHECK_EQUAL(parse("{a=1 b=2}"), pec::unexpected_character); CAF_CHECK_EQUAL(parse("{a=1 b=2}"), pec::unexpected_character);
} }
CAF_TEST(put values) {
using v = config_value;
using d = config_value::dictionary;
using dd = caf::dictionary<d>;
dd content;
put(content, "a.b", 42);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{42}}})}}));
put(content, "a.b.c", 1);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{d({{"c", v{1}}})}}})}}));
put(content, "a.b.d", 2);
CAF_CHECK_EQUAL(content,
dd({{"a", d({{"b", v{d({{"c", v{1}}, {"d", v{2}}})}}})}}));
}
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