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_);
  }
}
Example #2
0
 void value(T&& x) {
   value_impl(config_value{std::forward<T>(x)});
 }
Example #3
0
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();
}
Example #4
0
bool config_data::has_value(const std::string &name) const
{
    return value_impl(name);
}