63 TObjArray::TObjArray(Int_t s, Int_t lowerBound)
66 Warning(
"TObjArray",
"size (%d) < 0", s);
67 s = TCollection::kInitCapacity;
69 s = TCollection::kInitCapacity;
77 TObjArray::TObjArray(
const TObjArray &a) : TSeqCollection()
80 Init(a.fSize, a.fLowerBound);
82 for (Int_t i = 0; i < fSize; i++)
83 fCont[i] = a.fCont[i];
93 TObjArray::~TObjArray()
98 TStorage::Dealloc(fCont);
106 TObjArray& TObjArray::operator=(
const TObjArray &a)
109 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
115 Init(a.fSize, a.fLowerBound);
117 for (Int_t i = 0; i < fSize; i++)
118 fCont[i] = a.fCont[i];
130 TObject *&TObjArray::operator[](Int_t i)
132 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
134 int j = i-fLowerBound;
135 if (j >= 0 && j < fSize) {
136 fLast = TMath::Max(j, GetAbsLast());
140 BoundsOk(
"operator[]", i);
148 TObject *TObjArray::operator[](Int_t i)
const
150 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
152 int j = i-fLowerBound;
153 if (j >= 0 && j < fSize)
return fCont[j];
154 BoundsOk(
"operator[] const", i);
163 void TObjArray::AddFirst(TObject *obj)
165 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
177 void TObjArray::AddLast(TObject *obj)
179 AddAtAndExpand(obj, GetAbsLast()+1+fLowerBound);
188 void TObjArray::AddBefore(
const TObject *before, TObject *obj)
193 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
195 Int_t idx = IndexOf(before) - fLowerBound;
197 Error(
"AddBefore",
"before not found, object not added");
201 Error(
"AddBefore",
"cannot add before lowerbound (%d)", fLowerBound);
204 AddAt(obj, idx+fLowerBound-1);
214 void TObjArray::AddAfter(
const TObject *after, TObject *obj)
219 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
221 Int_t idx = IndexOf(after) - fLowerBound;
223 Error(
"AddAfter",
"after not found, object not added");
226 AddAtAndExpand(obj, idx+fLowerBound+1);
234 void TObjArray::AddAtAndExpand(TObject *obj, Int_t idx)
236 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
238 if (idx < fLowerBound) {
239 Error(
"AddAt",
"out of bounds at %d in %lx", idx, (Long_t)
this);
242 if (idx-fLowerBound >= fSize)
243 Expand(TMath::Max(idx-fLowerBound+1, GrowBy(fSize)));
244 fCont[idx-fLowerBound] = obj;
245 fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
253 void TObjArray::AddAt(TObject *obj, Int_t idx)
255 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
257 if (!BoundsOk(
"AddAt", idx))
return;
259 fCont[idx-fLowerBound] = obj;
260 fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
268 Int_t TObjArray::AddAtFree(TObject *obj)
270 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
274 for (i = 0; i < fSize; i++)
277 fLast = TMath::Max(i, GetAbsLast());
279 return i+fLowerBound;
289 TObject *TObjArray::After(
const TObject *obj)
const
293 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
295 Int_t idx = IndexOf(obj) - fLowerBound;
296 if (idx == -1 || idx == fSize-1)
return 0;
304 TObject *TObjArray::Before(
const TObject *obj)
const
308 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
310 Int_t idx = IndexOf(obj) - fLowerBound;
311 if (idx == -1 || idx == 0)
return 0;
320 void TObjArray::Clear(Option_t *)
322 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
327 Init(fSize, fLowerBound);
333 void TObjArray::Compress()
335 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
339 for (Int_t i = 0; i < fSize; i++) {
348 for ( ; j < fSize; j++)
355 void TObjArray::Delete(Option_t * )
369 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
373 for (Int_t i = 0; i < fSize; i++) {
374 if (fCont[i] && fCont[i]->IsOnHeap()) {
375 TCollection::GarbageCollect(fCont[i]);
380 Init(fSize, fLowerBound);
386 void TObjArray::Expand(Int_t newSize)
388 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
391 Error (
"Expand",
"newSize must be positive (%d)", newSize);
394 if (newSize == fSize)
396 if (newSize < fSize) {
398 for (Int_t j = newSize; j < fSize; j++)
400 Error (
"Expand",
"expand would cut off nonempty entries at %d", j);
404 fCont = (TObject**) TStorage::ReAlloc(fCont, newSize *
sizeof(TObject*),
405 fSize *
sizeof(TObject*));
414 TObject *TObjArray::FindObject(
const char *name)
const
416 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
418 Int_t nobjects = GetAbsLast()+1;
419 for (Int_t i = 0; i < nobjects; ++i) {
420 TObject *obj = fCont[i];
421 if (obj && 0==strcmp(name, obj->GetName()))
return obj;
433 TObject *TObjArray::FindObject(
const TObject *iobj)
const
435 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
437 Int_t nobjects = GetAbsLast()+1;
438 for (Int_t i = 0; i < nobjects; ++i) {
439 TObject *obj = fCont[i];
440 if (obj && obj->IsEqual(iobj))
return obj;
448 void TObjArray::Streamer(TBuffer &b)
453 Version_t v = b.ReadVersion(&R__s, &R__c);
455 TObject::Streamer(b);
459 if (GetEntriesFast() > 0) Clear();
463 if (nobjects >= fSize) Expand(nobjects);
466 for (Int_t i = 0; i < nobjects; i++) {
467 obj = (TObject*) b.ReadObjectAny(TObject::Class());
474 b.CheckByteCount(R__s, R__c,TObjArray::IsA());
476 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
478 R__c = b.WriteVersion(TObjArray::IsA(), kTRUE);
479 TObject::Streamer(b);
481 nobjects = GetAbsLast()+1;
485 for (Int_t i = 0; i < nobjects; i++) {
488 b.SetByteCount(R__c, kTRUE);
495 TObject *TObjArray::First()
const
497 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
505 TObject *TObjArray::Last()
const
507 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
512 return fCont[GetAbsLast()];
522 Int_t TObjArray::GetEntries()
const
526 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
528 for (Int_t i = 0; i < fSize; i++)
538 Int_t TObjArray::GetAbsLast()
const
544 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
547 for (Int_t i = fSize-1; i >= 0; i--)
549 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
550 ((TObjArray*)
this)->fLast = i;
553 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
554 ((TObjArray*)
this)->fLast = -1;
564 Int_t TObjArray::GetEntriesUnsafe()
const
566 if (R__unlikely(fLast == -2))
567 return GetEntriesFast();
576 Int_t TObjArray::GetLast()
const
578 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
580 return fLowerBound+GetAbsLast();
586 TObject **TObjArray::GetObjectRef(
const TObject *obj)
const
591 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
593 Int_t index = IndexOf(obj);
594 return &fCont[index];
604 Int_t TObjArray::IndexOf(
const TObject *obj)
const
608 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
611 for (i = 0; i < fSize; i++)
612 if (fCont[i] && fCont[i]->IsEqual(obj))
613 return i+fLowerBound;
615 for (i = 0; i < fSize; i++)
617 return i+fLowerBound;
620 return fLowerBound-1;
626 void TObjArray::Init(Int_t s, Int_t lowerBound)
628 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
630 if (fCont && fSize != s) {
631 TStorage::Dealloc(fCont);
638 fCont = (TObject**) TStorage::Alloc(fSize*
sizeof(TObject*));
639 memset(fCont, 0, fSize*
sizeof(TObject*));
640 fLowerBound = lowerBound;
648 TIterator *TObjArray::MakeIterator(Bool_t dir)
const
650 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
651 return new TObjArrayIter(
this, dir);
657 Bool_t TObjArray::OutOfBoundsError(
const char *where, Int_t i)
const
659 Error(where,
"index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)
this);
667 void TObjArray::RecursiveRemove(TObject *obj)
674 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
676 for (
int i = 0; i < fSize; i++) {
677 if (fCont[i] && fCont[i]->TestBit(kNotDeleted) && fCont[i]->IsEqual(obj)) {
683 }
while (fLast >= 0 && fCont[fLast] == 0);
685 }
else if (fCont[i] && fCont[i]->TestBit(kNotDeleted))
686 fCont[i]->RecursiveRemove(obj);
693 TObject *TObjArray::RemoveAt(Int_t idx)
695 if (!BoundsOk(
"RemoveAt", idx))
return 0;
697 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
699 int i = idx-fLowerBound;
709 }
while (fLast >= 0 && fCont[fLast] == 0);
718 TObject *TObjArray::Remove(TObject *obj)
722 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
724 Int_t idx = IndexOf(obj) - fLowerBound;
726 if (idx == -1)
return 0;
728 TObject *ob = fCont[idx];
734 }
while (fLast >= 0 && fCont[fLast] == 0);
742 void TObjArray::RemoveRange(Int_t idx1, Int_t idx2)
744 if (!BoundsOk(
"RemoveRange", idx1))
return;
745 if (!BoundsOk(
"RemoveRange", idx2))
return;
747 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
752 Bool_t change = kFALSE;
753 for (TObject **obj = fCont+idx1; obj <= fCont+idx2; obj++) {
761 if (change) Changed();
762 if (idx1 < fLast || fLast > idx2)
return;
763 do { fLast--; }
while (fLast >= 0 && fCont[fLast] == 0);
774 void TObjArray::SetLast(Int_t last)
776 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
778 if (last == -2 || last == -1)
780 else if (BoundsOk(
"SetLast", last))
781 fLast = last - fLowerBound;
794 void TObjArray::Randomize(Int_t ntimes)
796 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
798 for (Int_t i = 0; i < ntimes; i++) {
799 for (Int_t j = 0; j < fLast; j++) {
801 Int_t k = (Int_t)(0.5+fLast*Double_t(rand())/Double_t((RAND_MAX+1.0)));
803 Int_t k = (Int_t)(0.5+fLast*Double_t(random())/Double_t((RAND_MAX+1.0)));
805 if (k == j)
continue;
806 TObject *obj = fCont[j];
817 void TObjArray::Sort(Int_t upto)
819 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
821 if (GetAbsLast() == -1 || fSorted)
return;
822 for (Int_t i = 0; i < fSize; i++)
824 if (!fCont[i]->IsSortable()) {
825 Error(
"Sort",
"objects in array are not sortable");
830 QSort(fCont, 0, TMath::Min(fSize, upto-fLowerBound));
840 Int_t TObjArray::BinarySearch(TObject *op, Int_t upto)
842 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
844 Int_t base, position, last, result = 0;
850 Error(
"BinarySearch",
"array must first be sorted");
855 last = TMath::Min(fSize, upto-fLowerBound) - 1;
857 while (last >= base) {
858 position = (base+last) / 2;
859 op2 = fCont[position];
860 if (op2 && (result = op->Compare(op2)) == 0)
861 return position + fLowerBound;
862 if (!op2 || result < 0)
874 ClassImp(TObjArrayIter);
880 TObjArrayIter::TObjArrayIter(
const TObjArray *arr, Bool_t dir)
890 TObjArrayIter::TObjArrayIter(
const TObjArrayIter &iter) : TIterator(iter)
892 fArray = iter.fArray;
893 fDirection = iter.fDirection;
894 fCursor = iter.fCursor;
895 fCurCursor = iter.fCurCursor;
901 TIterator &TObjArrayIter::operator=(
const TIterator &rhs)
903 if (
this != &rhs && rhs.IsA() == TObjArrayIter::Class()) {
904 const TObjArrayIter &rhs1 = (
const TObjArrayIter &)rhs;
905 fArray = rhs1.fArray;
906 fDirection = rhs1.fDirection;
907 fCursor = rhs1.fCursor;
908 fCurCursor = rhs1.fCurCursor;
916 TObjArrayIter &TObjArrayIter::operator=(
const TObjArrayIter &rhs)
920 fDirection = rhs.fDirection;
921 fCursor = rhs.fCursor;
922 fCurCursor = rhs.fCurCursor;
930 TObject *TObjArrayIter::Next()
932 if (fDirection == kIterForward) {
933 for ( ; fCursor < fArray->Capacity() && fArray->fCont[fCursor] == 0;
936 fCurCursor = fCursor;
937 if (fCursor < fArray->Capacity()) {
938 return fArray->fCont[fCursor++];
941 for ( ; fCursor >= 0 && fArray->fCont[fCursor] == 0;
944 fCurCursor = fCursor;
946 return fArray->fCont[fCursor--];
955 void TObjArrayIter::Reset()
957 if (fDirection == kIterForward)
960 fCursor = fArray->Capacity() - 1;
962 fCurCursor = fCursor;
968 Bool_t TObjArrayIter::operator!=(
const TIterator &aIter)
const
970 if (aIter.IsA() == TObjArrayIter::Class()) {
971 const TObjArrayIter &iter(dynamic_cast<const TObjArrayIter &>(aIter));
972 return (fCurCursor != iter.fCurCursor);
980 Bool_t TObjArrayIter::operator!=(
const TObjArrayIter &aIter)
const
982 return (fCurCursor != aIter.fCurCursor);
988 TObject *TObjArrayIter::operator*()
const
990 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
991 fArray->fCont[fCurCursor] :
nullptr);