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