Logo ROOT  
Reference Guide
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#include "TSystem.h"
104#include "TROOT.h"
105
107
108////////////////////////////////////////////////////////////////////////////////
109/// default constructor
110
112{
114 fUIDs = 0;
115 fSize = 0;
116 fLast = -1;
117 fLowerBound = 0;
118 Changed();
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Create an object array. Using s one can set the array size
123/// and lowerBound can be used to set the array lowerbound
124/// index (default is 0).
125
127{
128 if (s < 0) {
129 Warning("TRefArray", "size (%d) < 0", s);
131 }
132
134 fUIDs = 0;
135 Init(s, 0);
136}
137
138////////////////////////////////////////////////////////////////////////////////
139/// Create an object array. Using s one can set the array size
140/// and lowerBound can be used to set the array lowerbound
141/// index (default is 0).
142
144{
145 if (s < 0) {
146 Warning("TRefArray", "size (%d) < 0", s);
148 }
149
151 fUIDs = 0;
152 Init(s, lowerBound);
153}
154
155////////////////////////////////////////////////////////////////////////////////
156/// Create a copy of TRefArray a.
157
159{
160 fPID = a.fPID;
161 fUIDs = 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 fSize = a.fSize;
181 fSorted = a.fSorted;
182
183 fPID = a.fPID;
184 Init(a.fSize, a.fLowerBound);
185
186 for (Int_t i = 0; i < fSize; i++)
187 fUIDs[i] = a.fUIDs[i];
188
189 fLast = a.fLast;
190 fName = a.fName;
191 }
192 return *this;
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Usual destructor (The object pointed to by the array are never deleted).
197
199{
200 if (fUIDs) delete [] fUIDs;
201 fPID = 0;
202 fUIDs = 0;
203 fSize = 0;
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Private/static function, check for validity of pid.
208
209Bool_t TRefArray::GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
210{
211 // Check if the object can belong here.
212 Bool_t valid = kTRUE;
213 if (obj->TestBit(kHasUUID)) {
214 valid = kFALSE;
215 } else if (obj->TestBit(kIsReferenced)) {
216 valid = (fPID == TProcessID::GetProcessWithUID(obj));
217 if (valid) {
218 uid = obj->GetUniqueID();
219 } else {
220 if (GetAbsLast() < 0) {
221 // The container is empty, we can switch the ProcessID.
223 valid = kTRUE;
224 if (gDebug > 3)
225 Info(TString::Format("TRefArray::%s",methodname),"The ProcessID for the %p has been switched to %s/%s:%d.",
226 this,fPID->GetName(),fPID->GetTitle(),fPID->GetUniqueID());
227 }
228 }
229 } else {
230 // If we could, we would just add the object to the
231 // TRefArray's ProcessID. For now, just check the
232 // ProcessID it would be added to, i.e the current one,
233 // is not full.
234
235 if (!(TProcessID::GetObjectCount() >= 16777215)) {
237 if (valid) {
238 uid = TProcessID::AssignID(obj);
239 }
240 } else {
241 // The AssignID will create a new TProcessID.
242 if (GetAbsLast() < 0) {
243 // If we are empty, we can handle it.
244 uid = TProcessID::AssignID(obj);
246 Warning(TString::Format("TRefArray::%s",methodname),"The ProcessID for the %p has been switched to %s/%s:%d. There are too many referenced objects.",
247 this,fPID->GetName(),fPID->GetTitle(),fPID->GetUniqueID());
248 return kTRUE;
249 } else {
250 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());
251 return kFALSE;
252 }
253 }
254 }
255
256 if (!valid) {
257 ::Error(TString::Format("TRefArray::%s",methodname),
258 "The object at %p is not registered in the process the TRefArray points to (pid = %s/%s)",obj,fPID->GetName(),fPID->GetTitle());
259 }
260 return valid;
261}
262
263////////////////////////////////////////////////////////////////////////////////
264/// Add object in the first slot of the array. This will overwrite the
265/// first element that might have been there. To have insertion semantics
266/// use either a TList or a TOrdCollection.
267
269{
270 if (!obj) return;
271
272 // Check if the object can belong here
273 Int_t uid;
274 if (GetObjectUID(uid, obj, "AddFirst")) {
275 fUIDs[0] = uid;
276 Changed();
277 }
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// Add object in the next empty slot in the array. Expand the array
282/// if necessary.
283
285{
287}
288
289////////////////////////////////////////////////////////////////////////////////
290/// Add object in the slot before object before. If before=0 add object
291/// in the first slot. Note that this will overwrite any object that
292/// might have already been in this slot. For insertion semantics use
293/// either a TList or a TOrdCollection.
294
295void TRefArray::AddBefore(const TObject *before, TObject *obj)
296{
297 if (!before)
298 AddFirst(obj);
299 else {
300 Int_t idx = IndexOf(before) - fLowerBound;
301 if (idx == -1) {
302 Error("AddBefore", "before not found, object not added");
303 return;
304 }
305 if (idx == 0) {
306 Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
307 return;
308 }
309 AddAt(obj, idx+fLowerBound-1);
310 }
311}
312
313////////////////////////////////////////////////////////////////////////////////
314/// Add object in the slot after object after. If after=0 add object in
315/// the last empty slot. Note that this will overwrite any object that
316/// might have already been in this slot. For insertion semantics use
317/// either a TList or a TOrdCollection.
318
319void TRefArray::AddAfter(const TObject *after, TObject *obj)
320{
321 if (!after)
322 AddLast(obj);
323 else {
324 Int_t idx = IndexOf(after) - fLowerBound;
325 if (idx == -1) {
326 Error("AddAfter", "after not found, object not added");
327 return;
328 }
329 AddAtAndExpand(obj, idx+fLowerBound+1);
330 }
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Add object at position idx. If idx is larger than the current size
335/// of the array, expand the array (double its size).
336
338{
339 if (!obj) return;
340 if (idx < fLowerBound) {
341 Error("AddAt", "out of bounds at %d in %lx", idx, (Long_t)this);
342 return;
343 }
344 if (idx-fLowerBound >= fSize)
346
347 // Check if the object can belong here
348 Int_t uid;
349 if (GetObjectUID(uid, obj, "AddAtAndExpand")) {
350 fUIDs[idx-fLowerBound] = uid;
352 Changed();
353 }
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Add object at position ids. Give an error when idx is out of bounds
358/// (i.e. the array is not expanded).
359
361{
362 if (!obj) return;
363 if (!BoundsOk("AddAt", idx)) return;
364
365 // Check if the object can belong here
366 Int_t uid;
367 if (GetObjectUID(uid, obj, "AddAt")) {
368 fUIDs[idx-fLowerBound] = uid;;
370 Changed();
371 }
372}
373
374////////////////////////////////////////////////////////////////////////////////
375/// Return the position of the new object.
376/// Find the first empty cell or AddLast if there is no empty cell
377
379{
380 if (!obj) return 0;
381 if (Last()) { // <---------- This is to take in account "empty" TRefArray's
382 Int_t i;
383 for (i = 0; i < fSize; i++)
384 if (!fUIDs[i]) { // Add object at position i
385 // Check if the object can belong here
386 Int_t uid;
387 if (GetObjectUID(uid, obj, "AddAtFree")) {
388 fUIDs[i] = uid;
390 Changed();
391 return i+fLowerBound;
392 }
393 }
394 }
395 AddLast(obj);
396 return GetLast();
397}
398
399////////////////////////////////////////////////////////////////////////////////
400/// Return the object after obj. Returns 0 if obj is last object.
401
403{
404 if (!obj || !fPID) return 0;
405
406 Int_t idx = IndexOf(obj) - fLowerBound;
407 if (idx == -1 || idx == fSize-1) return 0;
408
409 return fPID->GetObjectWithID(fUIDs[idx+1]);
410}
411
412////////////////////////////////////////////////////////////////////////////////
413/// Return the object before obj. Returns 0 if obj is first object.
414
416{
417 if (!obj || !fPID) return 0;
418
419 Int_t idx = IndexOf(obj) - fLowerBound;
420 if (idx == -1 || idx == 0) return 0;
421
422 return fPID->GetObjectWithID(fUIDs[idx-1]);
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// Remove all objects from the array.
427
429{
430 fLast = - 1;
431
432 for (Int_t j=0 ; j < fSize; j++) fUIDs[j] = 0;
433
434 Changed();
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Remove empty slots from array.
439
441{
442 Int_t j = 0;
443
444 for (Int_t i = 0; i < fSize; i++) {
445 if (fUIDs[i]) {
446 fUIDs[j] = fUIDs[i];
447 j++;
448 }
449 }
450
451 fLast = j - 1;
452
453 for ( ; j < fSize; j++) fUIDs[j] = 0;
454}
455
456////////////////////////////////////////////////////////////////////////////////
457/// Remove all objects from the array and free the internal memory.
458
460{
461 fLast = -1;
462
463 fSize = 0;
464 if (fUIDs) {
465 delete [] fUIDs;
466 fUIDs = 0;
467 }
468
469 Changed();
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Expand or shrink the array to newSize elements.
474
476{
477 if (newSize < 0) {
478 Error ("Expand", "newSize must be positive (%d)", newSize);
479 return;
480 }
481 if (newSize == fSize) return;
482 UInt_t *temp = fUIDs;
483 if (newSize != 0) {
484 fUIDs = new UInt_t[newSize];
485 if (newSize < fSize) memcpy(fUIDs,temp, newSize*sizeof(UInt_t));
486 else {
487 memcpy(fUIDs,temp,fSize*sizeof(UInt_t));
488 memset(&fUIDs[fSize],0,(newSize-fSize)*sizeof(UInt_t));
489 }
490 } else {
491 fUIDs = 0;
492 }
493 if (temp) delete [] temp;
494 fSize = newSize;
495}
496
497////////////////////////////////////////////////////////////////////////////////
498///the reference may be in the TRefTable
499
501{
503 if (table) {
504 table->SetUID(fUIDs[idx], fPID);
505 table->Notify();
506 return fPID->GetObjectWithID(fUIDs[idx]);
507 }
508 return 0;
509}
510
511////////////////////////////////////////////////////////////////////////////////
512/// Stream all objects in the array to or from the I/O buffer.
513
514void TRefArray::Streamer(TBuffer &R__b)
515{
516 UInt_t R__s, R__c;
517 Int_t nobjects;
518 UShort_t pidf;
519 if (R__b.IsReading()) {
520 R__b.ReadVersion(&R__s, &R__c);
521 TObject::Streamer(R__b);
522 fName.Streamer(R__b);
523 R__b >> nobjects;
524 R__b >> fLowerBound;
525 if (nobjects >= fSize) Expand(nobjects);
526 fLast = -1;
527 R__b >> pidf;
528 pidf += R__b.GetPidOffset();
529 fPID = R__b.ReadProcessID(pidf);
530 if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
531 for (Int_t i = 0; i < nobjects; i++) {
532 R__b >> fUIDs[i];
533 if (fUIDs[i] != 0) fLast = i;
534 if (gDebug > 1) {
535 printf(" %d",fUIDs[i]);
536 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
537 }
538 }
539 memset(&fUIDs[fLast+1], 0, (fSize - fLast - 1)*sizeof(fUIDs[0]));
540 Changed();
541 R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
542 } else {
543 R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
544 TObject::Streamer(R__b);
545 fName.Streamer(R__b);
546 nobjects = GetAbsLast()+1;
547 R__b << nobjects;
548 R__b << fLowerBound;
549 pidf = R__b.WriteProcessID(fPID);
550 R__b << pidf;
551 if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
552
553 for (Int_t i = 0; i < nobjects; i++) {
554 R__b << fUIDs[i];
555 if (gDebug > 1) {
556 printf(" %d",fUIDs[i]);
557 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
558 }
559 }
560 R__b.SetByteCount(R__c, kTRUE);
561 }
562}
563
564////////////////////////////////////////////////////////////////////////////////
565/// Return the object in the first slot.
566
568{
569 return fPID->GetObjectWithID(fUIDs[0]);
570}
571
572////////////////////////////////////////////////////////////////////////////////
573/// Return the object in the last filled slot. Returns 0 if no entries.
574
576{
577 if (fLast == -1)
578 return 0;
579 else
581}
582
583////////////////////////////////////////////////////////////////////////////////
584/// Return the number of objects in array (i.e. number of non-empty slots).
585/// Attention: use this method ONLY if you want to know the number of
586/// non-empty slots. This function loops over the complete array and
587/// is therefore very slow when applied in a loop. Most of the time you
588/// better use GetLast()+1.
589
591{
592 Int_t cnt = 0;
593
594 for (Int_t i = 0; i < fSize; i++)
595 if (fUIDs[i]) cnt++;
596
597 return cnt;
598}
599
600////////////////////////////////////////////////////////////////////////////////
601/// Return absolute index to last object in array. Returns -1 in case
602/// array is empty.
603
605{
606 // For efficiency we need sometimes to update fLast so we have
607 // to cast const away. Ugly, but making GetAbsLast() not const breaks
608 // many other const functions.
609 if (fLast == -2) {
610 for (Int_t i = fSize-1; i >= 0; i--)
611 if (fUIDs[i]) {
612 ((TRefArray*)this)->fLast = i;
613 return fLast;
614 }
615 ((TRefArray*)this)->fLast = -1;
616 }
617 return fLast;
618}
619
620////////////////////////////////////////////////////////////////////////////////
621/// Return index of last object in array. Returns lowerBound-1 in case
622/// array is empty.
623
625{
626 return fLowerBound+GetAbsLast();
627}
628
629////////////////////////////////////////////////////////////////////////////////
630/// Return address of pointer obj.
631
633{
634 //Int_t index = IndexOf(obj);
635 //return &fCont[index];
636 return 0;
637}
638
639////////////////////////////////////////////////////////////////////////////////
640/// Return UID of element at.
641
643{
644 int j = at-fLowerBound;
645 if (j >= 0 && j < fSize) {
646 if (!fPID) return 0;
647 return fUIDs[j];
648 }
649 BoundsOk("At", at);
650 return 0;
651}
652
653////////////////////////////////////////////////////////////////////////////////
654/// - obj != 0 Return index of object in array.
655/// Returns lowerBound-1 in case array doesn't contain the obj.
656///
657/// - obj == 0 Return the index of the first empty slot.
658/// Returns lowerBound-1 in case array doesn't contain any empty slot.
659
661{
662 Int_t i;
663 if (obj) {
665 return fLowerBound-1;
666 }
667 for (i = 0; i < fSize; i++)
668 if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
669 return i+fLowerBound;
670 } else { // Look for the first empty slot
671 for (i = 0; i < fSize; i++)
672 if (!fUIDs[i])
673 return i+fLowerBound;
674 }
675
676 return fLowerBound-1;
677}
678
679////////////////////////////////////////////////////////////////////////////////
680/// Initialize a TRefArray.
681
682void TRefArray::Init(Int_t s, Int_t lowerBound)
683{
684 if (fUIDs && fSize != s) {
685 delete [] fUIDs;
686 fUIDs = 0;
687 }
688
689 fSize = s;
690
691 if (fSize) {
692 fUIDs = new UInt_t[fSize];
693 for (Int_t i=0;i<s;i++) fUIDs[i] = 0;
694 } else {
695 fUIDs = 0;
696 }
697 fLowerBound = lowerBound;
698 fLast = -1;
699 Changed();
700}
701
702////////////////////////////////////////////////////////////////////////////////
703/// Returns an array iterator.
704
706{
707 return new TRefArrayIter(this, dir);
708}
709
710////////////////////////////////////////////////////////////////////////////////
711/// Generate an out-of-bounds error. Always returns false.
712
713Bool_t TRefArray::OutOfBoundsError(const char *where, Int_t i) const
714{
715 Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
716 return kFALSE;
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// Remove object at index idx.
721
723{
724 if (!BoundsOk("RemoveAt", idx)) return 0;
725
726 int i = idx-fLowerBound;
727
728 TObject *obj = 0;
729 if (fUIDs[i]) {
730 if (!TProcessID::IsValid(fPID)) return 0;
731 obj = fPID->GetObjectWithID(fUIDs[i]);
732 fUIDs[i] = 0;
733 // recalculate array size
734 if (i == fLast)
735 do {
736 fLast--;
737 } while (fLast >= 0 && fUIDs[fLast] == 0);
738 Changed();
739 }
740
741 return obj;
742}
743
744////////////////////////////////////////////////////////////////////////////////
745/// Remove object from array.
746
748{
749 if (!obj) return 0;
750
751 Int_t idx = IndexOf(obj) - fLowerBound;
752
753 if (idx == -1) return 0;
754
755 TObject *ob = fPID->GetObjectWithID(fUIDs[idx]);
756 fUIDs[idx] = 0;
757 // recalculate array size
758 if (idx == fLast)
759 do {
760 fLast--;
761 } while (fLast >= 0 && fUIDs[fLast] == 0);
762 Changed();
763 return ob;
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
774{
775 if (last == -2)
776 fLast = -2;
777 else if (BoundsOk("SetLast", last))
778 fLast = last - fLowerBound;
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// If objects in array are sortable (i.e. IsSortable() returns true
783/// for all objects) then sort array.
784
786{
787 Error("Sort","Function not yet implemented");
788/*
789 if (GetAbsLast() == -1 || fSorted) return;
790 for (Int_t i = 0; i < fSize; i++)
791 if (fUIDs[i]) {
792 if (!fUIDs[i]->IsSortable()) {
793 Error("Sort", "objects in array are not sortable");
794 return;
795 }
796 }
797
798 QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
799
800 fLast = -2;
801 fSorted = kTRUE;
802*/
803}
804
805////////////////////////////////////////////////////////////////////////////////
806/// Find object using a binary search. Array must first have been sorted.
807/// Search can be limited by setting upto to desired index.
808
810{
811 Error("BinarySearch","Function not yet implemented");
812/*
813 Int_t base, position, last, result = 0;
814 TObject *op2;
815
816 if (!op) return -1;
817
818 if (!fSorted) {
819 Error("BinarySearch", "array must first be sorted");
820 return -1;
821 }
822
823 base = 0;
824 last = TMath::Min(fSize, upto-fLowerBound) - 1;
825
826 while (last >= base) {
827 //position = (base+last) / 2;
828 //op2 = fCont[position];
829 //if (op2 && (result = op->Compare(op2)) == 0)
830 // return position + fLowerBound;
831 //if (!op2 || result < 0)
832 // last = position-1;
833 //else
834 // base = position+1;
835 }
836*/
837 return -1;
838}
839
840/** \class TRefArrayIter
841Iterator of object array.
842*/
843
845
846////////////////////////////////////////////////////////////////////////////////
847/// Create array iterator. By default the iteration direction
848/// is kIterForward. To go backward use kIterBackward.
849
851{
852 fArray = arr;
853 fDirection = dir;
854 Reset();
855}
856
857////////////////////////////////////////////////////////////////////////////////
858/// Copy ctor.
859
861{
862 fArray = iter.fArray;
863 fDirection = iter.fDirection;
864 fCursor = iter.fCursor;
865 fCurCursor = iter.fCurCursor;
866}
867
868////////////////////////////////////////////////////////////////////////////////
869/// Overridden assignment operator.
870
872{
873 if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
874 const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
875 fArray = rhs1.fArray;
876 fDirection = rhs1.fDirection;
877 fCursor = rhs1.fCursor;
878 fCurCursor = rhs1.fCurCursor;
879 }
880 return *this;
881}
882
883////////////////////////////////////////////////////////////////////////////////
884/// Overloaded assignment operator.
885
887{
888 if (this != &rhs) {
889 fArray = rhs.fArray;
891 fCursor = rhs.fCursor;
893 }
894 return *this;
895}
896
897////////////////////////////////////////////////////////////////////////////////
898/// Return next object in array. Returns 0 when no more objects in array.
899
901{
902 if (fDirection == kIterForward) {
903 for ( ; fCursor < fArray->Capacity() && fArray->At(fCursor+fArray->LowerBound()) == 0;
904 fCursor++) { }
905
907 if (fCursor < fArray->Capacity()) {
908 fCursor++;
910 }
911 } else {
912 for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
913 fCursor--) { }
914
916 if (fCursor >= 0) {
917 fCursor--;
919 }
920 }
921 return 0;
922}
923
924////////////////////////////////////////////////////////////////////////////////
925/// Reset array iterator.
926
928{
930 fCursor = 0;
931 else
932 fCursor = fArray->Capacity() - 1;
933
935}
936
937////////////////////////////////////////////////////////////////////////////////
938/// This operator compares two TIterator objects.
939
941{
942 if (aIter.IsA() == TRefArrayIter::Class()) {
943 const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
944 return (fCurCursor != iter.fCurCursor);
945 }
946 return false; // for base class we don't implement a comparison
947}
948
949////////////////////////////////////////////////////////////////////////////////
950/// This operator compares two TRefArrayIter objects.
951
953{
954 return (fCurCursor != aIter.fCurCursor);
955}
956
957////////////////////////////////////////////////////////////////////////////////
958/// Return current object or nullptr.
959
961{
962 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
963 fArray->At(fCurCursor) : nullptr);
964}
void Class()
Definition: Class.C:29
unsigned short UShort_t
Definition: RtypesCore.h:38
int Int_t
Definition: RtypesCore.h:43
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
bool Bool_t
Definition: RtypesCore.h:61
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
const Bool_t kIterForward
Definition: TCollection.h:40
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:344
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:353
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual UShort_t GetPidOffset() const =0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Bool_t IsReading() const
Definition: TBuffer.h:85
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Int_t Capacity() const
Definition: TCollection.h:165
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
TString fName
Definition: TCollection.h:147
Iterator abstract base class.
Definition: TIterator.h:30
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition: TObject.h:62
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:358
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced,...
Definition: TProcessID.cxx:153
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:303
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
Definition: TProcessID.cxx:295
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:330
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:322
Iterator of object array.
Definition: TRefArray.h:125
TObject * operator*() const
Return current object or nullptr.
Definition: TRefArray.cxx:960
Bool_t fDirection
Definition: TRefArray.h:131
const TRefArray * fArray
Definition: TRefArray.h:128
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
Definition: TRefArray.cxx:900
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TRefArray.cxx:871
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TRefArray.cxx:940
Int_t fCursor
Definition: TRefArray.h:130
Int_t fCurCursor
Definition: TRefArray.h:129
void Reset()
Reset array iterator.
Definition: TRefArray.cxx:927
An array of references to TObjects.
Definition: TRefArray.h:39
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TRefArray.cxx:705
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TRefArray.cxx:773
Int_t fLowerBound
Definition: TRefArray.h:46
TProcessID * fPID
Definition: TRefArray.h:44
virtual void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
Definition: TRefArray.cxx:295
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
Definition: TRefArray.cxx:682
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TRefArray.cxx:428
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
Definition: TRefArray.cxx:378
TObject * First() const
Return the object in the first slot.
Definition: TRefArray.cxx:567
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
Definition: TRefArray.cxx:500
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TRefArray.cxx:747
UInt_t GetUID(Int_t at) const
Return UID of element at.
Definition: TRefArray.cxx:642
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
Definition: TRefArray.cxx:268
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
Definition: TRefArray.cxx:198
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TRefArray.cxx:475
TRefArray(TProcessID *pid=0)
default constructor
Definition: TRefArray.cxx:111
Int_t IndexOf(const TObject *obj) const
Definition: TRefArray.cxx:660
UInt_t * fUIDs
Definition: TRefArray.h:45
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TRefArray.h:159
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
Definition: TRefArray.cxx:402
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TRefArray.cxx:713
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
Definition: TRefArray.cxx:415
Int_t GetLast() const
Return index of last object in array.
Definition: TRefArray.cxx:624
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
Definition: TRefArray.cxx:809
friend class TRefArrayIter
Definition: TRefArray.h:41
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TRefArray.cxx:360
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
Definition: TRefArray.cxx:319
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TRefArray.cxx:575
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TRefArray.cxx:337
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TRefArray.cxx:604
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TRefArray.cxx:590
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TRefArray.cxx:284
virtual void Delete(Option_t *option="")
Remove all objects from the array and free the internal memory.
Definition: TRefArray.cxx:459
TObject * At(Int_t idx) const
Definition: TRefArray.h:180
Int_t fLast
Definition: TRefArray.h:47
TRefArray & operator=(const TRefArray &a)
Assignment operator.
Definition: TRefArray.cxx:174
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Definition: TRefArray.cxx:785
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
Definition: TRefArray.cxx:209
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TRefArray.cxx:722
virtual void Compress()
Remove empty slots from array.
Definition: TRefArray.cxx:440
Int_t LowerBound() const
Definition: TRefArray.h:97
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer obj.
Definition: TRefArray.cxx:632
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
virtual Bool_t Notify()
This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer when reading a reference.
Definition: TRefTable.cxx:299
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
virtual void SetUID(UInt_t uid, TProcessID *context=0)
Definition: TRefTable.h:87
Sequenceable collection abstract base class.
virtual void Changed()
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:2311
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
const char * cnt
Definition: TXMLSetup.cxx:74
auto * a
Definition: textangle.C:12