util
kdevvarlengtharray.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #ifndef KDEVVARLENGTHARRAY_H
00045 #define KDEVVARLENGTHARRAY_H
00046
00047
00048 #include <QtCore/QtGlobal>
00049 #include <QtCore/QVector>
00050 #include <new>
00051
00054 #define FOREACH_ARRAY(item, container) for(int a = 0, mustDo = 1; a < container.size(); ++a) if((mustDo == 0 || mustDo == 1) && (mustDo = 2)) for(item(container[a]); mustDo; mustDo = 0)
00055
00056 QT_BEGIN_HEADER
00057
00058 QT_BEGIN_NAMESPACE
00059
00060 QT_MODULE(Core)
00061
00062
00063
00064
00065 #ifdef FAKE_KDEVVARLENGTH_ARRAY
00066 template<class T, int Prealloc = 256>
00067 class KDevVarLengthArray : public QVector<T> {
00068 public:
00070 void insert(const T& item, int position) {
00071 QVector<T>::insert(position, item);
00072 }
00073
00074
00075 bool removeOne(const T& value) {
00076 int i = this->indexOf(value);
00077 if(i == -1)
00078 return false;
00079 erase(i);
00080 return true;
00081 }
00082 void erase(int pos) {
00083 this->remove(pos);
00084 }
00085 void append(const T& item) {
00086 QVector<T>::append(item);
00087 }
00088
00089 void pop_back() {
00090 Q_ASSERT(!this->isEmpty());
00091 QVector<T>::pop_back();
00092 }
00093
00094 void append(const T *buf, int size) {
00095 for(int a = 0; a < size; ++a)
00096 append(buf[a]);
00097 }
00098 };
00099 #else
00100
00101 template<class T, int Prealloc = 256>
00102 class KDevVarLengthArray
00103 {
00104 public:
00105 inline explicit KDevVarLengthArray(int size = 0);
00106
00107 inline KDevVarLengthArray(const KDevVarLengthArray<T, Prealloc> &other)
00108 : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
00109 {
00110 append(other.constData(), other.size());
00111 }
00112
00113 inline ~KDevVarLengthArray() {
00114 if (QTypeInfo<T>::isComplex) {
00115 T *i = ptr + s;
00116 while (i-- > ptr)
00117 i->~T();
00118 }
00119 if (ptr != reinterpret_cast<T *>(array))
00120 qFree(ptr);
00121 }
00122 inline KDevVarLengthArray<T, Prealloc> &operator=(const KDevVarLengthArray<T, Prealloc> &other)
00123 {
00124 if (this != &other) {
00125 clear();
00126 append(other.constData(), other.size());
00127 }
00128 return *this;
00129 }
00130
00131 inline int size() const { return s; }
00132 inline int count() const { return s; }
00133 inline bool isEmpty() const { return (s == 0); }
00134 inline void resize(int size);
00135 inline void clear() { resize(0); }
00136
00137 inline int capacity() const { return a; }
00138 inline void reserve(int size);
00139
00140 inline T &operator[](int idx) {
00141 Q_ASSERT(idx >= 0 && idx < s);
00142 return ptr[idx];
00143 }
00144 inline const T &operator[](int idx) const {
00145 Q_ASSERT(idx >= 0 && idx < s);
00146 return ptr[idx];
00147 }
00148
00150 int indexOf(const T& t) const {
00151 for(int a = 0; a < s; ++a)
00152 if(t == ptr[a])
00153 return a;
00154 return -1;
00155 }
00156
00157 inline KDevVarLengthArray& operator<<(const T &t) {
00158 append(t);
00159 return *this;
00160 }
00161
00162 inline void append(const T &t) {
00163 const int idx = s++;
00165 if (s >= a)
00166 realloc(s, s<<1);
00167 if (QTypeInfo<T>::isComplex) {
00168 new (ptr + idx) T(t);
00169 } else {
00170 ptr[idx] = t;
00171 }
00172 }
00173 void append(const T *buf, int size);
00174
00175 inline T *data() { return ptr; }
00176 inline const T *data() const { return ptr; }
00177 inline const T * constData() const { return ptr; }
00178
00180 bool contains(const T& value) const {
00181 for(int a = 0; a < s; ++a)
00182 if(ptr[a] == value)
00183 return true;
00184
00185 return false;
00186 }
00187
00189 void insert(const T& item, int position) {
00190 Q_ASSERT(position >= 0 && position <= size());
00191 resize(s+1);
00192 for(int a = s-1; a > position; --a) {
00193 ptr[a] = ptr[a-1];
00194 }
00195 ptr[position] = item;
00196 }
00197
00199 void erase(int position) {
00200 Q_ASSERT(position >= 0 && position < s);
00201 for(int a = position; a < s-1; ++a) {
00202 ptr[a] = ptr[a+1];
00203 }
00204 resize(s-1);
00205 }
00206
00207
00208 bool removeOne(const T& value) {
00209 for(int a = 0; a < s; ++a) {
00210 if(ptr[a] == value) {
00211 erase(a);
00212 return true;
00213 }
00214 }
00215 return false;
00216 }
00217
00218 T& back() {
00219 return ptr[s-1];
00220 }
00221
00222 const T& back() const {
00223 return ptr[s-1];
00224 }
00225
00226 void pop_back() {
00227 Q_ASSERT(s > 0);
00228 resize(s-1);
00229 }
00230
00231 private:
00232 void realloc(int size, int alloc);
00233
00234 int a;
00235 int s;
00236 T *ptr;
00237 union {
00238
00239 char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
00240 qint64 q_for_alignment_1;
00241 double q_for_alignment_2;
00242 };
00243 };
00244
00245 template <class T, int Prealloc>
00246 Q_INLINE_TEMPLATE KDevVarLengthArray<T, Prealloc>::KDevVarLengthArray(int asize)
00247 : s(asize) {
00248 if (s > Prealloc) {
00249 ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
00250 a = s;
00251 } else {
00252 ptr = reinterpret_cast<T *>(array);
00253 a = Prealloc;
00254 }
00255 if (QTypeInfo<T>::isComplex) {
00256 T *i = ptr + s;
00257 while (i != ptr)
00258 new (--i) T;
00259 }
00260 }
00261
00262 template <class T, int Prealloc>
00263 Q_INLINE_TEMPLATE void KDevVarLengthArray<T, Prealloc>::resize(int asize)
00264 { Q_ASSERT(asize >= 0 && asize < 100000); realloc(asize, qMax(asize, a)); }
00265
00266 template <class T, int Prealloc>
00267 Q_INLINE_TEMPLATE void KDevVarLengthArray<T, Prealloc>::reserve(int asize)
00268 { if (asize > a) realloc(s, asize); }
00269
00270 template <class T, int Prealloc>
00271 Q_OUTOFLINE_TEMPLATE void KDevVarLengthArray<T, Prealloc>::append(const T *abuf, int asize)
00272 {
00273 Q_ASSERT(abuf);
00274 if (asize <= 0)
00275 return;
00276
00277 const int idx = s;
00278 const int news = s + asize;
00279 if (news >= a)
00280 realloc(news, news<<1);
00281 else
00282 s = news;
00283
00284 if (QTypeInfo<T>::isComplex) {
00285 T *i = ptr + idx;
00286 T *j = i + asize;
00287 while (i < j)
00288 new (i++) T(*abuf++);
00289 } else {
00290 qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
00291 }
00292 }
00293
00294 template <class T, int Prealloc>
00295 Q_OUTOFLINE_TEMPLATE void KDevVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
00296 {
00297 Q_ASSERT(aalloc >= asize);
00298 T *oldPtr = ptr;
00299 int osize = s;
00300 s = asize;
00301
00302 if (aalloc != a) {
00303 ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
00304 if (ptr) {
00305 a = aalloc;
00306
00307 if (QTypeInfo<T>::isStatic) {
00308 T *i = ptr + osize;
00309 T *j = oldPtr + osize;
00310 while (i != ptr) {
00311 new (--i) T(*--j);
00312 j->~T();
00313 }
00314 } else {
00315 qMemCopy(ptr, oldPtr, osize * sizeof(T));
00316 }
00317 } else {
00318 ptr = oldPtr;
00319 s = 0;
00320 asize = 0;
00321 }
00322 }
00323
00324 if (QTypeInfo<T>::isComplex) {
00325 if (asize < osize) {
00326 T *i = oldPtr + osize;
00327 T *j = oldPtr + asize;
00328 while (i-- != j)
00329 i->~T();
00330 } else {
00331 T *i = ptr + asize;
00332 T *j = ptr + osize;
00333 while (i != j)
00334 new (--i) T;
00335 }
00336 }
00337
00338 if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
00339 qFree(oldPtr);
00340 }
00341 #endif
00342 QT_END_NAMESPACE
00343
00344 QT_END_HEADER
00345
00346 #endif // QVARLENGTHARRAY_H