StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TTableDescriptor.cxx
1 // @(#)root/table:$Id$
2 // Author: Valery Fine 09/08/99 (E-mail: fine@bnl.gov)
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include <stdlib.h>
13 
14 #include "TTableDescriptor.h"
15 #include "TTable.h"
16 #include "TClass.h"
17 #include "TDataMember.h"
18 #include "TDataType.h"
19 #include "Ttypes.h"
20 #include "TInterpreter.h"
21 
22 #include "TError.h"
23 
24 //______________________________________________________________________________
25 //
26 // TTableDescriptor - run-time descriptor of the TTable object rows.
27 //______________________________________________________________________________
28 
29 TTableDescriptor *TTableDescriptor::fgColDescriptors = 0;
30 // TString TTableDescriptor::fgCommentsName = TTableDescriptor::SetCommentsSetName();
31 TString TTableDescriptor::fgCommentsName = ".comments";
33 
36 
38 {
39  return fgColDescriptors;
40 }
41 
44 
46 {
47  fgColDescriptors = list;
48 }
49 
52 
54 {
55  fgCommentsName = name;
56 }
57 
58 
61 
62 void TTableDescriptor::Streamer(TBuffer &R__b)
63 {
64  fSecondDescriptor = 0;
65  TTable::Streamer(R__b);
66 }
67 
70 
72  : TTable("tableDescriptor",sizeof(tableDescriptor_st)), fRowClass(0),fSecondDescriptor(0)
73 {
74  if (parentTable) {
75  TClass *classPtr = parentTable->GetRowClass();
76  Init(classPtr);
77  }
78  else MakeZombie();
79 }
80 
85 
87  : TTable("tableDescriptor",sizeof(tableDescriptor_st)),fRowClass(0),fSecondDescriptor(0)
88 {
89  Init(classPtr);
90 }
93 
95 {
96 #ifdef NORESTRICTIONS
97  if (!IsZombie()) {
98  for (Int_t i=0;i<GetNRows();i++) {
99  Char_t *name = (Char_t *)ColumnName(i);
100  if (name) delete [] name;
101  UInt_t *indxArray = (UInt_t *)IndexArray(i);
102  if (indxArray) delete [] indxArray;
103  }
104  }
105 #endif
106  if (fSecondDescriptor != this) {
107  delete fSecondDescriptor;
108  fSecondDescriptor = 0;
109  }
110 }
111 
114 
115 Int_t TTableDescriptor::AddAt(const void *c)
116 {
117  if (!c) return -1;
118  TDataSet *cmnt = MakeCommentField();
119  R__ASSERT(cmnt!=0);
120 
121  return TTable::AddAt(c);
122 }
125 
126 void TTableDescriptor::AddAt(const void *c, Int_t i)
127 {
128  if (c) {
129  tableDescriptor_st *element = (tableDescriptor_st *)c;
130 #ifdef NORESTRICTIONS
131  const char *comment = element->fColumnName && element->fColumnName[0] ? element->fColumnName : "N/A";
132 #else
133  const char *comment = element->fColumnName[0] ? element->fColumnName : "N/A";
134 #endif
135  AddAt(*(tableDescriptor_st *)c,comment,i);
136  }
137 }
138 
143 
144 void TTableDescriptor::AddAt(TDataSet *dataset,Int_t idx)
145 {
146  TTable::AddAt(dataset,idx);
147 }
148 
152 
153 void TTableDescriptor::AddAt(const tableDescriptor_st &element,const char *commentText,Int_t indx)
154 {
155  TTable::AddAt(&element,indx);
156  TDataSet *cmnt = MakeCommentField();
157  R__ASSERT(cmnt!=0);
158  TDataSet *comment = new TDataSet(element.fColumnName);
159  comment->SetTitle(commentText);
160  cmnt->AddAtAndExpand(comment,indx);
161 }
162 
165 
167 {
168  const Char_t typeMapTBranch[]="\0FIISDiisbBC";
169  Int_t maxRows = NumberOfColumns();
170  TString string;
171  for (Int_t i=0;i<maxRows;i++){
172  if (i) string += ":";
173  UInt_t nDim = Dimensions(i);
174 
175  UInt_t totalSize = 1;
176  UInt_t k = 0;
177 
178  if (nDim) {
179  const UInt_t *indx = IndexArray(i);
180  if (!indx){
181  string = "";
182  Error("CreateLeafList()","Can not create leaflist for arrays");
183  return string;
184  }
185  for (k=0;k< nDim; k++) totalSize *= indx[k];
186  }
187  const Char_t *colName = ColumnName(i);
188  if (totalSize > 1) {
189  for ( k = 0; k < totalSize; k++) {
190  Char_t buf[10];
191  snprintf(buf,10,"_%d",k);
192  string += colName;
193  string += buf;
194  if (k==0) {
195  string += "/";
196  string += typeMapTBranch[ColumnType(i)];
197  }
198  if (k != totalSize -1) string += ":";
199  }
200  } else {
201  string += ColumnName(i);
202  string += "/";
203  string += typeMapTBranch[ColumnType(i)];
204  }
205  }
206  return string;
207 }
208 
213 
214 void TTableDescriptor::Init(TClass *classPtr)
215 {
216  fSecondDescriptor = 0;
217  SetType("tableDescriptor");
218  if (classPtr) {
219  fRowClass = classPtr; // remember my row class
220  SetName(classPtr->GetName());
221  LearnTable(classPtr);
222  }
223  else
224  MakeZombie();
225 }
228 
229 void TTableDescriptor::LearnTable(const TTable *parentTable)
230 {
231  if (!parentTable) {
232  MakeZombie();
233  return;
234  }
235  LearnTable(parentTable->GetRowClass());
236 }
237 
254 
255 void TTableDescriptor::LearnTable(TClass *classPtr)
256 {
257  if (!classPtr) return;
258 
259  if (!(classPtr->GetNdata())) return;
260 
261  Char_t *varname;
262 
263  tableDescriptor_st elementDescriptor;
264 
265  ReAllocate(classPtr->GetListOfDataMembers()->GetSize());
266  Int_t columnIndex = 0;
267  TIter next(classPtr->GetListOfDataMembers());
268  TDataMember *member = 0;
269  while ( (member = (TDataMember *) next()) ) {
270  memset(&elementDescriptor,0,sizeof(tableDescriptor_st));
271  varname = (Char_t *) member->GetName();
272 #ifdef NORESTRICTIONS
273 // This is remove to introduce an artificial restriction demanded by STAR infrastructure group
274  elementDescriptor.fColumnName = StrDup(varname);
275 #else
276  elementDescriptor.fColumnName[0] = '\0';
277  strncat(elementDescriptor.fColumnName,varname,sizeof(elementDescriptor.fColumnName)-1);
278 #endif
279  // define index
280  if (member->IsaPointer() ) {
281  elementDescriptor.fTypeSize = sizeof(void *);
282  const char *typeName = member->GetTypeName();
283  elementDescriptor.fType = TTable::GetTypeId(typeName);
284  } else {
285  TDataType *memberType = member->GetDataType();
286  R__ASSERT(memberType!=0);
287  elementDescriptor.fTypeSize = memberType->Size();
288  elementDescriptor.fType = TTable::GetTypeId(memberType->GetTypeName());
289  }
290  Int_t globalIndex = 1;
291  if (elementDescriptor.fType != kNAN) {
292  Int_t dim = 0;
293  if ( (dim = member->GetArrayDim()) ) {
294  elementDescriptor.fDimensions = dim;
295 #ifdef NORESTRICTIONS
296  elementDescriptor.fIndexArray = new UInt_t(dim);
297 #else
298  UInt_t maxDim = sizeof(elementDescriptor.fIndexArray)/sizeof(UInt_t);
299  if (UInt_t(dim) > maxDim) {
300  Error("LearnTable","Too many dimenstions - %d", dim);
301  dim = maxDim;
302  }
303 #endif
304  for( Int_t indx=0; indx < dim; indx++ ){
305  elementDescriptor.fIndexArray[indx] = member->GetMaxIndex(indx);
306  globalIndex *= elementDescriptor.fIndexArray[indx];
307  }
308  }
309  }
310  else Error("LearnTable","Wrong data type for <%s> structure",classPtr->GetName());
311  elementDescriptor.fSize = globalIndex * (elementDescriptor.fTypeSize);
312  elementDescriptor.fOffset = member->GetOffset();
313  AddAt(elementDescriptor,member->GetTitle(),columnIndex); columnIndex++;
314  }
315 }
316 
327 
329 {
330  TTableDescriptor *dsc = 0;
331  TClass *cl = TClass::GetClass(structName, kTRUE);
332 // TClass *cl = new TClass(structName,1,0,0);
333  R__ASSERT(cl!=0);
334  dsc = new TTableDescriptor(cl);
335  return dsc;
336 }
339 
341  TDataSet *comments = FindByName(fgCommentsName.Data());
342  if (!comments && createFlag)
343  comments = new TDataSet(fgCommentsName.Data(),this,kTRUE);
344  return comments;
345 }
350 
352 {
353  Int_t maxColumns = NumberOfColumns();
354  Int_t mismathes = 0;
355 
356  if ( (UInt_t(maxColumns) == newDescriptor->NumberOfColumns())
357  && (memcmp(GetArray(),newDescriptor->GetArray(),sizeof(tableDescriptor_st)*GetNRows()) == 0)
358  ) return mismathes; // everything fine for sure !
359 
360  // Something wrong here, we have to check things piece by piece
361  for (Int_t colCounter=0; colCounter < maxColumns; colCounter++) {
362  Int_t colNewIndx = newDescriptor->ColumnByName(ColumnName(colCounter));
363  // look for analog
364  EColumnType newType = colNewIndx >=0 ? newDescriptor->ColumnType(colNewIndx): kNAN;
365 #ifdef __STAR__
366  if (newType == kInt) newType = kLong;
367  else if (newType == kUInt) newType = kULong;
368 #endif
369  if ( colNewIndx >=0
370  && Dimensions(colCounter) == newDescriptor->Dimensions(colNewIndx)
371  && ColumnType(colCounter) == newType) {
372  Bool_t same = kFALSE;
373  if ( Dimensions(colCounter)) {
374  for (UInt_t d = 0; d < Dimensions(colCounter); d++) {
375  if (IndexArray(colCounter)[d] != newDescriptor->IndexArray(colNewIndx)[d]){ same = kTRUE; break; }
376  }
377  }
378  SetOffset(newDescriptor->Offset(colNewIndx),colCounter);
379  if (colNewIndx != colCounter) {
380  Printf("Schema evolution: \t%d column of the \"%s\" table has been moved to %d-th column\n",
381  colCounter,ColumnName(colCounter),colNewIndx);
382  mismathes++;
383  } else if (same) {
384  Printf("Schema evolution: \t%d column \"%s\" size has been changed\n",
385  colNewIndx, ColumnName(colCounter));
386  mismathes++;
387  }
388  } else {
389  Printf("Schema evolution: \t%d column \"%s\" of %d type has been lost\n",
390  colCounter,ColumnName(colCounter),ColumnType(colCounter));
391  Printf(" Indx = %d, name = %s \n", colNewIndx, ColumnName(colCounter));
392  SetOffset(UInt_t(-1),colCounter);
393  mismathes++;
394  }
395  }
396  if (!mismathes && UInt_t(maxColumns) != newDescriptor->NumberOfColumns()) {
397  mismathes++;
398  Printf("Warning: One extra column has been introduced\n");
399  }
400  return mismathes;
401 }
402 
405 
406 Int_t TTableDescriptor::ColumnByName(const Char_t *columnName) const
407 {
408  const tableDescriptor_st *elementDescriptor = ((TTableDescriptor *)this)->GetTable();
409  Int_t i = -1;
410  if (!elementDescriptor) return i;
411  Int_t nRows = GetNRows();
412  char *bracket = 0;
413  if (nRows) {
414  char *name = StrDup(columnName);
415  if ((bracket = strchr(name,'[')) ) *bracket = 0;
416  for (i=0; i < nRows; i++,elementDescriptor++)
417  if (strcmp(name,elementDescriptor->fColumnName) == 0) break;
418  delete [] name;
419  }
420  if (i==nRows) i = -1;
421  // Check array
422  if (bracket && !Dimensions(i)) {
423  i = -1;
424  Warning("ColumnByName","%s column contains a scalar value",columnName);
425  }
426  return i;
427 }
428 
433 
434 Int_t TTableDescriptor::Offset(const Char_t *columnName) const
435 {
436  Int_t offset = -1;
437  if (columnName) {
438  Int_t indx = ColumnByName(columnName);
439  if (indx >= 0 ) {
440  offset = Offset(indx);
441  const char *openBracket = 0;
442  if ( (openBracket = strchr(columnName,'[')) )
443  offset += atoi(openBracket+1)*TypeSize(indx);
444  }
445  }
446  return offset;
447 }
448 
451 
452 Int_t TTableDescriptor::ColumnSize(const Char_t *columnName) const
453 {
454  Int_t indx = ColumnByName(columnName);
455  if (indx >= 0 ) indx = ColumnSize(indx);
456  return indx;
457 }
458 
461 
462 Int_t TTableDescriptor::TypeSize(const Char_t *columnName) const
463 {
464  Int_t indx = ColumnByName(columnName);
465  if (indx >= 0 ) indx = TypeSize(indx);
466  return indx;
467 }
468 
471 
472 Int_t TTableDescriptor::Dimensions(const Char_t *columnName) const
473 {
474  Int_t indx = ColumnByName(columnName);
475  if (indx >= 0 ) indx = Dimensions(indx);
476  return indx;
477 }
478 
481 
482 TTable::EColumnType TTableDescriptor::ColumnType(const Char_t *columnName) const
483 {
484  Int_t indx = ColumnByName(columnName);
485  if (indx >= 0 ) indx = ColumnType(indx);
486  return EColumnType(indx);
487 }
490 
492 {
493  Int_t fullRowSize = 0;
494  if (RowClass() ) fullRowSize = RowClass()->Size();
495  else {
496  // Calculate the size myslef.
497  Int_t iLastRows = GetNRows()-1;
498  if (iLastRows >=0) fullRowSize = Offset(iLastRows) + ColumnSize(iLastRows);
499  }
500  return fullRowSize;
501 }
502 
void LearnTable(const TTable *parentTable)
to be documented
Definition: FJcore.h:367
virtual TClass * GetRowClass() const
to be documented
Definition: TTable.cxx:1375
void * ReAllocate()
Definition: TTable.cxx:1222
virtual void SetDescriptorPointer(TTableDescriptor *list)
set table descriptor
virtual void AddAtAndExpand(TDataSet *dataset, Int_t idx=0)
Definition: TDataSet.cxx:254
virtual TTableDescriptor * GetDescriptorPointer() const
return column descriptor
virtual Int_t UpdateOffsets(const TTableDescriptor *newDesciptor)
Int_t Sizeof() const
to be documented
Int_t ColumnByName(const Char_t *columnName=0) const
Find the column index but the column name.
virtual void Init(TClass *classPtr)
virtual Int_t AddAt(const void *c)
Append one row pointed by &quot;c&quot; to the descriptor.
virtual void SetType(const char *const type)
to be documented
Definition: TTable.cxx:1973
virtual Long_t GetNRows() const
Returns the number of the used rows for the wrapped table.
Definition: TTable.cxx:1388
virtual Int_t AddAt(const void *c)
Definition: TTable.cxx:1122
static EColumnType GetTypeId(const char *typeName)
Definition: TTable.cxx:292
static void SetCommentsSetName(const char *name=".comments")
set comments name
Definition: TTable.h:48
static TTableDescriptor * MakeDescriptor(const char *structName)
virtual TDataSet * FindByName(const char *name, const char *path="", Option_t *opt="") const
Definition: TDataSet.cxx:378
TString CreateLeafList() const
Create a list of leaf to be useful for TBranch::TBranch ctor.
virtual ~TTableDescriptor()
class destructor
TDataSet * MakeCommentField(Bool_t createFlag=kTRUE)
Instantiate a comment dataset if any.
TTableDescriptor(const TTable *parentTable)
to be documented