Răsfoiți Sursa

dot: first draft

Michele Caini 3 ani în urmă
părinte
comite
d2a0f86908
5 a modificat fișierele cu 95 adăugiri și 0 ștergeri
  1. 1 0
      CMakeLists.txt
  2. 1 0
      src/entt/entt.hpp
  3. 47 0
      src/entt/graph/dot.hpp
  4. 1 0
      test/CMakeLists.txt
  5. 45 0
      test/entt/graph/dot.cpp

+ 1 - 0
CMakeLists.txt

@@ -148,6 +148,7 @@ if(ENTT_INCLUDE_HEADERS)
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/storage.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/view.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/adjacency_matrix.hpp>
+            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/dot.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/flow.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/fwd.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/locator/locator.hpp>

+ 1 - 0
src/entt/entt.hpp

@@ -33,6 +33,7 @@
 #include "entity/storage.hpp"
 #include "entity/view.hpp"
 #include "graph/adjacency_matrix.hpp"
+#include "graph/dot.hpp"
 #include "graph/flow.hpp"
 #include "locator/locator.hpp"
 #include "meta/adl_pointer.hpp"

+ 47 - 0
src/entt/graph/dot.hpp

@@ -0,0 +1,47 @@
+#ifndef ENTT_GRAPH_DOT_HPP
+#define ENTT_GRAPH_DOT_HPP
+
+#include <ostream>
+#include "adjacency_matrix.hpp"
+
+namespace entt {
+
+/**
+ * @brief Outputs a graph in dot format.
+ * @tparam Graph Graph type, valid as long as it exposes edges and vertices.
+ * @tparam Writer Vertex decorator type.
+ * @param out A standard output stream.
+ * @param graph The graph to output.
+ * @param writer Vertex decorator object.
+ */
+template<typename Graph, typename Writer>
+auto dot(std::ostream &out, const Graph &graph, Writer writer) -> decltype(*graph.vertices().begin(), void()) {
+    out << "digraph{";
+
+    for(auto &&vertex: graph.vertices()) {
+        out << vertex << "[";
+        writer(out, vertex);
+        out << "];";
+    }
+
+    for(auto [lhs, rhs]: graph.edges()) {
+        out << lhs << "->" << rhs << ";";
+    }
+
+    out << "}";
+}
+
+/**
+ * @brief Outputs a graph in dot format.
+ * @tparam Graph Graph type, valid as long as it exposes edges and vertices.
+ * @param out A standard output stream.
+ * @param graph The graph to output.
+ */
+template<typename Graph>
+auto dot(std::ostream &out, const Graph &graph) -> decltype(*graph.vertices().begin(), void()) {
+    return dot(out, graph, [](auto &&...) {});
+}
+
+} // namespace entt
+
+#endif

+ 1 - 0
test/CMakeLists.txt

@@ -220,6 +220,7 @@ SETUP_BASIC_TEST(view entt/entity/view.cpp)
 # Test graph
 
 SETUP_BASIC_TEST(adjacency_matrix entt/graph/adjacency_matrix.cpp)
+SETUP_BASIC_TEST(dot entt/graph/dot.cpp)
 SETUP_BASIC_TEST(flow entt/graph/flow.cpp)
 
 # Test locator

+ 45 - 0
test/entt/graph/dot.cpp

@@ -0,0 +1,45 @@
+#include <sstream>
+#include <string>
+#include <gtest/gtest.h>
+#include <entt/graph/adjacency_matrix.hpp>
+#include <entt/graph/dot.hpp>
+
+TEST(Dot, DefaultWriter) {
+    std::ostringstream output{};
+    entt::adjacency_matrix adjacency_matrix{3u};
+
+    adjacency_matrix.insert(0u, 1u);
+    adjacency_matrix.insert(1u, 2u);
+    adjacency_matrix.insert(0u, 2u);
+
+    entt::dot(output, adjacency_matrix);
+
+    const std::string expected = "digraph{0[];1[];2[];0->1;0->2;1->2;}";
+    const auto str = output.str();
+
+    ASSERT_FALSE(str.empty());
+    ASSERT_EQ(str, expected);
+}
+
+TEST(Dot, CustomWriter) {
+    std::ostringstream output{};
+    entt::adjacency_matrix adjacency_matrix{3u};
+
+    adjacency_matrix.insert(0u, 1u);
+    adjacency_matrix.insert(1u, 2u);
+    adjacency_matrix.insert(0u, 2u);
+
+    entt::dot(output, adjacency_matrix, [&adjacency_matrix](std::ostream &out, std::size_t vertex) {
+        out << "label=\"v" << vertex << "\"";
+
+        if(auto in_edges = adjacency_matrix.in_edges(vertex); in_edges.cbegin() == in_edges.cend()) {
+            out << ",shape=\"box\"";
+        }
+    });
+
+    const std::string expected = "digraph{0[label=\"v0\",shape=\"box\"];1[label=\"v1\"];2[label=\"v2\"];0->1;0->2;1->2;}";
+    const auto str = output.str();
+
+    ASSERT_FALSE(str.empty());
+    ASSERT_EQ(str, expected);
+}