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.
85 * @param Container type of container
86 * @param _Ty a bidrectional iterator to guard
88 template <class Container, typename _Ty>
89 class XMLObjectChildrenIterator
93 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
94 template <class _Tx, class _Tz> friend class XMLObjectPairList;
96 #ifdef HAVE_ITERATOR_TRAITS
97 typedef typename std::iterator_traits<_Ty>::iterator_category iterator_category;
98 typedef typename std::iterator_traits<_Ty>::value_type value_type;
99 typedef typename std::iterator_traits<_Ty>::difference_type difference_type;
100 typedef typename std::iterator_traits<_Ty>::pointer pointer;
101 typedef typename std::iterator_traits<_Ty>::reference reference;
103 typedef typename _Ty::iterator_category iterator_category;
104 typedef typename _Ty::value_type value_type;
105 typedef typename _Ty::difference_type difference_type;
106 typedef typename _Ty::pointer pointer;
107 typedef typename _Ty::reference reference;
109 typedef typename Container::const_reference const_reference;
110 typedef typename Container::const_pointer const_pointer;
112 XMLObjectChildrenIterator() {
115 XMLObjectChildrenIterator(_Ty iter) {
119 const_reference operator*() const {
123 const_reference operator->() const {
127 XMLObjectChildrenIterator& operator++() {
133 XMLObjectChildrenIterator& operator--() {
139 XMLObjectChildrenIterator operator++(int) {
141 XMLObjectChildrenIterator _Tmp = *this;
146 XMLObjectChildrenIterator operator--(int) {
148 XMLObjectChildrenIterator _Tmp = *this;
153 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
154 // increment by integer
159 XMLObjectChildrenIterator operator+(difference_type _Off) const {
160 // return this + integer
161 return m_iter + _Off;
164 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
165 // decrement by integer
166 return (*this += -_Off);
169 XMLObjectChildrenIterator operator-(difference_type _Off) const {
170 // return this - integer
171 XMLObjectChildrenIterator _Tmp = *this;
172 return (_Tmp -= _Off);
175 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
176 // return difference of iterators
177 return m_iter - _Right.m_iter;
180 const_reference operator[](difference_type _Off) const {
182 return (*(*this + _Off));
185 bool operator==(const XMLObjectChildrenIterator &_Right) const {
186 // test for iterator equality
187 return (m_iter == _Right.m_iter);
190 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
191 // test for iterator inequality
192 return (!(m_iter == _Right.m_iter));
195 bool operator<(const XMLObjectChildrenIterator &_Right) const {
196 return (m_iter < _Right.m_iter);
201 #ifndef HAVE_ITERATOR_TRAITS
203 * STL iterator that mediates access to an iterator that's a pointer.
205 * @param Container type of container
206 * @param _Ty the type of object being referenced
208 template <class Container, typename _Ty>
209 class XMLObjectChildrenIterator<Container, _Ty*>
212 typename _Ty* m_iter;
213 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
214 template <class _Tx, class _Tz> friend class XMLObjectPairList;
216 typedef std::random_access_iterator_tag iterator_category;
217 typedef _Ty value_type;
218 typedef ptrdiff_t difference_type;
219 typedef _Ty* pointer;
220 typedef _Ty& reference;
221 typedef const _Ty& const_reference;
222 typedef const _Ty* const_pointer;
224 XMLObjectChildrenIterator() {
227 XMLObjectChildrenIterator(_Ty* iter) {
231 const_reference operator*() const {
235 const_reference operator->() const {
239 XMLObjectChildrenIterator& operator++() {
245 XMLObjectChildrenIterator& operator--() {
251 XMLObjectChildrenIterator operator++(int) {
253 XMLObjectChildrenIterator _Tmp = *this;
258 XMLObjectChildrenIterator operator--(int) {
260 XMLObjectChildrenIterator _Tmp = *this;
265 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
266 // increment by integer
271 XMLObjectChildrenIterator operator+(difference_type _Off) const {
272 // return this + integer
273 return m_iter + _Off;
276 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
277 // decrement by integer
278 return (*this += -_Off);
281 XMLObjectChildrenIterator operator-(difference_type _Off) const {
282 // return this - integer
283 XMLObjectChildrenIterator _Tmp = *this;
284 return (_Tmp -= _Off);
287 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
288 // return difference of iterators
289 return m_iter - _Right.m_iter;
292 const_reference operator[](difference_type _Off) const {
294 return (*(*this + _Off));
297 bool operator==(const XMLObjectChildrenIterator &_Right) const {
298 // test for iterator equality
299 return (m_iter == _Right.m_iter);
302 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
303 // test for iterator inequality
304 return (!(m_iter == _Right.m_iter));
307 bool operator<(const XMLObjectChildrenIterator &_Right) const {
308 return (m_iter < _Right.m_iter);
314 * STL iterator that mediates access to an iterator that's a const pointer.
316 * @param Container type of container
317 * @param _Ty the type of object being referenced
319 template <class Container, typename _Ty>
320 class XMLObjectChildrenIterator<Container, const _Ty*>
323 typename const _Ty* m_iter;
324 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
325 template <class _Tx, class _Tz> friend class XMLObjectPairList;
327 typedef std::random_access_iterator_tag iterator_category;
328 typedef _Ty value_type;
329 typedef ptrdiff_t difference_type;
330 typedef const _Ty* pointer;
331 typedef const _Ty& reference;
332 typedef const _Ty& const_reference;
333 typedef const _Ty* const_pointer;
335 XMLObjectChildrenIterator() {
338 XMLObjectChildrenIterator(_Ty* iter) {
342 const_reference operator*() const {
346 const_reference operator->() const {
350 XMLObjectChildrenIterator& operator++() {
356 XMLObjectChildrenIterator& operator--() {
362 XMLObjectChildrenIterator operator++(int) {
364 XMLObjectChildrenIterator _Tmp = *this;
369 XMLObjectChildrenIterator operator--(int) {
371 XMLObjectChildrenIterator _Tmp = *this;
376 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
377 // increment by integer
382 XMLObjectChildrenIterator operator+(difference_type _Off) const {
383 // return this + integer
384 return m_iter + _Off;
387 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
388 // decrement by integer
389 return (*this += -_Off);
392 XMLObjectChildrenIterator operator-(difference_type _Off) const {
393 // return this - integer
394 XMLObjectChildrenIterator _Tmp = *this;
395 return (_Tmp -= _Off);
398 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
399 // return difference of iterators
400 return m_iter - _Right.m_iter;
403 const_reference operator[](difference_type _Off) const {
405 return (*(*this + _Off));
408 bool operator==(const XMLObjectChildrenIterator &_Right) const {
409 // test for iterator equality
410 return (m_iter == _Right.m_iter);
413 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
414 // test for iterator inequality
415 return (!(m_iter == _Right.m_iter));
418 bool operator<(const XMLObjectChildrenIterator &_Right) const {
419 return (m_iter < _Right.m_iter);
426 * STL-compatible container that mediates access to underlying lists of typed XML children.
427 * @param _Tx the subtype container to encapsulate
428 * @param _Ty the base type in the underlying list (defaults to XMLObject)
430 template <class Container, class _Ty>
431 class XMLObjectChildrenList
433 Container& m_container;
434 typename std::list<_Ty*>* m_list;
435 typename std::list<_Ty*>::iterator m_fence;
440 typedef typename Container::value_type value_type;
441 typedef typename Container::reference reference;
442 typedef typename Container::const_reference const_reference;
443 typedef typename Container::difference_type difference_type;
444 typedef typename Container::size_type size_type;
446 // We override the iterator types with our constrained wrapper.
447 typedef XMLObjectChildrenIterator<Container, typename Container::iterator> iterator;
448 typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> const_iterator;
452 * Constructor to expose a typed collection of children backed by a list of a base type.
454 * @param parent parent object of the collection
455 * @param sublist underlying container to expose
456 * @param backing pointer to backing list for children, if any
457 * @param ins_fence a marker designating where new children of this type should be added
459 XMLObjectChildrenList(
462 typename std::list<_Ty*>* backing,
463 typename std::list<_Ty*>::iterator ins_fence
464 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
469 size_type size() const {
470 // return length of sequence
471 return m_container.size();
475 // test if sequence is empty
476 return m_container.empty();
480 // return iterator for beginning of mutable sequence
481 return m_container.begin();
485 // return iterator for end of mutable sequence
486 return m_container.end();
489 const_iterator begin() const {
490 // return iterator for beginning of const sequence
491 return const_cast<const Container&>(m_container).begin();
494 const_iterator end() const {
495 // return iterator for end of const sequence
496 return const_cast<const Container&>(m_container).end();
499 const_reference at(size_type _Pos) const {
500 // subscript nonmutable sequence with checking
501 return m_container.at(_Pos);
504 const_reference operator[](size_type _Pos) const {
505 // subscript nonmutable sequence
506 return m_container[_Pos];
509 const_reference front() const {
510 // return first element of nonmutable sequence
511 return m_container.front();
514 const_reference back() const {
515 // return last element of nonmutable sequence
516 return m_container.back();
519 void push_back(const_reference _Val) {
522 m_list->insert(m_fence,_Val);
523 m_container.push_back(_Val);
526 iterator erase(iterator _Where) {
527 removeParent(*_Where);
529 removeChild(*_Where);
531 delete *_Where.m_iter;
532 return m_container.erase(_Where.m_iter);
535 iterator erase(iterator _First, iterator _Last) {
536 for (iterator i=_First; i!=_Last; i++) {
543 return m_container.erase(_First.m_iter,_Last.m_iter);
547 erase(begin(),end());
551 void setParent(const_reference _Val) {
552 if (_Val->getParent())
553 throw XMLObjectException("Child object already has a parent.");
554 _Val->setParent(m_parent);
555 _Val->releaseParentDOM(true);
558 void removeParent(const_reference _Val) {
559 if (_Val->getParent()!=m_parent)
560 throw XMLObjectException("Child object not owned by this parent.");
561 _Val->setParent(NULL);
562 m_parent->releaseParentDOM(true);
565 void removeChild(const_reference _Val) {
566 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
578 * STL-compatible container that mediates access to underlying lists of typed XML children
579 * that come in pairs.
581 * @param _Tx the subtype container to encapsulate
582 * @param _Ty the base type in the underlying list (defaults to XMLObject)
584 template <class Container, class _Ty>
585 class XMLObjectPairList
587 Container& m_container;
588 typename std::list<_Ty*>* m_list;
589 typename std::list<_Ty*>::iterator m_fence;
594 typedef typename Container::value_type value_type;
595 typedef typename Container::reference reference;
596 typedef typename Container::const_reference const_reference;
597 typedef typename Container::difference_type difference_type;
598 typedef typename Container::size_type size_type;
600 // We override the iterator types with our constrained wrapper.
601 typedef XMLObjectChildrenIterator<Container, typename Container::iterator> iterator;
602 typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> const_iterator;
606 * Constructor to expose a typed collection of pairs backed by a list of a base type.
608 * @param parent parent object of the collection
609 * @param sublist underlying container to expose
610 * @param backing pointer to backing list for children, if any
611 * @param ins_fence a marker designating where new children of this type should be added
616 typename std::list<_Ty*>* backing,
617 typename std::list<_Ty*>::iterator ins_fence
618 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
623 size_type size() const {
624 // return length of sequence
625 return m_container.size();
629 // test if sequence is empty
630 return m_container.empty();
634 // return iterator for beginning of mutable sequence
635 return m_container.begin();
639 // return iterator for end of mutable sequence
640 return m_container.end();
643 const_iterator begin() const {
644 // return iterator for beginning of const sequence
645 return const_cast<const Container&>(m_container).begin();
648 const_iterator end() const {
649 // return iterator for end of const sequence
650 return const_cast<const Container&>(m_container).end();
653 const_reference at(size_type _Pos) const {
654 // subscript nonmutable sequence with checking
655 return m_container.at(_Pos);
658 const_reference operator[](size_type _Pos) const {
659 // subscript nonmutable sequence
660 return m_container[_Pos];
663 const_reference front() const {
664 // return first element of nonmutable sequence
665 return m_container.front();
668 const_reference back() const {
669 // return last element of nonmutable sequence
670 return m_container.back();
673 void push_back(const_reference _Val) {
676 m_list->insert(m_fence,_Val.first);
677 m_list->insert(m_fence,_Val.second);
679 m_container.push_back(_Val);
682 iterator erase(iterator _Where) {
683 removeParent(*_Where);
685 removeChild(*_Where);
687 delete _Where.m_iter->first;
688 delete _Where.m_iter->second;
690 return m_container.erase(_Where.m_iter);
693 iterator erase(iterator _First, iterator _Last) {
694 for (iterator i=_First; i!=_Last; i++) {
699 delete i.m_iter->first;
700 delete i.m_iter->second;
703 return m_container.erase(_First,_Last);
707 erase(begin(),end());
711 void setParent(const_reference _Val) {
712 if (_Val.first->getParent() || (_Val.second && _Val.second->getParent()))
713 throw XMLObjectException("One of the child objects already has a parent.");
714 _Val.first->setParent(m_parent);
716 _Val.second->setParent(m_parent);
717 _Val.first->releaseParentDOM(true);
720 void removeParent(const_reference _Val) {
721 if (_Val.first->getParent()!=m_parent || (_Val.second && _Val.second->getParent()!=m_parent))
722 throw XMLObjectException("One of the child objects not owned by this parent.");
723 _Val.first->setParent(NULL);
725 _Val.second->setParent(NULL);
726 m_parent->releaseParentDOM(true);
729 void removeChild(const_reference _Val) {
730 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
731 if ((*i)==_Val.first) {
732 typename std::list<_Ty*>::iterator j=i++;
747 #endif /* __xmltooling_list_h__ */