Logo ROOT   6.16/01
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 "TError.h"
101#include "TBits.h"
102#include "TSystem.h"
103#include "TROOT.h"
104
106
107////////////////////////////////////////////////////////////////////////////////
108/// default constructor
109
111{
113 fUIDs = 0;
114 fSize = 0;
115 fLast = -1;
116 fLowerBound = 0;
117 Changed();
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Create an object array. Using s one can set the array size
122/// and lowerBound can be used to set the array lowerbound
123/// index (default is 0).
124
126{
127 if (s < 0) {
128 Warning("TRefArray", "size (%d) < 0", s);
130 }
131
133 fUIDs = 0;
134 Init(s, 0);
135}
136
137////////////////////////////////////////////////////////////////////////////////
138/// Create an object array. Using s one can set the array size
139/// and lowerBound can be used to set the array lowerbound
140/// index (default is 0).
141
143{
144 if (s < 0) {
145 Warning("TRefArray", "size (%d) < 0", s);
147 }
148
150 fUIDs = 0;
151 Init(s, lowerBound);
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Create a copy of TRefArray a.
156
158{
159 fPID = a.fPID;
160 fUIDs = 0;
161 Init(a.fSize, a.fLowerBound);
162
163 for (Int_t i = 0; i < fSize; i++)
164 fUIDs[i] = a.fUIDs[i];
165
166 fLast = a.fLast;
167 fName = a.fName;
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Assignment operator.
172
174{
175 if (this != &a) {
176 // Copy this by hand because the assignment operator
177 // of TCollection is private
178 fName = a.fName;
179 fSize = a.fSize;
180 fSorted = a.fSorted;
181
182 fPID = a.fPID;
183 Init(a.fSize, a.fLowerBound);
184
185 for (Int_t i = 0; i < fSize; i++)
186 fUIDs[i] = a.fUIDs[i];
187
188 fLast = a.fLast;
189 fName = a.fName;
190 }
191 return *this;
192}
193
194////////////////////////////////////////////////////////////////////////////////
195/// Usual destructor (The object pointed to by the array are never deleted).
196
198{
199 if (fUIDs) delete [] fUIDs;
200 fPID = 0;
201 fUIDs = 0;
202 fSize = 0;
203}
204
205////////////////////////////////////////////////////////////////////////////////
206/// Private/static function, check for validity of pid.
207
208Bool_t TRefArray::GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
209{
210 // Check if the object can belong here.
211 Bool_t valid = kTRUE;
212 if (obj->TestBit(kHasUUID)) {
213 valid = kFALSE;
214 } else if (obj->TestBit(kIsReferenced)) {
215 valid = (fPID == TProcessID::GetProcessWithUID(obj));
216 if (valid) {
217 uid = obj->GetUniqueID();
218 } else {
219 if (GetAbsLast() < 0) {
220 // The container is empty, we can switch the ProcessID.
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
284{
286}
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
294void TRefArray::AddBefore(const TObject *before, TObject *obj)
295{
296 if (!before)
297 AddFirst(obj);
298 else {
299 Int_t idx = IndexOf(before) - fLowerBound;
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
318void TRefArray::AddAfter(const TObject *after, TObject *obj)
319{
320 if (!after)
321 AddLast(obj);
322 else {
323 Int_t idx = IndexOf(after) - fLowerBound;
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 %lx", idx, (Long_t)this);
341 return;
342 }
343 if (idx-fLowerBound >= 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;
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;;
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;
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 0;
404
405 Int_t idx = IndexOf(obj) - fLowerBound;
406 if (idx == -1 || idx == fSize-1) return 0;
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 0;
417
418 Int_t idx = IndexOf(obj) - fLowerBound;
419 if (idx == -1 || idx == 0) return 0;
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 = 0;
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) memcpy(fUIDs,temp, newSize*sizeof(UInt_t));
485 else {
486 memcpy(fUIDs,temp,fSize*sizeof(UInt_t));
487 memset(&fUIDs[fSize],0,(newSize-fSize)*sizeof(UInt_t));
488 }
489 } else {
490 fUIDs = 0;
491 }
492 if (temp) delete [] temp;
493 fSize = newSize;
494}
495
496////////////////////////////////////////////////////////////////////////////////
497///the reference may be in the TRefTable
498
500{
502 if (table) {
503 table->SetUID(fUIDs[idx], fPID);
504 table->Notify();
505 return fPID->GetObjectWithID(fUIDs[idx]);
506 }
507 return 0;
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Stream all objects in the array to or from the I/O buffer.
512
513void TRefArray::Streamer(TBuffer &R__b)
514{
515 UInt_t R__s, R__c;
516 Int_t nobjects;
517 UShort_t pidf;
518 if (R__b.IsReading()) {
519 R__b.ReadVersion(&R__s, &R__c);
520 TObject::Streamer(R__b);
521 fName.Streamer(R__b);
522 R__b >> nobjects;
523 R__b >> fLowerBound;
524 if (nobjects >= fSize) Expand(nobjects);
525 fLast = -1;
526 R__b >> pidf;
527 pidf += R__b.GetPidOffset();
528 fPID = R__b.ReadProcessID(pidf);
529 if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
530 for (Int_t i = 0; i < nobjects; i++) {
531 R__b >> fUIDs[i];
532 if (fUIDs[i] != 0) fLast = i;
533 if (gDebug > 1) {
534 printf(" %d",fUIDs[i]);
535 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
536 }
537 }
538 memset(&fUIDs[fLast+1], 0, (fSize - fLast - 1)*sizeof(fUIDs[0]));
539 Changed();
540 R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
541 } else {
542 R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
543 TObject::Streamer(R__b);
544 fName.Streamer(R__b);
545 nobjects = GetAbsLast()+1;
546 R__b << nobjects;
547 R__b << fLowerBound;
548 pidf = R__b.WriteProcessID(fPID);
549 R__b << pidf;
550 if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
551
552 for (Int_t i = 0; i < nobjects; i++) {
553 R__b << fUIDs[i];
554 if (gDebug > 1) {
555 printf(" %d",fUIDs[i]);
556 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
557 }
558 }
559 R__b.SetByteCount(R__c, kTRUE);
560 }
561}
562
563////////////////////////////////////////////////////////////////////////////////
564/// Return the object in the first slot.
565
567{
568 return fPID->GetObjectWithID(fUIDs[0]);
569}
570
571////////////////////////////////////////////////////////////////////////////////
572/// Return the object in the last filled slot. Returns 0 if no entries.
573
575{
576 if (fLast == -1)
577 return 0;
578 else
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Return the number of objects in array (i.e. number of non-empty slots).
584/// Attention: use this method ONLY if you want to know the number of
585/// non-empty slots. This function loops over the complete array and
586/// is therefore very slow when applied in a loop. Most of the time you
587/// better use GetLast()+1.
588
590{
591 Int_t cnt = 0;
592
593 for (Int_t i = 0; i < fSize; i++)
594 if (fUIDs[i]) cnt++;
595
596 return cnt;
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Return absolute index to last object in array. Returns -1 in case
601/// array is empty.
602
604{
605 // For efficiency we need sometimes to update fLast so we have
606 // to cast const away. Ugly, but making GetAbsLast() not const breaks
607 // many other const functions.
608 if (fLast == -2) {
609 for (Int_t i = fSize-1; i >= 0; i--)
610 if (fUIDs[i]) {
611 ((TRefArray*)this)->fLast = i;
612 return fLast;
613 }
614 ((TRefArray*)this)->fLast = -1;
615 }
616 return fLast;
617}
618
619////////////////////////////////////////////////////////////////////////////////
620/// Return index of last object in array. Returns lowerBound-1 in case
621/// array is empty.
622
624{
625 return fLowerBound+GetAbsLast();
626}
627
628////////////////////////////////////////////////////////////////////////////////
629/// Return address of pointer obj.
630
632{
633 //Int_t index = IndexOf(obj);
634 //return &fCont[index];
635 return 0;
636}
637
638////////////////////////////////////////////////////////////////////////////////
639/// Return UID of element at.
640
642{
643 int j = at-fLowerBound;
644 if (j >= 0 && j < fSize) {
645 if (!fPID) return 0;
646 return fUIDs[j];
647 }
648 BoundsOk("At", at);
649 return 0;
650}
651
652////////////////////////////////////////////////////////////////////////////////
653/// - obj != 0 Return index of object in array.
654/// Returns lowerBound-1 in case array doesn't contain the obj.
655///
656/// - obj == 0 Return the index of the first empty slot.
657/// Returns lowerBound-1 in case array doesn't contain any empty slot.
658
660{
661 Int_t i;
662 if (obj) {
664 return fLowerBound-1;
665 }
666 for (i = 0; i < fSize; i++)
667 if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
668 return i+fLowerBound;
669 } else { // Look for the first empty slot
670 for (i = 0; i < fSize; i++)
671 if (!fUIDs[i])
672 return i+fLowerBound;
673 }
674
675 return fLowerBound-1;
676}
677
678////////////////////////////////////////////////////////////////////////////////
679/// Initialize a TRefArray.
680
681void TRefArray::Init(Int_t s, Int_t lowerBound)
682{
683 if (fUIDs && fSize != s) {
684 delete [] fUIDs;
685 fUIDs = 0;
686 }
687
688 fSize = s;
689
690 if (fSize) {
691 fUIDs = new UInt_t[fSize];
692 for (Int_t i=0;i<s;i++) fUIDs[i] = 0;
693 } else {
694 fUIDs = 0;
695 }
696 fLowerBound = lowerBound;
697 fLast = -1;
698 Changed();
699}
700
701////////////////////////////////////////////////////////////////////////////////
702/// Returns an array iterator.
703
705{
706 return new TRefArrayIter(this, dir);
707}
708
709////////////////////////////////////////////////////////////////////////////////
710/// Generate an out-of-bounds error. Always returns false.
711
712Bool_t TRefArray::OutOfBoundsError(const char *where, Int_t i) const
713{
714 Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
715 return kFALSE;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719/// Remove object at index idx.
720
722{
723 if (!BoundsOk("RemoveAt", idx)) return 0;
724
725 int i = idx-fLowerBound;
726
727 TObject *obj = 0;
728 if (fUIDs[i]) {
729 if (!TProcessID::IsValid(fPID)) return 0;
730 obj = fPID->GetObjectWithID(fUIDs[i]);
731 fUIDs[i] = 0;
732 // recalculate array size
733 if (i == fLast)
734 do {
735 fLast--;
736 } while (fLast >= 0 && fUIDs[fLast] == 0);
737 Changed();
738 }
739
740 return obj;
741}
742
743////////////////////////////////////////////////////////////////////////////////
744/// Remove object from array.
745
747{
748 if (!obj) return 0;
749
750 Int_t idx = IndexOf(obj) - fLowerBound;
751
752 if (idx == -1) return 0;
753
754 TObject *ob = fPID->GetObjectWithID(fUIDs[idx]);
755 fUIDs[idx] = 0;
756 // recalculate array size
757 if (idx == fLast)
758 do {
759 fLast--;
760 } while (fLast >= 0 && fUIDs[fLast] == 0);
761 Changed();
762 return ob;
763}
764
765////////////////////////////////////////////////////////////////////////////////
766/// Set index of last object in array, effectively truncating the
767/// array. Use carefully since whenever last position has to be
768/// recalculated, e.g. after a Remove() or Sort() it will be reset
769/// to the last non-empty slot. If last is -2 this will force the
770/// recalculation of the last used slot.
771
773{
774 if (last == -2)
775 fLast = -2;
776 else if (BoundsOk("SetLast", last))
777 fLast = last - fLowerBound;
778}
779
780////////////////////////////////////////////////////////////////////////////////
781/// If objects in array are sortable (i.e. IsSortable() returns true
782/// for all objects) then sort array.
783
785{
786 Error("Sort","Function not yet implemented");
787/*
788 if (GetAbsLast() == -1 || fSorted) return;
789 for (Int_t i = 0; i < fSize; i++)
790 if (fUIDs[i]) {
791 if (!fUIDs[i]->IsSortable()) {
792 Error("Sort", "objects in array are not sortable");
793 return;
794 }
795 }
796
797 QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
798
799 fLast = -2;
800 fSorted = kTRUE;
801*/
802}
803
804////////////////////////////////////////////////////////////////////////////////
805/// Find object using a binary search. Array must first have been sorted.
806/// Search can be limited by setting upto to desired index.
807
809{
810 Error("BinarySearch","Function not yet implemented");
811/*
812 Int_t base, position, last, result = 0;
813 TObject *op2;
814
815 if (!op) return -1;
816
817 if (!fSorted) {
818 Error("BinarySearch", "array must first be sorted");
819 return -1;
820 }
821
822 base = 0;
823 last = TMath::Min(fSize, upto-fLowerBound) - 1;
824
825 while (last >= base) {
826 //position = (base+last) / 2;
827 //op2 = fCont[position];
828 //if (op2 && (result = op->Compare(op2)) == 0)
829 // return position + fLowerBound;
830 //if (!op2 || result < 0)
831 // last = position-1;
832 //else
833 // base = position+1;
834 }
835*/
836 return -1;
837}
838
839/** \class TRefArrayIter
840Iterator of object array.
841*/
842
844
845////////////////////////////////////////////////////////////////////////////////
846/// Create array iterator. By default the iteration direction
847/// is kIterForward. To go backward use kIterBackward.
848
850{
851 fArray = arr;
852 fDirection = dir;
853 Reset();
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// Copy ctor.
858
860{
861 fArray = iter.fArray;
862 fDirection = iter.fDirection;
863 fCursor = iter.fCursor;
864 fCurCursor = iter.fCurCursor;
865}
866
867////////////////////////////////////////////////////////////////////////////////
868/// Overridden assignment operator.
869
871{
872 if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
873 const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
874 fArray = rhs1.fArray;
875 fDirection = rhs1.fDirection;
876 fCursor = rhs1.fCursor;
877 fCurCursor = rhs1.fCurCursor;
878 }
879 return *this;
880}
881
882////////////////////////////////////////////////////////////////////////////////
883/// Overloaded assignment operator.
884
886{
887 if (this != &rhs) {
888 fArray = rhs.fArray;
890 fCursor = rhs.fCursor;
892 }
893 return *this;
894}
895
896////////////////////////////////////////////////////////////////////////////////
897/// Return next object in array. Returns 0 when no more objects in array.
898
900{
901 if (fDirection == kIterForward) {
902 for ( ; fCursor < fArray->Capacity() && fArray->At(fCursor+fArray->LowerBound()) == 0;
903 fCursor++) { }
904
906 if (fCursor < fArray->Capacity()) {
907 fCursor++;
909 }
910 } else {
911 for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
912 fCursor--) { }
913
915 if (fCursor >= 0) {
916 fCursor--;
918 }
919 }
920 return 0;
921}
922
923////////////////////////////////////////////////////////////////////////////////
924/// Reset array iterator.
925
927{
929 fCursor = 0;
930 else
931 fCursor = fArray->Capacity() - 1;
932
934}
935
936////////////////////////////////////////////////////////////////////////////////
937/// This operator compares two TIterator objects.
938
940{
941 if (aIter.IsA() == TRefArrayIter::Class()) {
942 const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
943 return (fCurCursor != iter.fCurCursor);
944 }
945 return false; // for base class we don't implement a comparison
946}
947
948////////////////////////////////////////////////////////////////////////////////
949/// This operator compares two TRefArrayIter objects.
950
952{
953 return (fCurCursor != aIter.fCurCursor);
954}
955
956////////////////////////////////////////////////////////////////////////////////
957/// Return current object or nullptr.
958
960{
961 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
962 fArray->At(fCurCursor) : nullptr);
963}
void Class()
Definition: Class.C:29
unsigned short UShort_t
Definition: RtypesCore.h:36
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
const Bool_t kIterForward
Definition: TCollection.h:40
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:323
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:332
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:83
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:172
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:866
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
@ 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:854
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:959
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:899
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TRefArray.cxx:870
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TRefArray.cxx:939
Int_t fCursor
Definition: TRefArray.h:130
Int_t fCurCursor
Definition: TRefArray.h:129
void Reset()
Reset array iterator.
Definition: TRefArray.cxx:926
An array of references to TObjects.
Definition: TRefArray.h:39
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TRefArray.cxx:704
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TRefArray.cxx:772
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:294
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
Definition: TRefArray.cxx:681
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TRefArray.cxx:427
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
Definition: TRefArray.cxx:377
TObject * First() const
Return the object in the first slot.
Definition: TRefArray.cxx:566
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
Definition: TRefArray.cxx:499
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TRefArray.cxx:746
UInt_t GetUID(Int_t at) const
Return UID of element at.
Definition: TRefArray.cxx:641
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
Definition: TRefArray.cxx:267
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
Definition: TRefArray.cxx:197
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TRefArray.cxx:474
TRefArray(TProcessID *pid=0)
default constructor
Definition: TRefArray.cxx:110
Int_t IndexOf(const TObject *obj) const
Definition: TRefArray.cxx:659
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:401
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TRefArray.cxx:712
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
Definition: TRefArray.cxx:414
Int_t GetLast() const
Return index of last object in array.
Definition: TRefArray.cxx:623
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
Definition: TRefArray.cxx:808
friend class TRefArrayIter
Definition: TRefArray.h:41
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TRefArray.cxx:359
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
Definition: TRefArray.cxx:318
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TRefArray.cxx:574
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TRefArray.cxx:336
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TRefArray.cxx:603
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TRefArray.cxx:589
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TRefArray.cxx:283
virtual void Delete(Option_t *option="")
Remove all objects from the array and free the internal memory.
Definition: TRefArray.cxx:458
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:173
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Definition: TRefArray.cxx:784
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
Definition: TRefArray.cxx:208
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TRefArray.cxx:721
virtual void Compress()
Remove empty slots from array.
Definition: TRefArray.cxx:439
Int_t LowerBound() const
Definition: TRefArray.h:97
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer obj.
Definition: TRefArray.cxx:631
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
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:2286
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
const char * cnt
Definition: TXMLSetup.cxx:74
void table()
Definition: table.C:85
auto * a
Definition: textangle.C:12