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 #include "TOrdCollection.h"
00032 #include "TError.h"
00033
00034
00035 ClassImp(TOrdCollection)
00036
00037
00038 TOrdCollection::TOrdCollection(Int_t capacity)
00039 {
00040
00041
00042 if (capacity < 0) {
00043 Warning("TOrdCollection", "capacity (%d) < 0", capacity);
00044 capacity = kDefaultCapacity;
00045 } else if (capacity == 0)
00046 capacity = kDefaultCapacity;
00047 Init(capacity);
00048 }
00049
00050
00051 TOrdCollection::~TOrdCollection()
00052 {
00053
00054
00055
00056 if (IsOwner())
00057 Delete();
00058
00059 TStorage::Dealloc(fCont);
00060 fCont = 0;
00061 fSize = 0;
00062 }
00063
00064
00065 void TOrdCollection::AddAt(TObject *obj, Int_t idx)
00066 {
00067
00068
00069 Int_t physIdx;
00070
00071 if (idx > fSize) idx = fSize;
00072
00073 if (fGapSize <= 0)
00074 SetCapacity(GrowBy(TMath::Max(fCapacity, (int)kMinExpand)));
00075
00076 if (idx == fGapStart) {
00077 physIdx = fGapStart;
00078 fGapStart++;
00079 } else {
00080 physIdx = PhysIndex(idx);
00081 if (physIdx < fGapStart) {
00082 MoveGapTo(physIdx);
00083 physIdx = fGapStart;
00084 fGapStart++;
00085 } else {
00086 MoveGapTo(physIdx - fGapSize);
00087 physIdx = fGapStart + fGapSize - 1;
00088 }
00089 }
00090 R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
00091 fCont[physIdx] = obj;
00092 fGapSize--;
00093 fSize++;
00094 Changed();
00095 }
00096
00097
00098 void TOrdCollection::AddFirst(TObject *obj)
00099 {
00100
00101
00102 AddAt(obj, 0);
00103 }
00104
00105
00106 void TOrdCollection::AddLast(TObject *obj)
00107 {
00108
00109
00110 AddAt(obj, fSize);
00111 }
00112
00113
00114 void TOrdCollection::AddBefore(const TObject *before, TObject *obj)
00115 {
00116
00117
00118 if (!before)
00119 AddFirst(obj);
00120 else {
00121 Int_t idx = IndexOf(before);
00122 if (idx == -1) {
00123 Error("AddBefore", "before not found, object not added");
00124 return;
00125 }
00126 if (idx == 0) {
00127 AddFirst(obj);
00128 return;
00129 }
00130 AddAt(obj, idx);
00131 }
00132 }
00133
00134
00135 void TOrdCollection::AddAfter(const TObject *after, TObject *obj)
00136 {
00137
00138
00139 if (!after)
00140 AddLast(obj);
00141 else {
00142 Int_t idx = IndexOf(after);
00143 if (idx == -1) {
00144 Error("AddAfter", "after not found, object not added");
00145 return;
00146 }
00147 AddAt(obj, idx+1);
00148 }
00149 }
00150
00151
00152 TObject *TOrdCollection::After(const TObject *obj) const
00153 {
00154
00155
00156
00157 if (!obj) return 0;
00158
00159 Int_t idx = IndexOf(obj);
00160 if (idx == -1 || idx == fSize-1) return 0;
00161
00162 return At(idx+1);
00163 }
00164
00165
00166 TObject *TOrdCollection::At(Int_t idx) const
00167 {
00168
00169
00170 if (IllegalIndex("At", idx)) return 0;
00171 return fCont[PhysIndex(idx)];
00172 }
00173
00174
00175 TObject *TOrdCollection::Before(const TObject *obj) const
00176 {
00177
00178
00179
00180 if (!obj) return 0;
00181
00182 Int_t idx = IndexOf(obj);
00183 if (idx == -1 || idx == 0) return 0;
00184
00185 return At(idx-1);
00186 }
00187
00188
00189 void TOrdCollection::Clear(Option_t *)
00190 {
00191
00192
00193
00194 if (IsOwner())
00195 Delete();
00196 else {
00197 TStorage::Dealloc(fCont);
00198 fCont = 0;
00199 Init(fCapacity);
00200 fSize = 0;
00201 }
00202 }
00203
00204
00205 void TOrdCollection::Delete(Option_t *)
00206 {
00207
00208
00209 for (Int_t i = 0; i < fSize; i++) {
00210 TObject *obj = At(i);
00211 if (obj && obj->IsOnHeap())
00212 TCollection::GarbageCollect(obj);
00213 }
00214 TStorage::Dealloc(fCont);
00215 fCont = 0;
00216 Init(fCapacity);
00217 fSize = 0;
00218 }
00219
00220
00221 TObject *TOrdCollection::First() const
00222 {
00223
00224
00225
00226 return At(0);
00227 }
00228
00229
00230 TObject **TOrdCollection::GetObjectRef(const TObject *obj) const
00231 {
00232
00233 Int_t index = IndexOf(obj);
00234 return &fCont[index];
00235 }
00236
00237
00238 TObject *TOrdCollection::Last() const
00239 {
00240
00241
00242
00243 return At(fSize-1);
00244 }
00245
00246
00247 Bool_t TOrdCollection::IllegalIndex(const char *method, Int_t idx) const
00248 {
00249
00250
00251 if (idx < 0 || idx >= fSize) {
00252 Error(method, "index error (= %d) < 0 or > Size() (= %d)", idx, fSize);
00253 return kTRUE;
00254 }
00255 return kFALSE;
00256 }
00257
00258
00259 Int_t TOrdCollection::IndexOf(const TObject *obj) const
00260 {
00261
00262
00263
00264 for (Int_t i = 0; i < GetSize(); i++)
00265 if (fCont[PhysIndex(i)]->IsEqual(obj))
00266 return i;
00267
00268 return -1;
00269 }
00270
00271
00272 void TOrdCollection::Init(Int_t capacity)
00273 {
00274
00275
00276 fCapacity = capacity;
00277 fCont = (TObject**) TStorage::Alloc(fCapacity*sizeof(TObject*));
00278 memset(fCont, 0, fCapacity*sizeof(TObject*));
00279 fGapStart = 0;
00280 fGapSize = capacity;
00281 Changed();
00282 }
00283
00284
00285 TIterator *TOrdCollection::MakeIterator(Bool_t dir) const
00286 {
00287
00288
00289 return new TOrdCollectionIter(this, dir);
00290 }
00291
00292
00293 void TOrdCollection::MoveGapTo(Int_t start)
00294 {
00295
00296
00297
00298 Int_t i;
00299
00300 R__ASSERT(start + fGapSize - 1 < fCapacity);
00301
00302 if (fGapSize <= 0) {
00303 fGapStart = start;
00304 return;
00305 }
00306 if (start < fGapStart) {
00307 for (i = fGapStart - 1; i >= start; i--)
00308 fCont[i + fGapSize] = fCont[i];
00309 } else if (start > fGapStart) {
00310 Int_t stop = start + fGapSize;
00311 for (i = fGapStart + fGapSize; i < stop; i++)
00312 fCont[i - fGapSize] = fCont[i];
00313 }
00314 fGapStart = start;
00315 for (i = fGapStart; i < fGapStart + fGapSize; i++)
00316 fCont[i] = 0;
00317 }
00318
00319
00320 void TOrdCollection::PutAt(TObject *obj, Int_t idx)
00321 {
00322
00323
00324 if (IllegalIndex("PutAt", idx)) return;
00325
00326 Int_t phx = PhysIndex(idx);
00327 R__ASSERT(phx >= 0 && phx < fCapacity);
00328 fCont[phx] = obj;
00329 Changed();
00330 }
00331
00332
00333 TObject *TOrdCollection::RemoveAt(Int_t idx)
00334 {
00335
00336
00337 Int_t physIdx;
00338
00339 if (idx == fGapStart - 1 || idx == fGapStart) {
00340 if (idx == fGapStart)
00341 physIdx = fGapStart + fGapSize;
00342 else
00343 physIdx = --fGapStart;
00344 } else {
00345 physIdx = PhysIndex(idx);
00346 if (physIdx < fGapStart) {
00347 MoveGapTo(physIdx + 1);
00348 physIdx = --fGapStart;
00349 } else {
00350 MoveGapTo(physIdx - fGapSize);
00351 physIdx = fGapStart + fGapSize;
00352 }
00353 }
00354 R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
00355 TObject *obj = fCont[physIdx];
00356 fCont[physIdx] = 0;
00357 fGapSize++;
00358 fSize--;
00359 Changed();
00360
00361 if (LowWaterMark()) {
00362 Int_t newCapacity = TMath::Max(int(fCapacity / kShrinkFactor), 1);
00363 if (fCapacity > newCapacity)
00364 SetCapacity(newCapacity);
00365 }
00366 return obj;
00367 }
00368
00369
00370 TObject *TOrdCollection::Remove(TObject *obj)
00371 {
00372
00373
00374 if (!obj) return 0;
00375
00376 Int_t idx = IndexOf(obj);
00377 if (idx == -1) return 0;
00378
00379 return RemoveAt(idx);
00380 }
00381
00382
00383 void TOrdCollection::SetCapacity(Int_t newCapacity)
00384 {
00385
00386
00387 R__ASSERT(newCapacity > 0);
00388 R__ASSERT(fSize <= newCapacity);
00389
00390 if (fCapacity == newCapacity) return;
00391
00392 Int_t newGapSize = newCapacity - fSize;
00393 MoveGapTo(fCapacity - fGapSize);
00394 fCont = (TObject**) TStorage::ReAlloc(fCont, newCapacity*sizeof(TObject*),
00395 fCapacity*sizeof(TObject*));
00396 fGapSize = newGapSize;
00397 fCapacity = newCapacity;
00398 }
00399
00400
00401 void TOrdCollection::Sort()
00402 {
00403
00404
00405
00406 if (fSize <= 0 || fSorted) return;
00407 if (!At(0)->IsSortable()) {
00408 Error("Sort", "objects in collection are not sortable");
00409 return;
00410 }
00411
00412 MoveGapTo(fCapacity - fGapSize);
00413 QSort(fCont, 0, fSize);
00414
00415 fSorted = kTRUE;
00416 }
00417
00418
00419 Int_t TOrdCollection::BinarySearch(TObject *obj)
00420 {
00421
00422
00423
00424 Int_t result;
00425
00426 if (!obj) return -1;
00427
00428 if (!fSorted) {
00429 Error("BinarySearch", "collection must first be sorted");
00430 return -1;
00431 }
00432
00433 MoveGapTo(fCapacity - fGapSize);
00434
00435 Int_t base = 0;
00436 Int_t last = base + GetSize() - 1;
00437 while (last >= base) {
00438 Int_t position = (base + last) / 2;
00439 TObject *obj2 = fCont[position];
00440 if ((obj2 == 0) || (result = obj->Compare(obj2)) == 0)
00441 return LogIndex(position);
00442 if (result < 0)
00443 last = position - 1;
00444 else
00445 base = position + 1;
00446 }
00447 return -1;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 ClassImp(TOrdCollectionIter)
00460
00461
00462 TOrdCollectionIter::TOrdCollectionIter(const TOrdCollection *col, Bool_t dir): fCol(col), fDirection(dir)
00463 {
00464
00465
00466
00467 Reset();
00468 }
00469
00470
00471 TOrdCollectionIter::TOrdCollectionIter(const TOrdCollectionIter &iter) : TIterator(iter)
00472 {
00473
00474
00475 fCol = iter.fCol;
00476 fDirection = iter.fDirection;
00477 fCursor = iter.fCursor;
00478 fCurCursor = iter.fCurCursor;
00479 }
00480
00481
00482 TIterator &TOrdCollectionIter::operator=(const TIterator &rhs)
00483 {
00484
00485
00486 if (this != &rhs && rhs.IsA() == TOrdCollectionIter::Class()) {
00487 const TOrdCollectionIter &rhs1 = (const TOrdCollectionIter &)rhs;
00488 fCol = rhs1.fCol;
00489 fDirection = rhs1.fDirection;
00490 fCursor = rhs1.fCursor;
00491 fCurCursor = rhs1.fCurCursor;
00492 }
00493 return *this;
00494 }
00495
00496
00497 TOrdCollectionIter &TOrdCollectionIter::operator=(const TOrdCollectionIter &rhs)
00498 {
00499
00500
00501 if (this != &rhs) {
00502 fCol = rhs.fCol;
00503 fDirection = rhs.fDirection;
00504 fCursor = rhs.fCursor;
00505 fCurCursor = rhs.fCurCursor;
00506 }
00507 return *this;
00508 }
00509
00510
00511 TObject *TOrdCollectionIter::Next()
00512 {
00513
00514
00515
00516 fCurCursor = fCursor;
00517 if (fDirection == kIterForward) {
00518 if (fCursor < fCol->GetSize())
00519 return fCol->At(fCursor++);
00520 } else {
00521 if (fCursor >= 0)
00522 return fCol->At(fCursor--);
00523 }
00524 return 0;
00525 }
00526
00527
00528 void TOrdCollectionIter::Reset()
00529 {
00530
00531
00532 if (fDirection == kIterForward)
00533 fCursor = 0;
00534 else
00535 fCursor = fCol->GetSize() - 1;
00536
00537 fCurCursor = fCursor;
00538 }
00539
00540
00541 bool TOrdCollectionIter::operator!=(const TIterator &aIter) const
00542 {
00543
00544
00545 if (nullptr == (&aIter))
00546 return (fCurCursor < fCol->GetSize());
00547
00548 if (aIter.IsA() == TOrdCollectionIter::Class()) {
00549 const TOrdCollectionIter &iter(dynamic_cast<const TOrdCollectionIter &>(aIter));
00550 return (fCurCursor != iter.fCurCursor);
00551 }
00552 return false;
00553 }
00554
00555
00556 bool TOrdCollectionIter::operator!=(const TOrdCollectionIter &aIter) const
00557 {
00558
00559
00560 if (nullptr == (&aIter))
00561 return (fCurCursor < fCol->GetSize());
00562
00563 return (fCurCursor != aIter.fCurCursor);
00564 }
00565
00566
00567 TObject *TOrdCollectionIter::operator*() const
00568 {
00569
00570
00571 return (((fCurCursor >= 0) && (fCurCursor < fCol->GetSize())) ?
00572 fCol->At(fCurCursor) : nullptr);
00573 }