593 lines
9.4 KiB
C++
593 lines
9.4 KiB
C++
#ifndef _XSARRAY_OPT_H_
|
|
#define _XSARRAY_OPT_H_
|
|
|
|
|
|
#define SZ_ONE_ELEMENT(a) (sizeof(T)==sizeof(T*) && (a <= 1))
|
|
#define SET_DATA(a) ( (*(T*)&m_Data) = a)
|
|
|
|
/************************************************
|
|
Name: XSArray
|
|
|
|
Summary: Class representation of an array.
|
|
|
|
Remarks:
|
|
This array behaves exactly like the XArray,
|
|
exept that its size is exactly the number it contains,
|
|
so it is more slow for adding and removing elements,
|
|
but it occupies less memory.
|
|
|
|
|
|
|
|
See Also : XClassArray, XArray
|
|
************************************************/
|
|
template <class T>
|
|
class XSArray
|
|
{
|
|
public:
|
|
|
|
XSArray()
|
|
{
|
|
// Init
|
|
m_Data = NULL;
|
|
m_Size = 0;
|
|
}
|
|
|
|
|
|
XSArray(const XSArray<T>& a)
|
|
{
|
|
// the resize
|
|
int size = a.Size();
|
|
if(SZ_ONE_ELEMENT(size)){
|
|
m_Data = a.m_Data;
|
|
}else{
|
|
m_Data = Allocate(size);
|
|
// The copy
|
|
XCopy(m_Data,a.Begin(),a.End());
|
|
}
|
|
m_Size = size;
|
|
}
|
|
|
|
|
|
~XSArray()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
XSArray<T>& operator = (const XSArray<T>& a)
|
|
{
|
|
if(this != &a) {
|
|
Free();
|
|
// the resize
|
|
int size = a.Size();
|
|
if(SZ_ONE_ELEMENT(size)){
|
|
m_Data = a.m_Data;
|
|
}else{
|
|
m_Data = Allocate(size);
|
|
// The copy
|
|
XCopy(m_Data,a.Begin(),a.End());
|
|
}
|
|
m_Size = size;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
XSArray<T>& operator += (const XSArray<T>& a)
|
|
{
|
|
int size = a.Size();
|
|
if (size) {
|
|
int oldsize = Size();
|
|
if(SZ_ONE_ELEMENT(oldsize+size)){
|
|
// Empty += Single Element
|
|
m_Data = a.m_Data;
|
|
}else{
|
|
T* temp = Allocate(oldsize+size);
|
|
// we recopy the old array
|
|
XCopy(temp,Begin(),End());
|
|
// we copy the given array
|
|
XCopy(temp+oldsize,a.Begin(),a.End());
|
|
|
|
// we free the old memory
|
|
Free();
|
|
// we set the new pointer
|
|
m_Data = temp;
|
|
}
|
|
m_Size = oldsize+size;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
XSArray<T>& operator -= (const XSArray<T>& a)
|
|
{
|
|
int size = a.Size();
|
|
if (size) {
|
|
int oldsize = Size();
|
|
if (oldsize) {
|
|
if(SZ_ONE_ELEMENT(oldsize)){
|
|
T* it = Begin();
|
|
if(a.Find(*it) != a.End()) {
|
|
// Our only Item is in the array
|
|
// we clear the array
|
|
Clear();
|
|
}
|
|
}else{
|
|
|
|
T* newarray = Allocate(oldsize);
|
|
T* temp = newarray;
|
|
|
|
for(T* t = Begin(); t != End(); ++t) {
|
|
// we search for the element in the other array
|
|
T* iEnd = a.End();
|
|
if(a.Find(*t) == iEnd) {
|
|
// the element is not in the other array, we copy it to the new one
|
|
*temp = *t;
|
|
++temp;
|
|
}
|
|
}
|
|
|
|
// we free the memory
|
|
Free();
|
|
// the resize
|
|
int size = temp - newarray;
|
|
if(size){
|
|
if(SZ_ONE_ELEMENT(size)){
|
|
SET_DATA(*newarray);
|
|
}else{
|
|
m_Data = Allocate(size);
|
|
// The copy
|
|
XCopy(m_Data,newarray,temp);
|
|
}
|
|
m_Size = size;
|
|
}else{
|
|
m_Data = NULL;
|
|
m_Size = 0;
|
|
}
|
|
XFree(newarray);
|
|
}
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
void Clear()
|
|
{
|
|
Free();
|
|
}
|
|
|
|
|
|
void Fill(const T& o)
|
|
{
|
|
T* iEnd = End();
|
|
for(T* t = Begin(); t !=iEnd; ++t)
|
|
*t=o;
|
|
}
|
|
|
|
|
|
void Resize(int size)
|
|
{
|
|
// No change ?
|
|
if (size == Size())
|
|
return;
|
|
|
|
if(0 == size){
|
|
Clear();
|
|
return;
|
|
}
|
|
|
|
if(SZ_ONE_ELEMENT(size)){
|
|
// the New size is 1
|
|
// And the array was not of size 1 already
|
|
if(m_Size){
|
|
T dat = m_Data[0];
|
|
SET_DATA(dat);
|
|
}else{
|
|
(int)m_Data = 0xcdcdcdcd;
|
|
}
|
|
m_Size = 1;
|
|
}else{
|
|
// the new data does not fit in one slot
|
|
// [0..N] -> N
|
|
// allocation of new size
|
|
T* newdata = Allocate(size);
|
|
|
|
// Recopy of old elements
|
|
T* last = XMin(Begin()+size,End());
|
|
XCopy(newdata,Begin(),last);
|
|
|
|
// new Pointers
|
|
Free();
|
|
m_Data = newdata;
|
|
}
|
|
m_Size = size;
|
|
}
|
|
|
|
|
|
void PushBack(const T& o)
|
|
{
|
|
XInsert(End(),o);
|
|
}
|
|
|
|
|
|
void PushFront(const T& o)
|
|
{
|
|
XInsert(Begin(),o);
|
|
}
|
|
|
|
|
|
void Insert(T* i, const T& o)
|
|
{
|
|
// TODO : s'assurer que i est dans les limites...
|
|
if(i<Begin() || i>End())
|
|
return;
|
|
|
|
// The Call
|
|
XInsert(i,o);
|
|
}
|
|
|
|
|
|
void Insert(int pos, const T& o)
|
|
{
|
|
Insert(Begin()+pos,o);
|
|
}
|
|
|
|
|
|
void Move(T* i, T* n)
|
|
{
|
|
// TODO : s'assurer que i est dans les limites...
|
|
if(i<Begin() || i>End()) return;
|
|
if(n<Begin() || n>End()) return;
|
|
|
|
// The Call
|
|
int insertpos = i - Begin();
|
|
if (n < i)
|
|
--insertpos;
|
|
|
|
T tn = *n;
|
|
XRemove(n);
|
|
Insert(insertpos,tn);
|
|
}
|
|
|
|
|
|
void PopBack()
|
|
{
|
|
// we remove the last element only if it exists
|
|
if(Size())
|
|
XRemove(End()-1);
|
|
}
|
|
|
|
|
|
void PopFront()
|
|
{
|
|
// we remove the first element only if it exists
|
|
if(Size())
|
|
XRemove(Begin());
|
|
}
|
|
|
|
|
|
T* Remove(T* i)
|
|
{
|
|
// we ensure i is in boundary...
|
|
if(i<Begin() || i>=End())
|
|
return 0;
|
|
// the Call
|
|
return XRemove(i);
|
|
}
|
|
|
|
|
|
XBOOL RemoveAt(unsigned int pos,T& old)
|
|
{
|
|
T* t = Begin()+pos;
|
|
// we ensure i is in boundary...
|
|
if(t >= End()) return 0;
|
|
old = *t; // we keep the old value
|
|
// the removal
|
|
XRemove(t);
|
|
return TRUE; // really removed
|
|
}
|
|
|
|
|
|
T* RemoveAt(int pos)
|
|
{
|
|
// we ensure i is in boundary...
|
|
if((pos < 0) || (Begin()+pos >= End())) return 0;
|
|
|
|
// the Call
|
|
return XRemove(Begin()+pos);
|
|
}
|
|
|
|
|
|
int Remove(const T& o)
|
|
{
|
|
for(T* t = Begin(); t != End(); ++t) {
|
|
if(*t == o) {
|
|
XRemove(t);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
T& operator [](unsigned int i) const
|
|
{
|
|
return *(Begin()+i);
|
|
}
|
|
|
|
|
|
T* At(unsigned int i) const
|
|
{
|
|
return Begin()+i;
|
|
}
|
|
|
|
|
|
T* Find(const T& o) const
|
|
{
|
|
T* tEnd = End();
|
|
for(T* t = Begin(); t != tEnd; ++t) {
|
|
if(*t == o) return t;
|
|
}
|
|
return tEnd;
|
|
}
|
|
|
|
|
|
XBOOL IsHere(const T& o) const
|
|
{
|
|
T* t = Begin();
|
|
T* tEnd = End();
|
|
while(t < tEnd && *t != o) ++t;
|
|
|
|
return (t != tEnd);
|
|
}
|
|
|
|
|
|
int GetPosition(const T& o) const
|
|
{
|
|
T* tEnd = End();
|
|
for(T* t = Begin(); t != tEnd; ++t) {
|
|
if(*t == o)
|
|
return (t-Begin());
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/************************************************
|
|
Summary: Swaps two items in array.
|
|
|
|
Input Arguments:
|
|
pos1: position of first item to swap
|
|
pos2: position of second item to swap.
|
|
************************************************/
|
|
void Swap(int pos1,int pos2)
|
|
{
|
|
if(sizeof(T) == sizeof(void*)){
|
|
T* t1 = Begin()+pos1;
|
|
T* t2 = Begin()+pos2;
|
|
T temp = *t1;
|
|
*t1=*t2;
|
|
*t2 = temp;
|
|
}else{
|
|
char buffer[sizeof(T)];
|
|
memcpy(buffer,Begin()+pos1,sizeof(T));
|
|
memcpy(Begin()+pos1,Begin()+pos2,sizeof(T));
|
|
memcpy(Begin()+pos2,buffer,sizeof(T));
|
|
}
|
|
}
|
|
|
|
|
|
void Swap(XSArray<T>& a)
|
|
{
|
|
XSwap(m_Data,a.m_Data);
|
|
XSwap(m_Size,a.m_Size);
|
|
}
|
|
|
|
|
|
static
|
|
int XCompare(const void *elem1, const void *elem2 )
|
|
{
|
|
return *(T*)elem1 < *(T*)elem2;
|
|
}
|
|
|
|
|
|
// compare func should return :
|
|
// < 0 elem1 less than elem2
|
|
// 0 elem1 equivalent to elem2
|
|
// > 0 elem1 greater than elem2
|
|
// elem1 & elem2 T*
|
|
|
|
void Sort( VxSortFunc compare = XCompare )
|
|
{
|
|
if (Size() > 1) qsort(Begin(),Size(),sizeof(T),compare);
|
|
}
|
|
|
|
|
|
void BubbleSort( VxSortFunc compare = XCompare)
|
|
{
|
|
if (!compare) return;
|
|
if ((Size())<=1) return;
|
|
|
|
BOOL Noswap=TRUE;
|
|
|
|
T* iEnd0 = End();
|
|
T* iEnd1 = End()-1;
|
|
|
|
for (T* it1=Begin()+1;it1<iEnd0;it1++) {
|
|
for (T* it2=iEnd1;it2>=it1;it2--) {
|
|
T* t2= it2-1;
|
|
if (compare(it2,t2) < 0) {
|
|
XSwap(*it2,*t2);
|
|
Noswap=FALSE;
|
|
}
|
|
}
|
|
if (Noswap)
|
|
break;
|
|
Noswap=TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
T* Begin() const {
|
|
if(SZ_ONE_ELEMENT(m_Size))
|
|
return m_Size ? (T*) &m_Data : NULL;
|
|
return m_Data;
|
|
}
|
|
|
|
|
|
T* End() const {
|
|
if(SZ_ONE_ELEMENT(m_Size)){
|
|
return m_Size ? ((T*)&m_Data)+1 : 0;
|
|
}
|
|
return m_Data+m_Size;
|
|
}
|
|
|
|
|
|
int Size() const {
|
|
return m_Size;
|
|
}
|
|
|
|
|
|
int GetMemoryOccupation(XBOOL addstatic=FALSE) const {
|
|
if(SZ_ONE_ELEMENT(m_Size)){
|
|
return addstatic?sizeof(this):0;
|
|
}
|
|
return Size()*sizeof(T)+addstatic?sizeof(this):0;
|
|
}
|
|
|
|
protected:
|
|
///
|
|
// Methods
|
|
|
|
|
|
void XCopy(T* dest, T* start, T* end)
|
|
{
|
|
int size = ((XBYTE*)end - (XBYTE*)start);
|
|
if(size)
|
|
memcpy(dest,start,size);
|
|
}
|
|
|
|
|
|
void XMove(T* dest, T* start, T* end)
|
|
{
|
|
int size = ((XBYTE*)end - (XBYTE*)start);
|
|
if(size)
|
|
memmove(dest,start,size);
|
|
}
|
|
|
|
|
|
void XInsert(T* i, const T& o)
|
|
{
|
|
// Reallocation
|
|
int newsize = Size()+1;
|
|
if(SZ_ONE_ELEMENT(newsize)){
|
|
//0->1
|
|
m_Size = newsize;
|
|
SET_DATA(o);
|
|
}else{
|
|
//[1..N]->[2..N+1]
|
|
T* newdata = Allocate(newsize);
|
|
// copy before insertion point
|
|
XCopy(newdata,Begin(),i);
|
|
|
|
// copy the new element
|
|
T* insertionpoint = newdata+(i-Begin());
|
|
*(insertionpoint) = o;
|
|
|
|
// copy after insertion point
|
|
XCopy(insertionpoint+1,i,End());
|
|
|
|
// New Pointers
|
|
Free();
|
|
m_Size = newsize;
|
|
m_Data = newdata;
|
|
}
|
|
}
|
|
|
|
|
|
T* XRemove(T* i)
|
|
{
|
|
if(0 == m_Size)
|
|
return i;
|
|
|
|
int newsize = m_Size-1;
|
|
|
|
if(SZ_ONE_ELEMENT(newsize)){
|
|
if(newsize){
|
|
// [2]->[1]
|
|
T data;
|
|
if(Begin() == i){
|
|
data = *Begin();
|
|
}else{
|
|
data = *End();
|
|
}
|
|
Free();
|
|
m_Size = newsize;
|
|
SET_DATA(data);
|
|
}else{
|
|
// 1->0
|
|
Free();
|
|
}
|
|
}else{
|
|
T* newdata = Allocate(newsize);
|
|
|
|
// copy before insertion point
|
|
XCopy(newdata,Begin(),i);
|
|
|
|
// copy after insertion point
|
|
T* deletionpoint = newdata+(i-Begin());
|
|
XCopy(deletionpoint,i+1,End());
|
|
i = deletionpoint;
|
|
|
|
// New Pointers
|
|
Free();
|
|
m_Size = newsize;
|
|
m_Data = newdata;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
///
|
|
// Allocation and deallocation methods : to override for alignment purposes
|
|
|
|
|
|
T* Allocate(int size)
|
|
{
|
|
if(size)
|
|
return (T*) XAllocate(sizeof(T)*size);
|
|
else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void Free() {
|
|
if(!SZ_ONE_ELEMENT(m_Size)){
|
|
XFree(m_Data);
|
|
}
|
|
m_Size = 0;
|
|
m_Data = NULL;
|
|
}
|
|
|
|
|
|
void XFree(T* data){
|
|
free(data);
|
|
}
|
|
|
|
|
|
void* XAllocate(unsigned int size){
|
|
return malloc(size);
|
|
}
|
|
|
|
// Members
|
|
private:
|
|
|
|
T* m_Data;
|
|
|
|
unsigned int m_Size;
|
|
};
|
|
|
|
#endif |