| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/keyed_service/core/dependency_graph.h" | 5 #include "components/keyed_service/core/dependency_graph.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 | 10 |
| 11 #include "base/strings/string_piece.h" |
| 12 |
| 13 namespace { |
| 14 |
| 15 // Escapes |id| to be a valid ID in the DOT format [1]. This is implemented as |
| 16 // enclosing the string in quotation marks, and escaping any quotation marks |
| 17 // found with backslashes. |
| 18 // [1] http://www.graphviz.org/content/dot-language |
| 19 std::string Escape(base::StringPiece id) { |
| 20 std::string result = "\""; |
| 21 result.reserve(id.size() + 2); // +2 for the enclosing quotes. |
| 22 size_t after_last_quot = 0; |
| 23 size_t next_quot = id.find('"'); |
| 24 while (next_quot != base::StringPiece::npos) { |
| 25 result.append(id.data() + after_last_quot, next_quot - after_last_quot); |
| 26 result.append("\""); |
| 27 after_last_quot = next_quot + 1; |
| 28 next_quot = id.find('"', after_last_quot); |
| 29 } |
| 30 result.append(id.data() + after_last_quot, id.size() - after_last_quot); |
| 31 result.append("\""); |
| 32 return result; |
| 33 } |
| 34 |
| 35 } // namespace |
| 36 |
| 11 DependencyGraph::DependencyGraph() {} | 37 DependencyGraph::DependencyGraph() {} |
| 12 | 38 |
| 13 DependencyGraph::~DependencyGraph() {} | 39 DependencyGraph::~DependencyGraph() {} |
| 14 | 40 |
| 15 void DependencyGraph::AddNode(DependencyNode* node) { | 41 void DependencyGraph::AddNode(DependencyNode* node) { |
| 16 all_nodes_.push_back(node); | 42 all_nodes_.push_back(node); |
| 17 construction_order_.clear(); | 43 construction_order_.clear(); |
| 18 } | 44 } |
| 19 | 45 |
| 20 void DependencyGraph::RemoveNode(DependencyNode* node) { | 46 void DependencyGraph::RemoveNode(DependencyNode* node) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 | 135 |
| 110 construction_order_ = output; | 136 construction_order_ = output; |
| 111 return true; | 137 return true; |
| 112 } | 138 } |
| 113 | 139 |
| 114 std::string DependencyGraph::DumpAsGraphviz( | 140 std::string DependencyGraph::DumpAsGraphviz( |
| 115 const std::string& toplevel_name, | 141 const std::string& toplevel_name, |
| 116 const base::Callback<std::string(DependencyNode*)>& node_name_callback) | 142 const base::Callback<std::string(DependencyNode*)>& node_name_callback) |
| 117 const { | 143 const { |
| 118 std::string result("digraph {\n"); | 144 std::string result("digraph {\n"); |
| 145 std::string escaped_toplevel_name = Escape(toplevel_name); |
| 119 | 146 |
| 120 // Make a copy of all nodes. | 147 // Make a copy of all nodes. |
| 121 std::deque<DependencyNode*> nodes; | 148 std::deque<DependencyNode*> nodes; |
| 122 std::copy(all_nodes_.begin(), all_nodes_.end(), std::back_inserter(nodes)); | 149 std::copy(all_nodes_.begin(), all_nodes_.end(), std::back_inserter(nodes)); |
| 123 | 150 |
| 124 // State all dependencies and remove |second| so we don't generate an | 151 // State all dependencies and remove |second| so we don't generate an |
| 125 // implicit dependency on the top level node. | 152 // implicit dependency on the top level node. |
| 126 std::deque<DependencyNode*>::iterator nodes_end(nodes.end()); | 153 std::deque<DependencyNode*>::iterator nodes_end(nodes.end()); |
| 127 result.append(" /* Dependencies */\n"); | 154 result.append(" /* Dependencies */\n"); |
| 128 for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) { | 155 for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) { |
| 129 result.append(" "); | 156 result.append(" "); |
| 130 result.append(node_name_callback.Run(it->second)); | 157 result.append(Escape(node_name_callback.Run(it->second))); |
| 131 result.append(" -> "); | 158 result.append(" -> "); |
| 132 result.append(node_name_callback.Run(it->first)); | 159 result.append(Escape(node_name_callback.Run(it->first))); |
| 133 result.append(";\n"); | 160 result.append(";\n"); |
| 134 | 161 |
| 135 nodes_end = std::remove(nodes.begin(), nodes_end, it->second); | 162 nodes_end = std::remove(nodes.begin(), nodes_end, it->second); |
| 136 } | 163 } |
| 137 nodes.erase(nodes_end, nodes.end()); | 164 nodes.erase(nodes_end, nodes.end()); |
| 138 | 165 |
| 139 // Every node that doesn't depend on anything else will implicitly depend on | 166 // Every node that doesn't depend on anything else will implicitly depend on |
| 140 // the top level node. | 167 // the top level node. |
| 141 result.append("\n /* Toplevel attachments */\n"); | 168 result.append("\n /* Toplevel attachments */\n"); |
| 142 for (std::deque<DependencyNode*>::const_iterator it = nodes.begin(); | 169 for (std::deque<DependencyNode*>::const_iterator it = nodes.begin(); |
| 143 it != nodes.end(); | 170 it != nodes.end(); |
| 144 ++it) { | 171 ++it) { |
| 145 result.append(" "); | 172 result.append(" "); |
| 146 result.append(node_name_callback.Run(*it)); | 173 result.append(Escape(node_name_callback.Run(*it))); |
| 147 result.append(" -> "); | 174 result.append(" -> "); |
| 148 result.append(toplevel_name); | 175 result.append(escaped_toplevel_name); |
| 149 result.append(";\n"); | 176 result.append(";\n"); |
| 150 } | 177 } |
| 151 | 178 |
| 152 result.append("\n /* Toplevel node */\n"); | 179 result.append("\n /* Toplevel node */\n"); |
| 153 result.append(" "); | 180 result.append(" "); |
| 154 result.append(toplevel_name); | 181 result.append(escaped_toplevel_name); |
| 155 result.append(" [shape=box];\n"); | 182 result.append(" [shape=box];\n"); |
| 156 | 183 |
| 157 result.append("}\n"); | 184 result.append("}\n"); |
| 158 return result; | 185 return result; |
| 159 } | 186 } |
| OLD | NEW |