blob: 0262b71cf25eb21546bb4fab0f7438ba6e67281a [file] [log] [blame]
surmeh01bceff2f2018-03-29 16:29:27 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
surmeh01bceff2f2018-03-29 16:29:27 +01004//
5
6#include "DotSerializer.hpp"
David Monahana8837bf2020-04-16 10:01:56 +01007#include "armnn/utility/StringUtils.hpp"
Nikhil Raj7dcc6972021-04-30 15:44:24 +01008#include <common/include/ProfilingGuid.hpp>
surmeh01bceff2f2018-03-29 16:29:27 +01009
surmeh01bceff2f2018-03-29 16:29:27 +010010#include <sstream>
11#include <cstring>
12
13namespace armnn
14{
15
16namespace
17{
18std::string Indent(int numSpaces)
19{
20 std::stringstream ss;
21 for (int i = 0; i < numSpaces; i++)
22 {
23 ss << " ";
24 }
25 return ss.str();
26}
Rob Hughes362e0322019-11-06 09:36:29 +000027
28std::string Escape(std::string s)
29{
David Monahana8837bf2020-04-16 10:01:56 +010030 armnn::stringUtils::StringReplaceAll(s, "<", "\\<");
31 armnn::stringUtils::StringReplaceAll(s, ">", "\\>");
Rob Hughes362e0322019-11-06 09:36:29 +000032 return s;
33}
34
surmeh01bceff2f2018-03-29 16:29:27 +010035} //namespace
36
37
38HtmlFont::HtmlFont(std::ostream& stream, int fontSize, const char *color, const char *face)
39 : DotBase(stream)
40{
41 GetStream() << "<FONT";
42
43 if (fontSize > -1)
44 {
45 GetStream() << " POINT-SIZE=" << "\"" << fontSize << "\"";
46 }
47
48 if (color && std::strlen(color) != 0)
49 {
50 GetStream() << " COLOR=\"" << color << "\" ";
51 }
52
53 if (face && std::strlen(face) != 0)
54 {
55 GetStream() << " FACE=\"" << face << "\" ";
56 }
57
58 GetStream() << ">";
59}
60
61
62HtmlFont::HtmlFont(std::ostream& stream)
63 : HtmlFont(stream, -1, nullptr, nullptr)
64{}
65
66HtmlFont::~HtmlFont()
67{
68 GetStream() << "</FONT>";
69}
70
71
72DotAttributeSet::DotAttributeSet(std::ostream& stream)
73 : DotBase(stream)
74{
75 GetStream() << "[";
76}
77
78DotAttributeSet::~DotAttributeSet()
79{
80 bool doSpace=false;
surmeh013537c2c2018-05-18 16:31:43 +010081 for (auto&& attrib : m_Attributes)
surmeh01bceff2f2018-03-29 16:29:27 +010082 {
83 if (doSpace)
84 {
85 GetStream() << " ";
86 }
87
88 GetStream() << attrib;
89 doSpace=true;
90 }
91
92 GetStream() << "]";
93}
94
95DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, const std::stringstream& value)
96{
97 std::stringstream ss;
98 ss << name <<"=" << value.str();
99 m_Attributes.push_back(ss.str());
100 return *this;
101}
102
103DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, int value)
104{
105 std::stringstream ss;
106 ss << name <<"=" << value;
107 m_Attributes.push_back(ss.str());
108 return *this;
109}
110
111DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, const std::string& value)
112{
113 std::stringstream ss;
114 ss << name <<"=\"" << value << "\"";
115 m_Attributes.push_back(ss.str());
116 return *this;
117}
118
janeil013fec1ea2019-11-07 09:47:20 +0000119DotEdge::DotEdge(std::ostream& stream, LayerGuid fromNodeId, LayerGuid toNodeId)
surmeh01bceff2f2018-03-29 16:29:27 +0100120 : DotBase(stream)
121{
122 std::stringstream ss;
123 ss << Indent(4) << fromNodeId << " -> " << toNodeId << " ";
124 GetStream() << ss.str();
125
126 m_Attributes = std::make_unique<DotAttributeSet>(stream);
127}
128
129DotEdge::~DotEdge()
130{
131 m_Attributes.reset(nullptr);
132 GetStream() << ";" << std::endl;
133}
134
135
136NodeContent::NodeContent(std::ostream& stream)
137 : DotBase(stream)
138{
139}
140
141NodeContent & NodeContent::SetName(const std::string & name)
142{
143 m_Name = name;
144 return *this;
145}
146
147NodeContent & NodeContent::AddContent(const std::string & content)
148{
149 m_Contents.push_back(content);
150 return *this;
151}
152
153NodeContent::~NodeContent()
154{
155 std::stringstream ss;
156 ss << "label=\"{" << m_Name;
157 if (!m_Contents.empty())
158 {
159 ss << "|";
160 }
161 for (auto & content : m_Contents)
162 {
Rob Hughes362e0322019-11-06 09:36:29 +0000163 ss << Escape(content);
surmeh01bceff2f2018-03-29 16:29:27 +0100164 ss << "\\l";
165 }
166 ss << "}\"";
surmeh013537c2c2018-05-18 16:31:43 +0100167
168 std::string s;
169 try
170 {
171 // Coverity fix: std::stringstream::str() may throw an exception of type std::length_error.
172 s = ss.str();
173 }
174 catch (const std::exception&) { } // Swallow any exception.
175
176 GetStream() << s;
surmeh01bceff2f2018-03-29 16:29:27 +0100177}
178
janeil013fec1ea2019-11-07 09:47:20 +0000179DotNode::DotNode(std::ostream& stream, LayerGuid nodeId, const char* label)
surmeh01bceff2f2018-03-29 16:29:27 +0100180 : DotBase(stream)
181{
182 std::stringstream ss;
183 ss << Indent(4) << nodeId;
184
185 GetStream() << ss.str() << " ";
186
187 m_Contents = std::make_unique<NodeContent>(stream);
188 m_Attributes = std::make_unique<DotAttributeSet>(stream);
189
190 if (std::strlen(label) != 0)
191 {
192 m_Contents->SetName(label);
193 }
194 else
195 {
196 m_Contents->SetName("<noname>");
197 }
198}
199
200DotNode::~DotNode()
201{
202 m_Contents.reset(nullptr);
203 m_Attributes.reset(nullptr);
204 GetStream() << ";" << std::endl;
205}
206
207
208DotDefaults::DotDefaults(std::ostream& stream, const char* type)
209 : DotBase(stream)
210{
211 std::stringstream ss;
212 ss << Indent(4) << type;
213
214 GetStream() << ss.str() << " ";
215 m_Attributes = std::make_unique<DotAttributeSet>(stream);
216}
217
218DotDefaults::~DotDefaults()
219{
220 m_Attributes.reset(nullptr);
221 GetStream() << ";" << std::endl;
222}
223
224DotGraph::DotGraph(std::ostream& stream, const char* name)
225 : DotBase(stream)
226{
227 GetStream() << "digraph " << name << " {" << std::endl;
228}
229
230DotGraph::~DotGraph()
231{
232 GetStream() << "}" << std::endl;
233}
234
235} //namespace armnn
236
237