Logo ROOT   6.19/01
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 
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]) {
550  ((TObjArray*)this)->fLast = i;
551  return fLast;
552  }
554  ((TObjArray*)this)->fLast = -1;
555  }
556  return fLast;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Return the number of objects in array (i.e. number of non-empty slots).
561 /// This is a thread-unsafe version of GetEntriesFast. Use it only if sure
562 /// it will not be invoked concurrently.
563 
565 {
566  if (R__unlikely(fLast == -2))
567  return GetEntriesFast();
568  else
569  return fLast + 1;
570 }
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 /// Return index of last object in array. Returns lowerBound-1 in case
574 /// array is empty.
575 
577 {
579 
580  return fLowerBound+GetAbsLast();
581 }
582 
583 ////////////////////////////////////////////////////////////////////////////////
584 /// Return address of pointer obj. If obj is 0 returns address of container.
585 
587 {
588  if (!obj)
589  return fCont;
590 
592 
593  Int_t index = IndexOf(obj);
594  return &fCont[index];
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 /// - obj != 0 Return index of object in array.
599 /// Returns lowerBound-1 in case array doesn't contain the obj.
600 ///
601 /// - obj == 0 Return the index of the first empty slot.
602 /// Returns lowerBound-1 in case array doesn't contain any empty slot.
603 
605 {
606  Int_t i;
607 
609 
610  if (obj) {
611  for (i = 0; i < fSize; i++)
612  if (fCont[i] && fCont[i]->IsEqual(obj))
613  return i+fLowerBound;
614  } else { // Look for the first empty slot
615  for (i = 0; i < fSize; i++)
616  if (!fCont[i])
617  return i+fLowerBound;
618  }
619 
620  return fLowerBound-1;
621 }
622 
623 ////////////////////////////////////////////////////////////////////////////////
624 /// Initialize a TObjArray.
625 
626 void TObjArray::Init(Int_t s, Int_t lowerBound)
627 {
629 
630  if (fCont && fSize != s) {
632  fCont = 0;
633  }
634 
635  fSize = s;
636 
637  if (!fCont)
638  fCont = (TObject**) TStorage::Alloc(fSize*sizeof(TObject*)); //new TObject* [fSize];
639  memset(fCont, 0, fSize*sizeof(TObject*));
640  fLowerBound = lowerBound;
641  fLast = -1;
642  Changed();
643 }
644 
645 ////////////////////////////////////////////////////////////////////////////////
646 /// Returns an array iterator.
647 
649 {
651  return new TObjArrayIter(this, dir);
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// Generate an out-of-bounds error. Always returns false.
656 
657 Bool_t TObjArray::OutOfBoundsError(const char *where, Int_t i) const
658 {
659  Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
660  return kFALSE;
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 /// Remove object from this collection and recursively remove the object
665 /// from all other objects (and collections).
666 
668 {
669  if (!obj) return;
670 
671  // We need to have the write lock even-though we are 'just'
672  // reading as any insert or remove during the iteration will
673  // invalidate fatally the cursor (e.g. might skip some items)
675 
676  for (int i = 0; i < fSize; i++) {
677  if (fCont[i] && fCont[i]->TestBit(kNotDeleted) && fCont[i]->IsEqual(obj)) {
678  fCont[i] = 0;
679  // recalculate array size
680  if (i == fLast)
681  do {
682  fLast--;
683  } while (fLast >= 0 && fCont[fLast] == 0);
684  Changed();
685  } else if (fCont[i] && fCont[i]->TestBit(kNotDeleted))
686  fCont[i]->RecursiveRemove(obj);
687  }
688 }
689 
690 ////////////////////////////////////////////////////////////////////////////////
691 /// Remove object at index idx.
692 
694 {
695  if (!BoundsOk("RemoveAt", idx)) return 0;
696 
698 
699  int i = idx-fLowerBound;
700 
701  TObject *obj = 0;
702  if (fCont[i]) {
703  obj = fCont[i];
704  fCont[i] = 0;
705  // recalculate array size
706  if (i == fLast)
707  do {
708  fLast--;
709  } while (fLast >= 0 && fCont[fLast] == 0);
710  Changed();
711  }
712  return obj;
713 }
714 
715 ////////////////////////////////////////////////////////////////////////////////
716 /// Remove object from array.
717 
719 {
720  if (!obj) return 0;
721 
723 
724  Int_t idx = IndexOf(obj) - fLowerBound;
725 
726  if (idx == -1) return 0;
727 
728  TObject *ob = fCont[idx];
729  fCont[idx] = 0;
730  // recalculate array size
731  if (idx == fLast)
732  do {
733  fLast--;
734  } while (fLast >= 0 && fCont[fLast] == 0);
735  Changed();
736  return ob;
737 }
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 /// Remove objects from index idx1 to idx2 included.
741 
743 {
744  if (!BoundsOk("RemoveRange", idx1)) return;
745  if (!BoundsOk("RemoveRange", idx2)) return;
746 
748 
749  idx1 -= fLowerBound;
750  idx2 -= fLowerBound;
751 
752  Bool_t change = kFALSE;
753  for (TObject **obj = fCont+idx1; obj <= fCont+idx2; obj++) {
754  if (*obj) {
755  *obj = 0;
756  change = kTRUE;
757  }
758  }
759 
760  // recalculate array size
761  if (change) Changed();
762  if (idx1 < fLast || fLast > idx2) return;
763  do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
764 }
765 
766 ////////////////////////////////////////////////////////////////////////////////
767 /// Set index of last object in array, effectively truncating the
768 /// array. Use carefully since whenever last position has to be
769 /// recalculated, e.g. after a Remove() or Sort() it will be reset
770 /// to the last non-empty slot. If last is -2 this will force the
771 /// recalculation of the last used slot.
772 /// If last is -1, this effectively truncate the array completely.
773 
775 {
777 
778  if (last == -2 || last == -1)
779  fLast = last;
780  else if (BoundsOk("SetLast", last))
781  fLast = last - fLowerBound;
782 }
783 
784 ////////////////////////////////////////////////////////////////////////////////
785 /// Randomize objects inside the array, i.e. permute randomly objects.
786 /// With fLast being the index of the last entry in the array, the following
787 /// algorithm is applied to the array:
788 ///
789 /// - for each entry j between 0 and fLast, another entry k is chosen
790 /// randomly between 0 and fLast.
791 /// - the objects at j and k are swapped.
792 /// - this process is repeated ntimes (ntimes = 1 by default).
793 
795 {
797 
798  for (Int_t i = 0; i < ntimes; i++) {
799  for (Int_t j = 0; j < fLast; j++) {
800 #ifdef R__WIN32
801  Int_t k = (Int_t)(0.5+fLast*Double_t(rand())/Double_t((RAND_MAX+1.0)));
802 #else
803  Int_t k = (Int_t)(0.5+fLast*Double_t(random())/Double_t((RAND_MAX+1.0)));
804 #endif
805  if (k == j) continue;
806  TObject *obj = fCont[j];
807  fCont[j] = fCont[k];
808  fCont[k] = obj;
809  }
810  }
811 }
812 
813 ////////////////////////////////////////////////////////////////////////////////
814 /// If objects in array are sortable (i.e. IsSortable() returns true
815 /// for all objects) then sort array.
816 
818 {
820 
821  if (GetAbsLast() == -1 || fSorted) return;
822  for (Int_t i = 0; i < fSize; i++)
823  if (fCont[i]) {
824  if (!fCont[i]->IsSortable()) {
825  Error("Sort", "objects in array are not sortable");
826  return;
827  }
828  }
829 
830  QSort(fCont, 0, TMath::Min(fSize, upto-fLowerBound));
831 
832  fLast = -2;
833  fSorted = kTRUE;
834 }
835 
836 ////////////////////////////////////////////////////////////////////////////////
837 /// Find object using a binary search. Array must first have been sorted.
838 /// Search can be limited by setting upto to desired index.
839 
841 {
843 
844  Int_t base, position, last, result = 0;
845  TObject *op2;
846 
847  if (!op) return -1;
848 
849  if (!fSorted) {
850  Error("BinarySearch", "array must first be sorted");
851  return -1;
852  }
853 
854  base = 0;
855  last = TMath::Min(fSize, upto-fLowerBound) - 1;
856 
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)
863  last = position-1;
864  else
865  base = position+1;
866  }
867  return -1;
868 }
869 
870 /** \class TObjArrayIter
871 Iterator of object array.
872 */
873 
875 
876 ////////////////////////////////////////////////////////////////////////////////
877 /// Create array iterator. By default the iteration direction
878 /// is kIterForward. To go backward use kIterBackward.
879 
881 {
882  fArray = arr;
883  fDirection = dir;
884  Reset();
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////
888 /// Copy ctor.
889 
891 {
892  fArray = iter.fArray;
893  fDirection = iter.fDirection;
894  fCursor = iter.fCursor;
895  fCurCursor = iter.fCurCursor;
896 }
897 
898 ////////////////////////////////////////////////////////////////////////////////
899 /// Overridden assignment operator.
900 
902 {
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;
909  }
910  return *this;
911 }
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Overloaded assignment operator.
915 
917 {
918  if (this != &rhs) {
919  fArray = rhs.fArray;
920  fDirection = rhs.fDirection;
921  fCursor = rhs.fCursor;
922  fCurCursor = rhs.fCurCursor;
923  }
924  return *this;
925 }
926 
927 ////////////////////////////////////////////////////////////////////////////////
928 /// Return next object in array. Returns 0 when no more objects in array.
929 
931 {
932  if (fDirection == kIterForward) {
933  for ( ; fCursor < fArray->Capacity() && fArray->fCont[fCursor] == 0;
934  fCursor++) { }
935 
937  if (fCursor < fArray->Capacity()) {
938  return fArray->fCont[fCursor++];
939  }
940  } else {
941  for ( ; fCursor >= 0 && fArray->fCont[fCursor] == 0;
942  fCursor--) { }
943 
945  if (fCursor >= 0) {
946  return fArray->fCont[fCursor--];
947  }
948  }
949  return 0;
950 }
951 
952 ////////////////////////////////////////////////////////////////////////////////
953 /// Reset array iterator.
954 
956 {
957  if (fDirection == kIterForward)
958  fCursor = 0;
959  else
960  fCursor = fArray->Capacity() - 1;
961 
963 }
964 
965 ////////////////////////////////////////////////////////////////////////////////
966 /// This operator compares two TIterator objects.
967 
969 {
970  if (aIter.IsA() == TObjArrayIter::Class()) {
971  const TObjArrayIter &iter(dynamic_cast<const TObjArrayIter &>(aIter));
972  return (fCurCursor != iter.fCurCursor);
973  }
974  return false; // for base class we don't implement a comparison
975 }
976 
977 ////////////////////////////////////////////////////////////////////////////////
978 /// This operator compares two TObjArrayIter objects.
979 
981 {
982  return (fCurCursor != aIter.fCurCursor);
983 }
984 
985 ////////////////////////////////////////////////////////////////////////////////
986 /// Return current object or nullptr.
987 
989 {
990  return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
991  fArray->fCont[fCurCursor] : nullptr);
992 }
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition: TStorage.cxx:170
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:817
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TObjArray.cxx:968
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.
#define R__unlikely(expr)
Definition: RConfig.hxx:611
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:718
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:794
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Iterator of object array.
Definition: TObjArray.h:123
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:129
TObject ** GetObjectRef() const
Definition: TObjArray.h:69
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:742
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:132
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:774
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:657
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:930
#define R__COLLECTION_READ_LOCKGUARD(mutex)
Definition: TCollection.h:435
void Reset()
Reset array iterator.
Definition: TObjArray.cxx:955
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:840
Bool_t IsOwner() const
Definition: TCollection.h:188
static constexpr double s
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:576
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
auto * a
Definition: textangle.C:12
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:693
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:130
void Init(Int_t s, Int_t lowerBound)
Initialize a TObjArray.
Definition: TObjArray.cxx:626
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:159
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:131
long Long_t
Definition: RtypesCore.h:50
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TObjArray.h:159
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:648
#define ClassImp(name)
Definition: Rtypes.h:365
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TObjArray.cxx:901
double Double_t
Definition: RtypesCore.h:55
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:604
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:386
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:988
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TObjArray.cxx:667
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
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
object has not been deleted
Definition: TObject.h:78
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
Int_t GetEntriesUnsafe() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:564
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 void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
Definition: TObjArray.cxx:188