diff --git a/src/option_manager.cc b/src/option_manager.cc index b3c56d31..dfcafc5c 100644 --- a/src/option_manager.cc +++ b/src/option_manager.cc @@ -87,20 +87,6 @@ void OptionManager::unset_option(StringView name) } } -OptionManager::OptionList OptionManager::flatten_options() const -{ - OptionList res = m_parent ? m_parent->flatten_options() : OptionList{}; - for (auto& option : m_options) - { - auto it = find_if(res, [&](const Option* opt) { return opt->name() == option.key; }); - if (it != res.end()) - *it = option.value.get(); - else - res.emplace_back(option.value.get()); - } - return res; -} - void OptionManager::on_option_changed(const Option& option) { // if parent option changed, but we overrided it, it's like nothing happened diff --git a/src/option_manager.hh b/src/option_manager.hh index 0e1ddaab..05b9641f 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -90,8 +90,18 @@ public: void unset_option(StringView name); - using OptionList = Vector; - OptionList flatten_options() const; + auto flatten_options() const + { + auto merge = [](auto&& first, const OptionMap& second) { + return concatenated(std::forward(first) + | filter([&second](auto& i) { return not second.contains(i.key); }), + second); + }; + static const OptionMap empty; + auto& parent = m_parent ? m_parent->m_options : empty; + auto& grand_parent = (m_parent and m_parent->m_parent) ? m_parent->m_parent->m_options : empty; + return merge(merge(grand_parent, parent), m_options) | transform(std::mem_fn(&OptionMap::Item::value)); + } void register_watcher(OptionManagerWatcher& watcher) const; void unregister_watcher(OptionManagerWatcher& watcher) const; @@ -103,8 +113,9 @@ private: // the only one allowed to construct a root option manager friend class Scope; friend class OptionsRegistry; + using OptionMap = HashMap, MemoryDomain::Options>; - HashMap, MemoryDomain::Options> m_options; + OptionMap m_options; OptionManager* m_parent; mutable Vector m_watchers;