Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRefArray.cxx
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Rene Brun 02/10/2001
3
4/*************************************************************************
5 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TRefArray
13\ingroup Containers
14An array of references to TObjects. The array expands automatically
15when objects are added (shrinking can be done by hand using Expand() )
16
17The TRefArray can be filled with:
18~~~ {.cpp}
19 array.Add(obj)
20 array.AddAt(obj,i)
21 but not array[i] = obj !!!
22~~~
23The array elements can be retrieved with:
24~~~ {.cpp}
25 TObject *obj = array.At(i);
26~~~
27By default the TRefArray 'points' to the current process and can only
28receive object that have been created in this process.
29To point the TRefArray to a different process do:
30~~~ {.cpp}
31 TRefArray array( processId );
32~~~
33For example, if 'obj' is an instance that was created in the different
34process and you do:
35~~~ {.cpp}
36 TRefArray array( TProcessID::GetProcessWithUID( obj ) );
37~~~
38Then
39~~~ {.cpp}
40 array.Add(obj);
41~~~
42is correct (obj comes from the process the array is pointed to
43while
44~~~ {.cpp}
45 TObject *nobj = new TObject;
46 array.Add(nobj);
47~~~
48is incorrect since 'nobj' was created in a different process than the
49one the array is pointed to. In this case you will see error message:
50~~~ {.cpp}
51 Error in <TRefArray::AddAtAndExpand>: The object at 0x... is not
52 registered in the process the TRefArray point to
53 (pid = ProcessID../....)
54~~~
55When a TRefArray is Streamed, only the pointer unique id is written,
56not the referenced object. TRefArray may be assigned to different
57branches of one Tree or several Trees.
58The branch containing the TRefArray can be read before or after the
59array (eg TClonesArray, STL vector,..) of the referenced objects.
60
61See an example in $ROOTSYS/test/Event.h
62
63### RESTRICTIONS when using TRefArray
64
65 - Elements in a TRefArray cannot point to a TFile or TDirectory.
66 - All elements of a TRefArray must be set in the same process,
67 In particular, one cannot modify some elements of the array in
68 a different process.
69
70Use an array of TRef when one of the above restrictions is met.
71
72The number of TRef handled by a single process id is limited to
7316777215 (see TRef for more detail). When the TProcessID is full
74(has seen 16777215 objects), we switch to new one TProcessID
75maximum 65535 including the TProcessIDs read from file).
76However TRefArray can not switch to new TProcessID if they already
77contain objects.
78
79When the TProcessID has been switched due to overflow and an new
80object is added to an existing, empty TRefArray, you will see:
81
82~~~ {.cpp}
83Warning in <TRefArray::AddAtAndExpand>: The ProcessID for the 0x5f83819e8 has been switched to ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef:4
84~~~
85If the TRefArray was not empty, you will see:
86
87~~~ {.cpp}
88Error in <TRefArray::AddAtAndExpand>: The object at %p can not be registered in the process the TRefArray points to (pid = ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef) because the ProcessID has too many objects and the TRefArray already contains other objects.
89~~~
90When running out of TProcessIds, you will see:
91
92~~~ {.cpp}
93Warning in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.
94Fatal in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.
95~~~
96*/
97
98#include "TRefArray.h"
99#include "TRefTable.h"
100#include "TBuffer.h"
101#include "TError.h"
102#include "TBits.h"
103
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
515void TRefArray::Streamer(TBuffer &R__b)
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}
#define a(i)
Definition RSha256.hxx:99
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
unsigned int UInt_t
Definition RtypesCore.h:46
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:364
const Bool_t kIterForward
Definition TCollection.h:42
Int_t gDebug
Definition TROOT.cxx:592
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
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
TString fName
Iterator abstract base class.
Definition TIterator.h:30
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:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:447
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:949
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition TObject.h:66
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:65
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:937
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced,...
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Iterator of object array.
Definition TRefArray.h:116
TObject * operator*() const
Return current object or nullptr.
Bool_t fDirection
Definition TRefArray.h:122
const TRefArray * fArray
Definition TRefArray.h:119
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Int_t fCurCursor
Definition TRefArray.h:120
void Reset()
Reset array iterator.
An array of references to TObjects.
Definition TRefArray.h:33
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Int_t fLowerBound
Definition TRefArray.h:40
TProcessID * fPID
Definition TRefArray.h:38
virtual void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
virtual void Clear(Option_t *option="")
Remove all objects from the array.
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
TObject * First() const
Return the object in the first slot.
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
virtual TObject * Remove(TObject *obj)
Remove object from array.
UInt_t GetUID(Int_t at) const
Return UID of element at.
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
TRefArray(TProcessID *pid=0)
default constructor
Int_t IndexOf(const TObject *obj) const
UInt_t * fUIDs
Definition TRefArray.h:39
Bool_t BoundsOk(const char *where, Int_t at) const
Definition TRefArray.h:157
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
Int_t GetLast() const
Return index of last object in array.
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
friend class TRefArrayIter
Definition TRefArray.h:35
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Int_t GetAbsLast() const
Return absolute index to last object in array.
Int_t GetEntries() const
Return the number of objects in array (i.e.
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
virtual void Delete(Option_t *option="")
Remove all objects from the array and free the internal memory.
TObject * At(Int_t idx) const
Definition TRefArray.h:178
Int_t fLast
Definition TRefArray.h:41
TRefArray & operator=(const TRefArray &a)
Assignment operator.
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
virtual void Compress()
Remove empty slots from array.
Int_t LowerBound() const
Definition TRefArray.h:91
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer obj.
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.
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
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:2336
Short_t Max(Short_t a, Short_t b)
Definition TMathBase.h:208