/*************************************************************************/ /* 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 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& 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& operator = (const XClassArray& 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(im_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_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_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= (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& 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