deargui-vpl/applications/nodehub/core/XClassArray.h
2026-02-03 18:25:25 +01:00

575 lines
13 KiB
C++

/*************************************************************************/
/* File : XClassArray.h */
/* Author : Aymeric Bard */
/* */
/* Virtools SDK */
/* Copyright (c) Virtools 2000, All Rights Reserved. */
/*************************************************************************/
#ifndef _XCLASSARRAY_H_
#define _XCLASSARRAY_H_ "$Id:$"
#include "XUtil.h"
#ifdef _WIN32
#pragma warning(disable : 4786)
#endif
/************************************************
{filename:XClassArray}
Name: XClassArray
Summary: Class representation of an array.
Remarks:
This array is designed to hold structure or class
which have something specific to do on the construction,
deletion or recopy, like allocating/destroying pointers.
See Also : XArray, XSArray
************************************************/
template <class T>
class XClassArray
{
public:
typedef T* Iterator;
/************************************************
Summary: Constructors.
Input Arguments:
ss: Default number of reserved elements.
a: An array to copy from.
************************************************/
XClassArray(int ss=0)
{
// Allocated
if(ss>0) {
m_Begin = Allocate(ss);
m_End = m_Begin;
m_AllocatedEnd = m_Begin+ss;
} else {
m_AllocatedEnd = 0;
m_Begin = m_End = 0;
}
}
XClassArray(const XClassArray<T>& a)
{
// the resize
int size = a.Size();
m_Begin = Allocate(size);
m_End = m_Begin+size;
m_AllocatedEnd = m_End;
// The copy
XCopy(m_Begin,a.m_Begin,a.m_End);
}
/************************************************
Summary: Destructor.
Remarks:
Release the elements contained in the array. If
you were storing pointers, you need first to iterate
on the array and call delete on each pointer.
************************************************/
~XClassArray()
{
Clear();
}
/************************************************
Summary: Affectation operator.
Remarks:
The content of the array is enterely overwritten
by the given array.
************************************************/
XClassArray<T>& operator = (const XClassArray<T>& a)
{
if(this != &a) {
if (Allocated() >= a.Size()) { // No need to allocate
// The copy
XCopy(m_Begin,a.m_Begin,a.m_End);
m_End = m_Begin + a.Size();
} else {
Free();
// the resize
int size = a.Size();
m_Begin = Allocate(size);
m_End = m_Begin+size;
m_AllocatedEnd = m_End;
// The copy
XCopy(m_Begin,a.m_Begin,a.m_End);
}
}
return *this;
}
/************************************************
Summary: Removes all the elements from an array.
Remarks:
There is no more space reserved after this call.
************************************************/
void Clear()
{
Free();
m_Begin = 0;
m_End = 0;
m_AllocatedEnd = 0;
}
/************************************************
Summary: Reserves n elements for an array.
Remarks:
The elements beyond the reserved limit are
discarded.
************************************************/
void Reserve(int size)
{
// allocation of new size
T* newdata = Allocate(size);
// Recopy of old elements
T* last = XMin(m_Begin+size,m_End);
XCopy(newdata,m_Begin,last);
// new Pointers
Free();
m_End = newdata+(last-m_Begin);
m_Begin = newdata;
m_AllocatedEnd = newdata+size;
}
/************************************************
Summary: Resizes th elements numbers of an array.
Remarks:
If the size is greater than the reserved size,
the array is reallocated at the exact needed size.
If not, there is no reallocation at all. Resize(0)
is faster than Clear() if you know you will probably
push some more elements after.
************************************************/
void Resize(int size)
{
// we check if the array has enough capacity
int oldsize = (m_AllocatedEnd-m_Begin);
// If not, we allocate extra data
if(size > oldsize) Reserve(size);
// We set the end cursor
m_End = m_Begin+size;
}
/************************************************
Summary: Inserts an element at the end of an array.
Input Arguments:
o: object to insert.
************************************************/
void PushBack(const T& o)
{
XInsert(m_End,o);
}
/************************************************
Summary: Expands an array of e elements.
Input Arguments:
e: size to expand.
************************************************/
void Expand(int e = 1)
{
// we check if the array has enough capacity
// If not, we allocate extra data
while (Size()+e > Allocated()) {
Reserve(Allocated()?Allocated()*2:2);
}
// We set the end cursor
m_End += e;
}
/************************************************
Summary: Inserts an element at the start of an array.
Input Arguments:
o: object to insert.
************************************************/
void PushFront(const T& o)
{
XInsert(m_Begin,o);
}
/************************************************
Summary: Inserts an element before another one.
Input Arguments:
i: iterator on the element to insert before.
pos: position to insert the object
o: object to insert.
Remarks:
The element to insert before is given as
an iterator on it, i.e. a pointer on it in
this case.
************************************************/
void Insert(T* i, const T& o)
{
// TODO : s'assurer que i est dans les limites...
if(i<m_Begin || i>m_End) return;
// The Call
XInsert(i,o);
}
void Insert(int pos, const T& o)
{
Insert(m_Begin+pos,o);
}
/************************************************
Summary: Removes the last element of an array.
************************************************/
void PopBack()
{
// we remove the last element only if it exists
if(m_End > m_Begin) XRemove(m_End-1);
}
/************************************************
Summary: Removes the first element of an array.
************************************************/
void PopFront()
{
// we remove the first element only if it exists
if(m_Begin != m_End) XRemove(m_Begin);
}
/************************************************
Summary: Removes an element.
Input Arguments:
i: iterator on the element to remove.
pos: position of the object to remove.
Return Value: an iterator on the next
element after the element removed (to go on with
an iteration).
Remarks:
The elements are given by iterators on them,
i.e. pointer on them in this case.
************************************************/
T* Remove(T* i)
{
// we ensure i is in boundary...
if(i<m_Begin || i>=m_End) return 0;
// the Call
return XRemove(i);
}
T* RemoveAt(int pos)
{
// we ensure i is in boundary...
if (pos >= Size()) return NULL;
// the Call
return XRemove(m_Begin+pos);
}
void FastRemove(const T& o)
{
FastRemove(Find(o));
}
void FastRemove(const Iterator& iT)
{
// we ensure i is in boundary...
if(iT<m_Begin || iT>=m_End)
return;
m_End--;
if (iT < m_End)
*iT = *m_End;
}
/************************************************
Summary: Access to an array element.
Input Arguments:
i: index of the element to access.
Return Value: a reference on the object accessed.
Remarks:
No test are provided on i.
************************************************/
T& operator [](int i) const
{
XASSERT(i>=0 && i<Size());
return *(m_Begin+i);
}
/************************************************
Summary: Access to an array element.
Input Arguments:
i: index of the element to access.
Return Value: a pointer on the object accessed.
Remarks:
End() is returned if i is outside the array
limits.
************************************************/
T* At(unsigned int i) const
{
if (i >= (unsigned int)Size()) return m_End;
return m_Begin+i;
}
/************************************************
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)
{
char buffer[sizeof(T)];
memcpy(buffer,m_Begin+pos1,sizeof(T));
memcpy(m_Begin+pos1,m_Begin+pos2,sizeof(T));
memcpy(m_Begin+pos2,buffer,sizeof(T));
}
/************************************************
Summary: Swaps two arrays.
Input Arguments:
o: second array to swap.
************************************************/
void Swap(XClassArray<T>& a)
{
XSwap(m_Begin,a.m_Begin);
XSwap(m_End,a.m_End);
XSwap(m_AllocatedEnd,a.m_AllocatedEnd);
}
/************************************************
Summary: Returns the last element of an array.
Remarks:
No test are provided to see if there is an
element.
************************************************/
T& Back() {return *(End()-1);}
const T& Back() const {return *(End()-1);}
/************************************************
Summary: Returns an iterator on the first element.
Example:
Typically, an algorithm iterating on an array
looks like:
for(T* t = a.Begin(); t != a.End(); ++t) {
// do something with *t
}
************************************************/
T* Begin() const {return m_Begin;}
/************************************************
Summary: Returns an iterator after the last element.
************************************************/
T* End() const {return m_End;}
/************************************************
Summary: Returns the elements number.
************************************************/
int Size() const {return m_End-m_Begin;}
/************************************************
Summary: Returns the elements allocated.
************************************************/
int Allocated() const {return m_AllocatedEnd-m_Begin;}
/************************************************
Summary: Returns the occupied size in memory in bytes
Parameters:
addstatic: TRUE if you want to add the size occupied
by the class itself.
************************************************/
int GetMemoryOccupation(XBOOL addstatic=FALSE) const {
return Allocated()*sizeof(T)+(addstatic?sizeof(*this):0);
}
/************************************************
Summary: Finds an element.
Input Arguments:
o: element to find.
Return Value: a pointer on the first object found
or End() if the object is not found.
************************************************/
T* Find(const T& o) const
{
// If the array is empty
if(!(m_End - m_Begin)) return m_End;
T* t = m_Begin;
while(t < m_End && *t != o)
++t;
return t;
}
/************************************************
Summary: Returns the position of an element.
Input Arguments:
o: element to find.
Return Value: position or -1 if not found.
************************************************/
int GetPosition(const T& o) const
{
T* t = Find(o);
// If the element is not found
if(t == m_End) return -1;
// else return the position
return t-m_Begin;
}
static
int XCompare(const void *elem1, const void *elem2 )
{
return *(T*)elem1 - *(T*)elem2;
}
/************************************************
Summary: Sorts an array with a quick sort.
Input Arguments:
compare: The function comparing two elements.
Remarks:
Two sorts algorithm are available : BubbleSort
and (quick)Sort.
************************************************/
void Sort( VxSortFunc Fct = XCompare)
{
qsort(m_Begin,Size(),sizeof(T),Fct);
}
protected:
///
// Methods
void XCopy(T* dest, T* start, T* end)
{
while(start != end) {
*dest = *start;
start++;
dest++;
}
}
void XMove(T* dest, T* start, T* end)
{
if (dest>start)
{
dest += end-start;
while(start != end) {
--dest;
--end;
*dest = *end;
}
} else XCopy(dest,start,end);
}
void XInsert(T* i, const T& o)
{
// Test For Reallocation
if(m_End+1 > m_AllocatedEnd) {
int newsize = (m_AllocatedEnd-m_Begin)*2;//+m_AllocationSize;
if(!newsize) newsize = 1;
T* newdata = Allocate(newsize);
// copy before insertion point
XCopy(newdata,m_Begin,i);
// copy the new element
T* insertionpoint = newdata+(i-m_Begin);
*(insertionpoint) = o;
// copy after insertion point
XCopy(insertionpoint+1,i,m_End);
// New Pointers
m_End = newdata+(m_End-m_Begin);
Free();
m_Begin = newdata;
m_AllocatedEnd = newdata+newsize;
} else {
// copy after insertion point
XMove(i+1,i,m_End);
// copy the new element
*i = o;
}
m_End++;
}
T* XRemove(T* i)
{
// copy after insertion point
XMove(i,i+1,m_End);
m_End--;
return i;
}
///
// Allocation and deallocation methods : to be override for alignement purposes
T* Allocate(int size)
{
if(size) return new T[size];
else return 0;
}
void Free()
{
delete [] m_Begin;
}
///
// Members
T* m_Begin;
T* m_End;
T* m_AllocatedEnd;
};
#endif