TObjArray.cxx

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

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