00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00025
00026
00027 TTableDescriptor *TTableDescriptor::fgColDescriptors = 0;
00028
00029 TString TTableDescriptor::fgCommentsName = ".comments";
00030 TableClassImp(TTableDescriptor,tableDescriptor_st)
00031
00032
00033 TTableDescriptor *TTableDescriptor::GetDescriptorPointer() const
00034 {
00035
00036 return fgColDescriptors;
00037 }
00038
00039
00040 void TTableDescriptor::SetDescriptorPointer(TTableDescriptor *list)
00041 {
00042
00043 fgColDescriptors = list;
00044 }
00045
00046
00047 void TTableDescriptor::SetCommentsSetName(const char *name)
00048 {
00049
00050 fgCommentsName = name;
00051 }
00052
00053
00054
00055 void TTableDescriptor::Streamer(TBuffer &R__b)
00056 {
00057
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
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
00079
00080
00081 Init(classPtr);
00082 }
00083
00084 TTableDescriptor::~TTableDescriptor()
00085 {
00086
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
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
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
00133
00134
00135 TTable::AddAt(dataset,idx);
00136 }
00137
00138
00139 void TTableDescriptor::AddAt(const tableDescriptor_st &element,const char *commentText,Int_t indx)
00140 {
00141
00142
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
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
00201
00202
00203 fSecondDescriptor = 0;
00204 SetType("tableDescriptor");
00205 if (classPtr) {
00206 fRowClass = classPtr;
00207 SetName(classPtr->GetName());
00208 LearnTable(classPtr);
00209 }
00210 else
00211 MakeZombie();
00212 }
00213
00214 void TTableDescriptor::LearnTable(const TTable *parentTable)
00215 {
00216
00217 if (!parentTable) {
00218 MakeZombie();
00219 return;
00220 }
00221 LearnTable(parentTable->GetRowClass());
00222 }
00223
00224
00225 void TTableDescriptor::LearnTable(TClass *classPtr)
00226 {
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
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
00260 elementDescriptor.fColumnName = StrDup(varname);
00261 #else
00262 elementDescriptor.fColumnName[0] = '\0';
00263 strncat(elementDescriptor.fColumnName,varname,sizeof(elementDescriptor.fColumnName)-1);
00264 #endif
00265
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
00309
00310
00311
00312
00313
00314
00315 TTableDescriptor *dsc = 0;
00316 TClass *cl = TClass::GetClass(structName, kTRUE);
00317
00318 assert(cl!=0);
00319 dsc = new TTableDescriptor(cl);
00320 return dsc;
00321 }
00322
00323 TDataSet *TTableDescriptor::MakeCommentField(Bool_t createFlag){
00324
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
00334
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;
00342
00343
00344 for (Int_t colCounter=0; colCounter < maxColumns; colCounter++) {
00345 Int_t colNewIndx = newDescriptor->ColumnByName(ColumnName(colCounter));
00346
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
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
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
00405
00406
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
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
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
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
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
00458 Int_t fullRowSize = 0;
00459 if (RowClass() ) fullRowSize = RowClass()->Size();
00460 else {
00461
00462 Int_t iLastRows = GetNRows()-1;
00463 if (iLastRows >=0) fullRowSize = Offset(iLastRows) + ColumnSize(iLastRows);
00464 }
00465 return fullRowSize;
00466 }
00467