// @(#)root/star:$Name:  $:$Id: TTableDescriptor.cxx,v 1.2 2000/06/05 08:01:03 brun Exp $
// Author: Valery Fine   09/08/99  (E-mail: fine@bnl.gov)
// $Id: TTableDescriptor.cxx,v 1.2 2000/06/05 08:01:03 brun Exp $
#include <stdlib.h>

#include "TTableDescriptor.h"
#include "TTable.h"
#include "TClass.h"
#include "TDataMember.h"
#include "TDataType.h"
#include "Ttypes.h"

TTableDescriptor *TTableDescriptor::fgColDescriptors = 0;
TableClassImp(TTableDescriptor,tableDescriptor_st)

//______________________________________________________________________________
 void TTableDescriptor::Streamer(TBuffer &R__b)
{
  // The custom Streamer for this table
#if 0
  Version_t R__v = 0;
  if (R__b.IsReading())
    R__v = R__b.ReadVersion();
  else
    R__b.WriteVersion(TTableDescriptor::IsA());
#endif
  TTable::Streamer(R__b);
}

//______________________________________________________________________________
 TTableDescriptor::TTableDescriptor(const TTable *parentTable)
 : TTable("tableDescriptor",sizeof(tableDescriptor_st)), fRowClass(0)
{
  if (parentTable) {
     TClass *classPtr = parentTable->GetRowClass();
     Init(classPtr);
  }
  else MakeZombie();
}

//______________________________________________________________________________
 TTableDescriptor::TTableDescriptor(TClass *classPtr)
 : TTable("tableDescriptor",sizeof(tableDescriptor_st)),fRowClass(0)
{
  // Create a descriptor of the C-structure defined by TClass
  // TClass *classPtr must be a valid pointer to TClass object for
  // "plain" C_struture only !!!
  Init(classPtr);
}
//______________________________________________________________________________
 void TTableDescriptor::Init(TClass *classPtr)
{
  // Create a descriptor of the C-structure defined by TClass
  // TClass *classPtr must be a valid pointer to TClass object for
  // "plain" C_struture only !!!
  SetType("tableDescriptor");
  if (classPtr) {
    fRowClass = classPtr; // remember my row class
    SetName(classPtr->GetName());
    LearnTable(classPtr);
  }
  else
    MakeZombie();
}
//______________________________________________________________________________
 TTableDescriptor::~TTableDescriptor()
{
#ifdef NORESTRICTIONS
  if (!IsZombie()) {
    for (Int_t i=0;i<GetNRows();i++) {
      Char_t *name = (Char_t *)ColumnName(i);
      if (name) delete [] name;
      UInt_t  *indxArray = (UInt_t *)IndexArray(i);
      if (indxArray) delete [] indxArray;
    }
  }
#endif
}

//____________________________________________________________________________
 TString TTableDescriptor::CreateLeafList() const
{
  // Create a list of leaf to be useful for TBranch::TBranch ctor
  const Char_t TypeMapTBranch[]="0FIISDiisbBC";
  Int_t maxRows = NumberOfColumns();
  TString string;
  for (Int_t i=0;i<maxRows;i++){
    if (i) string += ":";
    UInt_t nDim = Dimensions(i);

    UInt_t totalSize = 1;
    UInt_t k = 0;

    if (nDim) {
      const UInt_t *indx = IndexArray(i);
      if (!indx){
        string = "";
        Error("CreateLeafList()","Can not create leaflist for arrays");
        return string;
      }
      for (k=0;k< nDim; k++) totalSize *= indx[k];
    }
    const Char_t *colName = ColumnName(i);
    if (totalSize > 1) {
       for ( k = 0; k < totalSize; k++) {
         Char_t buf[10];
         sprintf(buf,"_%d",k);
         string += colName;
         string += buf;
         if (k==0) {
           string += "/";
           string += TypeMapTBranch[ColumnType(i)];
         }
         if (k != totalSize -1) string += ":";
      }
    } else {
       string += ColumnName(i);
       string += "/";
       string += TypeMapTBranch[ColumnType(i)];
    }
  }
  return string;
}

