Files
tlib/oversampling/WDL/ptrlist_indexed.h
2024-05-24 13:28:31 +02:00

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