void ini_consumer::value_impl(config_value&& x) { using dict_type = config_value::dictionary; auto dict = get_if<dict_type>(&x); if (dict == nullptr) { warnings_.emplace_back(make_error(pec::type_mismatch, "expected a dictionary at top level")); return; } if (current_key_ != "global") { auto& dst = cfg_.emplace(current_key_, dict_type{}).first->second; if (dict != nullptr && !dict->empty() && holds_alternative<dict_type>(dst)) { auto& dst_dict = get<dict_type>(dst); // We need to "merge" values into the destination, because it can already // contain any number of unrelated entries. for (auto& entry : *dict) dst_dict.insert_or_assign(entry.first, std::move(entry.second)); } } else { std::string prev_key; swap(current_key_, prev_key); for (auto& entry : *dict) { if (holds_alternative<dict_type>(entry.second)) { // Recurse into top-level maps. current_key_ = std::move(entry.first); value_impl(std::move(entry.second)); } else { cfg_.insert_or_assign(entry.first, std::move(entry.second)); } } swap(prev_key, current_key_); } }
void value(T&& x) { value_impl(config_value{std::forward<T>(x)}); }
std::string config_data::string_value(const std::string &name) const { auto value = value_impl(name); return value ? boost::apply_visitor(stringify_visitor(), *value) : std::string(); }
bool config_data::has_value(const std::string &name) const { return value_impl(name); }