Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRefArray.cxx
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Rene Brun 02/10/2001
3
4/*************************************************************************
5 * Copyright (C) 1995-2001, 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 TRefArray
13\ingroup Containers
14An array of references to TObjects. The array expands automatically
15when objects are added (shrinking can be done by hand using Expand() )
16
17The TRefArray can be filled with:
18~~~ {.cpp}
19 array.Add(obj)
20 array.AddAt(obj,i)
21 but not array[i] = obj !!!
22~~~
23The array elements can be retrieved with:
24~~~ {.cpp}
25 TObject *obj = array.At(i);
26~~~
27By default the TRefArray 'points' to the current process and can only
28receive object that have been created in this process.
29To point the TRefArray to a different process do:
30~~~ {.cpp}
31 TRefArray array( processId );
32~~~
33For example, if 'obj' is an instance that was created in the different
34process and you do:
35~~~ {.cpp}
36 TRefArray array( TProcessID::GetProcessWithUID( obj ) );
37~~~
38Then
39~~~ {.cpp}
40 array.Add(obj);
41~~~
42is correct (obj comes from the process the array is pointed to
43while
44~~~ {.cpp}
45 TObject *nobj = new TObject;
46 array.Add(nobj);
47~~~
48is incorrect since 'nobj' was created in a different process than the
49one the array is pointed to. In this case you will see error message:
50~~~ {.cpp}
51 Error in <TRefArray::AddAtAndExpand>: The object at 0x... is not
52 registered in the process the TRefArray point to
53 (pid = ProcessID../....)
54~~~
55When a TRefArray is Streamed, only the pointer unique id is written,
56not the referenced object. TRefArray may be assigned to different
57branches of one Tree or several Trees.
58The branch containing the TRefArray can be read before or after the
59array (eg TClonesArray, STL vector,..) of the referenced objects.
60
61See an example in $ROOTSYS/test/Event.h
62
63### RESTRICTIONS when using TRefArray
64
65 - Elements in a TRefArray cannot point to a TFile or TDirectory.
66 - All elements of a TRefArray must be set in the same process,
67 In particular, one cannot modify some elements of the array in
68 a different process.
69
70Use an array of TRef when one of the above restrictions is met.
71
72The number of TRef handled by a single process id is limited to
7316777215 (see TRef for more detail). When the TProcessID is full
74(has seen 16777215 objects), we switch to new one TProcessID
75maximum 65535 including the TProcessIDs read from file).
76However TRefArray can not switch to new TProcessID if they already
77contain objects.
78
79When the TProcessID has been switched due to overflow and an new
80object is added to an existing, empty TRefArray, you will see:
81
82~~~ {.cpp}
83Warning in <TRefArray::AddAtAndExpand>: The ProcessID for the 0x5f83819e8 has been switched to ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef:4
84~~~
85If the TRefArray was not empty, you will see:
86
87~~~ {.cpp}
88Error in <TRefArray::AddAtAndExpand>: The object at %p can not be registered in the process the TRefArray points to (pid = ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef) because the ProcessID has too many objects and the TRefArray already contains other objects.
89~~~
90When running out of TProcessIds, you will see:
91
92~~~ {.cpp}
93Warning in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.
94Fatal in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.
95~~~
96*/
97
98#include "TRefArray.h"
99#include "TRefTable.h"
100#include "TBuffer.h"
101#include "TError.h"
102#include "TBits.h"
103
104
105////////////////////////////////////////////////////////////////////////////////
106/// default constructor
107
109{
111 fUIDs = nullptr;
112 fSize = 0;
113 fLast = -1;
114 fLowerBound = 0;
115 Changed();
116}
117
118////////////////////////////////////////////////////////////////////////////////
119/// Create an object array. Using s one can set the array size
120/// and lowerBound can be used to set the array lowerbound
121/// index (default is 0).
122
124{
125 if (s < 0) {
126 Warning("TRefArray", "size (%d) < 0", s);
128 }
129
131 fUIDs = nullptr;
132 fSize = 0;
133 Init(s, 0);
134}
135
136////////////////////////////////////////////////////////////////////////////////
137/// Create an object array. Using s one can set the array size
138/// and lowerBound can be used to set the array lowerbound
139/// index (default is 0).
140
142{
143 if (s < 0) {
144 Warning("TRefArray", "size (%d) < 0", s);
146 }
147
149 fUIDs = nullptr;
150 fSize = 0;
151 Init(s, lowerBound);
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Create a copy of TRefArray a.
156
158{
159 fPID = a.fPID;
160 fUIDs = nullptr;
161 fSize = 0;
162 Init(a.fSize, a.fLowerBound);
163
164 for (Int_t i = 0; i < fSize; i++)
165 fUIDs[i] = a.fUIDs[i];
166
167 fLast = a.fLast;
168 fName = a.fName;
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// Assignment operator.
173
175{
176 if (this != &a) {
177 // Copy this by hand because the assignment operator
178 // of TCollection is private
179 fName = a.fName;
180 fSorted = a.fSorted;
181 fPID = a.fPID;
182 Init(a.fSize, a.fLowerBound);
183
184 for (Int_t i = 0; i < fSize; i++)
185 fUIDs[i] = a.fUIDs[i];
186
187 fLast = a.fLast;
188 fName = a.fName;
189 }
190 return *this;
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Usual destructor (The object pointed to by the array are never deleted).
195
197{
198 if (fUIDs) delete [] fUIDs;
199 fPID = nullptr;
200 fUIDs = nullptr;
201 fSize = 0;
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// Private/static function, check for validity of pid.
206
208{
209 // Check if the object can belong here.
211 if (obj->TestBit(kHasUUID)) {
212 valid = kFALSE;
213 } else if (obj->TestBit(kIsReferenced)) {
215 if (valid) {
216 uid = obj->GetUniqueID();
217 } else {
218 if (GetAbsLast() < 0) {
219 // The container is empty, we can switch the ProcessID.
220 uid = obj->GetUniqueID();
222 valid = kTRUE;
223 if (gDebug > 3)
224 Info(TString::Format("TRefArray::%s",methodname),"The ProcessID for the %p has been switched to %s/%s:%d.",
225 this,fPID->GetName(),fPID->GetTitle(),fPID->GetUniqueID());
226 }
227 }
228 } else {
229 // If we could, we would just add the object to the
230 // TRefArray's ProcessID. For now, just check the
231 // ProcessID it would be added to, i.e the current one,
232 // is not full.
233
234 if (!(TProcessID::GetObjectCount() >= 16777215)) {
236 if (valid) {
237 uid = TProcessID::AssignID(obj);
238 }
239 } else {
240 // The AssignID will create a new TProcessID.
241 if (GetAbsLast() < 0) {
242 // If we are empty, we can handle it.
243 uid = TProcessID::AssignID(obj);
245 Warning(TString::Format("TRefArray::%s",methodname),"The ProcessID for the %p has been switched to %s/%s:%d. There are too many referenced objects.",
246 this,fPID->GetName(),fPID->GetTitle(),fPID->GetUniqueID());
247 return kTRUE;
248 } else {
249 Error(TString::Format("TRefArray::%s",methodname),"The object at %p can not be registered in the process the TRefArray points to (pid = %s/%s) because the ProcessID has too many objects and the TRefArray already contains other objects.",obj,fPID->GetName(),fPID->GetTitle());
250 return kFALSE;
251 }
252 }
253 }
254
255 if (!valid) {
256 ::Error(TString::Format("TRefArray::%s",methodname),
257 "The object at %p is not registered in the process the TRefArray points to (pid = %s/%s)",obj,fPID->GetName(),fPID->GetTitle());
258 }
259 return valid;
260}
261
262////////////////////////////////////////////////////////////////////////////////
263/// Add object in the first slot of the array. This will overwrite the
264/// first element that might have been there. To have insertion semantics
265/// use either a TList or a TOrdCollection.
266
268{
269 if (!obj) return;
270
271 // Check if the object can belong here
272 Int_t uid;
273 if (GetObjectUID(uid, obj, "AddFirst")) {
274 fUIDs[0] = uid;
275 Changed();
276 }
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// Add object in the next empty slot in the array. Expand the array
281/// if necessary.
282
287
288////////////////////////////////////////////////////////////////////////////////
289/// Add object in the slot before object before. If before=0 add object
290/// in the first slot. Note that this will overwrite any object that
291/// might have already been in this slot. For insertion semantics use
292/// either a TList or a TOrdCollection.
293
295{
296 if (!before)
297 AddFirst(obj);
298 else {
300 if (idx == -1) {
301 Error("AddBefore", "before not found, object not added");
302 return;
303 }
304 if (idx == 0) {
305 Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
306 return;
307 }
308 AddAt(obj, idx+fLowerBound-1);
309 }
310}
311
312////////////////////////////////////////////////////////////////////////////////
313/// Add object in the slot after object after. If after=0 add object in
314/// the last empty slot. Note that this will overwrite any object that
315/// might have already been in this slot. For insertion semantics use
316/// either a TList or a TOrdCollection.
317
319{
320 if (!after)
321 AddLast(obj);
322 else {
324 if (idx == -1) {
325 Error("AddAfter", "after not found, object not added");
326 return;
327 }
328 AddAtAndExpand(obj, idx+fLowerBound+1);
329 }
330}
331
332////////////////////////////////////////////////////////////////////////////////
333/// Add object at position idx. If idx is larger than the current size
334/// of the array, expand the array (double its size).
335
337{
338 if (!obj) return;
339 if (idx < fLowerBound) {
340 Error("AddAt", "out of bounds at %d in %zx", idx, (size_t)this);
341 return;
342 }
343 if (idx-fLowerBound >= fSize)
344 Expand(std::max(idx-fLowerBound+1, GrowBy(fSize)));
345
346 // Check if the object can belong here
347 Int_t uid;
348 if (GetObjectUID(uid, obj, "AddAtAndExpand")) {
349 fUIDs[idx-fLowerBound] = uid; // NOLINT
350 fLast = std::max(idx-fLowerBound, GetAbsLast());
351 Changed();
352 }
353}
354
355////////////////////////////////////////////////////////////////////////////////
356/// Add object at position ids. Give an error when idx is out of bounds
357/// (i.e. the array is not expanded).
358
360{
361 if (!obj) return;
362 if (!BoundsOk("AddAt", idx)) return;
363
364 // Check if the object can belong here
365 Int_t uid;
366 if (GetObjectUID(uid, obj, "AddAt")) {
367 fUIDs[idx-fLowerBound] = uid;
368 fLast = std::max(idx-fLowerBound, GetAbsLast());
369 Changed();
370 }
371}
372
373////////////////////////////////////////////////////////////////////////////////
374/// Return the position of the new object.
375/// Find the first empty cell or AddLast if there is no empty cell
376
378{
379 if (!obj) return 0;
380 if (Last()) { // <---------- This is to take in account "empty" TRefArray's
381 Int_t i;
382 for (i = 0; i < fSize; i++)
383 if (!fUIDs[i]) { // Add object at position i
384 // Check if the object can belong here
385 Int_t uid;
386 if (GetObjectUID(uid, obj, "AddAtFree")) {
387 fUIDs[i] = uid; // NOLINT
388 fLast = std::max(i, GetAbsLast());
389 Changed();
390 return i+fLowerBound;
391 }
392 }
393 }
394 AddLast(obj);
395 return GetLast();
396}
397
398////////////////////////////////////////////////////////////////////////////////
399/// Return the object after obj. Returns 0 if obj is last object.
400
402{
403 if (!obj || !fPID) return nullptr;
404
405 Int_t idx = IndexOf(obj) - fLowerBound;
406 if (idx == -1 || idx == fSize-1) return nullptr;
407
408 return fPID->GetObjectWithID(fUIDs[idx+1]);
409}
410
411////////////////////////////////////////////////////////////////////////////////
412/// Return the object before obj. Returns 0 if obj is first object.
413
415{
416 if (!obj || !fPID) return nullptr;
417
418 Int_t idx = IndexOf(obj) - fLowerBound;
419 if (idx == -1 || idx == 0) return nullptr;
420
421 return fPID->GetObjectWithID(fUIDs[idx-1]);
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Remove all objects from the array.
426
428{
429 fLast = - 1;
430
431 for (Int_t j=0 ; j < fSize; j++) fUIDs[j] = 0;
432
433 Changed();
434}
435
436////////////////////////////////////////////////////////////////////////////////
437/// Remove empty slots from array.
438
440{
441 Int_t j = 0;
442
443 for (Int_t i = 0; i < fSize; i++) {
444 if (fUIDs[i]) {
445 fUIDs[j] = fUIDs[i];
446 j++;
447 }
448 }
449
450 fLast = j - 1;
451
452 for ( ; j < fSize; j++) fUIDs[j] = 0;
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Remove all objects from the array and free the internal memory.
457
459{
460 fLast = -1;
461
462 fSize = 0;
463 if (fUIDs) {
464 delete [] fUIDs;
465 fUIDs = nullptr;
466 }
467
468 Changed();
469}
470
471////////////////////////////////////////////////////////////////////////////////
472/// Expand or shrink the array to newSize elements.
473
475{
476 if (newSize < 0) {
477 Error ("Expand", "newSize must be positive (%d)", newSize);
478 return;
479 }
480 if (newSize == fSize) return;
481 UInt_t *temp = fUIDs;
482 if (newSize != 0) {
483 fUIDs = new UInt_t[newSize];
484 if (newSize < fSize) {
485 memcpy(fUIDs, temp, newSize*sizeof(UInt_t));
486 } else if (temp) {
487 memcpy(fUIDs, temp, fSize*sizeof(UInt_t));
488 memset(&fUIDs[fSize], 0, (newSize-fSize)*sizeof(UInt_t));
489 } else {
490 memset(fUIDs, 0, newSize*sizeof(UInt_t));
491 }
492 } else {
493 fUIDs = nullptr;
494 }
495 if (temp) delete [] temp;
496 fSize = newSize;
497}
498
499////////////////////////////////////////////////////////////////////////////////
500///the reference may be in the TRefTable
501
503{
505 if (table) {
506 table->SetUID(fUIDs[idx], fPID);
507 table->Notify();
508 return fPID->GetObjectWithID(fUIDs[idx]);
509 }
510 return nullptr;
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Stream all objects in the array to or from the I/O buffer.
515
517{
521 if (R__b.IsReading()) {
522 R__b.ReadVersion(&R__s, &R__c);
525 R__b >> nobjects;
526 R__b >> fLowerBound;
527 if (nobjects >= fSize) Expand(nobjects);
528 fLast = -1;
529 R__b >> pidf;
530 pidf += R__b.GetPidOffset();
531 fPID = R__b.ReadProcessID(pidf);
532 if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%zx, nobjects=%d\n",pidf,(size_t)fPID,nobjects);
533 for (Int_t i = 0; i < nobjects; i++) {
534 R__b >> fUIDs[i];
535 if (fUIDs[i] != 0) fLast = i;
536 if (gDebug > 1) {
537 printf(" %d",fUIDs[i]);
538 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
539 }
540 }
541 memset(&fUIDs[fLast+1], 0, (fSize - fLast - 1)*sizeof(fUIDs[0]));
542 Changed();
543 R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
544 } else {
545 R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
548 nobjects = GetAbsLast()+1;
549 R__b << nobjects;
550 R__b << fLowerBound;
551 pidf = R__b.WriteProcessID(fPID);
552 R__b << pidf;
553 if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%zx, nobjects=%d\n",pidf,(size_t)fPID,nobjects);
554
555 for (Int_t i = 0; i < nobjects; i++) {
556 R__b << fUIDs[i];
557 if (gDebug > 1) {
558 printf(" %d",fUIDs[i]);
559 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
560 }
561 }
562 R__b.SetByteCount(R__c, kTRUE);
563 }
564}
565
566////////////////////////////////////////////////////////////////////////////////
567/// Return the object in the first slot.
568
570{
571 return fPID->GetObjectWithID(fUIDs[0]);
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Return the object in the last filled slot. Returns 0 if no entries.
576
578{
579 if (fLast == -1)
580 return nullptr;
581 else
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// Return the number of objects in array (i.e. number of non-empty slots).
587/// Attention: use this method ONLY if you want to know the number of
588/// non-empty slots. This function loops over the complete array and
589/// is therefore very slow when applied in a loop. Most of the time you
590/// better use GetLast()+1.
591
593{
594 Int_t cnt = 0;
595
596 for (Int_t i = 0; i < fSize; i++)
597 if (fUIDs[i]) cnt++;
598
599 return cnt;
600}
601
602////////////////////////////////////////////////////////////////////////////////
603/// Return absolute index to last object in array. Returns -1 in case
604/// array is empty.
605
607{
608 // For efficiency we need sometimes to update fLast so we have
609 // to cast const away. Ugly, but making GetAbsLast() not const breaks
610 // many other const functions.
611 if (fLast == -2) {
612 for (Int_t i = fSize-1; i >= 0; i--)
613 if (fUIDs[i]) {
614 ((TRefArray*)this)->fLast = i;
615 return fLast;
616 }
617 ((TRefArray*)this)->fLast = -1;
618 }
619 return fLast;
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Return index of last object in array. Returns lowerBound-1 in case
624/// array is empty.
625
627{
628 return fLowerBound+GetAbsLast();
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Return address of pointer obj.
633
635{
636 //Int_t index = IndexOf(obj);
637 //return &fCont[index];
638 return nullptr;
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// Return UID of element at.
643
645{
646 int j = at-fLowerBound;
647 if (j >= 0 && j < fSize) {
648 if (!fPID) return 0;
649 return fUIDs[j];
650 }
651 BoundsOk("At", at);
652 return 0;
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// - obj != 0 Return index of object in array.
657/// Returns lowerBound-1 in case array doesn't contain the obj.
658///
659/// - obj == 0 Return the index of the first empty slot.
660/// Returns lowerBound-1 in case array doesn't contain any empty slot.
661
663{
664 Int_t i;
665 if (obj) {
667 return fLowerBound-1;
668 }
669 for (i = 0; i < fSize; i++)
670 if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
671 return i+fLowerBound;
672 } else { // Look for the first empty slot
673 for (i = 0; i < fSize; i++)
674 if (!fUIDs[i])
675 return i+fLowerBound;
676 }
677
678 return fLowerBound-1;
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// Initialize a TRefArray.
683
685{
686 if (s != fSize) {
687 if (fUIDs) {
688 delete [] fUIDs;
689 fUIDs = nullptr;
690 }
691 fSize = s;
692
693 if (fSize) {
694 fUIDs = new UInt_t[fSize];
695 for (Int_t i=0;i<s;i++)
696 fUIDs[i] = 0;
697 }
698 }
699
701 fLast = -1;
702 Changed();
703}
704
705////////////////////////////////////////////////////////////////////////////////
706/// Returns an array iterator.
707
709{
710 return new TRefArrayIter(this, dir);
711}
712
713////////////////////////////////////////////////////////////////////////////////
714/// Generate an out-of-bounds error. Always returns false.
715
717{
718 Error(where, "index %d out of bounds (size: %d, this: 0x%zx)", i, fSize, (size_t)this);
719 return kFALSE;
720}
721
722////////////////////////////////////////////////////////////////////////////////
723/// Remove object at index idx.
724
726{
727 if (!BoundsOk("RemoveAt", idx)) return nullptr;
728
729 int i = idx-fLowerBound;
730
731 TObject *obj = nullptr;
732 if (fUIDs[i]) {
733 if (!TProcessID::IsValid(fPID)) return nullptr;
734 obj = fPID->GetObjectWithID(fUIDs[i]);
735 fUIDs[i] = 0;
736 // recalculate array size
737 if (i == fLast)
738 do {
739 fLast--;
740 } while (fLast >= 0 && fUIDs[fLast] == 0);
741 Changed();
742 }
743
744 return obj;
745}
746
747////////////////////////////////////////////////////////////////////////////////
748/// Remove object from array.
749
751{
752 if (!obj) return nullptr;
753
754 Int_t idx = IndexOf(obj) - fLowerBound;
755
756 if (idx == -1) return nullptr;
757
759 fUIDs[idx] = 0;
760 // recalculate array size
761 if (idx == fLast)
762 do {
763 fLast--;
764 } while (fLast >= 0 && fUIDs[fLast] == 0);
765 Changed();
766 return ob;
767}
768
769////////////////////////////////////////////////////////////////////////////////
770/// Set index of last object in array, effectively truncating the
771/// array. Use carefully since whenever last position has to be
772/// recalculated, e.g. after a Remove() or Sort() it will be reset
773/// to the last non-empty slot. If last is -2 this will force the
774/// recalculation of the last used slot.
775
777{
778 if (last == -2)
779 fLast = -2;
780 else if (BoundsOk("SetLast", last))
781 fLast = last - fLowerBound;
782}
783
784////////////////////////////////////////////////////////////////////////////////
785/// If objects in array are sortable (i.e. IsSortable() returns true
786/// for all objects) then sort array.
787
789{
790 Error("Sort","Function not yet implemented");
791/*
792 if (GetAbsLast() == -1 || fSorted) return;
793 for (Int_t i = 0; i < fSize; i++)
794 if (fUIDs[i]) {
795 if (!fUIDs[i]->IsSortable()) {
796 Error("Sort", "objects in array are not sortable");
797 return;
798 }
799 }
800
801 QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
802
803 fLast = -2;
804 fSorted = kTRUE;
805*/
806}
807
808////////////////////////////////////////////////////////////////////////////////
809/// Find object using a binary search. Array must first have been sorted.
810/// Search can be limited by setting upto to desired index.
811
813{
814 Error("BinarySearch","Function not yet implemented");
815/*
816 Int_t base, position, last, result = 0;
817 TObject *op2;
818
819 if (!op) return -1;
820
821 if (!fSorted) {
822 Error("BinarySearch", "array must first be sorted");
823 return -1;
824 }
825
826 base = 0;
827 last = TMath::Min(fSize, upto-fLowerBound) - 1;
828
829 while (last >= base) {
830 //position = (base+last) / 2;
831 //op2 = fCont[position];
832 //if (op2 && (result = op->Compare(op2)) == 0)
833 // return position + fLowerBound;
834 //if (!op2 || result < 0)
835 // last = position-1;
836 //else
837 // base = position+1;
838 }
839*/
840 return -1;
841}
842
843/** \class TRefArrayIter
844Iterator of object array.
845*/
846
847
848////////////////////////////////////////////////////////////////////////////////
849/// Create array iterator. By default the iteration direction
850/// is kIterForward. To go backward use kIterBackward.
851
853{
854 fArray = arr;
855 fDirection = dir;
856 Reset();
857}
858
859////////////////////////////////////////////////////////////////////////////////
860/// Copy ctor.
861
863{
864 fArray = iter.fArray;
865 fDirection = iter.fDirection;
866 fCursor = iter.fCursor;
867 fCurCursor = iter.fCurCursor;
868}
869
870////////////////////////////////////////////////////////////////////////////////
871/// Overridden assignment operator.
872
874{
875 if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
876 const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
877 fArray = rhs1.fArray;
878 fDirection = rhs1.fDirection;
879 fCursor = rhs1.fCursor;
880 fCurCursor = rhs1.fCurCursor;
881 }
882 return *this;
883}
884
885////////////////////////////////////////////////////////////////////////////////
886/// Overloaded assignment operator.
887
889{
890 if (this != &rhs) {
891 fArray = rhs.fArray;
892 fDirection = rhs.fDirection;
893 fCursor = rhs.fCursor;
894 fCurCursor = rhs.fCurCursor;
895 }
896 return *this;
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Return next object in array. Returns 0 when no more objects in array.
901
903{
904 if (fDirection == kIterForward) {
905 for ( ; fCursor < fArray->Capacity() && !fArray->At(fCursor+fArray->LowerBound());
906 fCursor++) { }
907
909 if (fCursor < fArray->Capacity()) {
910 fCursor++;
911 return fArray->At(fCurCursor+fArray->LowerBound());
912 }
913 } else {
914 for ( ; fCursor >= 0 && !fArray->At(fCursor);
915 fCursor--) { }
916
918 if (fCursor >= 0) {
919 fCursor--;
920 return fArray->At(fCurCursor+fArray->LowerBound());
921 }
922 }
923 return nullptr;
924}
925
926////////////////////////////////////////////////////////////////////////////////
927/// Reset array iterator.
928
930{
932 fCursor = 0;
933 else
934 fCursor = fArray->Capacity() - 1;
935
937}
938
939////////////////////////////////////////////////////////////////////////////////
940/// This operator compares two TIterator objects.
941
943{
944 if (aIter.IsA() == TRefArrayIter::Class()) {
945 const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
946 return (fCurCursor != iter.fCurCursor);
947 }
948 return false; // for base class we don't implement a comparison
949}
950
951////////////////////////////////////////////////////////////////////////////////
952/// This operator compares two TRefArrayIter objects.
953
955{
956 return (fCurCursor != aIter.fCurCursor);
957}
958
959////////////////////////////////////////////////////////////////////////////////
960/// Return current object or nullptr.
961
963{
964 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
965 fArray->At(fCurCursor) : nullptr);
966}
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
const Bool_t kIterForward
Definition TCollection.h:42
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
TString fName
Iterator abstract base class.
Definition TIterator.h:30
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:475
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:972
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition TObject.h:72
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:71
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced,...
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Iterator of object array.
Definition TRefArray.h:116
TObject * Next() override
Return next object in array. Returns 0 when no more objects in array.
Bool_t fDirection
Definition TRefArray.h:122
void Reset() override
Reset array iterator.
const TRefArray * fArray
Definition TRefArray.h:119
static TClass * Class()
TIterator & operator=(const TIterator &rhs) override
Overridden assignment operator.
Bool_t operator!=(const TIterator &aIter) const override
This operator compares two TIterator objects.
Int_t fCurCursor
Definition TRefArray.h:120
TObject * operator*() const override
Return current object or nullptr.
An array of references to TObjects.
Definition TRefArray.h:33
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Int_t fLowerBound
Definition TRefArray.h:40
TProcessID * fPID
Definition TRefArray.h:38
TRefArray(TProcessID *pid=nullptr)
default constructor
TObject * RemoveAt(Int_t idx) override
Remove object at index idx.
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
void AddFirst(TObject *obj) override
Add object in the first slot of the array.
UInt_t GetUID(Int_t at) const
Return UID of element at.
TClass * IsA() const override
Definition TRefArray.h:98
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
void Delete(Option_t *option="") override
Remove all objects from the array and free the internal memory.
UInt_t * fUIDs
Definition TRefArray.h:39
Bool_t BoundsOk(const char *where, Int_t at) const
Definition TRefArray.h:157
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Int_t GetLast() const override
Return index of last object in array.
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Returns an array iterator.
void AddLast(TObject *obj) override
Add object in the next empty slot in the array.
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
TObject * After(const TObject *obj) const override
Return the object after obj. Returns 0 if obj is last object.
void AddAfter(const TObject *after, TObject *obj) override
Add object in the slot after object after.
friend class TRefArrayIter
Definition TRefArray.h:35
void AddBefore(const TObject *before, TObject *obj) override
Add object in the slot before object before.
void Clear(Option_t *option="") override
Remove all objects from the array.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Int_t GetAbsLast() const
Return absolute index to last object in array.
TObject * Remove(TObject *obj) override
Remove object from array.
Int_t IndexOf(const TObject *obj) const override
Int_t fLast
Definition TRefArray.h:41
void Streamer(TBuffer &) override
Stream all objects in the array to or from the I/O buffer.
TRefArray & operator=(const TRefArray &a)
Assignment operator.
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
TObject * First() const override
Return the object in the first slot.
TObject ** GetObjectRef(const TObject *obj) const override
Return address of pointer obj.
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
virtual void Compress()
Remove empty slots from array.
TObject * Before(const TObject *obj) const override
Return the object before obj. Returns 0 if obj is first object.
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition TRefTable.h:35
virtual void SetUID(UInt_t uid, TProcessID *context=nullptr)
Definition TRefTable.h:91
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Bool_t Notify() override
This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer when reading a reference.
Sequenceable collection abstract base class.
virtual void Changed()
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384