From ee4637e3a22a1efc480bb66ea025afd107d1b158 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Fri, 22 May 2020 01:52:03 +0100 Subject: [PATCH] refactor(3p/nix/libexpr): Use absl::btree_map::merge for '//' Instead of doing some sort of inline merge-sort of the two attribute sets, use the attribute sets merge function. This commit alone does not build and is not supposed to. --- third_party/nix/src/libexpr/attr-set.cc | 8 ++++++++ third_party/nix/src/libexpr/attr-set.hh | 3 +++ third_party/nix/src/libexpr/eval.cc | 25 +++---------------------- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/third_party/nix/src/libexpr/attr-set.cc b/third_party/nix/src/libexpr/attr-set.cc index 8b2af8639..e0fac9234 100644 --- a/third_party/nix/src/libexpr/attr-set.cc +++ b/third_party/nix/src/libexpr/attr-set.cc @@ -37,6 +37,14 @@ Bindings::iterator Bindings::find(const Symbol& name) { Bindings::iterator Bindings::begin() { return &(attributes_.begin()->second); } Bindings::iterator Bindings::end() { return &(attributes_.end()->second); } +void Bindings::merge(Bindings* other) { + // We want the values from the other attribute set to take + // precedence, but .merge() works the other way around. + // + // To work around that, we merge and then swap. + other->attributes_.merge(attributes_); + attributes_.swap(other->attributes_); +} // /* Allocate a new array of attributes for an attribute set with a specific // capacity. The space is implicitly reserved after the Bindings structure. diff --git a/third_party/nix/src/libexpr/attr-set.hh b/third_party/nix/src/libexpr/attr-set.hh index 551cddaae..39af7c482 100644 --- a/third_party/nix/src/libexpr/attr-set.hh +++ b/third_party/nix/src/libexpr/attr-set.hh @@ -50,6 +50,9 @@ class Bindings { iterator begin(); iterator end(); + // Merge values from other into the current attribute + void merge(Bindings* other); + // ??? [[deprecated]] void sort(); diff --git a/third_party/nix/src/libexpr/eval.cc b/third_party/nix/src/libexpr/eval.cc index 760bada7b..dcaaadbd0 100644 --- a/third_party/nix/src/libexpr/eval.cc +++ b/third_party/nix/src/libexpr/eval.cc @@ -1301,31 +1301,12 @@ void ExprOpUpdate::eval(EvalState& state, Env& env, Value& v) { return; } - state.mkAttrs(v, v1.attrs->size() + v2.attrs->size()); + state.mkAttrs(v, /* capacity = */ 0); /* Merge the sets, preferring values from the second set. Make sure to keep the resulting vector in sorted order. */ - Bindings::iterator i = v1.attrs->begin(); - Bindings::iterator j = v2.attrs->begin(); - - while (i != v1.attrs->end() && j != v2.attrs->end()) { - if (i->name == j->name) { - v.attrs->push_back(*j); - ++i; - ++j; - } else if (i->name < j->name) { - v.attrs->push_back(*i++); - } else { - v.attrs->push_back(*j++); - } - } - - while (i != v1.attrs->end()) { - v.attrs->push_back(*i++); - } - while (j != v2.attrs->end()) { - v.attrs->push_back(*j++); - } + v.attrs->merge(v1.attrs); + v.attrs->merge(v2.attrs); state.nrOpUpdateValuesCopied += v.attrs->size(); }