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