first commit
This commit is contained in:
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__
|
||||
Reference in New Issue
Block a user