1 /*
2  * Copyright (C) 2009 Vaclav Slavik <vslavik@gmail.com>
3  * All Rights Reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  * 3. Neither the name of the Author nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
23  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /**
34     @file
35 
36     This file contains the definition of the xml::nodes_view and
37     xml::const_nodes_view classes.
38  */
39 
40 #ifndef _xmlwrapp_nodes_view_h_
41 #define _xmlwrapp_nodes_view_h_
42 
43 // xmlwrapp includes
44 #include "xmlwrapp/init.h"
45 #include "xmlwrapp/export.h"
46 
47 // standard includes
48 #include <iterator>
49 
50 namespace xml
51 {
52 
53 class node;
54 class const_nodes_view;
55 
56 namespace impl
57 {
58 
59 struct nipimpl;
60 class iter_advance_functor;
61 
62 } // namespace impl
63 
64 /**
65     This class implements a view of XML nodes. A @em view is a container-like
66     class that only allows access to a subset of xml::node's child nodes. The
67     exact content depends on how the view was obtained; typical uses are
68     e.g. a view of all element children or all elements with a given name.
69 
70     The nodes_view class implements the same container interface that
71     xml::node does: it has begin() and end() methods.
72 
73     @since  0.6.0
74 
75     @see xml::node::elements(), xml::node::elements(const char *)
76  */
77 class XMLWRAPP_API nodes_view
78 {
79 public:
80     /// Size type.
81     typedef std::size_t size_type;
82 
nodes_view()83     nodes_view() : data_begin_(0), advance_func_(0) {}
84     nodes_view(const nodes_view& other);
85     ~nodes_view();
86 
87     nodes_view& operator=(const nodes_view& other);
88 
89     class const_iterator;
90 
91     /**
92         The iterator provides a way to access nodes in the view
93         similar to a standard C++ container.
94 
95         @see xml::node::iterator
96      */
97     class iterator
98     {
99     public:
100         typedef node value_type;
101         typedef int difference_type;
102         typedef value_type* pointer;
103         typedef value_type& reference;
104         typedef std::forward_iterator_tag iterator_category;
105 
iterator()106         iterator() : pimpl_(0), advance_func_(0) {}
107         iterator(const iterator& other);
108         iterator& operator=(const iterator& other);
109         ~iterator();
110 
111         reference operator*() const;
112         pointer   operator->() const;
113 
114         iterator& operator++();
115         iterator  operator++(int);
116 
117     private:
118         explicit iterator(void *data, impl::iter_advance_functor *advance_func);
119         void* get_raw_node() const;
120         void swap(iterator& other);
121 
122         impl::nipimpl *pimpl_;
123         // function for advancing the iterator (note that it is "owned" by the
124         // parent view object, so we don't have to care about its reference
125         // count here)
126         impl::iter_advance_functor *advance_func_;
127 
128         friend class nodes_view;
129         friend class const_iterator;
130         friend bool XMLWRAPP_API operator==(const iterator& lhs, const iterator& rhs);
131     };
132 
133     /**
134         The const_iterator provides a way to access nodes in the view
135         similar to a standard C++ container. The nodes that are pointed to by
136         the iterator cannot be changed.
137 
138         @see xml::node::const_iterator
139      */
140     class const_iterator
141     {
142     public:
143         typedef const node value_type;
144         typedef int difference_type;
145         typedef value_type* pointer;
146         typedef value_type& reference;
147         typedef std::forward_iterator_tag iterator_category;
148 
const_iterator()149         const_iterator() : pimpl_(0), advance_func_(0) {}
150         const_iterator(const const_iterator& other);
151         const_iterator(const iterator& other);
152         const_iterator& operator=(const const_iterator& other);
153         const_iterator& operator=(const iterator& other);
154         ~const_iterator();
155 
156         reference operator*() const;
157         pointer   operator->() const;
158 
159         const_iterator& operator++();
160         const_iterator  operator++(int);
161 
162     private:
163         explicit const_iterator(void *data, impl::iter_advance_functor *advance_func);
164         void* get_raw_node() const;
165         void swap(const_iterator& other);
166 
167         impl::nipimpl *pimpl_;
168         // function for advancing the iterator (note that it is "owned" by the
169         // parent view object, so we don't have to care about its reference
170         // count here)
171         impl::iter_advance_functor *advance_func_;
172 
173         friend class const_nodes_view;
174         friend class nodes_view;
175         friend bool XMLWRAPP_API operator==(const const_iterator& lhs, const const_iterator& rhs);
176     };
177 
178     /// Get an iterator that points to the beginning of this view's nodes.
begin()179     iterator begin() { return iterator(data_begin_, advance_func_); }
180 
181     /// Get an iterator that points to the beginning of this view's nodes.
begin()182     const_iterator begin() const { return const_iterator(data_begin_, advance_func_); }
183 
184     /// Get an iterator that points one past the last child for this view.
end()185     iterator end() { return iterator(); }
186 
187     /// Get an iterator that points one past the last child for this view.
end()188     const_iterator end() const { return const_iterator(); }
189 
190     /// Returns the number of nodes in this view.
191     size_type size() const;
192 
193     /// Is the view empty?
empty()194     bool empty() const { return !data_begin_; }
195 
196 private:
nodes_view(void * data_begin,impl::iter_advance_functor * advance_func)197     explicit nodes_view(void *data_begin, impl::iter_advance_functor *advance_func)
198         : data_begin_(data_begin), advance_func_(advance_func) {}
199 
200     // begin iterator
201     void *data_begin_;
202     // function for advancing the iterator (owned by the view object)
203     impl::iter_advance_functor *advance_func_;
204 
205     friend class node;
206     friend class const_nodes_view;
207 };
208 
209 
210 /**
211     This class implements a @em read-only view of XML nodes. The only
212     difference from xml::nodes_view is that it doesn't allow modifications of
213     the nodes, it is otherwise identical.
214 
215     @see nodes_view
216 
217     @since  0.6.0
218  */
219 class XMLWRAPP_API const_nodes_view
220 {
221 public:
222     /// Size type.
223     typedef std::size_t size_type;
224 
const_nodes_view()225     const_nodes_view() : data_begin_(0), advance_func_(0) {}
226     const_nodes_view(const const_nodes_view& other);
227     const_nodes_view(const nodes_view& other);
228     ~const_nodes_view();
229 
230     const_nodes_view& operator=(const const_nodes_view& other);
231     const_nodes_view& operator=(const nodes_view& other);
232 
233     typedef nodes_view::const_iterator iterator;
234     typedef nodes_view::const_iterator const_iterator;
235 
236     /// Get an iterator that points to the beginning of this view's nodes.
begin()237     const_iterator begin() const
238         { return const_iterator(data_begin_, advance_func_); }
239 
240     /// Get an iterator that points one past the last child for this view.
end()241     const_iterator end() const { return const_iterator(); }
242 
243     /// Returns the number of nodes in this view.
244     size_type size() const;
245 
246     /// Is the view empty?
empty()247     bool empty() const { return !data_begin_; }
248 
249 private:
const_nodes_view(void * data_begin,impl::iter_advance_functor * advance_func)250     explicit const_nodes_view(void *data_begin, impl::iter_advance_functor *advance_func)
251         : data_begin_(data_begin), advance_func_(advance_func) {}
252 
253     // begin iterator
254     void *data_begin_;
255     // function for advancing the iterator (owned by the view object)
256     impl::iter_advance_functor *advance_func_;
257 
258     friend class node;
259 };
260 
261 // Comparison operators for xml::[const_]nodes_view iterators
262 
263 inline bool XMLWRAPP_API operator==(const nodes_view::iterator& lhs,
264                                     const nodes_view::iterator& rhs)
265     { return lhs.get_raw_node() == rhs.get_raw_node(); }
266 inline bool XMLWRAPP_API operator!=(const nodes_view::iterator& lhs,
267                                     const nodes_view::iterator& rhs)
268     { return !(lhs == rhs); }
269 
270 inline bool XMLWRAPP_API operator==(const nodes_view::const_iterator& lhs,
271                                     const nodes_view::const_iterator& rhs)
272     { return lhs.get_raw_node() == rhs.get_raw_node(); }
273 inline bool XMLWRAPP_API operator!=(const nodes_view::const_iterator& lhs,
274                                     const nodes_view::const_iterator& rhs)
275     { return !(lhs == rhs); }
276 
277 } // end xml namespace
278 
279 #endif // _xmlwrapp_nodes_view_h_
280