Logo ROOT   6.08/07
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 
63 TObjArray::TObjArray(Int_t s, Int_t lowerBound)
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) {
109  if (IsOwner())
110  Delete();
111  SetOwner(kFALSE);
112 
113  Init(a.fSize, a.fLowerBound);
114 
115  for (Int_t i = 0; i < fSize; i++)
116  fCont[i] = a.fCont[i];
117 
118  fLast = a.fLast;
119  fName = a.fName;
120  }
121  return *this;
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// Return the object at position i. Returns address at position 0
126 /// if i is out of bounds. Result may be used as an lvalue.
127 
129 {
130  int j = i-fLowerBound;
131  if (j >= 0 && j < fSize) {
132  fLast = TMath::Max(j, GetAbsLast());
133  Changed();
134  return fCont[j];
135  }
136  BoundsOk("operator[]", i);
137  fLast = -2; // invalidate fLast since the result may be used as an lvalue
138  return fCont[0];
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// Return the object at position at. Returns 0 if i is out of bounds.
143 
145 {
146  int j = i-fLowerBound;
147  if (j >= 0 && j < fSize) return fCont[j];
148  BoundsOk("operator[] const", i);
149  return 0;
150 }
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 /// Add object in the first slot of the array. This will overwrite the
154 /// first element that might have been there. To have insertion semantics
155 /// use either a TList or a TOrdCollection.
156 
158 {
159  fCont[0] = obj;
160  if (fLast == -1)
161  fLast = 0;
162  Changed();
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Add object in the next empty slot in the array. Expand the array
167 /// if necessary.
168 
170 {
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Add object in the slot before object before. If before=0 add object
176 /// in the first slot. Note that this will overwrite any object that
177 /// might have already been in this slot. For insertion semantics use
178 /// either a TList or a TOrdCollection.
179 
180 void TObjArray::AddBefore(const TObject *before, TObject *obj)
181 {
182  if (!before)
183  AddFirst(obj);
184  else {
185  Int_t idx = IndexOf(before) - fLowerBound;
186  if (idx == -1) {
187  Error("AddBefore", "before not found, object not added");
188  return;
189  }
190  if (idx == 0) {
191  Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
192  return;
193  }
194  AddAt(obj, idx+fLowerBound-1);
195  }
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// Add object in the slot after object after. If after=0 add object in
200 /// the last empty slot. Note that this will overwrite any object that
201 /// might have already been in this slot. For insertion semantics use
202 /// either a TList or a TOrdCollection.
203 
204 void TObjArray::AddAfter(const TObject *after, TObject *obj)
205 {
206  if (!after)
207  AddLast(obj);
208  else {
209  Int_t idx = IndexOf(after) - fLowerBound;
210  if (idx == -1) {
211  Error("AddAfter", "after not found, object not added");
212  return;
213  }
214  AddAtAndExpand(obj, idx+fLowerBound+1);
215  }
216 }
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 /// Add object at position idx. If idx is larger than the current size
220 /// of the array, expand the array (double its size).
221 
223 {
224  if (idx < fLowerBound) {
225  Error("AddAt", "out of bounds at %d in %lx", idx, (Long_t)this);
226  return;
227  }
228  if (idx-fLowerBound >= fSize)
230  fCont[idx-fLowerBound] = obj;
232  Changed();
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Add object at position ids. Give an error when idx is out of bounds
237 /// (i.e. the array is not expanded).
238 
240 {
241  if (!BoundsOk("AddAt", idx)) return;
242 
243  fCont[idx-fLowerBound] = obj;
245  Changed();
246 }
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Return the position of the new object.
250 /// Find the first empty cell or AddLast if there is no empty cell
251 
253 {
254  if (Last()) { // <---------- This is to take in account "empty" TObjArray's
255  Int_t i;
256  for (i = 0; i < fSize; i++)
257  if (!fCont[i]) { // Add object at position i
258  fCont[i] = obj;
259  fLast = TMath::Max(i, GetAbsLast());
260  Changed();
261  return i+fLowerBound;
262  }
263  }
264  AddLast(obj);
265  return GetLast();
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Return the object after obj. Returns 0 if obj is last object.
270 
271 TObject *TObjArray::After(const TObject *obj) const
272 {
273  if (!obj) return 0;
274 
275  Int_t idx = IndexOf(obj) - fLowerBound;
276  if (idx == -1 || idx == fSize-1) return 0;
277 
278  return fCont[idx+1];
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Return the object before obj. Returns 0 if obj is first object.
283 
285 {
286  if (!obj) return 0;
287 
288  Int_t idx = IndexOf(obj) - fLowerBound;
289  if (idx == -1 || idx == 0) return 0;
290 
291  return fCont[idx-1];
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Remove all objects from the array. Does not delete the objects
296 /// unless the TObjArray is the owner (set via SetOwner()).
297 
299 {
300  if (IsOwner())
301  Delete();
302  else
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// Remove empty slots from array.
308 
310 {
311  Int_t j = 0;
312 
313  for (Int_t i = 0; i < fSize; i++) {
314  if (fCont[i]) {
315  fCont[j] = fCont[i];
316  j++;
317  }
318  }
319 
320  fLast = j - 1;
321 
322  for ( ; j < fSize; j++)
323  fCont[j] = 0;
324 }
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 /// Remove all objects from the array AND delete all heap based objects.
328 
330 {
331  // In some case, for example TParallelCoord, a list (the pad's list of
332  // primitives) will contain both the container and the containees
333  // (the TParallelCoorVar) but if the Clear is being called from
334  // the destructor of the container of this list, one of the first
335  // thing done will be the remove the container (the pad) from the
336  // list (of Primitives of the canvas) that was connecting it
337  // (indirectly) to the list of cleanups.
338  // So let's temporarily add the current list and remove it later.
339  //
340  // If opt is "noregistration", then this protect is skipped.
341  // (To avoid performance penalties, the option must be spelt exactly (no
342  // uppercase, no spaces)
343  const char *noreg = "noregistration";
344  bool needRegister = fSize && TROOT::Initialized() && strcmp(opt,noreg) == 0;
345  if(needRegister) {
347  needRegister = needRegister && !gROOT->GetListOfCleanups()->FindObject(this);
348  }
349  if (needRegister) {
351  gROOT->GetListOfCleanups()->Add(this);
352  }
353  for (Int_t i = 0; i < fSize; i++) {
354  if (fCont[i] && fCont[i]->IsOnHeap()) {
356  fCont[i] = 0;
357  }
358  }
359  if (needRegister) {
362  }
363 
364  Init(fSize, fLowerBound);
365 }
366 
367 ////////////////////////////////////////////////////////////////////////////////
368 /// Expand or shrink the array to newSize elements.
369 
371 {
372  if (newSize < 0) {
373  Error ("Expand", "newSize must be positive (%d)", newSize);
374  return;
375  }
376  if (newSize == fSize)
377  return;
378  if (newSize < fSize) {
379  // if the array is shrunk check whether there are nonempty entries
380  for (Int_t j = newSize; j < fSize; j++)
381  if (fCont[j]) {
382  Error ("Expand", "expand would cut off nonempty entries at %d", j);
383  return;
384  }
385  }
386  fCont = (TObject**) TStorage::ReAlloc(fCont, newSize * sizeof(TObject*),
387  fSize * sizeof(TObject*));
388  fSize = newSize;
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 /// Find an object in this collection using its name. Requires a sequential
393 /// scan till the object has been found. Returns 0 if object with specified
394 /// name is not found.
395 
396 TObject *TObjArray::FindObject(const char *name) const
397 {
398  Int_t nobjects = GetAbsLast()+1;
399  for (Int_t i = 0; i < nobjects; ++i) {
400  TObject *obj = fCont[i];
401  if (obj && 0==strcmp(name, obj->GetName())) return obj;
402  }
403  return 0;
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Find an object in this collection using the object's IsEqual()
408 /// member function. Requires a sequential scan till the object has
409 /// been found. Returns 0 if object is not found.
410 /// Typically this function is overridden by a more efficient version
411 /// in concrete collection classes (e.g. THashTable).
412 
414 {
415  Int_t nobjects = GetAbsLast()+1;
416  for (Int_t i = 0; i < nobjects; ++i) {
417  TObject *obj = fCont[i];
418  if (obj && obj->IsEqual(iobj)) return obj;
419  }
420  return 0;
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Stream all objects in the array to or from the I/O buffer.
425 
426 void TObjArray::Streamer(TBuffer &b)
427 {
428  UInt_t R__s, R__c;
429  Int_t nobjects;
430  if (b.IsReading()) {
431  Version_t v = b.ReadVersion(&R__s, &R__c);
432  if (v > 2)
433  TObject::Streamer(b);
434  if (v > 1)
435  fName.Streamer(b);
436 
437  if (GetEntriesFast() > 0) Clear();
438 
439  b >> nobjects;
440  b >> fLowerBound;
441  if (nobjects >= fSize) Expand(nobjects);
442  fLast = -1;
443  TObject *obj;
444  for (Int_t i = 0; i < nobjects; i++) {
445  obj = (TObject*) b.ReadObjectAny(TObject::Class());
446  if (obj) {
447  fCont[i] = obj;
448  fLast = i;
449  }
450  }
451  Changed();
452  b.CheckByteCount(R__s, R__c,TObjArray::IsA());
453  } else {
454  R__c = b.WriteVersion(TObjArray::IsA(), kTRUE);
455  TObject::Streamer(b);
456  fName.Streamer(b);
457  nobjects = GetAbsLast()+1;
458  b << nobjects;
459  b << fLowerBound;
460 
461  for (Int_t i = 0; i < nobjects; i++) {
462  b << fCont[i];
463  }
464  b.SetByteCount(R__c, kTRUE);
465  }
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Return the object in the first slot.
470 
472 {
473  return fCont[0];
474 }
475 
476 ////////////////////////////////////////////////////////////////////////////////
477 /// Return the object in the last filled slot. Returns 0 if no entries.
478 
480 {
481  if (fLast == -1)
482  return 0;
483  else
484  return fCont[GetAbsLast()];
485 }
486 
487 ////////////////////////////////////////////////////////////////////////////////
488 /// Return the number of objects in array (i.e. number of non-empty slots).
489 /// Attention: use this method ONLY if you want to know the number of
490 /// non-empty slots. This function loops over the complete array and
491 /// is therefore very slow when applied in a loop. Most of the time you
492 /// better use GetEntriesFast() (only in case when there are no empty slots).
493 
495 {
496  Int_t cnt = 0;
497 
498  for (Int_t i = 0; i < fSize; i++)
499  if (fCont[i]) cnt++;
500 
501  return cnt;
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Return absolute index to last object in array. Returns -1 in case
506 /// array is empty.
507 
509 {
510  // For efficiency we need sometimes to update fLast so we have
511  // to cast const away. Ugly, but making GetAbsLast() not const breaks
512  // many other const functions.
513  if (fLast == -2) {
514  for (Int_t i = fSize-1; i >= 0; i--)
515  if (fCont[i]) {
516  ((TObjArray*)this)->fLast = i;
517  return fLast;
518  }
519  ((TObjArray*)this)->fLast = -1;
520  }
521  return fLast;
522 }
523 
524 ////////////////////////////////////////////////////////////////////////////////
525 /// Return index of last object in array. Returns lowerBound-1 in case
526 /// array is empty.
527 
529 {
530  return fLowerBound+GetAbsLast();
531 }
532 
533 ////////////////////////////////////////////////////////////////////////////////
534 /// Return address of pointer obj. If obj is 0 returns address of container.
535 
537 {
538  if (!obj)
539  return fCont;
540 
541  Int_t index = IndexOf(obj);
542  return &fCont[index];
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// - obj != 0 Return index of object in array.
547 /// Returns lowerBound-1 in case array doesn't contain the obj.
548 ///
549 /// - obj == 0 Return the index of the first empty slot.
550 /// Returns lowerBound-1 in case array doesn't contain any empty slot.
551 
553 {
554  Int_t i;
555  if (obj) {
556  for (i = 0; i < fSize; i++)
557  if (fCont[i] && fCont[i]->IsEqual(obj))
558  return i+fLowerBound;
559  } else { // Look for the first empty slot
560  for (i = 0; i < fSize; i++)
561  if (!fCont[i])
562  return i+fLowerBound;
563  }
564 
565  return fLowerBound-1;
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Initialize a TObjArray.
570 
571 void TObjArray::Init(Int_t s, Int_t lowerBound)
572 {
573  if (fCont && fSize != s) {
575  fCont = 0;
576  }
577 
578  fSize = s;
579 
580  if (!fCont)
581  fCont = (TObject**) TStorage::Alloc(fSize*sizeof(TObject*)); //new TObject* [fSize];
582  memset(fCont, 0, fSize*sizeof(TObject*));
583  fLowerBound = lowerBound;
584  fLast = -1;
585  Changed();
586 }
587 
588 ////////////////////////////////////////////////////////////////////////////////
589 /// Returns an array iterator.
590 
592 {
593  return new TObjArrayIter(this, dir);
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 /// Generate an out-of-bounds error. Always returns false.
598 
599 Bool_t TObjArray::OutOfBoundsError(const char *where, Int_t i) const
600 {
601  Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
602  return kFALSE;
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Remove object from this collection and recursively remove the object
607 /// from all other objects (and collections).
608 
610 {
611  if (!obj) return;
612 
613  for (int i = 0; i < fSize; i++) {
614  if (fCont[i] && fCont[i]->TestBit(kNotDeleted) && fCont[i]->IsEqual(obj)) {
615  fCont[i] = 0;
616  // recalculate array size
617  if (i == fLast)
618  do {
619  fLast--;
620  } while (fLast >= 0 && fCont[fLast] == 0);
621  Changed();
622  } else if (fCont[i] && fCont[i]->TestBit(kNotDeleted))
623  fCont[i]->RecursiveRemove(obj);
624  }
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 /// Remove object at index idx.
629 
631 {
632  if (!BoundsOk("RemoveAt", idx)) return 0;
633 
634  int i = idx-fLowerBound;
635 
636  TObject *obj = 0;
637  if (fCont[i]) {
638  obj = fCont[i];
639  fCont[i] = 0;
640  // recalculate array size
641  if (i == fLast)
642  do {
643  fLast--;
644  } while (fLast >= 0 && fCont[fLast] == 0);
645  Changed();
646  }
647  return obj;
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////
651 /// Remove object from array.
652 
654 {
655  if (!obj) return 0;
656 
657  Int_t idx = IndexOf(obj) - fLowerBound;
658 
659  if (idx == -1) return 0;
660 
661  TObject *ob = fCont[idx];
662  fCont[idx] = 0;
663  // recalculate array size
664  if (idx == fLast)
665  do {
666  fLast--;
667  } while (fLast >= 0 && fCont[fLast] == 0);
668  Changed();
669  return ob;
670 }
671 
672 ////////////////////////////////////////////////////////////////////////////////
673 /// Remove objects from index idx1 to idx2 included.
674 
676 {
677  if (!BoundsOk("RemoveRange", idx1)) return;
678  if (!BoundsOk("RemoveRange", idx2)) return;
679 
680  idx1 -= fLowerBound;
681  idx2 -= fLowerBound;
682 
683  Bool_t change = kFALSE;
684  for (TObject **obj = fCont+idx1; obj <= fCont+idx2; obj++) {
685  if (*obj) {
686  *obj = 0;
687  change = kTRUE;
688  }
689  }
690 
691  // recalculate array size
692  if (change) Changed();
693  if (idx1 < fLast || fLast > idx2) return;
694  do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
695 }
696 
697 ////////////////////////////////////////////////////////////////////////////////
698 /// Set index of last object in array, effectively truncating the
699 /// array. Use carefully since whenever last position has to be
700 /// recalculated, e.g. after a Remove() or Sort() it will be reset
701 /// to the last non-empty slot. If last is -2 this will force the
702 /// recalculation of the last used slot.
703 /// If last is -1, this effectively truncate the array completely.
704 
706 {
707  if (last == -2 || last == -1)
708  fLast = last;
709  else if (BoundsOk("SetLast", last))
710  fLast = last - fLowerBound;
711 }
712 
713 ////////////////////////////////////////////////////////////////////////////////
714 /// Randomize objects inside the array, i.e. permute randomly objects.
715 /// With fLast being the index of the last entry in the array, the following
716 /// algorithm is applied to the array:
717 ///
718 /// - for each entry j between 0 and fLast, another entry k is chosen
719 /// randomly between 0 and fLast.
720 /// - the objects at j and k are swapped.
721 /// - this process is repeated ntimes (ntimes = 1 by default).
722 
724 {
725  for (Int_t i = 0; i < ntimes; i++) {
726  for (Int_t j = 0; j < fLast; j++) {
727 #ifdef R__WIN32
728  Int_t k = (Int_t)(0.5+fLast*Double_t(rand())/Double_t((RAND_MAX+1.0)));
729 #else
730  Int_t k = (Int_t)(0.5+fLast*Double_t(random())/Double_t((RAND_MAX+1.0)));
731 #endif
732  if (k == j) continue;
733  TObject *obj = fCont[j];
734  fCont[j] = fCont[k];
735  fCont[k] = obj;
736  }
737  }
738 }
739 
740 ////////////////////////////////////////////////////////////////////////////////
741 /// If objects in array are sortable (i.e. IsSortable() returns true
742 /// for all objects) then sort array.
743 
745 {
746  if (GetAbsLast() == -1 || fSorted) return;
747  for (Int_t i = 0; i < fSize; i++)
748  if (fCont[i]) {
749  if (!fCont[i]->IsSortable()) {
750  Error("Sort", "objects in array are not sortable");
751  return;
752  }
753  }
754 
755  QSort(fCont, 0, TMath::Min(fSize, upto-fLowerBound));
756 
757  fLast = -2;
758  fSorted = kTRUE;
759 }
760 
761 ////////////////////////////////////////////////////////////////////////////////
762 /// Find object using a binary search. Array must first have been sorted.
763 /// Search can be limited by setting upto to desired index.
764 
766 {
767  Int_t base, position, last, result = 0;
768  TObject *op2;
769 
770  if (!op) return -1;
771 
772  if (!fSorted) {
773  Error("BinarySearch", "array must first be sorted");
774  return -1;
775  }
776 
777  base = 0;
778  last = TMath::Min(fSize, upto-fLowerBound) - 1;
779 
780  while (last >= base) {
781  position = (base+last) / 2;
782  op2 = fCont[position];
783  if (op2 && (result = op->Compare(op2)) == 0)
784  return position + fLowerBound;
785  if (!op2 || result < 0)
786  last = position-1;
787  else
788  base = position+1;
789  }
790  return -1;
791 }
792 
793 /** \class TObjArrayIter
794 Iterator of object array.
795 */
796 
798 
799 ////////////////////////////////////////////////////////////////////////////////
800 /// Create array iterator. By default the iteration direction
801 /// is kIterForward. To go backward use kIterBackward.
802 
804 {
805  fArray = arr;
806  fDirection = dir;
807  Reset();
808 }
809 
810 ////////////////////////////////////////////////////////////////////////////////
811 /// Copy ctor.
812 
814 {
815  fArray = iter.fArray;
816  fDirection = iter.fDirection;
817  fCursor = iter.fCursor;
818  fCurCursor = iter.fCurCursor;
819 }
820 
821 ////////////////////////////////////////////////////////////////////////////////
822 /// Overridden assignment operator.
823 
825 {
826  if (this != &rhs && rhs.IsA() == TObjArrayIter::Class()) {
827  const TObjArrayIter &rhs1 = (const TObjArrayIter &)rhs;
828  fArray = rhs1.fArray;
829  fDirection = rhs1.fDirection;
830  fCursor = rhs1.fCursor;
831  fCurCursor = rhs1.fCurCursor;
832  }
833  return *this;
834 }
835 
836 ////////////////////////////////////////////////////////////////////////////////
837 /// Overloaded assignment operator.
838 
840 {
841  if (this != &rhs) {
842  fArray = rhs.fArray;
843  fDirection = rhs.fDirection;
844  fCursor = rhs.fCursor;
845  fCurCursor = rhs.fCurCursor;
846  }
847  return *this;
848 }
849 
850 ////////////////////////////////////////////////////////////////////////////////
851 /// Return next object in array. Returns 0 when no more objects in array.
852 
854 {
855  if (fDirection == kIterForward) {
856  for ( ; fCursor < fArray->Capacity() && fArray->fCont[fCursor] == 0;
857  fCursor++) { }
858 
860  if (fCursor < fArray->Capacity()) {
861  return fArray->fCont[fCursor++];
862  }
863  } else {
864  for ( ; fCursor >= 0 && fArray->fCont[fCursor] == 0;
865  fCursor--) { }
866 
868  if (fCursor >= 0) {
869  return fArray->fCont[fCursor--];
870  }
871  }
872  return 0;
873 }
874 
875 ////////////////////////////////////////////////////////////////////////////////
876 /// Reset array iterator.
877 
879 {
880  if (fDirection == kIterForward)
881  fCursor = 0;
882  else
883  fCursor = fArray->Capacity() - 1;
884 
886 }
887 
888 ////////////////////////////////////////////////////////////////////////////////
889 /// This operator compares two TIterator objects.
890 
892 {
893  if (aIter.IsA() == TObjArrayIter::Class()) {
894  const TObjArrayIter &iter(dynamic_cast<const TObjArrayIter &>(aIter));
895  return (fCurCursor != iter.fCurCursor);
896  }
897  return false; // for base class we don't implement a comparison
898 }
899 
900 ////////////////////////////////////////////////////////////////////////////////
901 /// This operator compares two TObjArrayIter objects.
902 
904 {
905  return (fCurCursor != aIter.fCurCursor);
906 }
907 
908 ////////////////////////////////////////////////////////////////////////////////
909 /// Return current object or nullptr.
910 
912 {
913  return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
914  fArray->fCont[fCurCursor] : nullptr);
915 }
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition: TStorage.cxx:165
virtual TObject * Remove(TObject *obj)=0
Bool_t IsReading() const
Definition: TBuffer.h:83
object has not been deleted
Definition: TObject.h:69
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:39
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
Definition: TObjArray.cxx:252
TSeqCollection * GetListOfCleanups() const
Definition: TROOT.h:256
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:744
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TObjArray.cxx:891
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:298
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:329
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
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:42
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:364
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:653
virtual void Randomize(Int_t ntimes=1)
Randomize objects inside the array, i.e.
Definition: TObjArray.cxx:723
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
Iterator of object array.
Definition: TObjArray.h:124
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
TString fName
Definition: TCollection.h:62
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
Definition: TObjArray.cxx:157
const TObjArray * fArray
Definition: TObjArray.h:130
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
const char * Class
Definition: TXMLSetup.cxx:64
TObject ** GetObjectRef() const
Definition: TObjArray.h:70
Iterator abstract base class.
Definition: TIterator.h:32
virtual void RemoveRange(Int_t idx1, Int_t idx2)
Remove objects from index idx1 to idx2 included.
Definition: TObjArray.cxx:675
virtual TObject *& operator[](Int_t i)
Return the object at position i.
Definition: TObjArray.cxx:128
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition: TObject.cxx:617
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:479
Bool_t fDirection
Definition: TObjArray.h:133
Sequenceable collection abstract base class.
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TObjArray.cxx:705
virtual void Changed()
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
Definition: TObjArray.cxx:204
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2626
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TObjArray.cxx:599
virtual ~TObjArray()
Delete an array.
Definition: TObjArray.cxx:93
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:119
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:853
void Reset()
Reset array iterator.
Definition: TObjArray.cxx:878
const Bool_t kIterForward
Definition: TCollection.h:43
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
Definition: TObjArray.cxx:765
Bool_t IsOwner() const
Definition: TCollection.h:101
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:528
TObject * First() const
Return the object in the first slot.
Definition: TObjArray.cxx:471
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:528
friend class TObjArrayIter
Definition: TObjArray.h:41
Int_t fLast
Definition: TObjArray.h:47
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:222
SVector< double, 2 > v
Definition: Dict.h:5
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:630
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
Int_t fCurCursor
Definition: TObjArray.h:131
Int_t fSize
Definition: TCollection.h:63
void Init(Int_t s, Int_t lowerBound)
Initialize a TObjArray.
Definition: TObjArray.cxx:571
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:219
void Reset(Detail::TBranchProxy *x)
TROOT * GetROOT()
Definition: TROOT.cxx:487
void Warning(const char *location, const char *msgfmt,...)
TObject ** fCont
Definition: TObjArray.h:45
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:239
#define R__LOCKGUARD2(mutex)
Int_t fLowerBound
Array contents.
Definition: TObjArray.h:46
static void * Alloc(size_t size)
Allocate a block of memory, that later can be resized using TStorage::ReAlloc().
Definition: TStorage.cxx:147
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
Int_t fCursor
Definition: TObjArray.h:132
long Long_t
Definition: RtypesCore.h:50
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TObjArray.h:160
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TObjArray.cxx:508
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:591
Bool_t IsOnHeap() const
Definition: TObject.h:119
#define ClassImp(name)
Definition: Rtypes.h:279
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TObjArray.cxx:824
double Double_t
Definition: RtypesCore.h:55
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:370
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:284
Mother of all ROOT objects.
Definition: TObject.h:37
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:178
TObject * operator*() const
Return current object or nullptr.
Definition: TObjArray.cxx:911
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TObjArray.cxx:609
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Int_t Capacity() const
Definition: TCollection.h:80
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:494
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
Definition: TObjArray.cxx:271
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TObjArray.cxx:169
double result[121]
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:309
Bool_t IsSortable() const
Definition: TCollection.h:102
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
const Bool_t kTRUE
Definition: Rtypes.h:91
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:75
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:180