1 #ifndef RAPIDXML_ITERATORS_HPP_INCLUDED 2 #define RAPIDXML_ITERATORS_HPP_INCLUDED 3 4 // Copyright (C) 2006, 2009 Marcin Kalicinski 5 // Version 1.13 6 // Revision $DateTime: 2009/05/15 23:02:39 $ 7 //! \file rapidxml_iterators.hpp This file contains rapidxml iterators 8 9 #include "rapidxml.hpp" 10 11 namespace rapidxml 12 { 13 14 //! Iterator of child nodes of xml_node 15 template<class Ch = char> 16 class node_iterator 17 { 18 19 public: 20 21 typedef xml_node<Ch> value_type; 22 typedef xml_node<Ch> &reference; 23 typedef xml_node<Ch> *pointer; 24 typedef std::ptrdiff_t difference_type; 25 typedef std::bidirectional_iterator_tag iterator_category; 26 node_iterator()27 node_iterator() 28 : m_node(0) 29 { 30 } 31 node_iterator(const xml_node<Ch> * node)32 node_iterator(const xml_node<Ch> *node) 33 : m_node(node->first_node()) 34 { 35 } 36 operator *() const37 reference operator *() const 38 { 39 assert(m_node); 40 return *m_node; 41 } 42 operator ->() const43 pointer operator->() const 44 { 45 assert(m_node); 46 return m_node; 47 } 48 operator ++()49 node_iterator& operator++() 50 { 51 assert(m_node); 52 m_node = m_node->next_sibling(); 53 return *this; 54 } 55 operator ++(int)56 node_iterator operator++(int) 57 { 58 node_iterator tmp = *this; 59 this->operator++(); 60 return tmp; 61 } 62 operator --()63 node_iterator &operator--() 64 { 65 assert(m_node && m_node->previous_sibling()); 66 m_node = m_node->previous_sibling(); 67 return *this; 68 } 69 operator --(int)70 node_iterator operator--(int) 71 { 72 node_iterator tmp = *this; 73 this->operator--(); 74 return tmp; 75 } 76 operator ==(const node_iterator<Ch> & rhs) const77 bool operator==(const node_iterator<Ch> &rhs) const 78 { 79 return m_node == rhs.m_node; 80 } 81 operator !=(const node_iterator<Ch> & rhs) const82 bool operator!=(const node_iterator<Ch> &rhs) const 83 { 84 return m_node != rhs.m_node; 85 } 86 87 private: 88 89 xml_node<Ch> *m_node; 90 91 }; 92 93 //! Iterator of child attributes of xml_node 94 template<class Ch = char> 95 class attribute_iterator 96 { 97 98 public: 99 100 typedef xml_attribute<Ch> value_type; 101 typedef xml_attribute<Ch> &reference; 102 typedef xml_attribute<Ch> *pointer; 103 typedef std::ptrdiff_t difference_type; 104 typedef std::bidirectional_iterator_tag iterator_category; 105 attribute_iterator()106 attribute_iterator() 107 : m_attribute(0) 108 { 109 } 110 attribute_iterator(const xml_node<Ch> * node)111 attribute_iterator(const xml_node<Ch> *node) 112 : m_attribute(node->first_attribute()) 113 { 114 } 115 operator *() const116 reference operator *() const 117 { 118 assert(m_attribute); 119 return *m_attribute; 120 } 121 operator ->() const122 pointer operator->() const 123 { 124 assert(m_attribute); 125 return m_attribute; 126 } 127 operator ++()128 attribute_iterator &operator++() 129 { 130 assert(m_attribute); 131 m_attribute = m_attribute->next_attribute(); 132 return *this; 133 } 134 operator ++(int)135 attribute_iterator operator++(int) 136 { 137 attribute_iterator tmp = *this; 138 this->operator++(); 139 return tmp; 140 } 141 operator --()142 attribute_iterator& operator--() 143 { 144 assert(m_attribute && m_attribute->previous_attribute()); 145 m_attribute = m_attribute->previous_attribute(); 146 return *this; 147 } 148 operator --(int)149 attribute_iterator operator--(int) 150 { 151 attribute_iterator tmp = *this; 152 this->operator--(); 153 return tmp; 154 } 155 operator ==(const attribute_iterator<Ch> & rhs) const156 bool operator ==(const attribute_iterator<Ch> &rhs) const 157 { 158 return m_attribute == rhs.m_attribute; 159 } 160 operator !=(const attribute_iterator<Ch> & rhs) const161 bool operator !=(const attribute_iterator<Ch> &rhs) const 162 { 163 return m_attribute != rhs.m_attribute; 164 } 165 166 private: 167 168 xml_attribute<Ch> *m_attribute; 169 }; 170 171 // Range-based for loop support 172 template<class Iterator> 173 class iterator_range 174 { 175 176 public: 177 using const_iterator = Iterator; 178 using iterator = Iterator; 179 iterator_range(Iterator first,Iterator last)180 iterator_range(Iterator first, Iterator last) noexcept 181 : m_first(first) 182 , m_last(last) 183 { 184 } 185 begin() const186 Iterator begin() const noexcept 187 { 188 return m_first; 189 } end() const190 Iterator end() const noexcept 191 { 192 return m_last; 193 } 194 195 private: 196 Iterator m_first; 197 Iterator m_last; 198 }; 199 200 template<class Ch> 201 using node_range = iterator_range<node_iterator<Ch>>; 202 203 template<class Ch> 204 using attribute_range = iterator_range<attribute_iterator<Ch>>; 205 206 //! \pre `parent` is not equal to `nullptr`. 207 //! \return A range of pointers to the children of `parent`. 208 template<class Ch> nodes(const xml_node<Ch> * parent)209 node_range<Ch> nodes(const xml_node<Ch> *parent) noexcept 210 { 211 return {node_iterator<Ch>{parent}, {}}; 212 } 213 214 //! \pre `node` is not equal to `nullptr`. 215 //! \remarks The range offers range-based for loop support. 216 template<class Ch> attributes(const xml_node<Ch> * node)217 attribute_range<Ch> attributes(const xml_node<Ch> *node) noexcept 218 { 219 return {attribute_iterator<Ch>{node}, {}}; 220 } 221 } 222 223 #endif 224