Containers definition
[u/mrichter/AliRoot.git] / CONTAINERS / AliArrayBranch.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 */
19 #include "TROOT.h"
20 #include "AliArrayBranch.h"
21 #include "TFile.h"
22 #include "TTree.h" 
23 #include "TBasket.h"
24 #include "TClass.h"
25 #include "TRealData.h"
26 #include "TDataType.h"
27 #include "TDataMember.h"
28
29 #include "TBranch.h"
30 #include "TBranchClones.h"
31 #include "TLeaf.h"
32 #include "TLeafB.h"
33 #include "TLeafC.h"
34 #include "TLeafF.h"
35 #include "TLeafD.h"
36 #include "TLeafI.h"
37 #include "TLeafS.h"
38 #include "TLeafObject.h"
39
40 #include "AliObjectArray.h"
41 #include "AliDataType.h"
42
43 //-----------------------------------------------------
44 // A Branch for the case of an array of clone objects. 
45 //-----------------------------------------------------
46
47 //*KEND.
48
49 R__EXTERN TTree *gTree;
50
51 ClassImp(AliArraySubBranch)
52 ClassImp(AliArrayBranch)
53 ClassImp(AliObjectBranch)
54 ClassImp(AliTree)
55
56
57
58 Int_t AliArraySubBranch::GetEntryExport(Int_t entry, Int_t getall, AliObjectArray *list, Int_t nentries)
59 {
60 //*-*-*-*-*-*Read all leaves of entry and return total number of bytes*-*-*
61 //*-* export buffers to real objects in the AliObjectArray list.
62 //*-*
63
64    if (TestBit(kDoNotProcess)) return 0;
65    if (fReadEntry == entry) return 1;
66    if (entry < 0 || entry >= fEntryNumber) return 0;
67    Int_t nbytes;
68    Int_t first  = fBasketEntry[fReadBasket];
69    Int_t last;
70    if (fReadBasket == fWriteBasket) last = fEntryNumber - 1;
71    else                             last = fBasketEntry[fReadBasket+1] - 1;
72 //
73 //      Are we still in the same ReadBasket?
74    if (entry < first || entry > last) {
75       fReadBasket = TMath::BinarySearch(fWriteBasket+1, fBasketEntry, entry);
76       first       = fBasketEntry[fReadBasket];
77    }
78
79 //     We have found the basket containing this entry.
80 //     make sure basket buffers are in memory.
81    TBasket *basket = GetBasket(fReadBasket);
82    if (!basket) return 0;
83    TBuffer *buf    = basket->GetBufferRef();
84 //     Set entry offset in buffer and read data from all leaves
85    if (!buf->IsReading()) {
86       basket->SetReadMode();
87    }
88 //   Int_t bufbegin = basket->GetEntryPointer(entry-first);
89    Int_t bufbegin;
90    Int_t *entryOffset = basket->GetEntryOffset();
91    if (entryOffset) bufbegin = entryOffset[entry-first];
92    else             bufbegin = basket->GetKeylen() + (entry-first)*basket->GetNevBufSize();
93    buf->SetBufferOffset(bufbegin);
94
95    TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
96    //   leaf->ReadBasketExport(*buf,list,nentries);  //!!! MI
97    ReadBasketExport(*buf,leaf, list,nentries);
98    nbytes = buf->Length() - bufbegin;
99    fReadEntry = entry;
100
101    return nbytes;
102 }
103
104 void AliArraySubBranch::ReadBasketExport(TBuffer &b, TLeaf *leaf, AliObjectArray *list, Int_t n)
105 {
106   //
107   // 
108   Int_t len    = leaf->GetLenStatic();
109   Int_t offset = leaf->GetOffset();
110   void *value  = leaf->GetValuePointer();
111
112   //8bit integer
113   if (leaf->IsA()==TLeafB::Class()){   
114     Int_t j = 0;
115     for (Int_t i=0;i<n;i++) {
116       memcpy((char*)list->UncheckedAt(i) + offset,&((Char_t*)value)[j], len);
117       j += len;
118     } 
119   } 
120   //variable length string.
121   if (leaf->IsA()==TLeafC::Class()){  
122     UChar_t len;
123     b >> len;
124     if (len) {
125       if (len >= len) len = len-1;
126       b.ReadFastArray((Char_t*)value,len);
127       ((Char_t*)value)[len] = 0;
128     } else {
129       value = 0;
130     }    
131     Int_t j = 0;
132     for (Int_t i=0;i<n;i++) {
133       memcpy((char*)list->UncheckedAt(i) + offset,&((Char_t*)value)[j], 1);
134       j += len;
135     }
136   }
137   //double
138   if (leaf->IsA()==TLeafD::Class()){   
139     b.ReadFastArray(((Double_t*)value),n*len);    
140     Int_t j = 0;
141     for (Int_t i=0;i<n;i++) {
142       memcpy((char*)list->UncheckedAt(i) + offset,&((Double_t*)value)[j], 8*len);
143       j += len;
144    }
145   }
146   //float
147   if (leaf->IsA()==TLeafF::Class()){   
148     if (n*len == 1) {
149       b >> ((Float_t*)value)[0];
150     } else {
151       b.ReadFastArray(((Float_t*)value),n*len);
152     }
153     
154     Float_t *val = (Float_t*)value;
155     for (Int_t i=0;i<n;i++) {
156       char *first = (char*)list->UncheckedAt(i);
157       Float_t *ff = (Float_t*)&first[offset];
158       for (Int_t j=0;j<len;j++) {
159         ff[j] = val[j];
160       }
161       val += len;
162     }
163     return;
164   }
165   //int2
166   if (leaf->IsA()==TLeafS::Class()){       
167     if (n*len == 1) {
168       b >> ((Short_t*)value)[0];
169     } else {
170       b.ReadFastArray(((Short_t*)value),n*len);
171     }
172     Short_t *val = (Short_t*)value;
173     for (Int_t i=0;i<n;i++) {
174       char *first = (char*)list->UncheckedAt(i);
175       Short_t *ii = (Short_t*)&first[offset];
176       for (Int_t j=0;j<len;j++) {
177         ii[j] = val[j];
178       }
179       val += len;
180     }    
181     return;
182   }     
183   //int4
184   if (leaf->IsA()==TLeafI::Class()){       
185     if (n*len == 1) {
186       b >> ((Int_t*)value)[0];
187     } else {
188       b.ReadFastArray(((Int_t*)value),n*len);
189     }
190     Int_t *val = (Int_t*)value;
191     for (Int_t i=0;i<n;i++) {
192       char *first = (char*)list->UncheckedAt(i);
193       Int_t *ii = (Int_t*)&first[offset];
194       for (Int_t j=0;j<len;j++) {
195         ii[j] = val[j];
196       }
197       val += len;
198     }    
199     return;
200   }      
201 }
202
203
204 //______________________________________________________________________________
205 AliArrayBranch::AliArrayBranch(): TBranch()
206 {
207 //*-*-*-*-*-*Default constructor for BranchClones*-*-*-*-*-*-*-*-*-*
208 //*-*        ====================================
209
210    fList        = 0;
211    fRead        = 0;
212    fN           = 0;
213    fNdataMax    = 0;
214    fBranchCount = 0;
215 }
216
217
218 //______________________________________________________________________________
219 AliArrayBranch::AliArrayBranch(const Text_t *name, void *pointer, TTree * tree,  Int_t basketsize, Int_t compress)
220     :TBranch()
221 {
222 //*-*-*-*-*-*-*-*-*-*-*-*-*Create a BranchClones*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
223 //*-*                      =====================
224 //
225    char leaflist[80];
226    char branchname[80];
227    char branchcount[64];
228    fTree       = tree;
229    gTree       = tree; // MI because some bug in ROOT I didn't obtain proper gTree
230    // it is necesary to set gTree because oder subranchces  defined below need it
231    SetName(name);
232    if (compress == -1) {
233       TFile *bfile = fTree->GetDirectory()->GetFile();
234       if (bfile) compress = bfile->GetCompressionLevel();
235    }
236    char *cpointer  = (char*)pointer;
237    char **ppointer = (char**)(cpointer);
238    fList     = (AliObjectArray*)(*ppointer);
239    fAddress  = cpointer;
240    fRead     = 0;
241    fN        = 0;
242    fNdataMax = 0;
243
244    AliClassInfo *clinfo = fList->GetClassInfo();
245    if (!clinfo) return;
246    fClassName = clinfo->GetName();   
247    
248 //*-*- Create a branch to store the array count
249    if (basketsize < 100) basketsize = 100;
250    sprintf(leaflist,"%s_/I",name);
251    sprintf(branchcount,"%s_",name);
252    fBranchCount = new TBranch(branchcount,&fN,leaflist,basketsize);
253    fBranchCount->SetBit(kIsClone);
254    TLeaf *leafcount = (TLeaf*)fBranchCount->GetListOfLeaves()->UncheckedAt(0);
255
256 //*-*-  Create the first basket
257
258    fDirectory  = fTree->GetDirectory();
259    fFileName   = "";
260
261    TBasket *basket = new TBasket(branchcount,fTree->GetName(),this);
262    fBaskets.Add(basket);
263
264 //*-*- Loop on all public data members of the class and its base classes
265
266    TClass *cl = fList->GetClass();
267    if (cl){
268      if (!cl->GetListOfRealData())  cl->BuildRealData();
269      
270      const char *itype = 0;
271      TRealData *rd;
272      TIter      next(cl->GetListOfRealData());
273      while ((rd = (TRealData *) next())) {
274        TDataMember *member = rd->GetDataMember();
275        if (!member->IsBasic()) {
276          Warning("BranchClones","Cannot process member:%s",member->GetName());
277          continue;
278        }
279        if (!member->IsPersistent()) continue; //do not process members with a ! as the first
280        // character in the comment field
281        TDataType *membertype = member->GetDataType();
282        Int_t type = membertype->GetType();
283        if (type == 0) {
284          Warning("BranchClones","Cannot process member:%s",member->GetName());
285          continue;
286        }
287        if (type == 1)  itype = "B";
288        if (type == 11) itype = "b";
289        if (type == 3)  itype = "I";
290        if (type == 5)  itype = "F";
291        if (type == 8)  itype = "D";
292        if (type == 13) itype = "i";
293        if (type == 2)  itype = "S";
294        if (type == 12) itype = "s";
295        
296        
297        Int_t arraydim = member->GetArrayDim();
298        if (arraydim!=1){
299          //   OLD Version 
300          sprintf(leaflist,"%s[%s]/%s",member->GetName(),branchcount,itype);
301          Int_t comp = compress;
302          if (type == 5) comp--;
303          sprintf(branchname,"%s.%s",name,rd->GetName());
304          TBranch *branch  = new AliArraySubBranch(branchname,this,leaflist,basketsize,comp);
305          branch->SetBit(kIsClone);
306          TObjArray *leaves = branch->GetListOfLeaves();
307          TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
308          leaf->SetOffset(rd->GetThisOffset());
309          leaf->SetLeafCount(leafcount);
310          Int_t arraydim = member->GetArrayDim();
311          if (arraydim) {
312            Int_t maxindex = member->GetMaxIndex(arraydim-1);
313            leaf->SetLen(maxindex);
314          }
315          fBranches.Add(branch);
316        }
317        else
318          for (Int_t i=0;i< member->GetMaxIndex(0);i++){
319            const char * dmname = member->GetName() ;
320            char  bname[200];
321            Int_t j=0;
322            while ( (dmname[j]!='[') && (dmname[j]!=0) ){
323              bname[j]=dmname[j];
324              j++;
325            }
326            bname[j]=0;
327            sprintf(leaflist,"%s(%d)[%s]/%s",bname,i,branchcount,itype);
328            Int_t comp = compress;
329            if (type == 5) comp--;
330            sprintf(branchname,"%s.%s(%d)",name,bname,i);
331            TBranch *branch  = new AliArraySubBranch(branchname,this,leaflist,basketsize,comp);
332            branch->SetBit(kIsClone);
333            TObjArray *leaves = branch->GetListOfLeaves();
334            TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
335            leaf->SetOffset(rd->GetThisOffset()+membertype->Size()*i);
336            leaf->SetLeafCount(leafcount);
337            fBranches.Add(branch);
338          }                
339        
340      }     
341    }
342    else if (clinfo->IsA()->InheritsFrom("AliDataType")){ //branch for basic type
343      Int_t type = (((AliDataType*)clinfo)->GetDataType())->GetType();
344      char *itype = 0;
345      if (type <=0) 
346        Warning("BranchClones","Cannot process member:%s",clinfo->GetName());       
347      else{
348      
349        if (type == 1)  itype = "B";
350        if (type == 11) itype = "b";
351        if (type == 3)  itype = "I";
352        if (type == 5)  itype = "F";
353        if (type == 8)  itype = "D";
354        if (type == 13) itype = "i";
355        if (type == 2)  itype = "S";
356        if (type == 12) itype = "s";
357        sprintf(leaflist,"%s[%s]/%s",name,branchcount,itype);
358        Int_t comp = compress;
359        if (type == 5) comp--;
360        sprintf(branchname,"%s",clinfo->GetName());       
361        TBranch *branch  = new AliArraySubBranch(branchname,this,leaflist,basketsize,comp);
362        branch->SetBit(kIsClone);
363        TObjArray *leaves = branch->GetListOfLeaves();
364        TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
365        leaf->SetOffset(0);
366        leaf->SetLeafCount(leafcount);
367        fBranches.Add(branch);  
368      }
369    }
370
371 }
372
373
374 //______________________________________________________________________________
375 AliArrayBranch::~AliArrayBranch()
376 {
377 //*-*-*-*-*-*Default destructor for a BranchClones*-*-*-*-*-*-*-*-*-*-*-*
378 //*-*        =====================================
379
380    delete fBranchCount;
381    fBranchCount = 0;
382    fBranches.Delete();
383    fList = 0;
384 }
385
386
387 //______________________________________________________________________________
388 void AliArrayBranch::Browse(TBrowser *b)
389 {
390    fBranches.Browse( b );
391 }
392
393 //______________________________________________________________________________
394 Int_t AliArrayBranch::Fill()
395 {
396 //*-*-*-*-*Loop on all Branches of this BranchClones to fill Basket buffer*-*
397 //*-*      ===============================================================
398
399    Int_t i;
400    Int_t nbytes = 0;
401    Int_t nbranches = fBranches.GetEntriesFast();
402    char **ppointer = (char**)(fAddress);
403    if (ppointer == 0) return 0;
404    fList = (AliObjectArray*)(*ppointer);
405    //   fN    = fList->GetEntriesFast();
406    fN    = fList->GetSize();
407    fEntries++;
408
409    if (fN > fNdataMax) {
410       fNdataMax = fList->GetSize();
411       char branchcount[64];
412       sprintf(branchcount,"%s_",GetName());
413       TLeafI *leafi = (TLeafI*)fBranchCount->GetLeaf(branchcount);
414       leafi->SetMaximum(fNdataMax);
415       for (i=0;i<nbranches;i++)  {
416          TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
417          TObjArray *leaves = branch->GetListOfLeaves();
418          TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
419          leaf->SetAddress();
420       }
421    }
422    nbytes += fBranchCount->Fill();
423    for (i=0;i<nbranches;i++)  {
424       TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
425       TObjArray *leaves = branch->GetListOfLeaves();
426       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
427       // leaf->Import(fList, fN);   // MI
428       Import(leaf,fN);              // MI change
429       nbytes += branch->Fill();
430    }
431    return nbytes;
432 }
433
434 //______________________________________________________________________________
435 Int_t AliArrayBranch::GetEntry(Int_t entry, Int_t getall)
436 {
437 //*-*-*-*-*Read all branches of a BranchClones and return total number of bytes
438 //*-*      ====================================================================
439
440    if (TestBit(kDoNotProcess) && !getall) return 0;
441    Int_t nbytes = fBranchCount->GetEntry(entry);
442    TLeaf *leafcount = (TLeaf*)fBranchCount->GetListOfLeaves()->UncheckedAt(0);
443    fN = Int_t(leafcount->GetValue());
444    if (fN <= 0) return 0;
445
446    TBranch *branch;
447    Int_t nbranches = fBranches.GetEntriesFast();
448
449      // if fList exists, create clonesarray objects
450    if (fList) {
451      //fList->ExpandCreateFast(fN);   //MI  
452      fList->Resize(fN);    //MI change 
453      for (Int_t i=0;i<nbranches;i++)  {
454        branch = (TBranch*)fBranches.UncheckedAt(i);  
455        nbytes += ((AliArraySubBranch*)branch)->GetEntryExport(entry, getall, fList, fN);  // !!!MI
456       }
457    } else {
458       for (Int_t i=0;i<nbranches;i++)  {
459          branch = (TBranch*)fBranches.UncheckedAt(i);
460          nbytes += branch->GetEntry(entry, getall);
461       }
462    }
463   return nbytes;
464 }
465
466 //______________________________________________________________________________
467 void AliArrayBranch::Print(Option_t *option)
468 {
469 //*-*-*-*-*-*-*-*-*-*-*-*Print TBranch parameters*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
470 //*-*                    ========================
471
472    fBranchCount->Print(option);
473    Int_t i;
474    Int_t nbranches = fBranches.GetEntriesFast();
475    for (i=0;i<nbranches;i++)  {
476       TBranch *branch = (TBranch*)fBranches[i];
477       branch->Print(option);
478    }
479 }
480
481 //______________________________________________________________________________
482 void AliArrayBranch::Reset(Option_t *option)
483 {
484 //*-*-*-*-*-*-*-*Reset a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
485 //*-*            ====================
486 //
487 //    Existing buffers are deleted
488 //    Entries, max and min are reset
489 //
490
491    fEntries        = 0;
492    fTotBytes       = 0;
493    fZipBytes       = 0;
494    Int_t i;
495    Int_t nbranches = fBranches.GetEntriesFast();
496    for (i=0;i<nbranches;i++)  {
497       TBranch *branch = (TBranch*)fBranches[i];
498       branch->Reset(option);
499    }
500    fBranchCount->Reset();
501
502
503 //______________________________________________________________________________
504 void  AliArrayBranch::SetAddress(void *add)  
505 {
506 //*-*-*-*-*-*-*-*Set address of this branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
507 //*-*            ====================
508 //*-*
509
510    fReadEntry = -1;
511    fAddress = (char*)add;
512    char **ppointer = (char**)(fAddress);
513    if ( (*ppointer)==0 ) {  //MI change 
514      *ppointer = (char*) new AliObjectArray(fClassName);
515      fAddress = (char*)ppointer;
516    }
517    fList = (AliObjectArray*)(*ppointer);
518    fBranchCount->SetAddress(&fN);
519
520 }
521
522 //______________________________________________________________________________
523 void AliArrayBranch::SetBasketSize(Int_t buffsize)
524 {
525 //*-*-*-*-*-*-*-*Reset basket size for all subbranches of this branchclones
526 //*-*            ==========================================================
527 //
528
529    fBasketSize = buffsize;
530    Int_t i;
531    Int_t nbranches = fBranches.GetEntriesFast();
532    for (i=0;i<nbranches;i++)  {
533       TBranch *branch = (TBranch*)fBranches[i];
534       branch->SetBasketSize(buffsize);
535    }
536 }
537
538 //_______________________________________________________________________
539 void AliArrayBranch::Streamer(TBuffer &b)
540 {
541 //*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
542 //*-*              =========================================
543    if (b.IsReading()) {
544       b.ReadVersion();  //Version_t v = b.ReadVersion();
545       TNamed::Streamer(b);
546       b >> fCompress;
547       b >> fBasketSize;
548       b >> fEntryOffsetLen;
549       b >> fMaxBaskets;
550       b >> fWriteBasket;
551       b >> fEntryNumber;
552       b >> fEntries;
553       b >> fTotBytes;
554       b >> fZipBytes;
555       b >> fOffset;
556       b >> fBranchCount;
557       fClassName.Streamer(b);
558       fBranches.Streamer(b);
559       fTree = gTree;
560       TBranch *branch;
561       TLeaf *leaf;
562       Int_t nbranches = fBranches.GetEntriesFast();
563       for (Int_t i=0;i<nbranches;i++)  {
564          branch = (TBranch*)fBranches[i];
565          branch->SetBit(kIsClone);
566          leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(0);
567          leaf->SetOffset(0);
568       }
569       fRead = 1;
570
571       AliClassInfo *clinfo = AliClassInfo::FindClassInfo(fClassName);
572       if (!clinfo) {
573         AliObjectArray tmp(fClassName); 
574         //MI change - object array to construct class description
575         clinfo = AliClassInfo::FindClassInfo(fClassName);
576       }
577       if (!clinfo) return;
578       
579       TClass *cl = clinfo->GetClass();
580       //      if (!cl) {
581       //   Warning("Streamer","Unknow class: %s. Cannot read BranchClones: %s",
582       //      fClassName.Data(),GetName());
583       //   return;
584       //}
585       if (cl){
586
587         if (!cl->GetListOfRealData())  cl->BuildRealData();
588         char branchname[80];
589         TRealData *rd;
590         TIter      next(cl->GetListOfRealData());
591         while ((rd = (TRealData *) next())) {
592           TDataMember *member = rd->GetDataMember();
593           if (!member->IsBasic())      continue;
594           if (!member->IsPersistent()) continue;
595           TDataType *membertype = member->GetDataType();
596           if (membertype->GetType() == 0) continue; 
597          //MI change - for array spliting
598           Int_t arraydim = member->GetArrayDim();
599           if (arraydim==1){
600             for (Int_t i=0;i< member->GetMaxIndex(0);i++){
601               const char * dmname = member->GetName() ;
602               char  bname[200];
603               Int_t j=0;
604               while ( (dmname[j]!='[') && (dmname[j]!=0) ){
605                 bname[j]=dmname[j];
606                 j++;
607               }
608               bname[j]=0;
609               sprintf(branchname,"%s.%s(%d)",GetName(),bname,i);
610               branch  = (TBranch*)fBranches.FindObject(branchname);
611               if (!branch) continue;
612               TObjArray *leaves = branch->GetListOfLeaves();
613               leaf = (TLeaf*)leaves->UncheckedAt(0);
614               leaf->SetOffset(rd->GetThisOffset()+membertype->Size()*i);
615             }
616           }
617           sprintf(branchname,"%s.%s",GetName(),rd->GetName());
618           branch  = (TBranch*)fBranches.FindObject(branchname);
619           if (!branch) continue;
620           TObjArray *leaves = branch->GetListOfLeaves();
621           leaf = (TLeaf*)leaves->UncheckedAt(0);
622           leaf->SetOffset(rd->GetThisOffset());         
623         }
624
625       }
626       else if (clinfo->IsA()->InheritsFrom("AliDataType")){ //branch for basic type
627         char branchname[100];
628         sprintf(branchname,"%s",clinfo->GetName());  
629         branch  = (TBranch*)fBranches.FindObject(branchname);
630         if (branch){
631           TObjArray *leaves = branch->GetListOfLeaves();
632           leaf = (TLeaf*)leaves->UncheckedAt(0);
633           leaf->SetOffset(0);
634         }   
635       }
636    }
637    else{
638         
639       b.WriteVersion(AliArrayBranch::IsA());
640       TNamed::Streamer(b);
641       b << fCompress;
642       b << fBasketSize;
643       b << fEntryOffsetLen;
644       b << fMaxBaskets;
645       b << fWriteBasket;
646       b << fEntryNumber;
647       b << fEntries;
648       b << fTotBytes;
649       b << fZipBytes;
650       b << fOffset;
651       b << fBranchCount;
652       fClassName.Streamer(b);
653       fBranches.Streamer(b);
654    }
655 }
656
657
658
659 void AliArrayBranch::Import(TLeaf * leaf, Int_t n)
660 {
661
662   const Int_t kIntUndefined = -9999;
663   Int_t j = 0;
664   char *clone;
665   Int_t len    = leaf->GetLenStatic();
666   Int_t fOffset = leaf->GetOffset();
667   void *value  = leaf->GetValuePointer();
668   //
669   for (Int_t i=0;i<n;i++) {
670     clone = (char*)fList->UncheckedAt(i);
671     //8bit int
672     if (leaf->IsA()==TLeafB::Class()){  
673       memcpy(&((Char_t*)value)[j],clone + fOffset, len);
674     }
675     //var size
676     if (leaf->IsA()==TLeafC::Class()){  
677       memcpy(&((Char_t*)value)[j],clone + fOffset, 1);
678     }
679     //double
680     if (leaf->IsA()==TLeafD::Class()){  
681       if (clone) memcpy(&((Double_t*)value)[j],clone + fOffset, 8*len);
682       else       memcpy(&((Double_t*)value)[j],&kIntUndefined,  8*len);      
683     }
684     //float
685     if (leaf->IsA()==TLeafF::Class()){   
686       if (clone) memcpy(&((Float_t*)value)[j],clone + fOffset, 4*len);
687       else       memcpy(&((Float_t*)value)[j],&kIntUndefined,  4*len);     
688     }    
689     //int
690     if (leaf->IsA()==TLeafI::Class()){  
691       if (clone) memcpy(&((Int_t*)value)[j],clone + fOffset, 4*len);
692       else       memcpy(&((Int_t*)value)[j],&kIntUndefined,  4*len);
693     }
694    //short
695     if (leaf->IsA()==TLeafS::Class()){  
696       if (clone) memcpy(&((Short_t*)value)[j],clone + fOffset, 2*len);
697       else       memcpy(&((Short_t*)value)[j],&kIntUndefined,  2*len);
698     }     
699     j += len;  
700   }
701   //
702 }
703
704 AliObjectBranch::AliObjectBranch(const Text_t *name, const Text_t *classname, void *addobj,
705                                  TTree * tree, 
706                                  Int_t basketsize, Int_t splitlevel, Int_t compress): TBranchObject()
707 {
708 //*-*-*-*-*-*-*-*-*-*-*-*-*Create a BranchObject*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
709 //*-*                      =====================
710 //
711    TClass *cl      = gROOT->GetClass(classname);
712    fTree =tree;  //MI change
713    if (!cl) {
714       Error("TBranchObject","Cannot find class:%s",classname);
715       return;
716    }
717    if (!cl->GetListOfRealData())  cl->BuildRealData();
718    Int_t bufsize=basketsize; //MI ?
719    SetName(name);
720    SetTitle(name);
721    fCompress = compress;
722    if (compress == -1) {
723      TFile *bfile = fTree->GetDirectory()->GetFile(); //MI chnge fTrre - gTree
724       if (bfile) fCompress = bfile->GetCompressionLevel();
725    }
726    if (basketsize < 100) basketsize = 100;
727    fBasketSize     = basketsize;
728    fAddress        = (char*)addobj;
729    fClassName      = classname;
730    fBasketEntry    = new Int_t[fMaxBaskets];
731    fBasketBytes    = new Int_t[fMaxBaskets];
732    fBasketSeek     = new Seek_t[fMaxBaskets];
733    fOldObject      = 0;
734
735    fBasketEntry[0] = fEntryNumber;
736    fBasketBytes[0] = 0;
737
738    TLeaf *leaf     = new TLeafObject(name,classname);
739    leaf->SetBranch(this);
740    leaf->SetAddress(addobj);
741    fNleaves = 1;
742    fLeaves.Add(leaf);
743    fTree->GetListOfLeaves()->Add(leaf);  //MI change fTree-gTree
744
745 // Set the bit kAutoDelete to specify that when reading
746 // in TLeafObject::ReadBasket, the object should be deleted
747 // before calling Streamer.
748 // It is foreseen to not set this bit in a future version.
749    SetAutoDelete(kTRUE);
750
751 //*-*-  Create the first basket
752    //   fTree       = gTree;  //MI change - no need anymore 
753    fDirectory  = fTree->GetDirectory();
754    fFileName   = "";
755
756    if (!splitlevel){
757      TBasket *basket = new TBasket(name,fTree->GetName(),this);
758      fBaskets.Add(basket);
759      return;
760    }
761
762    //
763    // 
764    TBranch * branch =this;
765    TObjArray *blist = branch->GetListOfBranches();
766    const char *rdname;
767    const char *dname;
768    char branchname[64];
769    if (!cl->GetListOfRealData()) cl->BuildRealData();
770    char **apointer = (char**)(addobj);
771    TObject *obj = (TObject*)(*apointer);
772    Bool_t delobj = kFALSE;
773    if (!obj) {
774       obj = (TObject*)cl->New();
775       delobj = kTRUE;
776    }
777 //*-*- Loop on all public data members of the class and its base classes
778    Int_t lenName = strlen(name);
779    Int_t isDot = 0;
780    if (name[lenName-1] == '.') isDot = 1;
781    TBranch *branch1 = 0;
782    TRealData *rd;
783    TIter      next(cl->GetListOfRealData());
784    while ((rd = (TRealData *) next())) {
785       TDataMember *dm = rd->GetDataMember();
786       if (!dm->IsPersistent()) continue; //do not process members with a ! as the first
787                                          // character in the comment field
788       rdname = rd->GetName();
789       dname  = dm->GetName();
790
791   //  Next line now commented, functionality to process arrays is now implemented
792   //  the statement is left to show how to use Property() and kIsArray
793   //     if (dm->Property() & kIsArray) continue;
794
795       TDataType *dtype = dm->GetDataType();
796       Int_t code = 0;
797       if (dtype) code = dm->GetDataType()->GetType();
798
799 //*-*- Encode branch name. Use real data member name
800       sprintf(branchname,"%s",rdname);
801       if (isDot) {
802          if (dm->IsaPointer()) sprintf(branchname,"%s%s",name,&rdname[1]);
803          else                  sprintf(branchname,"%s%s",name,&rdname[0]);
804       }
805       char leaflist[64];
806       Int_t offset    = rd->GetThisOffset();
807       char *pointer   = (char*)obj + offset;
808       if (dm->IsaPointer()) {
809          TClass *clobj = 0;
810          if (!dm->IsBasic()) clobj = gROOT->GetClass(dm->GetTypeName());
811          if (clobj && !strcmp("TClonesArray",clobj->GetName())) {
812             char *cpointer  =(char*)pointer;
813             char **ppointer =(char**)cpointer;
814             TClonesArray *list = (TClonesArray*)(*ppointer);
815             if (splitlevel != 2) {
816                if (isDot) branch1 = new TBranchClones(&branchname[0],pointer,bufsize);
817                else       branch1 = new TBranchClones(&branchname[1],pointer,bufsize);
818                blist->Add(branch1);
819             } else {
820                if (isDot) branch1 = new TBranchObject(&branchname[0],list->ClassName(),pointer,bufsize);
821                else       branch1 = new TBranchObject(&branchname[1],list->ClassName(),pointer,bufsize);
822                blist->Add(branch1);
823             }
824          }
825          else
826            if (clobj && !strcmp("AliObjectArray",clobj->GetName())) {
827              char *cpointer  =(char*)pointer;
828              char **ppointer =(char**)cpointer;
829              TClonesArray *list = (TClonesArray*)(*ppointer);
830              if (splitlevel != 2) {
831                if (isDot) branch1 = new AliArrayBranch(&branchname[0],pointer,fTree,bufsize,compress);
832                else       branch1 = new AliArrayBranch(&branchname[1],pointer,fTree,bufsize,compress);
833                blist->Add(branch1);
834              } else {
835                if (isDot) branch1 = new AliObjectBranch(&branchname[0],list->ClassName(),pointer,fTree,bufsize);
836                else       branch1 = new AliObjectBranch(&branchname[1],list->ClassName(),pointer,fTree,bufsize);
837                blist->Add(branch1);
838              }
839            }
840            else {
841              if (!clobj) {
842                if (code != 1) continue;
843                sprintf(leaflist,"%s/%s",dname,"C");
844                branch1 = new TBranch(branchname,pointer,leaflist,bufsize);
845                branch1->SetTitle(dname);
846                blist->Add(branch1);
847              } else {
848                if (!clobj->InheritsFrom(TObject::Class())) continue;
849                //branch1 = new TBranchObject(dname,clobj->GetName(),pointer,bufsize,0); //MI change
850                branch1 = new AliObjectBranch(dname,clobj->GetName(),pointer,fTree,bufsize,splitlevel);
851                if (isDot) branch1->SetName(&branchname[0]);
852                else       branch1->SetName(&branchname[1]);  //do not use the first character (*)
853                blist->Add(branch1);
854              }
855            }
856       }else {
857 //*-*-------------Data Member is a basic data type----------
858         if (dm->IsBasic()) {
859           if      (code ==  1) sprintf(leaflist,"%s/%s",rdname,"B");
860           else if (code == 11) sprintf(leaflist,"%s/%s",rdname,"b");
861           else if (code ==  2) sprintf(leaflist,"%s/%s",rdname,"S");
862           else if (code == 12) sprintf(leaflist,"%s/%s",rdname,"s");
863           else if (code ==  3) sprintf(leaflist,"%s/%s",rdname,"I");
864           else if (code == 13) sprintf(leaflist,"%s/%s",rdname,"i");
865           else if (code ==  5) sprintf(leaflist,"%s/%s",rdname,"F");
866           else if (code ==  8) sprintf(leaflist,"%s/%s",rdname,"D");
867           else {
868             printf("Cannot create branch for rdname=%s, code=%d\n",branchname, code);
869             leaflist[0] = 0;
870           }
871           branch1 = new TBranch(branchname,pointer,leaflist,bufsize);
872           branch1->SetTitle(rdname);
873           blist->Add(branch1);
874         }
875       }
876       if (branch1) branch1->SetOffset(offset);
877       else Warning("Branch","Cannot process member:%s",rdname);      
878    }
879    if (delobj) delete obj;
880 }
881
882
883
884 //______________________________________________________________________________
885 void AliObjectBranch::SetAddress(void *add)
886 {
887 //*-*-*-*-*-*-*-*Set address of this branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
888 //*-*            ====================
889 //
890
891    //special case when called from code generated by TTree::MakeClass
892    if (Long_t(add) == -1) {
893       SetBit(kWarn);
894       return;
895    }
896    fReadEntry = -1;
897    Int_t nbranches = fBranches.GetEntriesFast();
898    TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
899    if (leaf) leaf->SetAddress(add);
900    TBranch *branch;
901    fAddress = (char*)add;
902    char *pointer   = fAddress;
903    void **ppointer = (void**)add;
904    TObject *obj = (TObject*)(*ppointer);
905    TClass *cl = gROOT->GetClass(fClassName.Data());
906    if (!obj && cl) {
907       obj = (TObject*)cl->New();
908       *ppointer = (void*)obj;
909    }
910    Int_t i, offset;
911    if (!cl) {
912       for (i=0;i<nbranches;i++)  {
913          branch  = (TBranch*)fBranches[i];
914          pointer = (char*)obj;
915          branch->SetAddress(pointer);
916       }
917       return;
918    }
919    if (!cl->GetListOfRealData())  cl->BuildRealData();
920    char *fullname = new char[200];
921    const char *bname = GetName();
922    Int_t lenName = strlen(bname);
923    Int_t isDot = 0;
924    if (bname[lenName-1] == '.') isDot = 1;
925    const char *rdname;
926    TRealData *rd;
927    TIter      next(cl->GetListOfRealData());
928    while ((rd = (TRealData *) next())) {
929       TDataMember *dm = rd->GetDataMember();
930       if (!dm->IsPersistent()) continue;
931       rdname = rd->GetName();
932       TDataType *dtype = dm->GetDataType();
933       Int_t code = 0;
934       if (dtype) code = dm->GetDataType()->GetType();
935       offset  = rd->GetThisOffset();
936       pointer = (char*)obj + offset;
937       branch  = 0;
938       if (dm->IsaPointer()) {
939          TClass *clobj = 0;
940          if (!dm->IsBasic()) clobj = gROOT->GetClass(dm->GetTypeName());
941          if (clobj && !strcmp("TClonesArray",clobj->GetName())) {
942             if (isDot) sprintf(fullname,"%s%s",bname,&rdname[1]);
943             else       sprintf(fullname,"%s",&rdname[1]);
944             branch = (TBranch*)fBranches.FindObject(fullname);
945          }
946          else
947            if (clobj && !strcmp("AliObjectArray",clobj->GetName())) {
948              if (isDot) sprintf(fullname,"%s%s",bname,&rdname[1]);
949              else       sprintf(fullname,"%s",&rdname[1]);
950              branch = (TBranch*)fBranches.FindObject(fullname);
951            }
952          else {
953             if (!clobj) {
954                if (code != 1) continue;
955                if (isDot) sprintf(fullname,"%s%s",bname,&rdname[0]);
956                else       sprintf(fullname,"%s",&rdname[0]);
957                branch = (TBranch*)fBranches.FindObject(fullname);
958             } else {
959                if (!clobj->InheritsFrom(TObject::Class())) continue;
960                if (isDot) sprintf(fullname,"%s%s",bname,&rdname[1]);
961                else       sprintf(fullname,"%s",&rdname[1]);
962                branch = (TBranch*)fBranches.FindObject(fullname);
963             }
964          }
965       } else {
966          if (dm->IsBasic()) {
967             if (isDot) sprintf(fullname,"%s%s",bname,&rdname[0]);
968             else       sprintf(fullname,"%s",&rdname[0]);
969             branch = (TBranch*)fBranches.FindObject(fullname);
970          }
971       }
972       if(branch) branch->SetAddress(pointer);
973    }
974    delete [] fullname;
975 }
976
977
978
979
980
981 AliTree::AliTree(const char *name,const char *title, Int_t maxvirtualsize):
982   TTree(name,title,maxvirtualsize)
983 {
984   //
985   //default constructor for AliTree
986   gTree =this;
987 }
988
989 TBranch * AliTree::AliBranch(const char *name, void *clonesaddress, Int_t bufsize, Int_t splitlevel,
990                              Int_t compres)
991 {
992   if (clonesaddress == 0) return 0;
993   char *cpointer =(char*)clonesaddress;
994   char **ppointer =(char**)cpointer;
995   AliObjectArray *list = (AliObjectArray*)(*ppointer);
996   if (list == 0) return 0;
997   gTree = this;
998   if (splitlevel) {
999     TBranch *branch = new AliArrayBranch(name,clonesaddress,this,bufsize, compres);
1000     fBranches.Add(branch);
1001     return branch;
1002   } else {
1003     TBranchObject *branch = new TBranchObject(name,list->ClassName(),clonesaddress,bufsize,0);
1004     fBranches.Add(branch);
1005     return branch;
1006   }
1007 }
1008
1009 TBranch* AliTree::AliBranch(const char *name, const char *classname, void *addobj, 
1010                      Int_t bufsize, Int_t splitlevel)
1011 {
1012   gTree = this;
1013   TClass *cl = gROOT->GetClass(classname);
1014   if (!cl) {
1015     Error("BranchObject","Cannot find class:%s",classname);
1016     return 0;
1017   }
1018   TBranch * branch = new AliObjectBranch(name,classname,addobj, this, bufsize,splitlevel);
1019   fBranches.Add(branch);
1020   return branch;
1021 }
1022
1023