Logo ROOT   6.10/09
Reference Guide
TTableDescriptor.cxx
Go to the documentation of this file.
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 
30 // TString TTableDescriptor::fgCommentsName = TTableDescriptor::SetCommentsSetName();
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 ///return column descriptor
36 
38 {
39  return fgColDescriptors;
40 }
41 
42 ////////////////////////////////////////////////////////////////////////////////
43 ///set table descriptor
44 
46 {
47  fgColDescriptors = list;
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 ///set comments name
52 
54 {
56 }
57 
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// The custom Streamer for this table
61 
62 void TTableDescriptor::Streamer(TBuffer &R__b)
63 {
65  TTable::Streamer(R__b);
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 ///to be documented
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 
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Create a descriptor of the C-structure defined by TClass
83 /// TClass *classPtr must be a valid pointer to TClass object for
84 /// "plain" C_struture only !!!
85 
87  : TTable("tableDescriptor",sizeof(tableDescriptor_st)),fRowClass(0),fSecondDescriptor(0)
88 {
89  Init(classPtr);
90 }
91 ////////////////////////////////////////////////////////////////////////////////
92 /// class destructor
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 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Append one row pointed by "c" to the descriptor
114 
116 {
117  if (!c) return -1;
118  TDataSet *cmnt = MakeCommentField();
119  R__ASSERT(cmnt!=0);
120 
121  return TTable::AddAt(c);
122 }
123 ////////////////////////////////////////////////////////////////////////////////
124 ///Add one row pointed by "c" to the "i"-th row of the descriptor
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 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Add one dataset to the descriptor.
141 /// There is no new implementation here.
142 /// One needs it to avoid the "hidden method" compilation warning
143 
145 {
146  TTable::AddAt(dataset,idx);
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Add the descriptor element followed by its commentText
151 /// at the indx-th position of the descriptor (counted from zero)
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 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// Create a list of leaf to be useful for TBranch::TBranch ctor
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 
209 ////////////////////////////////////////////////////////////////////////////////
210 /// Create a descriptor of the C-structure defined by TClass
211 /// TClass *classPtr must be a valid pointer to TClass object for
212 /// "plain" C_structure only !!!
213 
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 }
226 ////////////////////////////////////////////////////////////////////////////////
227 ///to be documented
228 
229 void TTableDescriptor::LearnTable(const TTable *parentTable)
230 {
231  if (!parentTable) {
232  MakeZombie();
233  return;
234  }
235  LearnTable(parentTable->GetRowClass());
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 ///
240 /// LearnTable() creates an array of the descriptors for elements of the row
241 ///
242 /// It creates a descriptor of the C-structure defined by TClass
243 /// TClass *classPtr must be a valid pointer to TClass object for
244 /// "plain" C-structure only !!!
245 ///
246 /// This is to introduce an artificial restriction demanded by STAR database group
247 ///
248 /// 1. the name may be 31 symbols at most
249 /// 2. the number the dimension is 3 at most
250 ///
251 /// To lift this restriction one has to provide -DNORESTRICTIONS CPP symbol and
252 /// recompile code (and debug code NOW!)
253 ///
254 
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 
317 ////////////////////////////////////////////////////////////////////////////////
318 ////////////////////////////////////////////////////////////
319 ///
320 /// MakeDescriptor(const char *structName) - static method
321 /// structName - the name of the C structure
322 /// to create descriptor of
323 /// return a new instance of the TTableDescriptor or 0
324 /// if the "structName is not present with the dictionary
325 ///
326 ////////////////////////////////////////////////////////////
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 }
337 ////////////////////////////////////////////////////////////////////////////////
338 /// Instantiate a comment dataset if any
339 
341  TDataSet *comments = FindByName(fgCommentsName.Data());
342  if (!comments && createFlag)
343  comments = new TDataSet(fgCommentsName.Data(),this,kTRUE);
344  return comments;
345 }
346 ////////////////////////////////////////////////////////////////////////////////
347 /// "Schema evolution"
348 /// Method updates the offsets with a new ones from another descriptor
349 ///
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 
403 ////////////////////////////////////////////////////////////////////////////////
404 /// Find the column index but the column name
405 
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 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Return offset of the column defined by "columnName"
431 /// Take in account index if provided
432 /// Can not handle multidimensional indeces yet.
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 
449 ////////////////////////////////////////////////////////////////////////////////
450 ///to be documented
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 
459 ////////////////////////////////////////////////////////////////////////////////
460 ///to be documented
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 
469 ////////////////////////////////////////////////////////////////////////////////
470 ///to be documented
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 
479 ////////////////////////////////////////////////////////////////////////////////
480 ///to be documented
481 
483 {
484  Int_t indx = ColumnByName(columnName);
485  if (indx >= 0 ) indx = ColumnType(indx);
486  return EColumnType(indx);
487 }
488 ////////////////////////////////////////////////////////////////////////////////
489 ///to be documented
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 
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Int_t GetNdata()
Return the number of data members of this class Note that in case the list of data members is not yet...
Definition: TClass.cxx:4315
void LearnTable(const TTable *parentTable)
to be documented
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
void * ReAllocate()
Reallocate this table leaving only (used rows)+1 allocated GetTableSize() = GetNRows() + 1 returns a ...
Definition: TTable.cxx:1225
unsigned int fIndexArray[3]
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
unsigned int fOffset
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
virtual TClass * GetRowClass() const
to be documented
Definition: TTable.cxx:1378
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
#define R__ASSERT(e)
Definition: TError.h:96
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3562
Basic string class.
Definition: TString.h:129
virtual void AddAtAndExpand(TDataSet *dataset, Int_t idx=0)
!!!! Under construction !!!!! Add TDataSet object at the "idx" position in ds or at the end of the da...
Definition: TDataSet.cxx:254
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual Int_t UpdateOffsets(const TTableDescriptor *newDesciptor)
"Schema evolution" Method updates the offsets with a new ones from another descriptor ...
virtual TDataSet * FindByName(const char *name, const char *path="", Option_t *opt="") const
Full description see: TDataSetIter::Find.
Definition: TDataSet.cxx:378
static TTableDescriptor * fgColDescriptors
const UInt_t * IndexArray(Int_t columnIndex) const
TableClassImp(TTableDescriptor, tableDescriptor_st) TTableDescriptor *TTableDescriptor
return column descriptor
const Char_t * ColumnName(Int_t columnIndex) const
static TString fgCommentsName
virtual TTableDescriptor * GetDescriptorPointer() const
to be documented
UInt_t Offset(Int_t columnIndex) const
virtual void Init(TClass *classPtr)
Create a descriptor of the C-structure defined by TClass TClass *classPtr must be a valid pointer to ...
friend class TDataSet
Definition: TTable.h:49
EColumnType
Definition: TTable.h:82
UInt_t ColumnSize(Int_t columnIndex) const
TClass * RowClass() const
virtual Int_t AddAt(const void *c)
Append one row pointed by "c" to the descriptor.
TString CreateLeafList() const
Create a list of leaf to be useful for TBranch::TBranch ctor.
TTableDescriptor * fSecondDescriptor
UInt_t TypeSize(Int_t columnIndex) const
virtual void SetType(const char *const type)
to be documented
Definition: TTable.cxx:1982
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
unsigned int fSize
virtual Int_t AddAt(const void *c)
Add the "row" at the GetNRows() position, and reallocate the table if neccesary, and return the row i...
Definition: TTable.cxx:1125
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:873
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5348
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
void * GetArray() const
Definition: TTable.h:280
#define Printf
Definition: TGeoToOCC.h:18
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2524
const Bool_t kFALSE
Definition: RtypesCore.h:92
Bool_t IsZombie() const
Definition: TObject.h:122
TTable::EColumnType ColumnType(Int_t columnIndex) const
static EColumnType GetTypeId(const char *typeName)
return the Id of the C basic type by given name return kNAN if the name provided fits no knwn basic n...
Definition: TTable.cxx:291
unsigned int fDimensions
static void SetCommentsSetName(const char *name=".comments")
set comments name
UInt_t NumberOfColumns() const
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
unsigned int fTypeSize
Definition: TTable.h:48
void SetOffset(UInt_t offset, Int_t column)
static TTableDescriptor * MakeDescriptor(const char *structName)
MakeDescriptor(const char *structName) - static method structName - the name of the C structure to cr...
char Char_t
Definition: RtypesCore.h:29
virtual void SetDescriptorPointer(TTableDescriptor *list)
to be documented
virtual Long_t GetNRows() const
Returns the number of the used rows for the wrapped table.
Definition: TTable.cxx:1391
void MakeZombie()
Definition: TObject.h:49
Int_t Size() const
Get size of basic typedef&#39;ed type.
Definition: TDataType.cxx:366
#define snprintf
Definition: civetweb.c:822
virtual ~TTableDescriptor()
class destructor
Int_t ColumnByName(const Char_t *columnName=0) const
Find the column index but the column name.
virtual Int_t GetSize() const
Definition: TCollection.h:89
Int_t Sizeof() const
to be documented
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
const Bool_t kTRUE
Definition: RtypesCore.h:91
UInt_t Dimensions(Int_t columnIndex) const
TDataSet * MakeCommentField(Bool_t createFlag=kTRUE)
Instantiate a comment dataset if any.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:859
const char * Data() const
Definition: TString.h:347