5 #include <unordered_map>
11 using string_view = std::string_view;
12 using ostream = std::ostream;
13 using string_list = std::initializer_list<string_view>;
18 Sanitize(string_view str,
bool left_align =
false)
19 : str(str), left_align(left_align) {}
22 friend ostream& operator<<(ostream& os, Sanitize s);
26 DotPrinter(ostream& os) : os(os), min_height_{
"0"}, min_width_{
"70"} {}
30 : os(os), min_height_{min_height}, min_width_{min_height} {}
34 bool left_align =
false) {
35 print_html_start(
"tr");
36 print_html_start(
"td", {
"colspan",
"3",
"height", min_height_}, cell_attrs);
37 os << Sanitize{cell_text, left_align};
44 string_list cell1_attrs = {},
45 string_list cell2_attrs = {}) {
46 print_html_start(
"tr");
48 "td", {
"height", min_height_,
"width", min_width_}, cell1_attrs);
49 os << Sanitize{cell1_text};
53 {
"height", min_height_,
"width", min_width_,
"colspan",
"2"},
55 os << Sanitize{cell2_text};
62 string_view cell3_text, string_list cell1_attrs = {},
63 string_list cell2_attrs = {},
64 string_list cell3_attrs = {}) {
65 print_html_start(
"tr");
66 print_html_start(
"td", {
"width", min_width_}, cell1_attrs);
67 os << Sanitize{cell1_text};
69 print_html_start(
"td", {
"width", min_width_}, cell2_attrs);
70 os << Sanitize{cell2_text};
72 print_html_start(
"td", {
"width", min_width_}, cell3_attrs);
73 os << Sanitize{cell3_text};
80 string_view cellpadding =
"1") {
81 indent() <<
"node" << id <<
" [shape=none margin=0.01";
82 print_attr_list(attrs,
false);
92 "cellpadding", cellpadding,
101 print_html_end(
"table");
108 indent() <<
"node" << id <<
" [shape=rect";
109 print_attr_list(attrs,
false);
117 void printLabel(
int id, string_view label, string_list attrs = {}) {
125 indent() <<
"subgraph cluster_" << id <<
" {\n";
128 indent() <<
"label=<" << Sanitize{label} <<
">;\n";
140 os <<
"digraph G {\n";
152 indent() <<
"node" << from <<
" -> node" << to <<
";\n";
158 indent() <<
"node" << from <<
" -> node" << to
159 <<
" [weight=0, style=dashed, color=red];\n";
168 int lhead_cluster = -1) {
169 indent() <<
"node" << from << port <<
" -> node" << to;
170 if(lhead_cluster != -1) {
171 os <<
" [lhead=cluster_" << lhead_cluster <<
"]";
177 int id() {
return id_++; }
179 template <
typename T>
180 int id(T
const* ptr) {
181 auto key =
reinterpret_cast<
void const*>(ptr);
182 return ptr_to_id[key] =
id();
185 template <
typename T>
186 int getId(T
const* ptr) {
187 auto key =
reinterpret_cast<
void const*>(ptr);
189 return ptr_to_id.contains(key) ? ptr_to_id[key] : -1;
193 void sanitize(string_view str) { os << Sanitize{str}; }
196 void print(string_view str) { indent() << str <<
"\n"; }
200 for(
int i = 0; i < indent_; i++) os <<
" ";
204 void print_attr_list(string_list attrs,
bool quote) {
206 for(
auto attr : attrs) {
208 os <<
" " << attr <<
"=";
210 if(quote) os <<
"\"";
212 if(quote) os <<
"\"";
218 void print_html_start(string_view tag, string_list attrs = {},
219 string_list attrs2 = {}) {
221 if(tag ==
"td") newline =
false;
222 indent() <<
"<" << tag;
223 print_attr_list(attrs,
true);
224 print_attr_list(attrs2,
true);
232 void print_html_end(string_view tag) {
234 if(tag ==
"td") newline =
false;
239 os <<
"</" << tag <<
">\n";
246 string_view min_height_;
247 string_view min_width_;
248 std::unordered_map<
void const*,
int> ptr_to_id;