143 lines
3.8 KiB
C++
143 lines
3.8 KiB
C++
#ifndef _WDL_PTRLIST_INDEXED_H_
|
|
#define _WDL_PTRLIST_INDEXED_H_
|
|
|
|
#include "assocarray.h"
|
|
#include "ptrlist.h"
|
|
|
|
template<class T> class WDL_IndexedPtrList {
|
|
public:
|
|
WDL_IndexedPtrList() { }
|
|
~WDL_IndexedPtrList() { }
|
|
|
|
int GetSize() const {
|
|
// do not _checkState(), GetSize() may be called while unlocked for estimation purposes
|
|
return m_list.GetSize();
|
|
}
|
|
T * const *GetList() const { _checkState(); return m_list.GetList(); }
|
|
T *Get(INT_PTR idx) const { _checkState(); return m_list.Get(idx); }
|
|
int Find(const T *p) const
|
|
{
|
|
_checkState();
|
|
if (!p) return -1;
|
|
const int *ret = m_index.GetPtr((INT_PTR)p);
|
|
return ret ? *ret : -1;
|
|
}
|
|
void Empty() { _checkState(); m_list.Empty(); m_index.DeleteAll(); }
|
|
void Empty(bool wantDelete, void (*delfunc)(void*)=NULL) { _checkState(); m_list.Empty(wantDelete,delfunc); m_index.DeleteAll(); }
|
|
void EmptySafe(bool wantDelete=false,void (*delfunc)(void *)=NULL)
|
|
{
|
|
_checkState();
|
|
m_index.DeleteAll();
|
|
m_list.EmptySafe(wantDelete,delfunc);
|
|
m_index.DeleteAll();
|
|
}
|
|
void Delete(int idx, bool wantDelete=false, void (*delfunc)(void *)=NULL)
|
|
{
|
|
_checkState();
|
|
T *item = m_list.Get(idx);
|
|
m_list.Delete(idx,wantDelete,delfunc);
|
|
if (item)
|
|
{
|
|
m_index.Delete((INT_PTR)item);
|
|
const int indexsz = m_index.GetSize();
|
|
WDL_ASSERT(m_list.GetSize() == indexsz);
|
|
if (idx < indexsz)
|
|
{
|
|
for (int x=0;x<indexsz;x++)
|
|
{
|
|
int *val = m_index.EnumeratePtr(x);
|
|
if (WDL_NORMALLY(val))
|
|
{
|
|
WDL_ASSERT(*val != idx);
|
|
if (*val > idx) (*val)--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void DeletePtr(const T *p) { Delete(Find(p)); }
|
|
void DeletePtr(const T *p, bool wantDelete, void (*delfunc)(void *)=NULL) { Delete(Find(p),wantDelete,delfunc); }
|
|
void Add(T *p)
|
|
{
|
|
_checkState();
|
|
WDL_ASSERT(Find(p) < 0);
|
|
if (WDL_NORMALLY(p))
|
|
{
|
|
const int sz = m_list.GetSize();
|
|
m_list.Add(p);
|
|
m_index.Insert((INT_PTR)p,sz);
|
|
}
|
|
}
|
|
void RebuildIndex()
|
|
{
|
|
m_index.DeleteAll();
|
|
for (int x = 0; x < m_list.GetSize(); x ++)
|
|
{
|
|
m_index.AddUnsorted((INT_PTR)m_list.Get(x),x);
|
|
}
|
|
m_index.Resort();
|
|
_checkState();
|
|
}
|
|
void Swap(int index1, int index2)
|
|
{
|
|
_checkState();
|
|
if (index1 != index2 &&
|
|
WDL_NORMALLY(index1>=0) &&
|
|
WDL_NORMALLY(index1<m_list.GetSize()) &&
|
|
WDL_NORMALLY(index2>=0) &&
|
|
WDL_NORMALLY(index2<m_list.GetSize()))
|
|
{
|
|
T **list = m_list.GetList();
|
|
T *a = list[index1];
|
|
T *b = list[index2];
|
|
list[index2]=a;
|
|
list[index1]=b;
|
|
m_index.Insert((INT_PTR)a,index2);
|
|
m_index.Insert((INT_PTR)b,index1);
|
|
}
|
|
}
|
|
void Insert(int index, T *p)
|
|
{
|
|
_checkState();
|
|
if (!WDL_NORMALLY(p)) return;
|
|
const int listsz = m_list.GetSize();
|
|
if (index < 0) index=0;
|
|
if (index >= listsz) { Add(p); return; }
|
|
|
|
const int indexsz = m_index.GetSize();
|
|
WDL_ASSERT(listsz==indexsz);
|
|
|
|
for (int x=0;x<indexsz;x++)
|
|
{
|
|
int *val = m_index.EnumeratePtr(x);
|
|
if (WDL_NORMALLY(val))
|
|
{
|
|
if (*val >= index) (*val)++;
|
|
WDL_ASSERT(*val != index);
|
|
}
|
|
}
|
|
m_list.Insert(index,p);
|
|
m_index.Insert((INT_PTR)p,index);
|
|
}
|
|
|
|
WDL_PtrList<T> m_list;
|
|
WDL_PtrKeyedArray<int> m_index;
|
|
|
|
WDL_IndexedPtrList<T> &operator=(const WDL_IndexedPtrList<T> &cp)
|
|
{
|
|
m_list = cp.m_list;
|
|
RebuildIndex();
|
|
return *this;
|
|
}
|
|
|
|
void _checkState() const
|
|
{
|
|
#ifdef _DEBUG
|
|
const int idxsz = m_index.GetSize(), listsz = m_list.GetSize();
|
|
WDL_ASSERT(idxsz == listsz);
|
|
#endif
|
|
}
|
|
};
|
|
|
|
#endif
|