Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TObjArray.cxx
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Fons Rademakers 11/09/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TObjArray
13\ingroup Containers
14An array of TObjects. The array expands automatically when
15objects are added (shrinking can be done by hand using Expand(),
16how nice to have meaningful names -:)).
17Use operator[] to have "real" array behaviour.
18
19Note on ownership and copy:
20By default the TObjArray does not own the objects it points to and
21will not delete them unless explicitly asked (via a call to the
22Delete member function). To assign ownership of the content to
23the array, call:
24~~~ {.cpp}
25 myarr->SetOwner(kTRUE);
26~~~
27When the array owns its content a call to Clear or the deletion of
28the array itself will lead to the deletion of its contents.
29
30You can either make a shallow copy of the array:
31~~~ {.cpp}
32 otherarr = new TObjArray(*myarr);
33 *otherarr = *myarr;
34~~~
35in which case ownership (if any) is not transfered but the other
36array points to the same object as the original array. Note that
37if the content of either array is deleted the other array is not
38notified in any way (i.e. still points to the now deleted objects).
39
40You can also make a deep copy of the array:
41~~~ {.cpp}
42 otherarr = (TObjArray*)myarr->Clone();
43~~~
44in which case the array and the content are both duplicated (i.e.
45otherarr and myarr do not point to the same objects). If myarr
46is set to the be the owner of its content, otherarr will also be
47set to the owner of its own content.
48*/
49
50#include "TObjArray.h"
51#include "TError.h"
52#include "TROOT.h"
53#include "TBuffer.h"
54#include "TVirtualMutex.h"
55#include <stdlib.h>
56
58
59////////////////////////////////////////////////////////////////////////////////
60/// Create an object array. Using s one can set the array size (default is
61/// kInitCapacity=16) and lowerBound can be used to set the array lowerbound
62/// index (default is 0).
63
65{
66 if (s < 0) {
67 Warning("TObjArray", "size (%d) < 0", s);
69 } else if (s == 0)
71 fCont = 0;
72 Init(s, lowerBound);
73}
74
75////////////////////////////////////////////////////////////////////////////////
76/// Create a copy of TObjArray a. Note, does not copy the kIsOwner flag.
77
79{
80 fCont = 0;
81 Init(a.fSize, a.fLowerBound);
82
83 for (Int_t i = 0; i < fSize; i++)
84 fCont[i] = a.fCont[i];
85
86 fLast = a.fLast;
87 fName = a.fName;
88}
89
90////////////////////////////////////////////////////////////////////////////////
91/// Delete an array. Objects are not deleted unless the TObjArray is the
92/// owner (set via SetOwner()).
93
95{
96 if (IsOwner())
97 Delete();
98
100 fCont = 0;
101 fSize = 0;
102}
103
104////////////////////////////////////////////////////////////////////////////////
105/// Assignment operator. Note, unsets the kIsOwner flag.
106
108{
109 if (this != &a) {
111
112 if (IsOwner())
113 Delete();
115
116 Init(a.fSize, a.fLowerBound);
117
118 for (Int_t i = 0; i < fSize; i++)
119 fCont[i] = a.fCont[i];
120
121 fLast = a.fLast;
122 fName = a.fName;
123 }
124 return *this;
125}
126
127////////////////////////////////////////////////////////////////////////////////
128/// Return the object at position i. Returns address at position 0
129/// if i is out of bounds. Result may be used as an lvalue.
130
132{
134
135 int j = i-fLowerBound;
136 if (j >= 0 && j < fSize) {
138 Changed();
139 return fCont[j];
140 }
141 BoundsOk("operator[]", i);
142 fLast = -2; // invalidate fLast since the result may be used as an lvalue
143 return fCont[0];
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// Return the object at position at. Returns 0 if i is out of bounds.
148
150{
152
153 int j = i-fLowerBound;
154 if (j >= 0 && j < fSize) return fCont[j];
155 BoundsOk("operator[] const", i);
156 return 0;
157}
158
159////////////////////////////////////////////////////////////////////////////////
160/// Add object in the first slot of the array. This will overwrite the
161/// first element that might have been there. To have insertion semantics
162/// use either a TList or a TOrdCollection.
163
165{
167
168 fCont[0] = obj;
169 if (fLast == -1)
170 fLast = 0;
171 Changed();
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// Add object in the next empty slot in the array. Expand the array
176/// if necessary.
177
179{
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// Add object in the slot before object before. If before=0 add object
185/// in the first slot. Note that this will overwrite any object that
186/// might have already been in this slot. For insertion semantics use
187/// either a TList or a TOrdCollection.
188
189void TObjArray::AddBefore(const TObject *before, TObject *obj)
190{
191 if (!before)
192 AddFirst(obj);
193 else {
195
196 Int_t idx = IndexOf(before) - fLowerBound;
197 if (idx == -1) {
198 Error("AddBefore", "before not found, object not added");
199 return;
200 }
201 if (idx == 0) {
202 Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
203 return;
204 }
205 AddAt(obj, idx+fLowerBound-1);
206 }
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Add object in the slot after object after. If after=0 add object in
211/// the last empty slot. Note that this will overwrite any object that
212/// might have already been in this slot. For insertion semantics use
213/// either a TList or a TOrdCollection.
214
215void TObjArray::AddAfter(const TObject *after, TObject *obj)
216{
217 if (!after)
218 AddLast(obj);
219 else {
221
222 Int_t idx = IndexOf(after) - fLowerBound;
223 if (idx == -1) {
224 Error("AddAfter", "after not found, object not added");
225 return;
226 }
227 AddAtAndExpand(obj, idx+fLowerBound+1);
228 }
229}
230
231////////////////////////////////////////////////////////////////////////////////
232/// Add object at position idx. If idx is larger than the current size
233/// of the array, expand the array (double its size).
234
236{
238
239 if (idx < fLowerBound) {
240 Error("AddAt", "out of bounds at %d in %zx", idx, (size_t)this);
241 return;
242 }
243 if (idx-fLowerBound >= fSize)
245 fCont[idx-fLowerBound] = obj;
247 Changed();
248}
249
250////////////////////////////////////////////////////////////////////////////////
251/// Add object at position ids. Give an error when idx is out of bounds
252/// (i.e. the array is not expanded).
253
255{
257
258 if (!BoundsOk("AddAt", idx)) return;
259
260 fCont[idx-fLowerBound] = obj;
262 Changed();
263}
264
265////////////////////////////////////////////////////////////////////////////////
266/// Return the position of the new object.
267/// Find the first empty cell or AddLast if there is no empty cell
268
270{
272
273 if (Last()) { // <---------- This is to take in account "empty" TObjArray's
274 Int_t i;
275 for (i = 0; i < fSize; i++)
276 if (!fCont[i]) { // Add object at position i
277 fCont[i] = obj;
279 Changed();
280 return i+fLowerBound;
281 }
282 }
283 AddLast(obj);
284 return GetLast();
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// Return the object after obj. Returns 0 if obj is last object.
289
291{
292 if (!obj) return 0;
293
295
296 Int_t idx = IndexOf(obj) - fLowerBound;
297 if (idx == -1 || idx == fSize-1) return 0;
298
299 return fCont[idx+1];
300}
301
302////////////////////////////////////////////////////////////////////////////////
303/// Return the object before obj. Returns 0 if obj is first object.
304
306{
307 if (!obj) return 0;
308
310
311 Int_t idx = IndexOf(obj) - fLowerBound;
312 if (idx == -1 || idx == 0) return 0;
313
314 return fCont[idx-1];
315}
316
317////////////////////////////////////////////////////////////////////////////////
318/// Remove all objects from the array. Does not delete the objects
319/// unless the TObjArray is the owner (set via SetOwner()).
320
322{
324
325 if (IsOwner())
326 Delete();
327 else
329}
330
331////////////////////////////////////////////////////////////////////////////////
332/// Remove empty slots from array.
333
335{
337
338 Int_t j = 0;
339
340 for (Int_t i = 0; i < fSize; i++) {
341 if (fCont[i]) {
342 fCont[j] = fCont[i];
343 j++;
344 }
345 }
346
347 fLast = j - 1;
348
349 for ( ; j < fSize; j++)
350 fCont[j] = 0;
351}
352
353////////////////////////////////////////////////////////////////////////////////
354/// Remove all objects from the array AND delete all heap based objects.
355
357{
358 // In some case, for example TParallelCoord, a list (the pad's list of
359 // primitives) will contain both the container and the containees
360 // (the TParallelCoordVar) but if the Clear is being called from
361 // the destructor of the container of this list, one of the first
362 // thing done will be the remove the container (the pad) from the
363 // list (of Primitives of the canvas) that was connecting it
364 // (indirectly) to the list of cleanups.
365 // Note: The Code in TParallelCoordVar was changed (circa June 2017),
366 // to no longer have this behavior and thus rely on this code (by moving
367 // from using Draw to Paint) but the structure might still exist elsewhere
368 // so we keep this comment here.
369
371
372 // Since we set fCont[i] only after the deletion is completed, we do not
373 // lose the connection and thus do not need to take any special action.
374 for (Int_t i = 0; i < fSize; i++) {
375 if (fCont[i] && fCont[i]->IsOnHeap()) {
377 fCont[i] = 0;
378 }
379 }
380
382}
383
384////////////////////////////////////////////////////////////////////////////////
385/// Expand or shrink the array to newSize elements.
386
388{
390
391 if (newSize < 0) {
392 Error ("Expand", "newSize must be positive (%d)", newSize);
393 return;
394 }
395 if (newSize == fSize)
396 return;
397 if (newSize < fSize) {
398 // if the array is shrunk check whether there are nonempty entries
399 for (Int_t j = newSize; j < fSize; j++)
400 if (fCont[j]) {
401 Error ("Expand", "expand would cut off nonempty entries at %d", j);
402 return;
403 }
404 }
405 fCont = (TObject**) TStorage::ReAlloc(fCont, newSize * sizeof(TObject*),
406 fSize * sizeof(TObject*));
407 fSize = newSize;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// Find an object in this collection using its name. Requires a sequential
412/// scan till the object has been found. Returns 0 if object with specified
413/// name is not found.
414
416{
418
419 Int_t nobjects = GetAbsLast()+1;
420 for (Int_t i = 0; i < nobjects; ++i) {
421 TObject *obj = fCont[i];
422 if (obj && 0==strcmp(name, obj->GetName())) return obj;
423 }
424 return 0;
425}
426
427////////////////////////////////////////////////////////////////////////////////
428/// Find an object in this collection using the object's IsEqual()
429/// member function. Requires a sequential scan till the object has
430/// been found. Returns 0 if object is not found.
431/// Typically this function is overridden by a more efficient version
432/// in concrete collection classes (e.g. THashTable).
433
435{
437
438 Int_t nobjects = GetAbsLast()+1;
439 for (Int_t i = 0; i < nobjects; ++i) {
440 TObject *obj = fCont[i];
441 if (obj && obj->IsEqual(iobj)) return obj;
442 }
443 return 0;
444}
445
446////////////////////////////////////////////////////////////////////////////////
447/// Stream all objects in the array to or from the I/O buffer.
448
449void TObjArray::Streamer(TBuffer &b)
450{
451 UInt_t R__s, R__c;
452 Int_t nobjects;
453 if (b.IsReading()) {
454 Version_t v = b.ReadVersion(&R__s, &R__c);
455 if (v > 2)
456 TObject::Streamer(b);
457 if (v > 1)
458 fName.Streamer(b);
459
460 if (GetEntriesFast() > 0) Clear();
461
462 b >> nobjects;
463 b >> fLowerBound;
464 if (nobjects >= fSize) Expand(nobjects);
465 fLast = -1;
466 TObject *obj;
467 for (Int_t i = 0; i < nobjects; i++) {
468 obj = (TObject*) b.ReadObjectAny(TObject::Class());
469 if (obj) {
470 fCont[i] = obj;
471 fLast = i;
472 }
473 }
474 Changed();
475 b.CheckByteCount(R__s, R__c,TObjArray::IsA());
476 } else {
478
479 R__c = b.WriteVersion(TObjArray::IsA(), kTRUE);
480 TObject::Streamer(b);
481 fName.Streamer(b);
482 nobjects = GetAbsLast()+1;
483 b << nobjects;
484 b << fLowerBound;
485
486 for (Int_t i = 0; i < nobjects; i++) {
487 b << fCont[i];
488 }
489 b.SetByteCount(R__c, kTRUE);
490 }
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// Return the object in the first slot.
495
497{
499
500 return fCont[0];
501}
502
503////////////////////////////////////////////////////////////////////////////////
504/// Return the object in the last filled slot. Returns 0 if no entries.
505
507{
509
510 if (fLast == -1)
511 return 0;
512 else
513 return fCont[GetAbsLast()];
514}
515
516////////////////////////////////////////////////////////////////////////////////
517/// Return the number of objects in array (i.e. number of non-empty slots).
518/// Attention: use this method ONLY if you want to know the number of
519/// non-empty slots. This function loops over the complete array and
520/// is therefore very slow when applied in a loop. Most of the time you
521/// better use GetEntriesFast() (only in case when there are no empty slots).
522
524{
525 Int_t cnt = 0;
526
528
529 for (Int_t i = 0; i < fSize; i++)
530 if (fCont[i]) cnt++;
531
532 return cnt;
533}
534
535////////////////////////////////////////////////////////////////////////////////
536/// Return absolute index to last object in array. Returns -1 in case
537/// array is empty.
538
540{
541 // For efficiency we need sometimes to update fLast so we have
542 // to cast const away. Ugly, but making GetAbsLast() not const breaks
543 // many other const functions.
544
546
547 if (fLast == -2) {
548 for (Int_t i = fSize-1; i >= 0; i--)
549 if (fCont[i]) {
551 ((TObjArray*)this)->fLast = i;
552 return fLast;
553 }
555 ((TObjArray*)this)->fLast = -1;
556 }
557 return fLast;
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Return the number of objects in array (i.e. number of non-empty slots).
562/// This is a thread-unsafe version of GetEntriesFast. Use it only if sure
563/// it will not be invoked concurrently.
564
566{
567 if (R__unlikely(fLast == -2))
568 return GetEntriesFast();
569 else
570 return fLast + 1;
571}
572
573////////////////////////////////////////////////////////////////////////////////
574/// Return index of last object in array. Returns lowerBound-1 in case
575/// array is empty.
576
578{
580
581 return fLowerBound+GetAbsLast();
582}
583
584////////////////////////////////////////////////////////////////////////////////
585/// Return address of pointer obj. If obj is 0 returns address of container.
586
588{
589 if (!obj)
590 return fCont;
591
593
594 Int_t index = IndexOf(obj);
595 return &fCont[index];
596}
597
598////////////////////////////////////////////////////////////////////////////////
599/// - obj != 0 Return index of object in array.
600/// Returns lowerBound-1 in case array doesn't contain the obj.
601///
602/// - obj == 0 Return the index of the first empty slot.
603/// Returns lowerBound-1 in case array doesn't contain any empty slot.
604
606{
607 Int_t i;
608
610
611 if (obj) {
612 for (i = 0; i < fSize; i++)
613 if (fCont[i] && fCont[i]->IsEqual(obj))
614 return i+fLowerBound;
615 } else { // Look for the first empty slot
616 for (i = 0; i < fSize; i++)
617 if (!fCont[i])
618 return i+fLowerBound;
619 }
620
621 return fLowerBound-1;
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// Initialize a TObjArray.
626
627void TObjArray::Init(Int_t s, Int_t lowerBound)
628{
630
631 if (fCont && fSize != s) {
633 fCont = 0;
634 }
635
636 fSize = s;
637
638 if (!fCont)
639 fCont = (TObject**) TStorage::Alloc(fSize*sizeof(TObject*)); //new TObject* [fSize];
640 memset(fCont, 0, fSize*sizeof(TObject*));
641 fLowerBound = lowerBound;
642 fLast = -1;
643 Changed();
644}
645
646////////////////////////////////////////////////////////////////////////////////
647/// Returns an array iterator.
648
650{
652 return new TObjArrayIter(this, dir);
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Generate an out-of-bounds error. Always returns false.
657
658Bool_t TObjArray::OutOfBoundsError(const char *where, Int_t i) const
659{
660 Error(where, "index %d out of bounds (size: %d, this: 0x%zx)", i, fSize, (size_t)this);
661 return kFALSE;
662}
663
664////////////////////////////////////////////////////////////////////////////////
665/// Remove object from this collection and recursively remove the object
666/// from all other objects (and collections).
667
669{
670 if (!obj) return;
671
672 // We need to have the write lock even-though we are 'just'
673 // reading as any insert or remove during the iteration will
674 // invalidate fatally the cursor (e.g. might skip some items)
676
677 for (int i = 0; i < fSize; i++) {
678 if (fCont[i] && !ROOT::Detail::HasBeenDeleted(fCont[i]) && fCont[i]->IsEqual(obj)) {
679 fCont[i] = nullptr;
680 // recalculate array size
681 if (i == fLast)
682 do {
683 fLast--;
684 } while (fLast >= 0 && fCont[fLast] == 0);
685 Changed();
686 } else if (fCont[i] && !ROOT::Detail::HasBeenDeleted(fCont[i]))
687 fCont[i]->RecursiveRemove(obj);
688 }
689}
690
691////////////////////////////////////////////////////////////////////////////////
692/// Remove object at index idx.
693
695{
696 if (!BoundsOk("RemoveAt", idx)) return 0;
697
699
700 int i = idx-fLowerBound;
701
702 TObject *obj = 0;
703 if (fCont[i]) {
704 obj = fCont[i];
705 fCont[i] = 0;
706 // recalculate array size
707 if (i == fLast)
708 do {
709 fLast--;
710 } while (fLast >= 0 && fCont[fLast] == 0);
711 Changed();
712 }
713 return obj;
714}
715
716////////////////////////////////////////////////////////////////////////////////
717/// Remove object from array.
718
720{
721 if (!obj) return 0;
722
724
725 Int_t idx = IndexOf(obj) - fLowerBound;
726
727 if (idx == -1) return 0;
728
729 TObject *ob = fCont[idx];
730 fCont[idx] = 0;
731 // recalculate array size
732 if (idx == fLast)
733 do {
734 fLast--;
735 } while (fLast >= 0 && fCont[fLast] == 0);
736 Changed();
737 return ob;
738}
739
740////////////////////////////////////////////////////////////////////////////////
741/// Remove objects from index idx1 to idx2 included.
742
744{
745 if (!BoundsOk("RemoveRange", idx1)) return;
746 if (!BoundsOk("RemoveRange", idx2)) return;
747
749
750 idx1 -= fLowerBound;
751 idx2 -= fLowerBound;
752
753 Bool_t change = kFALSE;
754 for (TObject **obj = fCont+idx1; obj <= fCont+idx2; obj++) {
755 if (*obj) {
756 *obj = 0;
757 change = kTRUE;
758 }
759 }
760
761 // recalculate array size
762 if (change) Changed();
763 if (idx1 < fLast || fLast > idx2) return;
764 do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
765}
766
767////////////////////////////////////////////////////////////////////////////////
768/// Set index of last object in array, effectively truncating the
769/// array. Use carefully since whenever last position has to be
770/// recalculated, e.g. after a Remove() or Sort() it will be reset
771/// to the last non-empty slot. If last is -2 this will force the
772/// recalculation of the last used slot.
773/// If last is -1, this effectively truncate the array completely.
774
776{
778
779 if (last == -2 || last == -1)
780 fLast = last;
781 else if (BoundsOk("SetLast", last))
782 fLast = last - fLowerBound;
783}
784
785////////////////////////////////////////////////////////////////////////////////
786/// Randomize objects inside the array, i.e. permute randomly objects.
787/// With fLast being the index of the last entry in the array, the following
788/// algorithm is applied to the array:
789///
790/// - for each entry j between 0 and fLast, another entry k is chosen
791/// randomly between 0 and fLast.
792/// - the objects at j and k are swapped.
793/// - this process is repeated ntimes (ntimes = 1 by default).
794
796{
798
799 for (Int_t i = 0; i < ntimes; i++) {
800 for (Int_t j = 0; j < fLast; j++) {
801#ifdef R__WIN32
802 Int_t k = (Int_t)(0.5+fLast*Double_t(rand())/Double_t((RAND_MAX+1.0)));
803#else
804 Int_t k = (Int_t)(0.5+fLast*Double_t(random())/Double_t((RAND_MAX+1.0)));
805#endif
806 if (k == j) continue;
807 TObject *obj = fCont[j];
808 fCont[j] = fCont[k];
809 fCont[k] = obj;
810 }
811 }
812}
813
814////////////////////////////////////////////////////////////////////////////////
815/// If objects in array are sortable (i.e. IsSortable() returns true
816/// for all objects) then sort array.
817
819{
821
822 if (GetAbsLast() == -1 || fSorted) return;
823 for (Int_t i = 0; i < fSize; i++)
824 if (fCont[i]) {
825 if (!fCont[i]->IsSortable()) {
826 Error("Sort", "objects in array are not sortable");
827 return;
828 }
829 }
830
832
833 fLast = -2;
834 fSorted = kTRUE;
835}
836
837////////////////////////////////////////////////////////////////////////////////
838/// Find object using a binary search. Array must first have been sorted.
839/// Search can be limited by setting upto to desired index.
840
842{
844
845 Int_t base, position, last, result = 0;
846 TObject *op2;
847
848 if (!op) return -1;
849
850 if (!fSorted) {
851 Error("BinarySearch", "array must first be sorted");
852 return -1;
853 }
854
855 base = 0;
856 last = TMath::Min(fSize, upto-fLowerBound) - 1;
857
858 while (last >= base) {
859 position = (base+last) / 2;
860 op2 = fCont[position];
861 if (op2 && (result = op->Compare(op2)) == 0)
862 return position + fLowerBound;
863 if (!op2 || result < 0)
864 last = position-1;
865 else
866 base = position+1;
867 }
868 return -1;
869}
870
871/** \class TObjArrayIter
872Iterator of object array.
873*/
874
876
877////////////////////////////////////////////////////////////////////////////////
878/// Create array iterator. By default the iteration direction
879/// is kIterForward. To go backward use kIterBackward.
880
882{
883 fArray = arr;
884 fDirection = dir;
885 Reset();
886}
887
888////////////////////////////////////////////////////////////////////////////////
889/// Copy ctor.
890
892{
893 fArray = iter.fArray;
894 fDirection = iter.fDirection;
895 fCursor = iter.fCursor;
896 fCurCursor = iter.fCurCursor;
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Overridden assignment operator.
901
903{
904 if (this != &rhs && rhs.IsA() == TObjArrayIter::Class()) {
905 const TObjArrayIter &rhs1 = (const TObjArrayIter &)rhs;
906 fArray = rhs1.fArray;
907 fDirection = rhs1.fDirection;
908 fCursor = rhs1.fCursor;
909 fCurCursor = rhs1.fCurCursor;
910 }
911 return *this;
912}
913
914////////////////////////////////////////////////////////////////////////////////
915/// Overloaded assignment operator.
916
918{
919 if (this != &rhs) {
920 fArray = rhs.fArray;
922 fCursor = rhs.fCursor;
924 }
925 return *this;
926}
927
928////////////////////////////////////////////////////////////////////////////////
929/// Return next object in array. Returns 0 when no more objects in array.
930
932{
933 if (fDirection == kIterForward) {
934 for ( ; fCursor < fArray->Capacity() && fArray->fCont[fCursor] == 0;
935 fCursor++) { }
936
938 if (fCursor < fArray->Capacity()) {
939 return fArray->fCont[fCursor++];
940 }
941 } else {
942 for ( ; fCursor >= 0 && fArray->fCont[fCursor] == 0;
943 fCursor--) { }
944
946 if (fCursor >= 0) {
947 return fArray->fCont[fCursor--];
948 }
949 }
950 return 0;
951}
952
953////////////////////////////////////////////////////////////////////////////////
954/// Reset array iterator.
955
957{
959 fCursor = 0;
960 else
961 fCursor = fArray->Capacity() - 1;
962
964}
965
966////////////////////////////////////////////////////////////////////////////////
967/// This operator compares two TIterator objects.
968
970{
971 if (aIter.IsA() == TObjArrayIter::Class()) {
972 const TObjArrayIter &iter(dynamic_cast<const TObjArrayIter &>(aIter));
973 return (fCurCursor != iter.fCurCursor);
974 }
975 return false; // for base class we don't implement a comparison
976}
977
978////////////////////////////////////////////////////////////////////////////////
979/// This operator compares two TObjArrayIter objects.
980
982{
983 return (fCurCursor != aIter.fCurCursor);
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Return current object or nullptr.
988
990{
991 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
992 fArray->fCont[fCurCursor] : nullptr);
993}
#define R__unlikely(expr)
Definition RConfig.hxx:598
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
#define R__COLLECTION_READ_LOCKGUARD(mutex)
const Bool_t kIterForward
Definition TCollection.h:42
#define R__COLLECTION_WRITE_LOCKGUARD(mutex)
char name[80]
Definition TGX11.cxx:110
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Bool_t IsSortable() const
Int_t Capacity() const
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TString fName
Bool_t IsOwner() const
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
Iterator abstract base class.
Definition TIterator.h:30
Iterator of object array.
Definition TObjArray.h:117
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
void Reset()
Reset array iterator.
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
TObject * operator*() const
Return current object or nullptr.
const TObjArray * fArray
Definition TObjArray.h:120
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
Int_t fCurCursor
Definition TObjArray.h:121
Bool_t fDirection
Definition TObjArray.h:123
An array of TObjects.
Definition TObjArray.h:31
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
TObjArray & operator=(const TObjArray &)
Assignment operator. Note, unsets the kIsOwner flag.
Int_t IndexOf(const TObject *obj) const
Int_t GetEntriesFast() const
Definition TObjArray.h:58
TObject ** fCont
Definition TObjArray.h:37
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Int_t GetEntriesUnsafe() const
Return the number of objects in array (i.e.
virtual TObject *& operator[](Int_t i)
Return the object at position i.
TObject ** GetObjectRef() const
Definition TObjArray.h:63
virtual ~TObjArray()
Delete an array.
Definition TObjArray.cxx:94
void Init(Int_t s, Int_t lowerBound)
Initialize a TObjArray.
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
virtual void Compress()
Remove empty slots from array.
Bool_t BoundsOk(const char *where, Int_t at) const
Definition TObjArray.h:157
Int_t GetEntries() const
Return the number of objects in array (i.e.
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
TObject * First() const
Return the object in the first slot.
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
virtual void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Int_t fLowerBound
Array contents.
Definition TObjArray.h:38
Int_t GetAbsLast() const
Return absolute index to last object in array.
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
virtual void Randomize(Int_t ntimes=1)
Randomize objects inside the array, i.e.
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Int_t GetLast() const
Return index of last object in array.
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
virtual TObject * Remove(TObject *obj)
Remove object from array.
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
virtual void RemoveRange(Int_t idx1, Int_t idx2)
Remove objects from index idx1 to idx2 included.
TObjArray(Int_t s=TCollection::kInitCapacity, Int_t lowerBound=0)
Create an object array.
Definition TObjArray.cxx:64
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
friend class TObjArrayIter
Definition TObjArray.h:33
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Int_t fLast
Definition TObjArray.h:39
Mother of all ROOT objects.
Definition TObject.h:41
virtual Bool_t IsEqual(const TObject *obj) const
Default equal comparison (objects are equal if they have the same address in memory).
Definition TObject.cxx:555
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition TObject.cxx:644
R__ALWAYS_INLINE Bool_t IsOnHeap() const
Definition TObject.h:152
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:949
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition TObject.cxx:231
Sequenceable collection abstract base class.
virtual void Changed()
static void QSort(TObject **a, Int_t first, Int_t last)
Sort array of TObject pointers using a quicksort algorithm.
static void * Alloc(size_t size)
Allocate a block of memory, that later can be resized using TStorage::ReAlloc().
Definition TStorage.cxx:152
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition TStorage.cxx:183
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition TStorage.cxx:170
R__ALWAYS_INLINE bool HasBeenDeleted(const TObject *obj)
Check if the TObject's memory has been deleted.
Definition TObject.h:404
R__EXTERN TVirtualRWMutex * gCoreMutex
Short_t Max(Short_t a, Short_t b)
Definition TMathBase.h:208
Short_t Min(Short_t a, Short_t b)
Definition TMathBase.h:176