blob: f3029c118c2229383d7c7af1f9418f15f68ad7da [file] [log] [blame]
Andrew de los Reyes81ebcd82010-03-09 15:56:18 -08001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Alex Deymo161c4a12014-05-16 15:56:21 -07004#include "update_engine/payload_generator/tarjan.h"
Andrew de los Reyes81ebcd82010-03-09 15:56:18 -08005
6#include <algorithm>
7#include <vector>
Alex Deymo161c4a12014-05-16 15:56:21 -07008
9#include <base/logging.h>
10
Andrew de los Reyes81ebcd82010-03-09 15:56:18 -080011#include "update_engine/utils.h"
12
13using std::min;
14using std::vector;
15
16namespace chromeos_update_engine {
17
18namespace {
19const vector<Vertex>::size_type kInvalidIndex = -1;
20}
21
22void TarjanAlgorithm::Execute(Vertex::Index vertex,
23 Graph* graph,
24 vector<Vertex::Index>* out) {
25 stack_.clear();
26 components_.clear();
27 index_ = 0;
28 for (Graph::iterator it = graph->begin(); it != graph->end(); ++it)
29 it->index = it->lowlink = kInvalidIndex;
30 required_vertex_ = vertex;
31
32 Tarjan(vertex, graph);
33 if (!components_.empty())
34 out->swap(components_[0]);
35}
36
37void TarjanAlgorithm::Tarjan(Vertex::Index vertex, Graph* graph) {
38 CHECK_EQ((*graph)[vertex].index, kInvalidIndex);
39 (*graph)[vertex].index = index_;
40 (*graph)[vertex].lowlink = index_;
41 index_++;
42 stack_.push_back(vertex);
43 for (Vertex::EdgeMap::iterator it = (*graph)[vertex].out_edges.begin();
44 it != (*graph)[vertex].out_edges.end(); ++it) {
45 Vertex::Index vertex_next = it->first;
46 if ((*graph)[vertex_next].index == kInvalidIndex) {
47 Tarjan(vertex_next, graph);
48 (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink,
49 (*graph)[vertex_next].lowlink);
50 } else if (utils::VectorContainsValue(stack_, vertex_next)) {
51 (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink,
52 (*graph)[vertex_next].index);
53 }
54 }
55 if ((*graph)[vertex].lowlink == (*graph)[vertex].index) {
56 vector<Vertex::Index> component;
57 Vertex::Index other_vertex;
58 do {
59 other_vertex = stack_.back();
60 stack_.pop_back();
61 component.push_back(other_vertex);
62 } while (other_vertex != vertex && !stack_.empty());
Alex Deymo161c4a12014-05-16 15:56:21 -070063
Andrew de los Reyes81ebcd82010-03-09 15:56:18 -080064 if (utils::VectorContainsValue(component, required_vertex_)) {
65 components_.resize(components_.size() + 1);
66 component.swap(components_.back());
67 }
68 }
69}
70
71} // namespace chromeos_update_engine