00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 template <class T> Array<T>::Array()
00022 : mpArray(NULL),
00023 mReservedLen(0),
00024 mUsedLen(0),
00025 mGrowLen(kDefaultGrowthLength)
00026 {
00027 if(mGrowLen < 1) {
00028
00029 mGrowLen = 1;
00030 }
00031 }
00032
00033 template <class T> Array<T>::Array(size_t usedLength, const T& defaultVal, size_t growLength)
00034 : mpArray(NULL),
00035 mReservedLen(0),
00036 mUsedLen(0),
00037 mGrowLen(growLength)
00038 {
00039 if(mGrowLen < 1) {
00040
00041 mGrowLen = 1;
00042 }
00043
00044
00045 if(usedLength > 0) {
00046 mpArray = ArrayAllocate(usedLength);
00047 if (mpArray == NULL) {
00048 handleOutOfMemory();
00049 }
00050 else {
00051
00052
00053 ArrayConstruct(mpArray, usedLength, defaultVal);
00054
00055 mReservedLen = usedLength;
00056 mUsedLen = usedLength;
00057 }
00058 }
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068 template <class T> Array<T>::Array(const Array<T>& src)
00069 : mpArray(NULL),
00070 mReservedLen(src.mReservedLen),
00071 mUsedLen(src.mUsedLen),
00072 mGrowLen(src.mGrowLen)
00073 {
00074 if (mReservedLen > 0) {
00075 mpArray = ArrayAllocate(mReservedLen);
00076 if (mpArray == NULL) {
00077 handleOutOfMemory();
00078 mReservedLen = 0;
00079 mUsedLen = 0;
00080 }
00081 else {
00082 ArrayCopyConstruct(mpArray, src.mpArray, mUsedLen);
00083 }
00084 }
00085 }
00086
00087 template <class T> Array<T>::~Array()
00088 {
00089 if (mpArray != NULL) {
00090 ArrayDestruct(mpArray, mUsedLen);
00091 ArrayDeAllocate(mpArray);
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 template <class T> Array<T>& Array<T>::operator = (const Array<T>& src)
00105 {
00106 if (this != &src) {
00107
00108 if (mReservedLen < src.mUsedLen) {
00109
00110 if (mpArray != NULL) {
00111 ArrayDestruct(mpArray, mUsedLen);
00112 ArrayDeAllocate(mpArray);
00113 }
00114
00115 mReservedLen = src.mUsedLen;
00116 mpArray = ArrayAllocate(mReservedLen);
00117 if (mpArray == NULL) {
00118 handleOutOfMemory();
00119 mReservedLen = 0;
00120 mUsedLen = 0;
00121 return *this;
00122 }
00123
00124 mUsedLen = src.mUsedLen;
00125 ArrayCopyConstruct(mpArray, src.mpArray, mUsedLen);
00126 }
00127 else if(mUsedLen < src.mUsedLen) {
00128
00129 ArrayCopy(mpArray, src.mpArray, mUsedLen);
00130
00131 ArrayCopyConstruct(mpArray + mUsedLen, src.mpArray + mUsedLen, src.mUsedLen - mUsedLen);
00132 mUsedLen = src.mUsedLen;
00133 }
00134 else if(mUsedLen > src.mUsedLen) {
00135
00136 ArrayCopy(mpArray, src.mpArray, src.mUsedLen);
00137
00138 ArrayDestruct(mpArray + src.mUsedLen, mUsedLen - src.mUsedLen);
00139 mUsedLen = src.mUsedLen;
00140 }
00141 else {
00142
00143 ArrayCopy(mpArray, src.mpArray, mUsedLen);
00144 }
00145 }
00146 return *this;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 template <class T> bool Array<T>::operator == (const Array<T>& cpr) const
00157 {
00158 if (mUsedLen == cpr.mUsedLen)
00159 {
00160 for (size_t i = 0; i < mUsedLen; i++)
00161 if (mpArray[i] != cpr.mpArray[i])
00162 return false;
00163 return true;
00164 }
00165 return false;
00166 }
00167
00168
00169
00170
00171 template <class T> Array<T>& Array<T>::setAll(const T& value)
00172 {
00173 for (size_t i = 0; i < mUsedLen; i++) {
00174 mpArray[i] = value;
00175 }
00176 return *this;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 template <class T> Array<T>& Array<T>::append(const Array<T>& otherArray)
00186 {
00187 size_t otherLen = otherArray.length();
00188 if (otherLen == 0) {
00189 return *this;
00190 }
00191 size_t newLen = mUsedLen + otherLen;
00192 if (newLen > mReservedLen) {
00193 setLengthReserved(newLen);
00194 }
00195
00196 ArrayCopyConstruct(mpArray + mUsedLen, otherArray.mpArray, otherLen);
00197
00198 mUsedLen = newLen;
00199 return *this;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 template <class T> Array<T>& Array<T>::insertAt(size_t index, const T& value)
00210 {
00211 DbgAssert(index >= 0 && index <= mUsedLen);
00212
00213 if (mUsedLen >= mReservedLen) {
00214 size_t growth = (mUsedLen * sizeof(T)) < kArrayGrowthThreshold ?
00215 (mUsedLen / 2) : kArrayGrowthThreshold / sizeof(T);
00216 setLengthReserved(mUsedLen + __max(growth, mGrowLen));
00217 }
00218
00219 if (index != mUsedLen) {
00220
00221
00222 ArrayCopyConstruct(mpArray + mUsedLen, mpArray + mUsedLen - 1, 1);
00223
00224
00225 for(size_t i = mUsedLen - 1; i > index; --i) {
00226 mpArray[i] = mpArray[i-1];
00227 }
00228
00229
00230 mpArray[index] = value;
00231 }
00232 else {
00233
00234 ArrayCopyConstruct(mpArray + mUsedLen, &value, 1);
00235 }
00236
00237 mUsedLen++;
00238 return *this;
00239 }
00240
00241 template <class T> Array<T>& Array<T>::insertAt(size_t index, const T* values, size_t count)
00242 {
00243 DbgAssert(index >= 0 && index <= mUsedLen);
00244
00245 if(index <= mUsedLen) {
00246
00247 size_t lastInsertIndex = index + count - 1;
00248
00249
00250 size_t newUsedLen = mUsedLen + count;
00251 if(newUsedLen > mReservedLen) {
00252
00253
00254 T* newArray = ArrayAllocate(newUsedLen);
00255 if(newArray == NULL) {
00256
00257 handleOutOfMemory();
00258 return *this;
00259 }
00260
00261
00262 ArrayCopyConstruct(newArray, mpArray, index);
00263
00264
00265 ArrayCopyConstruct(newArray + index, values, count);
00266
00267
00268 if(index < mUsedLen) {
00269 ArrayCopyConstruct(newArray + index + count, mpArray + index, mUsedLen - index);
00270 }
00271
00272
00273 ArrayDestruct(mpArray, mUsedLen);
00274 ArrayDeAllocate(mpArray);
00275
00276 mpArray = newArray;
00277 mUsedLen = newUsedLen;
00278 mReservedLen = newUsedLen;
00279 }
00280 else {
00281 if(index < mUsedLen) {
00282
00283 ArrayCopyConstruct(mpArray + mUsedLen, mpArray + mUsedLen - count, count);
00284
00285
00286 if((index + count) < mUsedLen) {
00287 ArrayCopyOverlap(mpArray + index + count, mpArray + index, mUsedLen - index - count);
00288 }
00289
00290
00291 if(lastInsertIndex < mUsedLen) {
00292 ArrayCopy(mpArray + index, values, count);
00293 }
00294 else {
00295 ArrayCopy(mpArray + index, values, mUsedLen - index);
00296 }
00297 }
00298
00299
00300 if(lastInsertIndex >= mUsedLen) {
00301 size_t numElementsInserted = (mUsedLen - index);
00302 DbgAssert(numElementsInserted < count);
00303 ArrayCopyConstruct(mpArray + mUsedLen, values + numElementsInserted, count - numElementsInserted);
00304 }
00305
00306 mUsedLen += count;
00307 }
00308 }
00309
00310 return *this;
00311 }
00312
00313
00314
00315
00316 template <class T> Array<T>& Array<T>::removeAt(size_t index)
00317 {
00318 DbgAssert(isValidIndex(index));
00319
00320 if(index < mUsedLen) {
00321
00322
00323 if (index < mUsedLen - 1) {
00324 for(size_t i = index; i < mUsedLen - 1; ++i) {
00325 mpArray[i] = mpArray[i+1];
00326 }
00327 }
00328
00329
00330 ArrayDestruct(mpArray + mUsedLen - 1, 1);
00331
00332 mUsedLen--;
00333 }
00334
00335 return *this;
00336 }
00337
00338
00339
00340
00341 template <class T> Array<T>& Array<T>::removeSubArray(size_t startIndex, size_t endIndex)
00342 {
00343 DbgAssert(isValidIndex(startIndex));
00344 DbgAssert(startIndex <= endIndex);
00345
00346 if(startIndex < mUsedLen) {
00347
00348 if(endIndex >= mUsedLen) {
00349 endIndex = mUsedLen - 1;
00350 }
00351
00352 size_t numToRemove = endIndex - startIndex + 1;
00353
00354
00355 for(size_t i = endIndex + 1; i < mUsedLen; ++i) {
00356 mpArray[i - numToRemove] = mpArray[i];
00357 }
00358
00359
00360 ArrayDestruct(mpArray + mUsedLen - numToRemove, numToRemove);
00361
00362 mUsedLen -= numToRemove;
00363 }
00364
00365 return *this;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 template <class T> bool Array<T>::find(const T& value, size_t& index, size_t start) const
00375 {
00376 const size_t nFoundAt = this->findFrom(value, start);
00377 if (nFoundAt == -1)
00378 return false;
00379 index = nFoundAt;
00380 return true;
00381 }
00382
00383 template <class T> size_t Array<T>::find(const T& value) const
00384 {
00385 return this->findFrom(value, 0);
00386 }
00387
00388 template <class T> size_t Array<T>::findFrom(const T& value, size_t start) const
00389 {
00390 for (size_t i = start; i < this->mUsedLen; i++) {
00391 if (mpArray[i] == value)
00392 return i;
00393 }
00394 return (size_t)-1;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 template <class T> Array<T>& Array<T>::setLengthUsed(size_t n, const T& defaultVal)
00405 {
00406 DbgAssert(n >= 0);
00407 if (n > mReservedLen) {
00408
00409 size_t growth = (mReservedLen * sizeof(T)) < kArrayGrowthThreshold ?
00410 (mReservedLen / 2) : kArrayGrowthThreshold / sizeof(T);
00411
00412 size_t minSize = mReservedLen + __max(growth, mGrowLen);
00413 if ( n > minSize)
00414 minSize = n;
00415 setLengthReserved(minSize);
00416 }
00417
00418 if(n > mUsedLen) {
00419
00420 ArrayConstruct(mpArray + mUsedLen, n - mUsedLen, defaultVal);
00421 }
00422 else {
00423
00424 ArrayDestruct(mpArray + n, mUsedLen - n);
00425 }
00426
00427 mUsedLen = n;
00428 return *this;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437 template <class T> Array<T>& Array<T>::setLengthReserved(size_t n)
00438 {
00439 DbgAssert(n >= 0);
00440
00441 if(n != mReservedLen) {
00442
00443 if(n == 0) {
00444 if(mReservedLen > 0) {
00445 ArrayDestruct(mpArray, mUsedLen);
00446 ArrayDeAllocate(mpArray);
00447 mpArray = NULL;
00448 mUsedLen = 0;
00449 mReservedLen = 0;
00450 }
00451 }
00452 else if(mReservedLen == 0) {
00453 mpArray = ArrayAllocate(n);
00454 if(mpArray == NULL) {
00455
00456 handleOutOfMemory();
00457 return *this;
00458 }
00459 mReservedLen = n;
00460 }
00461 else {
00462 T* oldArray = mpArray;
00463 size_t oldUsedLen = mUsedLen;
00464
00465
00466 mpArray = ArrayAllocate(n);
00467 if(mpArray == NULL) {
00468
00469 handleOutOfMemory();
00470 mpArray = oldArray;
00471 return *this;
00472 }
00473
00474
00475 if(n < mUsedLen) {
00476
00477 ArrayCopyConstruct(mpArray, oldArray, n);
00478 mUsedLen = n;
00479 }
00480 else {
00481 ArrayCopyConstruct(mpArray, oldArray, mUsedLen);
00482 }
00483 mReservedLen = n;
00484
00485
00486 ArrayDestruct(oldArray, oldUsedLen);
00487 ArrayDeAllocate(oldArray);
00488 }
00489 }
00490
00491 return *this;
00492 }
00493
00494
00495
00496
00497
00498 template <class T> Array<T>& Array<T>::reverse()
00499 {
00500 size_t halfUsedLen = mUsedLen/2;
00501 for (size_t i = 0; i < halfUsedLen; i++) {
00502 T tmp = mpArray[i];
00503 mpArray[i] = mpArray[mUsedLen - 1 - i];
00504 mpArray[mUsedLen - 1 - i] = tmp;
00505 }
00506 return *this;
00507 }
00508
00509
00510
00511 template <class T> Array<T>& Array<T>::swap(size_t i1, size_t i2)
00512 {
00513 DbgAssert(isValidIndex(i1));
00514 DbgAssert(isValidIndex(i2));
00515
00516 if (i1 == i2) return *this;
00517
00518 T tmp = mpArray[i1];
00519 mpArray[i1] = mpArray[i2];
00520 mpArray[i2] = tmp;
00521 return *this;
00522 }
00523
00524
00525
00526
00527
00528
00529 template <class T> bool Array<T>::remove(const T& value, size_t start)
00530 {
00531 const size_t i = this->findFrom(value, start);
00532 if (i == -1)
00533 return false;
00534 this->removeAt(i);
00535 return true;
00536 }
00537
00538 #pragma warning(push)
00539 #pragma warning(disable:4127)
00540 template <class T> void Array<T>::sort(CompareFnc cmp) {
00541
00542 if(mUsedLen > 1) {
00543
00544
00545
00546
00547
00548
00549 if(!__has_assign(T)) {
00550 qsort(mpArray, mUsedLen, sizeof(T), cmp);
00551 }
00552 else {
00553 quickSortRecursive(mpArray, 0, mUsedLen - 1, cmp);
00554 }
00555 }
00556 }
00557 #pragma warning(pop)
00558
00559 template <class T> size_t Array<T>::quickSortPartition(T* data, size_t first, size_t last, CompareFnc cmp)
00560 {
00561 const T& pivot = data[last];
00562 size_t left = first;
00563 size_t right = last - 1;
00564
00565 do {
00566 while ((left < last) && (cmp(&(data[left]), &pivot) <= 0))
00567 {
00568 ++left;
00569 }
00570 while ((right > first) && (cmp(&(data[right]), &pivot) >= 0))
00571 {
00572 --right;
00573 }
00574 if (left < right) {
00575 T swapValue = data[left];
00576 data[left] = data[right];
00577 data[right] = swapValue;
00578 }
00579 } while (left < right);
00580
00581 if (cmp(&data[left], &pivot) > 0)
00582 {
00583 T swapValue = data[left];
00584 data[left] = data[last];
00585 data[last] = swapValue;
00586 }
00587
00588 return left;
00589 }
00590
00591 template <class T> void Array<T>::quickSortRecursive(T* data, size_t first, size_t last, CompareFnc cmp)
00592 {
00593 if (first < last)
00594 {
00595 size_t pivot_position = quickSortPartition(data, first, last, cmp);
00596
00597
00598
00599
00600 if (pivot_position > 0)
00601 {
00602 quickSortRecursive(data, first, pivot_position - 1, cmp);
00603 }
00604 quickSortRecursive(data, pivot_position + 1, last, cmp);
00605 }
00606 }