Parasol Planning Library (PPL)
XMLNode.h
Go to the documentation of this file.
1 #ifndef XML_NODE_H_
2 #define XML_NODE_H_
3 
4 #include <memory>
5 #include <sstream>
6 #include <string>
7 #include <unordered_set>
8 #include <vector>
9 
10 // Tell TinyXML to use the stl.
11 #ifndef TIXML_USE_STL
12 #define TIXML_USE_STL
13 #endif
14 
15 #include "tinyxml2.h"
16 
17 #include "PMPLExceptions.h"
18 
19 
27 class XMLNode {
28 
29  public:
30 
33 
40  XMLNode(const std::string& _filename, const std::string& _desiredNode);
41 
48  XMLNode(const std::string& _filename, std::shared_ptr<tinyxml2::XMLDocument> doc, const std::string& _desiredNode);
49 
50  private:
51 
56  XMLNode(tinyxml2::XMLNode* _node, const std::string& _filename,
57  std::shared_ptr<tinyxml2::XMLDocument> _doc);
58 
60 
61  void FindNode(const std::string& _desiredNode);
62 
63  public:
64 
67 
68  typedef std::vector<XMLNode>::iterator iterator;
69 
71  iterator begin();
72 
74  iterator end();
75 
79 
81  const std::string& Name() const;
82 
84  const std::string& Filename() const;
85 
87  std::string GetPath() const;
88 
92 
94  std::string GetText() const;
95 
99 
114  template <typename T>
115  T Read(const std::string& _name, const bool _req, const T& _default,
116  const T& _min, const T& _max, const std::string& _desc);
117 
128  bool Read(const std::string& _name, const bool _req, const bool _default,
129  const std::string& _desc);
130 
136  std::string Read(const std::string& _name, const bool _req,
137  const char* _default, const std::string& _desc);
138 
149  std::string Read(const std::string& _name,
150  const bool _req,
151  const std::string& _default,
152  const std::string& _desc);
153 
157 
159  void Ignore();
160 
169  void WarnAll(const bool _warningsAsErrors = false);
170 
176  std::string Where() const;
177 
179 
180  private:
181 
184 
194  std::string Where(const std::string& _f, const int _l, const int _c,
195  const bool _name = true) const;
196 
201  void BuildChildVector();
202 
207  std::string AttrWrongType(const std::string& _name, const std::string& _desc)
208  const;
209 
214  std::string AttrMissing(const std::string& _name, const std::string& _desc)
215  const;
216 
225  template <typename T>
226  std::string AttrInvalidBounds(const std::string& _name,
227  const std::string& _desc, const T& _min, const T& _max, const T& _val)
228  const;
229 
231  void ComputeAccessed();
232 
237  void WarnAllRec(bool& _anyWarnings);
238 
240  void WarnUnknownNode();
241 
243  bool WarnUnrequestedAttributes();
244 
248 
249  tinyxml2::XMLNode* m_node{nullptr};
250  bool m_childBuilt{false};
251  bool m_accessed{false};
252  std::vector<XMLNode> m_children;
253  std::unordered_set<std::string> m_reqAttributes;
254  std::string m_filename;
255 
257  std::shared_ptr<tinyxml2::XMLDocument> m_doc;
258 
260 };
261 
262 // specialization for size_t since tinyxml2 doesn't support it
263 template <>
264 size_t
265 XMLNode::
266 Read(const std::string& _name, const bool _req, const size_t& _default,
267  const size_t& _min, const size_t& _max, const std::string& _desc);
268 
269 /*---------------------------- Templated Members -----------------------------*/
270 
271 template <typename T>
272 T
274 Read(const std::string& _name, const bool _req, const T& _default, const T& _min,
275  const T& _max, const std::string& _desc) {
276  m_accessed = true;
277  m_reqAttributes.insert(_name);
278  T toReturn;
279 
280  tinyxml2::XMLError qr = m_node->ToElement()->QueryAttribute(_name.c_str(), &toReturn);
281  switch(qr) {
282  case tinyxml2::XML_WRONG_ATTRIBUTE_TYPE:
283  throw ParseException(Where(), AttrWrongType(_name, _desc));
284  break;
285  case tinyxml2::XML_NO_ATTRIBUTE:
286  {
287  if(_req)
288  throw ParseException(Where(), AttrMissing(_name, _desc));
289  else
290  toReturn = _default;
291  break;
292  }
293  case tinyxml2::XML_SUCCESS:
294  {
295  if(toReturn < _min || toReturn > _max)
296  throw ParseException(Where(),
297  AttrInvalidBounds(_name, _desc, _min, _max, toReturn));
298  break;
299  }
300  default:
301  throw RunTimeException(WHERE, "Logic shouldn't be able to reach this.");
302  }
303 
304  return toReturn;
305 }
306 
307 
308 template <typename T>
309 std::string
310 XMLNode::
311 AttrInvalidBounds(const std::string& _name, const std::string& _desc,
312  const T& _min, const T& _max, const T& _val) const {
313  std::ostringstream oss;
314  oss << "Invalid value for attribute '" << _name << "'."
315  << "\n\tAttribute description: " << _desc << "."
316  << "\n\tValid range: [" << _min << ", " << _max << "]"
317  << "\n\tValue specified: " << _val;
318  return oss.str();
319 }
320 
321 /*----------------------------------------------------------------------------*/
322 
323 #endif
#define WHERE
Macro for retrieving info about file, function, and line number.
Definition: RuntimeUtils.h:32
Definition: XMLNode.h:27
void Ignore()
Ignore unrequested node/attribute errors for this node.
Definition: XMLNode.cpp:218
std::vector< XMLNode >::iterator iterator
Definition: XMLNode.h:68
std::string GetPath() const
Get the directory path containing the XML file.
Definition: XMLNode.cpp:106
const std::string & Filename() const
Get the XML filename.
Definition: XMLNode.cpp:99
const std::string & Name() const
Get the XMLNode name.
Definition: XMLNode.cpp:90
XMLNode(const std::string &_filename, const std::string &_desiredNode)
Definition: XMLNode.cpp:10
void WarnAll(const bool _warningsAsErrors=false)
Definition: XMLNode.cpp:232
iterator end()
Get an iterator to this node's last child.
Definition: XMLNode.cpp:83
std::string Where() const
Definition: XMLNode.cpp:243
iterator begin()
Get an iterator to this node's first child.
Definition: XMLNode.cpp:75
std::string GetText() const
Get the text between opening and closing tags.
Definition: XMLNode.cpp:116
T Read(const std::string &_name, const bool _req, const T &_default, const T &_min, const T &_max, const std::string &_desc)
Definition: XMLNode.h:274
Definition: PMPLExceptions.h:38
Definition: PMPLExceptions.h:62