2 * Copyright 2001-2007 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file xmltooling/util/XMLObjectChildrenList.h
20 * STL-compatible container wrapper
23 #ifndef __xmltooling_list_h__
24 #define __xmltooling_list_h__
26 #include <xmltooling/exceptions.h>
27 #include <xmltooling/XMLObject.h>
32 * Shorthand for an XMLObjectChildrenList wrapped around a vector
34 * @param type the type of object in the vector
36 #define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector<type*> >
39 * Shorthand for an XMLObjectChildrenList wrapped around a list
41 * @param type the type of object in the list
43 #define ListOf(type) xmltooling::XMLObjectChildrenList< std::list<type*> >
46 * Shorthand for an XMLObjectChildrenList wrapped around a deque
48 * @param type the type of object in the deque
50 #define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque<type*> >
53 * Shorthand for an XMLObjectPairList wrapped around a vector
55 * @param type1 the first type of object in the vector
56 * @param type2 the second type of object in the vector
58 #define VectorOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::vector< std::pair<type1*,type2*> > >
61 * Shorthand for an XMLObjectPairList wrapped around a list
63 * @param type1 the first type of object in the vector
64 * @param type2 the second type of object in the vector
66 #define ListOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::list< std::pair<type1*,type2*> > >
69 * Shorthand for an XMLObjectPairList wrapped around a deque
71 * @param type1 the first type of object in the vector
72 * @param type2 the second type of object in the vector
74 #define DequeOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::deque< std::pair<type1*,type2*> > >
76 namespace xmltooling {
79 template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
80 template <class _Tx, class _Ty=XMLObject> class XMLObjectPairList;
83 * STL iterator that mediates access to an iterator over typed XML children.
84 * @param _Ty a bidrectional sequence of the subtype to iterate over
87 class XMLObjectChildrenIterator
90 typename _Ty::iterator m_iter;
91 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
92 template <class _Tx, class _Tz> friend class XMLObjectPairList;
94 typedef typename std::iterator_traits<typename _Ty::iterator>::iterator_category iterator_category;
95 typedef typename std::iterator_traits<typename _Ty::iterator>::value_type value_type;
96 typedef typename std::iterator_traits<typename _Ty::iterator>::difference_type difference_type;
97 typedef typename std::iterator_traits<typename _Ty::iterator>::pointer pointer;
98 typedef typename std::iterator_traits<typename _Ty::iterator>::reference reference;
99 typedef typename _Ty::const_reference const_reference;
100 typedef typename _Ty::const_pointer const_pointer;
102 XMLObjectChildrenIterator() {
105 XMLObjectChildrenIterator(typename _Ty::iterator iter) {
109 const_reference operator*() const {
113 const_reference operator->() const {
117 XMLObjectChildrenIterator& operator++() {
123 XMLObjectChildrenIterator& operator--() {
129 XMLObjectChildrenIterator operator++(int) {
131 XMLObjectChildrenIterator _Tmp = *this;
136 XMLObjectChildrenIterator operator--(int) {
138 XMLObjectChildrenIterator _Tmp = *this;
143 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
144 // increment by integer
149 XMLObjectChildrenIterator operator+(difference_type _Off) const {
150 // return this + integer
151 return m_iter + _Off;
154 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
155 // decrement by integer
156 return (*this += -_Off);
159 XMLObjectChildrenIterator operator-(difference_type _Off) const {
160 // return this - integer
161 XMLObjectChildrenIterator _Tmp = *this;
162 return (_Tmp -= _Off);
165 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
166 // return difference of iterators
167 return m_iter - _Right.m_iter;
170 const_reference operator[](difference_type _Off) const {
172 return (*(*this + _Off));
175 bool operator==(const XMLObjectChildrenIterator &_Right) const {
176 // test for iterator equality
177 return (m_iter == _Right.m_iter);
180 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
181 // test for iterator inequality
182 return (!(m_iter == _Right.m_iter));
185 bool operator<(const XMLObjectChildrenIterator &_Right) const {
186 return (m_iter < _Right.m_iter);
192 * STL-compatible container that mediates access to underlying lists of typed XML children.
193 * @param _Tx the subtype container to encapsulate
194 * @param _Ty the base type in the underlying list (defaults to XMLObject)
196 template <class Container, class _Ty>
197 class XMLObjectChildrenList
199 Container& m_container;
200 typename std::list<_Ty*>* m_list;
201 typename std::list<_Ty*>::iterator m_fence;
206 typedef typename Container::value_type value_type;
207 typedef typename Container::reference reference;
208 typedef typename Container::const_reference const_reference;
209 typedef typename Container::difference_type difference_type;
210 typedef typename Container::size_type size_type;
212 // We override the iterator types with our constrained wrapper.
213 typedef XMLObjectChildrenIterator<Container> iterator;
214 typedef XMLObjectChildrenIterator<Container> const_iterator;
218 * Constructor to expose a typed collection of children backed by a list of a base type.
220 * @param parent parent object of the collection
221 * @param sublist underlying container to expose
222 * @param backing pointer to backing list for children, if any
223 * @param ins_fence a marker designating where new children of this type should be added
225 XMLObjectChildrenList(
228 typename std::list<_Ty*>* backing,
229 typename std::list<_Ty*>::iterator ins_fence
230 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
235 size_type size() const {
236 // return length of sequence
237 return m_container.size();
241 // test if sequence is empty
242 return m_container.empty();
246 // return iterator for beginning of mutable sequence
247 return m_container.begin();
251 // return iterator for end of mutable sequence
252 return m_container.end();
255 const_iterator begin() const {
256 // return iterator for beginning of const sequence
257 return m_container.begin();
260 const_iterator end() const {
261 // return iterator for end of const sequence
262 return m_container.end();
265 const_reference at(size_type _Pos) const {
266 // subscript nonmutable sequence with checking
267 return m_container.at(_Pos);
270 const_reference operator[](size_type _Pos) const {
271 // subscript nonmutable sequence
272 return m_container[_Pos];
275 const_reference front() const {
276 // return first element of nonmutable sequence
277 return m_container.front();
280 const_reference back() const {
281 // return last element of nonmutable sequence
282 return m_container.back();
285 void push_back(const_reference _Val) {
288 m_list->insert(m_fence,_Val);
289 m_container.push_back(_Val);
292 iterator erase(iterator _Where) {
293 removeParent(*_Where);
295 removeChild(*_Where);
297 delete *_Where.m_iter;
298 return m_container.erase(_Where.m_iter);
301 iterator erase(iterator _First, iterator _Last) {
302 for (iterator i=_First; i!=_Last; i++) {
309 return m_container.erase(_First.m_iter,_Last.m_iter);
313 erase(begin(),end());
317 void setParent(const_reference _Val) {
318 if (_Val->getParent())
319 throw XMLObjectException("Child object already has a parent.");
320 _Val->setParent(m_parent);
321 _Val->releaseParentDOM(true);
324 void removeParent(const_reference _Val) {
325 if (_Val->getParent()!=m_parent)
326 throw XMLObjectException("Child object not owned by this parent.");
327 _Val->setParent(NULL);
328 m_parent->releaseParentDOM(true);
331 void removeChild(const_reference _Val) {
332 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
344 * STL-compatible container that mediates access to underlying lists of typed XML children
345 * that come in pairs.
347 * @param _Tx the subtype container to encapsulate
348 * @param _Ty the base type in the underlying list (defaults to XMLObject)
350 template <class Container, class _Ty>
351 class XMLObjectPairList
353 Container& m_container;
354 typename std::list<_Ty*>* m_list;
355 typename std::list<_Ty*>::iterator m_fence;
360 typedef typename Container::value_type value_type;
361 typedef typename Container::reference reference;
362 typedef typename Container::const_reference const_reference;
363 typedef typename Container::difference_type difference_type;
364 typedef typename Container::size_type size_type;
366 // We override the iterator types with our constrained wrapper.
367 typedef XMLObjectChildrenIterator<Container> iterator;
368 typedef XMLObjectChildrenIterator<Container> const_iterator;
372 * Constructor to expose a typed collection of pairs backed by a list of a base type.
374 * @param parent parent object of the collection
375 * @param sublist underlying container to expose
376 * @param backing pointer to backing list for children, if any
377 * @param ins_fence a marker designating where new children of this type should be added
382 typename std::list<_Ty*>* backing,
383 typename std::list<_Ty*>::iterator ins_fence
384 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
389 size_type size() const {
390 // return length of sequence
391 return m_container.size();
395 // test if sequence is empty
396 return m_container.empty();
400 // return iterator for beginning of mutable sequence
401 return m_container.begin();
405 // return iterator for end of mutable sequence
406 return m_container.end();
409 const_iterator begin() const {
410 // return iterator for beginning of const sequence
411 return m_container.begin();
414 const_iterator end() const {
415 // return iterator for end of const sequence
416 return m_container.end();
419 const_reference at(size_type _Pos) const {
420 // subscript nonmutable sequence with checking
421 return m_container.at(_Pos);
424 const_reference operator[](size_type _Pos) const {
425 // subscript nonmutable sequence
426 return m_container[_Pos];
429 const_reference front() const {
430 // return first element of nonmutable sequence
431 return m_container.front();
434 const_reference back() const {
435 // return last element of nonmutable sequence
436 return m_container.back();
439 void push_back(const_reference _Val) {
442 m_list->insert(m_fence,_Val.first);
443 m_list->insert(m_fence,_Val.second);
445 m_container.push_back(_Val);
448 iterator erase(iterator _Where) {
449 removeParent(*_Where);
451 removeChild(*_Where);
453 delete _Where.m_iter->first;
454 delete _Where.m_iter->second;
456 return m_container.erase(_Where.m_iter);
459 iterator erase(iterator _First, iterator _Last) {
460 for (iterator i=_First; i!=_Last; i++) {
465 delete i.m_iter->first;
466 delete i.m_iter->second;
469 return m_container.erase(_First,_Last);
473 erase(begin(),end());
477 void setParent(const_reference _Val) {
478 if (_Val.first->getParent() || (_Val.second && _Val.second->getParent()))
479 throw XMLObjectException("One of the child objects already has a parent.");
480 _Val.first->setParent(m_parent);
482 _Val.second->setParent(m_parent);
483 _Val.first->releaseParentDOM(true);
486 void removeParent(const_reference _Val) {
487 if (_Val.first->getParent()!=m_parent || (_Val.second && _Val.second->getParent()!=m_parent))
488 throw XMLObjectException("One of the child objects not owned by this parent.");
489 _Val.first->setParent(NULL);
491 _Val.second->setParent(NULL);
492 m_parent->releaseParentDOM(true);
495 void removeChild(const_reference _Val) {
496 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
497 if ((*i)==_Val.first) {
498 typename std::list<_Ty*>::iterator j=i++;
513 #endif /* __xmltooling_list_h__ */