/* ----------------------------------------------------------------------------- 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 ArrayList { Array array; Array 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 &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 &_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 &operator = (const T &v) { if (this != &v) { Clear(); for (uint n = 0; n < v.GetCount(); ++n) Add(v[n]); } return *this; } ArrayList &operator << (const T &v) { Add(v); return *this; } //---------------------------------------------------------------------- //---------------------------------------------------------------------- bool Resize(uint new_size) { if ((int)new_size == (int)array.GetCount() - 1) return true; Array _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 struct SharedArrayList : public ArrayList { virtual bool Insert(const T &v, uint at) { v->AddRef(); return ArrayList ::Insert(v, at); } virtual bool RemoveAt(uint i) { (*this)[i]->RemoveRef(); return ArrayList :: RemoveAt(i); } virtual void Clear(bool free_internals = true) { for (uint n = 0; n < this->GetCount(); ++n) (*this)[n]->RemoveRef(); return ArrayList ::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 ::Iterator iterator(L); T V = iterator.ObjectPtr(); ++iterator) // Iterate over a list of objects. #define ArrayListForeach(T, V, L) \ for (ArrayList ::Iterator V(L); V.IsOver() == false; ++V) /// Find item by using a template identification class. template T ArrayListFindEx(const ArrayList &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__