// @(#)root/tree:$Id$
// 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>

ClassImp(TLeaf)

//______________________________________________________________________________
TLeaf::TLeaf()
   : TNamed()
   , fNdata(0)
   , fLen(0)
   , fLenType(0)
   , fOffset(0)
   , fIsRange(kFALSE)
   , fIsUnsigned(kFALSE)
   , fLeafCount(0)
   , fBranch(0)
{
}

//______________________________________________________________________________
TLeaf::TLeaf(TBranch *parent, const char* name, const char *)
   : TNamed(name, name)
   , fNdata(0)
   , fLen(0)
   , fLenType(4)
   , fOffset(0)
   , fIsRange(kFALSE)
   , fIsUnsigned(kFALSE)
   , fLeafCount(0)
   , fBranch(parent)
{
   // Create a Leaf.
   //
   // See the TTree and TBranch constructors for explanation of parameters.

   fLeafCount = GetLeafCounter(fLen);

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

   const char *bracket = strchr(name, '[');
   if (bracket) fName.ReplaceAll(bracket,"");
}

//______________________________________________________________________________
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)
{
   //assignment 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()
{
   // -- Destructor.

   if (fBranch) {
      TTree* tree = fBranch->GetTree();
      fBranch = 0;
      if (tree) {
         TObjArray *lst = tree->GetListOfLeaves();
         if (lst->GetLast()!=-1) lst->Remove(this);
      }
   }
   fLeafCount = 0;
}

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

   if (strchr(GetName(), '.')) {
      fBranch->GetTree()->Draw(GetName(), "", b ? b->GetDrawOption() : "");
   } else {
      if ((fBranch->GetListOfLeaves()->GetEntries() > 1) ||
          (strcmp(fBranch->GetName(), GetName()) != 0)) {
         TString name;
         name.Form("%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 a pointer to the counter of this leaf.
   //
   //  If leaf name has the form var[nelem], where nelem is alphanumeric, then
   //     if nelem is a leaf name, return countval = 1 and the pointer to
   //          the leaf named nelem, otherwise return 0.
   //  If leaf name has the form var[nelem], where nelem is a non-negative integer, then
   //     return countval = nelem and a null pointer.
   //  If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2]
   //     where nelem and nelem2 are non-negative integers) then
   //     return countval = product of all dimension sizes and a null pointer.
   //  If leaf name has the form var[... (and does not match the previous 2
   //     cases) return countval = -1 and null pointer;
   //  Otherwise return countval = 1 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;
      countname = 0;
      countval = -1;
      return 0;
   }
   char *bleft2 = (char*) strchr(countname, '[');
   *bright = 0;
   nch = strlen(countname);

   // Now search a branch name with a leaf name = countname
   if (fBranch == 0) {
      Error("GetLeafCounter","TLeaf %s is not setup properly, fBranch is null.",GetName());
      return 0;
   }
   if (fBranch->GetTree() == 0) {
      Error("GetLeafCounter","For Leaf %s, the TBranch %s is not setup properly, fTree is null.",GetName(),fBranch->GetName());
      return 0;
   }
   TTree* pTree = fBranch->GetTree();

   TLeaf* leaf = (TLeaf*) GetBranch()->GetListOfLeaves()->FindObject(countname);
   if (leaf == 0) {
      // Try outside the branch:
      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[strlen(GetName())+strlen(countname)+1];
      strcpy(withdot, GetName());
      char* lastdot = strrchr(withdot, '.');
      strcpy(lastdot, countname);
      leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
      delete[] withdot;
      withdot = 0;
   }
   if (!leaf && strchr(countname,'.')) {
      // Not yet found and the countname has a dot in it, let's try
      // to find the leaf using its full name
      leaf = pTree->FindLeaf(countname);
   }
   Int_t i = 0;
   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;
      countname = 0;
      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;
         countname = 0;
         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;
   countname = 0;
   return 0;
}

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

   if (fLeafCount) {
      // -- We are a varying length array.
      Int_t len = Int_t(fLeafCount->GetValue());
      if (len > fLeafCount->GetMaximum()) {
         Error("GetLen", "Leaf counter is greater than maximum!  leaf: '%s' len: %d max: %d", GetName(), len, fLeafCount->GetMaximum());
         len = fLeafCount->GetMaximum();
      }
      return len * fLen;
   } else {
      // -- We are a fixed size thing.
      return fLen;
   }
}

//______________________________________________________________________________
Int_t TLeaf::ResetAddress(void* addr, Bool_t calledFromDestructor)
{
   // -- Helper routine for TLeafX::SetAddress.
   //
   // The return value is non-zero if we owned the old
   // value buffer and must delete it now.  The size
   // of the value buffer is recalculated and stored,
   // and a decision is made whether or not we own the
   // new value buffer.
   //

   // The kNewValue bit records whether or not we own
   // the current value buffer or not.  If we own it,
   // then we are responsible for deleting it.
   Bool_t deleteValue = kFALSE;
   if (TestBit(kNewValue)) {
      deleteValue = kTRUE;
   }
   // If we are not being called from a destructor,
   // recalculate the value buffer size and decide
   // whether or not we own the new value buffer.
   if (!calledFromDestructor) {
      // -- Recalculate value buffer size and decide ownership of value.
      if (fLeafCount) {
         // -- Varying length array data member.
         fNdata = (fLeafCount->GetMaximum() + 1) * fLen;
      } else {
         // -- Fixed size data member.
         fNdata = fLen;
      }
      // If we were provided an address, then we do not own
      // the value, otherwise we do and must delete it later,
      // keep track of this with bit kNewValue.
      if (addr) {
         ResetBit(kNewValue);
      } else {
         SetBit(kNewValue);
      }
   }
   return deleteValue;
}

//_______________________________________________________________________
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) {
         b.ReadClassBuffer(TLeaf::Class(), 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());
      }
      if (!fLen) {
         fLen = 1;
      }
      // We do not own the value buffer right now.
      ResetBit(kNewValue);
      SetAddress();
   } else {
      b.WriteClassBuffer(TLeaf::Class(), this);
   }
}

 TLeaf.cxx:1
 TLeaf.cxx:2
 TLeaf.cxx:3
 TLeaf.cxx:4
 TLeaf.cxx:5
 TLeaf.cxx:6
 TLeaf.cxx:7
 TLeaf.cxx:8
 TLeaf.cxx:9
 TLeaf.cxx:10
 TLeaf.cxx:11
 TLeaf.cxx:12
 TLeaf.cxx:13
 TLeaf.cxx:14
 TLeaf.cxx:15
 TLeaf.cxx:16
 TLeaf.cxx:17
 TLeaf.cxx:18
 TLeaf.cxx:19
 TLeaf.cxx:20
 TLeaf.cxx:21
 TLeaf.cxx:22
 TLeaf.cxx:23
 TLeaf.cxx:24
 TLeaf.cxx:25
 TLeaf.cxx:26
 TLeaf.cxx:27
 TLeaf.cxx:28
 TLeaf.cxx:29
 TLeaf.cxx:30
 TLeaf.cxx:31
 TLeaf.cxx:32
 TLeaf.cxx:33
 TLeaf.cxx:34
 TLeaf.cxx:35
 TLeaf.cxx:36
 TLeaf.cxx:37
 TLeaf.cxx:38
 TLeaf.cxx:39
 TLeaf.cxx:40
 TLeaf.cxx:41
 TLeaf.cxx:42
 TLeaf.cxx:43
 TLeaf.cxx:44
 TLeaf.cxx:45
 TLeaf.cxx:46
 TLeaf.cxx:47
 TLeaf.cxx:48
 TLeaf.cxx:49
 TLeaf.cxx:50
 TLeaf.cxx:51
 TLeaf.cxx:52
 TLeaf.cxx:53
 TLeaf.cxx:54
 TLeaf.cxx:55
 TLeaf.cxx:56
 TLeaf.cxx:57
 TLeaf.cxx:58
 TLeaf.cxx:59
 TLeaf.cxx:60
 TLeaf.cxx:61
 TLeaf.cxx:62
 TLeaf.cxx:63
 TLeaf.cxx:64
 TLeaf.cxx:65
 TLeaf.cxx:66
 TLeaf.cxx:67
 TLeaf.cxx:68
 TLeaf.cxx:69
 TLeaf.cxx:70
 TLeaf.cxx:71
 TLeaf.cxx:72
 TLeaf.cxx:73
 TLeaf.cxx:74
 TLeaf.cxx:75
 TLeaf.cxx:76
 TLeaf.cxx:77
 TLeaf.cxx:78
 TLeaf.cxx:79
 TLeaf.cxx:80
 TLeaf.cxx:81
 TLeaf.cxx:82
 TLeaf.cxx:83
 TLeaf.cxx:84
 TLeaf.cxx:85
 TLeaf.cxx:86
 TLeaf.cxx:87
 TLeaf.cxx:88
 TLeaf.cxx:89
 TLeaf.cxx:90
 TLeaf.cxx:91
 TLeaf.cxx:92
 TLeaf.cxx:93
 TLeaf.cxx:94
 TLeaf.cxx:95
 TLeaf.cxx:96
 TLeaf.cxx:97
 TLeaf.cxx:98
 TLeaf.cxx:99
 TLeaf.cxx:100
 TLeaf.cxx:101
 TLeaf.cxx:102
 TLeaf.cxx:103
 TLeaf.cxx:104
 TLeaf.cxx:105
 TLeaf.cxx:106
 TLeaf.cxx:107
 TLeaf.cxx:108
 TLeaf.cxx:109
 TLeaf.cxx:110
 TLeaf.cxx:111
 TLeaf.cxx:112
 TLeaf.cxx:113
 TLeaf.cxx:114
 TLeaf.cxx:115
 TLeaf.cxx:116
 TLeaf.cxx:117
 TLeaf.cxx:118
 TLeaf.cxx:119
 TLeaf.cxx:120
 TLeaf.cxx:121
 TLeaf.cxx:122
 TLeaf.cxx:123
 TLeaf.cxx:124
 TLeaf.cxx:125
 TLeaf.cxx:126
 TLeaf.cxx:127
 TLeaf.cxx:128
 TLeaf.cxx:129
 TLeaf.cxx:130
 TLeaf.cxx:131
 TLeaf.cxx:132
 TLeaf.cxx:133
 TLeaf.cxx:134
 TLeaf.cxx:135
 TLeaf.cxx:136
 TLeaf.cxx:137
 TLeaf.cxx:138
 TLeaf.cxx:139
 TLeaf.cxx:140
 TLeaf.cxx:141
 TLeaf.cxx:142
 TLeaf.cxx:143
 TLeaf.cxx:144
 TLeaf.cxx:145
 TLeaf.cxx:146
 TLeaf.cxx:147
 TLeaf.cxx:148
 TLeaf.cxx:149
 TLeaf.cxx:150
 TLeaf.cxx:151
 TLeaf.cxx:152
 TLeaf.cxx:153
 TLeaf.cxx:154
 TLeaf.cxx:155
 TLeaf.cxx:156
 TLeaf.cxx:157
 TLeaf.cxx:158
 TLeaf.cxx:159
 TLeaf.cxx:160
 TLeaf.cxx:161
 TLeaf.cxx:162
 TLeaf.cxx:163
 TLeaf.cxx:164
 TLeaf.cxx:165
 TLeaf.cxx:166
 TLeaf.cxx:167
 TLeaf.cxx:168
 TLeaf.cxx:169
 TLeaf.cxx:170
 TLeaf.cxx:171
 TLeaf.cxx:172
 TLeaf.cxx:173
 TLeaf.cxx:174
 TLeaf.cxx:175
 TLeaf.cxx:176
 TLeaf.cxx:177
 TLeaf.cxx:178
 TLeaf.cxx:179
 TLeaf.cxx:180
 TLeaf.cxx:181
 TLeaf.cxx:182
 TLeaf.cxx:183
 TLeaf.cxx:184
 TLeaf.cxx:185
 TLeaf.cxx:186
 TLeaf.cxx:187
 TLeaf.cxx:188
 TLeaf.cxx:189
 TLeaf.cxx:190
 TLeaf.cxx:191
 TLeaf.cxx:192
 TLeaf.cxx:193
 TLeaf.cxx:194
 TLeaf.cxx:195
 TLeaf.cxx:196
 TLeaf.cxx:197
 TLeaf.cxx:198
 TLeaf.cxx:199
 TLeaf.cxx:200
 TLeaf.cxx:201
 TLeaf.cxx:202
 TLeaf.cxx:203
 TLeaf.cxx:204
 TLeaf.cxx:205
 TLeaf.cxx:206
 TLeaf.cxx:207
 TLeaf.cxx:208
 TLeaf.cxx:209
 TLeaf.cxx:210
 TLeaf.cxx:211
 TLeaf.cxx:212
 TLeaf.cxx:213
 TLeaf.cxx:214
 TLeaf.cxx:215
 TLeaf.cxx:216
 TLeaf.cxx:217
 TLeaf.cxx:218
 TLeaf.cxx:219
 TLeaf.cxx:220
 TLeaf.cxx:221
 TLeaf.cxx:222
 TLeaf.cxx:223
 TLeaf.cxx:224
 TLeaf.cxx:225
 TLeaf.cxx:226
 TLeaf.cxx:227
 TLeaf.cxx:228
 TLeaf.cxx:229
 TLeaf.cxx:230
 TLeaf.cxx:231
 TLeaf.cxx:232
 TLeaf.cxx:233
 TLeaf.cxx:234
 TLeaf.cxx:235
 TLeaf.cxx:236
 TLeaf.cxx:237
 TLeaf.cxx:238
 TLeaf.cxx:239
 TLeaf.cxx:240
 TLeaf.cxx:241
 TLeaf.cxx:242
 TLeaf.cxx:243
 TLeaf.cxx:244
 TLeaf.cxx:245
 TLeaf.cxx:246
 TLeaf.cxx:247
 TLeaf.cxx:248
 TLeaf.cxx:249
 TLeaf.cxx:250
 TLeaf.cxx:251
 TLeaf.cxx:252
 TLeaf.cxx:253
 TLeaf.cxx:254
 TLeaf.cxx:255
 TLeaf.cxx:256
 TLeaf.cxx:257
 TLeaf.cxx:258
 TLeaf.cxx:259
 TLeaf.cxx:260
 TLeaf.cxx:261
 TLeaf.cxx:262
 TLeaf.cxx:263
 TLeaf.cxx:264
 TLeaf.cxx:265
 TLeaf.cxx:266
 TLeaf.cxx:267
 TLeaf.cxx:268
 TLeaf.cxx:269
 TLeaf.cxx:270
 TLeaf.cxx:271
 TLeaf.cxx:272
 TLeaf.cxx:273
 TLeaf.cxx:274
 TLeaf.cxx:275
 TLeaf.cxx:276
 TLeaf.cxx:277
 TLeaf.cxx:278
 TLeaf.cxx:279
 TLeaf.cxx:280
 TLeaf.cxx:281
 TLeaf.cxx:282
 TLeaf.cxx:283
 TLeaf.cxx:284
 TLeaf.cxx:285
 TLeaf.cxx:286
 TLeaf.cxx:287
 TLeaf.cxx:288
 TLeaf.cxx:289
 TLeaf.cxx:290
 TLeaf.cxx:291
 TLeaf.cxx:292
 TLeaf.cxx:293
 TLeaf.cxx:294
 TLeaf.cxx:295
 TLeaf.cxx:296
 TLeaf.cxx:297
 TLeaf.cxx:298
 TLeaf.cxx:299
 TLeaf.cxx:300
 TLeaf.cxx:301
 TLeaf.cxx:302
 TLeaf.cxx:303
 TLeaf.cxx:304
 TLeaf.cxx:305
 TLeaf.cxx:306
 TLeaf.cxx:307
 TLeaf.cxx:308
 TLeaf.cxx:309
 TLeaf.cxx:310
 TLeaf.cxx:311
 TLeaf.cxx:312
 TLeaf.cxx:313
 TLeaf.cxx:314
 TLeaf.cxx:315
 TLeaf.cxx:316
 TLeaf.cxx:317
 TLeaf.cxx:318
 TLeaf.cxx:319
 TLeaf.cxx:320
 TLeaf.cxx:321
 TLeaf.cxx:322
 TLeaf.cxx:323
 TLeaf.cxx:324
 TLeaf.cxx:325
 TLeaf.cxx:326
 TLeaf.cxx:327
 TLeaf.cxx:328
 TLeaf.cxx:329
 TLeaf.cxx:330
 TLeaf.cxx:331
 TLeaf.cxx:332
 TLeaf.cxx:333
 TLeaf.cxx:334
 TLeaf.cxx:335
 TLeaf.cxx:336
 TLeaf.cxx:337
 TLeaf.cxx:338
 TLeaf.cxx:339
 TLeaf.cxx:340
 TLeaf.cxx:341
 TLeaf.cxx:342
 TLeaf.cxx:343
 TLeaf.cxx:344
 TLeaf.cxx:345
 TLeaf.cxx:346
 TLeaf.cxx:347
 TLeaf.cxx:348
 TLeaf.cxx:349
 TLeaf.cxx:350
 TLeaf.cxx:351
 TLeaf.cxx:352
 TLeaf.cxx:353
 TLeaf.cxx:354
 TLeaf.cxx:355
 TLeaf.cxx:356
 TLeaf.cxx:357
 TLeaf.cxx:358
 TLeaf.cxx:359
 TLeaf.cxx:360
 TLeaf.cxx:361
 TLeaf.cxx:362
 TLeaf.cxx:363
 TLeaf.cxx:364
 TLeaf.cxx:365
 TLeaf.cxx:366
 TLeaf.cxx:367
 TLeaf.cxx:368
 TLeaf.cxx:369
 TLeaf.cxx:370
 TLeaf.cxx:371
 TLeaf.cxx:372
 TLeaf.cxx:373
 TLeaf.cxx:374
 TLeaf.cxx:375
 TLeaf.cxx:376
 TLeaf.cxx:377
 TLeaf.cxx:378
 TLeaf.cxx:379