Ariles
writer.cpp
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2018-2020 Alexander Sherikov, Licensed under the Apache License, Version 2.0.
6  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7 
8  @brief
9 */
10 
12 
13 #include <vector>
14 #include <utility>
15 #include <set>
16 
17 #include <boost/lexical_cast.hpp>
18 
19 
20 
21 namespace ariles2
22 {
23  namespace ns_graphviz
24  {
25  class NodeWrapper : public serialization::Node<std::string>
26  {
27  public:
29 
30  public:
31  std::string actual_id_;
32  std::string label_;
33 
34 
35  public:
36  explicit NodeWrapper(const std::string &node, const Base::Type type = Base::GENERIC) : Base(node, type)
37  {
38  label_ = node;
39  actual_id_ = node;
40  }
41 
42  explicit NodeWrapper(
43  const std::string &node,
44  const std::string &label,
45  const Base::Type type = Base::GENERIC)
46  : Base(node, type)
47  {
48  label_ = label;
49  actual_id_ = node;
50  }
51 
53  const std::string &node,
54  const std::string &label,
55  const std::size_t index,
56  const std::size_t size)
57  : Base(node, index, size)
58  {
59  label_ = label;
60  actual_id_ = node;
61  }
62  };
63  } // namespace ns_graphviz
64 } // namespace ariles2
65 
66 
67 namespace ariles2
68 {
69  namespace ns_graphviz
70  {
71  namespace impl
72  {
74  {
75  public:
76  std::vector<NodeWrapper> node_stack_;
77  /// output file stream
78  std::ofstream config_ofs_;
79 
80  /// output stream
81  std::ostream *output_stream_;
82 
83  std::set<std::string> all_ids_;
85 
86 
87  public:
88  explicit Visitor(const std::string &file_name)
89  {
90  ariles2::write::Visitor::openFile(config_ofs_, file_name);
91  output_stream_ = &config_ofs_;
92  }
93 
94  explicit Visitor(std::ostream &output_stream)
95  {
96  output_stream_ = &output_stream;
97  }
98 
99 
100  void clear()
101  {
102  all_ids_.clear();
103  node_stack_.clear();
104  }
105 
106 
108  {
109  ARILES2_TRACE_FUNCTION;
110 
111  const std::size_t stack_size = node_stack_.size();
112 
113  ARILES2_ASSERT(0 < stack_size, "Internal error: stack must contain at least 2 entries.");
114 
115  // node
116  node_stack_.back().actual_id_ = node_options.id_;
117 
118  if (true == all_ids_.insert(node_stack_.back().actual_id_).second)
119  {
120  *output_stream_ << node_options.id_;
121  *output_stream_ << "[";
122  if (false == node_options.label_.empty())
123  {
124  *output_stream_ << "label=\"" << node_options.label_ << "\"";
125  }
126  if (false == node_options.options_.empty())
127  {
128  *output_stream_ << "," << node_options.options_;
129  }
130  *output_stream_ << "];\n";
131  }
132 
133  // connection
134  if (stack_size > 1)
135  {
136  *output_stream_ //
137  << node_stack_[stack_size - 2].actual_id_ //
138  << "->" //
139  << node_stack_.back().actual_id_ << ";\n";
140  }
141  }
142  };
143  } // namespace impl
144  } // namespace ns_graphviz
145 } // namespace ariles2
146 
147 
148 namespace ariles2
149 {
150  namespace ns_graphviz
151  {
152  Visitor::Visitor(const std::string &file_name)
153  {
154  impl_ = ImplPtr(new Impl(file_name));
155  }
156 
157 
158  Visitor::Visitor(std::ostream &output_stream)
159  {
160  impl_ = ImplPtr(new Impl(output_stream));
161  }
162 
163 
165  {
166  impl_->output_stream_->flush();
167  }
168 
169 
170  void Visitor::startRoot(const std::string &name, const Parameters &parameters)
171  {
172  ARILES2_TRACE_FUNCTION;
173  impl_->clear();
174  impl_->parameters_ = &parameters;
175  if (true == name.empty())
176  {
177  impl_->node_stack_.push_back(NodeWrapper("ariles"));
178  }
179  else
180  {
181  impl_->node_stack_.push_back(NodeWrapper(name));
182  }
183  *impl_->output_stream_ //
184  << "digraph graph_" << impl_->node_stack_.back().node_ //
185  << " {\n" //
186  << parameters.graph_options_; //
187  }
188 
189 
190  void Visitor::endRoot(const std::string & /*name*/)
191  {
192  ARILES2_TRACE_FUNCTION;
193  *impl_->output_stream_ << "}\n";
194  }
195 
196  std::string Visitor::getDefaultNodeId() const
197  {
198  if (true == impl_->node_stack_.back().isArray())
199  {
200  return (impl_->node_stack_.back().node_ + "_"
201  + boost::lexical_cast<std::string>(impl_->node_stack_.back().index_));
202  }
203  return (impl_->node_stack_.back().node_);
204  }
205 
206  std::string Visitor::getDefaultNodeLabel() const
207  {
208  if (true == impl_->node_stack_.back().isArray())
209  {
210  return (impl_->node_stack_.back().label_ + "_"
211  + boost::lexical_cast<std::string>(impl_->node_stack_.back().index_));
212  }
213  return (impl_->node_stack_.back().label_);
214  }
215 
216  void Visitor::startMap(const Parameters &parameters, const Parameters::NodeOptions &node_options)
217  {
218  ARILES2_TRACE_FUNCTION;
219  if (false == impl_->parameters_->override_parameters_)
220  {
221  impl_->parameters_ = &parameters;
222  }
223  impl_->writeNodeAndConnection(node_options);
224  }
225 
226  void Visitor::startMap(const Parameters &parameters, const std::size_t /*num_entries*/)
227  {
228  ARILES2_TRACE_FUNCTION;
229  if (false == impl_->parameters_->override_parameters_)
230  {
231  impl_->parameters_ = &parameters;
232  }
233  impl_->writeNodeAndConnection(
234  impl_->parameters_->getDefaultNodeOptions(getDefaultNodeId(), getDefaultNodeLabel()));
235  }
236 
237  void Visitor::startMapEntry(const std::string &name)
238  {
239  ARILES2_TRACE_FUNCTION;
240  if (true == impl_->node_stack_.back().isArray())
241  {
242  std::string node = impl_->node_stack_.back().node_;
243  node += "_";
244  node += boost::lexical_cast<std::string>(impl_->node_stack_.back().index_);
245  node += "_";
246  node += name;
247  impl_->node_stack_.push_back(NodeWrapper(node, name));
248  }
249  else
250  {
251  impl_->node_stack_.push_back(NodeWrapper(impl_->node_stack_.back().node_ + "_" + name, name));
252  }
253  }
254 
256  {
257  ARILES2_TRACE_FUNCTION;
258  impl_->node_stack_.pop_back();
259  }
260 
261 
262  void Visitor::startArray(const std::size_t size, const bool compact)
263  {
264  ARILES2_TRACE_FUNCTION;
265  ARILES2_ASSERT(false == impl_->node_stack_.empty(), "Internal error: empty stack.");
266 
267  if (size > 0 || false == compact)
268  {
269  impl_->writeNodeAndConnection(
270  impl_->parameters_->getDefaultNodeOptions(getDefaultNodeId(), getDefaultNodeLabel()));
271  }
272 
273  if (true == impl_->node_stack_.back().isArray())
274  {
275  std::string node = impl_->node_stack_.back().node_;
276  std::string label = impl_->node_stack_.back().label_;
277  node += "_";
278  node += boost::lexical_cast<std::string>(impl_->node_stack_.back().index_);
279  label += "_";
280  label += boost::lexical_cast<std::string>(impl_->node_stack_.back().index_);
281  impl_->node_stack_.push_back(NodeWrapper(node, label, 0, size));
282  }
283  else
284  {
285  impl_->node_stack_.push_back(
286  NodeWrapper(impl_->node_stack_.back().node_, impl_->node_stack_.back().label_, 0, size));
287  }
288  }
289 
291  {
292  ARILES2_ASSERT(true == impl_->node_stack_.back().isArray(), "Internal error: array expected.");
293  ++impl_->node_stack_.back().index_;
294  }
295 
297  {
298  ARILES2_TRACE_FUNCTION;
299  impl_->node_stack_.pop_back();
300  }
301 
302 
303 #define ARILES2_BASIC_TYPE(type) \
304  void Visitor::writeElement(const type &, const Parameters &) \
305  { \
306  impl_->writeNodeAndConnection( \
307  impl_->parameters_->getDefaultNodeOptions(getDefaultNodeId(), getDefaultNodeLabel())); \
308  }
309 
312 
313 #undef ARILES2_BASIC_TYPE
314  } // namespace ns_graphviz
315 } // namespace ariles2
ariles2
Definition: basic.h:16
ariles2::ns_graphviz::impl::Visitor
Definition: writer.cpp:73
ariles2::ns_graphviz::NodeWrapper::actual_id_
std::string actual_id_
Definition: writer.cpp:31
ARILES2_BASIC_TYPES_LIST
#define ARILES2_BASIC_TYPES_LIST
Definition: helpers.h:131
ariles2::ns_graphviz::NodeWrapper::NodeWrapper
NodeWrapper(const std::string &node, const std::string &label, const std::size_t index, const std::size_t size)
Definition: writer.cpp:52
ariles2::ns_graphviz::impl::Visitor::writeNodeAndConnection
void writeNodeAndConnection(const Parameters::NodeOptions &node_options)
Definition: writer.cpp:107
ariles2::ns_graphviz::Visitor::startMapEntry
void startMapEntry(const std::string &map_name)
Starts a nested map in the configuration file.
Definition: writer.cpp:237
ariles2::ns_graphviz::impl::Visitor::Visitor
Visitor(std::ostream &output_stream)
Definition: writer.cpp:94
ariles2::ns_graphviz::Parameters
Definition: graphviz.h:41
ariles2::ns_graphviz::Parameters::NodeOptions::id_
std::string id_
Definition: graphviz.h:47
ariles2::ns_graphviz::Visitor::endArrayElement
void endArrayElement()
Definition: writer.cpp:290
ariles2::ns_graphviz::impl::Visitor::clear
void clear()
Definition: writer.cpp:100
ariles2::ns_graphviz::Parameters::graph_options_
std::string graph_options_
Definition: graphviz.h:83
ariles2::visitor::Visitor::Visitor
Visitor()
Definition: common.h:36
ariles2::ns_graphviz::Visitor::startArray
void startArray(const std::size_t size, const bool compact=false)
Definition: writer.cpp:262
ariles2::ns_graphviz::Visitor::endRoot
void endRoot(const std::string &name)
Definition: writer.cpp:190
ariles2::ns_graphviz::NodeWrapper::NodeWrapper
NodeWrapper(const std::string &node, const Base::Type type=Base::GENERIC)
Definition: writer.cpp:36
ariles2::ns_graphviz::Visitor::getDefaultNodeId
std::string getDefaultNodeId() const
Definition: writer.cpp:196
ariles2::ns_graphviz::Visitor::getDefaultNodeLabel
std::string getDefaultNodeLabel() const
Definition: writer.cpp:206
ariles2::ns_graphviz::impl::Visitor::config_ofs_
std::ofstream config_ofs_
output file stream
Definition: writer.cpp:78
ariles2::ns_graphviz::Visitor::startRoot
void startRoot(const std::string &name, const Parameters &)
Definition: writer.cpp:170
ariles2::serialization::Node< std::string >::GENERIC
@ GENERIC
Definition: serialization.h:55
ariles2::ns_graphviz::Visitor::endMapEntry
void endMapEntry()
Definition: writer.cpp:255
ariles2::serialization::Node< std::string >::Type
Type
Definition: serialization.h:52
ARILES2_COMPLEX_NUMBER_TYPES_LIST
#define ARILES2_COMPLEX_NUMBER_TYPES_LIST
Definition: helpers.h:127
ariles2::serialization::PIMPLVisitor< write::VisitorBase< Visitor, Parameters >, impl::Visitor >::Impl
impl::Visitor Impl
Definition: serialization.h:124
ariles2::ns_graphviz::NodeWrapper::NodeWrapper
NodeWrapper(const std::string &node, const std::string &label, const Base::Type type=Base::GENERIC)
Definition: writer.cpp:42
ariles2::ns_octave::NodeWrapper
serialization::Node< std::string > NodeWrapper
Definition: writer.cpp:23
ariles2::ns_graphviz::impl::Visitor::Visitor
Visitor(const std::string &file_name)
Definition: writer.cpp:88
ARILES2_VISIBILITY_ATTRIBUTE
#define ARILES2_VISIBILITY_ATTRIBUTE
Definition: helpers.h:138
ariles2::ns_graphviz::Parameters::NodeOptions::options_
std::string options_
Definition: graphviz.h:49
ariles2::ns_yaml_cpp::ARILES2_MACRO_SUBSTITUTE
ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_INTEGER_TYPES_LIST) ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_REAL_TYPES_LIST) void Writer
Definition: writer.cpp:198
ariles2::ns_graphviz::impl::Visitor::parameters_
const Parameters * parameters_
Definition: writer.cpp:84
ariles2::serialization::PIMPLVisitor< write::VisitorBase< Visitor, Parameters >, impl::Visitor >::impl_
ImplPtr impl_
Definition: serialization.h:128
ariles2::ns_graphviz::Parameters::NodeOptions::label_
std::string label_
Definition: graphviz.h:48
ariles2::ns_graphviz::NodeWrapper::Base
serialization::Node< std::string > Base
Definition: writer.cpp:28
ariles2::ns_graphviz::Visitor::endArray
void endArray()
Definition: writer.cpp:296
ariles2::ns_graphviz::Visitor::flush
void flush()
Flush the configuration to the output.
Definition: writer.cpp:164
ariles2::ns_graphviz::NodeWrapper
Definition: writer.cpp:25
graphviz.h
ariles2::write::VisitorBase< Visitor, Parameters >::openFile
static void openFile(std::ofstream &config_ofs, const std::string &file_name)
open configuration file
Definition: write.h:58
ariles2::ns_graphviz::impl::Visitor::node_stack_
std::vector< NodeWrapper > node_stack_
Definition: writer.cpp:76
ariles2::ns_graphviz::impl::Visitor::output_stream_
std::ostream * output_stream_
output stream
Definition: writer.cpp:81
ariles2::ns_graphviz::impl::Visitor::all_ids_
std::set< std::string > all_ids_
Definition: writer.cpp:83
ariles2::serialization::Node
Definition: serialization.h:49
ariles2::ns_graphviz::Parameters::NodeOptions
Definition: graphviz.h:44
ariles2::ns_graphviz::Visitor::startMap
void startMap(const Parameters &, const Parameters::NodeOptions &)
Definition: writer.cpp:216
ariles2::serialization::PIMPLVisitor< write::VisitorBase< Visitor, Parameters >, impl::Visitor >::ImplPtr
ARILES2_SHARED_PTR< impl::Visitor > ImplPtr
Definition: serialization.h:125
ariles2::ns_graphviz::NodeWrapper::label_
std::string label_
Definition: writer.cpp:32