// @(#)root/tree:$Name:  $:$Id: TLeaf.cxx,v 1.18 2006/05/24 15:10:47 brun Exp $
// Author: Rene Brun   12/01/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// A TLeaf describes individual elements of a TBranch                   //
//       See TBranch structure in TTree.                                //
//////////////////////////////////////////////////////////////////////////

#include "TLeaf.h"
#include "TBranch.h"
#include "TTree.h"
#include "TVirtualPad.h"
#include "TBrowser.h"
#include "TClass.h"

#include <ctype.h>

R__EXTERN TTree *gTree;
R__EXTERN TBranch *gBranch;


ClassImp(TLeaf)

//______________________________________________________________________________
TLeaf::TLeaf(): TNamed()
{
//*-*-*-*-*-*Default constructor for Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ============================
   fLen        = 0;
   //fBranch     = 0;
   fBranch     = gBranch;
   fLeafCount  = 0;
   fNdata      = 0;
   fOffset     = 0;
}

//______________________________________________________________________________
TLeaf::TLeaf(const char *name, const char *)
    :TNamed(name,name)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =============
//
//     See the TTree and TBranch constructors for explanation of parameters.

   fBranch     = 0;
   fIsRange    = 0;
   fIsUnsigned = 0;
   fLenType    = 4;
   fNdata      = 0;
   fOffset     = 0;

   fLeafCount  = GetLeafCounter(fLen);

   if (fLen == -1) {
      MakeZombie();
      return;
   }

   if (fLeafCount || strchr(name,'[')) {
      char newname[64];
      strcpy(newname,name);
      char *bracket = strchr(newname,'[');
      *bracket = 0;
      SetName(newname);
   }
   fBranch     = gBranch;
}

//______________________________________________________________________________
TLeaf::TLeaf(const TLeaf& lf) :
  TNamed(lf),
  fNdata(lf.fNdata),
  fLen(lf.fLen),
  fLenType(lf.fLenType),
  fOffset(lf.fOffset),
  fIsRange(lf.fIsRange),
  fIsUnsigned(lf.fIsUnsigned),
  fLeafCount(lf.fLeafCount),
  fBranch(lf.fBranch)
{
   //copy constructor
}

//______________________________________________________________________________
TLeaf& TLeaf::operator=(const TLeaf& lf)
{
   //assignement operator
   if(this!=&lf) {
      TNamed::operator=(lf);
      fNdata=lf.fNdata;
      fLen=lf.fLen;
      fLenType=lf.fLenType;
      fOffset=lf.fOffset;
      fIsRange=lf.fIsRange;
      fIsUnsigned=lf.fIsUnsigned;
      fLeafCount=lf.fLeafCount;
      fBranch=lf.fBranch;
   }
   return *this;
}

//______________________________________________________________________________
TLeaf::~TLeaf()
{
//*-*-*-*-*-*Default destructor for a Leaf*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ===============================

//   if (fBranch) fBranch->GetListOfLeaves().Remove(this);
   if (!fBranch) return;
   TTree *tree = fBranch->GetTree();
   fBranch = 0;
   if (!tree) return;
   tree->GetListOfLeaves()->Remove(this);
}



//______________________________________________________________________________
void TLeaf::Browse(TBrowser *b)
{
   // Browse the content of this leaf.

   char name[64];
   if (strchr(GetName(),'.')) {
      fBranch->GetTree()->Draw(GetName(), "", b ? b->GetDrawOption() : "");
   } else {
      if (fBranch->GetListOfLeaves()->GetEntries()>1 ||
          strcmp(fBranch->GetName(),GetName()) != 0 ) {
         sprintf(name,"%s.%s",fBranch->GetName(),GetName());
         fBranch->GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
      } else {
         fBranch->GetTree()->Draw(GetName(), "", b ? b->GetDrawOption() : "");
      }
   }
   if (gPad) gPad->Update();
}


//______________________________________________________________________________
void TLeaf::FillBasket(TBuffer &)
{
//*-*-*-*-*-*-*-*-*-*-*Pack leaf elements in Basket output buffer*-*-*-*-*-*-*
//*-*                  =========================================

}

