first commit

This commit is contained in:
2026-06-22 11:49:35 +02:00
commit d805f2ba86
619 changed files with 126873 additions and 0 deletions

View File

@ -0,0 +1,57 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __CONTAINER_SORT__
#define __CONTAINER_SORT__
namespace GS {
class ContainerSort
{
template <typename T, typename L> static inline void Swap(L &t, int i, int j)
{
if (i != j)
{ T swap = t[j]; t[j] = t[i]; t[i] = swap; }
}
template <typename T, typename L, typename C> static int QuickSortPartition(L &t, C compare, int first, int last, int pivot)
{
Swap <T, L> (t, pivot, last);
int j = first;
for (int i = first; i < last; ++i)
if (compare(t[i], t[last]) > 0)
{
Swap <T, L> (t, i, j);
++j;
}
Swap <T, L> (t, j, last);
return j;
}
template <typename T, typename L, typename C> static void QuickSortStep(L &t, C compare, int first, int last)
{
if (first < last)
{
int pivot = (first + last) / 2;
pivot = QuickSortPartition <T, L, C> (t, compare, first, last, pivot);
QuickSortStep <T, L, C> (t, compare, first, pivot - 1);
QuickSortStep <T, L, C> (t, compare, pivot + 1, last);
}
}
public:
/// Quick-sort a container in-place.
template <typename T, typename L, typename C> static void QuickSort(L &t, C compare)
{ QuickSortStep <T, L, C> (t, compare, 0, t.GetCount() - 1); }
};
} // GS
#endif // __CONTAINER_SORT__

View File

@ -0,0 +1,136 @@
/*
Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are
those of the authors and should not be interpreted as representing official
policies, either expressed or implied, of Dmitry Vyukov.
*/
#ifndef __MPMC_BOUNDED_QUEUE__
#define __MPMC_BOUNDED_QUEUE__
#include "thread/atomic_value.h"
// Adapted from https://sites.google.com/site/1024cores/home/lock-free-algorithms/queues/bounded-mpmc-queue
template<typename T> class mpmc_bounded_queue
{
struct cell_t
{
GS::Threading::Atomic32 sequence_;
T data_;
};
static size_t const cacheline_size = 64;
typedef char cacheline_pad_t[cacheline_size];
cacheline_pad_t pad0_;
cell_t * const buffer_;
size_t const buffer_mask_;
cacheline_pad_t pad1_;
GS::Threading::Atomic32 enqueue_pos_;
cacheline_pad_t pad2_;
GS::Threading::Atomic32 dequeue_pos_;
cacheline_pad_t pad3_;
void operator = (mpmc_bounded_queue const&);
mpmc_bounded_queue(mpmc_bounded_queue const&);
public:
bool enqueue(T const &data)
{
cell_t *cell;
int pos = enqueue_pos_.Get();
for (;;)
{
cell = &buffer_[pos & buffer_mask_];
size_t seq = cell->sequence_.Get();
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
if (dif == 0)
{
if (enqueue_pos_.Cas(pos, pos + 1) == pos)
break;
}
else if (dif < 0)
return false;
else
pos = enqueue_pos_.Get();
}
cell->data_ = data;
cell->sequence_.Set(pos + 1);
return true;
}
bool dequeue(T &data)
{
cell_t *cell;
int pos = dequeue_pos_.Get();
for (;;)
{
cell = &buffer_[pos & buffer_mask_];
size_t seq = cell->sequence_.Get();
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
if (dif == 0)
{
if (dequeue_pos_.Cas(pos, pos + 1) == pos)
break;
}
else if (dif < 0)
return false;
else
pos = dequeue_pos_.Get();
}
data = cell->data_;
cell->sequence_.Set(pos + buffer_mask_ + 1);
return true;
}
mpmc_bounded_queue(size_t buffer_size) : buffer_(new cell_t [buffer_size]), buffer_mask_(buffer_size - 1)
{
for (size_t i = 0; i != buffer_size; i += 1)
buffer_[i].sequence_.Set(i);
enqueue_pos_.Set(0);
dequeue_pos_.Set(0);
}
~mpmc_bounded_queue()
{
delete [] buffer_;
}
};
#endif // __MPMC_BOUNDED_QUEUE__

