00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "TBranchSTL.h"
00015 #include "TList.h"
00016 #include "TBranchElement.h"
00017 #include "TBasket.h"
00018 #include "TStreamerInfo.h"
00019 #include "TStreamerElement.h"
00020 #include <string>
00021 #include <utility>
00022
00023 #include "TError.h"
00024
00025 ClassImp(TBranchSTL)
00026
00027
00028 TBranchSTL::TBranchSTL():
00029 fCollProxy( 0 ),
00030 fParent( 0 ),
00031 fIndArrayCl( 0 ),
00032 fClassVersion( 0 ),
00033 fClCheckSum( 0 ),
00034 fInfo( 0 ),
00035 fObject( 0 ),
00036 fID( -2 )
00037 {
00038
00039
00040 fIndArrayCl = TClass::GetClass( "TIndArray" );
00041 fBranchVector.reserve( 25 );
00042 fNleaves = 0;
00043 fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00044 }
00045
00046
00047 TBranchSTL::TBranchSTL( TTree *tree, const char *name,
00048 TVirtualCollectionProxy *collProxy,
00049 Int_t buffsize, Int_t splitlevel )
00050 {
00051
00052
00053 fTree = tree;
00054 fCollProxy = collProxy;
00055 fBasketSize = buffsize;
00056 fSplitLevel = splitlevel;
00057 fContName = collProxy->GetCollectionClass()->GetName();
00058 fClCheckSum = 0;
00059 fClassVersion = 1;
00060 fID = -2;
00061 fInfo = 0;
00062 fMother = this;
00063 fParent = 0;
00064 fDirectory = fTree->GetDirectory();
00065 fFileName = "";
00066 SetName( name );
00067 fIndArrayCl = TClass::GetClass( "TIndArray" );
00068 fBranchVector.reserve( 25 );
00069 fNleaves = 0;
00070 fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00071
00072
00073
00074
00075 fBasketBytes = new Int_t[fMaxBaskets];
00076 fBasketEntry = new Long64_t[fMaxBaskets];
00077 fBasketSeek = new Long64_t[fMaxBaskets];
00078
00079 for (Int_t i = 0; i < fMaxBaskets; ++i) {
00080 fBasketBytes[i] = 0;
00081 fBasketEntry[i] = 0;
00082 fBasketSeek[i] = 0;
00083 }
00084
00085 }
00086
00087
00088 TBranchSTL::TBranchSTL( TBranch* parent, const char* name,
00089 TVirtualCollectionProxy* collProxy,
00090 Int_t buffsize, Int_t splitlevel,
00091 TStreamerInfo* info, Int_t id )
00092 {
00093
00094
00095 fTree = parent->GetTree();
00096 fCollProxy = collProxy;
00097 fBasketSize = buffsize;
00098 fSplitLevel = splitlevel;
00099 fContName = collProxy->GetCollectionClass()->GetName();
00100 fClassName = info->GetClass()->GetName();
00101 fClassVersion = info->GetClassVersion();
00102 fClCheckSum = info->GetClass()->GetCheckSum();
00103 fInfo = info;
00104 fID = id;
00105 fMother = parent->GetMother();
00106 fParent = parent;
00107 fDirectory = fTree->GetDirectory();
00108 fFileName = "";
00109 fNleaves = 0;
00110 fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00111
00112 SetName( name );
00113 fIndArrayCl = TClass::GetClass( "TIndArray" );
00114 fBranchVector.reserve( 25 );
00115
00116
00117
00118
00119 fBasketBytes = new Int_t[fMaxBaskets];
00120 fBasketEntry = new Long64_t[fMaxBaskets];
00121 fBasketSeek = new Long64_t[fMaxBaskets];
00122
00123 for (Int_t i = 0; i < fMaxBaskets; ++i) {
00124 fBasketBytes[i] = 0;
00125 fBasketEntry[i] = 0;
00126 fBasketSeek[i] = 0;
00127 }
00128
00129 }
00130
00131
00132 TBranchSTL::~TBranchSTL()
00133 {
00134
00135 BranchMap_t::iterator brIter;
00136 for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter ) {
00137 (*brIter).second.fPointers->clear();
00138 delete (*brIter).second.fPointers;
00139 }
00140 }
00141
00142
00143 void TBranchSTL::Browse( TBrowser *b )
00144 {
00145
00146 Int_t nbranches = fBranches.GetEntriesFast();
00147 if (nbranches > 0) {
00148 TList persistentBranches;
00149 TBranch* branch=0;
00150 TIter iB(&fBranches);
00151 while( (branch = (TBranch*)iB()) )
00152 persistentBranches.Add(branch);
00153 persistentBranches.Browse( b );
00154 }
00155 }
00156
00157
00158 Int_t TBranchSTL::Fill()
00159 {
00160
00161
00162
00163 BranchMap_t::iterator brIter;
00164 for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter )
00165 (*brIter).second.fPointers->clear();
00166
00167
00168
00169
00170 if( fAddress != fObject ) {
00171
00172
00173
00174 if( fObject == 0 ) {
00175 Int_t bytes = 0;
00176 Int_t totalBytes = 0;
00177
00178
00179
00180
00181 fInd.SetNumItems( 0 );
00182 bytes = TBranch::Fill();
00183
00184 if( bytes < 0 ) {
00185 Error( "Fill", "The IO error while writing the indices!");
00186 return -1;
00187 }
00188 totalBytes += bytes;
00189
00190
00191
00192
00193 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00194 TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00195 bytes = br->Fill();
00196 if( bytes < 0 ) {
00197 Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
00198 return -1;
00199 }
00200 totalBytes += bytes;
00201 }
00202 return totalBytes;
00203 }
00204 }
00205
00206
00207
00208
00209 TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
00210 UInt_t size = fCollProxy->Size();
00211
00212
00213
00214
00215 if( fInd.GetCapacity() < size )
00216 fInd.Reserve( size );
00217
00218 fInd.SetNumItems( size );
00219
00220
00221
00222
00223 TClass* cl = fCollProxy->GetValueClass();
00224 TClass* actClass = 0;
00225 TClass* vectClass = 0;
00226 char* element = 0;
00227 std::vector<void*>* elPointers = 0;
00228 TBranchElement* elBranch = 0;
00229 UInt_t elOffset = 0;
00230 UChar_t maxID = fBranches.GetEntriesFast()+1;
00231 UChar_t elID;
00232 ElementBranchHelper_t bHelper;
00233 Int_t totalBytes = 0;
00234 Int_t bytes = 0;
00235 TString brName;
00236
00237 for( UInt_t i = 0; i < size; ++i ) {
00238
00239
00240
00241 element = *(char**)fCollProxy->At( i );
00242 if( !element ) {
00243 fInd.At(i) = 0;
00244 continue;
00245 }
00246
00247
00248 actClass = cl->GetActualClass( element );
00249 brIter = fBranchMap.find( actClass );
00250
00251
00252
00253
00254 if( brIter == fBranchMap.end() ) {
00255
00256
00257
00258 std::string vectClName("vector<");
00259 vectClName += actClass->GetName() + std::string("*>");
00260 vectClass = TClass::GetClass( vectClName.c_str() );
00261 if( !vectClass ) {
00262 Warning( "Fill", "Unable to find dictionary for class %s", vectClName.c_str() );
00263 continue;
00264 }
00265
00266
00267
00268
00269
00270 elPointers = new std::vector<void*>();
00271 brName.Form( "%s.%s", GetName(), actClass->GetName() );
00272 elBranch = new TBranchElement( this, brName,
00273 vectClass->GetCollectionProxy(),
00274 fBasketSize, fSplitLevel-1 );
00275 elID = maxID++;
00276 elBranch->SetFirstEntry( fEntryNumber );
00277
00278
00279 fBranches.Add( elBranch );
00280
00281 bHelper.fId = elID;
00282 bHelper.fBranch = elBranch;
00283 bHelper.fPointers = elPointers;
00284 bHelper.fBaseOffset = actClass->GetBaseClassOffset( cl );
00285
00286 brIter = fBranchMap.insert(std::make_pair(actClass, bHelper ) ).first;
00287 elBranch->SetAddress( &((*brIter).second.fPointers) );
00288 }
00289
00290
00291
00292 else {
00293 elPointers = (*brIter).second.fPointers;
00294 elBranch = (*brIter).second.fBranch;
00295 elID = (*brIter).second.fId;
00296 elOffset = (*brIter).second.fBaseOffset;
00297 }
00298
00299
00300
00301
00302 elPointers->push_back( element + elOffset );
00303 fInd.At(i) = elID;
00304 }
00305
00306
00307
00308
00309 bytes = TBranch::Fill();
00310 if( bytes < 0 ) {
00311 Error( "Fill", "The IO error while writing the indices!");
00312 return -1;
00313 }
00314 totalBytes += bytes;
00315
00316
00317
00318
00319 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00320 TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00321 bytes = br->Fill();
00322 if( bytes < 0 ) {
00323 Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
00324 return -1;
00325 }
00326 totalBytes += bytes;
00327 }
00328
00329 return totalBytes;
00330 }
00331
00332
00333 Int_t TBranchSTL::GetEntry( Long64_t entry, Int_t getall )
00334 {
00335
00336
00337
00338 if( TestBit( kDoNotProcess ) && !getall )
00339 return 0;
00340
00341 if ( (entry < fFirstEntry) || (entry >= fEntryNumber) )
00342 return 0;
00343
00344 if( !fAddress )
00345 return 0;
00346
00347
00348
00349
00350 if( !fCollProxy ) {
00351 TClass *cl = TClass::GetClass( fContName );
00352
00353 if( !cl ) {
00354 Error( "GetEntry", "Dictionary class not found for: %s", fContName.Data() );
00355 return -1;
00356 }
00357
00358 fCollProxy = cl->GetCollectionProxy();
00359 if( !fCollProxy ) {
00360 Error( "GetEntry", "No collection proxy!" );
00361 return -1;
00362 }
00363 }
00364
00365
00366
00367
00368 Int_t totalBytes = 0;
00369 Int_t bytes = TBranch::GetEntry( entry, getall );
00370 totalBytes += bytes;
00371
00372 if( bytes == 0 )
00373 return 0;
00374
00375 if( bytes < 0 ) {
00376 Error( "GetEntry", "IO error! Unable to get the indices!" );
00377 return -1;
00378 }
00379
00380 Int_t size = fInd.GetNumItems();
00381
00382
00383
00384
00385 UInt_t nBranches = fBranches.GetEntriesFast();
00386 TClass* elClass = fCollProxy->GetValueClass();
00387 TClass* tmpClass = 0;
00388
00389 if( fBranchVector.size() < nBranches )
00390 fBranchVector.resize( nBranches );
00391
00392
00393
00394
00395 if( fAddress != fObject ) {
00396 *((void **)fAddress) = fCollProxy->New();
00397 fObject = *(char**)fAddress;
00398 }
00399 TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
00400 void* env = fCollProxy->Allocate( size, kTRUE );
00401
00402
00403
00404
00405 UChar_t index = 0;
00406 void** element = 0;
00407 std::vector<void*>* elemVect = 0;
00408 TBranchElement* elemBranch = 0;
00409
00410 for( Int_t i = 0; i < size; ++i ) {
00411 element = (void**)fCollProxy->At(i);
00412 index = fInd.At(i);
00413
00414
00415
00416
00417 if( index == 0 ) {
00418 *element = 0;
00419 continue;
00420 }
00421
00422
00423
00424
00425 if( index > nBranches ) {
00426 Error( "GetEntry", "Index %d out of range, unable to find the branch, setting pointer to 0",
00427 index );
00428 *element = 0;
00429 continue;
00430 }
00431
00432
00433
00434
00435 index--;
00436 elemVect = fBranchVector[index].fPointers;
00437 if( !elemVect ) {
00438 elemBranch = (TBranchElement *)fBranches.UncheckedAt(index);
00439 elemBranch->SetAddress( &(fBranchVector[index].fPointers) );
00440
00441 bytes = elemBranch->GetEntry( entry, getall );
00442
00443 if( bytes == 0 ) {
00444 Error( "GetEntry", "No entry for index %d, setting pointer to 0", index );
00445 *element = 0;
00446 fBranchVector[index].fPosition++;
00447 continue;
00448 }
00449
00450 if( bytes <= 0 ) {
00451 Error( "GetEntry", "I/O error while getting entry for index %d, setting pointer to 0", index );
00452 *element = 0;
00453 fBranchVector[index].fPosition++;
00454 continue;
00455 }
00456 totalBytes += bytes;
00457 elemVect = fBranchVector[index].fPointers;
00458
00459
00460
00461
00462 TVirtualCollectionProxy *proxy = elemBranch->GetCollectionProxy();
00463 if (!proxy) {
00464 proxy = TClass::GetClass(elemBranch->GetClassName())->GetCollectionProxy();
00465 }
00466 if (proxy) {
00467 tmpClass = proxy->GetValueClass();
00468 if (tmpClass && elClass) {
00469 fBranchVector[index].fBaseOffset = tmpClass->GetBaseClassOffset( elClass );
00470 fBranchVector[index].fPosition = 0;
00471 } else {
00472 Error("GetEntry","Missing TClass for %s (%s)",elemBranch->GetName(),elemBranch->GetClassName());
00473 }
00474 } else {
00475 Error("GetEntry","Missing CollectionProxy for %s (%s)",elemBranch->GetName(),elemBranch->GetClassName());
00476 }
00477 }
00478
00479
00480
00481
00482 *element = ((char*)(*elemVect)[fBranchVector[index].fPosition++])
00483 - fBranchVector[index].fBaseOffset;
00484
00485 }
00486
00487 fCollProxy->Commit(env);
00488
00489
00490
00491
00492 for( UInt_t i = 0; i < fBranchVector.size(); ++i ) {
00493 delete fBranchVector[i].fPointers;
00494 fBranchVector[i].fPointers = 0;
00495 }
00496
00497 return totalBytes;
00498 }
00499
00500
00501 TStreamerInfo* TBranchSTL::GetInfo() const
00502 {
00503
00504
00505
00506 if( !fInfo ) {
00507
00508
00509
00510 TClass *cl = TClass::GetClass( fClassName );
00511
00512
00513
00514
00515 fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
00516
00517
00518
00519
00520 if( fClCheckSum && cl->IsForeign() ) {
00521
00522
00523
00524 Int_t ninfos = cl->GetStreamerInfos()->GetEntriesFast() - 1;
00525 for( Int_t i = -1; i < ninfos; ++i ) {
00526 TVirtualStreamerInfo* info = (TVirtualStreamerInfo*) cl->GetStreamerInfos()->UncheckedAt(i);
00527 if( !info )
00528 continue;
00529
00530
00531
00532
00533 if( info->GetCheckSum() == fClCheckSum ) {
00534 fClassVersion = i;
00535 fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
00536 }
00537 }
00538 }
00539 fInfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00540 fInfo->BuildOld();
00541 }
00542 return fInfo;
00543 }
00544
00545
00546 Bool_t TBranchSTL::IsFolder() const
00547 {
00548
00549
00550 if( fBranches.GetEntriesFast() >= 1 )
00551 return kTRUE;
00552 return kFALSE;
00553 }
00554
00555
00556 void TBranchSTL::FillLeaves( TBuffer& b )
00557 {
00558
00559
00560 b.WriteClassBuffer( fIndArrayCl, &fInd );
00561 }
00562
00563
00564 void TBranchSTL::Print(const char *option) const
00565 {
00566
00567
00568 if (strncmp(option,"debugAddress",strlen("debugAddress"))==0) {
00569 if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
00570 else Printf("%-24s ", GetName());
00571
00572 TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
00573 Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
00574 TVirtualStreamerInfo *info = GetInfo();
00575 Int_t *branchOffset = parent ? parent->GetBranchOffset() : 0;
00576
00577 Printf("%-16s %2d SplitCollPtr %-16s %-16s %8x %-16s n/a\n",
00578 info ? info->GetName() : "StreamerInfo unvailable", fID,
00579 GetClassName(), fParent ? fParent->GetName() : "n/a",
00580 (branchOffset && parent && ind>=0) ? branchOffset[ind] : 0,
00581 fObject);
00582 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00583 TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00584 br->Print("debugAddressSub");
00585 }
00586 } else if (strncmp(option,"debugInfo",strlen("debugInfo"))==0) {
00587 Printf("Branch %s uses:\n",GetName());
00588 if (fID>=0) {
00589 ULong_t* elems = GetInfo()->GetElems();
00590 ((TStreamerElement*) elems[fID])->ls();
00591 }
00592 for (Int_t i = 0; i < fBranches.GetEntriesFast(); ++i) {
00593 TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
00594 subbranch->Print("debugInfoSub");
00595 }
00596 return;
00597 } else {
00598 TBranch::Print(option);
00599 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00600 TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00601 br->Print(option);
00602 }
00603 }
00604 }
00605
00606
00607 void TBranchSTL::ReadLeavesImpl( TBuffer& b )
00608 {
00609
00610
00611 b.ReadClassBuffer( fIndArrayCl, &fInd );
00612 }
00613
00614
00615 void TBranchSTL::SetAddress( void* addr )
00616 {
00617
00618
00619
00620 if( fID < 0 ) {
00621 fAddress = (char*)addr;
00622 fObject = *(char**)addr;
00623 }
00624
00625
00626
00627 else {
00628
00629
00630
00631 GetInfo();
00632 TStreamerElement *el = (TStreamerElement*)fInfo->GetElements()->At( fID );
00633
00634
00635
00636
00637 if( el->IsaPointer() ) {
00638 fAddress = (char*)addr+el->GetOffset();
00639 fObject = *(char**)fAddress;
00640 } else {
00641 fAddress = (char*)addr+el->GetOffset();
00642 fObject = (char*)addr+el->GetOffset();
00643 }
00644 }
00645 }