00001 /*+-------------------------------------------------------------------------+ 00002 | MultiVehicle simulator (libmvsim) | 00003 | | 00004 | Copyright (C) 2014 Jose Luis Blanco Claraco (University of Almeria) | 00005 | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) | 00006 | Distributed under GNU General Public License version 3 | 00007 | See <http://www.gnu.org/licenses/> | 00008 +-------------------------------------------------------------------------+ */ 00009 #pragma once 00010 00011 #include <rapidxml.hpp> 00012 #include <stdexcept> 00013 00014 namespace mvsim 00015 { 00017 template <typename Ch = char> 00018 class JointXMLnode 00019 { 00020 public: 00021 typedef std::vector<const rapidxml::xml_node<Ch>*> TListNodes; 00022 00023 private: 00024 TListNodes m_nodes; 00025 00026 public: 00027 void add(const rapidxml::xml_node<Ch>* node) { m_nodes.push_back(node); } 00028 const rapidxml::xml_node<Ch>* first_node(const char* name) 00029 { 00030 const rapidxml::xml_node<Ch>* ret = NULL; 00031 for (typename TListNodes::const_iterator it = m_nodes.begin(); 00032 it != m_nodes.end(); ++it) 00033 { 00034 ret = (*it)->first_node(name); 00035 if (ret != NULL) return ret; 00036 } 00037 return ret; 00038 } 00039 00040 TListNodes& getListOfNodes() { return m_nodes; } 00041 // Iterators-like interface ---------------------- 00042 class iterator 00043 { 00044 public: 00045 template <typename Ch_> 00046 friend class JointXMLnode; 00047 00048 // ++it 00049 iterator& operator++() 00050 { 00051 if (!current) 00052 throw std::runtime_error("++ called on end() iterator!?"); 00053 current = current->next_sibling(); 00054 JointXMLnode<Ch>::TListNodes& lst = parent.getListOfNodes(); 00055 while (!current && lst_idx < lst.size()) 00056 { 00057 lst_idx++; 00058 if (lst_idx < lst.size()) 00059 current = lst[lst_idx]->first_node(); 00060 else 00061 current = NULL; 00062 } 00063 return *this; 00064 } 00065 00066 rapidxml::xml_node<Ch>* operator->() const 00067 { 00068 if (!current) 00069 throw std::runtime_error("-> called on end() iterator!?"); 00070 return current; 00071 } 00072 00073 rapidxml::xml_node<Ch>* operator*() const 00074 { 00075 if (!current) 00076 throw std::runtime_error("* called on end() iterator!?"); 00077 return current; 00078 } 00079 00080 bool operator==(const iterator& it) const 00081 { 00082 return (this->current == it.current) && 00083 (this->lst_idx == it.lst_idx) && 00084 (&this->parent == &it.parent); 00085 } 00086 bool operator!=(const iterator& it) const { return !(*this == it); } 00087 private: 00088 // begin(): 00089 iterator(JointXMLnode<Ch>& pa) : parent(pa), lst_idx(0), current(NULL) 00090 { 00091 JointXMLnode<Ch>::TListNodes& lst = parent.getListOfNodes(); 00092 while (!current && lst_idx < lst.size()) 00093 { 00094 current = lst[lst_idx]->first_node(); 00095 if (!current) lst_idx++; 00096 } 00097 } 00098 // end() 00099 iterator(JointXMLnode<Ch>& pa, size_t idx) 00100 : parent(pa), lst_idx(idx), current(NULL) 00101 { 00102 } 00103 00104 JointXMLnode<Ch>& parent; 00105 size_t lst_idx; // => lst.size() means this is "end()" 00106 rapidxml::xml_node<Ch>* current; 00107 00108 }; // end class iterator 00109 00110 iterator begin() { return iterator(*this); } 00111 iterator end() { return iterator(*this, m_nodes.size()); } 00112 }; 00113 }