Index: src/platform/update_engine/tarjan.cc |
diff --git a/src/platform/update_engine/tarjan.cc b/src/platform/update_engine/tarjan.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aaca7d02b705483fba691ee76528934d639e52a8 |
--- /dev/null |
+++ b/src/platform/update_engine/tarjan.cc |
@@ -0,0 +1,70 @@ |
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <algorithm> |
+#include <vector> |
+#include "chromeos/obsolete_logging.h" |
+#include "update_engine/tarjan.h" |
+#include "update_engine/utils.h" |
+ |
+using std::min; |
+using std::vector; |
+ |
+namespace chromeos_update_engine { |
+ |
+namespace { |
+const vector<Vertex>::size_type kInvalidIndex = -1; |
+} |
+ |
+void TarjanAlgorithm::Execute(Vertex::Index vertex, |
+ Graph* graph, |
+ vector<Vertex::Index>* out) { |
+ stack_.clear(); |
+ components_.clear(); |
+ index_ = 0; |
+ for (Graph::iterator it = graph->begin(); it != graph->end(); ++it) |
+ it->index = it->lowlink = kInvalidIndex; |
+ required_vertex_ = vertex; |
+ |
+ Tarjan(vertex, graph); |
+ if (!components_.empty()) |
+ out->swap(components_[0]); |
+} |
+ |
+void TarjanAlgorithm::Tarjan(Vertex::Index vertex, Graph* graph) { |
+ CHECK_EQ((*graph)[vertex].index, kInvalidIndex); |
+ (*graph)[vertex].index = index_; |
+ (*graph)[vertex].lowlink = index_; |
+ index_++; |
+ stack_.push_back(vertex); |
+ for (Vertex::EdgeMap::iterator it = (*graph)[vertex].out_edges.begin(); |
+ it != (*graph)[vertex].out_edges.end(); ++it) { |
+ Vertex::Index vertex_next = it->first; |
+ if ((*graph)[vertex_next].index == kInvalidIndex) { |
+ Tarjan(vertex_next, graph); |
+ (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, |
+ (*graph)[vertex_next].lowlink); |
+ } else if (utils::VectorContainsValue(stack_, vertex_next)) { |
+ (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, |
+ (*graph)[vertex_next].index); |
+ } |
+ } |
+ if ((*graph)[vertex].lowlink == (*graph)[vertex].index) { |
+ vector<Vertex::Index> component; |
+ Vertex::Index other_vertex; |
+ do { |
+ other_vertex = stack_.back(); |
+ stack_.pop_back(); |
+ component.push_back(other_vertex); |
+ } while (other_vertex != vertex && !stack_.empty()); |
+ |
+ if (utils::VectorContainsValue(component, required_vertex_)) { |
+ components_.resize(components_.size() + 1); |
+ component.swap(components_.back()); |
+ } |
+ } |
+} |
+ |
+} // namespace chromeos_update_engine |
+ |