// @(#)root/cont:$Name:  $:$Id: TRefTable.cxx,v 1.3 2004/08/24 10:41:58 brun Exp $
// Author: Rene Brun   28/09/2001

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

//////////////////////////////////////////////////////////////////////////
//
// TRefTable
//
// A TRefTable maintains the association between a referenced object    //
// and the parent object supporting this referenced object.             //
// The parent object is typically a branch of a TTree.                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TRefTable.h"

TRefTable *TRefTable::fgRefTable = 0;

ClassImp(TRefTable)

//______________________________________________________________________________
 TRefTable::TRefTable()
{
   // Default constructor for I/O

   fSize      = 0;
   fN         = 0;
   fParentID  = -1;
   fParentIDs = 0;
   fParents   = 0;
   fOwner     = 0;
   fgRefTable = this;
}

//______________________________________________________________________________
 TRefTable::TRefTable(TObject *owner, Int_t size)
{
   // Create a TRefTable with initial size

   if (size < 10) size = 10;
   fSize      = size;
   fN         = 0;
   fParentID  = -1;
   fParentIDs = new Int_t[fSize];
   for (Int_t i=0;i<fSize;i++) {
      fParentIDs[i] = 0;
   }
   fParents   = new TObjArray(1);
   fOwner     = owner;
   fgRefTable = this;
}

//______________________________________________________________________________
 TRefTable::~TRefTable()
{
   delete [] fParentIDs;
   delete fParents;
   if (fgRefTable == this) fgRefTable = 0;
}

//______________________________________________________________________________
 Int_t TRefTable::Add(Int_t uid)
{
   // add a new uid to the table
   // we add a new pair (uid,fparent) to the map
   // This function is called by TObject::Streamer or TStreamerInfo::WriteBuffer
   
   if (uid <= 0) {
      Error("Add","Attempt to add an invalid uid=%d",uid);
      return uid;
   }
   Int_t newsize = 0;
   if (uid >= fSize) newsize = Expand(uid+uid/2);
   if (newsize < 0) {
      Error("Add","Cannot allocate space to store uid=%d",uid);
      return -1;
   }
   if (fParentID < 0) {
      Error("Add","SetParent must be called before adding uid=%d",uid);
      return -1;
   }
   fParentIDs[uid] = fParentID+1;
   if (uid >= fN) fN = uid+1;
   return uid;
}

//______________________________________________________________________________
 void TRefTable::Clear(Option_t * /*option*/)
{
   // clear all entries in the table
   for (Int_t i=0;i<fN;i++) {
      fParentIDs[i] = 0;
   }
   fN = 0;
   fParentID = -1;
}

//______________________________________________________________________________
 Int_t TRefTable::Expand(Int_t newsize)
{
   // expand fParentID to newsize
   
   if (newsize < 0) return newsize;
   if (newsize != fSize) {
      Int_t *temp = fParentIDs;
      if (newsize != 0) {
         fParentIDs = new Int_t[newsize];
         if (newsize < fSize) memcpy(fParentIDs,temp, newsize*sizeof(Int_t));
         else {
            memcpy(fParentIDs,temp,fSize*sizeof(Int_t));
            memset(&fParentIDs[fSize],0,(newsize-fSize)*sizeof(Int_t));
         }
      } else {
        fParentIDs = 0;
      }
      if (fSize) delete [] temp;
      fSize = newsize;
   }
   return newsize;
}

//______________________________________________________________________________
 void TRefTable::FillBuffer(TBuffer &b)
{
   // fill buffer b with the fN elements in fParentdIDs
   // This function is called by TBranchRef::FillLeaves
   
   b << fN;
   b.WriteFastArray(fParentIDs,fN);
}

//______________________________________________________________________________
 TObject *TRefTable::GetParent(Int_t uid) const
{
   // return object corresponding to uid
   if (uid < 0 || uid >= fN) return 0;
   Int_t pnumber = fParentIDs[uid]-1;
   Int_t nparents = fParents->GetEntriesFast();
   if (pnumber < 0 || pnumber >= nparents) return 0;
   return fParents->UncheckedAt(pnumber);
}

//______________________________________________________________________________
 TRefTable *TRefTable::GetRefTable()
{
   // static function returning the current TRefTable
   
   return fgRefTable;
}

//______________________________________________________________________________
 Bool_t TRefTable::Notify()
{
   // This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer
   // when reading a reference.
   // This function, in turns, notifies the TRefTable owner for action.
   // eg, when the owner is a TBranchRef, TBranchRef::Notify is called
   // to read the branch containing the referenced object.
   
   return fOwner->Notify();
}

//______________________________________________________________________________
 void TRefTable::ReadBuffer(TBuffer &b)
{
   // fill buffer b with the fN elements in fParentdIDs
   // This function is called by TBranchRef::ReadLeaves
   
   b >> fN;
   if (fN > fSize) fSize = Expand(fN +fN/2);
   b.ReadFastArray(fParentIDs,fN);
}
 
//______________________________________________________________________________
 Int_t TRefTable::SetParent(const TObject *parent)
{
   // Set Current parent object
   // The parent object is typically a branch of a Tree.
   // This function is called by TBranchElement::Fill
   
   Int_t nparents = fParents->GetEntriesFast();
   Int_t ind = fParents->IndexOf(parent);
   if (ind >= 0) {
      fParentID = ind;
   } else {
      fParents->AddAtAndExpand((TObject*)parent,nparents);
      fParentID = nparents;
   }
   return fParentID;
}

//______________________________________________________________________________
 void TRefTable::SetRefTable(TRefTable *table)
{
   // static function setting the current TRefTable
   
   fgRefTable = table;
}


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.