216 lines
4.3 KiB
C++
216 lines
4.3 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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__
|