// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef RYAI_CHILD_CONTAINER #define RYAI_CHILD_CONTAINER #include "alias_tree_owner.h" ////////////////////////////////////////////////////////////////////////////// // Class made to manage hierarchical objets .. supports IALiasChild interface. ////////////////////////////////////////////////////////////////////////////// template class CCont; ////////////////////////////////////////////////////////////////////////////// // CChild // ////////////////////////////////////////////////////////////////////////////// /// A named based hierarchy child. /** It references an owner, which can change during object lifetime. It also have an index that is the position of the object in owner's container. */ template class CChild { public: explicit CChild(TPrnt* owner, uint32 index = -1); virtual ~CChild() { } /// @name Virtual interface //@{ // virtual std::string getIndexString() const = 0; // virtual std::string getEntityIdString() const { return NLMISC::CEntityId().toString(); } // virtual std::string getOneLineInfoString() const = 0; // virtual std::vector getMultiLineInfoString() const = 0; // virtual std::string getFullName() const = 0; // virtual std::string getName() const = 0; //@} TPrnt* getOwner() const { return _Owner; } void setOwner(TPrnt* owner) { _Owner = owner; } uint32 getChildIndex() const { return _Index; } void setChildIndex(uint32 index) { _Index = index; } private: TPrnt* _Owner; uint32 _Index; }; ////////////////////////////////////////////////////////////////////////////// // CAliasChild // ////////////////////////////////////////////////////////////////////////////// /// A named based aliased hierarchy child. template class CAliasChild : public CChild , public CAliasTreeOwner { public: explicit CAliasChild(TPrnt* owner, CAIAliasDescriptionNode* node); explicit CAliasChild(TPrnt* owner, uint32 alias, std::string const& name); }; ////////////////////////////////////////////////////////////////////////////// // CCont // ////////////////////////////////////////////////////////////////////////////// /// A vector container /// ( indirect use of vector to ensure constraint like Smart Pointers ). template class CCont { public: typedef TChld value_type; /// @name Special iterator skipping NULL elements //@{ class base_iterator : public std::iterator { public: explicit base_iterator() : _cont(NULL) { _index = -1; } base_iterator& operator=(base_iterator const& other) { _index = other._index; _cont = other._cont; return *this; } void operator++() { size_t size = _cont->_Childs.size(); ++_index; while (size_t(_index)<=(size-1) && _cont->_Childs[size_t(_index)]==NULL) ++_index; } void operator--() { size_t size = _cont->_Childs.size(); ++_index; if (_index>=size) _index = size-1; while (_index>=0 && _cont->_Childs[_index]==NULL) --_index; } bool operator==(base_iterator const& other) const { return _index==other._index && _cont==other._cont; } bool operator!=(base_iterator const& other) const { return _index!=other._index || _cont!=other._cont; } protected: explicit base_iterator(CCont const* cont, bool end = false) : _cont(cont) { int size = (int)_cont->_Childs.size(); if (end) { _index = size; } else { _index = 0; while (_index<=(size-1) && !_cont->_Childs[_index]) ++_index; } } explicit base_iterator(CCont const* cont, TChld const* child) : _cont(cont) { if (!child || &child->getOwner()!=_cont) _index = -1; else _index = child->getIndex(); } protected: int _index; CCont const* _cont; }; class iterator : public base_iterator { friend class CCont; public: explicit iterator() : base_iterator() { } TChld* operator*() { return this->_cont->_Childs[this->_index]; } TChld* operator->() const { return this->_cont->_Childs[this->_index]; } iterator& operator=(iterator const& other) { base_iterator::operator=(other); return *this; } bool operator==(iterator const& other) const { return base_iterator::operator==(other); } bool operator!=(iterator const& other) const { return base_iterator::operator!=(other); } private: explicit iterator(CCont* cont, bool end = false) : base_iterator(cont, end) { } explicit iterator(CCont const* cont, TChld const* child) : base_iterator(cont, child) { } }; class const_iterator : public base_iterator { friend class CCont; public: explicit const_iterator() : base_iterator() { } TChld const* operator*() const { return this->_cont->_Childs[this->_index]; } TChld const* operator->() const { return this->_cont->_Childs[this->_index]; } const_iterator& operator=(base_iterator const& other) { base_iterator::operator=(other); return *this; } bool operator==(const_iterator const& other) const { return base_iterator::operator==(other); } bool operator!=(const_iterator const& other) const { return base_iterator::operator!=(other); } private: explicit const_iterator(CCont const* cont, bool end = false) : base_iterator(cont, end) { } explicit const_iterator(CCont const* cont, TChld const* child) : base_iterator(cont, child) { } }; //@} friend class base_iterator; friend class iterator; friend class const_iterator; public: explicit CCont(); virtual ~CCont(); void clear() { _Childs.clear(); } void setChildSize(size_t newSize); TChld* addChild(TChld* child, uint32 index); // Reserved space, not really used. size_t size() const { return _Childs.size(); } TChld* operator[](uint32 index) const { return getChild(index); } void removeChildByIndex(size_t index); TChld* addChild(TChld* child); iterator begin() { return iterator(this); } const_iterator begin() const { return const_iterator(this); } iterator end() { return iterator(this, true); } const_iterator end() const { return const_iterator(this, true); } iterator find(TChld const* child) { return iterator(this, child); } const_iterator find(TChld const* child) const { return const_iterator(this,child); } // :OBSOLETE: TChld* getNextValidChild(TChld* child = NULL); bool isEmpty() const; void swap(CCont& other) { other._Childs.swap(_Childs); } std::vector >& getInternalCont() { return _Childs; } protected: uint32 getFirstFreeChild(); private: TChld* getChild(uint32 index) const; protected: typedef std::vector > TChildCont; TChildCont _Childs; }; ////////////////////////////////////////////////////////////////////////////// // CAliasCont // ////////////////////////////////////////////////////////////////////////////// template class CAliasCont : public CCont , public IAliasCont { public: explicit CAliasCont(); uint32 size() const { return (uint32)this->_Childs.size(); } uint32 getChildIndexByAlias(uint32 alias) const; TChld* getChildByAlias(uint32 alias) const; TChld* getChildByName(std::string const& name) const; CAliasTreeOwner* getAliasChildByAlias(uint32 alias) const; CAliasTreeOwner* addAliasChild(CAliasTreeOwner* child); CAliasTreeOwner* addAliasChild(CAliasTreeOwner* child, uint32 index); void removeChildByAlias(uint32 alias); void removeChildByIndex(uint32 index); }; /****************************************************************************/ /* Inlined methods */ /****************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // CChild // ////////////////////////////////////////////////////////////////////////////// template CChild::CChild(TPrnt* owner, uint32 index) : _Owner(owner) , _Index(index) { } /* template std::string CChild::getOneLineInfoString() const { return std::string("No info available"); } template std::vector CChild::getMultiLineInfoString() const { std::vector container; container.push_back(std::string("No info available")); return container; } */ ////////////////////////////////////////////////////////////////////////////// // CAliasChild // ////////////////////////////////////////////////////////////////////////////// template CAliasChild::CAliasChild(TPrnt* owner, CAIAliasDescriptionNode* node) : CChild(owner) , CAliasTreeOwner(node) { } template CAliasChild::CAliasChild(TPrnt* owner, uint32 alias, std::string const& name) : CChild(owner) , CAliasTreeOwner(alias, name) { } ////////////////////////////////////////////////////////////////////////////// // CCont // ////////////////////////////////////////////////////////////////////////////// template CCont::CCont() { _Childs.resize(0); } template CCont::~CCont() { setChildSize(0); _Childs.clear(); } template void CCont::setChildSize(size_t newSize) { // have to erase some children if (newSize<_Childs.size()) { size_t size = _Childs.size(); for (size_t i=newSize; i()); } template TChld* CCont::addChild(TChld* child, uint32 index) { if (_Childs.size()<=index) { _Childs.resize(index+1, NLMISC::CSmartPtr()); } _Childs[index] = child; if (child) child->setChildIndex(index); return child; } template void CCont::removeChildByIndex(size_t index) { nlassert(index<_Childs.size()); _Childs[index] = NULL; } template TChld* CCont::addChild(TChld* child) { return addChild(child, getFirstFreeChild()); } template TChld* CCont::getNextValidChild(TChld* child) { size_t childCount = _Childs.size(); size_t index = 0; if (child!=NULL) index = child->getChildIndex()+1; for (; index bool CCont::isEmpty() const { size_t childCount = _Childs.size(); size_t index = 0; for (; index uint32 CCont::getFirstFreeChild() { size_t childCount = _Childs.size(); size_t index = 0; for (; index TChld* CCont::getChild(uint32 index) const { if (index >= _Childs.size()) return NULL; return _Childs[index]; } ////////////////////////////////////////////////////////////////////////////// // CAliasCont // ////////////////////////////////////////////////////////////////////////////// template CAliasCont::CAliasCont() : CCont() { } template uint32 CAliasCont::getChildIndexByAlias(uint32 alias) const { size_t size = this->_Childs.size(); for (size_t i=0; i_Childs[i]; if (child!=NULL && child->getAlias()==alias) return (uint32)i; } return ~0; } template TChld* CAliasCont::getChildByAlias(uint32 alias) const { size_t size = this->_Childs.size(); for (size_t i=0; i_Childs[i]; if (child!=NULL && child->getAlias()==alias) return child; } return NULL; } template TChld* CAliasCont::getChildByName(std::string const& name) const { size_t size = this->_Childs.size(); for (size_t i=0; i_Childs[i]; if (child!=NULL && child->getName()==name) return child; } return NULL; } template CAliasTreeOwner* CAliasCont::getAliasChildByAlias(uint32 alias) const { return NLMISC::type_cast(getChildByAlias(alias)); } template CAliasTreeOwner* CAliasCont::addAliasChild(CAliasTreeOwner* child) { return NLMISC::type_cast(addChild(static_cast(child))); } template CAliasTreeOwner* CAliasCont::addAliasChild(CAliasTreeOwner* child, uint32 index) { return NLMISC::type_cast(addChild(static_cast(child), index)); } template void CAliasCont::removeChildByAlias(uint32 alias) { CCont::removeChildByIndex(getChildIndexByAlias(alias)); } template void CAliasCont::removeChildByIndex(uint32 index) { CCont::removeChildByIndex(index); } #endif