//______________________________________________________________________________
TLeaf *TLeaf::GetLeafCounter(Int_t &countval) const
{
//*-*-*-*-*-*-*Return Pointer to counter of referenced Leaf*-*-*-*-*-*-*-*
//*-*          ============================================
//
//  If leaf name has the forme var[nelem], where nelem is alphanumeric, then
//     If nelem is a leaf name, return countval = 1 and the pointer to
//     the leaf named nelem.
//  If leaf name has the forme var[nelem], where nelem is a digit, then
//     return countval = nelem and a null pointer.
//  Otherwise return countval=0 and a null pointer.
//

   countval = 1;
   const char *name = GetTitle();
   char *bleft = (char*)strchr(name,'[');
   if (!bleft) return 0;
   bleft++;
   Int_t nch = strlen(bleft);
   char *countname = new char[nch+1];
   strcpy(countname,bleft);
   char *bright = (char*)strchr(countname,']');
   if (!bright) { delete [] countname; return 0;}
   char *bleft2 = (char*)strchr(countname,'[');
   *bright = 0; nch = strlen(countname);

   // Now search a branch name with a leave name = countname
   // We search for the leaf in the ListOfLeaves from the TTree. We can in principle
   // access the TTree by calling fBranch()->GetTree(), but fBranch is not set if this
   // method is called from the TLeaf constructor. In that case, use global pointer
   // gTree.
   // Also, if fBranch is set, but fBranch->GetTree() returns NULL, use gTree.
   TTree* pTree = fBranch ? fBranch->GetTree() : gTree;
   if (!pTree) pTree = gTree;
   TLeaf *leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
   //if not found, make one more trial in case the leaf name has a "."
   if (!leaf && strchr(GetName(),'.')) {
      char *withdot = new char[1000];
      strcpy(withdot,GetName());
      char *lastdot = strrchr(withdot,'.');
      strcpy(lastdot,countname);
      leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
      delete [] withdot;
   }
   Int_t i;
   if (leaf) {
      countval = 1;
      leaf->SetRange();
      if (bleft2) {
         sscanf(bleft2,"[%d]",&i);
         countval *= i;
      }
      bleft = bleft2;
      while(bleft) {
         bleft2++;
         bleft = (char*)strchr(bleft2,'[');
         if (!bleft) break;
         sscanf(bleft,"[%d]",&i);
         countval *= i;
         bleft2 = bleft;
      }
      delete [] countname;
      return leaf;
   }
   // not found in a branch/leaf. Is it a numerical value?
   for (i=0;i<nch;i++) {
      if (!isdigit(countname[i])) {
         delete [] countname;
         countval = -1;
         return 0;
      }
   }
   sscanf(countname,"%d",&countval);
   if (bleft2) {
      sscanf(bleft2,"[%d]",&i);
      countval *= i;
   }
   bleft = bleft2;
   while(bleft) {
      bleft2++;
      bleft = (char*)strchr(bleft2,'[');
      if (!bleft) break;
      sscanf(bleft,"[%d]",&i);
      countval *= i;
      bleft2 = bleft;
   }

   delete [] countname;
   return 0;
}


//______________________________________________________________________________
Int_t TLeaf::GetLen() const
{
   // Return the number of effective elements of this leaf

   Int_t len;
   if (fLeafCount) {
      len = Int_t(fLeafCount->GetValue());
      if (len > fLeafCount->GetMaximum()) {
         printf("ERROR leaf:%s, len=%d and max=%d\n",GetName(),len,fLeafCount->GetMaximum());
         len = fLeafCount->GetMaximum();
      }
      return len*fLen;
   } else {
      return fLen;
   }
}

//______________________________________________________________________________
Int_t TLeaf::ResetAddress(void *add, Bool_t destructor)
{
   // Set leaf buffer data address
   //
   //  This function is called by all TLeafX::SetAddress

   Int_t todelete = 0;
   if (TestBit(kNewValue)) todelete = 1;
   if (destructor) return todelete;

   if (fLeafCount) fNdata = fLen*(fLeafCount->GetMaximum() + 1);
   else            fNdata = fLen;

   ResetBit(kNewValue);
   if (!add) SetBit(kNewValue);
   return todelete;
}


//_______________________________________________________________________
void TLeaf::SetLeafCount(TLeaf *leaf)
{
   // Set the leaf count of this leaf

   if (IsZombie() && fLen==-1 && leaf) {
      // The constructor noted that it could not find the
      // leafcount. Now that we did find it, let's remove
      // the side-effects
      ResetBit(kZombie);
      fLen = 1;
   }
   fLeafCount=leaf;
}

//_______________________________________________________________________
void TLeaf::Streamer(TBuffer &b)
{
//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              =========================================

   if (b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = b.ReadVersion(&R__s, &R__c);
      if (R__v > 1) {
         TLeaf::Class()->ReadBuffer(b, this, R__v, R__s, R__c);
      } else {
         //====process old versions before automatic schema evolution
         TNamed::Streamer(b);
         b >> fLen;
         b >> fLenType;
         b >> fOffset;
         b >> fIsRange;
         b >> fIsUnsigned;
         b >> fLeafCount;
         b.CheckByteCount(R__s, R__c, TLeaf::IsA());
         //====end of old versions
      }
      if (fLen == 0) fLen = 1;
      ResetBit(kNewValue);
      SetAddress();
   } else {
      TLeaf::Class()->WriteBuffer(b,this);
   }
}


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.