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:
parent
6166c9daf2
commit
c5de35ee62
1 changed files with 27 additions and 16 deletions
43
third_party/nix/src/libexpr/attr-set.cc
vendored
43
third_party/nix/src/libexpr/attr-set.cc
vendored
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue