ROOT  6.06/09
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 An array of references to TObjects. The array expands automatically
14 when objects are added (shrinking can be done by hand using Expand() )
15 
16 The TRefArray can be filled with:
17 ~~~ {.cpp}
18  array.Add(obj)
19  array.AddAt(obj,i)
20  but not array[i] = obj !!!
21 ~~~
22 The array elements can be retrieved with:
23 ~~~ {.cpp}
24  TObject *obj = array.At(i);
25 ~~~
26 By default the TRefArray 'points' to the current process and can only
27 receive object that have been created in this process.
28 To point the TRefArray to a different process do:
29 ~~~ {.cpp}
30  TRefArray array( processId );
31 ~~~
32 For example, if 'obj' is an instance that was created in the different
33 process and you do:
34 ~~~ {.cpp}
35  TRefArray array( TProcessID::GetProcessWithUID( obj ) );
36 ~~~
37 Then
38 ~~~ {.cpp}
39  array.Add(obj);
40 ~~~
41 is correct (obj comes from the process the array is pointed to
42 while
43 ~~~ {.cpp}
44  TObject *nobj = new TObject;
45  array.Add(nobj);
46 ~~~
47 is incorrect since 'nobj' was created in a different process than the
48 one the array is pointed to. In this case you will see error message:
49 ~~~ {.cpp}
50  Error in <TRefArray::AddAtAndExpand>: The object at 0x... is not
51  registered in the process the TRefArray point to
52  (pid = ProcessID../....)
53 ~~~
54 When a TRefArray is Streamed, only the pointer unique id is written,
55 not the referenced object. TRefArray may be assigned to different
56 branches of one Tree or several Trees.
57 The branch containing the TRefArray can be read before or after the
58 array (eg TClonesArray, STL vector,..) of the referenced objects.
59 
60 See an example in $ROOTSYS/test/Event.h
61 
62 ### RESTRICTIONS when using TRefArray
63 
64  - Elements in a TRefArray cannot point to a TFile or TDirectory.
65  - All elements of a TRefArray must be set in the same process,
66  In particular, one cannot modify some elements of the array in
67  a different process.
68 
69 Use an array of TRef when one of the above restrictions is met.
70 
71 The number of TRef handled by a single process id is limited to
72 16777215 (see TRef for more detail). When the TProcessID is full
73 (has seen 16777215 objects), we switch to new one TProcessID
74 maximum 65535 including the TProcessIDs read from file).
75 However TRefArray can not switch to new TProcessID if they already
76 contain objects.
77 
78 When the TProcessID has been switched due to overflow and an new
79 object is added to an existing, empty TRefArray, you will see:
80 
81 ~~~ {.cpp}
82 Warning in <TRefArray::AddAtAndExpand>: The ProcessID for the 0x5f83819e8 has been switched to ProcessID4/6c89f37e-8259-11e2-9717-166ee183beef:4
83 ~~~
84 If the TRefArray was not empty, you will see:
85 
86 ~~~ {.cpp}
87 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.
88 ~~~
89 When running out of TProcessIds, you will see:
90 
91 ~~~ {.cpp}
92 Warning in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.
93 Fatal in <TProcessID::AddProcessID>: Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.
94 ~~~
95 */
96 
97 #include "TRefArray.h"
98 #include "TRefTable.h"
99 #include "TError.h"
100 #include "TBits.h"
101 #include "TSystem.h"
102 #include "TROOT.h"
103 
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// default constructor
108 
110 {
111  fPID = pid ? pid : TProcessID::GetSessionProcessID();
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 
131  fPID = pid ? pid : TProcessID::GetSessionProcessID();
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 
148  fPID = pid ? pid : TProcessID::GetSessionProcessID();
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 
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 {
284  AddAtAndExpand(obj, GetAbsLast()+1+fLowerBound);
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 
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 
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)
343  Expand(TMath::Max(idx-fLowerBound+1, GrowBy(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;
349  fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
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;;
367  fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
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;
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 
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 
512 void 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
578  return fPID->GetObjectWithID(fUIDs[GetAbsLast()]);
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) {
662  if (!TProcessID::IsValid(fPID)) {
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 
680 void 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 
711 Bool_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
839 Iterator 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;
888  fDirection = rhs.fDirection;
889  fCursor = rhs.fCursor;
890  fCurCursor = rhs.fCurCursor;
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++;
907  return fArray->At(fCurCursor+fArray->LowerBound());
908  }
909  } else {
910  for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
911  fCursor--) { }
912 
914  if (fCursor >= 0) {
915  fCursor--;
916  return fArray->At(fCurCursor+fArray->LowerBound());
917  }
918  }
919  return 0;
920 }
921 
922 ////////////////////////////////////////////////////////////////////////////////
923 /// Reset array iterator.
924 
926 {
927  if (fDirection == kIterForward)
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 }
virtual Int_t AddAtFree(TObject *obj)
Return the position of the new object.
Definition: TRefArray.cxx:376
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
void Init(Int_t s, Int_t lowerBound)
Initialize a TRefArray.
Definition: TRefArray.cxx:680
Int_t IndexOf(const TObject *obj) const
Definition: TRefArray.cxx:658
TObject * Before(const TObject *obj) const
Return the object before obj. Returns 0 if obj is first object.
Definition: TRefArray.cxx:413
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TRefArray.cxx:869
Bool_t IsReading() const
Definition: TBuffer.h:81
const TRefArray * fArray
Definition: TRefArray.h:132
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Definition: TRefArray.cxx:783
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TRefArray.h:163
Int_t Capacity() const
Definition: TCollection.h:80
const char Option_t
Definition: RtypesCore.h:62
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TRefArray.cxx:473
Int_t LowerBound() const
Definition: TRefArray.h:101
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TRefArray.cxx:711
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
TObject * ob
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
An array of references to TObjects.
Definition: TRefArray.h:43
TString fName
Definition: TCollection.h:62
virtual UShort_t GetPidOffset() const =0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TRefArray.cxx:771
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TRefArray.cxx:602
virtual Int_t BinarySearch(TObject *obj, Int_t upto=kMaxInt)
Find object using a binary search.
Definition: TRefArray.cxx:807
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TRefArray.cxx:282
Iterator abstract base class.
Definition: TIterator.h:32
TObject Int_t at
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TRefArray.cxx:588
virtual ~TRefArray()
Usual destructor (The object pointed to by the array are never deleted).
Definition: TRefArray.cxx:196
Int_t GetLast() const
Return index of last object in array.
Definition: TRefArray.cxx:622
Sequenceable collection abstract base class.
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:311
TObject * At(Int_t idx) const
Definition: TRefArray.h:184
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:2334
void Class()
Definition: Class.C:29
virtual void Changed()
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer obj.
Definition: TRefArray.cxx:630
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
virtual void AddFirst(TObject *obj)
Add object in the first slot of the array.
Definition: TRefArray.cxx:266
UInt_t * fUIDs
Definition: TRefArray.h:49
const Bool_t kIterForward
Definition: TCollection.h:43
Bool_t fDirection
Definition: TRefArray.h:135
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:34
Bool_t GetObjectUID(Int_t &uid, TObject *obj, const char *methodname)
Private/static function, check for validity of pid.
Definition: TRefArray.cxx:207
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Int_t fCurCursor
Definition: TRefArray.h:133
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:320
Iterator of object array.
Definition: TRefArray.h:126
TObject * First() const
Return the object in the first slot.
Definition: TRefArray.cxx:565
TObject * GetFromTable(Int_t idx) const
the reference may be in the TRefTable
Definition: TRefArray.cxx:498
Int_t fCursor
Definition: TRefArray.h:134
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TRefArray.cxx:573
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:252
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TRefArray.cxx:358
virtual void Compress()
Remove empty slots from array.
Definition: TRefArray.cxx:438
Int_t fLowerBound
Definition: TRefArray.h:50
TClass * IsA() const
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
Int_t fSize
Definition: TCollection.h:63
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
void Reset(Detail::TBranchProxy *x)
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TRefArray.cxx:703
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:287
long Long_t
Definition: RtypesCore.h:50
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TRefArray.cxx:335
virtual void Delete(Option_t *option="")
Remove all objects from the array and free the internal memory.
Definition: TRefArray.cxx:457
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TRefArray.cxx:426
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:285
TRefArray(TProcessID *pid=0)
virtual void AddAfter(const TObject *after, TObject *obj)
Add object in the slot after object after.
Definition: TRefArray.cxx:317
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:37
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
Definition: TRefArray.cxx:898
TObject * operator*() const
Return current object or nullptr.
Definition: TRefArray.cxx:958
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:260
friend class TRefArrayIter
Definition: TRefArray.h:45
UInt_t GetUID(Int_t at) const
Return UID of element at.
Definition: TRefArray.cxx:640
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:433
Mother of all ROOT objects.
Definition: TObject.h:58
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TRefArray.cxx:938
void Reset()
Reset array iterator.
Definition: TRefArray.cxx:925
TProcessID * fPID
Definition: TRefArray.h:48
ClassImp(TRefArray) TRefArray
default constructor
Definition: TRefArray.cxx:104
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced, its kIsReferenced bit is set and its fUniqueID set to the current number of referenced objects so far.
Definition: TProcessID.cxx:128
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:279
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TRefArray.cxx:720
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:315
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TRefArray.cxx:745
TObject * obj
Int_t fLast
Definition: TRefArray.h:51
virtual void SetUID(UInt_t uid, TProcessID *context=0)
Definition: TRefTable.h:89
const char * cnt
Definition: TXMLSetup.cxx:75
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual Bool_t Notify()
This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer when reading a reference...
Definition: TRefTable.cxx:297
TRefArray & operator=(const TRefArray &a)
Assignment operator.
Definition: TRefArray.cxx:172
TObject * After(const TObject *obj) const
Return the object after obj. Returns 0 if obj is last object.
Definition: TRefArray.cxx:400
virtual void AddBefore(const TObject *before, TObject *obj)
Add object in the slot before object before.
Definition: TRefArray.cxx:293
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904