| #include "rive/dependency_sorter.hpp" | |
| #include "rive/component.hpp" | |
| #include <algorithm> | |
| using namespace rive; | |
| void DependencySorter::sort(Component* root, std::vector<Component*>& order) | |
| { | |
| order.clear(); | |
| visit(root, order); | |
| // visit() appends in finish order; the caller wants its reverse. See the | |
| // note in visit() on why this is not an insert at begin(). | |
| std::reverse(order.begin(), order.end()); | |
| } | |
| void DependencySorter::sort(std::vector<Component*> roots, | |
| std::vector<Component*>& order) | |
| { | |
| order.clear(); | |
| for (auto root : roots) | |
| { | |
| visit(root, order); | |
| } | |
| std::reverse(order.begin(), order.end()); | |
| } | |
| bool DependencySorter::visit(Component* component, | |
| std::vector<Component*>& order) | |
| { | |
| if (m_Perm.find(component) != m_Perm.end()) | |
| { | |
| return true; | |
| } | |
| if (m_Temp.find(component) != m_Temp.end()) | |
| { | |
| fprintf(stderr, "Dependency cycle!\n"); | |
| return false; | |
| } | |
| m_Temp.emplace(component); | |
| // By reference: dependents() returns `const std::vector<U*>&`, and a plain | |
| // `auto` strips the reference, deep-copying the vector for every component | |
| // visited. | |
| const auto& dependents = component->dependents(); | |
| for (auto dependent : dependents) | |
| { | |
| if (!visit(dependent, order)) | |
| { | |
| return false; | |
| } | |
| } | |
| m_Perm.emplace(component); | |
| // Append and let sort() reverse once, rather than inserting at the front | |
| // per component: insert(begin()) shifts the whole vector every time, making | |
| // this O(n^2) in the component count. The Dart port already does it this | |
| // way -- see the same note in dependency_sorter.dart. | |
| order.push_back(component); | |
| return true; | |
| } |