00001 // @(#)root/table:$Id: TDataSet.cxx 34263 2010-07-01 07:08:27Z brun $ 00002 // Author: Valery Fine(fine@mail.cern.ch) 03/07/98 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 #include "Riostream.h" 00013 #include "TSystem.h" 00014 #include "TDataSetIter.h" 00015 #include "TDataSet.h" 00016 00017 #include "TROOT.h" 00018 #include "TBrowser.h" 00019 00020 #include "TSystem.h" 00021 #include <assert.h> 00022 00023 ////////////////////////////////////////////////////////////////////////// 00024 // // 00025 // TDataSet // 00026 // // 00027 // TDataSet class is to create a special compound object-container: // 00028 // // 00029 // ==================================================================== // 00030 // TDataSet object ::= the "named" list of TDataSet objects // 00031 // ==================================================================== // 00032 // where the "list" (the pointer to TList object) may contain no object // 00033 // // 00034 // TDataSet object has a back pointer to its "parent" TDataSet // 00035 // object, the "character" *name* and "character" *title* // 00036 // // 00037 // The service this class does provide is to help the user to build // 00038 // and manage the hierarchy of his/her data but the data itself. // 00039 // // 00040 // So it is not "Container" itself rather the basement (base class) // 00041 // to built the containers. // 00042 // // 00043 // One may derive the custom container classes from TDataSet. // 00044 // See for example TObjectSet, TTable, TVolume, TFileSet // 00045 // These classes derived from TDataSet: // 00046 // // 00047 // Class Name // 00048 // ---------- // 00049 // TObjectSet::public TDataSet - is a container for TObject // 00050 // TTable:: public TDataSet - is a container for the array // 00051 // of any "plain" C-structure // 00052 // TNode:: public TDataSet - is a container for 3D objects // 00053 // TMaker:: public TDataSet - is a container for STAR "control" // 00054 // objects // 00055 // etc etc // 00056 // // 00057 // TDataSet class is a base class to implement the directory-like // 00058 // data structures and maintain it via TDataSetIter class iterator // 00059 // // 00060 // TDataSet can be iterated using an iterator object (see TDataSetIter) // 00061 // or by TDataSet::Pass method (see below) // 00062 // // 00063 // Terms: Dataset - any object from the list above // 00064 // ===== Member is called "DataSet Member" // 00065 // // 00066 // Structural - the "Dataset Member" is its // 00067 // member "Structural member" if its "back pointer" // 00068 // points to this object // 00069 // // 00070 // Dataset - we will say this TDataSet object "OWNs" // 00071 // Owner (or is an OWNER / PARENT of ) another // 00072 // (parent) TDataSet object if the last one is its // 00073 // "Structural Member" // 00074 // // 00075 // Associated - If some object is not "Structural member" // 00076 // member of this object we will say it is an // 00077 // "Associated Member" of this dataset // 00078 // // 00079 // Orphan - If some dataset is a member of NO other // 00080 // dataset TDataSet object it is called an "orphan" // 00081 // dataset object // 00082 // // 00083 // - Any TDataSet object may be "Owned" by one and only one another // 00084 // TDataSet object if any. // 00085 // // 00086 // - Any TDataSet object can be the "Structural Member" of one and // 00087 // only one another TDataSet // 00088 // // 00089 // - Any TDataSet object may be an "Associated Member" for any number // 00090 // of other TDataSet objects if any // 00091 // // 00092 // - NAME issue: // 00093 // Each "dataset member" is in possession of some "alpha-numerical" // 00094 // NAME as defined by TNamed class. // 00095 // The NAME may contain any "printable" symbols but "SLASH" - "/" // 00096 // The symbol "RIGHT SLASH" - "/" can not be used as any part of the // 00097 // "DataSet Member" NAME // 00098 // Any DataSet can be found by its NAME with TDataSetIter object // 00099 // // 00100 // - TITLE issue: // 00101 // Each "dataset member" is in possession of the "alpha-numerical" // 00102 // TITLE as defined by TNamed class. The meaning of the TITLE is // 00103 // reserved for the derived classes to hold there some indetification // 00104 // that is special for that derived class. // 00105 // // 00106 // This means the user must be careful about the "TDataSet // 00107 // NAME and TITLE since this may cause some "side effects" of the // 00108 // particular class functions // 00109 // // 00110 // - It is NOT required those all "DataSet Members" are in possession // 00111 // of the unique names, i.e. any number of "DataSet Members" // 00112 // may bear one and the same name // 00113 // // 00114 // Actions: // 00115 // ======== // 00116 // Create DataSet is born either as "Orphan" or // 00117 // as "Structural Member" // 00118 // of another TDataSet object // 00119 // // 00120 // Add One dataset can be included into another dataset. // 00121 // Upon adding: // 00122 // - the "Orphan dataset" becomes "Structural Member" // 00123 // - "Structural Members" of another dataset becomes the // 00124 // "Associated Member" of this datatset // 00125 // // 00126 // Delete - Upon deleting the "Structural Member": // 00127 // - "REMOVES" itself from the "Parent DataSet". // 00128 // - Its "Associated memberships" is not changed though // 00129 // // 00130 // The last means the DataSet with the "Associated Members"// 00131 // may contain a DIED pointers to unexisting "Associated" // 00132 // objects !!! // 00133 // // 00134 // Further information is provided my the particular method // 00135 // descriptions. // 00136 // // 00137 // The TDataSet class has several methods to control object('s) // 00138 // memberships // 00139 // // 00140 ////////////////////////////////////////////////////////////////////////// 00141 00142 TDataSet mainSet("DSMAIN"); 00143 TDataSet *TDataSet::fgMainSet = &mainSet; 00144 00145 ClassImp(TDataSet) 00146 00147 //______________________________________________________________________________ 00148 TDataSet::TDataSet(const Char_t *name, TDataSet *parent, Bool_t arrayFlag) 00149 : TNamed(name,"TDataSet"),fParent(0),fList(0) 00150 { 00151 // cout << "ctor for " << GetName() << " - " << GetTitle() << endl; 00152 if (name && strchr(name,'/')) { 00153 Error("TDataSet::TDataSet","dataset name (%s) cannot contain a slash", name); 00154 return; 00155 } 00156 fList =0; fParent=0; 00157 if (arrayFlag) SetBit(kArray); 00158 if (parent) parent->Add(this); 00159 // else AddMain(this); 00160 } 00161 00162 //______________________________________________________________________________ 00163 TDataSet *TDataSet::GetRealParent() 00164 { 00165 //return real parent 00166 TDataSet *p = GetParent(); 00167 if (fgMainSet && p == fgMainSet) p = 0; 00168 return p; 00169 } 00170 //______________________________________________________________________________ 00171 TDataSet::TDataSet(const TDataSet &pattern,EDataSetPass iopt):TNamed(pattern.GetName(),pattern.GetTitle()), 00172 fParent(0),fList(0) 00173 { 00174 // 00175 // Creates TDataSet (clone) with a topology similar with TDataSet *pattern 00176 // 00177 // Parameters: 00178 // ----------- 00179 // pattern - the pattern dataset 00180 // iopt = kStruct - clone only my structural links 00181 // kAll - clone all links 00182 // kRefs - clone only refs 00183 // kMarked - clone marked (not implemented yet) only 00184 // 00185 // All new-created sets become the structural ones anyway. 00186 // 00187 // cout << "ctor for " << GetName() << " - " << GetTitle() << endl; 00188 00189 TDataSet *set = 0; 00190 TDataSetIter next((TDataSet *)&pattern); 00191 Bool_t optsel = (iopt == kStruct); 00192 Bool_t optall = (iopt == kAll); 00193 while ((set = next())) { 00194 // define the parent of the next set 00195 TDataSet *parent = set->GetParent(); 00196 if ( optall || (optsel && parent == this) ) 00197 Add((TDataSet *)(set->Clone())); 00198 } 00199 } 00200 00201 //______________________________________________________________________________ 00202 TDataSet::TDataSet(TNode &) 00203 { 00204 // This copy ctor has been depricated (left for thwe sake of the backweard compatibility) 00205 assert(0); 00206 } 00207 //______________________________________________________________________________ 00208 TDataSet::~TDataSet() 00209 { 00210 // cout << "Default destructor for " << GetName() << " - " << GetTitle() << endl; 00211 Shunt(0); Delete(); 00212 } 00213 00214 //______________________________________________________________________________ 00215 void TDataSet::MakeCollection() 00216 { 00217 // Create the internal container at once if any 00218 if (!fList) 00219 fList = TestBit(kArray) ? (TSeqCollection *)new TObjArray : (TSeqCollection *) new TList; 00220 } 00221 00222 //______________________________________________________________________________ 00223 void TDataSet::AddAt(TDataSet *dataset,Int_t idx) 00224 { 00225 // 00226 // Add TDataSet object at the "idx" position in ds 00227 // or at the end of the dataset 00228 // The final result is defined by either TList::AddAt or TObjArray::AddAt 00229 // methods 00230 // 00231 if (!dataset) return; 00232 00233 MakeCollection(); 00234 00235 // Check whether this new child has got any parent yet 00236 if (!dataset->GetRealParent()) dataset->SetParent(this); 00237 fList->AddAt(dataset,idx); 00238 } 00239 00240 //______________________________________________________________________________ 00241 void TDataSet::AddAtAndExpand(TDataSet *dataset, Int_t idx) 00242 { 00243 // !!!! Under construction !!!!! 00244 // Add TDataSet object at the "idx" position in ds 00245 // or at the end of the dataset 00246 // The final result is defined by either TList::AddAt or TObjArray::AddAt 00247 // methods 00248 // 00249 if (!dataset) return; 00250 00251 MakeCollection(); 00252 00253 // Check whether this new child has got any parent yet 00254 if (!dataset->GetRealParent()) dataset->SetParent(this); 00255 if (TestBit(kArray)) ((TObjArray *) fList)->AddAtAndExpand(dataset,idx); 00256 else fList->AddAt(dataset,idx); 00257 } 00258 00259 //______________________________________________________________________________ 00260 void TDataSet::AddLast(TDataSet *dataset) 00261 { 00262 // Add TDataSet object at the end of the dataset list of this dataset 00263 if (!dataset) return; 00264 00265 MakeCollection(); 00266 00267 // Check whether this new child has got any parent yet 00268 if (!dataset->GetRealParent()) dataset->SetParent(this); 00269 fList->AddLast(dataset); 00270 } 00271 00272 //______________________________________________________________________________ 00273 void TDataSet::AddFirst(TDataSet *dataset) 00274 { 00275 // Add TDataSet object at the beginning of the dataset list of this dataset 00276 if (!dataset) return; 00277 00278 MakeCollection(); 00279 00280 // Check whether this new child has got any partent yet 00281 if (!dataset->GetRealParent()) dataset->SetParent(this); 00282 fList->AddFirst(dataset); 00283 } 00284 00285 //______________________________________________________________________________ 00286 void TDataSet::Browse(TBrowser *b) 00287 { 00288 // Browse this dataset (called by TBrowser). 00289 TDataSetIter next(this); 00290 TDataSet *obj; 00291 if (b) 00292 while ((obj = next())) b->Add(obj,obj->GetName()); 00293 } 00294 00295 //______________________________________________________________________________ 00296 TObject *TDataSet::Clone(const char*) const 00297 { 00298 // the custom implementation fo the TObject::Clone 00299 return new TDataSet(*this); 00300 } 00301 00302 //______________________________________________________________________________ 00303 void TDataSet::Delete(Option_t *opt) 00304 { 00305 // 00306 // Delete - deletes the list of the TDataSet objects and all "Structural Members" 00307 // as well 00308 // This method doesn't affect the "Associated Members" 00309 // 00310 if(opt){/*unused*/} 00311 00312 // Delete list of the TDataSet 00313 TSeqCollection *thisList = GetCollection(); 00314 if (!thisList) return; 00315 fList = 0; 00316 TIter next(thisList); 00317 TDataSet *son = 0; 00318 // Delete the "Structural Members" of this TDataSet only 00319 while ((son = (TDataSet *)next())) { 00320 if ( (!son->TObject::IsOnHeap()) || (this != son->TDataSet::GetParent()) ) continue; 00321 // mark the object is deleted from the TDataSet dtor or Delete method 00322 son->TDataSet::SetParent(0); 00323 if (son->TDataSet::Last()) { son->TDataSet::Delete(); } 00324 son->TObject::SetBit(kCanDelete); 00325 delete son; 00326 } 00327 // Cleare list 00328 thisList->Clear("nodelete"); 00329 delete thisList; 00330 } 00331 00332 //______________________________________________________________________________ 00333 TDataSet *TDataSet::FindByPath(const Char_t *path) const 00334 { 00335 // Aliase for TDataSet::Find(const Char_t *path) method 00336 return Find(path); 00337 } 00338 00339 //______________________________________________________________________________ 00340 TDataSet *TDataSet::Find(const Char_t *path) const 00341 { 00342 // 00343 // Full description see: TDataSetIter::Find 00344 // 00345 // Note. This method is quite expansive. 00346 // ----- It is done to simplify the user's code when one wants to find ONLY object. 00347 // If you need to find more then 1 object in this dataset, 00348 // regard using TDataSetIter class yourself. 00349 // 00350 TDataSetIter next((TDataSet*)this); 00351 return next.Find(path); 00352 } 00353 00354 //______________________________________________________________________________ 00355 TDataSet *TDataSet::FindByName(const Char_t *name,const Char_t *path,Option_t *opt) const 00356 { 00357 // 00358 // Full description see: TDataSetIter::Find 00359 // 00360 // Note. This is method is quite expansive. 00361 // ----- It is done to simplify the user's code when one wants to find ONLY object. 00362 // If you need to find more then 1 object in this dataset, 00363 // regard using TDataSetIter class yourself. 00364 // 00365 00366 TDataSetIter next((TDataSet*)this); 00367 return next.FindByName(name,path,opt); 00368 } 00369 00370 //______________________________________________________________________________ 00371 TDataSet *TDataSet::FindByTitle(const Char_t *title,const Char_t *path,Option_t *opt) const 00372 { 00373 // 00374 // Full description see: TDataSetIter::Find 00375 // 00376 // Note. This method is quite expansive. 00377 // ----- It is done to simplify the user's code when one wants to find ONLY object. 00378 // If you need to find more then 1 object in this dataset, 00379 // regard using TDataSetIter class yourself. 00380 // 00381 TDataSetIter next((TDataSet*)this); 00382 return next.FindByTitle(title,path,opt); 00383 } 00384 00385 //______________________________________________________________________________ 00386 TDataSet *TDataSet::First() const 00387 { 00388 // Return the first object in the list. Returns 0 when list is empty. 00389 if (fList) return (TDataSet *)(fList->First()); 00390 return 0; 00391 } 00392 00393 //______________________________________________________________________________ 00394 void TDataSet::AddMain(TDataSet *set) 00395 { 00396 //add data set to main data set 00397 00398 if (fgMainSet && set) fgMainSet->AddFirst(set); 00399 } 00400 00401 //______________________________________________________________________________ 00402 TDataSet *TDataSet::GetMainSet() 00403 { 00404 //return pointer to the main dataset 00405 00406 return fgMainSet; 00407 } 00408 00409 //______________________________________________________________________________ 00410 TObject *TDataSet::GetObject() const 00411 { 00412 // The depricated method (left here for the sake of the backward compatibility) 00413 Print("***DUMMY GetObject***\n"); 00414 return 0; 00415 } 00416 00417 //______________________________________________________________________________ 00418 TDataSet *TDataSet::Last() const 00419 { 00420 // Return the last object in the list. Returns 0 when list is empty. 00421 if (fList) return (TDataSet *)(fList->Last()); 00422 return 0; 00423 } 00424 00425 //______________________________________________________________________________ 00426 TDataSet *TDataSet::Next() const 00427 { 00428 // Return the object next to this one in the parent structure 00429 // This convinient but time-consuming. Don't use it in the inner loops 00430 TDataSet *set = 0; 00431 TDataSet *parent = GetParent(); 00432 if (parent) { 00433 TIter next(parent->GetCollection()); 00434 // Find this object 00435 while ( (set = (TDataSet *)next()) && (set != this) ){} 00436 if (set) set = (TDataSet *)next(); 00437 } 00438 return set; 00439 } 00440 00441 //______________________________________________________________________________ 00442 TDataSet *TDataSet::Prev() const 00443 { 00444 // Return the object that is previous to this one in the parent structure 00445 // This convinient but time-consuming. Don't use it in the inner loops 00446 TDataSet *prev = 0; 00447 TDataSet *set = 0; 00448 TDataSet *parent = GetParent(); 00449 if (parent) { 00450 TIter next(parent->GetCollection()); 00451 // Find this object 00452 while ( (set = (TDataSet *)next()) && (set != this) ){prev = set;} 00453 if (!set) prev = 0; 00454 } 00455 return prev; 00456 } 00457 //______________________________________________________________________________ 00458 void TDataSet::SetObject(TObject * /*obj*/) 00459 { 00460 // The depricated method (left here for the sake of the backward compatibility) 00461 Print("***DUMMY PutObject***\n"); 00462 } 00463 00464 //______________________________________________________________________________ 00465 void TDataSet::ls(Option_t *option) const 00466 { 00467 ///////////////////////////////////////////////////////////////////// 00468 // // 00469 // ls(Option_t *option) // 00470 // // 00471 // option - defines the path to be listed // 00472 // = "*" - means print all levels // 00473 // // 00474 ///////////////////////////////////////////////////////////////////// 00475 00476 if (option && !strcmp(option,"*")) ls(Int_t(0)); 00477 else { 00478 TDataSet *set = 0; 00479 if (option && strlen(option) > 0) { 00480 TDataSetIter local((TDataSet*)this); 00481 set = local(option); 00482 } else 00483 set = (TDataSet*)this; 00484 if (set) set->ls(Int_t(1)); 00485 else 00486 if (option) Warning("ls","Dataset <%s> not found",option); 00487 } 00488 } 00489 00490 //______________________________________________________________________________ 00491 void TDataSet::ls(Int_t depth) const 00492 { 00493 ///////////////////////////////////////////////////////////////////// 00494 // // 00495 // ls(Int_t depth) // 00496 // // 00497 // Prints the list of the this TDataSet. // 00498 // // 00499 // Parameter: // 00500 // ========= // 00501 // Int_t depth >0 the number of levels to be printed // 00502 // =0 all levels will be printed // 00503 // No par - ls() prints only level out // 00504 // // 00505 ///////////////////////////////////////////////////////////////////// 00506 PrintContents(); 00507 00508 if (!fList || depth == 1 ) return; 00509 if (!depth) depth = 99999; 00510 00511 TIter next(fList); 00512 TDataSet *d=0; 00513 while ((d = (TDataSet *)next())) { 00514 TROOT::IncreaseDirLevel(); 00515 d->ls(depth-1); 00516 TROOT::DecreaseDirLevel(); 00517 } 00518 } 00519 //______________________________________________________________________________ 00520 TDataSet *TDataSet::Instance() const 00521 { 00522 // apply the class default ctor to instantiate a new object of the same kind. 00523 // This is a base method to be overriden by the classes 00524 // derived from TDataSet (to support TDataSetIter::Mkdir for example) 00525 return instance(); 00526 } 00527 00528 //______________________________________________________________________________ 00529 Bool_t TDataSet::IsThisDir(const Char_t *dirname,int len,int ignorecase) const 00530 { 00531 // Compare the name of the TDataSet with "dirname" 00532 // ignorercase flags indicates whether the comparision is case sensitive 00533 00534 if (!ignorecase) { 00535 if (len<0) {return !strcmp (GetName(),dirname); 00536 } else {return !strncmp(GetName(),dirname,len);} 00537 } else { 00538 const char *name = GetName(); 00539 if (len==-1) len = strlen(dirname); 00540 for (int i=0;i<len;i++) { if ( tolower(name[i])!=tolower(dirname[i])) return 0;} 00541 return 1; 00542 } 00543 } 00544 00545 //______________________________________________________________________________ 00546 void TDataSet::MarkAll() 00547 { 00548 // Mark all members of this dataset 00549 Mark(); 00550 TDataSetIter nextMark(this,0); 00551 TDataSet *set = 0; 00552 while ( (set = nextMark()) ) set->Mark(); 00553 } 00554 00555 //______________________________________________________________________________ 00556 void TDataSet::UnMarkAll() 00557 { 00558 // UnMark all members of this dataset 00559 Mark(kMark,kReset); 00560 TDataSetIter nextMark(this,0); 00561 TDataSet *set = 0; 00562 while ( (set = nextMark()) ) set->Mark(kMark,kReset); 00563 } 00564 00565 //______________________________________________________________________________ 00566 void TDataSet::InvertAllMarks() 00567 { 00568 // Invert mark bit for all members of this dataset 00569 if (IsMarked()) Mark(kMark,kReset); 00570 else Mark(); 00571 TDataSetIter nextMark(this,0); 00572 TDataSet *set = 0; 00573 while (( set = nextMark()) ) { 00574 if (set->IsMarked()) set->Mark(kMark,kReset); 00575 else set->Mark(); 00576 } 00577 } 00578 00579 //______________________________________________________________________________ 00580 Bool_t TDataSet::IsEmpty() const 00581 { 00582 // return kTRUE if the "internal" collection has no member 00583 return First() ? kFALSE : kTRUE ; 00584 } 00585 00586 //______________________________________________________________________________ 00587 void TDataSet::PrintContents(Option_t *opt) const { 00588 // Callback method to complete ls() method recursive loop 00589 // This is to allow to sepoarate navigation and the custom invormation 00590 // in the derived classes (see; TTable::PrintContents for example 00591 if (opt) { /* no used */ } 00592 Printf("%3d - %s\t%s\n",TROOT::GetDirLevel(),(const char*)Path(),(char*)GetTitle()); 00593 } 00594 00595 //______________________________________________________________________________ 00596 TString TDataSet::Path() const 00597 { 00598 // return the full path of this data set 00599 TString str; 00600 TDataSet *parent = GetParent(); 00601 if (parent) { 00602 str = parent->Path(); 00603 str += "/"; 00604 } 00605 str += GetName(); 00606 return str; 00607 } 00608 00609 //______________________________________________________________________________ 00610 void TDataSet::Remove(TDataSet *set) 00611 { 00612 // Remiove the "set" from this TDataSet 00613 if (fList && set) { 00614 if (set->GetParent() == this) set->SetParent(0); 00615 fList->Remove(set); 00616 } 00617 00618 } 00619 00620 //______________________________________________________________________________ 00621 TDataSet *TDataSet::RemoveAt(Int_t idx) 00622 { 00623 // 00624 // Remove object from the "idx" cell of this set and return 00625 // the pointer to the removed object if any 00626 // 00627 TDataSet *set = 0; 00628 if (fList) { 00629 set = (TDataSet *)fList->At(idx); 00630 fList->RemoveAt(idx); 00631 if (set && (set->GetParent() == this) ) set->SetParent(0); 00632 } 00633 return set; 00634 } 00635 00636 //______________________________________________________________________________ 00637 TDataSet::EDataSetPass TDataSet::Pass(EDataSetPass ( *callback)(TDataSet *),Int_t depth) 00638 { 00639 ///////////////////////////////////////////////////////////////////// 00640 // // 00641 // Pass (callback,depth) // 00642 // // 00643 // Calls callback(this) for all datasets those recursively // 00644 // // 00645 // Parameter: // 00646 // ========= // 00647 // Int_t depth >0 the number of levels to be passed // 00648 // =0 all levels will be passed // 00649 // // 00650 // Return (this value mast be returned by the user's callback): // 00651 // ====== // 00652 // kContinue - continue passing // 00653 // kPrune - stop passing the current branch, go to the next one// 00654 // kUp - stop passing, leave the current branch, // 00655 // return to previous level and continue // 00656 // kStop - stop passing, leave all braches // 00657 // // 00658 ///////////////////////////////////////////////////////////////////// 00659 00660 if (!callback) return kStop; 00661 00662 EDataSetPass condition = callback(this); 00663 00664 if (condition == kContinue){ 00665 if (fList && depth != 1 ) { 00666 TIter next(fList); 00667 TDataSet *d=0; 00668 while ( (d = (TDataSet *)next()) ) { 00669 condition = d->Pass(callback, depth == 0 ? 0 : --depth); 00670 if (condition == kStop || condition == kUp) break; 00671 } 00672 } 00673 } 00674 return condition==kUp ? kContinue:condition; 00675 } 00676 00677 //______________________________________________________________________________ 00678 TDataSet::EDataSetPass TDataSet::Pass(EDataSetPass ( *callback)(TDataSet *,void*),void *user,Int_t depth) 00679 { 00680 ///////////////////////////////////////////////////////////////////// 00681 // // 00682 // Pass (callback,user,depth) // 00683 // // 00684 // Calls callback(this,user) for all datasets those recursively // 00685 // // 00686 // Parameter: // 00687 // ========= // 00688 // Int_t depth >0 the number of levels to be passed // 00689 // =0 all levels will be passed // 00690 // // 00691 // Return (this value mast be returned by the user's callback): // 00692 // ====== // 00693 // kContinue - continue passing // 00694 // kPrune - stop passing the current branch, go to the next one// 00695 // kUp - stop passing, leave the current branch, // 00696 // return to previous level and continue // 00697 // kStop - stop passing, leave all braches // 00698 // // 00699 ///////////////////////////////////////////////////////////////////// 00700 00701 if (!callback) return kStop; 00702 00703 EDataSetPass condition = callback(this,user); 00704 00705 if (condition == kContinue){ 00706 if (fList && depth != 1 ) { 00707 TIter next(fList); 00708 TDataSet *d=0; 00709 while ((d = (TDataSet *)next())) { 00710 condition = d->Pass(callback, user, depth == 0 ? 0 : --depth); 00711 if (condition == kStop) break; 00712 if (condition == kUp ) break; 00713 } 00714 } 00715 } 00716 return (condition==kUp) ? kContinue:condition; 00717 } 00718 00719 //______________________________________________________________________________ 00720 Int_t TDataSet::Purge(Option_t *) 00721 { 00722 // 00723 // Purge - deletes all "dummy" "Structural Members" those are not ended 00724 // up with some dataset with data inside (those return HasData() = 0) 00725 // 00726 // Purge does affect only the "Structural Members" and doesn't "Associated" ones 00727 // 00728 00729 if (!fList) return 0; 00730 TIter next(fList); 00731 TDataSet *son = 0; 00732 // Purge "Structural Members" only 00733 TList garbage; 00734 while ((son = (TDataSet *)next())) { 00735 if (this == son->GetParent()) continue; 00736 // mark the object is deleted from the TDataSet dtor 00737 son->Purge(); 00738 if (son->HasData() || son->GetListSize()) continue; 00739 delete son; 00740 } 00741 return 0; 00742 } 00743 00744 //______________________________________________________________________________ 00745 void TDataSet::SetParent(TDataSet *parent) 00746 { 00747 // 00748 // Break the "parent" relationship with the current object parent if present 00749 // parent != 0 Makes this object the "Structural Member" 00750 // of the "parent" dataset 00751 // = 0 Makes this object the "pure Associator", i.e it makes this 00752 // object the "Structural Member" of NO other TDataSet 00753 // 00754 fParent = parent; 00755 } 00756 00757 //______________________________________________________________________________ 00758 void TDataSet::SetWrite() 00759 { 00760 // One should not use this method but TDataSet::Write instead 00761 // This method os left here for the sake of the backward compatibility 00762 // To Write object first we should temporary break the 00763 // the backward fParent pointer (otherwise ROOT follows this links 00764 // and will pull fParent out too. 00765 // 00766 Write(); 00767 } 00768 00769 //______________________________________________________________________________ 00770 void TDataSet::Shunt(TDataSet *newParent) 00771 { 00772 // 00773 // Remove the object from the original and add it to dataset 00774 // TDataSet dataset != 0 - Make this object the "Structural Member" 00775 // of "dataset" 00776 // = 0 - Make this object "Orphan" 00777 // 00778 if (fParent) fParent->Remove(this); 00779 if (newParent) newParent->Add(this); 00780 } 00781 00782 //______________________________________________________________________________ 00783 void TDataSet::Update(TDataSet* set,UInt_t opt) 00784 { 00785 // 00786 // Update this TDataSet with "set" 00787 // 00788 // ATTENTION !!! 00789 // --------- 00790 // This method changes the parent relationships of the input "set" 00791 // 00792 if(opt){/*unused*/} 00793 if(!set) return; 00794 00795 SetTitle(set->GetTitle()); 00796 TDataSetIter nextnew(set); 00797 TDataSet *newset = 0; 00798 while((newset = nextnew())) { 00799 Bool_t found = kFALSE; 00800 // Check whether this has the list of the sons 00801 if (fList) { 00802 TIter nextold(fList); 00803 const Char_t *newname = newset->GetName(); 00804 TDataSet *oldset = 0; 00805 while ( ((oldset = (TDataSet *)nextold())!=0) && !found) { 00806 // if the "new" set does contain the dataset 00807 // with the same name as ours update it too 00808 // (We do not update itself (oldset == newset) 00809 if ( (oldset != newset) && oldset->IsThisDir(newname) ) { 00810 oldset->Update(newset); 00811 found = kTRUE; 00812 } 00813 } 00814 } 00815 // If the new "set" contains some new dataset with brand-new name 00816 // move it into the our dataset and remove it from its old location 00817 if (!found) newset->Shunt(this); 00818 } 00819 } 00820 00821 //______________________________________________________________________________ 00822 void TDataSet::Update() 00823 { 00824 // 00825 // Update() 00826 // 00827 // Recursively updates all tables for all nested datasets 00828 // in inverse order 00829 // 00830 00831 TDataSetIter next(this); 00832 TDataSet *set = 0; 00833 while(( set = next())) set->Update(); 00834 } 00835 00836 //______________________________________________________________________________ 00837 void TDataSet::Sort() 00838 { 00839 // Sort recursively all members of the TDataSet with TList::Sort method 00840 TDataSetIter next(this,0); 00841 TDataSet *ds; 00842 TList *list; 00843 while ((ds=next())) { 00844 list = ds->GetList(); 00845 if (!list) continue; 00846 list->Sort(); ds->Sort(); 00847 } 00848 } 00849 00850 //______________________________________________________________________________ 00851 Int_t TDataSet::Write(const char *name, Int_t option, Int_t bufsize) 00852 { 00853 // 00854 // To Write object first we should temporary break the 00855 // the backward fParent pointer (otherwise ROOT follows this links 00856 // and will pull fParent out too. 00857 // 00858 TDataSet *saveParent = fParent; // GetParent(); 00859 fParent = 0; 00860 Int_t nbytes = TObject::Write(name,option, bufsize); 00861 fParent = saveParent; 00862 return nbytes; 00863 } 00864 00865 //______________________________________________________________________________ 00866 Int_t TDataSet::Write(const char *name, Int_t option, Int_t bufsize) const 00867 { 00868 // 00869 // To Write object first we should temporary break the 00870 // the backward fParent pointer (otherwise ROOT follows this links 00871 // and will pull fParent out too. 00872 // 00873 TDataSet *saveParent = fParent; // GetParent(); 00874 const_cast<TDataSet*>(this)->fParent = 0; 00875 Int_t nbytes = TObject::Write(name,option, bufsize); 00876 const_cast<TDataSet*>(this)->fParent = saveParent; 00877 return nbytes; 00878 }