X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Futil%2FXMLObjectChildrenList.h;h=837d83eec544bd9a8d67d07983a1673a96c47f46;hb=81b488b2790e7bdeb2f43560b1d4a7d22c3dfdf5;hp=91cda640c707425624334701afee700910e4ef32;hpb=b3ed0767e4769c803e8e194f0634c7f83f3f1eeb;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/util/XMLObjectChildrenList.h b/xmltooling/util/XMLObjectChildrenList.h index 91cda64..837d83e 100644 --- a/xmltooling/util/XMLObjectChildrenList.h +++ b/xmltooling/util/XMLObjectChildrenList.h @@ -1,62 +1,122 @@ -/* - * Copyright 2001-2006 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. */ /** - * @file XMLObjectChildrenList.h + * @file xmltooling/util/XMLObjectChildrenList.h * - * STL-compatible container wrapper + * STL-compatible container wrapper. */ -#if !defined(__xmltooling_list_h__) +#ifndef __xmltooling_list_h__ #define __xmltooling_list_h__ -#include #include +#include +#include + +/** + * Shorthand for an XMLObjectChildrenList wrapped around a vector + * + * @param type the type of object in the vector + */ #define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector > + +/** + * Shorthand for an XMLObjectChildrenList wrapped around a list + * + * @param type the type of object in the list + */ #define ListOf(type) xmltooling::XMLObjectChildrenList< std::list > + +/** + * Shorthand for an XMLObjectChildrenList wrapped around a deque + * + * @param type the type of object in the deque + */ #define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque > +/** + * Shorthand for an XMLObjectPairList wrapped around a vector + * + * @param type1 the first type of object in the vector + * @param type2 the second type of object in the vector + */ +#define VectorOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::vector< std::pair > > + +/** + * Shorthand for an XMLObjectPairList wrapped around a list + * + * @param type1 the first type of object in the vector + * @param type2 the second type of object in the vector + */ +#define ListOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::list< std::pair > > + +/** + * Shorthand for an XMLObjectPairList wrapped around a deque + * + * @param type1 the first type of object in the vector + * @param type2 the second type of object in the vector + */ +#define DequeOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::deque< std::pair > > + namespace xmltooling { // Forward reference template class XMLObjectChildrenList; + template class XMLObjectPairList; /** * STL iterator that mediates access to an iterator over typed XML children. - * @param _Ty a bidrectional sequence of the subtype to iterate over + * + * @param Container type of container + * @param _Ty a bidrectional iterator to guard */ - template + template class XMLObjectChildrenIterator { - typename _Ty::iterator m_iter; + /// @cond OFF + _Ty m_iter; template friend class XMLObjectChildrenList; + template friend class XMLObjectPairList; public: - typedef typename _Ty::iterator::iterator_category iterator_category; - typedef typename _Ty::iterator::value_type value_type; - typedef typename _Ty::iterator::reference reference; - typedef typename _Ty::iterator::pointer pointer; - typedef typename _Ty::const_iterator::reference const_reference; - typedef typename _Ty::const_iterator::pointer const_pointer; - typedef typename _Ty::iterator::difference_type difference_type; +#ifdef HAVE_ITERATOR_TRAITS + typedef typename std::iterator_traits<_Ty>::iterator_category iterator_category; + typedef typename std::iterator_traits<_Ty>::value_type value_type; + typedef typename std::iterator_traits<_Ty>::difference_type difference_type; + typedef typename std::iterator_traits<_Ty>::pointer pointer; + typedef typename std::iterator_traits<_Ty>::reference reference; +#else + typedef typename _Ty::iterator_category iterator_category; + typedef typename _Ty::value_type value_type; + typedef typename _Ty::difference_type difference_type; + typedef typename _Ty::pointer pointer; + typedef typename _Ty::reference reference; +#endif + typedef typename Container::const_reference const_reference; + typedef typename Container::const_pointer const_pointer; XMLObjectChildrenIterator() { } - XMLObjectChildrenIterator(typename _Ty::iterator iter) { + XMLObjectChildrenIterator(_Ty iter) { m_iter=iter; } @@ -65,7 +125,7 @@ namespace xmltooling { } const_reference operator->() const { - return *(m_iter.operator->()); + return *m_iter; } XMLObjectChildrenIterator& operator++() { @@ -102,8 +162,230 @@ namespace xmltooling { XMLObjectChildrenIterator operator+(difference_type _Off) const { // return this + integer + return m_iter + _Off; + } + + XMLObjectChildrenIterator& operator-=(difference_type _Off) { + // decrement by integer + return (*this += -_Off); + } + + XMLObjectChildrenIterator operator-(difference_type _Off) const { + // return this - integer + XMLObjectChildrenIterator _Tmp = *this; + return (_Tmp -= _Off); + } + + difference_type operator-(const XMLObjectChildrenIterator& _Right) const { + // return difference of iterators + return m_iter - _Right.m_iter; + } + + const_reference operator[](difference_type _Off) const { + // subscript + return (*(*this + _Off)); + } + + bool operator==(const XMLObjectChildrenIterator &_Right) const { + // test for iterator equality + return (m_iter == _Right.m_iter); + } + + bool operator!=(const XMLObjectChildrenIterator &_Right) const { + // test for iterator inequality + return (!(m_iter == _Right.m_iter)); + } + + bool operator<(const XMLObjectChildrenIterator &_Right) const { + return (m_iter < _Right.m_iter); + } + /// @endcond + }; + +#ifndef HAVE_ITERATOR_TRAITS + /** + * STL iterator that mediates access to an iterator that's a pointer. + * + * @param Container type of container + * @param _Ty the type of object being referenced + */ + template + class XMLObjectChildrenIterator + { + /// @cond OFF + typename _Ty* m_iter; + template friend class XMLObjectChildrenList; + template friend class XMLObjectPairList; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef _Ty value_type; + typedef ptrdiff_t difference_type; + typedef _Ty* pointer; + typedef _Ty& reference; + typedef const _Ty& const_reference; + typedef const _Ty* const_pointer; + + XMLObjectChildrenIterator() { + } + + XMLObjectChildrenIterator(_Ty* iter) { + m_iter=iter; + } + + const_reference operator*() const { + return *m_iter; + } + + const_reference operator->() const { + return *m_iter; + } + + XMLObjectChildrenIterator& operator++() { + // preincrement + ++m_iter; + return (*this); + } + + XMLObjectChildrenIterator& operator--() { + // predecrement + --m_iter; + return (*this); + } + + XMLObjectChildrenIterator operator++(int) { + // postincrement + XMLObjectChildrenIterator _Tmp = *this; + ++*this; + return (_Tmp); + } + + XMLObjectChildrenIterator operator--(int) { + // postdecrement + XMLObjectChildrenIterator _Tmp = *this; + --*this; + return (_Tmp); + } + + XMLObjectChildrenIterator& operator+=(difference_type _Off) { + // increment by integer + m_iter += _Off; + return (*this); + } + + XMLObjectChildrenIterator operator+(difference_type _Off) const { + // return this + integer + return m_iter + _Off; + } + + XMLObjectChildrenIterator& operator-=(difference_type _Off) { + // decrement by integer + return (*this += -_Off); + } + + XMLObjectChildrenIterator operator-(difference_type _Off) const { + // return this - integer + XMLObjectChildrenIterator _Tmp = *this; + return (_Tmp -= _Off); + } + + difference_type operator-(const XMLObjectChildrenIterator& _Right) const { + // return difference of iterators + return m_iter - _Right.m_iter; + } + + const_reference operator[](difference_type _Off) const { + // subscript + return (*(*this + _Off)); + } + + bool operator==(const XMLObjectChildrenIterator &_Right) const { + // test for iterator equality + return (m_iter == _Right.m_iter); + } + + bool operator!=(const XMLObjectChildrenIterator &_Right) const { + // test for iterator inequality + return (!(m_iter == _Right.m_iter)); + } + + bool operator<(const XMLObjectChildrenIterator &_Right) const { + return (m_iter < _Right.m_iter); + } + /// @endcond + }; + + /** + * STL iterator that mediates access to an iterator that's a const pointer. + * + * @param Container type of container + * @param _Ty the type of object being referenced + */ + template + class XMLObjectChildrenIterator + { + /// @cond OFF + typename const _Ty* m_iter; + template friend class XMLObjectChildrenList; + template friend class XMLObjectPairList; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef _Ty value_type; + typedef ptrdiff_t difference_type; + typedef const _Ty* pointer; + typedef const _Ty& reference; + typedef const _Ty& const_reference; + typedef const _Ty* const_pointer; + + XMLObjectChildrenIterator() { + } + + XMLObjectChildrenIterator(_Ty* iter) { + m_iter=iter; + } + + const_reference operator*() const { + return *m_iter; + } + + const_reference operator->() const { + return *m_iter; + } + + XMLObjectChildrenIterator& operator++() { + // preincrement + ++m_iter; + return (*this); + } + + XMLObjectChildrenIterator& operator--() { + // predecrement + --m_iter; + return (*this); + } + + XMLObjectChildrenIterator operator++(int) { + // postincrement XMLObjectChildrenIterator _Tmp = *this; - return (_Tmp += _Off); + ++*this; + return (_Tmp); + } + + XMLObjectChildrenIterator operator--(int) { + // postdecrement + XMLObjectChildrenIterator _Tmp = *this; + --*this; + return (_Tmp); + } + + XMLObjectChildrenIterator& operator+=(difference_type _Off) { + // increment by integer + m_iter += _Off; + return (*this); + } + + XMLObjectChildrenIterator operator+(difference_type _Off) const { + // return this + integer + return m_iter + _Off; } XMLObjectChildrenIterator& operator-=(difference_type _Off) { @@ -136,7 +418,13 @@ namespace xmltooling { // test for iterator inequality return (!(m_iter == _Right.m_iter)); } + + bool operator<(const XMLObjectChildrenIterator &_Right) const { + return (m_iter < _Right.m_iter); + } + /// @endcond }; +#endif /** * STL-compatible container that mediates access to underlying lists of typed XML children. @@ -146,12 +434,13 @@ namespace xmltooling { template class XMLObjectChildrenList { - typename Container& m_container; + Container& m_container; typename std::list<_Ty*>* m_list; typename std::list<_Ty*>::iterator m_fence; XMLObject* m_parent; public: + /// @cond OFF typedef typename Container::value_type value_type; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; @@ -159,8 +448,9 @@ namespace xmltooling { typedef typename Container::size_type size_type; // We override the iterator types with our constrained wrapper. - typedef XMLObjectChildrenIterator iterator; - typedef const XMLObjectChildrenIterator const_iterator; + typedef XMLObjectChildrenIterator iterator; + typedef XMLObjectChildrenIterator const_iterator; + /// @endcond /** * Constructor to expose a typed collection of children backed by a list of a base type. @@ -175,9 +465,11 @@ namespace xmltooling { Container& sublist, typename std::list<_Ty*>* backing, typename std::list<_Ty*>::iterator ins_fence - ) : m_parent(parent), m_container(sublist), m_list(backing), m_fence(ins_fence) { + ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) { } + /// @cond OFF + size_type size() const { // return length of sequence return m_container.size(); @@ -200,12 +492,12 @@ namespace xmltooling { const_iterator begin() const { // return iterator for beginning of const sequence - return m_container.begin(); + return const_cast(m_container).begin(); } const_iterator end() const { // return iterator for end of const sequence - return m_container.end(); + return const_cast(m_container).end(); } const_reference at(size_type _Pos) const { @@ -239,6 +531,8 @@ namespace xmltooling { removeParent(*_Where); if (m_list) removeChild(*_Where); + else + delete *_Where.m_iter; return m_container.erase(_Where.m_iter); } @@ -247,8 +541,10 @@ namespace xmltooling { removeParent(*i); if (m_list) removeChild(*i); + else + delete *i.m_iter; } - return m_container.erase(_First,_Last); + return m_container.erase(_First.m_iter,_Last.m_iter); } void clear() { @@ -260,20 +556,14 @@ namespace xmltooling { if (_Val->getParent()) throw XMLObjectException("Child object already has a parent."); _Val->setParent(m_parent); - DOMCachingXMLObject* dc=dynamic_cast(_Val); - if (dc) { - dc->releaseParentDOM(true); - } + _Val->releaseParentDOM(true); } void removeParent(const_reference _Val) { if (_Val->getParent()!=m_parent) throw XMLObjectException("Child object not owned by this parent."); - _Val->setParent(NULL); - DOMCachingXMLObject* dc=dynamic_cast(m_parent); - if (dc) { - dc->releaseParentDOM(true); - } + _Val->setParent(nullptr); + m_parent->releaseParentDOM(true); } void removeChild(const_reference _Val) { @@ -285,6 +575,175 @@ namespace xmltooling { } } } + /// @endcond + }; + + /** + * STL-compatible container that mediates access to underlying lists of typed XML children + * that come in pairs. + * + * @param _Tx the subtype container to encapsulate + * @param _Ty the base type in the underlying list (defaults to XMLObject) + */ + template + class XMLObjectPairList + { + Container& m_container; + typename std::list<_Ty*>* m_list; + typename std::list<_Ty*>::iterator m_fence; + XMLObject* m_parent; + + public: + /// @cond OFF + typedef typename Container::value_type value_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::difference_type difference_type; + typedef typename Container::size_type size_type; + + // We override the iterator types with our constrained wrapper. + typedef XMLObjectChildrenIterator iterator; + typedef XMLObjectChildrenIterator const_iterator; + /// @endcond + + /** + * Constructor to expose a typed collection of pairs backed by a list of a base type. + * + * @param parent parent object of the collection + * @param sublist underlying container to expose + * @param backing pointer to backing list for children, if any + * @param ins_fence a marker designating where new children of this type should be added + */ + XMLObjectPairList( + XMLObject* parent, + Container& sublist, + typename std::list<_Ty*>* backing, + typename std::list<_Ty*>::iterator ins_fence + ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) { + } + + /// @cond OFF + + size_type size() const { + // return length of sequence + return m_container.size(); + } + + bool empty() const { + // test if sequence is empty + return m_container.empty(); + } + + iterator begin() { + // return iterator for beginning of mutable sequence + return m_container.begin(); + } + + iterator end() { + // return iterator for end of mutable sequence + return m_container.end(); + } + + const_iterator begin() const { + // return iterator for beginning of const sequence + return const_cast(m_container).begin(); + } + + const_iterator end() const { + // return iterator for end of const sequence + return const_cast(m_container).end(); + } + + const_reference at(size_type _Pos) const { + // subscript nonmutable sequence with checking + return m_container.at(_Pos); + } + + const_reference operator[](size_type _Pos) const { + // subscript nonmutable sequence + return m_container[_Pos]; + } + + const_reference front() const { + // return first element of nonmutable sequence + return m_container.front(); + } + + const_reference back() const { + // return last element of nonmutable sequence + return m_container.back(); + } + + void push_back(const_reference _Val) { + setParent(_Val); + if (m_list) { + m_list->insert(m_fence,_Val.first); + m_list->insert(m_fence,_Val.second); + } + m_container.push_back(_Val); + } + + iterator erase(iterator _Where) { + removeParent(*_Where); + if (m_list) + removeChild(*_Where); + else { + delete _Where.m_iter->first; + delete _Where.m_iter->second; + } + return m_container.erase(_Where.m_iter); + } + + iterator erase(iterator _First, iterator _Last) { + for (iterator i=_First; i!=_Last; i++) { + removeParent(*i); + if (m_list) + removeChild(*i); + else { + delete i.m_iter->first; + delete i.m_iter->second; + } + } + return m_container.erase(_First,_Last); + } + + void clear() { + erase(begin(),end()); + } + + private: + void setParent(const_reference _Val) { + if (_Val.first->getParent() || (_Val.second && _Val.second->getParent())) + throw XMLObjectException("One of the child objects already has a parent."); + _Val.first->setParent(m_parent); + if (_Val.second) + _Val.second->setParent(m_parent); + _Val.first->releaseParentDOM(true); + } + + void removeParent(const_reference _Val) { + if (_Val.first->getParent()!=m_parent || (_Val.second && _Val.second->getParent()!=m_parent)) + throw XMLObjectException("One of the child objects not owned by this parent."); + _Val.first->setParent(nullptr); + if (_Val.second) + _Val.second->setParent(nullptr); + m_parent->releaseParentDOM(true); + } + + void removeChild(const_reference _Val) { + for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) { + if ((*i)==_Val.first) { + typename std::list<_Ty*>::iterator j=i++; + m_list->erase(j); + m_list->erase(i); + delete _Val.first; + delete _Val.second; + return; + } + i++; + } + } + /// @endcond }; };