TRefArray.cxx

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TRefArray.cxx 34226 2010-06-30 12:03:31Z brun $
00002 // Author: Rene Brun  02/10/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 ////////////////////////////////////////////////////////////////////////////
00013 //                                                                        //
00014 // TRefArray                                                              //
00015 //                                                                        //
00016 // An array of references to TObjects. The array expands automatically    //
00017 // when  objects are added (shrinking can be done by hand using Expand() )//
00018 //                                                                        //
00019 // The TRefArray can be filled with:                                      //
00020 //     array.Add(obj)                                                     //
00021 //     array.AddAt(obj,i)                                                 //
00022 //     but not array[i] = obj  !!!                                        //
00023 //                                                                        //
00024 // The array elements can be retrieved with:                              //
00025 //     TObject *obj = array.At(i);                                        //
00026 //                                                                        //
00027 // By default the TRefArray 'points' to the current process and can only  //
00028 // receive object that have been created in this process.                 //
00029 // To point the TRefArray to a different process do:                      //
00030 //     TRefArray array( processId );                                      //
00031 //                                                                        //
00032 // For example, if 'obj' is an instance that was created in the different //
00033 // process and you do:                                                    //
00034 //     TRefArray array( TProcessID::GetProcessWithUID( obj ) );           //
00035 // Then                                                                   //
00036 //     array.Add(obj);                                                    //
00037 // is correct (obj comes from the process the array is pointed to         //
00038 // while                                                                  //
00039 //     TObject *nobj = new TObject;                                       //
00040 //     array.Add(nobj);                                                   //
00041 // is incorrect since 'nobj' was created in a different process than the  //
00042 // one the array is pointed to. In this case you will see error message:  //
00043 //     Error in <TRefArray::AddAtAndExpand>: The object at 0x... is not   //
00044 //     registered in the process the TRefArray point to                   //
00045 //     (pid = ProcessID../....)                                           //
00046 //                                                                        //
00047 // When a TRefArray is Streamed, only the pointer unique id is written,   //
00048 // not the referenced object. TRefArray may be assigned to different      //
00049 // branches of one Tree or several Trees.                                 //
00050 // The branch containing the TRefArray can be read before or after the    //
00051 // array (eg TClonesArray, STL vector,..) of the referenced objects.      //
00052 //                                                                        //
00053 // See an example in $ROOTSYS/test/Event.h                                //
00054 //                                                                        //
00055 // RESTRICTIONS when using TRefArray                                      //
00056 // ---------------------------------                                      //
00057 //  - Elements in a TRefArray cannot point to a TFile or TDirectory.      //
00058 //  - All elements of a TRefArray must be set in the same process,        //
00059 //    In particular, one cannot modify some elements of the array in      //
00060 //    a different process.                                                //
00061 // Use an array of TRef when one of the above restrictions is met.        //
00062 //                                                                        //
00063 ////////////////////////////////////////////////////////////////////////////
00064 
00065 #include "TRefArray.h"
00066 #include "TRefTable.h"
00067 #include "TError.h"
00068 #include "TBits.h"
00069 #include "TSystem.h"
00070 #include "TROOT.h"
00071 
00072 ClassImp(TRefArray)
00073 
00074 //______________________________________________________________________________
00075 TRefArray::TRefArray(TProcessID *pid)
00076 {
00077    // default constructor
00078 
00079    fPID  = pid ? pid : TProcessID::GetSessionProcessID();
00080    fUIDs = 0;
00081    fSize = 0;
00082    fLast = -1;
00083    fLowerBound = 0;
00084    Changed();
00085 }
00086 
00087 //______________________________________________________________________________
00088 TRefArray::TRefArray(Int_t s, TProcessID *pid)
00089 {
00090    // Create an object array. Using s one can set the array size
00091    // and lowerBound can be used to set the array lowerbound
00092    // index (default is 0).
00093 
00094    if (s < 0) {
00095       Warning("TRefArray", "size (%d) < 0", s);
00096       s = TCollection::kInitCapacity;
00097    }
00098 
00099    fPID  = pid ? pid : TProcessID::GetSessionProcessID();
00100    fUIDs = 0;
00101    Init(s, 0);
00102 }
00103 
00104 //______________________________________________________________________________
00105 TRefArray::TRefArray(Int_t s, Int_t lowerBound, TProcessID *pid)
00106 {
00107    // Create an object array. Using s one can set the array size
00108    // and lowerBound can be used to set the array lowerbound
00109    // index (default is 0).
00110 
00111    if (s < 0) {
00112       Warning("TRefArray", "size (%d) < 0", s);
00113       s = TCollection::kInitCapacity;
00114    }
00115 
00116    fPID  = pid ? pid : TProcessID::GetSessionProcessID();
00117    fUIDs = 0;
00118    Init(s, lowerBound);
00119 }
00120 
00121 //______________________________________________________________________________
00122 TRefArray::TRefArray(const TRefArray &a) : TSeqCollection()
00123 {
00124    // Create a copy of TRefArray a.
00125 
00126    fPID  = a.fPID;
00127    fUIDs = 0;
00128    Init(a.fSize, a.fLowerBound);
00129 
00130    for (Int_t i = 0; i < fSize; i++)
00131       fUIDs[i] = a.fUIDs[i];
00132 
00133    fLast = a.fLast;
00134    fName = a.fName;
00135 }
00136 
00137 //______________________________________________________________________________
00138 TRefArray& TRefArray::operator=(const TRefArray &a)
00139 {
00140    // Assignment operator.
00141 
00142    if (this != &a) {
00143       // Copy this by hand because the assigment operator
00144       // of TCollection is private
00145       fName   = a.fName;
00146       fSize   = a.fSize;
00147       fSorted = a.fSorted;
00148 
00149       fPID = a.fPID;
00150       Init(a.fSize, a.fLowerBound);
00151 
00152       for (Int_t i = 0; i < fSize; i++)
00153          fUIDs[i] = a.fUIDs[i];
00154 
00155       fLast = a.fLast;
00156       fName = a.fName;
00157    }
00158    return *this;
00159 }
00160 
00161 //______________________________________________________________________________
00162 TRefArray::~TRefArray()
00163 {
00164    // Usual destructor (The object pointed to by the array are never deleted).
00165 
00166    if (fUIDs) delete [] fUIDs;
00167    fPID  = 0;
00168    fUIDs = 0;
00169    fSize = 0;
00170 }
00171 
00172 //______________________________________________________________________________
00173 static Bool_t R__GetUID(Int_t &uid, TObject *obj, TProcessID *pid, const char *methodname)
00174 {
00175    // Private/static function, check for validity of pid.
00176 
00177    // Check if the object can belong here.
00178    Bool_t valid = kTRUE;
00179    if (obj->TestBit(kHasUUID)) {
00180       valid = kFALSE;
00181    } else if (obj->TestBit(kIsReferenced)) {
00182       valid = (pid == TProcessID::GetProcessWithUID(obj));
00183       if (valid) {
00184          uid = obj->GetUniqueID();
00185       }
00186    } else {
00187       valid = (pid == TProcessID::GetSessionProcessID());
00188       if (valid) {
00189          uid = TProcessID::AssignID(obj);
00190       }
00191    }
00192 
00193    if (!valid) {
00194       TString name; name.Form("TRefArray::%s",methodname);
00195       ::Error(name,
00196               "The object at %p is not registered in the process the TRefArray point to (pid = %s/%s)",obj,pid->GetName(),pid->GetTitle());
00197    }
00198    return valid;
00199 }
00200 
00201 //______________________________________________________________________________
00202 void TRefArray::AddFirst(TObject *obj)
00203 {
00204    // Add object in the first slot of the array. This will overwrite the
00205    // first element that might have been there. To have insertion semantics
00206    // use either a TList or a TOrdCollection.
00207 
00208    if (!obj) return;
00209 
00210    // Check if the object can belong here
00211    Int_t uid;
00212    if (R__GetUID(uid, obj, fPID, "AddFirst")) {
00213       fUIDs[0] = uid;
00214       Changed();
00215    }
00216 }
00217 
00218 //______________________________________________________________________________
00219 void TRefArray::AddLast(TObject *obj)
00220 {
00221    // Add object in the next empty slot in the array. Expand the array
00222    // if necessary.
00223 
00224    AddAtAndExpand(obj, GetAbsLast()+1+fLowerBound);
00225 }
00226 
00227 //______________________________________________________________________________
00228 void TRefArray::AddBefore(const TObject *before, TObject *obj)
00229 {
00230    // Add object in the slot before object before. If before=0 add object
00231    // in the first slot. Note that this will overwrite any object that
00232    // might have already been in this slot. For insertion semantics use
00233    // either a TList or a TOrdCollection.
00234 
00235    if (!before)
00236       AddFirst(obj);
00237    else {
00238       Int_t idx = IndexOf(before) - fLowerBound;
00239       if (idx == -1) {
00240          Error("AddBefore", "before not found, object not added");
00241          return;
00242       }
00243       if (idx == 0) {
00244          Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
00245          return;
00246       }
00247       AddAt(obj, idx+fLowerBound-1);
00248    }
00249 }
00250 
00251 //______________________________________________________________________________
00252 void TRefArray::AddAfter(const TObject *after, TObject *obj)
00253 {
00254    // Add object in the slot after object after. If after=0 add object in
00255    // the last empty slot. Note that this will overwrite any object that
00256    // might have already been in this slot. For insertion semantics use
00257    // either a TList or a TOrdCollection.
00258 
00259    if (!after)
00260       AddLast(obj);
00261    else {
00262       Int_t idx = IndexOf(after) - fLowerBound;
00263       if (idx == -1) {
00264          Error("AddAfter", "after not found, object not added");
00265          return;
00266       }
00267       AddAtAndExpand(obj, idx+fLowerBound+1);
00268    }
00269 }
00270 
00271 //______________________________________________________________________________
00272 void TRefArray::AddAtAndExpand(TObject *obj, Int_t idx)
00273 {
00274    // Add object at position idx. If idx is larger than the current size
00275    // of the array, expand the array (double its size).
00276 
00277    if (!obj) return;
00278    if (idx < fLowerBound) {
00279       Error("AddAt", "out of bounds at %d in %lx", idx, (Long_t)this);
00280       return;
00281    }
00282    if (idx-fLowerBound >= fSize)
00283       Expand(TMath::Max(idx-fLowerBound+1, GrowBy(fSize)));
00284 
00285    // Check if the object can belong here
00286    Int_t uid;
00287    if (R__GetUID(uid, obj, fPID, "AddAtAndExpand")) {
00288       fUIDs[idx-fLowerBound] = uid;
00289       fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
00290       Changed();
00291    }
00292 }
00293 
00294 //______________________________________________________________________________
00295 void TRefArray::AddAt(TObject *obj, Int_t idx)
00296 {
00297    // Add object at position ids. Give an error when idx is out of bounds
00298    // (i.e. the array is not expanded).
00299 
00300    if (!obj) return;
00301    if (!BoundsOk("AddAt", idx)) return;
00302 
00303    // Check if the object can belong here
00304    Int_t uid;
00305    if (R__GetUID(uid, obj, fPID, "AddAt")) {
00306       fUIDs[idx-fLowerBound] = uid;;
00307       fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
00308       Changed();
00309    }
00310 }
00311 
00312 //______________________________________________________________________________
00313 Int_t  TRefArray::AddAtFree(TObject *obj)
00314 {
00315    // Return the position of the new object.
00316    // Find the first empty cell or AddLast if there is no empty cell
00317 
00318    if (!obj) return 0;
00319    if (Last()) {    // <---------- This is to take in account "empty" TRefArray's
00320       Int_t i;
00321       for (i = 0; i < fSize; i++)
00322          if (!fUIDs[i]) {         // Add object at position i
00323             // Check if the object can belong here
00324             Int_t uid;
00325             if (R__GetUID(uid, obj, fPID, "AddAtFree")) {
00326                fUIDs[i] = uid;
00327                fLast = TMath::Max(i, GetAbsLast());
00328                Changed();
00329                return i+fLowerBound;
00330             }
00331          }
00332    }
00333    AddLast(obj);
00334    return GetLast();
00335 }
00336 
00337 //______________________________________________________________________________
00338 TObject *TRefArray::After(const TObject *obj) const
00339 {
00340    // Return the object after obj. Returns 0 if obj is last object.
00341 
00342    if (!obj || !fPID) return 0;
00343 
00344    Int_t idx = IndexOf(obj) - fLowerBound;
00345    if (idx == -1 || idx == fSize-1) return 0;
00346 
00347    return fPID->GetObjectWithID(fUIDs[idx+1]);
00348 }
00349 
00350 //______________________________________________________________________________
00351 TObject *TRefArray::Before(const TObject *obj) const
00352 {
00353    // Return the object before obj. Returns 0 if obj is first object.
00354 
00355    if (!obj || !fPID) return 0;
00356 
00357    Int_t idx = IndexOf(obj) - fLowerBound;
00358    if (idx == -1 || idx == 0) return 0;
00359 
00360    return fPID->GetObjectWithID(fUIDs[idx-1]);
00361 }
00362 
00363 //______________________________________________________________________________
00364 void TRefArray::Clear(Option_t *)
00365 {
00366    // Remove all objects from the array.
00367 
00368    fLast = - 1;
00369 
00370    for (Int_t j=0 ; j < fSize; j++) fUIDs[j] = 0;
00371 
00372    Changed();
00373 }
00374 
00375 //______________________________________________________________________________
00376 void TRefArray::Compress()
00377 {
00378    // Remove empty slots from array.
00379 
00380    Int_t j = 0;
00381 
00382    for (Int_t i = 0; i < fSize; i++) {
00383       if (fUIDs[i]) {
00384          fUIDs[j] = fUIDs[i];
00385          j++;
00386       }
00387    }
00388 
00389    fLast = j - 1;
00390 
00391    for ( ; j < fSize; j++) fUIDs[j] = 0;
00392 }
00393 
00394 //______________________________________________________________________________
00395 void TRefArray::Delete(Option_t *)
00396 {
00397    // Remove all objects from the array and free the internal memory.
00398 
00399    fLast = -1;
00400 
00401    fSize = 0;
00402    if (fUIDs) {
00403       delete [] fUIDs;
00404       fUIDs = 0;
00405    }
00406 
00407    Changed();
00408 }
00409 
00410 //______________________________________________________________________________
00411 void TRefArray::Expand(Int_t newSize)
00412 {
00413    // Expand or shrink the array to newSize elements.
00414 
00415    if (newSize < 0) {
00416       Error ("Expand", "newSize must be positive (%d)", newSize);
00417       return;
00418    }
00419    if (newSize == fSize) return;
00420    UInt_t *temp = fUIDs;
00421    if (newSize != 0) {
00422       fUIDs = new UInt_t[newSize];
00423       if (newSize < fSize) memcpy(fUIDs,temp, newSize*sizeof(UInt_t));
00424       else {
00425          memcpy(fUIDs,temp,fSize*sizeof(UInt_t));
00426          memset(&fUIDs[fSize],0,(newSize-fSize)*sizeof(UInt_t));
00427       }
00428    } else {
00429       fUIDs = 0;
00430    }
00431    if (temp) delete [] temp;
00432    fSize = newSize;
00433 }
00434 
00435 //______________________________________________________________________________
00436 TObject *TRefArray::GetFromTable(Int_t idx) const
00437 {
00438    //the reference may be in the TRefTable
00439    TRefTable *table = TRefTable::GetRefTable();
00440    if (table) {
00441       table->SetUID(fUIDs[idx], fPID);
00442       table->Notify();
00443       return fPID->GetObjectWithID(fUIDs[idx]);
00444    }
00445    return 0;
00446 }
00447 
00448 //_______________________________________________________________________
00449 void TRefArray::Streamer(TBuffer &R__b)
00450 {
00451    // Stream all objects in the array to or from the I/O buffer.
00452 
00453    UInt_t R__s, R__c;
00454    Int_t nobjects;
00455    UShort_t pidf;
00456    if (R__b.IsReading()) {
00457       R__b.ReadVersion(&R__s, &R__c);
00458       TObject::Streamer(R__b);
00459       fName.Streamer(R__b);
00460       R__b >> nobjects;
00461       R__b >> fLowerBound;
00462       if (nobjects >= fSize) Expand(nobjects);
00463       fLast = -1;
00464       R__b >> pidf;
00465       pidf += R__b.GetPidOffset();
00466       fPID = R__b.ReadProcessID(pidf);
00467       if (gDebug > 1) printf("Reading TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
00468       for (Int_t i = 0; i < nobjects; i++) {
00469          R__b >> fUIDs[i];
00470          if (fUIDs[i] != 0) fLast = i;
00471          if (gDebug > 1) {
00472             printf(" %d",fUIDs[i]);
00473             if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
00474          }
00475       }
00476       Changed();
00477       R__b.CheckByteCount(R__s, R__c,TRefArray::IsA());
00478    } else {
00479       R__c = R__b.WriteVersion(TRefArray::IsA(), kTRUE);
00480       TObject::Streamer(R__b);
00481       fName.Streamer(R__b);
00482       nobjects = GetAbsLast()+1;
00483       R__b << nobjects;
00484       R__b << fLowerBound;
00485       pidf = R__b.WriteProcessID(fPID);
00486       R__b << pidf;
00487       if (gDebug > 1) printf("Writing TRefArray, pidf=%d, fPID=%lx, nobjects=%d\n",pidf,(Long_t)fPID,nobjects);
00488 
00489       for (Int_t i = 0; i < nobjects; i++) {
00490          R__b << fUIDs[i];
00491          if (gDebug > 1) {
00492             printf(" %d",fUIDs[i]);
00493             if ((i > 0 && i%10 == 0) || (i == nobjects-1)) printf("\n");
00494          }
00495       }
00496       R__b.SetByteCount(R__c, kTRUE);
00497    }
00498 }
00499 
00500 //______________________________________________________________________________
00501 TObject *TRefArray::First() const
00502 {
00503    // Return the object in the first slot.
00504 
00505    return fPID->GetObjectWithID(fUIDs[0]);
00506 }
00507 
00508 //______________________________________________________________________________
00509 TObject *TRefArray::Last() const
00510 {
00511    // Return the object in the last filled slot. Returns 0 if no entries.
00512 
00513    if (fLast == -1)
00514       return 0;
00515    else
00516       return fPID->GetObjectWithID(fUIDs[GetAbsLast()]);
00517 }
00518 
00519 //______________________________________________________________________________
00520 Int_t TRefArray::GetEntries() const
00521 {
00522    // Return the number of objects in array (i.e. number of non-empty slots).
00523    // Attention: use this method ONLY if you want to know the number of
00524    // non-empty slots. This function loops over the complete array and
00525    // is therefore very slow when applied in a loop. Most of the time you
00526    // better use GetLast()+1.
00527 
00528    Int_t cnt = 0;
00529 
00530    for (Int_t i = 0; i < fSize; i++)
00531       if (fUIDs[i]) cnt++;
00532 
00533    return cnt;
00534 }
00535 
00536 //______________________________________________________________________________
00537 Int_t TRefArray::GetAbsLast() const
00538 {
00539    // Return absolute index to last object in array. Returns -1 in case
00540    // array is empty.
00541 
00542    // For efficiency we need sometimes to update fLast so we have
00543    // to cast const away. Ugly, but making GetAbsLast() not const breaks
00544    // many other const functions.
00545    if (fLast == -2) {
00546       for (Int_t i = fSize-1; i >= 0; i--)
00547          if (fUIDs[i]) {
00548             ((TRefArray*)this)->fLast = i;
00549             return fLast;
00550          }
00551       ((TRefArray*)this)->fLast = -1;
00552    }
00553    return fLast;
00554 }
00555 
00556 //______________________________________________________________________________
00557 Int_t TRefArray::GetLast() const
00558 {
00559    // Return index of last object in array. Returns lowerBound-1 in case
00560    // array is empty.
00561 
00562    return fLowerBound+GetAbsLast();
00563 }
00564 
00565 //______________________________________________________________________________
00566 TObject **TRefArray::GetObjectRef(const TObject *) const
00567 {
00568    // Return address of pointer obj.
00569 
00570    //Int_t index = IndexOf(obj);
00571    //return &fCont[index];
00572    return 0;
00573 }
00574 
00575 //______________________________________________________________________________
00576 UInt_t TRefArray::GetUID(Int_t at) const
00577 {
00578    // Return UID of element at.
00579 
00580    int j = at-fLowerBound;
00581    if (j >= 0 && j < fSize) {
00582       if (!fPID) return 0;
00583       return fUIDs[j];
00584    }
00585    BoundsOk("At", at);
00586    return 0;
00587 }
00588 
00589 //______________________________________________________________________________
00590 Int_t TRefArray::IndexOf(const TObject *obj) const
00591 {
00592    // obj != 0 Return index of object in array.
00593    //          Returns lowerBound-1 in case array doesn't contain the obj.
00594    //
00595    // obj == 0 Return the index of the first empty slot.
00596    //          Returns lowerBound-1 in case array doesn't contain any empty slot.
00597 
00598    Int_t i;
00599    if (obj) {
00600       for (i = 0; i < fSize; i++)
00601          if (fUIDs[i] && fPID->GetObjectWithID(fUIDs[i]) == obj)
00602             return i+fLowerBound;
00603    } else {    // Look for the first empty slot
00604       for (i = 0; i < fSize; i++)
00605          if (!fUIDs[i])
00606             return i+fLowerBound;
00607    }
00608 
00609    return fLowerBound-1;
00610 }
00611 
00612 //______________________________________________________________________________
00613 void TRefArray::Init(Int_t s, Int_t lowerBound)
00614 {
00615    // Initialize a TRefArray.
00616 
00617    if (fUIDs && fSize != s) {
00618       delete [] fUIDs;
00619       fUIDs = 0;
00620    }
00621 
00622    fSize = s;
00623 
00624    if (fSize) {
00625       fUIDs = new UInt_t[fSize];
00626       for (Int_t i=0;i<s;i++) fUIDs[i] = 0;
00627    } else {
00628       fUIDs = 0;
00629    }
00630    fLowerBound = lowerBound;
00631    fLast = -1;
00632    Changed();
00633 }
00634 
00635 //______________________________________________________________________________
00636 TIterator *TRefArray::MakeIterator(Bool_t dir) const
00637 {
00638    // Returns an array iterator.
00639 
00640    return new TRefArrayIter(this, dir);
00641 }
00642 
00643 //______________________________________________________________________________
00644 Bool_t TRefArray::OutOfBoundsError(const char *where, Int_t i) const
00645 {
00646    // Generate an out-of-bounds error. Always returns false.
00647 
00648    Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fSize, (Long_t)this);
00649    return kFALSE;
00650 }
00651 
00652 //______________________________________________________________________________
00653 TObject *TRefArray::RemoveAt(Int_t idx)
00654 {
00655    // Remove object at index idx.
00656 
00657    if (!BoundsOk("RemoveAt", idx)) return 0;
00658 
00659    int i = idx-fLowerBound;
00660 
00661    TObject *obj = 0;
00662    if (fUIDs[i]) {
00663       obj = fPID->GetObjectWithID(fUIDs[i]);
00664       fUIDs[i] = 0;
00665       // recalculate array size
00666       if (i == fLast)
00667          do {
00668             fLast--;
00669          } while (fLast >= 0 && fUIDs[fLast] == 0);
00670       Changed();
00671    }
00672 
00673    return obj;
00674 }
00675 
00676 //______________________________________________________________________________
00677 TObject *TRefArray::Remove(TObject *obj)
00678 {
00679    // Remove object from array.
00680 
00681    if (!obj) return 0;
00682 
00683    Int_t idx = IndexOf(obj) - fLowerBound;
00684 
00685    if (idx == -1) return 0;
00686 
00687    TObject *ob = fPID->GetObjectWithID(fUIDs[idx]);
00688    fUIDs[idx] = 0;
00689    // recalculate array size
00690    if (idx == fLast)
00691       do {
00692          fLast--;
00693       } while (fLast >= 0 && fUIDs[fLast] == 0);
00694    Changed();
00695    return ob;
00696 }
00697 
00698 //______________________________________________________________________________
00699 void TRefArray::SetLast(Int_t last)
00700 {
00701    // Set index of last object in array, effectively truncating the
00702    // array. Use carefully since whenever last position has to be
00703    // recalculated, e.g. after a Remove() or Sort() it will be reset
00704    // to the last non-empty slot. If last is -2 this will force the
00705    // recalculation of the last used slot.
00706 
00707    if (last == -2)
00708       fLast = -2;
00709    else if (BoundsOk("SetLast", last))
00710       fLast = last - fLowerBound;
00711 }
00712 
00713 //______________________________________________________________________________
00714 void TRefArray::Sort(Int_t)
00715 {
00716    // If objects in array are sortable (i.e. IsSortable() returns true
00717    // for all objects) then sort array.
00718 
00719    Error("Sort","Function not yet implemented");
00720 /*
00721    if (GetAbsLast() == -1 || fSorted) return;
00722    for (Int_t i = 0; i < fSize; i++)
00723       if (fUIDs[i]) {
00724          if (!fUIDs[i]->IsSortable()) {
00725             Error("Sort", "objects in array are not sortable");
00726             return;
00727          }
00728       }
00729 
00730    QSort(fUIDs, 0, TMath::Min(fSize, upto-fLowerBound));
00731 
00732    fLast   = -2;
00733    fSorted = kTRUE;
00734 */
00735 }
00736 
00737 //______________________________________________________________________________
00738 Int_t TRefArray::BinarySearch(TObject *, Int_t)
00739 {
00740    // Find object using a binary search. Array must first have been sorted.
00741    // Search can be limited by setting upto to desired index.
00742 
00743    Error("BinarySearch","Function not yet implemented");
00744 /*
00745    Int_t   base, position, last, result = 0;
00746    TObject *op2;
00747 
00748    if (!op) return -1;
00749 
00750    if (!fSorted) {
00751       Error("BinarySearch", "array must first be sorted");
00752       return -1;
00753    }
00754 
00755    base = 0;
00756    last = TMath::Min(fSize, upto-fLowerBound) - 1;
00757 
00758    while (last >= base) {
00759       //position = (base+last) / 2;
00760       //op2 = fCont[position];
00761       //if (op2 && (result = op->Compare(op2)) == 0)
00762       //   return position + fLowerBound;
00763       //if (!op2 || result < 0)
00764       //   last = position-1;
00765       //else
00766       //   base = position+1;
00767    }
00768 */
00769    return -1;
00770 }
00771 
00772 
00773 //////////////////////////////////////////////////////////////////////////
00774 //                                                                      //
00775 // TRefArrayIter                                                        //
00776 //                                                                      //
00777 // Iterator of object array.                                            //
00778 //                                                                      //
00779 //////////////////////////////////////////////////////////////////////////
00780 
00781 ClassImp(TRefArrayIter)
00782 
00783 //______________________________________________________________________________
00784 TRefArrayIter::TRefArrayIter(const TRefArray *arr, Bool_t dir)
00785 {
00786    // Create array iterator. By default the iteration direction
00787    // is kIterForward. To go backward use kIterBackward.
00788 
00789    fArray     = arr;
00790    fDirection = dir;
00791    Reset();
00792 }
00793 
00794 //______________________________________________________________________________
00795 TRefArrayIter::TRefArrayIter(const TRefArrayIter &iter) : TIterator(iter)
00796 {
00797    // Copy ctor.
00798 
00799    fArray     = iter.fArray;
00800    fDirection = iter.fDirection;
00801    fCursor    = iter.fCursor;
00802    fCurCursor = iter.fCurCursor;
00803 }
00804 
00805 //______________________________________________________________________________
00806 TIterator &TRefArrayIter::operator=(const TIterator &rhs)
00807 {
00808    // Overridden assignment operator.
00809 
00810    if (this != &rhs && rhs.IsA() == TRefArrayIter::Class()) {
00811       const TRefArrayIter &rhs1 = (const TRefArrayIter &)rhs;
00812       fArray     = rhs1.fArray;
00813       fDirection = rhs1.fDirection;
00814       fCursor    = rhs1.fCursor;
00815       fCurCursor = rhs1.fCurCursor;
00816    }
00817    return *this;
00818 }
00819 
00820 //______________________________________________________________________________
00821 TRefArrayIter &TRefArrayIter::operator=(const TRefArrayIter &rhs)
00822 {
00823    // Overloaded assignment operator.
00824 
00825    if (this != &rhs) {
00826       fArray     = rhs.fArray;
00827       fDirection = rhs.fDirection;
00828       fCursor    = rhs.fCursor;
00829       fCurCursor = rhs.fCurCursor;
00830    }
00831    return *this;
00832 }
00833 
00834 //______________________________________________________________________________
00835 TObject *TRefArrayIter::Next()
00836 {
00837    // Return next object in array. Returns 0 when no more objects in array.
00838 
00839    if (fDirection == kIterForward) {
00840       for ( ; fCursor < fArray->Capacity() && fArray->At(fCursor+fArray->LowerBound()) == 0;
00841               fCursor++) { }
00842 
00843       fCurCursor = fCursor;
00844       if (fCursor < fArray->Capacity()) {
00845          fCursor++;
00846          return fArray->At(fCurCursor+fArray->LowerBound());
00847       }
00848    } else {
00849       for ( ; fCursor >= 0 && fArray->At(fCursor) == 0;
00850               fCursor--) { }
00851 
00852       fCurCursor = fCursor;
00853       if (fCursor >= 0) {
00854          fCursor--;
00855          return fArray->At(fCurCursor+fArray->LowerBound());
00856       }
00857    }
00858    return 0;
00859 }
00860 
00861 //______________________________________________________________________________
00862 void TRefArrayIter::Reset()
00863 {
00864    // Reset array iterator.
00865 
00866    if (fDirection == kIterForward)
00867       fCursor = 0;
00868    else
00869       fCursor = fArray->Capacity() - 1;
00870 
00871    fCurCursor = fCursor;
00872 }
00873 
00874 //______________________________________________________________________________
00875 bool TRefArrayIter::operator!=(const TIterator &aIter) const
00876 {
00877    // This operator compares two TIterator objects.
00878 
00879    if (nullptr == (&aIter))
00880       return (fCurCursor < fArray->Capacity());
00881 
00882    if (aIter.IsA() == TRefArrayIter::Class()) {
00883       const TRefArrayIter &iter(dynamic_cast<const TRefArrayIter &>(aIter));
00884       return (fCurCursor != iter.fCurCursor);
00885    }
00886    return false; // for base class we don't implement a comparison
00887 }
00888 
00889 //______________________________________________________________________________
00890 bool TRefArrayIter::operator!=(const TRefArrayIter &aIter) const
00891 {
00892    // This operator compares two TRefArrayIter objects.
00893 
00894    if (nullptr == (&aIter))
00895       return (fCurCursor < fArray->Capacity());
00896 
00897    return (fCurCursor != aIter.fCurCursor);
00898 }
00899 
00900 //______________________________________________________________________________
00901 TObject *TRefArrayIter::operator*() const
00902 {
00903    // Return current object or nullptr.
00904 
00905    return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
00906            fArray->At(fCurCursor) : nullptr);
00907 }

Generated on Tue Jul 5 14:11:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1