Skip to content

Commit

Permalink
Optimized nested_trait::get_element method (#332)
Browse files Browse the repository at this point in the history
  • Loading branch information
bkryza committed Nov 3, 2024
1 parent b466d0a commit e3c2638
Showing 1 changed file with 40 additions and 23 deletions.
63 changes: 40 additions & 23 deletions src/common/model/nested_trait.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ template <typename T, typename Path> class nested_trait {
}

added_elements_.emplace(p->id(), p->type_name());
elements_by_name_.emplace(p->name(), elements_.size());
elements_.emplace_back(std::move(p));

return true;
Expand Down Expand Up @@ -152,41 +153,27 @@ template <typename T, typename Path> class nested_trait {
// For some reason it is legal to have a C/C++ struct with the same
// name as some ObjC protocol/interface, so the name is not necessarily
// unique
auto it = elements_.cbegin();
while (true) {
it = std::find_if(it, elements_.cend(),
[&](const auto &p) { return name == p->name(); });

if (it == elements_.cend())
auto matches = elements_by_name_.equal_range(name);

auto it = matches.first;
while (true) {
if (it == matches.second)
break;

assert(it->get() != nullptr);
assert((*it).second < elements_.size());

// Return the element if it has the expected type
if (dynamic_cast<V *>(it->get()))
return optional_ref<V>{
std::ref<V>(dynamic_cast<V &>(*it->get()))};
if (dynamic_cast<V *>(elements_.at((*it).second).get()))
return optional_ref<V>{std::ref<V>(
dynamic_cast<V &>(*elements_.at((*it).second).get()))};

++it;
}

return optional_ref<V>{};
}

/**
* Returns true of this nested level contains an element with specified
* name.
*
* @param name Name of the element.
* @return True if element exists.
*/
bool has_element(const std::string &name) const
{
return std::find_if(elements_.cbegin(), elements_.cend(),
[&](const auto &p) { return name == p->name(); }) !=
elements_.end();
}

/**
* Return result of functor f applied to all_of elements.
* @tparam F Functor type
Expand Down Expand Up @@ -260,6 +247,23 @@ template <typename T, typename Path> class nested_trait {

void remove(const std::set<eid_t> &element_ids)
{
// Find all elements positions to remove
size_t idx{0};
for (const auto &e : elements_) {
if (element_ids.count(e->id())) {
auto range = elements_by_name_.equal_range(e->name());

for (auto it = range.first; it != range.second; ++it) {
if (it->second == idx) {
elements_by_name_.erase(it);
break;
}
}
}

idx++;
}

// First remove all matching elements on this level
elements_.erase(std::remove_if(elements_.begin(), elements_.end(),
[&element_ids](auto &&e) {
Expand All @@ -285,8 +289,21 @@ template <typename T, typename Path> class nested_trait {
}

private:
/**
* Returns true of this nested level contains an element with specified
* name.
*
* @param name Name of the element.
* @return True if element exists.
*/
bool has_element(const std::string &name) const
{
return elements_by_name_.count(name);
}

std::set<std::pair<eid_t, std::string>> added_elements_;
std::vector<std::unique_ptr<T>> elements_;
std::multimap<std::string, size_t> elements_by_name_;
};

} // namespace clanguml::common::model

0 comments on commit e3c2638

Please sign in to comment.