diff --git a/src/api/sorting/group_sort.cpp b/src/api/sorting/group_sort.cpp index a9c2db7f..27d59af0 100644 --- a/src/api/sorting/group_sort.cpp +++ b/src/api/sorting/group_sort.cpp @@ -71,47 +71,6 @@ typedef boost::adjacency_list::vertex_descriptor vertex_t; typedef boost::graph_traits::edge_descriptor edge_t; -class CycleDetector : public boost::dfs_visitor<> { -public: - void tree_edge(edge_t edge, const GroupGraph& graph) { - auto source = boost::source(edge, graph); - - auto vertex = Vertex(graph[source].GetName(), graph[edge]); - - // Check if the plugin already exists in the recorded trail. - auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[source].GetName(); - }); - - if (it != end(trail)) { - // Erase everything from this position onwards, as it doesn't - // contribute to a forward-cycle. - trail.erase(it, end(trail)); - } - - trail.push_back(vertex); - } - - void back_edge(edge_t edge, const GroupGraph& graph) { - auto source = boost::source(edge, graph); - auto target = boost::target(edge, graph); - - auto vertex = Vertex(graph[source].GetName(), graph[edge]); - trail.push_back(vertex); - - auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[target].GetName(); - }); - - if (it != trail.end()) { - throw CyclicInteractionError(std::vector(it, trail.end())); - } - } - -private: - std::vector trail; -}; - class AfterGroupsVisitor : public boost::dfs_visitor<> { public: AfterGroupsVisitor(std::unordered_set& visitedGroups) : @@ -209,7 +168,7 @@ GetTransitiveAfterGroups(const std::unordered_set& masterlistGroups, if (logger) { logger->trace("Checking for cycles in the group graph"); } - boost::depth_first_search(graph, boost::visitor(CycleDetector())); + boost::depth_first_search(graph, boost::visitor(CycleDetector())); std::unordered_map> transitiveAfterGroups; diff --git a/src/api/sorting/group_sort.h b/src/api/sorting/group_sort.h index 32032f7c..7825da58 100644 --- a/src/api/sorting/group_sort.h +++ b/src/api/sorting/group_sort.h @@ -28,7 +28,12 @@ #include #include #include +#include +#include +#include + +#include "loot/exception/cyclic_interaction_error.h" #include "loot/metadata/group.h" namespace loot { @@ -36,5 +41,47 @@ namespace loot { std::unordered_map> GetTransitiveAfterGroups(const std::unordered_set& masterlistGroups, const std::unordered_set& userGroups); + +template +class CycleDetector : public boost::dfs_visitor<> { +public: + void tree_edge(typename boost::graph_traits::edge_descriptor edge, const G& graph) { + auto source = boost::source(edge, graph); + + auto vertex = Vertex(graph[source].GetName(), graph[edge]); + + // Check if the vertex already exists in the recorded trail. + auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { + return v.GetName() == graph[source].GetName(); + }); + + if (it != end(trail)) { + // Erase everything from this position onwards, as it doesn't + // contribute to a forward-cycle. + trail.erase(it, end(trail)); + } + + trail.push_back(vertex); + } + + void back_edge(typename boost::graph_traits::edge_descriptor edge, const G& graph) { + auto source = boost::source(edge, graph); + auto target = boost::target(edge, graph); + + auto vertex = Vertex(graph[source].GetName(), graph[edge]); + trail.push_back(vertex); + + auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { + return v.GetName() == graph[target].GetName(); + }); + + if (it != trail.end()) { + throw CyclicInteractionError(std::vector(it, trail.end())); + } + } + +private: + std::vector trail; +}; } #endif diff --git a/src/api/sorting/plugin_sorter.cpp b/src/api/sorting/plugin_sorter.cpp index 831c4fb2..17581238 100644 --- a/src/api/sorting/plugin_sorter.cpp +++ b/src/api/sorting/plugin_sorter.cpp @@ -49,47 +49,6 @@ typedef boost::graph_traits::vertex_iterator vertex_it; typedef boost::graph_traits::edge_descriptor edge_t; typedef boost::graph_traits::edge_iterator edge_it; -class CycleDetector : public boost::dfs_visitor<> { -public: - void tree_edge(edge_t edge, const PluginGraph& graph) { - const vertex_t source = boost::source(edge, graph); - - auto vertex = Vertex(graph[source].GetName(), graph[edge]); - - // Check if the plugin already exists in the recorded trail. - auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[source].GetName(); - }); - - if (it != end(trail)) { - // Erase everything from this position onwards, as it doesn't - // contribute to a forward-cycle. - trail.erase(it, end(trail)); - } - - trail.push_back(vertex); - } - - void back_edge(edge_t edge, const PluginGraph& graph) { - vertex_t source = boost::source(edge, graph); - vertex_t target = boost::target(edge, graph); - - auto vertex = Vertex(graph[source].GetName(), graph[edge]); - trail.push_back(vertex); - - auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[target].GetName(); - }); - - if (it != trail.end()) { - throw CyclicInteractionError(std::vector(it, trail.end())); - } - } - -private: - vector trail; -}; - std::vector PluginSorter::Sort(Game& game) { logger_ = getLogger(); @@ -297,7 +256,7 @@ bool PluginSorter::GetVertexByName(const std::string& name, void PluginSorter::CheckForCycles() const { boost::depth_first_search( - graph_, visitor(CycleDetector()).vertex_index_map(vertexIndexMap_)); + graph_, visitor(CycleDetector()).vertex_index_map(vertexIndexMap_)); } bool PluginSorter::EdgeCreatesCycle(const vertex_t& fromVertex,