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