TCollection.cxx

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TCollection.cxx 37411 2010-12-08 17:42:11Z pcanal $
00002 // Author: Fons Rademakers   13/08/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 // Collection abstract base class. This class describes the base        //
00015 // protocol all collection classes have to implement. The ROOT          //
00016 // collection classes always store pointers to objects that inherit     //
00017 // from TObject. They never adopt the objects. Therefore, it is the     //
00018 // user's responsability to take care of deleting the actual objects    //
00019 // once they are not needed anymore. In exceptional cases, when the     //
00020 // user is 100% sure nothing else is referencing the objects in the     //
00021 // collection, one can delete all objects and the collection at the     //
00022 // same time using the Delete() function.                               //
00023 //                                                                      //
00024 // Collections can be iterated using an iterator object (see            //
00025 // TIterator). Depending on the concrete collection class there may be  //
00026 // some additional methods of iterating. See the repective classes.     //
00027 //                                                                      //
00028 // TCollection inherits from TObject since we want to be able to have   //
00029 // collections of collections.                                          //
00030 //                                                                      //
00031 // In a later release the collections may become templatized.           //
00032 //                                                                      //
00033 //Begin_Html
00034 /*
00035 <img src="gif/tcollection_classtree.gif">
00036 */
00037 //End_Html
00038 //////////////////////////////////////////////////////////////////////////
00039 
00040 #include "TCollection.h"
00041 #include "Riostream.h"
00042 #include "Varargs.h"
00043 #include "TClass.h"
00044 #include "TROOT.h"
00045 #include "TBrowser.h"
00046 #include "TObjectTable.h"
00047 #include "TRegexp.h"
00048 #include "TPRegexp.h"
00049 #include "TVirtualMutex.h"
00050 
00051 TVirtualMutex *gCollectionMutex = 0;
00052 
00053 TCollection   *TCollection::fgCurrentCollection = 0;
00054 TObjectTable  *TCollection::fgGarbageCollection = 0;
00055 Bool_t         TCollection::fgEmptyingGarbage   = kFALSE;
00056 Int_t          TCollection::fgGarbageStack      = 0;
00057 
00058 ClassImp(TCollection)
00059 ClassImp(TIter)
00060 
00061 //______________________________________________________________________________
00062 void TCollection::AddAll(const TCollection *col)
00063 {
00064    // Add all objects from collection col to this collection.
00065 
00066    TIter next(col);
00067    TObject *obj;
00068 
00069    while ((obj = next()))
00070       Add(obj);
00071 }
00072 
00073 //______________________________________________________________________________
00074 void TCollection::AddVector(TObject *va_(obj1), ...)
00075 {
00076    // Add all arguments to the collection. The list of objects must be
00077    // temrinated by 0, e.g.: l.AddVector(o1, o2, o3, o4, 0);
00078 
00079    va_list ap;
00080    va_start(ap, va_(obj1));
00081    TObject *obj;
00082 
00083    Add(va_(obj1));
00084    while ((obj = va_arg(ap, TObject *)))
00085       Add(obj);
00086    va_end(ap);
00087 }
00088 
00089 //______________________________________________________________________________
00090 Bool_t TCollection::AssertClass(TClass *cl) const
00091 {
00092    // Make sure all objects in this collection inherit from class cl.
00093 
00094    TObject *obj;
00095    TIter    next(this);
00096    Bool_t   error = kFALSE;
00097 
00098    if (!cl) {
00099       Error("AssertClass", "class == 0");
00100       return kTRUE;
00101    }
00102 
00103    for (int i = 0; (obj = next()); i++)
00104       if (!obj->InheritsFrom(cl)) {
00105          Error("AssertClass", "element %d is not an instance of class %s (%s)",
00106                i, cl->GetName(), obj->ClassName());
00107          error = kTRUE;
00108       }
00109    return error;
00110 }
00111 
00112 //______________________________________________________________________________
00113 void TCollection::Browse(TBrowser *b)
00114 {
00115    // Browse this collection (called by TBrowser).
00116    // If b=0, there is no Browse call TObject::Browse(0) instead.
00117    //         This means TObject::Inspect() will be invoked indirectly
00118 
00119    TIter next(this);
00120    TObject *obj;
00121 
00122    if (b)
00123       while ((obj = next())) b->Add(obj);
00124    else
00125       TObject::Browse(b);
00126 }
00127 
00128 //______________________________________________________________________________
00129 TObject *TCollection::Clone(const char *newname) const
00130 {
00131    // Make a clone of an collection using the Streamer facility.
00132    // If newname is specified, this will be the name of the new collection.
00133    
00134    TCollection *new_collection = (TCollection*)TObject::Clone(newname);
00135    if (newname && strlen(newname)) new_collection->SetName(newname);
00136    return new_collection;
00137 }
00138 
00139 
00140 //______________________________________________________________________________
00141 Int_t TCollection::Compare(const TObject *obj) const
00142 {
00143    // Compare two TCollection objects. Returns 0 when equal, -1 when this is
00144    // smaller and +1 when bigger (like strcmp()).
00145 
00146    if (this == obj) return 0;
00147    return fName.CompareTo(obj->GetName());
00148 }
00149 
00150 //______________________________________________________________________________
00151 void TCollection::Draw(Option_t *option)
00152 {
00153    // Draw all objects in this collection.
00154 
00155    TIter next(this);
00156    TObject *object;
00157 
00158    while ((object = next())) {
00159       object->Draw(option);
00160    }
00161 }
00162 
00163 //______________________________________________________________________________
00164 void TCollection::Dump() const
00165 {
00166    // Dump all objects in this collection.
00167 
00168    TIter next(this);
00169    TObject *object;
00170 
00171    while ((object = next())) {
00172       object->Dump();
00173    }
00174 }
00175 
00176 //______________________________________________________________________________
00177 TObject *TCollection::FindObject(const char *name) const
00178 {
00179    // Find an object in this collection using its name. Requires a sequential
00180    // scan till the object has been found. Returns 0 if object with specified
00181    // name is not found.
00182 
00183    TIter next(this);
00184    TObject *obj;
00185 
00186    while ((obj = next()))
00187       if (!strcmp(name, obj->GetName())) return obj;
00188    return 0;
00189 }
00190 
00191 //______________________________________________________________________________
00192 TObject *TCollection::operator()(const char *name) const
00193 {
00194   // Find an object in this collection by name.
00195 
00196    return FindObject(name);
00197 }
00198 
00199 //______________________________________________________________________________
00200 TObject *TCollection::FindObject(const TObject *obj) const
00201 {
00202    // Find an object in this collection using the object's IsEqual()
00203    // member function. Requires a sequential scan till the object has
00204    // been found. Returns 0 if object is not found.
00205    // Typically this function is overridden by a more efficient version
00206    // in concrete collection classes (e.g. THashTable).
00207 
00208    TIter next(this);
00209    TObject *ob;
00210 
00211    while ((ob = next()))
00212       if (ob->IsEqual(obj)) return ob;
00213    return 0;
00214 }
00215 
00216 //______________________________________________________________________________
00217 const char *TCollection::GetName() const
00218 {
00219   // Return name of this collection.
00220   // if no name, return the collection class name.
00221 
00222    if (fName.Length() > 0) return fName.Data();
00223    return ClassName();
00224 }
00225 
00226 //______________________________________________________________________________
00227 Int_t TCollection::GrowBy(Int_t delta) const
00228 {
00229   // Increase the collection's capacity by delta slots.
00230 
00231    if (delta < 0) {
00232       Error("GrowBy", "delta < 0");
00233       delta = Capacity();
00234    }
00235    return Capacity() + TMath::Range(2, kMaxInt - Capacity(), delta);
00236 }
00237 
00238 //______________________________________________________________________________
00239 Bool_t  TCollection::IsArgNull(const char *where, const TObject *obj) const
00240 {
00241    // Returns true if object is a null pointer.
00242 
00243    return obj ? kFALSE : (Error(where, "argument is a null pointer"), kTRUE);
00244 }
00245 
00246 //______________________________________________________________________________
00247 void TCollection::ls(Option_t *option) const
00248 {
00249    // List (ls) all objects in this collection.
00250    // Wildcarding supported, eg option="xxx*" lists only objects
00251    // with names xxx*.
00252 
00253    TROOT::IndentLevel();
00254    cout <<"OBJ: " << IsA()->GetName() << "\t" << GetName() << "\t" << GetTitle() << " : "
00255         << Int_t(TestBit(kCanDelete)) << endl;
00256 
00257    TRegexp re(option,kTRUE);
00258    TIter next(this);
00259    TObject *object;
00260    char *star = 0;
00261    if (option) star = (char*)strchr(option,'*');
00262 
00263    TROOT::IncreaseDirLevel();
00264    while ((object = next())) {
00265       if (star) {
00266          TString s = object->GetName();
00267          if (s != option && s.Index(re) == kNPOS) continue;
00268       }
00269       object->ls(option);
00270    }
00271    TROOT::DecreaseDirLevel();
00272 }
00273 
00274 //______________________________________________________________________________
00275 void TCollection::Paint(Option_t *option)
00276 {
00277    // Paint all objects in this collection.
00278 
00279    this->R__FOR_EACH(TObject,Paint)(option);
00280 }
00281 
00282 //______________________________________________________________________________
00283 void TCollection::PrintCollectionHeader(Option_t*) const
00284 {
00285    // Print the collection header.
00286 
00287    TROOT::IndentLevel();
00288    printf("Collection name='%s', class='%s', size=%d\n",
00289           GetName(), ClassName(), GetSize());
00290 }
00291 
00292 //______________________________________________________________________________
00293 const char* TCollection::GetCollectionEntryName(TObject* entry) const
00294 {
00295    // For given collection entry return the string that is used to
00296    // identify the object and, potentially, perform wildcard/regexp
00297    // filtering on.
00298 
00299    return entry->GetName();
00300 }
00301 
00302 //______________________________________________________________________________
00303 void TCollection::PrintCollectionEntry(TObject* entry, Option_t* option, Int_t recurse) const
00304 {
00305    // Print the collection entry.
00306 
00307    TCollection* coll = dynamic_cast<TCollection*>(entry);
00308    if (coll) {
00309       coll->Print(option, recurse);
00310    } else {
00311       TROOT::IndentLevel();
00312       entry->Print(option);
00313    }
00314 }
00315 
00316 //______________________________________________________________________________
00317 void TCollection::Print(Option_t *option) const
00318 {
00319    // Defualt print for collections, calls Print(option, 1).
00320    // This will print the collection header and Print() methods of
00321    // all the collection entries.
00322    //
00323    // If you want to override Print() for a collection class, first
00324    // see if you can accomplish it by overriding the following protected
00325    // methods:
00326    //   void        PrintCollectionHeader(Option_t* option) const;
00327    //   const char* GetCollectionEntryName(TObject* entry) const;
00328    //   void        PrintCollectionEntry(TObject* entry, Option_t* option, Int_t recurse) const;
00329    // Otherwise override the Print(Option_t *option, Int_t)
00330    // variant. Remember to declare:
00331    //   using TCollection::Print;
00332    // somewhere close to the method declaration.
00333 
00334    Print(option, 1);
00335 }
00336 
00337 //______________________________________________________________________________
00338 void TCollection::Print(Option_t *option, Int_t recurse) const
00339 {
00340    // Print the collection header and its elements.
00341    //
00342    // If recurse is non-zero, descend into printing of
00343    // collection-entries with recurse - 1.
00344    // This means, if recurse is negative, the recursion is infinite.
00345    //
00346    // Option is passed recursively.
00347 
00348    PrintCollectionHeader(option);
00349 
00350    if (recurse != 0)
00351    {
00352       TIter next(this);
00353       TObject *object;
00354       
00355       TROOT::IncreaseDirLevel();
00356       while ((object = next())) {
00357          PrintCollectionEntry(object, option, recurse - 1);
00358       }
00359       TROOT::DecreaseDirLevel();
00360    }
00361 }
00362 
00363 //______________________________________________________________________________
00364 void TCollection::Print(Option_t *option, const char* wildcard, Int_t recurse) const
00365 {
00366    // Print the collection header and its elements that match the wildcard.
00367    //
00368    // If recurse is non-zero, descend into printing of
00369    // collection-entries with recurse - 1.
00370    // This means, if recurse is negative, the recursion is infinite.
00371    //
00372    // Option is passed recursively, but wildcard is only used on the
00373    // first level.
00374 
00375    PrintCollectionHeader(option);
00376 
00377    if (recurse != 0)
00378    {
00379       if (!wildcard) wildcard = "";
00380       TRegexp re(wildcard, kTRUE);
00381       Int_t nch = strlen(wildcard);
00382       TIter next(this);
00383       TObject *object;
00384 
00385       TROOT::IncreaseDirLevel();
00386       while ((object = next())) {
00387          TString s = GetCollectionEntryName(object);
00388          if (nch == 0 || s == wildcard || s.Index(re) != kNPOS) {
00389             PrintCollectionEntry(object, option, recurse - 1);
00390          }
00391       }
00392       TROOT::DecreaseDirLevel();
00393    }
00394 }
00395 
00396 //______________________________________________________________________________
00397 void TCollection::Print(Option_t *option, TPRegexp& regexp, Int_t recurse) const
00398 {
00399    // Print the collection header and its elements that match the regexp.
00400    //
00401    // If recurse is non-zero, descend into printing of
00402    // collection-entries with recurse - 1.
00403    // This means, if recurse is negative, the recursion is infinite.
00404    //
00405    // Option is passed recursively, but regexp is only used on the
00406    // first level.
00407 
00408    PrintCollectionHeader(option);
00409 
00410    if (recurse != 0)
00411    {
00412       TIter next(this);
00413       TObject *object;
00414 
00415       TROOT::IncreaseDirLevel();
00416       while ((object = next())) {
00417          TString s = GetCollectionEntryName(object);
00418          if (regexp.MatchB(s)) {
00419             PrintCollectionEntry(object, option, recurse - 1);
00420          }
00421       }
00422       TROOT::DecreaseDirLevel();
00423    }
00424 }
00425 
00426 //______________________________________________________________________________
00427 void TCollection::RecursiveRemove(TObject *obj)
00428 {
00429    // Remove object from this collection and recursively remove the object
00430    // from all other objects (and collections).
00431 
00432    if (!obj) return;
00433 
00434    // Scan list and remove obj in the list itself
00435    while (Remove(obj))
00436       ;
00437 
00438    // Scan again the list and invoke RecursiveRemove for all objects
00439    TIter next(this);
00440    TObject *object;
00441 
00442    while ((object = next())) {
00443       if (object->TestBit(kNotDeleted)) object->RecursiveRemove(obj);
00444    }
00445 }
00446 
00447 //______________________________________________________________________________
00448 void TCollection::RemoveAll(TCollection *col)
00449 {
00450    // Remove all objects in collection col from this collection.
00451 
00452    TIter next(col);
00453    TObject *obj;
00454 
00455    while ((obj = next()))
00456       Remove(obj);
00457 }
00458 
00459 //_______________________________________________________________________
00460 void TCollection::Streamer(TBuffer &b)
00461 {
00462    // Stream all objects in the collection to or from the I/O buffer.
00463 
00464    Int_t nobjects;
00465    TObject *obj;
00466    UInt_t R__s, R__c;
00467 
00468    if (b.IsReading()) {
00469       Version_t v = b.ReadVersion(&R__s, &R__c);
00470       if (v > 2)
00471          TObject::Streamer(b);
00472       if (v > 1)
00473          fName.Streamer(b);
00474       b >> nobjects;
00475       for (Int_t i = 0; i < nobjects; i++) {
00476          b >> obj;
00477          Add(obj);
00478       }
00479       b.CheckByteCount(R__s, R__c,TCollection::IsA());
00480    } else {
00481       R__c = b.WriteVersion(TCollection::IsA(), kTRUE);
00482       TObject::Streamer(b);
00483       fName.Streamer(b);
00484       nobjects = GetSize();
00485       b << nobjects;
00486 
00487       TIter next(this);
00488 
00489       while ((obj = next())) {
00490          b << obj;
00491       }
00492       b.SetByteCount(R__c, kTRUE);
00493    }
00494 }
00495 
00496 //______________________________________________________________________________
00497 Int_t TCollection::Write(const char *name, Int_t option, Int_t bsize) const
00498 {
00499    // Write all objects in this collection. By default all objects in
00500    // the collection are written individually (each object gets its
00501    // own key). Note, this is recursive, i.e. objects in collections
00502    // in the collection are also written individually. To write all
00503    // objects using a single key specify a name and set option to
00504    // TObject::kSingleKey (i.e. 1).
00505 
00506    if ((option & kSingleKey)) {
00507       return TObject::Write(name, option, bsize);
00508    } else {
00509       option &= ~kSingleKey;
00510       Int_t nbytes = 0;
00511       TIter next(this);
00512       TObject *obj;
00513       while ((obj = next())) {
00514          nbytes += obj->Write(name, option, bsize);
00515       }
00516       return nbytes;
00517    }
00518 }
00519 
00520 //______________________________________________________________________________
00521 Int_t TCollection::Write(const char *name, Int_t option, Int_t bsize)
00522 {
00523    // Write all objects in this collection. By default all objects in
00524    // the collection are written individually (each object gets its
00525    // own key). Note, this is recursive, i.e. objects in collections
00526    // in the collection are also written individually. To write all
00527    // objects using a single key specify a name and set option to
00528    // TObject::kSingleKey (i.e. 1).
00529 
00530    return ((const TCollection*)this)->Write(name,option,bsize);
00531 }
00532 
00533 // -------------------- Static data members access -----------------------------
00534 //______________________________________________________________________________
00535 TCollection *TCollection::GetCurrentCollection()
00536 {
00537    // Return the globally accessible collection.
00538 
00539    return fgCurrentCollection;
00540 }
00541 
00542 //______________________________________________________________________________
00543 void TCollection::SetCurrentCollection()
00544 {
00545    // Set this collection to be the globally accesible collection.
00546 
00547    fgCurrentCollection = this;
00548 }
00549 
00550 //______________________________________________________________________________
00551 void TCollection::StartGarbageCollection()
00552 {
00553    // Set up for garbage collection.
00554 
00555    R__LOCKGUARD2(gCollectionMutex);
00556    if (!fgGarbageCollection) {
00557       fgGarbageCollection = new TObjectTable;
00558       fgEmptyingGarbage   = kFALSE;
00559       fgGarbageStack      = 0;
00560    }
00561    fgGarbageStack++;
00562 }
00563 
00564 //______________________________________________________________________________
00565 void TCollection::EmptyGarbageCollection()
00566 {
00567    // Do the garbage collection.
00568 
00569    R__LOCKGUARD2(gCollectionMutex);
00570    if (fgGarbageStack > 0) fgGarbageStack--;
00571    if (fgGarbageCollection && fgGarbageStack == 0 && fgEmptyingGarbage == kFALSE) {
00572       fgEmptyingGarbage = kTRUE;
00573       fgGarbageCollection->Delete();
00574       fgEmptyingGarbage = kFALSE;
00575       SafeDelete(fgGarbageCollection);
00576    }
00577 }
00578 
00579 //______________________________________________________________________________
00580 void TCollection::GarbageCollect(TObject *obj)
00581 {
00582    // Add to the list of things to be cleaned up.
00583 
00584    R__LOCKGUARD2(gCollectionMutex);
00585    if (fgGarbageCollection) {
00586       if (!fgEmptyingGarbage) {
00587          fgGarbageCollection->Add(obj);
00588       } else
00589          delete obj;
00590    } else
00591       delete obj;
00592 }
00593 
00594 //______________________________________________________________________________
00595 void TCollection::SetOwner(Bool_t enable)
00596 {
00597    // Set whether this collection is the owner (enable==true)
00598    // of its content.  If it is the owner of its contents,
00599    // these objects will be deleted whenever the collection itself
00600    // is delete.   The objects might also be deleted or destructed when Clear
00601    // is called (depending on the collection).
00602 
00603    if (enable)
00604       SetBit(kIsOwner);
00605    else
00606       ResetBit(kIsOwner);
00607 }
00608 
00609 //______________________________________________________________________________
00610 TIter::TIter(const TIter &iter)
00611 {
00612    // Copy a TIter. This involves allocating a new TIterator of the right
00613    // sub class and assigning it with the original.
00614 
00615    if (iter.fIterator) {
00616       fIterator = iter.GetCollection()->MakeIterator();
00617       fIterator->operator=(*iter.fIterator);
00618    } else
00619       fIterator = 0;
00620 }
00621 
00622 //______________________________________________________________________________
00623 TIter &TIter::operator=(const TIter &rhs)
00624 {
00625    // Assigning an TIter to another. This involves allocatiing a new TIterator
00626    // of the right sub class and assigning it with the original.
00627 
00628    if (this != &rhs) {
00629       if (rhs.fIterator) {
00630          delete fIterator;
00631          fIterator = rhs.GetCollection()->MakeIterator();
00632          fIterator->operator=(*rhs.fIterator);
00633       }
00634    }
00635    return *this;
00636 }
00637 
00638 //______________________________________________________________________________
00639 TIter &TIter::Begin()
00640 {
00641    // Pointing to the first element of the container.
00642 
00643    fIterator->Reset();
00644    fIterator->Next();
00645    return *this;
00646 }
00647 
00648 //______________________________________________________________________________
00649 TIter TIter::End()
00650 {
00651    // Pointing to the element after the last - to a nullptr value in our case.
00652 
00653    return TIter(static_cast<TIterator*>(nullptr));
00654 }

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