#ifndef LIME_UTILS_QUICK_VEC_H #define LIME_UTILS_QUICK_VEC_H #include #include #include namespace lime { template void DoDelete(T &item) { } template void DoDelete(T *&item) { delete item; item = 0; } // Little vector/set class, optimised for small data and not using many malloc calls. // Data are allocated with "malloc", so they should not rely on constructors etc. template class QuickVec { enum { QBufSize = QBUF_SIZE_ }; public: typedef T_ *iterator; typedef const T_ * const_iterator; public: QuickVec () { mPtr = QBUF_SIZE_==0 ? 0 : mQBuf; mAlloc = QBufSize; mSize = 0; } QuickVec (const QuickVec &inRHS) { if (QBUF_SIZE_!=0 && inRHS.mSize<=QBufSize) { mAlloc = QBufSize; mPtr = mQBuf; } else { mAlloc = inRHS.mAlloc; mPtr = (T_ *)malloc(mAlloc * sizeof(T_)); } mSize = inRHS.mSize; memcpy (mPtr,inRHS.mPtr,sizeof(T_)*mSize); } int Mem() const { return mAlloc * sizeof(T_); } QuickVec (const T_ *inData,int inLen) { mPtr = QBUF_SIZE_==0 ? 0 : mQBuf; mAlloc = QBufSize; mSize = 0; resize(inLen); memcpy(mPtr,inData,sizeof(T_)*inLen); } QuickVec (int inLen) { mPtr = QBUF_SIZE_==0 ? 0 : mQBuf; mAlloc = QBufSize; mSize = 0; resize(inLen); } ~QuickVec () { if (QBUF_SIZE_==0 || mPtr!=mQBuf){ if (mPtr) { free(mPtr); } } } void clear () { if (QBUF_SIZE_==0) { if (mPtr) { free(mPtr); } mPtr = 0; mAlloc = 0; } else if (mPtr!=mQBuf) { free(mPtr); mPtr = mQBuf; mAlloc = QBufSize; } mSize = 0; } void Set(const T_ *inData,int inN) { resize(inN); if (inN) { memcpy(mPtr,inData,inN*sizeof(T_)); } } void Zero() { if (mPtr && mSize) memset(mPtr,0,mSize*sizeof(T_)); } // This assumes the values in the array are sorted. template void Change(X_ inValue,D_ inDiff) { if (mSize==0) { mPtr[mSize++] = T_(inValue,inDiff); return; } // Before/at start if (mPtr[0]==inValue) { mPtr[0] += inDiff; } else if (mPtr[0]>inValue) { InsertAt(0, T_(inValue,inDiff) ); } else { int last = mSize-1; // After/on end if (mPtr[last]==inValue) { mPtr[last] += inDiff; } else if (mPtr[last]min+1) { int middle = (max+min+1)/2; T_ &v = mPtr[middle]; if (v==inValue) { v += inDiff; return; } if (v=mPtr[last]) { if (inValue==mPtr[last]) EraseAt(last); else { Grow(); mPtr[mSize] = inValue; ++mSize; } } else { // between 0 ... last int min = 0; int max = last; while(max>min+1) { int middle = (max+min+1)/2; T_ v = mPtr[middle]; if (v==inValue) { EraseAt(middle); return; } if (v=mAlloc) { if (QBUF_SIZE_!=0 && mPtr==mQBuf) { mPtr = (T_ *)malloc(sizeof(T_)*(QBufSize*2)); memcpy(mPtr, mQBuf, sizeof(mQBuf)); mAlloc = QBufSize*2; } else { if (mAlloc) mAlloc *= 2; else mAlloc = 16; mPtr = (T_*)realloc(mPtr, sizeof(T_)*mAlloc); } } } void reserve(int inSize) { if (mAllocQBufSize) ) { mAlloc = inSize; if (QBUF_SIZE_==0 || mPtr!=mQBuf) { mPtr = (T_ *)realloc(mPtr,sizeof(T_)*mAlloc); } else { T_ *buf = (T_ *)malloc(sizeof(T_)*mAlloc); memcpy(buf,mPtr,mSize*sizeof(T_)); mPtr = buf; } } } void resize(int inSize) { if (mAllocmSize || inFirst<0) return; if (inFirst+inLen>=mSize || inLen<0) resize(inFirst); else { memmove(mPtr + inFirst, mPtr + inFirst + inLen, (mSize-inFirst-inLen) * sizeof(T_) ); mSize -= inLen; } } inline void InsertAt(int inPos,const T_ &inValue) { Grow(); memmove(mPtr + inPos + 1, mPtr + inPos, (mSize-inPos) * sizeof(T_) ); memcpy(mPtr+inPos,&inValue, sizeof(T_)); ++mSize; } inline void InsertAt(int inPos,const T_ *inValues,int inN) { resize(mSize+inN); memmove(mPtr + inPos + inN, mPtr + inPos, (mSize-inPos-inN) * sizeof(T_) ); memcpy(mPtr+inPos,inValues,inN*sizeof(T_)); } bool operator == (const QuickVec &inRHS) { return (*mPtr == *(inRHS.mPtr)); } bool operator != (const QuickVec &inRHS) { return !(*mPtr == *(inRHS.mPtr)); } inline int size() const { return mSize; } inline bool empty() const { return mSize==0; } inline T_& operator[](int inIndex) { return mPtr[inIndex]; } inline T_& last() { return mPtr[mSize-1]; } inline const T_& operator[](int inIndex) const { return mPtr[inIndex]; } inline iterator begin() { return mPtr; } inline iterator rbegin() { return mPtr + mSize -1; } inline iterator end() { return mPtr + mSize; } inline const_iterator begin() const { return mPtr; } inline const_iterator rbegin() const { return mPtr + mSize - 1; } inline const_iterator end() const { return mPtr + mSize; } void swap( QuickVec &inRHS ) { if (QBUF_SIZE_==0) { std::swap(mPtr,inRHS.mPtr); } else if (mPtr!=mQBuf) { // Both "real" pointers - just swap them if (inRHS.mPtr!=inRHS.mQBuf) { std::swap(mPtr,inRHS.mPtr); } else { // RHS in in the qbuf, we have a pointer memcpy(mQBuf,inRHS.mQBuf,inRHS.mSize*sizeof(T_)); inRHS.mPtr = mPtr; mPtr = mQBuf; } } else { // We have a qbuf, rhs has a pointer if (inRHS.mPtr!=inRHS.mQBuf) { memcpy(inRHS.mQBuf,mQBuf,mSize*sizeof(T_)); mPtr = inRHS.mPtr; inRHS.mPtr = inRHS.mQBuf; } else { // Both using QBuf ... if (mSize && inRHS.mSize) { T_ tmp[QBufSize]; memcpy(tmp,mPtr,mSize*sizeof(T_)); memcpy(mPtr,inRHS.mPtr,inRHS.mSize*sizeof(T_)); memcpy(inRHS.mPtr,tmp,mSize*sizeof(T_)); } else if (mSize) memcpy(inRHS.mQBuf,mQBuf,mSize*sizeof(T_)); else memcpy(mQBuf,inRHS.mQBuf,inRHS.mSize*sizeof(T_)); } } std::swap(mAlloc,inRHS.mAlloc); std::swap(mSize,inRHS.mSize); } QuickVec &operator=(const QuickVec &inRHS) { if ( (QBUF_SIZE_==0 || mPtr!=mQBuf) && mPtr ) free(mPtr); if (QBUF_SIZE_!=0 && inRHS.mSize<=QBufSize) { mPtr = mQBuf; mAlloc = QBufSize; } else { mAlloc = inRHS.mAlloc; mPtr = (T_ *)(mAlloc ? malloc( mAlloc * sizeof(T_)) : 0); } mSize = inRHS.mSize; if (mSize) memcpy(mPtr,inRHS.mPtr,mSize*sizeof(T_)); return *this; } void DeleteAll() { for(int i=0;i &inOther) { int s = mSize; resize(mSize+inOther.mSize); for(int i=0;i