refactor(3p/nix/libexpr): Backport upstream VectorBindings merge sort

Since one of the two implementations essentially uses the same shape
as the upstream Bindings, we backport their merge sort implementation
to ensure that we're doing the same thing semantically.

Paired-With: Luke Granger-Brown <git@lukegb.com>
Paired-With: Vincent Ambo <mail@tazj.in>
Paired-With: Perry Lorier <isomer@tvl.fyi>
Change-Id: I0d865897991eec0c4dd84d9bd0415cd1ca437792
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1162
Tested-by: BuildkiteCI
Reviewed-by: lukegb <lukegb@tvl.fyi>
Reviewed-by: glittershark <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2020-07-14 00:33:20 +01:00 committed by tazjin
parent 6166c9daf2
commit c5de35ee62

View file

@ -158,39 +158,51 @@ void VectorBindings::merge(Bindings& other) {
AttributeVector new_attributes; AttributeVector new_attributes;
new_attributes.reserve(size() + other.size()); new_attributes.reserve(size() + other.size());
auto m_it = attributes_.begin(); auto lhs = attributes_.begin();
auto other_it = other.begin(); auto rhs = other.begin();
while (other_it != other.end() && m_it != attributes_.end()) { while (lhs != attributes_.end() && rhs != other.end()) {
if (other_it->first < m_it->first) { if (lhs->first == rhs->first) {
new_attributes.push_back(*(m_it++)); new_attributes.push_back(*rhs);
++lhs;
++rhs;
} else if (lhs->first < rhs->first) {
new_attributes.push_back(*lhs++);
} else { } else {
if (m_it->first == other_it->first) { new_attributes.push_back(*rhs++);
++m_it;
}
new_attributes.push_back(*(other_it++));
} }
} }
if (m_it != attributes_.end()) { while (lhs != attributes_.end()) {
std::copy(m_it, attributes_.end(), std::back_inserter(new_attributes)); new_attributes.push_back(*lhs++);
} }
if (other_it != other.end()) { while (rhs != other.end()) {
std::copy(other_it, other.end(), std::back_inserter(new_attributes)); new_attributes.push_back(*rhs++);
} }
new_attributes.shrink_to_fit(); new_attributes.shrink_to_fit();
attributes_ = new_attributes; attributes_ = new_attributes;
} }
// Insert or assign (i.e. replace) a value in the attribute set.
void VectorBindings::push_back(const Attr& attr) { void VectorBindings::push_back(const Attr& attr) {
for (auto it = attributes_.begin(); it != attributes_.end(); ++it) {
if (it->first == attr.name) {
it->second = attr;
return;
} else if (attr.name < it->first) {
attributes_.emplace(it, attr.name, attr);
return;
}
}
attributes_.emplace_back(attr.name, attr); attributes_.emplace_back(attr.name, attr);
} }
std::vector<const Attr*> VectorBindings::lexicographicOrder() { std::vector<const Attr*> VectorBindings::lexicographicOrder() {
std::vector<const Attr*> result(attributes_.size()); std::vector<const Attr*> result;
result.reserve(attributes_.size());
for (auto& [_, attr] : attributes_) { for (auto& [_, attr] : attributes_) {
result.push_back(&attr); result.push_back(&attr);
@ -240,5 +252,4 @@ Value* EvalState::allocAttr(Value& vAttrs, const Symbol& name) {
return v; return v;
} }
} // namespace nix } // namespace nix