Files
Webcam/include/platform/container/nlist.h
2026-06-22 11:49:35 +02:00

605 lines
12 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NLIST__
#define __NLIST__
#include "alloc/ialloc.h"
#include "assert/nassert.h"
namespace GS {
/*
@short List.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> class List
{
public:
//----------------------------------------------------------------------
class Item
{
friend class List <T>;
T o;
Item *p, *n;
public:
NPLACEMENT_NEW(ListItem)
/// Return the previous list link.
inline Item *Previous() const { return p; }
/// Return the next list link.
inline Item *Next() const { return n; }
/// Retrieve a reference to the item object.
inline T &Object() { return o; }
Item(const T &obj)
{
o = obj;
p = n = 0;
}
};
//----------------------------------------------------------------------
//----------------------------------------------------------------------
class Iterator
{
Item *c, *n;
public:
inline void operator++()
{
if ((c = c ? n : 0) != 0)
n = c->n;
}
inline bool IsOver() const { return c ? false : true; }
inline Item *Next() const { return n; }
inline Item *GetItem() const { return c; }
inline T &Object() { return c->Object(); }
/// Only use when using a pointer type.
inline T ObjectPtr() { return c ? c->Object() : 0; }
void Reset(Item *start = 0)
{
c = start;
n = c ? c->Next() : 0;
}
Iterator(Item *start = 0)
{ Reset(start); }
};
//----------------------------------------------------------------------
protected:
uint count;
Item *root, *last;
public:
/// Get item count in list.
inline uint GetCount() const { return count; }
/// Get root item.
inline Item *GetRoot() const { return root; }
/// Get last item.
inline Item *GetLast() const { return last; }
/// Clone list.
void Clone(List <T> &clone_list) const
{
clone_list.Clear();
for (Item *_i = root; _i; _i = _i->Next())
clone_list.Add(_i->Object());
}
/// Get item from position.
Item *ItemAt(uint n) const
{
if (n > count)
return 0;
Item *p = root;
while (n--)
p = p->n;
return p;
}
inline T &ObjectAt(uint n) const
{ return ItemAt(n)->Object(); }
inline T &operator[] (uint n) const
{ return ItemAt(n)->Object(); }
/// Get index of a given item.
int Index(const T &o) const
{
int pos = 0;
for (Item *p = root; p; p = p->n)
{
if (p->Object() == o)
return pos;
pos++;
}
return -1;
}
/// Check whether a given item belongs to this list or not.
bool Belongs(Item *i) const
{
for (Item *s = root; s; s = s->n)
if (s == i)
return true;
return false;
}
/// Insert item after a given reference item (defaults to last).
virtual Item *Append(const T &o, Item *rfr = 0)
{
Item *i = new Item(o);
if (!i)
return 0;
if (!rfr)
{
i->p = last;
if (last)
last->n = i;
else
root = i;
last = i;
}
else
{
if (rfr->n)
rfr->n->p = i;
i->n = rfr->n;
rfr->n = i;
i->p = rfr;
if (last == rfr) // Update last.
last = i;
}
count++;
return i;
}
/// Insert item before a given reference item (defaults to root).
virtual Item *Prepend(const T &o, Item *rfr = 0)
{
Item *i = new Item(o);
if (!i)
return 0;
if (!rfr)
{
i->n = root;
if (root)
root->p = i;
else
last = i;
root = i;
}
else
{
if (rfr->p)
rfr->p->n = i;
i->p = rfr->p;
rfr->p = i;
i->n = rfr;
if (root == rfr) // Update root.
root = i;
}
count++;
return i;
}
/// Insert a value at a given position.
Item *Insert(const T &v, uint at)
{
Item *rfr = ItemAt(at);
return rfr ? Prepend(v, rfr) : 0;
}
/// Add item to list.
Item *Add(const T &o, bool append, bool allow_duplicate)
{
if (!allow_duplicate)
if (Item *i = Find(o))
return i;
return append ? Append(o) : Prepend(o);
}
/// Add item to list.
Item *Add(const T &o)
{ return Append(o); }
/// Add item to list.
List <T> &operator << (const T &o)
{
Add(o);
return *this;
}
/// Find item by reference to object.
Item *Find(const T &o) const
{
for (Item *p = root; p; p = p->n)
if (p->Object() == o)
return p;
return 0;
}
/// Find item by object value.
Item *FindByValue(const T &o) const
{
for (Item *p = root; p; p = p->n)
if (*p->Object() == *o)
return p;
return 0;
}
/*!
@short Subtract two given lists by object value.
@warning The resulting list holds pointers to the original objects.
*/
static List <T> *SubtractByValue(const List <T> &what, const List <T> &from)
{
List <T> *list = new List <T>;
if (list)
for (Item *f_p = from.root; f_p; f_p = f_p->n)
if (!what.FindByValue(f_p->Object()))
list->Add(f_p->Object());
return list;
}
/*!
@short Subtract two given lists by object address.
@warning The resulting list holds pointers to the original objects.
*/
static List <T> *SubtractByAddress(const List <T> &what, const List <T> &from)
{
List <T> *list = new List <T>;
if (list)
for (Item *f_p = from.root; f_p; f_p = f_p->n)
if (!what.Find(f_p->Object()))
list->Add(f_p->Object());
return list;
}
/// Filter out linked-list item function.
template <typename F> void FilterOut(F filter)
{
for (Item *c = GetRoot(); c; )
{
Item *n = c->Next();
if (filter(c->Object()))
Remove(c);
c = n;
}
}
/// Build a new list from select items.
template <typename F, typename P> uint Select(List <T> &out, F filter, const P &filter_param) const
{
out.Clear();
for (Item *c = GetRoot(); c; )
if (filter(c->Object(), filter_param))
out.Add(c->Object());
return out.GetCount();
}
/// Sort linked-list function.
template <typename C> void Sort(C compare)
{
for (bool swapped = true; swapped; )
{
swapped = false;
for (Item *c = GetRoot(); c; )
{
Item *n = c->Next();
if (!n)
break;
if (compare(c->Object(), n->Object()) < 0)
{
swapped = true;
c->n = n->n;
n->n = c;
n->p = c->p;
c->p = n;
if (n->p)
n->p->n = n;
else root = n;
if (c->n)
c->n->p = c;
else last = c;
}
else
c = n;
}
}
}
/// Merge sort linked-list function.
template <typename C> void MergeSort(C compare)
{
Item *list = root, *tail = 0;
if (!list)
return;
for (int insize = 1; ; insize *= 2)
{
Item *p = list;
list = 0;
tail = 0;
int merge_count = 0; // Count number of merges we do in this pass.
while (p)
{
merge_count++;
// Step along from p.
Item *q = p;
int psize = 0;
for ( ; q && (psize < insize); ++psize)
q = q->Next();
// If q hasn't fallen off end, we have two lists to merge.
int qsize = insize;
// Now we have two lists, merge them.
while (psize > 0 || (qsize > 0 && q))
{
Item *e;
if (!psize) // p is empty, e must come from q.
{ e = q; q = q->Next(); qsize--; }
else if (!qsize || !q) // q is empty, e must come from p.
{ e = p; p = p->Next(); psize--; }
else if (compare(p->Object(), q->Object()) <= 0) // First element of p is lower (or same), e must come from p.
{ e = p; p = p->Next(); psize--; }
else // First element of q is lower; e must come from q.
{ e = q; q = q->Next(); qsize--; }
// Add the next element to the merged list.
if (tail)
tail->n = e;
else list = e;
e->p = tail;
tail = e;
}
// Now p has stepped `insize' places along, and q has too.
p = q;
}
tail->n = 0;
// If we have done only one merge, we're done.
if (merge_count <= 1)
break;
}
root = list;
last = tail;
}
/// Extract object from list.
Item *ExtractItem(const T &o)
{
Item*i = Find(o);
return i ? ExtractItem(i) : 0;
}
/// Extract item from list.
Item *ExtractItem(Item *i)
{
if (!i)
return 0;
__ASSERT__(Belongs(i));
if (i->p)
i->p->n = i->n;
else
{
if (i->n)
i->n->p = 0;
root = i->n;
}
if (i->n)
i->n->p = i->p;
else
{
if (i->p)
i->p->n = 0;
last = i->p;
}
i->p = i->n = 0;
--count;
return i;
}
/// Extract item at position.
Item *ExtractAt(uint n)
{
Item *i = ItemAt(n);
return i ? ExtractItem(i) : 0;
}
/// Remove item from list.
virtual bool Remove(Item *i)
{
if (ExtractItem(i) == 0)
return false;
delete i;
return true;
}
/// Remove item from list.
virtual bool Remove(const T &o)
{
return Remove(Find(o));
}
/// Remove item at position.
bool RemoveAt(uint n)
{
Item *i = ItemAt(n);
return i ? Remove(i) : false;
}
/// Remove all items from the list.
virtual void Clear()
{
for (Item *p = root, *n; p; p = n)
{
n = p->n;
delete p;
}
count = 0;
root = last = 0;
}
List()
{
count = 0;
root = last = 0;
}
virtual ~List()
{ Clear(); }
};
/*
@short Auto linked-list.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> struct AutoList : public List <T>
{
virtual bool Remove(class List <T> ::Item *i)
{
T o = i->Object();
if (!List <T> ::Remove(i))
return false;
delete o;
return true;
}
virtual bool Remove(const T &o)
{
class List <T> ::Item *i = this->Find(o);
return i ? this->Remove(i) : false;
}
virtual void Clear()
{
for (class List <T> ::Item *p = this->root; p; p = p->Next())
delete p->Object();
List <T> ::Clear();
}
virtual ~AutoList()
{ this->Clear(); }
};
/*
@short Shared object linked-list.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> struct SharedList : public List <T>
{
virtual class List <T> ::Item *Append(const T &o, class List <T> ::Item *rfr = 0)
{
class List <T> ::Item *i = List <T> ::Append(o, rfr);
if (i)
o->AddRef();
return i;
}
virtual class List <T> ::Item *Prepend(const T &o, class List <T> ::Item *rfr = 0)
{
class List <T> ::Item *i = List <T> ::Prepend(o, rfr);
if (i)
o->AddRef();
return i;
}
virtual bool Remove(class List <T> ::Item *i)
{
T o = i->Object();
if (!List <T> ::Remove(i))
return false;
o->RemoveRef();
return true;
}
virtual bool Remove(const T &o)
{
class List <T> ::Item *i = this->Find(o);
return i ? this->Remove(i) : false;
}
virtual void Clear()
{
for (class List <T> ::Item *p = this->root; p; p = p->Next())
p->Object()->RemoveRef();
List <T> ::Clear();
}
virtual ~SharedList()
{ Clear(); }
};
//------------------------------------------------------------------------------
// Delete all list entries.
#define ListDeleteAllPtr(T, L) { class GS::List <T> ::Item *t; while ((t = (L).GetRoot()) != 0) { T _o = t->Object(); (L).Remove(t); delete(_o); } }
// Iterate over a list of pointers.
#define ListForeachPtr(T, V, L) \
for (class GS::List <T> ::Iterator iterator((L).GetRoot()); T V = iterator.ObjectPtr(); ++iterator)
// Iterate over a list of objects.
#define ListForeach(T, V, L) \
for (class GS::List <T> ::Iterator V((L).GetRoot()); V.IsOver() == false; ++V)
/// Find item by using a template identification class.
template <typename T, typename F, typename P> T ListFindEx(const List <T> &list, F filter, const P &what)
{
for (class List <T> ::Item *p = list.GetRoot(); p; p = p->Next())
if (filter(p->Object(), what))
return p->Object();
return 0;
}
/// Remove all items with a reference count of 1 from a shared list.
template <class T> uint PurgeSharedList(SharedList <T *> &list)
{
uint c = list.GetCount();
ListForeachPtr(T *, t, list)
if (t->GetRefCount() == 1)
list.Remove(iterator.GetItem());
return c - list.GetCount();
}
//------------------------------------------------------------------------------
} // GS
#endif // __NLIST__