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