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 = 0;
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 = 0;
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 = 0;
150 Init(s, lowerBound);
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Create a copy of TRefArray a.
155
157{
158 fPID = a.fPID;
159 fUIDs = 0;
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 = 0;
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 %lx", idx, (Long_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;
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;
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 = 0;
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) memcpy(fUIDs,temp, newSize*sizeof(UInt_t));
484 else {
485 memcpy(fUIDs,temp,fSize*sizeof(UInt_t));
486 memset(&fUIDs[fSize],0,(newSize-fSize)*sizeof(UInt_t));
487 }
488 } else {
489 fUIDs = 0;
490 }
491 if (temp) delete [] temp;
492 fSize = newSize;
493}
494
495////////////////////////////////////////////////////////////////////////////////
496///the reference may be in the TRefTable
497
499{
501 if (table) {
502 table->SetUID(fUIDs[idx], fPID);
503 table->Notify();
504 return fPID->GetObjectWithID(fUIDs[idx]);
505 }
506 return 0;
507}
508
509////////////////////////////////////////////////////////////////////////////////
510/// Stream all objects in the array to or from the I/O buffer.
511
512void TRefArray::Streamer(TBuffer &R__b)
513{
514 UInt_t R__s, R__c;
515 Int_t nobjects;
516 UShort_t pidf;
517 if (R__b.IsReading()) {
518 R__b.ReadVersion(&R__s, &R__c);
519 TObject::Streamer(R__b);
520 fName.Streamer(R__b);
521 R__b >> nobjects;
522 R__b >> fLowerBound;
523 if (nobjects >= fSize) Expand(nobjects);
524 fLast = -1;
525 R__b >> pidf;
526 pidf += R__b.GetPidOffset();
527 fPID = R__b.ReadProcessID(pidf);
528 if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
529 for (Int_t i = 0; i < nobjects; i++) {
530 R__b >> fUIDs[i];
531 if (fUIDs[i] != 0) fLast = i;
532 if (gDebug > 1) {
533 printf(" %d",fUIDs[i]);
534 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
535 }
536 }
537 memset(&fUIDs[fLast+1], 0, (fSize - fLast - 1)*sizeof(fUIDs[0]));
538 Changed();
539 R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
540 } else {
541 R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
542 TObject::Streamer(R__b);
543 fName.Streamer(R__b);
544 nobjects = GetAbsLast()+1;
545 R__b << nobjects;
546 R__b << fLowerBound;
547 pidf = R__b.WriteProcessID(fPID);
548 R__b << pidf;
549 if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
550
551 for (Int_t i = 0; i < nobjects; i++) {
552 R__b << fUIDs[i];
553 if (gDebug > 1) {
554 printf(" %d",fUIDs[i]);
555 if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
556 }
557 }
558 R__b.SetByteCount(R__c, kTRUE);
559 }
560}
561
562////////////////////////////////////////////////////////////////////////////////
563/// Return the object in the first slot.
564
566{
567 return fPID->GetObjectWithID(fUIDs[0]);
568}
569
570////////////////////////////////////////////////////////////////////////////////
571/// Return the object in the last filled slot. Returns 0 if no entries.
572
574{
575 if (fLast == -1)
576 return 0;
577 else
579}
580
581////////////////////////////////////////////////////////////////////////////////
582/// Return the number of objects in array (i.e. number of non-empty slots).
583/// Attention: use this method ONLY if you want to know the number of
584/// non-empty slots. This function loops over the complete array and
585/// is therefore very slow when applied in a loop. Most of the time you
586/// better use GetLast()+1.
587
589{
590 Int_t cnt = 0;
591
592 for (Int_t i = 0; i < fSize; i++)
593 if (fUIDs[i]) cnt++;
594
595 return cnt;
596}
597
598////////////////////////////////////////////////////////////////////////////////
599/// Return absolute index to last object in array. Returns -1 in case
600/// array is empty.
601
603{
604 // For efficiency we need sometimes to update fLast so we have
605 // to cast const away. Ugly, but making GetAbsLast() not const breaks
606 // many other const functions.
607 if (fLast == -2) {
608 for (Int_t i = fSize-1; i >= 0; i--)
609 if (fUIDs[i]) {
610 ((TRefArray*)this)->fLast = i;
611 return fLast;
612 }
613 ((TRefArray*)this)->fLast = -1;
614 }
615 return fLast;
616}
617
618////////////////////////////////////////////////////////////////////////////////
619/// Return index of last object in array. Returns lowerBound-1 in case
620/// array is empty.
621
623{
624 return fLowerBound+GetAbsLast();
625}
626
627////////////////////////////////////////////////////////////////////////////////
628/// Return address of pointer obj.
629
631{
632 //Int_t index = IndexOf(obj);
633 //return &fCont[index];
634 return 0;
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Return UID of element at.
639
641{
642 int j = at-fLowerBound;
643 if (j >= 0 && j < fSize) {
644 if (!fPID) return 0;
645 return fUIDs[j];
646 }
647 BoundsOk("At", at);
648 return 0;
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// - obj != 0 Return index of object in array.
653/// Returns lowerBound-1 in case array doesn't contain the obj.
654///
655/// - obj == 0 Return the index of the first empty slot.
656/// Returns lowerBound-1 in case array doesn't contain any empty slot.
657
659{
660 Int_t i;
661 if (obj) {
663 return fLowerBound-1;
664 }
665 for (i = 0; i < fSize; i++)
666 if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
667 return i+fLowerBound;
668 } else { // Look for the first empty slot
669 for (i = 0; i < fSize; i++)
670 if (!fUIDs[i])
671 return i+fLowerBound;
672 }
673
674 return fLowerBound-1;
675}
676
677////////////////////////////////////////////////////////////////////////////////
678/// Initialize a TRefArray.
679
680void TRefArray::Init(Int_t s, Int_t lowerBound)
681{
682 if (fUIDs && fSize != s) {
683 delete [] fUIDs;
684 fUIDs = 0;
685 }
686
687 fSize = s;
688
689 if (fSize) {
690 fUIDs = new UInt_t[fSize];
691 for (Int_t i=0;i<s;i++) fUIDs[i] = 0;
692 } else {
693 fUIDs = 0;
694 }
695 fLowerBound = lowerBound;
696 fLast = -1;
697 Changed();
698}
699
700////////////////////////////////////////////////////////////////////////////////
701/// Returns an array iterator.
702
704{
705 return new TRefArrayIter(this, dir);
706}
707
708////////////////////////////////////////////////////////////////////////////////
709/// Generate an out-of-bounds error. Always returns false.
710
711Bool_t TRefArray::OutOfBoundsError(const char *where, Int_t i) const
712{
713 Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
714 return kFALSE;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Remove object at index idx.
719
721{
722 if (!BoundsOk("RemoveAt", idx)) return 0;
723
724 int i = idx-fLowerBound;
725
726 TObject *obj = 0;
727 if (fUIDs[i]) {
728 if (!TProcessID::IsValid(fPID)) return 0;
729 obj = fPID->GetObjectWithID(fUIDs[i]);
730 fUIDs[i] = 0;
731 // recalculate array size
732 if (i == fLast)
733 do {
734 fLast--;
735 } while (fLast >= 0 && fUIDs[fLast] == 0);
736 Changed();
737 }
738
739 return obj;
740}
741
742////////////////////////////////////////////////////////////////////////////////
743/// Remove object from array.
744
746{
747 if (!obj) return 0;
748
749 Int_t idx = IndexOf(obj) - fLowerBound;
750
751 if (idx == -1) return 0;
752
753 TObject *ob = fPID->GetObjectWithID(fUIDs[idx]);
754 fUIDs[idx] = 0;
755 // recalculate array size
756 if (idx == fLast)
757 do {
758 fLast--;
759 } while (fLast >= 0 && fUIDs[fLast] == 0);
760 Changed();
761 return ob;
762}
763
764////////////////////////////////////////////////////////////////////////////////
765/// Set index of last object in array, effectively truncating the
766/// array. Use carefully since whenever last position has to be
767/// recalculated, e.g. after a Remove() or Sort() it will be reset
768/// to the last non-empty slot. If last is -2 this will force the
769/// recalculation of the last used slot.
770
772{
773 if (last == -2)
774 fLast = -2;
775 else if (BoundsOk("SetLast", last))
776 fLast = last - fLowerBound;
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// If objects in array are sortable (i.e. IsSortable() returns true
781/// for all objects) then sort array.
782
784{
785 Error("Sort","Function not yet implemented");
786/*
787 if (GetAbsLast() == -1 || fSorted) return;
788 for (Int_t i = 0; i < fSize; i++)
789 if (fUIDs[i]) {
790 if (!fUIDs[i]->IsSortable()) {
791 Error("Sort", "objects in array are not sortable");
792 return;
793 }
794 }
795
796 QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
797
798 fLast = -2;
799 fSorted = kTRUE;
800*/
801}
802
803////////////////////////////////////////////////////////////////////////////////
804/// Find object using a binary search. Array must first have been sorted.
805/// Search can be limited by setting upto to desired index.
806
808{
809 Error("BinarySearch","Function not yet implemented");
810/*
811 Int_t base, position, last, result = 0;
812 TObject *op2;
813
814 if (!op) return -1;
815
816 if (!fSorted) {
817 Error("BinarySearch", "array must first be sorted");
818 return -1;
819 }
820
821 base = 0;
822 last = TMath::Min(fSize, upto-fLowerBound) - 1;
823
824 while (last >= base) {
825 //position = (base+last) / 2;
826 //op2 = fCont[position];
827 //if (op2 && (result = op->Compare(op2)) == 0)
828 // return position + fLowerBound;
829 //if (!op2 || result < 0)
830 // last = position-1;
831 //else
832 // base = position+1;
833 }
834*/
835 return -1;
836}
837
838/** \class TRefArrayIter
839Iterator of object array.
840*/
841
843
844////////////////////////////////////////////////////////////////////////////////
845/// Create array iterator. By default the iteration direction
846/// is kIterForward. To go backward use kIterBackward.
847
849{
850 fArray = arr;
851 fDirection = dir;
852 Reset();
853}
854
855////////////////////////////////////////////////////////////////////////////////
856/// Copy ctor.
857
859{
860 fArray = iter.fArray;
861 fDirection = iter.fDirection;
862 fCursor = iter.fCursor;
863 fCurCursor = iter.fCurCursor;
864}
865
866////////////////////////////////////////////////////////////////////////////////
867/// Overridden assignment operator.
868
870{
871 if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
872 const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
873 fArray = rhs1.fArray;
874 fDirection = rhs1.fDirection;
875 fCursor = rhs1.fCursor;
876 fCurCursor = rhs1.fCurCursor;
877 }
878 return *this;
879}
880
881////////////////////////////////////////////////////////////////////////////////
882/// Overloaded assignment operator.
883
885{
886 if (this != &rhs) {
887 fArray = rhs.fArray;
889 fCursor = rhs.fCursor;
891 }
892 return *this;
893}
894
895////////////////////////////////////////////////////////////////////////////////
896/// Return next object in array. Returns 0 when no more objects in array.
897
899{
900 if (fDirection == kIterForward) {
901 for ( ; fCursor < fArray->Capacity() && fArray->At(fCursor+fArray->LowerBound()) == 0;
902 fCursor++) { }
903
905 if (fCursor < fArray->Capacity()) {
906 fCursor++;
908 }
909 } else {
910 for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
911 fCursor--) { }
912
914 if (fCursor >= 0) {
915 fCursor--;
917 }
918 }
919 return 0;
920}
921
922////////////////////////////////////////////////////////////////////////////////
923/// Reset array iterator.
924
926{
928 fCursor = 0;
929 else
930 fCursor = fArray->Capacity() - 1;
931
933}
934
935////////////////////////////////////////////////////////////////////////////////
936/// This operator compares two TIterator objects.
937
939{
940 if (aIter.IsA() == TRefArrayIter::Class()) {
941 const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
942 return (fCurCursor != iter.fCurCursor);
943 }
944 return false; // for base class we don't implement a comparison
945}
946
947////////////////////////////////////////////////////////////////////////////////
948/// This operator compares two TRefArrayIter objects.
949
951{
952 return (fCurCursor != aIter.fCurCursor);
953}
954
955////////////////////////////////////////////////////////////////////////////////
956/// Return current object or nullptr.
957
959{
960 return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
961 fArray->At(fCurCursor) : nullptr);
962}
#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:92
long Long_t
Definition RtypesCore.h:54
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
const Bool_t kIterForward
Definition TCollection.h:40
Int_t gDebug
Definition TROOT.cxx:590
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:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:187
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:377
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:879
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:893
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition TObject.h:62
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:61
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:867
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
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:125
TObject * operator*() const
Return current object or nullptr.
Bool_t fDirection
Definition TRefArray.h:131
const TRefArray * fArray
Definition TRefArray.h:128
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
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:129
void Reset()
Reset array iterator.
An array of references to TObjects.
Definition TRefArray.h:39
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:46
TProcessID * fPID
Definition TRefArray.h:44
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:45
Bool_t BoundsOk(const char *where, Int_t at) const
Definition TRefArray.h:159
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
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:41
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:180
Int_t fLast
Definition TRefArray.h:47
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:97
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:2331
Short_t Max(Short_t a, Short_t b)
Definition TMathBase.h:212