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
14 An array of references to TObjects. The array expands automatically
15 when objects are added (shrinking can be done by hand using Expand() )
16 
17 The TRefArray can be filled with:
18 ~~~ {.cpp}
19  array.Add(obj)
20  array.AddAt(obj,i)
21  but not array[i] = obj !!!
22 ~~~
23 The array elements can be retrieved with:
24 ~~~ {.cpp}
25  TObject *obj = array.At(i);
26 ~~~
27 By default the TRefArray 'points' to the current process and can only
28 receive object that have been created in this process.
29 To point the TRefArray to a different process do:
30 ~~~ {.cpp}
31  TRefArray array( processId );
32 ~~~
33 For example, if 'obj' is an instance that was created in the different
34 process and you do:
35 ~~~ {.cpp}
36  TRefArray array( TProcessID::GetProcessWithUID( obj ) );
37 ~~~
38 Then
39 ~~~ {.cpp}
40  array.Add(obj);
41 ~~~
42 is correct (obj comes from the process the array is pointed to
43 while
44 ~~~ {.cpp}
45  TObject *nobj = new TObject;
46  array.Add(nobj);
47 ~~~
48 is incorrect since 'nobj' was created in a different process than the
49 one 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 ~~~
55 When a TRefArray is Streamed, only the pointer unique id is written,
56 not the referenced object. TRefArray may be assigned to different
57 branches of one Tree or several Trees.
58 The branch containing the TRefArray can be read before or after the
59 array (eg TClonesArray, STL vector,..) of the referenced objects.
60 
61 See 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 
70 Use an array of TRef when one of the above restrictions is met.
71 
72 The number of TRef handled by a single process id is limited to
73 16777215 (see TRef for more detail). When the TProcessID is full
74 (has seen 16777215 objects), we switch to new one TProcessID
75 maximum 65535 including the TProcessIDs read from file).
76 However TRefArray can not switch to new TProcessID if they already
77 contain objects.
78 
79 When the TProcessID has been switched due to overflow and an new
80 object is added to an existing, empty TRefArray, you will see:
81 
82 ~~~ {.cpp}
83 Warning in <TRefArray::AddAtAndExpand>: The ProcessID for the 0x5f83819e8 has been switched to ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef:4
84 ~~~
85 If the TRefArray was not empty, you will see:
86 
87 ~~~ {.cpp}
88 Error 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 ~~~
90 When running out of TProcessIds, you will see:
91 
92 ~~~ {.cpp}
93 Warning in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.
94 Fatal 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 {
111  fPID = pid ? pid : TProcessID::GetSessionProcessID();
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 
131  fPID = pid ? pid : TProcessID::GetSessionProcessID();
132  fUIDs = nullptr;
133  Init(s, 0);
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Create an object array. Using s one can set the array size
138 /// and lowerBound can be used to set the array lowerbound
139 /// index (default is 0).
140 
142 {
143  if (s < 0) {
144  Warning("TRefArray", "size (%d) < 0", s);
146  }
147 
148  fPID = pid ? pid : TProcessID::GetSessionProcessID();
149  fUIDs = nullptr;
150  Init(s, lowerBound);
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 /// Create a copy of TRefArray a.
155 
157 {
158  fPID = a.fPID;
159  fUIDs = nullptr;
160  Init(a.fSize, a.fLowerBound);
161 
162  for (Int_t i = 0; i < fSize; i++)
163  fUIDs[i] = a.fUIDs[i];
164 
165  fLast = a.fLast;
166  fName = a.fName;
167 }
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Assignment operator.
171 
173 {
174  if (this != &a) {
175  // Copy this by hand because the assignment operator
176  // of TCollection is private
177  fName = a.fName;
178  fSize = a.fSize;
179  fSorted = a.fSorted;
180 
181  fPID = a.fPID;
182  Init(a.fSize, a.fLowerBound);
183 
184  for (Int_t i = 0; i < fSize; i++)
185  fUIDs[i] = a.fUIDs[i];
186 
187  fLast = a.fLast;
188  fName = a.fName;
189  }
190  return *this;
191 }
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 /// Usual destructor (The object pointed to by the array are never deleted).
195 
197 {
198  if (fUIDs) delete [] fUIDs;
199  fPID = 0;
200  fUIDs = nullptr;
201  fSize = 0;
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Private/static function, check for validity of pid.
206 
207 Bool_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)) {
234  valid = (fPID == TProcessID::GetSessionProcessID());
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 
293 void 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 
317 void TRefArray::AddAfter(const TObject *after, TObject *obj)
318 {
319  if (!after)
320  AddLast(obj);
321  else {
322  Int_t idx = IndexOf(after) - fLowerBound;
323  if (idx == -1) {
324  Error("AddAfter", "after not found, object not added");
325  return;
326  }
327  AddAtAndExpand(obj, idx+fLowerBound+1);
328  }
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Add object at position idx. If idx is larger than the current size
333 /// of the array, expand the array (double its size).
334 
336 {
337  if (!obj) return;
338  if (idx < fLowerBound) {
339  Error("AddAt", "out of bounds at %d in %zx", idx, (size_t)this);
340  return;
341  }
342  if (idx-fLowerBound >= fSize)
344 
345  // Check if the object can belong here
346  Int_t uid;
347  if (GetObjectUID(uid, obj, "AddAtAndExpand")) {
348  fUIDs[idx-fLowerBound] = uid; // NOLINT
350  Changed();
351  }
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Add object at position ids. Give an error when idx is out of bounds
356 /// (i.e. the array is not expanded).
357 
359 {
360  if (!obj) return;
361  if (!BoundsOk("AddAt", idx)) return;
362 
363  // Check if the object can belong here
364  Int_t uid;
365  if (GetObjectUID(uid, obj, "AddAt")) {
366  fUIDs[idx-fLowerBound] = uid;
368  Changed();
369  }
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Return the position of the new object.
374 /// Find the first empty cell or AddLast if there is no empty cell
375 
377 {
378  if (!obj) return 0;
379  if (Last()) { // <---------- This is to take in account "empty" TRefArray's
380  Int_t i;
381  for (i = 0; i < fSize; i++)
382  if (!fUIDs[i]) { // Add object at position i
383  // Check if the object can belong here
384  Int_t uid;
385  if (GetObjectUID(uid, obj, "AddAtFree")) {
386  fUIDs[i] = uid; // NOLINT
387  fLast = TMath::Max(i, GetAbsLast());
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 
400 TObject *TRefArray::After(const TObject *obj) const
401 {
402  if (!obj || !fPID) return 0;
403 
404  Int_t idx = IndexOf(obj) - fLowerBound;
405  if (idx == -1 || idx == fSize-1) return 0;
406 
407  return fPID->GetObjectWithID(fUIDs[idx+1]);
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// Return the object before obj. Returns 0 if obj is first object.
412 
414 {
415  if (!obj || !fPID) return 0;
416 
417  Int_t idx = IndexOf(obj) - fLowerBound;
418  if (idx == -1 || idx == 0) return 0;
419 
420  return fPID->GetObjectWithID(fUIDs[idx-1]);
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Remove all objects from the array.
425 
427 {
428  fLast = - 1;
429 
430  for (Int_t j=0 ; j < fSize; j++) fUIDs[j] = 0;
431 
432  Changed();
433 }
434 
435 ////////////////////////////////////////////////////////////////////////////////
436 /// Remove empty slots from array.
437 
439 {
440  Int_t j = 0;
441 
442  for (Int_t i = 0; i < fSize; i++) {
443  if (fUIDs[i]) {
444  fUIDs[j] = fUIDs[i];
445  j++;
446  }
447  }
448 
449  fLast = j - 1;
450 
451  for ( ; j < fSize; j++) fUIDs[j] = 0;
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Remove all objects from the array and free the internal memory.
456 
458 {
459  fLast = -1;
460 
461  fSize = 0;
462  if (fUIDs) {
463  delete [] fUIDs;
464  fUIDs = nullptr;
465  }
466 
467  Changed();
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 /// Expand or shrink the array to newSize elements.
472 
474 {
475  if (newSize < 0) {
476  Error ("Expand", "newSize must be positive (%d)", newSize);
477  return;
478  }
479  if (newSize == fSize) return;
480  UInt_t *temp = fUIDs;
481  if (newSize != 0) {
482  fUIDs = new UInt_t[newSize];
483  if (newSize < fSize) {
484  memcpy(fUIDs, temp, newSize*sizeof(UInt_t));
485  } else if (temp) {
486  memcpy(fUIDs, temp, fSize*sizeof(UInt_t));
487  memset(&fUIDs[fSize], 0, (newSize-fSize)*sizeof(UInt_t));
488  } else {
489  memset(fUIDs, 0, newSize*sizeof(UInt_t));
490  }
491  } else {
492  fUIDs = nullptr;
493  }
494  if (temp) delete [] temp;
495  fSize = newSize;
496 }
497 
498 ////////////////////////////////////////////////////////////////////////////////
499 ///the reference may be in the TRefTable
500 
502 {
504  if (table) {
505  table->SetUID(fUIDs[idx], fPID);
506  table->Notify();
507  return fPID->GetObjectWithID(fUIDs[idx]);
508  }
509  return 0;
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 /// Stream all objects in the array to or from the I/O buffer.
514 
515 void TRefArray::Streamer(TBuffer &R__b)
516 {
517  UInt_t R__s, R__c;
518  Int_t nobjects;
519  UShort_t pidf;
520  if (R__b.IsReading()) {
521  R__b.ReadVersion(&R__s, &R__c);
522  TObject::Streamer(R__b);
523  fName.Streamer(R__b);
524  R__b >> nobjects;
525  R__b >> fLowerBound;
526  if (nobjects >= fSize) Expand(nobjects);
527  fLast = -1;
528  R__b >> pidf;
529  pidf += R__b.GetPidOffset();
530  fPID = R__b.ReadProcessID(pidf);
531  if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%zx, nobjects=%d\n",pidf,(size_t)fPID,nobjects);
532  for (Int_t i = 0; i < nobjects; i++) {
533  R__b >> fUIDs[i];
534  if (fUIDs[i] != 0) fLast = i;
535  if (gDebug > 1) {
536  printf(" %d",fUIDs[i]);
537  if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
538  }
539  }
540  memset(&fUIDs[fLast+1], 0, (fSize - fLast - 1)*sizeof(fUIDs[0]));
541  Changed();
542  R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
543  } else {
544  R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
545  TObject::Streamer(R__b);
546  fName.Streamer(R__b);
547  nobjects = GetAbsLast()+1;
548  R__b << nobjects;
549  R__b << fLowerBound;
550  pidf = R__b.WriteProcessID(fPID);
551  R__b << pidf;
552  if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%zx, nobjects=%d\n",pidf,(size_t)fPID,nobjects);
553 
554  for (Int_t i = 0; i < nobjects; i++) {
555  R__b << fUIDs[i];
556  if (gDebug > 1) {
557  printf(" %d",fUIDs[i]);
558  if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
559  }
560  }
561  R__b.SetByteCount(R__c, kTRUE);
562  }
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Return the object in the first slot.
567 
569 {
570  return fPID->GetObjectWithID(fUIDs[0]);
571 }
572 
573 ////////////////////////////////////////////////////////////////////////////////
574 /// Return the object in the last filled slot. Returns 0 if no entries.
575 
577 {
578  if (fLast == -1)
579  return 0;
580  else
581  return fPID->GetObjectWithID(fUIDs[GetAbsLast()]);
582 }
583 
584 ////////////////////////////////////////////////////////////////////////////////
585 /// Return the number of objects in array (i.e. number of non-empty slots).
586 /// Attention: use this method ONLY if you want to know the number of
587 /// non-empty slots. This function loops over the complete array and
588 /// is therefore very slow when applied in a loop. Most of the time you
589 /// better use GetLast()+1.
590 
592 {
593  Int_t cnt = 0;
594 
595  for (Int_t i = 0; i < fSize; i++)
596  if (fUIDs[i]) cnt++;
597 
598  return cnt;
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////
602 /// Return absolute index to last object in array. Returns -1 in case
603 /// array is empty.
604 
606 {
607  // For efficiency we need sometimes to update fLast so we have
608  // to cast const away. Ugly, but making GetAbsLast() not const breaks
609  // many other const functions.
610  if (fLast == -2) {
611  for (Int_t i = fSize-1; i >= 0; i--)
612  if (fUIDs[i]) {
613  ((TRefArray*)this)->fLast = i;
614  return fLast;
615  }
616  ((TRefArray*)this)->fLast = -1;
617  }
618  return fLast;
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Return index of last object in array. Returns lowerBound-1 in case
623 /// array is empty.
624 
626 {
627  return fLowerBound+GetAbsLast();
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Return address of pointer obj.
632 
634 {
635  //Int_t index = IndexOf(obj);
636  //return &fCont[index];
637  return 0;
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Return UID of element at.
642 
644 {
645  int j = at-fLowerBound;
646  if (j >= 0 && j < fSize) {
647  if (!fPID) return 0;
648  return fUIDs[j];
649  }
650  BoundsOk("At", at);
651  return 0;
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// - obj != 0 Return index of object in array.
656 /// Returns lowerBound-1 in case array doesn't contain the obj.
657 ///
658 /// - obj == 0 Return the index of the first empty slot.
659 /// Returns lowerBound-1 in case array doesn't contain any empty slot.
660 
662 {
663  Int_t i;
664  if (obj) {
665  if (!TProcessID::IsValid(fPID)) {
666  return fLowerBound-1;
667  }
668  for (i = 0; i < fSize; i++)
669  if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
670  return i+fLowerBound;
671  } else { // Look for the first empty slot
672  for (i = 0; i < fSize; i++)
673  if (!fUIDs[i])
674  return i+fLowerBound;
675  }
676 
677  return fLowerBound-1;
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 /// Initialize a TRefArray.
682 
683 void TRefArray::Init(Int_t s, Int_t lowerBound)
684 {
685  if (fUIDs && fSize != s) {
686  delete [] fUIDs;
687  fUIDs = nullptr;
688  }
689 
690  fSize = s;
691 
692  if (fSize) {
693  fUIDs = new UInt_t[fSize];
694  for (Int_t i=0;i<s;i++) fUIDs[i] = 0;
695  } else {
696  fUIDs = nullptr;
697  }
698  fLowerBound = lowerBound;
699  fLast = -1;
700  Changed();
701 }
702 
703 ////////////////////////////////////////////////////////////////////////////////
704 /// Returns an array iterator.
705 
707 {
708  return new TRefArrayIter(this, dir);
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 /// Generate an out-of-bounds error. Always returns false.
713 
714 Bool_t TRefArray::OutOfBoundsError(const char *where, Int_t i) const
715 {
716  Error(where, "index %d out of bounds (size: %d, this: 0x%zx)", i, fSize, (size_t)this);
717  return kFALSE;
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Remove object at index idx.
722 
724 {
725  if (!BoundsOk("RemoveAt", idx)) return 0;
726 
727  int i = idx-fLowerBound;
728 
729  TObject *obj = 0;
730  if (fUIDs[i]) {
731  if (!TProcessID::IsValid(fPID)) return 0;
732  obj = fPID->GetObjectWithID(fUIDs[i]);
733  fUIDs[i] = 0;
734  // recalculate array size
735  if (i == fLast)
736  do {
737  fLast--;
738  } while (fLast >= 0 && fUIDs[fLast] == 0);
739  Changed();
740  }
741 
742  return obj;
743 }
744 
745 ////////////////////////////////////////////////////////////////////////////////
746 /// Remove object from array.
747 
749 {
750  if (!obj) return 0;
751 
752  Int_t idx = IndexOf(obj) - fLowerBound;
753 
754  if (idx == -1) return 0;
755 
756  TObject *ob = fPID->GetObjectWithID(fUIDs[idx]);
757  fUIDs[idx] = 0;
758  // recalculate array size
759  if (idx == fLast)
760  do {
761  fLast--;
762  } while (fLast >= 0 && fUIDs[fLast] == 0);
763  Changed();
764  return ob;
765 }
766 
767 ////////////////////////////////////////////////////////////////////////////////
768 /// Set index of last object in array, effectively truncating the
769 /// array. Use carefully since whenever last position has to be
770 /// recalculated, e.g. after a Remove() or Sort() it will be reset
771 /// to the last non-empty slot. If last is -2 this will force the
772 /// recalculation of the last used slot.
773 
775 {
776  if (last == -2)
777  fLast = -2;
778  else if (BoundsOk("SetLast", last))
779  fLast = last - fLowerBound;
780 }
781 
782 ////////////////////////////////////////////////////////////////////////////////
783 /// If objects in array are sortable (i.e. IsSortable() returns true
784 /// for all objects) then sort array.
785 
787 {
788  Error("Sort","Function not yet implemented");
789 /*
790  if (GetAbsLast() == -1 || fSorted) return;
791  for (Int_t i = 0; i < fSize; i++)
792  if (fUIDs[i]) {
793  if (!fUIDs[i]->IsSortable()) {
794  Error("Sort", "objects in array are not sortable");
795  return;
796  }
797  }
798 
799  QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
800 
801  fLast = -2;
802  fSorted = kTRUE;
803 */
804 }
805 
806 ////////////////////////////////////////////////////////////////////////////////
807 /// Find object using a binary search. Array must first have been sorted.
808 /// Search can be limited by setting upto to desired index.
809 
811 {
812  Error("BinarySearch","Function not yet implemented");
813 /*
814  Int_t base, position, last, result = 0;
815  TObject *op2;
816 
817  if (!op) return -1;
818 
819  if (!fSorted) {
820  Error("BinarySearch", "array must first be sorted");
821  return -1;
822  }
823 
824  base = 0;
825  last = TMath::Min(fSize, upto-fLowerBound) - 1;
826 
827  while (last >= base) {
828  //position = (base+last) / 2;
829  //op2 = fCont[position];
830  //if (op2 && (result = op->Compare(op2)) == 0)
831  // return position + fLowerBound;
832  //if (!op2 || result < 0)
833  // last = position-1;
834  //else
835  // base = position+1;
836  }
837 */
838  return -1;
839 }
840 
841 /** \class TRefArrayIter
842 Iterator of object array.
843 */
844 
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// Create array iterator. By default the iteration direction
849 /// is kIterForward. To go backward use kIterBackward.
850 
852 {
853  fArray = arr;
854  fDirection = dir;
855  Reset();
856 }
857 
858 ////////////////////////////////////////////////////////////////////////////////
859 /// Copy ctor.
860 
862 {
863  fArray = iter.fArray;
864  fDirection = iter.fDirection;
865  fCursor = iter.fCursor;
866  fCurCursor = iter.fCurCursor;
867 }
868 
869 ////////////////////////////////////////////////////////////////////////////////
870 /// Overridden assignment operator.
871 
873 {
874  if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
875  const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
876  fArray = rhs1.fArray;
877  fDirection = rhs1.fDirection;
878  fCursor = rhs1.fCursor;
879  fCurCursor = rhs1.fCurCursor;
880  }
881  return *this;
882 }
883 
884 ////////////////////////////////////////////////////////////////////////////////
885 /// Overloaded assignment operator.
886 
888 {
889  if (this != &rhs) {
890  fArray = rhs.fArray;
891  fDirection = rhs.fDirection;
892  fCursor = rhs.fCursor;
893  fCurCursor = rhs.fCurCursor;
894  }
895  return *this;
896 }
897 
898 ////////////////////////////////////////////////////////////////////////////////
899 /// Return next object in array. Returns 0 when no more objects in array.
900 
902 {
903  if (fDirection == kIterForward) {
904  for ( ; fCursor < fArray->Capacity() && fArray->At(fCursor+fArray->LowerBound()) == 0;
905  fCursor++) { }
906 
908  if (fCursor < fArray->Capacity()) {
909  fCursor++;
910  return fArray->At(fCurCursor+fArray->LowerBound());
911  }
912  } else {
913  for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
914  fCursor--) { }
915 
917  if (fCursor >= 0) {
918  fCursor--;
919  return fArray->At(fCurCursor+fArray->LowerBound());
920  }
921  }
922  return 0;
923 }
924 
925 ////////////////////////////////////////////////////////////////////////////////
926 /// Reset array iterator.
927 
929 {
930  if (fDirection == kIterForward)
931  fCursor = 0;
932  else
933  fCursor = fArray->Capacity() - 1;
934 
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// This operator compares two TIterator objects.
940 
942 {
943  if (aIter.IsA() == TRefArrayIter::Class()) {
944  const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
945  return (fCurCursor != iter.fCurCursor);
946  }
947  return false; // for base class we don't implement a comparison
948 }
949 
950 ////////////////////////////////////////////////////////////////////////////////
951 /// This operator compares two TRefArrayIter objects.
952 
954 {
955  return (fCurCursor != aIter.fCurCursor);
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////////
959 /// Return current object or nullptr.
960 
962 {
963  return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
964  fArray->At(fCurCursor) : nullptr);
965 }
TRefArrayIter::fCursor
Int_t fCursor
Definition: TRefArray.h:130
TProcessID::GetObjectCount
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:324
TRefArray.h
TRefArray::Remove
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TRefArray.cxx:748
TRefArray::fLast
Int_t fLast
Definition: TRefArray.h:47
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
TRefArray::BoundsOk
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TRefArray.h:159
Option_t
const char Option_t
Definition: RtypesCore.h:66
TRefArray::AddFirst
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
Definition: TRefArray.cxx:266
TMath::Max
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
TBuffer::GetPidOffset
virtual UShort_t GetPidOffset() const =0
TBuffer::WriteVersion
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TBuffer::SetByteCount
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:40
TRefArray::GetEntries
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TRefArray.cxx:591
TProcessID::IsValid
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:360
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TRefArrayIter
Iterator of object array.
Definition: TRefArray.h:125
TRefArray::GetObjectRef
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer obj.
Definition: TRefArray.cxx:633
TObject::Info
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:867
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
TRefArray::TRefArrayIter
friend class TRefArrayIter
Definition: TRefArray.h:41
TProcessID
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:74
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
Int_t
int Int_t
Definition: RtypesCore.h:45
TRefArray::Expand
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TRefArray.cxx:473
TObject::GetUniqueID
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:377
TRefArray::fLowerBound
Int_t fLowerBound
Definition: TRefArray.h:46
TRefArray::Delete
virtual void Delete(Option_t *option="")
Remove all objects from the array and free the internal memory.
Definition: TRefArray.cxx:457
TRefArray::Clear
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TRefArray.cxx:426
TCollection::fName
TString fName
Definition: TCollection.h:147
TRefArray
An array of references to TObjects.
Definition: TRefArray.h:39
TBuffer
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
TRefArray::GetFromTable
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
Definition: TRefArray.cxx:501
TString::Format
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:2333
TRefArrayIter::Reset
void Reset()
Reset array iterator.
Definition: TRefArray.cxx:928
TProcessID::AssignID
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
TRefArrayIter::fCurCursor
Int_t fCurCursor
Definition: TRefArray.h:129
TRefArrayIter::TRefArrayIter
TRefArrayIter()
Definition: TRefArray.h:133
TBuffer::CheckByteCount
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
TRefArray::GetAbsLast
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TRefArray.cxx:605
bool
TIterator
Iterator abstract base class.
Definition: TIterator.h:30
TRefArray::GetLast
Int_t GetLast() const
Return index of last object in array.
Definition: TRefArray.cxx:625
kIterForward
const Bool_t kIterForward
Definition: TCollection.h:40
TRefArray::AddAt
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TRefArray.cxx:358
TSeqCollection::fSorted
Bool_t fSorted
Definition: TSeqCollection.h:31
TRefArray::AddAtAndExpand
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TRefArray.cxx:335
TRefTable.h
TRefArrayIter::Next
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
Definition: TRefArray.cxx:901
TSeqCollection::Changed
virtual void Changed()
Definition: TSeqCollection.h:34
TBuffer.h
TRefArrayIter::fDirection
Bool_t fDirection
Definition: TRefArray.h:131
TRefArray::IndexOf
Int_t IndexOf(const TObject *obj) const
Definition: TRefArray.cxx:661
TRefArray::fUIDs
UInt_t * fUIDs
Definition: TRefArray.h:45
a
auto * a
Definition: textangle.C:12
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
TRefArrayIter::operator!=
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TRefArray.cxx:941
TRefArray::GetObjectUID
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
Definition: TRefArray.cxx:207
TProcessID::GetProcessWithUID
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
TCollection::fSize
Int_t fSize
Definition: TCollection.h:148
TRefTable::SetUID
virtual void SetUID(UInt_t uid, TProcessID *context=0)
Definition: TRefTable.h:87
TRefTable::GetRefTable
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
TCollection::GrowBy
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
Definition: TCollection.cxx:360
TRefTable::Notify
virtual Bool_t Notify()
This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer when reading a reference.
Definition: TRefTable.cxx:299
TRefArrayIter::operator=
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TRefArray.cxx:872
TRefArray::BinarySearch
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
Definition: TRefArray.cxx:810
gDebug
Int_t gDebug
Definition: TROOT.cxx:590
TCollection::kInitCapacity
@ kInitCapacity
Definition: TCollection.h:157
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
TRefArray::MakeIterator
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TRefArray.cxx:706
TRefArray::~TRefArray
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
Definition: TRefArray.cxx:196
TProcessID::GetSessionProcessID
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:305
TObject::Warning
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:879
TBuffer::ReadVersion
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
unsigned int
TRefTable
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
TRefArray::AddBefore
virtual void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
Definition: TRefArray.cxx:293
TSeqCollection
Sequenceable collection abstract base class.
Definition: TSeqCollection.h:28
TBuffer::IsReading
Bool_t IsReading() const
Definition: TBuffer.h:86
TRefArray::OutOfBoundsError
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TRefArray.cxx:714
TRefArray::Init
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
Definition: TRefArray.cxx:683
TObject::kIsReferenced
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
TRefArray::LowerBound
Int_t LowerBound() const
Definition: TRefArray.h:97
TBits.h
TBuffer::WriteProcessID
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:353
TRefArrayIter::fArray
const TRefArray * fArray
Definition: TRefArray.h:128
TRefArray::RemoveAt
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TRefArray.cxx:723
TRefArray::GetUID
UInt_t GetUID(Int_t at) const
Return UID of element at.
Definition: TRefArray.cxx:643
TRefArray::Before
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
Definition: TRefArray.cxx:413
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TCollection::Capacity
Int_t Capacity() const
Definition: TCollection.h:165
TRefArrayIter::operator*
TObject * operator*() const
Return current object or nullptr.
Definition: TRefArray.cxx:961
TBuffer::ReadProcessID
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:344
TRefArray::At
TObject * At(Int_t idx) const
Definition: TRefArray.h:180
TRefArray::TRefArray
TRefArray(TProcessID *pid=0)
default constructor
Definition: TRefArray.cxx:109
TRefArray::Compress
virtual void Compress()
Remove empty slots from array.
Definition: TRefArray.cxx:438
TRefArray::operator=
TRefArray & operator=(const TRefArray &a)
Assignment operator.
Definition: TRefArray.cxx:172
TRefArray::After
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
Definition: TRefArray.cxx:400
xmlio::cnt
const char * cnt
Definition: TXMLSetup.cxx:75
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TRefArray::Last
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TRefArray.cxx:576
TRefArray::AddAtFree
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
Definition: TRefArray.cxx:376
TProcessID::GetObjectWithID
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:332
Class
void Class()
Definition: Class.C:29
TObject::kHasUUID
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition: TObject.h:62
TRefArray::First
TObject * First() const
Return the object in the first slot.
Definition: TRefArray.cxx:568
TRefArray::SetLast
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TRefArray.cxx:774
TRefArray::fPID
TProcessID * fPID
Definition: TRefArray.h:44
TRefArray::AddLast
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TRefArray.cxx:282
TRefArray::Sort
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Definition: TRefArray.cxx:786
TRefArray::AddAfter
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
Definition: TRefArray.cxx:317
int
TError.h