Ariles
reader.cpp
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2018 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 
11 
12 #include "common.h"
13 
14 namespace ariles2
15 {
16  namespace ns_pugixml
17  {
18  namespace impl
19  {
20  class Reader : public serialization::NodeStackBase<NodeWrapper>
21  {
22  public:
23  pugi::xml_document document_;
24 
25 
26  public:
27  /**
28  * @brief Get current node
29  *
30  * @return pointer to the current node
31  */
32  pugi::xml_node &getRawNode()
33  {
34  return (back().node_);
35  }
36  };
37  } // namespace impl
38  } // namespace ns_pugixml
39 } // namespace ariles2
40 
41 
42 namespace ariles2
43 {
44  namespace ns_pugixml
45  {
46  Reader::Reader(const std::string &file_name)
47  {
48  impl_ = std::make_shared<impl::Reader>();
49 
50  const pugi::xml_parse_result result = impl_->document_.load_file(file_name.c_str(), pugi::parse_minimal);
51  CPPUT_ASSERT(result, std::string("Parsing of '") + file_name + "' failed: " + result.description());
52  impl_->node_stack_.emplace_back(impl_->document_);
53  }
54 
55 
56  Reader::Reader(std::istream &input_stream)
57  {
58  impl_ = std::make_shared<impl::Reader>();
59 
60  const pugi::xml_parse_result result = impl_->document_.load(input_stream, pugi::parse_minimal);
61  CPPUT_ASSERT(result, std::string("Parsing failed: ") + result.description());
62  impl_->node_stack_.emplace_back(impl_->document_);
63  }
64 
65 
66  bool Reader::startMapEntry(const std::string &child_name)
67  {
68  const pugi::xml_node child = impl_->getRawNode().child(child_name.c_str());
69 
70  if (nullptr != child)
71  {
72  impl_->emplace(child);
73  return (true);
74  }
75 
76  const pugi::xml_attribute attribute = impl_->getRawNode().attribute(child_name.c_str());
77  if (nullptr != attribute)
78  {
79  const pugi::xml_node new_child = impl_->getRawNode().append_child(child_name.c_str());
80  new_child.text() = attribute.value();
81  impl_->emplace(new_child);
82  return (true);
83  }
84 
85  return (false);
86  }
87 
88 
90  {
91  impl_->pop();
92  }
93 
94 
96  const SizeLimitEnforcementType /*limit_type*/,
97  const std::size_t /*min*/,
98  const std::size_t /*max*/)
99  {
100  const pugi::xml_node child = impl_->getRawNode().first_child();
101  if (nullptr != child)
102  {
103  impl_->emplace(child, NodeWrapper::Type::ITERATED_MAP);
104  return (true);
105  }
106  return (false);
107  }
108 
109  bool Reader::startIteratedMapElement(std::string &entry_name)
110  {
111  if (nullptr != impl_->getRawNode())
112  {
113  entry_name = impl_->getRawNode().name();
114  return (true);
115  }
116  return (false);
117  }
118 
120  {
121  const pugi::xml_node node = impl_->getRawNode();
122  if (nullptr != node)
123  {
124  impl_->getRawNode() = node.next_sibling();
125  }
126  }
127 
129  {
130  CPPUT_ASSERT(!impl_->getRawNode(), "End of iterated map has not been reached.");
131  impl_->pop();
132  }
133 
134 
135  std::size_t Reader::startArray()
136  {
137  std::size_t size = 0;
138  const pugi::xml_node node = impl_->getRawNode();
139  for (pugi::xml_node child = node.child("item"); nullptr != child;
140  child = child.next_sibling("item"), ++size)
141  {
142  }
143 
144  if (size > 0)
145  {
146  impl_->emplace(node.child("item"), 0, size);
147  }
148  else
149  {
150  // if there are no 'item' childs try to iterate
151  // over childs with the same name in the parent
152  // node
153  for (pugi::xml_node child = impl_->getRawNode(); nullptr != child;
154  child = child.next_sibling(child.name()), ++size)
155  {
156  }
157  impl_->emplace(impl_->getRawNode(), 0, size);
158  }
159 
160  return (size);
161  }
162 
163 
165  {
166  CPPUT_ASSERT(
167  impl_->back().index_ < impl_->back().size_,
168  "Internal error: array has more elements than expected.");
169  }
170 
171 
173  {
174  CPPUT_ASSERT(impl_->back().isArray(), "Internal error: expected array.");
175  impl_->back().node_ = impl_->getRawNode().next_sibling(impl_->getRawNode().name());
176  ++impl_->back().index_;
177  }
178 
179 
181  {
182  impl_->pop();
183  }
184 
185 
186  bool Reader::startRoot(const std::string &name)
187  {
189  if (name.empty())
190  {
191  return (startMapEntry("ariles"));
192  }
193  return (startMapEntry(name));
194  }
195 
196  void Reader::endRoot(const std::string & /*name*/)
197  {
199  endMapEntry();
200  }
201 
202 
203  void Reader::readElement(std::string &element)
204  {
205  element = impl_->getRawNode().text().as_string();
206  }
207 
208 
209 #define ARILES2_BASIC_TYPE(type) \
210  void Reader::readElement(type &element) \
211  { \
212  CPPUT_ASSERT(not impl_->getRawNode().text().empty(), "Empty integer elements are not allowed."); \
213  element = boost::lexical_cast<type>(impl_->getRawNode().text().as_string()); \
214  }
215 
217 
218 #undef ARILES2_BASIC_TYPE
219  } // namespace ns_pugixml
220 } // namespace ariles2
void endRoot(const std::string &name)
Definition: reader.cpp:196
bool startIteratedMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition: reader.cpp:95
bool startRoot(const std::string &name)
Definition: reader.cpp:186
Reader(const std::string &file_name)
Constructor.
Definition: reader.cpp:46
bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition: reader.cpp:66
bool startIteratedMapElement(std::string &entry_name)
Definition: reader.cpp:109
std::size_t startArray()
Definition: reader.cpp:135
void endMapEntry()
endMapEntry from the current entry to its parent.
Definition: reader.cpp:89
pugi::xml_node & getRawNode()
Get current node.
Definition: reader.cpp:32
pugi::xml_document document_
Definition: reader.cpp:23
void readElement(std::complex< t_Scalar > &entry)
Definition: read.h:357
#define CPPUT_ASSERT(condition,...)
Definition: exception.h:32
#define ARILES2_BASIC_NUMERIC_TYPES_LIST
Definition: helpers.h:63
#define CPPUT_MACRO_SUBSTITUTE(macro)
Definition: misc.h:21
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126