2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * @file xmltooling/util/XMLObjectChildrenList.h
24 * STL-compatible container wrapper.
27 #ifndef __xmltooling_list_h__
28 #define __xmltooling_list_h__
30 #include <xmltooling/exceptions.h>
31 #include <xmltooling/XMLObject.h>
36 * Shorthand for an XMLObjectChildrenList wrapped around a vector
38 * @param type the type of object in the vector
40 #define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector<type*> >
43 * Shorthand for an XMLObjectChildrenList wrapped around a list
45 * @param type the type of object in the list
47 #define ListOf(type) xmltooling::XMLObjectChildrenList< std::list<type*> >
50 * Shorthand for an XMLObjectChildrenList wrapped around a deque
52 * @param type the type of object in the deque
54 #define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque<type*> >
57 * Shorthand for an XMLObjectPairList wrapped around a vector
59 * @param type1 the first type of object in the vector
60 * @param type2 the second type of object in the vector
62 #define VectorOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::vector< std::pair<type1*,type2*> > >
65 * Shorthand for an XMLObjectPairList wrapped around a list
67 * @param type1 the first type of object in the vector
68 * @param type2 the second type of object in the vector
70 #define ListOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::list< std::pair<type1*,type2*> > >
73 * Shorthand for an XMLObjectPairList wrapped around a deque
75 * @param type1 the first type of object in the vector
76 * @param type2 the second type of object in the vector
78 #define DequeOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::deque< std::pair<type1*,type2*> > >
80 namespace xmltooling {
83 template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
84 template <class _Tx, class _Ty=XMLObject> class XMLObjectPairList;
87 * STL iterator that mediates access to an iterator over typed XML children.
89 * @param Container type of container
90 * @param _Ty a bidrectional iterator to guard
92 template <class Container, typename _Ty>
93 class XMLObjectChildrenIterator
97 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
98 template <class _Tx, class _Tz> friend class XMLObjectPairList;
100 #ifdef HAVE_ITERATOR_TRAITS
101 typedef typename std::iterator_traits<_Ty>::iterator_category iterator_category;
102 typedef typename std::iterator_traits<_Ty>::value_type value_type;
103 typedef typename std::iterator_traits<_Ty>::difference_type difference_type;
104 typedef typename std::iterator_traits<_Ty>::pointer pointer;
105 typedef typename std::iterator_traits<_Ty>::reference reference;
107 typedef typename _Ty::iterator_category iterator_category;
108 typedef typename _Ty::value_type value_type;
109 typedef typename _Ty::difference_type difference_type;
110 typedef typename _Ty::pointer pointer;
111 typedef typename _Ty::reference reference;
113 typedef typename Container::const_reference const_reference;
114 typedef typename Container::const_pointer const_pointer;
116 XMLObjectChildrenIterator() {
119 XMLObjectChildrenIterator(_Ty iter) {
123 const_reference operator*() const {
127 const_reference operator->() const {
131 XMLObjectChildrenIterator& operator++() {
137 XMLObjectChildrenIterator& operator--() {
143 XMLObjectChildrenIterator operator++(int) {
145 XMLObjectChildrenIterator _Tmp = *this;
150 XMLObjectChildrenIterator operator--(int) {
152 XMLObjectChildrenIterator _Tmp = *this;
157 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
158 // increment by integer
163 XMLObjectChildrenIterator operator+(difference_type _Off) const {
164 // return this + integer
165 return m_iter + _Off;
168 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
169 // decrement by integer
170 return (*this += -_Off);
173 XMLObjectChildrenIterator operator-(difference_type _Off) const {
174 // return this - integer
175 XMLObjectChildrenIterator _Tmp = *this;
176 return (_Tmp -= _Off);
179 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
180 // return difference of iterators
181 return m_iter - _Right.m_iter;
184 const_reference operator[](difference_type _Off) const {
186 return (*(*this + _Off));
189 bool operator==(const XMLObjectChildrenIterator &_Right) const {
190 // test for iterator equality
191 return (m_iter == _Right.m_iter);
194 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
195 // test for iterator inequality
196 return (!(m_iter == _Right.m_iter));
199 bool operator<(const XMLObjectChildrenIterator &_Right) const {
200 return (m_iter < _Right.m_iter);
205 #ifndef HAVE_ITERATOR_TRAITS
207 * STL iterator that mediates access to an iterator that's a pointer.
209 * @param Container type of container
210 * @param _Ty the type of object being referenced
212 template <class Container, typename _Ty>
213 class XMLObjectChildrenIterator<Container, _Ty*>
216 typename _Ty* m_iter;
217 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
218 template <class _Tx, class _Tz> friend class XMLObjectPairList;
220 typedef std::random_access_iterator_tag iterator_category;
221 typedef _Ty value_type;
222 typedef ptrdiff_t difference_type;
223 typedef _Ty* pointer;
224 typedef _Ty& reference;
225 typedef const _Ty& const_reference;
226 typedef const _Ty* const_pointer;
228 XMLObjectChildrenIterator() {
231 XMLObjectChildrenIterator(_Ty* iter) {
235 const_reference operator*() const {
239 const_reference operator->() const {
243 XMLObjectChildrenIterator& operator++() {
249 XMLObjectChildrenIterator& operator--() {
255 XMLObjectChildrenIterator operator++(int) {
257 XMLObjectChildrenIterator _Tmp = *this;
262 XMLObjectChildrenIterator operator--(int) {
264 XMLObjectChildrenIterator _Tmp = *this;
269 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
270 // increment by integer
275 XMLObjectChildrenIterator operator+(difference_type _Off) const {
276 // return this + integer
277 return m_iter + _Off;
280 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
281 // decrement by integer
282 return (*this += -_Off);
285 XMLObjectChildrenIterator operator-(difference_type _Off) const {
286 // return this - integer
287 XMLObjectChildrenIterator _Tmp = *this;
288 return (_Tmp -= _Off);
291 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
292 // return difference of iterators
293 return m_iter - _Right.m_iter;
296 const_reference operator[](difference_type _Off) const {
298 return (*(*this + _Off));
301 bool operator==(const XMLObjectChildrenIterator &_Right) const {
302 // test for iterator equality
303 return (m_iter == _Right.m_iter);
306 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
307 // test for iterator inequality
308 return (!(m_iter == _Right.m_iter));
311 bool operator<(const XMLObjectChildrenIterator &_Right) const {
312 return (m_iter < _Right.m_iter);
318 * STL iterator that mediates access to an iterator that's a const pointer.
320 * @param Container type of container
321 * @param _Ty the type of object being referenced
323 template <class Container, typename _Ty>
324 class XMLObjectChildrenIterator<Container, const _Ty*>
327 typename const _Ty* m_iter;
328 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
329 template <class _Tx, class _Tz> friend class XMLObjectPairList;
331 typedef std::random_access_iterator_tag iterator_category;
332 typedef _Ty value_type;
333 typedef ptrdiff_t difference_type;
334 typedef const _Ty* pointer;
335 typedef const _Ty& reference;
336 typedef const _Ty& const_reference;
337 typedef const _Ty* const_pointer;
339 XMLObjectChildrenIterator() {
342 XMLObjectChildrenIterator(_Ty* iter) {
346 const_reference operator*() const {
350 const_reference operator->() const {
354 XMLObjectChildrenIterator& operator++() {
360 XMLObjectChildrenIterator& operator--() {
366 XMLObjectChildrenIterator operator++(int) {
368 XMLObjectChildrenIterator _Tmp = *this;
373 XMLObjectChildrenIterator operator--(int) {
375 XMLObjectChildrenIterator _Tmp = *this;
380 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
381 // increment by integer
386 XMLObjectChildrenIterator operator+(difference_type _Off) const {
387 // return this + integer
388 return m_iter + _Off;
391 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
392 // decrement by integer
393 return (*this += -_Off);
396 XMLObjectChildrenIterator operator-(difference_type _Off) const {
397 // return this - integer
398 XMLObjectChildrenIterator _Tmp = *this;
399 return (_Tmp -= _Off);
402 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
403 // return difference of iterators
404 return m_iter - _Right.m_iter;
407 const_reference operator[](difference_type _Off) const {
409 return (*(*this + _Off));
412 bool operator==(const XMLObjectChildrenIterator &_Right) const {
413 // test for iterator equality
414 return (m_iter == _Right.m_iter);
417 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
418 // test for iterator inequality
419 return (!(m_iter == _Right.m_iter));
422 bool operator<(const XMLObjectChildrenIterator &_Right) const {
423 return (m_iter < _Right.m_iter);
430 * STL-compatible container that mediates access to underlying lists of typed XML children.
431 * @param _Tx the subtype container to encapsulate
432 * @param _Ty the base type in the underlying list (defaults to XMLObject)
434 template <class Container, class _Ty>
435 class XMLObjectChildrenList
437 Container& m_container;
438 typename std::list<_Ty*>* m_list;
439 typename std::list<_Ty*>::iterator m_fence;
444 typedef typename Container::value_type value_type;
445 typedef typename Container::reference reference;
446 typedef typename Container::const_reference const_reference;
447 typedef typename Container::difference_type difference_type;
448 typedef typename Container::size_type size_type;
450 // We override the iterator types with our constrained wrapper.
451 typedef XMLObjectChildrenIterator<Container, typename Container::iterator> iterator;
452 typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> const_iterator;
456 * Constructor to expose a typed collection of children backed by a list of a base type.
458 * @param parent parent object of the collection
459 * @param sublist underlying container to expose
460 * @param backing pointer to backing list for children, if any
461 * @param ins_fence a marker designating where new children of this type should be added
463 XMLObjectChildrenList(
466 typename std::list<_Ty*>* backing,
467 typename std::list<_Ty*>::iterator ins_fence
468 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
473 size_type size() const {
474 // return length of sequence
475 return m_container.size();
479 // test if sequence is empty
480 return m_container.empty();
484 // return iterator for beginning of mutable sequence
485 return m_container.begin();
489 // return iterator for end of mutable sequence
490 return m_container.end();
493 const_iterator begin() const {
494 // return iterator for beginning of const sequence
495 return const_cast<const Container&>(m_container).begin();
498 const_iterator end() const {
499 // return iterator for end of const sequence
500 return const_cast<const Container&>(m_container).end();
503 const_reference at(size_type _Pos) const {
504 // subscript nonmutable sequence with checking
505 return m_container.at(_Pos);
508 const_reference operator[](size_type _Pos) const {
509 // subscript nonmutable sequence
510 return m_container[_Pos];
513 const_reference front() const {
514 // return first element of nonmutable sequence
515 return m_container.front();
518 const_reference back() const {
519 // return last element of nonmutable sequence
520 return m_container.back();
523 void push_back(const_reference _Val) {
526 m_list->insert(m_fence,_Val);
527 m_container.push_back(_Val);
530 iterator erase(iterator _Where) {
531 removeParent(*_Where);
533 removeChild(*_Where);
535 delete *_Where.m_iter;
536 return m_container.erase(_Where.m_iter);
539 iterator erase(iterator _First, iterator _Last) {
540 for (iterator i=_First; i!=_Last; i++) {
547 return m_container.erase(_First.m_iter,_Last.m_iter);
551 erase(begin(),end());
555 void setParent(const_reference _Val) {
556 if (_Val->getParent())
557 throw XMLObjectException("Child object already has a parent.");
558 _Val->setParent(m_parent);
559 _Val->releaseParentDOM(true);
562 void removeParent(const_reference _Val) {
563 if (_Val->getParent()!=m_parent)
564 throw XMLObjectException("Child object not owned by this parent.");
565 _Val->setParent(nullptr);
566 m_parent->releaseParentDOM(true);
569 void removeChild(const_reference _Val) {
570 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
582 * STL-compatible container that mediates access to underlying lists of typed XML children
583 * that come in pairs.
585 * @param _Tx the subtype container to encapsulate
586 * @param _Ty the base type in the underlying list (defaults to XMLObject)
588 template <class Container, class _Ty>
589 class XMLObjectPairList
591 Container& m_container;
592 typename std::list<_Ty*>* m_list;
593 typename std::list<_Ty*>::iterator m_fence;
598 typedef typename Container::value_type value_type;
599 typedef typename Container::reference reference;
600 typedef typename Container::const_reference const_reference;
601 typedef typename Container::difference_type difference_type;
602 typedef typename Container::size_type size_type;
604 // We override the iterator types with our constrained wrapper.
605 typedef XMLObjectChildrenIterator<Container, typename Container::iterator> iterator;
606 typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> const_iterator;
610 * Constructor to expose a typed collection of pairs backed by a list of a base type.
612 * @param parent parent object of the collection
613 * @param sublist underlying container to expose
614 * @param backing pointer to backing list for children, if any
615 * @param ins_fence a marker designating where new children of this type should be added
620 typename std::list<_Ty*>* backing,
621 typename std::list<_Ty*>::iterator ins_fence
622 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
627 size_type size() const {
628 // return length of sequence
629 return m_container.size();
633 // test if sequence is empty
634 return m_container.empty();
638 // return iterator for beginning of mutable sequence
639 return m_container.begin();
643 // return iterator for end of mutable sequence
644 return m_container.end();
647 const_iterator begin() const {
648 // return iterator for beginning of const sequence
649 return const_cast<const Container&>(m_container).begin();
652 const_iterator end() const {
653 // return iterator for end of const sequence
654 return const_cast<const Container&>(m_container).end();
657 const_reference at(size_type _Pos) const {
658 // subscript nonmutable sequence with checking
659 return m_container.at(_Pos);
662 const_reference operator[](size_type _Pos) const {
663 // subscript nonmutable sequence
664 return m_container[_Pos];
667 const_reference front() const {
668 // return first element of nonmutable sequence
669 return m_container.front();
672 const_reference back() const {
673 // return last element of nonmutable sequence
674 return m_container.back();
677 void push_back(const_reference _Val) {
680 m_list->insert(m_fence,_Val.first);
681 m_list->insert(m_fence,_Val.second);
683 m_container.push_back(_Val);
686 iterator erase(iterator _Where) {
687 removeParent(*_Where);
689 removeChild(*_Where);
691 delete _Where.m_iter->first;
692 delete _Where.m_iter->second;
694 return m_container.erase(_Where.m_iter);
697 iterator erase(iterator _First, iterator _Last) {
698 for (iterator i=_First; i!=_Last; i++) {
703 delete i.m_iter->first;
704 delete i.m_iter->second;
707 return m_container.erase(_First,_Last);
711 erase(begin(),end());
715 void setParent(const_reference _Val) {
716 if (_Val.first->getParent() || (_Val.second && _Val.second->getParent()))
717 throw XMLObjectException("One of the child objects already has a parent.");
718 _Val.first->setParent(m_parent);
720 _Val.second->setParent(m_parent);
721 _Val.first->releaseParentDOM(true);
724 void removeParent(const_reference _Val) {
725 if (_Val.first->getParent()!=m_parent || (_Val.second && _Val.second->getParent()!=m_parent))
726 throw XMLObjectException("One of the child objects not owned by this parent.");
727 _Val.first->setParent(nullptr);
729 _Val.second->setParent(nullptr);
730 m_parent->releaseParentDOM(true);
733 void removeChild(const_reference _Val) {
734 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
735 if ((*i)==_Val.first) {
736 typename std::list<_Ty*>::iterator j=i++;
751 #endif /* __xmltooling_list_h__ */