first commit
This commit is contained in:
57
include/platform/container/container_sort.h
Normal file
57
include/platform/container/container_sort.h
Normal 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__
|
||||
136
include/platform/container/mpmc_bounded_queue.h
Normal file
136
include/platform/container/mpmc_bounded_queue.h
Normal 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__
|
||||
215
include/platform/container/narray.h
Normal file
215
include/platform/container/narray.h
Normal 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__
|
||||
268
include/platform/container/narray_list.h
Normal file
268
include/platform/container/narray_list.h
Normal 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__
|
||||
604
include/platform/container/nlist.h
Normal file
604
include/platform/container/nlist.h
Normal 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__
|
||||
68
include/platform/container/nmap.h
Normal file
68
include/platform/container/nmap.h
Normal 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__
|
||||
150
include/platform/container/nstack.h
Normal file
150
include/platform/container/nstack.h
Normal 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__
|
||||
161
include/platform/container/pair.h
Normal file
161
include/platform/container/pair.h
Normal 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__
|
||||
62
include/platform/container/smart_median_average.h
Normal file
62
include/platform/container/smart_median_average.h
Normal 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__
|
||||
Reference in New Issue
Block a user