Unix porting fixes
[shibboleth/xmltooling.git] / xmltooling / util / XMLObjectChildrenList.h
1 /*
2  *  Copyright 2001-2006 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file XMLObjectChildrenList.h
19  * 
20  * STL-compatible container wrapper
21  */
22
23 #ifndef __xmltooling_list_h__
24 #define __xmltooling_list_h__
25
26 #include <xmltooling/exceptions.h>
27
28 /**
29  * Shorthand for an XMLObjectChildrenList wrapped around a vector
30  * 
31  * @param type  the type of object in the vector
32  */
33 #define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector<type*> >
34
35 /**
36  * Shorthand for an XMLObjectChildrenList wrapped around a list
37  * 
38  * @param type  the type of object in the list
39  */
40 #define ListOf(type) xmltooling::XMLObjectChildrenList< std::list<type*> >
41
42 /**
43  * Shorthand for an XMLObjectChildrenList wrapped around a deque
44  * 
45  * @param type  the type of object in the deque
46  */
47 #define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque<type*> >
48
49 namespace xmltooling {
50
51     // Forward reference
52     template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
53
54     /**
55      * STL iterator that mediates access to an iterator over typed XML children.
56      * @param _Ty   a bidrectional sequence of the subtype to iterate over
57      */
58     template <class _Ty>
59     class XMLObjectChildrenIterator
60     {
61         /// @cond OFF
62         typename _Ty::iterator m_iter;
63         template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
64     public:
65         typedef typename _Ty::iterator::iterator_category iterator_category;
66         typedef typename _Ty::iterator::value_type value_type;
67         typedef typename _Ty::iterator::reference reference;
68         typedef typename _Ty::iterator::pointer pointer;
69         typedef typename _Ty::const_iterator::reference const_reference;
70         typedef typename _Ty::const_iterator::pointer const_pointer;
71         typedef typename _Ty::iterator::difference_type difference_type;
72
73         XMLObjectChildrenIterator() {
74         }
75
76         XMLObjectChildrenIterator(typename _Ty::iterator iter) {
77             m_iter=iter;
78         }
79
80         const_reference operator*() const {
81             return *m_iter;
82         }
83
84         const_reference operator->() const {
85             return *(m_iter.operator->());
86         }
87
88         XMLObjectChildrenIterator& operator++() {
89             // preincrement
90             ++m_iter;
91             return (*this);
92         }
93
94         XMLObjectChildrenIterator& operator--() {
95             // predecrement
96             --m_iter;
97             return (*this);
98         }
99
100         XMLObjectChildrenIterator operator++(int) {
101             // postincrement
102             XMLObjectChildrenIterator _Tmp = *this;
103             ++*this;
104             return (_Tmp);
105         }
106
107         XMLObjectChildrenIterator operator--(int) {
108             // postdecrement
109             XMLObjectChildrenIterator _Tmp = *this;
110             --*this;
111             return (_Tmp);
112         }
113
114         XMLObjectChildrenIterator& operator+=(difference_type _Off) {
115             // increment by integer
116             m_iter += _Off;
117             return (*this);
118         }
119
120         XMLObjectChildrenIterator operator+(difference_type _Off) const {
121             // return this + integer
122             return m_iter + _Off;
123         }
124
125         XMLObjectChildrenIterator& operator-=(difference_type _Off) {
126             // decrement by integer
127             return (*this += -_Off);
128         }
129
130         XMLObjectChildrenIterator operator-(difference_type _Off) const {
131             // return this - integer
132             XMLObjectChildrenIterator _Tmp = *this;
133             return (_Tmp -= _Off);
134         }
135
136         difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
137             // return difference of iterators
138             return m_iter - _Right.m_iter;
139         }
140
141         const_reference operator[](difference_type _Off) const {
142             // subscript
143             return (*(*this + _Off));
144         }
145
146         bool operator==(const XMLObjectChildrenIterator &_Right) const {
147                     // test for iterator equality
148                     return (m_iter == _Right.m_iter);
149             }
150
151             bool operator!=(const XMLObjectChildrenIterator &_Right) const {
152                     // test for iterator inequality
153                     return (!(m_iter == _Right.m_iter));
154             }
155         /// @endcond
156     };
157
158     /**
159      * STL-compatible container that mediates access to underlying lists of typed XML children.
160      * @param _Tx   the subtype container to encapsulate
161      * @param _Ty   the base type in the underlying list (defaults to XMLObject)
162      */
163     template <class Container, class _Ty>
164     class XMLObjectChildrenList
165     {
166         Container& m_container;
167         typename std::list<_Ty*>* m_list;
168         typename std::list<_Ty*>::iterator m_fence;
169         XMLObject* m_parent;
170
171         public:
172         /// @cond OFF
173         typedef typename Container::value_type value_type;
174         typedef typename Container::reference reference;
175         typedef typename Container::const_reference const_reference;
176         typedef typename Container::difference_type difference_type;
177         typedef typename Container::size_type size_type;
178
179         // We override the iterator types with our constrained wrapper.
180         typedef XMLObjectChildrenIterator<Container> iterator;
181         typedef XMLObjectChildrenIterator<Container> const_iterator;
182         /// @endcond
183
184         /**
185          * Constructor to expose a typed collection of children backed by a list of a base type.
186          *
187          * @param parent    parent object of the collection
188          * @param sublist   underlying container to expose
189          * @param backing   pointer to backing list for children, if any
190          * @param ins_fence a marker designating where new children of this type should be added
191          */
192         XMLObjectChildrenList(
193             XMLObject* parent,
194             Container& sublist,
195             typename std::list<_Ty*>* backing,
196             typename std::list<_Ty*>::iterator ins_fence
197             ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
198         }
199
200         /// @cond OFF
201
202         size_type size() const {
203             // return length of sequence
204             return m_container.size();
205         }
206
207         bool empty() const {
208             // test if sequence is empty
209             return m_container.empty();
210         }
211
212         iterator begin() {
213             // return iterator for beginning of mutable sequence
214             return m_container.begin();
215         }
216
217         iterator end() {
218             // return iterator for end of mutable sequence
219             return m_container.end();
220         }
221
222         const_iterator begin() const {
223             // return iterator for beginning of const sequence
224             return m_container.begin();
225         }
226
227         const_iterator end() const {
228             // return iterator for end of const sequence
229             return m_container.end();
230         }
231
232         const_reference at(size_type _Pos) const {
233             // subscript nonmutable sequence with checking
234             return m_container.at(_Pos);
235         }
236
237         const_reference operator[](size_type _Pos) const {
238             // subscript nonmutable sequence
239             return m_container[_Pos];
240         }
241
242         const_reference front() const {
243             // return first element of nonmutable sequence
244             return m_container.front();
245         }
246
247         const_reference back() const {
248             // return last element of nonmutable sequence
249             return m_container.back();
250         }
251
252         void push_back(const_reference _Val) {
253             setParent(_Val);
254             if (m_list)
255                 m_list->insert(m_fence,_Val);
256             m_container.push_back(_Val);
257         }
258
259         iterator erase(iterator _Where) {
260             removeParent(*_Where);
261             if (m_list)
262                 removeChild(*_Where);
263             else
264                 delete *_Where.m_iter;
265             return m_container.erase(_Where.m_iter);
266         }
267
268         iterator erase(iterator _First, iterator _Last) {
269             for (iterator i=_First; i!=_Last; i++) {
270                 removeParent(*i);
271                 if (m_list)
272                     removeChild(*i);
273                 else
274                     delete *i.m_iter;
275             }
276             return m_container.erase(_First,_Last);
277         }
278
279         void clear() {
280             erase(begin(),end());
281         }
282
283     private:
284         void setParent(const_reference _Val) {
285             if (_Val->getParent())
286                 throw XMLObjectException("Child object already has a parent.");
287             _Val->setParent(m_parent);
288             _Val->releaseParentDOM(true);
289         }
290
291         void removeParent(const_reference _Val) {
292             if (_Val->getParent()!=m_parent)
293                 throw XMLObjectException("Child object not owned by this parent.");
294             _Val->setParent(NULL);
295             m_parent->releaseParentDOM(true);
296         }
297
298         void removeChild(const_reference _Val) {
299             for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
300                 if ((*i)==_Val) {
301                     m_list->erase(i);
302                     delete _Val;
303                     return;
304                 }
305             }
306         }
307         /// @endcond
308     };
309
310 };
311
312 #endif /* __xmltooling_list_h__ */