//____________________________________________________________________________
 void TTableDescriptor::LearnTable(const TTable *parentTable)
{
  if (!parentTable) {
    MakeZombie();
    return;
  }
  LearnTable(parentTable->GetRowClass());
}

//____________________________________________________________________________
 void TTableDescriptor::LearnTable(TClass *classPtr)
{
//
//  LearnTable() creates an array of the descriptors for elements of the row
//
// It creates a descriptor of the C-structure defined by TClass
// TClass *classPtr must be a valid pointer to TClass object for
// "plain" C_struture only !!!
//
//  This is to introduce an artificial restriction demanded by STAR database group
//
//    1. the name may be 31 symbols at most
//    2. the number the dimension is 3 at most
//
//  To lift this restriction one has to provide -DNORESTRICTIONS CPP symbol and
//  recompile code (and debug code NOW!)
//

  if (!classPtr) return;

  if (!classPtr->GetListOfRealData()) classPtr->BuildRealData();
  if (!(classPtr->GetNdata())) return;

  const Char_t *types;
  Char_t *varname;

  tableDescriptor_st elementDescriptor;

  ReAllocate(classPtr->GetListOfDataMembers()->GetSize());
  Int_t columnIndex = 0;
  TIter next(classPtr->GetListOfDataMembers());
  TDataMember *member = 0;
  while ( (member = (TDataMember *) next()) ) {
    memset(&elementDescriptor,0,sizeof(tableDescriptor_st));
    varname = (Char_t *) member->GetName();
#ifdef NORESTRICTIONS
//  This is remove to introduce an artificial restriction demanded by STAR infrastructure group
                                             elementDescriptor.fColumnName = StrDup(varname);
#else
                                             elementDescriptor.fColumnName[0] = '\0';
         strncat(elementDescriptor.fColumnName,varname,sizeof(elementDescriptor.fColumnName));
#endif
    // define index
    TDataType *memberType = member->GetDataType();
                                              elementDescriptor.fTypeSize = memberType->Size();
    types = memberType->GetTypeName();
    elementDescriptor.fType = kNAN;
    if (!strcmp("float", types))              elementDescriptor.fType = kFloat;
    else if (!strcmp("int", types))           elementDescriptor.fType = kInt;
    else if (!strcmp("long", types))          elementDescriptor.fType = kLong;
    else if (!strcmp("short", types))         elementDescriptor.fType = kShort;
    else if (!strcmp("double", types))        elementDescriptor.fType = kDouble;
    else if (!strcmp("unsigned int", types))  elementDescriptor.fType = kUInt;
    else if (!strcmp("unsigned long", types)) elementDescriptor.fType = kULong ;
    else if (!strcmp("unsigned short", types))elementDescriptor.fType = kUShort;
    else if (!strcmp("unsigned char", types)) elementDescriptor.fType = kUChar;
    else if (!strcmp("char", types))          elementDescriptor.fType = kChar;

    Int_t globalIndex = 1;
    if (elementDescriptor.fType != kNAN) {
      Int_t dim = 0;
      if ( (dim = member->GetArrayDim()) ) {
                                              elementDescriptor.fDimensions = dim;
#ifdef NORESTRICTIONS
                                              elementDescriptor.fIndexArray = new UInt_t(dim);
#else
       UInt_t maxDim = sizeof(elementDescriptor.fIndexArray)/sizeof(UInt_t *);
       if (UInt_t(dim) > maxDim) {
                Error("LearnTable","Too many dimenstions - %d", dim);
                dim =  maxDim;
       }
#endif
        for( Int_t indx=0; indx < dim; indx++ ){
                                              elementDescriptor.fIndexArray[indx] = member->GetMaxIndex(indx);
          globalIndex *= elementDescriptor.fIndexArray[indx];
        }
      }
    }
    else Error("LearnTable","Wrong data type for <%s> structure",classPtr->GetName());
    elementDescriptor.fSize   =  globalIndex * (elementDescriptor.fTypeSize);
    elementDescriptor.fOffset = member->GetOffset();
    AddAt(&elementDescriptor,columnIndex); columnIndex++;
  }
}

