/*
- * Copyright 2001-2006 Internet2
+ * Copyright 2001-2007 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
/**
- * @file XMLObjectChildrenList.h
+ * @file xmltooling/util/XMLObjectChildrenList.h
*
* STL-compatible container wrapper
*/
-#if !defined(__xmltooling_list_h__)
+#ifndef __xmltooling_list_h__
#define __xmltooling_list_h__
-#include <xmltooling/DOMCachingXMLObject.h>
#include <xmltooling/exceptions.h>
+#include <xmltooling/XMLObject.h>
+#include <list>
+
+/**
+ * Shorthand for an XMLObjectChildrenList wrapped around a vector
+ *
+ * @param type the type of object in the vector
+ */
#define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector<type*> >
+
+/**
+ * Shorthand for an XMLObjectChildrenList wrapped around a list
+ *
+ * @param type the type of object in the list
+ */
#define ListOf(type) xmltooling::XMLObjectChildrenList< std::list<type*> >
+
+/**
+ * Shorthand for an XMLObjectChildrenList wrapped around a deque
+ *
+ * @param type the type of object in the deque
+ */
#define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque<type*> >
+/**
+ * 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<type1*,type2*> > >
+
+/**
+ * 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<type1*,type2*> > >
+
+/**
+ * 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<type1*,type2*> > >
+
namespace xmltooling {
// Forward reference
template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
+ template <class _Tx, class _Ty=XMLObject> 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 <class _Ty>
+ template <class Container, typename _Ty>
class XMLObjectChildrenIterator
{
- typename _Ty::iterator m_iter;
+ /// @cond OFF
+ _Ty m_iter;
+ template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
+ template <class _Tx, class _Tz> friend class XMLObjectPairList;
+ public:
+#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(_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
+ };
+
+#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 Container, typename _Ty>
+ class XMLObjectChildrenIterator<Container, _Ty*>
+ {
+ /// @cond OFF
+ typename _Ty* m_iter;
template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
+ template <class _Tx, class _Tz> 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;
+ 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(typename _Ty::iterator iter) {
+ XMLObjectChildrenIterator(_Ty* iter) {
m_iter=iter;
}
}
const_reference operator->() const {
- return *(m_iter.operator->());
+ return *m_iter;
}
XMLObjectChildrenIterator& operator++() {
// 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 Container, typename _Ty>
+ class XMLObjectChildrenIterator<Container, const _Ty*>
+ {
+ /// @cond OFF
+ typename const _Ty* m_iter;
+ template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
+ template <class _Tx, class _Tz> 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;
+ ++*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
+ };
+#endif
+
+ /**
* STL-compatible container that mediates access to underlying lists of typed XML children.
* @param _Tx the subtype container to encapsulate
* @param _Ty the base type in the underlying list (defaults to XMLObject)
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::size_type size_type;
// We override the iterator types with our constrained wrapper.
- typedef XMLObjectChildrenIterator<Container> iterator;
- typedef XMLObjectChildrenIterator<Container> const_iterator;
+ typedef XMLObjectChildrenIterator<Container, typename Container::iterator> iterator;
+ typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> const_iterator;
+ /// @endcond
/**
* Constructor to expose a typed collection of children backed by a list of a base type.
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();
const_iterator begin() const {
// return iterator for beginning of const sequence
- return m_container.begin();
+ return const_cast<const Container&>(m_container).begin();
}
const_iterator end() const {
// return iterator for end of const sequence
- return m_container.end();
+ return const_cast<const Container&>(m_container).end();
}
const_reference at(size_type _Pos) const {
else
delete *i.m_iter;
}
- return m_container.erase(_First,_Last);
+ return m_container.erase(_First.m_iter,_Last.m_iter);
}
void clear() {
if (_Val->getParent())
throw XMLObjectException("Child object already has a parent.");
_Val->setParent(m_parent);
- DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(_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<DOMCachingXMLObject*>(m_parent);
- if (dc) {
- dc->releaseParentDOM(true);
- }
+ m_parent->releaseParentDOM(true);
}
void removeChild(const_reference _Val) {
}
}
}
+ /// @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 Container, class _Ty>
+ 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<Container, typename Container::iterator> iterator;
+ typedef XMLObjectChildrenIterator<Container, typename Container::const_iterator> 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<const Container&>(m_container).begin();
+ }
+
+ const_iterator end() const {
+ // return iterator for end of const sequence
+ return const_cast<const Container&>(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(NULL);
+ if (_Val.second)
+ _Val.second->setParent(NULL);
+ 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
};
};