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