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