#ifndef AIW_NWAYSET_H_INCLUDED
#define AIW_NWAYSET_H_INCLUDED
#include <list>
#include <set>
#ifndef STD_NAMESPACE_USED
using namespace std;
#define STD_NAMESPACE_USED
#endif
template<class T, class A = allocator<T> > class nwayset
{
public:
//forward decls
class CCompareHelper;
class CDataListIterator;
//some typedefs
typedef bool (*TFncCompare)(const T &, const T &);
typedef list<T, A> TDataList;
typedef multiset<CDataListIterator,CCompareHelper> TIndex;
typedef TIndex index;
typedef list<TIndex> TIndexList;
//////////////////////
class CCompareHelper : public binary_function
<CDataListIterator, CDataListIterator, bool>
{
public:
inline CCompareHelper() : m_fncCompare(NULL) {};
inline CCompareHelper(TFncCompare fncCompare)
{m_fncCompare=fncCompare;};
inline bool operator()(CDataListIterator x,
CDataListIterator y) const
{ return m_fncCompare(*x, *y);};
protected:
mutable TFncCompare m_fncCompare;
};
//////////////////////
class CDataListIterator : public TDataList::iterator
{
public:
inline CDataListIterator(TDataList::iterator it)
{
m_p=NULL;
*((TDataList::iterator *)(this))=it;
}
inline CDataListIterator(const T &obj)
{ m_p=(T *)&obj;}
inline T &operator*(void)
{ return m_p ? *m_p :
*(*((TDataList::iterator *)this));}
inline const T &operator*(void) const
{ return m_p ? *m_p :
*(*((TDataList::iterator *)this));}
private:
T *m_p;
};
//////////////////////
typedef class CConstIterator :
public TIndex::const_iterator
{
public:
inline CConstIterator(TIndex::const_iterator it)
{
m_p=NULL;
*((TIndex::const_iterator *)(this))=it;
}
inline CConstIterator(const T &obj) { m_p=&obj; }
inline const T &operator*(void) const
{ return m_p ? *m_p :
*(*(*((TIndex::const_iterator *)(this))));}
private:
const T *m_p;
} const_iterator;
//////////////////////
typedef class CIterator : public TIndex::iterator
{
public:
inline CIterator(TIndex::iterator it)
{
m_p=NULL;
*((TIndex::iterator *)(this))=it;
}
inline CIterator(T &obj) {m_p=&obj;}
inline T &operator*(void)
{return m_p ? *m_p :
*(*(*((TIndex::iterator *)(this))));}
private:
T *m_p;
} iterator;
//////////////////////
//index related functions
typedef TIndexList::iterator index_iterator;
typedef TIndexList::const_iterator const_index_iterator;
////add a new index
index_iterator index_insert(TFncCompare fncCompare)
{
TIndexList::iterator it =
m_lIndexes.insert(m_lIndexes.end(),
TIndex(CCompareHelper(fncCompare)));
TIndex &obj=(*it);
for(TDataList::iterator itData=m_lData.begin();
itData!=m_lData.end();
itData++)
{ obj.insert(itData); }
return it;
}
////begin iterator for indexes
inline index_iterator index_begin(void)
{ return m_lIndexes.begin(); }
inline const_index_iterator index_begin(void) const
{ return m_lIndexes.begin(); }
////end iterator for indexes
inline index_iterator index_end(void)
{ return m_lIndexes.end();}
inline const_index_iterator index_end(void) const
{return m_lIndexes.end(); }
////remove an index
inline void index_erase(index_iterator it)
{ m_lIndexes.erase(it);}
//nwayset global related functions
////get size of set
inline int size(void) const {return m_lData.size();};
/////inserts an item
inline bool insert(const T &x)
{
TDataList::iterator it =
m_lData.insert(m_lData.end(), x);
for(TIndexList::iterator itIndexes=m_lIndexes.begin();
itIndexes!=m_lIndexes.end();
itIndexes++)
{ (*itIndexes).insert(it); }
return true;
}
////erase an item
void erase(CIterator it)
{
T &obj=*it;
TDataList::iterator itItem=*((TIndex::iterator)it);
for(TIndexList::iterator itIndex=m_lIndexes.begin();
itIndex!=m_lIndexes.end();
itIndex++)
{
TIndex &objIndex=(*itIndex);
for(CIterator itData=objIndex.find(obj);
itData!=objIndex.end();
itData++)
{
TDataList::iterator itEntry =
*((TIndex::iterator)itData);
if(itEntry==itItem)
{
objIndex.erase(itData);
break;
}
}
}
m_lData.erase(itItem);
}
////search all indexes for an item
CConstIterator find(const T &obj) const
{
for(TIndexList::const_iterator itIndex =
m_lIndexes.begin();
itIndex!=m_lIndexes.end();
itIndex++)
{
const TIndex &objIndex=(*itIndex);
CConstIterator itResult(objIndex.find(obj));
if(itResult!=objIndex.end())
return itResult;
}
return end();
}
////search all indexes for an item
CIterator find(const T &obj)
{
for(TIndexList::iterator itIndex=m_lIndexes.begin();
itIndex!=m_lIndexes.end();
itIndex++)
{
TIndex &objIndex=(*itIndex);
CIterator itResult(objIndex.find(obj));
if(itResult!=objIndex.end())
return itResult;
}
return end();
}
////end to designate find failure
CConstIterator end(void) const
{ return (*m_lIndexes.begin()).end();}
CIterator end(void) {return (*m_lIndexes.begin()).end();}
protected:
TDataList m_lData;
TIndexList m_lIndexes;
};
#endif