//______________________________________________________________________________
 Int_t TTableDescriptor::UpdateOffsets(const TTableDescriptor *newDescriptor)
{
  //                  "Schema evolution"
  // Method updates the offsets with a new ones from another descritor
  //
  Int_t maxColumns = NumberOfColumns();
  Int_t mismathes = 0;

  if (   (UInt_t(maxColumns) == newDescriptor->NumberOfColumns())
      && (memcmp(GetArray(),newDescriptor->GetArray(),sizeof(tableDescriptor_st)*GetNRows()) == 0)
     ) return mismathes; // everything fine for sure !

  // Something wrong here, we have to check things piece by piece
  for (Int_t colCounter=0; colCounter < maxColumns; colCounter++)
  {
    Int_t colNewIndx = newDescriptor->ColumnByName(ColumnName(colCounter));
    // look for analog
    if (    colNewIndx >=0
         && Dimensions(colCounter) == newDescriptor->Dimensions(colNewIndx)
         && ColumnType(colCounter) == newDescriptor->ColumnType(colNewIndx)
       )  {
      SetOffset(newDescriptor->Offset(colNewIndx),colCounter);
      if (colNewIndx != colCounter) {
        printf("Schema evolution: t%d column of the "%s" table has been moved to %d-th columnn",
        colCounter,ColumnName(colCounter),colNewIndx);
        mismathes++;
      }
    }
    else {
      printf("Schema evolution: t%d column of the "%s" table has been lostn",
        colCounter,ColumnName(colCounter));
      printf(" Indx = %d, name = %s n", colNewIndx, ColumnName(colCounter));
      SetOffset(-1,colCounter);
      mismathes++;
    }
  }
  return mismathes;
}

//____________________________________________________________________________
 const Int_t TTableDescriptor::ColumnByName(const Char_t *columnName) const
{
 // Find the column index but the column name
 const tableDescriptor_st *elementDescriptor = ((TTableDescriptor *)this)->GetTable();
 Int_t i = -1;
 if (!elementDescriptor) return i;
 Int_t nRows = GetNRows();
 char *bracket = 0;
 if (nRows) {
   char *name = StrDup(columnName);
   if ((bracket = strchr(name,'[')) )  *bracket = 0;
   for (i=0; i < nRows; i++,elementDescriptor++)
     if (strcmp(name,elementDescriptor->fColumnName) == 0) break;
   delete [] name;
 }
 if (i==nRows) i = -1;
 // Check array
 if (bracket && !Dimensions(i)) {
     i = -1;
     Warning("ColumnByName","%s column contains a scalar value",columnName);
 }
 return i;
}

//____________________________________________________________________________
 Int_t TTableDescriptor::Offset(const Char_t *columnName) const
{
  // Return offset of the column defined by "columnName"
  // Take in account index if provided
  // Can not handle multidimensional indeces yet.

   Int_t indx = ColumnByName(columnName);
   Int_t offset = -1;
   if (indx >= 0 ) {
      offset = Offset(indx);
      const char *openBracket = 0;
      if ( (openBracket = strchr(columnName,'['))  )
         offset += atoi(openBracket+1)*TypeSize(indx);
   }
   return offset;
}

//____________________________________________________________________________
 Int_t TTableDescriptor::ColumnSize(const Char_t *columnName) const
{
  Int_t indx = ColumnByName(columnName);
  if (indx >= 0 ) indx = ColumnSize(indx);
  return indx;
}

//____________________________________________________________________________
 Int_t TTableDescriptor::TypeSize(const Char_t *columnName) const
{
  Int_t indx = ColumnByName(columnName);
  if (indx >= 0 ) indx = TypeSize(indx);
  return indx;
}

//____________________________________________________________________________
 Int_t TTableDescriptor::Dimensions(const Char_t *columnName) const
{
  Int_t indx = ColumnByName(columnName);
  if (indx >= 0 ) indx = Dimensions(indx);
  return indx;
}

//____________________________________________________________________________
TTable::EColumnType TTableDescriptor::ColumnType(const Char_t *columnName) const
{
  Int_t indx = ColumnByName(columnName);
  if (indx >= 0 ) indx = ColumnType(indx);
  return EColumnType(indx);
}


ROOT page - Class index - 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.