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