TTableDescriptor.cxx

Go to the documentation of this file.
00001 // @(#)root/table:$Id: TTableDescriptor.cxx 35980 2010-10-01 09:58:09Z pcanal $
00002 // Author: Valery Fine   09/08/99  (E-mail: fine@bnl.gov)
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include <stdlib.h>
00013 
00014 #include "TTableDescriptor.h"
00015 #include "TTable.h"
00016 #include "TClass.h"
00017 #include "TDataMember.h"
00018 #include "TDataType.h"
00019 #include "Ttypes.h"
00020 #include "TInterpreter.h"
00021 
00022 //______________________________________________________________________________
00023 //
00024 // TTableDescriptor - run-time descriptor of the TTable object rows.
00025 //______________________________________________________________________________
00026 
00027 TTableDescriptor *TTableDescriptor::fgColDescriptors = 0;
00028 // TString TTableDescriptor::fgCommentsName = TTableDescriptor::SetCommentsSetName();
00029 TString TTableDescriptor::fgCommentsName = ".comments";
00030 TableClassImp(TTableDescriptor,tableDescriptor_st)
00031 
00032 //___________________________________________________________________
00033 TTableDescriptor *TTableDescriptor::GetDescriptorPointer() const 
00034 { 
00035    //return column descriptor
00036    return fgColDescriptors;
00037 }
00038 
00039 //___________________________________________________________________
00040 void TTableDescriptor::SetDescriptorPointer(TTableDescriptor *list)  
00041 { 
00042    //set table descriptor
00043    fgColDescriptors = list;
00044 }
00045 
00046 //___________________________________________________________________
00047 void TTableDescriptor::SetCommentsSetName(const char *name)
00048 {
00049    //set comments name
00050    fgCommentsName =  name;
00051 }
00052 
00053 
00054 //______________________________________________________________________________
00055 void TTableDescriptor::Streamer(TBuffer &R__b)
00056 {
00057    // The custom Streamer for this table
00058    fSecondDescriptor = 0;
00059    TTable::Streamer(R__b);
00060 }
00061 
00062 //______________________________________________________________________________
00063 TTableDescriptor::TTableDescriptor(const TTable *parentTable)
00064  : TTable("tableDescriptor",sizeof(tableDescriptor_st)), fRowClass(0),fSecondDescriptor(0)
00065 {
00066    //to be documented
00067    if (parentTable) {
00068       TClass *classPtr = parentTable->GetRowClass();
00069       Init(classPtr);
00070    }
00071    else MakeZombie();
00072 }
00073 
00074 //______________________________________________________________________________
00075 TTableDescriptor::TTableDescriptor(TClass *classPtr)
00076  : TTable("tableDescriptor",sizeof(tableDescriptor_st)),fRowClass(0),fSecondDescriptor(0)
00077 {
00078    // Create a descriptor of the C-structure defined by TClass
00079    // TClass *classPtr must be a valid pointer to TClass object for
00080    // "plain" C_struture only !!!
00081    Init(classPtr);
00082 }
00083 //______________________________________________________________________________
00084 TTableDescriptor::~TTableDescriptor()
00085 {
00086    // class destructor 
00087 #ifdef NORESTRICTIONS
00088    if (!IsZombie()) {
00089       for (Int_t i=0;i<GetNRows();i++) {
00090          Char_t *name = (Char_t *)ColumnName(i);
00091          if (name) delete [] name;
00092          UInt_t  *indxArray = (UInt_t *)IndexArray(i);
00093          if (indxArray) delete [] indxArray;
00094       }
00095    }
00096 #endif
00097    if (fSecondDescriptor != this) {
00098       delete fSecondDescriptor;
00099       fSecondDescriptor = 0;
00100    }
00101 }
00102 
00103 //____________________________________________________________________________
00104 Int_t TTableDescriptor::AddAt(const void *c)
00105 {
00106    // Append one row pointed by "c" to the descriptor
00107 
00108    if (!c) return -1;
00109    TDataSet *cmnt = MakeCommentField();
00110    assert(cmnt!=0);
00111 
00112    return TTable::AddAt(c);
00113 }
00114 //____________________________________________________________________________
00115 void  TTableDescriptor::AddAt(const void *c, Int_t i)
00116 {
00117    //Add one row pointed by "c" to the "i"-th row of the descriptor
00118    if (c) {
00119       tableDescriptor_st *element = (tableDescriptor_st *)c;
00120 #ifdef NORESTRICTIONS
00121       const char *comment = element->fColumnName && element->fColumnName[0] ? element->fColumnName : "N/A";
00122 #else
00123       const char *comment = element->fColumnName[0] ? element->fColumnName : "N/A";
00124 #endif
00125       AddAt(*(tableDescriptor_st *)c,comment,i);
00126    }
00127 }
00128 
00129 //____________________________________________________________________________
00130 void  TTableDescriptor::AddAt(TDataSet *dataset,Int_t idx)
00131 {
00132    // Add one dataset to the descriptor. 
00133    // There is no new implementation here. 
00134    // One needs it to avoid the "hidden method" compilation warning
00135    TTable::AddAt(dataset,idx);
00136 }
00137 
00138 //____________________________________________________________________________
00139 void TTableDescriptor::AddAt(const tableDescriptor_st &element,const char *commentText,Int_t indx)
00140 {
00141    // Add the descriptor element followed by its commentText
00142    // at the indx-th position of the descriptor (counted from zero)
00143 
00144    TTable::AddAt(&element,indx);
00145    TDataSet *cmnt = MakeCommentField();
00146    assert(cmnt!=0);
00147    TDataSet *comment = new TDataSet(element.fColumnName);
00148    comment->SetTitle(commentText);
00149    cmnt->AddAtAndExpand(comment,indx);
00150 }
00151 
00152 //____________________________________________________________________________
00153 TString TTableDescriptor::CreateLeafList() const
00154 {
00155    // Create a list of leaf to be useful for TBranch::TBranch ctor
00156    const Char_t typeMapTBranch[]="\0FIISDiisbBC";
00157    Int_t maxRows = NumberOfColumns();
00158    TString string;
00159    for (Int_t i=0;i<maxRows;i++){
00160       if (i) string += ":";
00161       UInt_t nDim = Dimensions(i);
00162 
00163       UInt_t totalSize = 1;
00164       UInt_t k = 0;
00165 
00166       if (nDim) {
00167          const UInt_t *indx = IndexArray(i);
00168          if (!indx){
00169             string = "";
00170             Error("CreateLeafList()","Can not create leaflist for arrays");
00171             return string;
00172          }
00173          for (k=0;k< nDim; k++) totalSize *= indx[k];
00174       }
00175       const Char_t *colName = ColumnName(i);
00176       if (totalSize > 1) {
00177          for ( k = 0; k < totalSize; k++) {
00178             Char_t buf[10];
00179             snprintf(buf,10,"_%d",k);
00180             string += colName;
00181             string += buf;
00182             if (k==0) {
00183                string += "/";
00184                string += typeMapTBranch[ColumnType(i)];
00185             }
00186             if (k != totalSize -1) string += ":";
00187          }
00188       } else {
00189          string += ColumnName(i);
00190          string += "/";
00191          string += typeMapTBranch[ColumnType(i)];
00192       }
00193    }
00194    return string;
00195 }
00196 
00197 //______________________________________________________________________________
00198 void TTableDescriptor::Init(TClass *classPtr)
00199 {
00200    // Create a descriptor of the C-structure defined by TClass
00201    // TClass *classPtr must be a valid pointer to TClass object for
00202    // "plain" C_structure only !!!
00203    fSecondDescriptor = 0;
00204    SetType("tableDescriptor");
00205    if (classPtr) {
00206       fRowClass = classPtr; // remember my row class
00207       SetName(classPtr->GetName());
00208       LearnTable(classPtr);
00209    }
00210    else
00211       MakeZombie();
00212 }
00213 //____________________________________________________________________________
00214 void TTableDescriptor::LearnTable(const TTable *parentTable)
00215 {
00216    //to be documented
00217    if (!parentTable) {
00218       MakeZombie();
00219       return;
00220    }
00221    LearnTable(parentTable->GetRowClass());
00222 }
00223 
00224 //____________________________________________________________________________
00225 void TTableDescriptor::LearnTable(TClass *classPtr)
00226 {
00227 //
00228 //  LearnTable() creates an array of the descriptors for elements of the row
00229 //
00230 // It creates a descriptor of the C-structure defined by TClass
00231 // TClass *classPtr must be a valid pointer to TClass object for
00232 // "plain" C-structure only !!!
00233 //
00234 //  This is to introduce an artificial restriction demanded by STAR database group
00235 //
00236 //    1. the name may be 31 symbols at most
00237 //    2. the number the dimension is 3 at most
00238 //
00239 //  To lift this restriction one has to provide -DNORESTRICTIONS CPP symbol and
00240 //  recompile code (and debug code NOW!)
00241 //
00242 
00243    if (!classPtr) return;
00244 
00245    if (!(classPtr->GetNdata())) return;
00246 
00247    Char_t *varname;
00248 
00249    tableDescriptor_st elementDescriptor;
00250 
00251    ReAllocate(classPtr->GetListOfDataMembers()->GetSize());
00252    Int_t columnIndex = 0;
00253    TIter next(classPtr->GetListOfDataMembers());
00254    TDataMember *member = 0;
00255    while ( (member = (TDataMember *) next()) ) {
00256       memset(&elementDescriptor,0,sizeof(tableDescriptor_st));
00257       varname = (Char_t *) member->GetName();
00258 #ifdef NORESTRICTIONS
00259 //  This is remove to introduce an artificial restriction demanded by STAR infrastructure group
00260                                              elementDescriptor.fColumnName = StrDup(varname);
00261 #else
00262                                              elementDescriptor.fColumnName[0] = '\0';
00263          strncat(elementDescriptor.fColumnName,varname,sizeof(elementDescriptor.fColumnName)-1);
00264 #endif
00265     // define index
00266       if (member->IsaPointer() ) {
00267          elementDescriptor.fTypeSize = sizeof(void *);
00268          const char *typeName = member->GetTypeName();
00269          elementDescriptor.fType = TTable::GetTypeId(typeName);
00270       } else {
00271          TDataType *memberType = member->GetDataType();
00272          assert(memberType!=0);
00273          elementDescriptor.fTypeSize = memberType->Size();
00274          elementDescriptor.fType = TTable::GetTypeId(memberType->GetTypeName());
00275       }
00276       Int_t globalIndex = 1;
00277       if (elementDescriptor.fType != kNAN) {
00278          Int_t dim = 0;
00279          if ( (dim = member->GetArrayDim()) ) {
00280                                               elementDescriptor.fDimensions = dim;
00281 #ifdef NORESTRICTIONS
00282                                               elementDescriptor.fIndexArray = new UInt_t(dim);
00283 #else
00284             UInt_t maxDim = sizeof(elementDescriptor.fIndexArray)/sizeof(UInt_t);
00285             if (UInt_t(dim) > maxDim) {
00286                Error("LearnTable","Too many dimenstions - %d", dim);
00287                dim =  maxDim;
00288             }
00289 #endif
00290             for( Int_t indx=0; indx < dim; indx++ ){
00291                                              elementDescriptor.fIndexArray[indx] = member->GetMaxIndex(indx);
00292                globalIndex *= elementDescriptor.fIndexArray[indx];
00293             }
00294          }
00295       }
00296       else Error("LearnTable","Wrong data type for <%s> structure",classPtr->GetName());
00297       elementDescriptor.fSize   =  globalIndex * (elementDescriptor.fTypeSize);
00298       elementDescriptor.fOffset = member->GetOffset();
00299       AddAt(elementDescriptor,member->GetTitle(),columnIndex); columnIndex++;
00300    }
00301 }
00302 
00303 //______________________________________________________________________________
00304 TTableDescriptor *TTableDescriptor::MakeDescriptor(const char *structName)
00305 {
00306    ///////////////////////////////////////////////////////////
00307    //
00308    // MakeDescriptor(const char *structName) - static method
00309    //                structName - the name of the C structure
00310    //                             to create descriptor of
00311    // return a new instance of the TTableDescriptor or 0
00312    // if the "structName is not present with the dictionary
00313    //
00314    ///////////////////////////////////////////////////////////
00315    TTableDescriptor *dsc = 0;
00316    TClass *cl = TClass::GetClass(structName, kTRUE);
00317 //    TClass *cl = new TClass(structName,1,0,0);
00318    assert(cl!=0);
00319    dsc = new TTableDescriptor(cl);
00320    return dsc;
00321 }
00322 //______________________________________________________________________________
00323 TDataSet *TTableDescriptor::MakeCommentField(Bool_t createFlag){
00324    // Instantiate a comment dataset if any
00325    TDataSet *comments = FindByName(fgCommentsName.Data());
00326    if (!comments && createFlag)
00327       comments =  new TDataSet(fgCommentsName.Data(),this,kTRUE);
00328    return comments;
00329 }
00330 //______________________________________________________________________________
00331 Int_t TTableDescriptor::UpdateOffsets(const TTableDescriptor *newDescriptor)
00332 {
00333   //                  "Schema evolution"
00334   // Method updates the offsets with a new ones from another descriptor
00335   //
00336    Int_t maxColumns = NumberOfColumns();
00337    Int_t mismathes = 0;
00338 
00339    if (   (UInt_t(maxColumns) == newDescriptor->NumberOfColumns())
00340       && (memcmp(GetArray(),newDescriptor->GetArray(),sizeof(tableDescriptor_st)*GetNRows()) == 0)
00341      ) return mismathes; // everything fine for sure !
00342 
00343   // Something wrong here, we have to check things piece by piece
00344    for (Int_t colCounter=0; colCounter < maxColumns; colCounter++) {
00345       Int_t colNewIndx = newDescriptor->ColumnByName(ColumnName(colCounter));
00346       // look for analog
00347       EColumnType newType = colNewIndx >=0 ? newDescriptor->ColumnType(colNewIndx): kNAN;
00348 #ifdef __STAR__
00349       if (newType == kInt)       newType = kLong;
00350       else if (newType == kUInt) newType = kULong;
00351 #endif
00352       if (    colNewIndx >=0
00353          && Dimensions(colCounter) == newDescriptor->Dimensions(colNewIndx)
00354          && ColumnType(colCounter) == newType)  {
00355          SetOffset(newDescriptor->Offset(colNewIndx),colCounter);
00356          if (colNewIndx != colCounter) {
00357             Printf("Schema evolution: \t%d column of the \"%s\" table has been moved to %d-th column\n",
00358             colCounter,ColumnName(colCounter),colNewIndx);
00359             mismathes++;
00360          }
00361       } else {
00362          Printf("Schema evolution: \t%d column \"%s\" of %d type has been lost\n",
00363          colCounter,ColumnName(colCounter),ColumnType(colCounter));
00364          Printf(" Indx = %d, name = %s \n", colNewIndx, ColumnName(colCounter));
00365          SetOffset(UInt_t(-1),colCounter);
00366          mismathes++;
00367       }
00368    }
00369    if (!mismathes && UInt_t(maxColumns) != newDescriptor->NumberOfColumns()) {
00370       mismathes++;
00371       Printf("Warning: One extra column has been introduced\n");
00372    }
00373    return mismathes;
00374 }
00375 
00376 //____________________________________________________________________________
00377 Int_t TTableDescriptor::ColumnByName(const Char_t *columnName) const
00378 {
00379  // Find the column index but the column name
00380    const tableDescriptor_st *elementDescriptor = ((TTableDescriptor *)this)->GetTable();
00381    Int_t i = -1;
00382    if (!elementDescriptor) return i;
00383    Int_t nRows = GetNRows();
00384    char *bracket = 0;
00385    if (nRows) {
00386       char *name = StrDup(columnName);
00387       if ((bracket = strchr(name,'[')) )  *bracket = 0;
00388       for (i=0; i < nRows; i++,elementDescriptor++)
00389          if (strcmp(name,elementDescriptor->fColumnName) == 0) break;
00390       delete [] name;
00391    }
00392    if (i==nRows) i = -1;
00393    // Check array
00394    if (bracket && !Dimensions(i)) {
00395       i = -1;
00396       Warning("ColumnByName","%s column contains a scalar value",columnName);
00397    }
00398    return i;
00399 }
00400 
00401 //____________________________________________________________________________
00402 Int_t TTableDescriptor::Offset(const Char_t *columnName) const
00403 {
00404   // Return offset of the column defined by "columnName"
00405   // Take in account index if provided
00406   // Can not handle multidimensional indeces yet.
00407 
00408    Int_t indx = ColumnByName(columnName);
00409    Int_t offset = -1;
00410    if (indx >= 0 ) {
00411       offset = Offset(indx);
00412       const char *openBracket = 0;
00413       if ( (openBracket = strchr(columnName,'['))  )
00414          offset += atoi(openBracket+1)*TypeSize(indx);
00415    }
00416    return offset;
00417 }
00418 
00419 //____________________________________________________________________________
00420 Int_t TTableDescriptor::ColumnSize(const Char_t *columnName) const
00421 {
00422    //to be documented
00423    Int_t indx = ColumnByName(columnName);
00424    if (indx >= 0 ) indx = ColumnSize(indx);
00425    return indx;
00426 }
00427 
00428 //____________________________________________________________________________
00429 Int_t TTableDescriptor::TypeSize(const Char_t *columnName) const
00430 {
00431    //to be documented
00432    Int_t indx = ColumnByName(columnName);
00433    if (indx >= 0 ) indx = TypeSize(indx);
00434    return indx;
00435 }
00436 
00437 //____________________________________________________________________________
00438 Int_t TTableDescriptor::Dimensions(const Char_t *columnName) const
00439 {
00440    //to be documented
00441    Int_t indx = ColumnByName(columnName);
00442    if (indx >= 0 ) indx = Dimensions(indx);
00443    return indx;
00444 }
00445 
00446 //____________________________________________________________________________
00447 TTable::EColumnType TTableDescriptor::ColumnType(const Char_t *columnName) const
00448 {
00449    //to be documented
00450    Int_t indx = ColumnByName(columnName);
00451    if (indx >= 0 ) indx = ColumnType(indx);
00452    return EColumnType(indx);
00453 }
00454 //____________________________________________________________________________
00455 Int_t   TTableDescriptor::Sizeof() const
00456 {
00457    //to be documented
00458    Int_t fullRowSize = 0;
00459    if (RowClass() ) fullRowSize = RowClass()->Size();
00460    else {
00461       // Calculate the size myslef.
00462       Int_t iLastRows = GetNRows()-1;
00463       if (iLastRows >=0) fullRowSize = Offset(iLastRows)  + ColumnSize(iLastRows);
00464    }
00465    return fullRowSize;
00466 }
00467 

Generated on Tue Jul 5 14:45:09 2011 for ROOT_528-00b_version by  doxygen 1.5.1