// 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