View File

@ -0,0 +1,215 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NARRAY__
#define __NARRAY__
#include "alloc/ialloc.h"
#include "memory/memory.h"
#include "assert/nassert.h"
namespace GS {
/*!
@short Managed array.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> class Array
{
uint count;
T *data;
#if __ENABLE_ALLOCATION_STAT__
Alloc::System system;
#endif
public:
inline operator T *() const
{ return data; }
inline T *c_ptr() const
{ return data; }
inline T &operator [] (int n) const
{ return data[n]; }
inline T &operator [] (uint n) const
{ return data[n]; }
void operator = (Array <T> &o) ///< Transfer assignation.
{ Transfer(o); }
inline T *Start() const
{ return data; }
inline T *End() const
{ return &data[count]; }
inline bool IsValid() const
{ return data ? true : false; }
inline bool IsNull() const
{ return data ? false : true; }
/// Return the number of elements of type T in the buffer.
inline uint GetCount() const
{ return count; }
/// Return the buffer size in bytes.
inline size_t GetSize() const
{ return count * sizeof(T); }
void Free()
{
if (data)
__NSTAT_DELETE(count * sizeof(T), system);
// _safe_delete_array(data);
delete[] data;
data = 0;
count = 0;
}
/// Reallocate buffer elements.
bool Reallocate(uint new_count)
{
if (new_count == count)
return true;
if (T *new_data = new T[new_count])
{
__NSTAT_ALLOC(new_count * sizeof(T), system);
Memory::Copy(new_data, data, GetSize());
if (data)
__NSTAT_DELETE(count * sizeof(T), system);
// _safe_delete_array(data);
delete[] data;
data = 0;
data = new_data;
count = new_count;
}
else
return false;
return true;
}
/// Allocate buffer elements.
bool Allocate(uint _count)
{
/// @note We could add a small tolerance here to potentially reduce fragmentation?
if (_count == count)
return true;
Free();
if (_count && ((data = new T[_count]) == 0))
return false;
__NSTAT_ALLOC(_count * sizeof(T), system);
count = _count;
return true;
}
/// Relinquish ownership of the managed memory block.
T *Detach()
{
T *r = data;
data = 0;
count = 0;
return r;
}
/// Take ownership of a managed memory block.
void Attach(uint _count, T *_data)
{
Free();
count = _count;
data = _data;
}
/// Transfer data buffer.
void Transfer(Array <T> &b)
{
Free();
count = b.GetCount();
data = b.Detach();
#if __ENABLE_ALLOCATION_STAT__
__NSTAT_DELETE(count * sizeof(T), b.system);
__NSTAT_ALLOC(count * sizeof(T), system);
#endif
}
/// Clone data buffer.
bool Clone(const Array <T> &b)
{
Free();
if (!Allocate(b.GetCount()))
return false;
for (uint n = 0; n < GetCount(); ++n)
data[n] = b[n];
return true;
}
/// Fill data buffer.
void Fill(const T &v, uint from = 0, uint to = 0)
{
if (to <= 0)
to = count + to;
__ASSERT__(from <= count);
__ASSERT__(to <= count);
for (uint n = from; n < to; ++n)
data[n] = v;
}
/// Swap two data buffer.
static void Swap(Array <T> &a, Array <T> &b)
{
uint count_a = a.GetCount(), count_b = b.GetCount();
T *data_a = a.Detach(), *data_b = b.Detach();
a.Attach(count_b, data_b);
b.Attach(count_a, data_a);
}
Array(uint _count, Alloc::System sys = Alloc::General)
{
data = 0; count = 0;
#if __ENABLE_ALLOCATION_STAT__
system = sys;
#endif
Allocate(_count);
}
Array(uint _count, const T *_data, Alloc::System sys = Alloc::General)
{
data = 0; count = 0;
#if __ENABLE_ALLOCATION_STAT__
system = sys;
#endif
if (Allocate(_count))
Memory::Copy(data, _data, sizeof(T) * _count);
}
Array(const Array <T> &array, Alloc::System sys = Alloc::General) ///< Copy constructor.
{
data = 0; count = 0;
#if __ENABLE_ALLOCATION_STAT__
system = sys;
#endif
Allocate(array.GetCount());
Memory::Copy(data, array.c_ptr(), array.GetSize());
}
Array(Alloc::System sys = Alloc::General)
{
data = 0; count = 0;
#if __ENABLE_ALLOCATION_STAT__
system = sys;
#endif
}
~Array()
{ Free(); }
};
} // GS
#endif // __NARRAY__

View File

@ -0,0 +1,268 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NARRAYLIST__
#define __NARRAYLIST__
#include "container/narray.h"
#include "log/log.h"
namespace GS {
/*!
@short Array list.
A flexible structure with faster access time (both linear and random) and
tighter memory usage than lists.
Especially suited for small types such as pointers.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> class ArrayList
{
Array <T> array;
Array <uint> usage_map;
uint usage; ///< Array usage.
uint grow_step;
//----------------------------------------------------------------------
inline bool Grow()
{
if (int(usage) >= int(array.GetCount() - 1))
return Resize(array.GetCount() + grow_step);
return true;
}
inline bool Shrink()
{
if (((int)array.GetCount() - 1) > (int)grow_step)
if ((int)usage < ((int)array.GetCount() - 1 - (int)grow_step))
return Resize(array.GetCount() - grow_step);
return true;
}
//----------------------------------------------------------------------
public:
//----------------------------------------------------------------------
class Iterator
{
const ArrayList <T> &list;
uint i;
public:
inline void Reset(uint from = 0) { i = from; }
inline bool IsOver() const { return i < list.GetCount() ? false : true; }
inline void operator++() { ++i; }
inline T &Object() { return list[i]; }
inline T ObjectPtr() { return list[i]; }
Iterator(const ArrayList <T> &_list, uint from = 0) : list(_list), i(from) {}
};
//----------------------------------------------------------------------
//----------------------------------------------------------------------
inline uint GetCount() const
{ return usage; }
inline T &ObjectAt(int n) const
{ return array[usage_map[n]]; }
inline T &ObjectAt(uint n) const
{ return array[usage_map[n]]; }
inline T &operator [] (int n) const
{ return array[usage_map[n]]; }
inline T &operator [] (uint n) const
{ return array[usage_map[n]]; }
inline void SetGrowStep(uint step)
{ grow_step = step; }
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// Insert a new value in the list.
virtual bool Insert(const T &v, uint at)
{
Grow();
// Claim entry...
uint claimed = usage_map[usage];
// ...and shift usage map.
for (int n = (int)usage - 1; n >= (int)at; --n)
usage_map[n + 1] = usage_map[n];
usage_map[at] = claimed;
usage++;
array[claimed] = v;
array[usage_map[usage]] = 0; // enforce terminator
return true;
}
/// Add a new value to the end of the list.
bool Add(const T &v)
{
return Insert(v, usage);
}
/// Return the index at which a value is first found in the list.
int IndexOf(const T &v, uint from = 0)
{
for (uint i = from; i < usage; ++i)
if (array[usage_map[i]] == v)
return i;
return -1;
}
/// Remove an entry from the list.
virtual bool RemoveAt(uint i)
{
if (usage == 0)
return false;
// Reclaim entry...
uint reclaimed = usage_map[i];
// ...and shift usage map.
for (uint n = i + 1; n < usage; ++n)
usage_map[n - 1] = usage_map[n];
usage_map[usage - 1] = reclaimed;
usage--;
array[reclaimed] = 0; // enforce terminator
Shrink();
return true;
}
bool Remove(const T &v)
{
int i = IndexOf(v);
return i != -1 ? RemoveAt(i) : false;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
ArrayList <T> &operator = (const T &v)
{
if (this != &v)
{
Clear();
for (uint n = 0; n < v.GetCount(); ++n)
Add(v[n]);
}
return *this;
}
ArrayList <T> &operator << (const T &v)
{
Add(v);
return *this;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
bool Resize(uint new_size)
{
if ((int)new_size == (int)array.GetCount() - 1)
return true;
Array <T> _array(new_size + 1);
if (_array.IsNull())
__ERR__(__LOG_E__ << "Failed to allocate new array.\n", false)
for (uint n = 0; n < usage; ++n)
_array[n] = array[usage_map[n]];
array.Transfer(_array);
if (!usage_map.Allocate(new_size + 1))
__ERR__(__LOG_E__ << "Failed to allocate array bookkeeping structures.\n", false)
for (uint n = 0; n < (new_size + 1); ++n)
usage_map[n] = n;
array[usage_map[usage]] = 0; // enforce terminator
return true;
}
/*!
@short Clear the container.
Pass false to prevent the internal structures from being released,
the array list will keep its current capacity and only its usage map
will be reset.
*/
virtual void Clear(bool free_internals = true)
{
usage = 0;
if (free_internals)
Resize(0);
else
{
for (uint n = 0; n < array.GetCount(); ++n)
usage_map[n] = n;
array[0] = 0; // enforce terminator
}
}
//----------------------------------------------------------------------
ArrayList(uint initial_size = 0, uint step = 64) : usage(0), grow_step(step) { Resize(initial_size); }
virtual ~ArrayList() {}
};
/*
@short Shared object array list.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> struct SharedArrayList : public ArrayList <T>
{
virtual bool Insert(const T &v, uint at)
{
v->AddRef();
return ArrayList <T> ::Insert(v, at);
}
virtual bool RemoveAt(uint i)
{
(*this)[i]->RemoveRef();
return ArrayList <T> :: RemoveAt(i);
}
virtual void Clear(bool free_internals = true)
{
for (uint n = 0; n < this->GetCount(); ++n)
(*this)[n]->RemoveRef();
return ArrayList <T> ::Clear(free_internals);
}
virtual ~SharedArrayList()
{ Clear(); }
};
//------------------------------------------------------------------------------
// Delete all list entries.
#define ArrayListDeleteAllPtr(T, L) { for (uint __n = 0; __n < (L).GetCount(); ++__n) delete (L)[__n]; (L).Clear(); }
// Iterate over a list of pointers.
#define ArrayListForeachPtr(T, V, L) \
for (ArrayList <T> ::Iterator iterator(L); T V = iterator.ObjectPtr(); ++iterator)
// Iterate over a list of objects.
#define ArrayListForeach(T, V, L) \
for (ArrayList <T> ::Iterator V(L); V.IsOver() == false; ++V)
/// Find item by using a template identification class.
template <typename T, typename F, typename P> T ArrayListFindEx(const ArrayList <T> &list, F filter, const P &what)
{
for (uint __n = 0; __n < list.GetCount(); ++__n)
if (filter(list[__n], what))
return list[__n];
return 0;
}
//------------------------------------------------------------------------------
} // GS
#endif // __NARRAYLIST__

View File

@ -0,0 +1,604 @@
/* -----------------------------------------------------------------------------
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__

View File

@ -0,0 +1,68 @@
/*------------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMAP__
#define __NMAP__
#include "container/nlist.h"
#include "memory/nauto_ptr.h"
namespace GS {
//
template <class KType, class VType> struct Pair
{
KType key;
VType value;
Pair(const KType _key, const VType _value) : key(_key), value(_value) {}
};
/*!
@short Very naive map.
@todo Red-black tree.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
template <class KType, class VType> class Map
{
AutoList <Pair <KType, VType> *> pairs;
public:
Pair <KType, VType> *Get(const KType &key) const
{
for (typename List <Pair <KType, VType> *> ::Item *p = pairs.GetRoot(); p; p = p->Next())
if (p->Object()->key == key)
return p->Object();
return 0;
}
uint GetCount() const
{ return pairs.GetCount(); }
bool HasKey(const KType &key) const
{ return asbool(Get(key)); }
VType &operator [] (const KType &key) const
{ return Get(key)->value; }
Pair <KType, VType> *Add(const KType &key, const VType &value)
{
AutoPtr <Pair <KType, VType> > pair(new Pair <KType, VType> (key, value));
return pair.IsValid() && pairs.Add(pair) ? pair.Detach() : 0;
}
bool Delete(Pair <KType, VType> *pair)
{ return pairs.Remove(pair); }
bool Delete(const KType &key)
{ return Delete(Get(key)); }
};
} // GS
#endif // __NMAP__

View File

@ -0,0 +1,150 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NSTACK__
#define __NSTACK__
#include "container/narray.h"
namespace GS {
/*!
@short Simple value stack.
@author Emmanuel Julien (ejulien@owloh.com)
*/
template <class T> class Stack
{
protected:
Array <T> data;
uint usage;
uint grow_step;
public:
inline const T &operator [] (int n) const
{ return data[n]; }
inline const T &Top() const
{ return data[usage - 1]; }
//----------------------------------------------------------------------
T *Detach()
{
usage = 0;
return data.Detach();
}
virtual void Transfer(Stack <T> &from)
{
usage = from.GetCount();
data.Transfer(from.data);
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// Push a value on top of the stack.
virtual bool Push(const T &v)
{
if (usage == data.GetCount())
if (!data.Reallocate(usage + 64))
return false;
data[usage++] = v;
return true;
}
/// Pop a value from the stack.
virtual void Pop()
{
if (usage > 0)
--usage;
}
inline bool Add(const T &v)
{ return Push(v); }
inline Stack <T> &operator << (const T &v)
{
Add(v);
return *this;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
inline uint GetCount() const
{ return usage; }
inline void SetGrowStep(uint step)
{ grow_step = step; }
virtual void Clear(bool free_internals = true)
{
if (free_internals)
data.Free();
usage = 0;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
inline int Index(const T &v) const
{
for (uint n = 0; n < usage; ++n)
if (data[n] == v)
return n;
return -1;
}
//----------------------------------------------------------------------
Stack(uint size = 0, uint step = 64) : usage(0), grow_step(step) { data.Allocate(size); }
virtual ~Stack() {}
};
/// Auto-stack.
template <class T> struct AutoStack : public Stack <T>
{
//----------------------------------------------------------------------
virtual void Transfer(Stack <T> &from)
{
for (uint n = 0; n < this->usage; ++n)
delete this->data[n];
Stack <T> ::Transfer(from);
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
virtual void Pop()
{
if (this->usage > 0)
delete this->data[--this->usage];
}
virtual void Clear(bool free_internals = true)
{
for (uint n = 0; n < this->usage; ++n)
delete this->data[n];
Stack <T> ::Clear(free_internals);
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/*!
@short Drop all pointers managed by this stack, does not free the storage.
The dropped pointers are expected to have been taken care of as this
container will completely forget about them.
*/
void DropContentOwnership()
{
for (uint n = 0; n < this->usage; ++n)
this->data[n] = 0;
this->usage = 0;
}
//----------------------------------------------------------------------
AutoStack(uint size = 0, uint step = 64) : Stack <T> (size, step) {}
virtual ~AutoStack() { Clear(); }
};
} // GS
#endif // __NSTACK__

View File

@ -0,0 +1,161 @@
/*
*/
#ifndef __TMPL_PAIRLIST__
#define __TMPL_PAIRLIST__
#include "data/array_list.h"
#include "platform_config.h"
//
template <class PAIR, class TYPE> class ntPairList;
/*
@short Pair item.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class TYPE> class ntPairItem : public nArrayEntry
{
protected:
int hash;
public:
TYPE *a, *b; ///< Object pair.
void *pair_data; ///< Pair associated data block.
/// Compute pair hash value.
static int ComputeHash(TYPE *_a, TYPE *_b)
{
int hash = (((uintptr_t)_a) & 0xf0f0f0f0) | (((uintptr_t)_b) & 0x0f0f0f0f);
hash = (hash + 0x7ed55d16) + (hash << 12);
hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
hash = (hash + 0x165667b1) + (hash << 5);
hash = (hash + 0xd3a2646c) ^ (hash << 9);
hash = (hash + 0xfd7046c5) + (hash << 3);
hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
return hash;
}
/// Get pair hash.
int Hash() const { return hash; }
ntPairItem(TYPE *_a, TYPE *_b)
{
a = _a; b = _b;
hash = ComputeHash(a, b);
}
};
/*
*/
struct ntPairListPool
{
uint bucket,
entry;
void Reset()
{ bucket = entry = 0; }
ntPairListPool()
{ Reset(); }
};
/*
@short Pair list.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class PAIR, class TYPE> class ntPairList
{
#define PairListBucketCount 64
#define OrderPairItems(_A_, _B_) { if (_A_ > _B_) { TYPE *t = _A_; _A_ = _B_; _B_ = t; } }
protected:
uint count;
nArrayList bucket[PairListBucketCount];
public:
/// Get item count in list.
uint GetCount() const
{ return count; }
/// Pool list.
PAIR *Pool(ntPairListPool &pool) const
{
while (pool.bucket < PairListBucketCount)
{
if (pool.entry < bucket[pool.bucket].GetCount())
break;
pool.entry = 0;
pool.bucket++;
}
if (pool.bucket == PairListBucketCount)
return 0;
return (PAIR *)bucket[pool.bucket][pool.entry++];
}
/// Add a pair.
PAIR *Add(TYPE *a, TYPE *b)
{
OrderPairItems(a, b);
PAIR *pair = new PAIR(a, b);
if (pair && !bucket[pair->Hash() & (PairListBucketCount - 1)].Add(pair))
_safe_delete(pair);
else
count++;
return pair;
}
/// Find a pair.
PAIR *Find(TYPE *a, TYPE *b)
{
OrderPairItems(a, b);
int hash = PAIR::ComputeHash(a, b);
nArrayList &h_bucket = bucket[hash & (PairListBucketCount - 1)];
for (uint n = 0; n < h_bucket.GetCount(); ++n)
{
PAIR *pair = (PAIR *)h_bucket[n];
if ((pair->a == a) && (pair->b == b))
return pair;
}
return 0;
}
/// Remove pair.
bool Remove(PAIR *pair)
{
if (bucket[pair->Hash() & (PairListBucketCount - 1)].Delete(pair))
{
count--;
return false;
}
return true;
}
/// Delete all pair.
void DeleteAll(bool freedata = true)
{
for (int n = 0; n < PairListBucketCount; ++n)
bucket[n].DeleteAll(freedata);
count = 0;
}
ntPairList()
{ count = 0; }
};
#endif // __TMPL_PAIRLIST__

View File

@ -0,0 +1,62 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __SMARTMEDIANAVG__
#define __SMARTMEDIANAVG__
#include "sort/sort.h"
namespace GS {
//
template <class T, int Size = 16, int SafeGuard = 4> class SmartMedianAverage
{
T history[Size];
int count;
public:
void LogValue(T v)
{
if (count < Size)
count++; // fill up
else
for (int n = 1; n < Size; ++n) // scroll
history[n - 1] = history[n];
history[count - 1] = v;
}
T GetMedian() const
{
if (count == 0)
return 0;
if (count < Size)
return history[0]; // unfiltered
// Sort current histogram values.
typename Sort <T, int> ::Entry entries[Size];
for (int n = 0; n < Size; ++n)
entries[n].v = history[n];
Sort <T, int> ::QuickSort(Size, entries);
// Compute average of the safe values.
T avg = 0;
for (int n = (Size / SafeGuard); n < (Size - Size / SafeGuard); ++n)
avg += entries[n].v;
return avg / (Size - (Size / SafeGuard) * 2);
}
void Reset() { count = 0; }
SmartMedianAverage() : count(0) {}
};
} // GS
#endif // __SMARTMEDIANAVG__