StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TTable.cxx
1 // @(#)root/table:$Id$
2 // Author: Valery Fine(fine@bnl.gov) 03/07/98
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 
14 // //
15 // TTable //
16 // //
17 // Wraps the array of the plain C-structures (one C-structure per element)//
18 // //
19 // class TTable provides the automatic schema evolution for //
20 // the derived "table" classes saved with ROOT format. //
21 // //
22 // "Automatic Schema evolution" provides: //
23 // - skipping data-member if it is not present for the current //
24 // implementation of the "table" but was present at the time the //
25 // table was written; //
26 // - assign a default value ZERO for the brand-new data-members, //
27 // those were not in the structure when the object was written but //
28 // present now; //
29 // - trace propely any change in the order of the data-members //
30 // //
31 // To enjoy this class one has to derive one's own custom class: //
32 // //
33 // St_dst_track_Table.h: //
34 // --------------------- //
35 // #ifndef STAF_St_dst_track_Table //
36 // #define STAF_St_dst_track_Table //
37 // //
38 // #include "TTable.h" //
39 // //
40 // // #include "dst_track.h" the C-structure defintion may be kept //
41 // separately //
42 // typedef struct dst_track_st { //
43 // float r0; /* radius at start (cm). See also comments*/
44 // float phi0; /* azimuthal angle at start (deg) */
45 // float z0; /* z-coord. at start (cm) */
46 // float psi; /* azimuthal angle of pT vector (deg) */
47 // float tanl; /* tan(dip) =pz/pt at start */
48 // float invpt; /* 1/pt at start (GeV/c)^(-1) */
49 // float curvature; /* Track curvature (1/cm) */
50 // float covar[15]; /* full covariance matrix */
51 // float chisq[2]; /* Chi-square per degree of freedom */
52 // float x_first[3]; /* coord. of first measured point (cm) */
53 // float x_last[3]; /* coord. of last measured point (cm) */
54 // float length; /* from first to last point (cm) */
55 // float impact; /* primary vertex (cm) */
56 // unsigned long map[2]; /* extrap. info. (see preceding comments)*/
57 // int id; /* Primary key (see comments) */
58 // int iflag; /* bitmask quality info. (see comments) */
59 // int det_id; /* Detector id information */
60 // int method; /* Track finding/fitting method, packed */
61 // int pid; /* Geant particle ID for assumed mass */
62 // int n_point; /* SVT, TPC, FTPC component #s are packed */
63 // int n_max_point; /* SVT, TPC, FTPC component #s are packed */
64 // int n_fit_point; /* SVT, TPC, FTPC component #s are packed */
65 // int icharge; /* Particle charge in units of |e| */
66 // int id_start_vertex; /* final fit and primary track candidates */
67 // } DST_TRACK_ST; //
68 // //
69 // class St_dst_track : public TTable //
70 // { //
71 // public: //
72 // ClassDefTable(St_dst_track,dst_track_st) //
73 // ClassDef(St_dst_track,2) //C++ wrapper for <dst_track> StAF table //
74 // }; //
75 // #endif //
76 // --------------------- //
77 // //
78 // where the CPP macro defines several convinient methods for the //
79 // "table" class (see: $ROOTSYS/table/inc/Ttypes.h for details: //
80 // //
81 // #define ClassDefTable(className,structName)
82 // protected:
83 // static TTableDescriptor *fgColDescriptors;
84 // virtual TTableDescriptor *GetDescriptorPointer() const { return fgColDescriptors;}
85 // virtual void SetDescriptorPointer(TTableDescriptor *list) const { fgColDescriptors = list;}
86 // public:
87 // typedef structName* iterator;
88 // className() : TTable(_QUOTE_(className),sizeof(structName)) {SetType(_QUOTE_(structName));}
89 // className(const char *name) : TTable(name,sizeof(structName)) {SetType(_QUOTE_(structName));}
90 // className(Int_t n) : TTable(_QUOTE_(className),n,sizeof(structName)) {SetType(_QUOTE_(structName));}
91 // className(const char *name,Int_t n) : TTable(name,n,sizeof(structName)) {SetType(_QUOTE_(structName));}
92 // structName *GetTable(Int_t i=0) const { return ((structName *)GetArray())+i;}
93 // structName &operator[](Int_t i){ assert(i>=0 && i < GetNRows()); return *GetTable(i); }
94 // const structName &operator[](Int_t i) const { assert(i>=0 && i < GetNRows()); return *((const structName *)(GetTable(i))); }
95 // structName *begin() const { return GetNRows()? GetTable(0):0;}
96 // structName *end() const {Int_t i = GetNRows(); return i? GetTable(i):0;}
97 // //
98 // The class implementation file may 2 lines and look as follows: //
99 // (for the example above): //
100 // //
101 // St_dst_track_Table.cxx: //
102 // ----------------------- //
103 // #include "St_dst_track_Table.h" //
104 // TableClassImpl(St_dst_track, dst_track_st) //
105 // ----------------------- //
106 // LinkDef.h //
107 // ----------------------- //
108 // To provide ROOT I/O for this class TWO CINT dictonary entries //
109 // should be defined with your custom LinkDef.h file //
110 // 1. First entry (as usually) for the class derived from TTable //
111 // for example: //
112 // #pragma C++ class St_dst_track //
113 // 2. Second entry for the C-structure wrapped into the class. //
114 // Since C-structuire is not derived from TObject it must be //
115 // properly defined as "foreign" ROOT class //
116 // #pragma C++ class dst_track_st+; //
117 // ----------------------- //
118 // meta-variables i$ and n$ introduced //
119 // where "i$" stands for the current row index //
120 // "n$" stands for the total number of rows //
121 // meta-variable can be used along the normal //
122 // table column names in the expressions (see for example //
123 // method TTable::Draw //
124 // //
126 
127 #include <assert.h>
128 
129 #ifdef WIN32
130 # include <float.h>
131 #endif
132 
133 #include "RConfigure.h"
134 
135 //#if ROOT_VERSION_CODE >= ROOT_VERSION(3,03,5)
136 #include "Riostream.h"
137 //#include <iomanip.h>
138 
139 // #endif
140 
141 #include "TROOT.h"
142 #include "TBaseClass.h"
143 #include "TSystem.h"
144 #include "TBuffer.h"
145 #include "TMath.h"
146 #include "TClass.h"
147 #include "TBrowser.h"
148 #include "TString.h"
149 #include "TInterpreter.h"
150 #include "TDataSetIter.h"
151 #include "TTable.h"
152 #include "TTableDescriptor.h"
153 #include "TColumnView.h"
154 #include "TDatime.h"
155 
156 #include "TGaxis.h"
157 #include "TH1.h"
158 #include "TH2.h"
159 #include "TProfile.h"
160 #include "TVirtualPad.h"
161 #include "TEventList.h"
162 #include "TPolyMarker.h"
163 #include "TView.h"
164 #include "TGaxis.h"
165 #include "TPolyMarker3D.h"
166 
167 #include "THLimitsFinder.h"
168 
169 #include "TTableMap.h"
170 
171 static TH1 *gCurrentTableHist = 0;
172 
173 static const char *gDtorName = "dtor";
174 static Int_t gNbins[4] = {100,100,100,100}; //Number of bins per dimension
175 static Float_t gVmin[4] = {0,0,0,0}; //Minima of varexp columns
176 static Float_t gVmax[4] = {20,20,20,20}; //Maxima of varexp columns
177 
178 const char *TTable::fgTypeName[] = {
179  "NAN", "float", "int", "long", "short", "double",
180  "unsigned int", "unsigned long","unsigned short",
181  "unsigned char", "char", "Ptr_t"
182 };
183 
197 
198 static void ArrayLayout(UInt_t *layout,const UInt_t *size, Int_t dim)
199 {
200  if (dim && layout && size) {
201  if (++layout[dim-1] >= size[dim-1]) {
202  layout[dim-1] = 0;
203  dim--;
204  ArrayLayout(layout,size, dim);
205  }
206  }
207 }
208 
209 ClassImp(TTable);
210 
213 
215  assert(0);
216  return new TTableDescriptor(this);
217 }
218 
228 
229 void TTable::AsString(void *buf, EColumnType type, Int_t width,std::ostream &out) const
230 {
231  int prevPrec = out.precision();
232  const std::ios_base::fmtflags prevFmt = out.flags();
233 
234  switch (type) {
235  case kFloat:
236  out << std::dec << std::setw(width) << std::setprecision(width-3) << *(float *)buf;
237  break;
238  case kInt:
239  out << std::dec << std::setw(width) << *(int *)buf;
240  break;
241  case kLong:
242  out << std::dec << std::setw(width) << *(Long_t *)buf;
243  break;
244  case kShort:
245  out << std::dec << std::setw(width) << *(short *)buf;
246  break;
247  case kDouble:
248  out << std::dec << std::setw(width) << std::setprecision(width-3) << *(double *)buf;
249  break;
250  case kUInt:
251  out << std::dec << std::setw(width) << *(unsigned int *)buf;
252  break;
253  case kULong:
254  out << std::dec << std::setw(width) << *(ULong_t *)buf;
255  break;
256  case kUShort:
257  out << std::setw(width) << "0x" << std::hex << *(unsigned short *)buf;
258  break;
259  case kUChar:
260  out << std::setw(width) << "0x" << std::hex << int(*(unsigned char *)buf);
261  break;
262  case kChar:
263  out << std::setw(width) << *(char *)buf;
264  break;
265  case kBool:
266  out << std::setw(width) << *(Bool_t *)buf;
267  break;
268  case kPtr:
269  out << "->" << std::setw(width) << *(void **)buf;
270  break;
271  default:
272  out << "\"NaN\"";
273  break;
274  };
275  out.precision(prevPrec);
276  out.setf(prevFmt);
277 }
278 
281 
282 const char *TTable::GetTypeName(TTable::EColumnType type)
283 {
284  return fgTypeName[type];
285 }
286 
291 
292 TTable::EColumnType TTable::GetTypeId(const char *typeName)
293 {
294  Int_t allTypes = sizeof(fgTypeName)/sizeof(const char *);
295  for (int i = 0; i < allTypes; i++)
296  if (!strcmp(fgTypeName[i],typeName)) return EColumnType(i);
297  return kNAN;
298 }
299 
302 
303 const void *TTable::At(Int_t i) const
304 {
305  if (!BoundsOk("TTable::At", i)) {
306  Warning("TTable::At","%s.%s",GetName(),GetType());
307  i = 0;
308  }
309  return (const void *)(fTable+i*fSize);
310 }
311 
331 
332 Int_t TTable::CopyRows(const TTable *srcTable, Long_t srcRow, Long_t dstRow, Long_t nRows, Bool_t expand)
333 {
334  assert(!TestBit(kIsNotOwn));
335  if (!(srcTable && srcTable->GetNRows()) || srcRow > srcTable->GetNRows()-1 ) return 0;
336  if (strcmp(GetType(),srcTable->GetType())) {
337  // check this table current capacity
338  if (!nRows) nRows = srcTable->GetNRows();
339  Long_t tSize = GetTableSize();
340  Long_t extraRows = (tSize - dstRow) - nRows;
341  if (extraRows < 0) {
342  if (expand) {
343  ReAllocate(tSize - extraRows);
344  extraRows = 0;
345  }
346  nRows += extraRows;
347  }
348  if (dstRow+nRows > GetNRows()) SetNRows(dstRow+nRows);
349  ::memmove((*this)[dstRow],(*srcTable)[srcRow],(size_t)GetRowSize()*nRows);
350  return nRows;
351  } else
352  Error("CopyRows",
353  "This table is <%s> but the src table has a wrong type <%s>",GetType()
354  ,srcTable->GetType());
355  return 0;
356 }
363 
364 void TTable::DeleteRows(Long_t indx, UInt_t nRows)
365 {
366  if (CopyRows(this, indx+nRows, indx, GetNRows()-indx-nRows))
367  SetUsedRows(GetNRows() - nRows);
368 }
379 
380 TH1 *TTable::Draw(TCut varexp, TCut selection, Option_t *option, Int_t nentries, Int_t firstentry)
381 {
382  return TTable::Draw(varexp.GetTitle(), selection.GetTitle(), option, nentries, firstentry);
383 }
384 
479 
480 TH1 *TTable::Draw(const char *varexp00, const char *selection, Option_t *option,Int_t nentries, Int_t firstentry)
481 {
482  if (GetNRows() == 0 || varexp00 == 0 || varexp00[0]==0) return 0;
483  TString opt;
484 // char *hdefault = (char *)"htemp";
485  const char *hdefault = "htemp";
486  Int_t i,j,action;
487  Int_t hkeep = 0;
488  opt = option;
489  opt.ToLower();
490  char *varexp0 = StrDup(varexp00);
491  char *hname = strstr(varexp0,">>");
492  TH1 *oldh1 = 0;
493  TEventList *elist = 0;
494  Bool_t profile = kFALSE;
495 
496  gCurrentTableHist = 0;
497  if (hname) {
498  *hname = 0;
499  hname += 2;
500  hkeep = 1;
501  i = strcspn(varexp0,">>");
502  Bool_t hnameplus = kFALSE;
503  while (*hname == ' ') hname++;
504  if (*hname == '+') {
505  hnameplus = kTRUE;
506  hname++;
507  while (*hname == ' ') hname++;
508  j = strlen(hname)-1;
509  while (j) {
510  if (hname[j] != ' ') break;
511  hname[j] = 0;
512  j--;
513  }
514  }
515  if (i) {
516  oldh1 = (TH1*)gDirectory->Get(hname);
517  if (oldh1 && !hnameplus) oldh1->Reset();
518  } else {
519  elist = (TEventList*)gDirectory->Get(hname);
520  if (!elist) {
521  elist = new TEventList(hname,selection,1000,0);
522  }
523  if (elist && !hnameplus) elist->Reset();
524  }
525  }
526  if (!hname || *hname==0) {
527  hkeep = 0;
528  if (gDirectory) {
529  oldh1 = (TH1*)gDirectory->Get(hdefault);
530  if (oldh1 ) { oldh1->Delete(); oldh1 = 0;}
531  }
532  }
533 
534  // Look for colons
535  const Char_t *expressions[] ={varexp0,0,0,0,selection};
536  Int_t maxExpressions = sizeof(expressions)/sizeof(Char_t *);
537  Char_t *nextColon = varexp0;
538  Int_t colIndex = 1;
539  while ((nextColon = strchr(nextColon,':')) && ( colIndex < maxExpressions - 1 ) ) {
540  *nextColon = 0;
541  nextColon++;
542  expressions[colIndex] = nextColon;
543  colIndex++;
544  }
545 
546  expressions[colIndex] = selection;
547 
548 
550 
551  Printf(" Draw %s for <%s>\n", varexp00, selection);
552  Char_t *exprFileName = MakeExpression(expressions,colIndex+1);
553  if (!exprFileName) {
554  delete [] varexp0;
555  return 0;
556  }
557 
558 //--------------------------------------------------
559 // if (!fVar1 && !elist) return 0;
560 
561 //*-*- In case oldh1 exists, check dimensionality
562  Int_t dimension = colIndex;
563 
564  TString title = expressions[0];
565  for (i=1;i<colIndex;i++) {
566  title += ":";
567  title += expressions[i];
568  }
569  Int_t nsel = strlen(selection);
570  if (nsel > 1) {
571  if (nsel < 80-title.Length()) {
572  title += "{";
573  title += selection;
574  title += "}";
575  } else
576  title += "{...}";
577  }
578 
579  const Char_t *htitle = title.Data();
580 
581  if (oldh1) {
582  Int_t mustdelete = 0;
583  if (oldh1->InheritsFrom(TProfile::Class())) profile = kTRUE;
584  if (opt.Contains("prof")) {
585  if (!profile) mustdelete = 1;
586  } else {
587  if (oldh1->GetDimension() != dimension) mustdelete = 1;
588  }
589  if (mustdelete) {
590  Warning("Draw","Deleting old histogram with different dimensions");
591  delete oldh1; oldh1 = 0;
592  }
593  }
594 //*-*- Create a default canvas if none exists
595  if (!gPad && !opt.Contains("goff") && dimension > 0) {
596  gROOT->MakeDefCanvas();
597  }
598 //*-*- 1-D distribution
599  if (dimension == 1) {
600  action = 1;
601  if (!oldh1) {
602  gNbins[0] = 100;
603  if (gPad && opt.Contains("same")) {
604  TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
605  if (oldhtemp) {
606  gNbins[0] = oldhtemp->GetXaxis()->GetNbins();
607  gVmin[0] = oldhtemp->GetXaxis()->GetXmin();
608  gVmax[0] = oldhtemp->GetXaxis()->GetXmax();
609  } else {
610  gVmin[0] = gPad->GetUxmin();
611  gVmax[0] = gPad->GetUxmax();
612  }
613  } else {
614  action = -1;
615  }
616  }
617  TH1F *h1;
618  if (oldh1) {
619  h1 = (TH1F*)oldh1;
620  gNbins[0] = h1->GetXaxis()->GetNbins(); // for proofserv
621  } else {
622  h1 = new TH1F(hname,htitle,gNbins[0],gVmin[0],gVmax[0]);
623  if (!hkeep) {
624  h1->SetBit(kCanDelete);
625  h1->SetDirectory(0);
626  }
627  if (opt.Length() && opt[0] == 'e') h1->Sumw2();
628  }
629 
630  EntryLoop(exprFileName,action, h1, nentries, firstentry, option);
631 
632 // if (!fDraw && !opt.Contains("goff")) h1->Draw(option);
633  if (!opt.Contains("goff")) h1->Draw(option);
634 
635 //*-*- 2-D distribution
636  } else if (dimension == 2) {
637  action = 2;
638  if (!opt.Contains("same") && gPad) gPad->Clear();
639  if (!oldh1 || !opt.Contains("same")) {
640  gNbins[0] = 40;
641  gNbins[1] = 40;
642  if (opt.Contains("prof")) gNbins[1] = 100;
643  if (opt.Contains("same")) {
644  TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
645  if (oldhtemp) {
646  gNbins[1] = oldhtemp->GetXaxis()->GetNbins();
647  gVmin[1] = oldhtemp->GetXaxis()->GetXmin();
648  gVmax[1] = oldhtemp->GetXaxis()->GetXmax();
649  gNbins[0] = oldhtemp->GetYaxis()->GetNbins();
650  gVmin[0] = oldhtemp->GetYaxis()->GetXmin();
651  gVmax[0] = oldhtemp->GetYaxis()->GetXmax();
652  } else {
653  gNbins[1] = 40;
654  gVmin[1] = gPad->GetUxmin();
655  gVmax[1] = gPad->GetUxmax();
656  gNbins[0] = 40;
657  gVmin[0] = gPad->GetUymin();
658  gVmax[0] = gPad->GetUymax();
659  }
660  } else {
661  action = -2;
662  }
663  }
664  if (profile || opt.Contains("prof")) {
665  TProfile *hp;
666  if (oldh1) {
667  action = 4;
668  hp = (TProfile*)oldh1;
669  } else {
670  if (action < 0) action = -4;
671  if (opt.Contains("profs"))
672  hp = new TProfile(hname,htitle,gNbins[1],gVmin[1], gVmax[1],"s");
673  else
674  hp = new TProfile(hname,htitle,gNbins[1],gVmin[1], gVmax[1],"");
675  if (!hkeep) {
676  hp->SetBit(kCanDelete);
677  hp->SetDirectory(0);
678  }
679  }
680 
681  EntryLoop(exprFileName,action,hp,nentries, firstentry, option);
682 
683  if (!opt.Contains("goff")) hp->Draw(option);
684  } else {
685  TH2F *h2;
686  if (oldh1) {
687  h2 = (TH2F*)oldh1;
688  } else {
689  h2 = new TH2F(hname,htitle,gNbins[1],gVmin[1], gVmax[1], gNbins[0], gVmin[0], gVmax[0]);
690  if (!hkeep) {
691  const Int_t kNoStats = BIT(9);
692  h2->SetBit(kCanDelete);
693  h2->SetBit(kNoStats);
694  h2->SetDirectory(0);
695  }
696  }
697  Int_t noscat = strlen(option);
698  if (opt.Contains("same")) noscat -= 4;
699  if (noscat) {
700  EntryLoop(exprFileName,action,h2,nentries, firstentry, option);
701  // if (!fDraw && !opt.Contains("goff")) h2->Draw(option);
702  if (!opt.Contains("goff")) h2->Draw(option);
703  } else {
704  action = 12;
705  if (!oldh1 && !opt.Contains("same")) action = -12;
706  EntryLoop(exprFileName,action,h2,nentries, firstentry, option);
707 // if (oldh1 && !fDraw && !opt.Contains("goff")) h2->Draw(option);
708  if (oldh1 && !opt.Contains("goff")) h2->Draw(option);
709  }
710  }
711 
712 //*-*- 3-D distribution
713  } else if (dimension == 3) {
714  action = 13;
715  if (!opt.Contains("same")) action = -13;
716  EntryLoop(exprFileName,action,0,nentries, firstentry, option);
717 
718 //*-* an Event List
719  //} else if (elist) {
720  // action = 5;
721 // Int_t oldEstimate = fEstimate;
722 // SetEstimate(1);
723  // EntryLoop(exprFileName,action,elist,nentries, firstentry, option);
724 // SetEstimate(oldEstimate);
725  }
726  delete [] exprFileName;
727  delete [] varexp0;
728  return gCurrentTableHist;
729 }
730 
734 
735 static void FindGoodLimits(Int_t nbins, Int_t &newbins, Float_t &xmin, Float_t &xmax)
736 {
737  Double_t binlow=0,binhigh=0,binwidth=0;
738  Int_t n;
739  Double_t dx = 0.1*(xmax-xmin);
740  Double_t umin = xmin - dx;
741  Double_t umax = xmax + dx;
742  if (umin < 0 && xmin >= 0) umin = 0;
743  if (umax > 0 && xmax <= 0) umax = 0;
744 
745 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,03,5)
746  THLimitsFinder::Optimize(umin,umax,nbins,binlow,binhigh,n,binwidth,"");
747 #else
748  TGaxis::Optimize(umin,umax,nbins,binlow,binhigh,n,binwidth,"");
749 #endif
750 
751  if (binwidth <= 0 || binwidth > 1.e+39) {
752  xmin = -1;
753  xmax = 1;
754  } else {
755  xmin = binlow;
756  xmax = binhigh;
757  }
758 
759  newbins = nbins;
760 }
761 
784 
785 Bool_t TTable::EntryLoop(const Char_t *exprFileName,Int_t &action, TObject *obj
786  ,Int_t nentries, Int_t firstentry, Option_t *option)
787 {
788  Double_t rmin[3],rmax[3];
789  if (gInterpreter->LoadFile((Char_t *)exprFileName) < 0) {
790  Error("EntryLoop","Error: loading file %s",exprFileName);
791  return kFALSE; // can not load file
792  }
793 
794  // Float_t Selection(Float_t *results[], void *address[], int& i$, int n$)
795  // where i$ - meta variable to set current row index
796  // n$ - meta variable to set the total table size
797  const Char_t *funcName = "SelectionQWERTY";
798 #ifdef BYTECODE
799  const Char_t *argtypes = "Float_t *,float **, int&, int& ";
800  Long_t offset;
801  G__ClassInfo globals;
802  G__MethodInfo func = globals.GetMethod(funcName,argtypes,&offset);
803 
804  // Compile bytecode
805  struct G__bytecodefunc *pbc = func.GetBytecode();
806  if(!pbc) {
807  Error("EntryLoop","Bytecode compilation %s",funcName);
808  G__unloadfile((Char_t *)exprFileName);
809  return kFALSE; // can not get bytecode
810  }
811 #endif
812  // Prepare callfunc object
813  int i;
814  int nRows = GetNRows();
815  TTableDescriptor *tabsDsc = GetRowDescriptors();
816  tableDescriptor_st *descTable = tabsDsc->GetTable();
817  Float_t results[] = {1,1,1,1,1};
818  Char_t **addressArray = (Char_t **)new ULong_t[tabsDsc->GetNRows()];
819  Char_t *thisTable = (Char_t *)GetArray();
820  const Char_t *argtypes = "Float_t *,float **, int&, int& ";
821  Long_t offset;
822  ClassInfo_t *globals = gInterpreter->ClassInfo_Factory();
823  CallFunc_t *callfunc = gInterpreter->CallFunc_Factory();
824  gInterpreter->CallFunc_SetFunc(callfunc,globals,funcName,argtypes,&offset);
825 
826  gInterpreter->CallFunc_SetArg(callfunc,(Long_t)(&results[0])); // give 'Float_t *results[5]' as 1st argument
827  gInterpreter->CallFunc_SetArg(callfunc,(Long_t)(addressArray)); // give 'void *addressArray[]' as 2nd argument
828  gInterpreter->CallFunc_SetArg(callfunc,(Long_t)(&i)); // give 'int& i$' as 3nd argument
829  gInterpreter->CallFunc_SetArg(callfunc,(Long_t)(&nRows)); // give 'int& n$= nRows as 4th argument
830 
831  // Call bytecode in loop
832 
833 #define CALLMETHOD gInterpreter->CallFunc_Exec(callfunc,0);
834 
835 #define TAKEACTION_BEGIN \
836  descTable = tabsDsc->GetTable(); \
837  for (i=0; i < tabsDsc->GetNRows(); i++,descTable++ ) \
838  addressArray[i] = addressEntry + descTable->fOffset; \
839  for(i=firstentry;i<lastEntry;i++) { \
840  CALLMETHOD
841 
842 #define TAKEACTION_END for (int j=0; j < tabsDsc->GetNRows(); j++ ) addressArray[j] += rSize;}
843 
844 
845  if (firstentry < nRows ) {
846  Long_t rSize = GetRowSize();
847  Char_t *addressEntry = thisTable + rSize*firstentry;
848  Int_t lastEntry = TMath::Min(UInt_t(firstentry+nentries),UInt_t(nRows));
849  if (action < 0) {
850  gVmin[0] = gVmin[1] = gVmin[2] = 1e30;
851  gVmax[0] = gVmax[1] = gVmax[2] = -gVmin[0];
852  }
853  Int_t nchans = 0;
854  switch ( action ) {
855  case -1: {
856  TAKEACTION_BEGIN
857  if (results[1]) {
858  if (gVmin[0] > results[0]) gVmin[0] = results[0];
859  if (gVmax[0] < results[0]) gVmax[0] = results[0];
860  }
861  TAKEACTION_END
862 
863  nchans = gNbins[0];
864  if (gVmin[0] >= gVmax[0]) { gVmin[0] -= 1; gVmax[0] += 1;}
865  FindGoodLimits(nchans,gNbins[0],gVmin[0],gVmax[0]);
866  ((TH1 *)obj)->SetBins(gNbins[0],gVmin[0],gVmax[0]);
867  }
868  // Intentional fall though
869  case 1:
870  TAKEACTION_BEGIN
871  if (results[1]) ((TH1 *)obj)->Fill(Axis_t(results[0]),Stat_t(results[1]));
872  TAKEACTION_END
873  gCurrentTableHist = ((TH1 *)obj);
874  break;
875  case -2:
876  TAKEACTION_BEGIN
877  if (results[2]) {
878  if (gVmin[0] > results[1]) gVmin[0] = results[1];
879  if (gVmax[0] < results[1]) gVmax[0] = results[1];
880  if (gVmin[1] > results[0]) gVmin[1] = results[0];
881  if (gVmax[1] < results[0]) gVmax[1] = results[0];
882  }
883  TAKEACTION_END
884  nchans = gNbins[0];
885  if (gVmin[0] >= gVmax[0]) { gVmin[0] -= 1; gVmax[0] += 1;}
886  FindGoodLimits(nchans,gNbins[0],gVmin[0],gVmax[0]);
887  if (gVmin[1] >= gVmax[1]) { gVmin[1] -= 1; gVmax[1] += 1;}
888  FindGoodLimits(nchans,gNbins[1],gVmin[1],gVmax[1]);
889  ((TH1*)obj)->SetBins(gNbins[1],gVmin[1],gVmax[1],gNbins[0],gVmin[0],gVmax[0]);
890  // Intentional fall though
891  case 2:
892  if (obj->IsA() == TH2F::Class()) {
893  TAKEACTION_BEGIN
894  if (results[2]) ((TH2F*)obj)->Fill(Axis_t(results[0]),Axis_t(results[1]),Stat_t(results[2]));
895  TAKEACTION_END
896  } else if (obj->IsA() == TH2S::Class()) {
897  TAKEACTION_BEGIN
898  if (results[2]) ((TH2S*)obj)->Fill(Axis_t(results[0]),Axis_t(results[1]),Stat_t(results[2]));
899  TAKEACTION_END
900  } else if (obj->IsA() == TH2C::Class()) {
901  TAKEACTION_BEGIN
902  if (results[2]) ((TH2C*)obj)->Fill(Axis_t(results[0]),Axis_t(results[1]),Stat_t(results[2]));
903  TAKEACTION_END
904  } else if (obj->IsA() == TH2D::Class()) {
905  TAKEACTION_BEGIN
906  if (results[2]) ((TH2D*)obj)->Fill(Axis_t(results[0]),Axis_t(results[1]),Stat_t(results[2]));
907  TAKEACTION_END
908  }
909  gCurrentTableHist = ((TH1 *)obj);
910  break;
911  case -4:
912  TAKEACTION_BEGIN
913  if (results[2]) {
914  if (gVmin[0] > results[1]) gVmin[0] = results[1];
915  if (gVmax[0] < results[1]) gVmax[0] = results[1];
916  if (gVmin[1] > results[0]) gVmin[1] = results[0];
917  if (gVmax[1] < results[0]) gVmax[1] = results[0];
918  }
919  TAKEACTION_END
920  nchans = gNbins[1];
921  if (gVmin[1] >= gVmax[1]) { gVmin[1] -= 1; gVmax[1] += 1;}
922  FindGoodLimits(nchans,gNbins[1],gVmin[1],gVmax[1]);
923  ((TProfile*)obj)->SetBins(gNbins[1],gVmin[1],gVmax[1]);
924  // Intentional fall though
925  case 4:
926  TAKEACTION_BEGIN
927  if (results[2]) ((TProfile*)obj)->Fill(Axis_t(results[0]),Axis_t(results[1]),Stat_t(results[2]));
928  TAKEACTION_END
929  break;
930  case -12:
931  TAKEACTION_BEGIN
932  if (results[2]) {
933  if (gVmin[0] > results[1]) gVmin[0] = results[1];
934  if (gVmax[0] < results[1]) gVmax[0] = results[1];
935  if (gVmin[1] > results[0]) gVmin[1] = results[0];
936  if (gVmax[1] < results[0]) gVmax[1] = results[0];
937  }
938  TAKEACTION_END
939  nchans = gNbins[0];
940  if (gVmin[0] >= gVmax[0]) { gVmin[0] -= 1; gVmax[0] += 1;}
941  FindGoodLimits(nchans,gNbins[0],gVmin[0],gVmax[0]);
942  if (gVmin[1] >= gVmax[1]) { gVmin[1] -= 1; gVmax[1] += 1;}
943  FindGoodLimits(nchans,gNbins[1],gVmin[1],gVmax[1]);
944  ((TH2F*)obj)->SetBins(gNbins[1],gVmin[1],gVmax[1],gNbins[0],gVmin[0],gVmax[0]);
945  // Intentional fall though
946  case 12: {
947  if (!strstr(option,"same") && !strstr(option,"goff")) {
948  ((TH2F*)obj)->DrawCopy(option);
949  gPad->Update();
950  }
951 // pm->SetMarkerStyle(GetMarkerStyle());
952 // pm->SetMarkerColor(GetMarkerColor());
953 // pm->SetMarkerSize(GetMarkerSize());
954  Float_t *x = new Float_t[lastEntry-firstentry]; // pm->GetX();
955  Float_t *y = new Float_t[lastEntry-firstentry]; // pm->GetY();
956  Float_t u, v;
957  Float_t umin = gPad->GetUxmin();
958  Float_t umax = gPad->GetUxmax();
959  Float_t vmin = gPad->GetUymin();
960  Float_t vmax = gPad->GetUymax();
961  Int_t pointIndex = 0;
962  TAKEACTION_BEGIN
963  if (results[2]) {
964  u = gPad->XtoPad(results[0]);
965  v = gPad->YtoPad(results[1]);
966  if (u < umin) u = umin;
967  if (u > umax) u = umax;
968  if (v < vmin) v = vmin;
969  if (v > vmax) v = vmax;
970  x[pointIndex] = u;
971  y[pointIndex] = v;
972  pointIndex++;
973  }
974  TAKEACTION_END
975  if (pointIndex && !strstr(option,"goff")) {
976  TPolyMarker *pm = new TPolyMarker(pointIndex,x,y);
977  pm->Draw();
978  pm->SetBit(kCanDelete);
979  }
980  if (!((TH2F*)obj)->TestBit(kCanDelete))
981  if (pointIndex)
982  for(i=0;i<pointIndex;i++) ((TH2F*)obj)->Fill(x[i], y[i]);
983  delete [] x; delete [] y;
984  gCurrentTableHist = ((TH1*)obj);
985  }
986  break;
987  case -13:
988  TAKEACTION_BEGIN
989  if (results[3]) {
990  if (gVmin[0] > results[2]) gVmin[0] = results[2];
991  if (gVmax[0] < results[2]) gVmax[0] = results[2];
992  if (gVmin[1] > results[1]) gVmin[1] = results[1];
993  if (gVmax[1] < results[1]) gVmax[1] = results[1];
994  if (gVmin[2] > results[0]) gVmin[2] = results[0];
995  if (gVmax[2] < results[0]) gVmax[2] = results[0];
996  }
997  TAKEACTION_END
998  rmin[0] = gVmin[2]; rmin[1] = gVmin[1]; rmin[2] = gVmin[0];
999  rmax[0] = gVmax[2]; rmax[1] = gVmax[1]; rmax[2] = gVmax[0];
1000  gPad->Clear();
1001  gPad->Range(-1,-1,1,1);
1002  TView::CreateView(1,rmin,rmax);
1003  // Intentional fall though
1004  case 13: {
1005  TPolyMarker3D *pm3d = new TPolyMarker3D(lastEntry-firstentry);
1006  pm3d->SetBit(kCanDelete);
1007 // pm3d->SetMarkerStyle(GetMarkerStyle());
1008 // pm3d->SetMarkerColor(GetMarkerColor());
1009 // pm3d->SetMarkerSize(GetMarkerSize());
1010  TAKEACTION_BEGIN
1011  if (results[3]) pm3d->SetNextPoint(results[0],results[1],results[2]);
1012  TAKEACTION_END
1013  pm3d->Draw();
1014  }
1015  break;
1016  default:
1017  Error("EntryLoop","unknown action \"%d\" for table <%s>", action, GetName());
1018  break;
1019  };
1020  }
1021  gInterpreter->CallFunc_Delete(callfunc);
1022  gInterpreter->ClassInfo_Delete(globals);
1023  gInterpreter->UnloadFile((Char_t *)exprFileName);
1024  delete [] addressArray;
1025  return kTRUE;
1026 }
1027 
1030 
1031 TTable::TTable(const char *name, Int_t size) : TDataSet(name),
1032  fSize(size),fN(0), fTable(0),fMaxIndex(0)
1033 {
1034  if (size == 0) Warning("TTable(0)","Wrong table format");
1035 }
1036 
1039 
1040 TTable::TTable(const char *name, Int_t n,Int_t size) : TDataSet(name),
1041  fSize(size),fN(0),fTable(0),fMaxIndex(0)
1042 {
1043  if (n > 0) Set(n);
1044 }
1045 
1048 
1049 TTable::TTable(const char *name, Int_t n, Char_t *table,Int_t size) : TDataSet(name),
1050  fSize(size),fN(0),fTable(0),fMaxIndex(0)
1051 {
1052  Set(n, table);
1053 }
1054 
1057 
1058 TTable::TTable(const char *name, const char *type, Int_t n, Char_t *array, Int_t size)
1059  : TDataSet(name),fSize(size),fTable(0),fMaxIndex(0)
1060 {
1061  fTable = array;
1062  SetType(type);
1063  SetfN(n);
1064 }
1065 
1068 
1069 TTable::TTable(const TTable &table):TDataSet(table)
1070 {
1071  fTable = 0;
1072  SetUsedRows(table.GetNRows());
1073  fSize = table.GetRowSize();
1074  SetfN(table.fN);
1075  Set(table.fN, table.fTable);
1076 }
1077 
1082 
1084 {
1085  if (strcmp(GetType(),rhs.GetType()) == 0) {
1086  if (this != &rhs && rhs.GetNRows() >0 ){
1087  Set(rhs.GetNRows(), rhs.fTable);
1088  SetUsedRows(rhs.GetNRows());
1089  }
1090  } else
1091  Error("operator=","Can not copy <%s> table into <%s> table", rhs.GetType(),GetType());
1092  return *this;
1093 }
1094 
1097 
1099 {
1100  Delete();
1101 }
1102 
1106 
1107 void TTable::Adopt(Int_t n, void *arr)
1108 {
1109  Clear();
1110 
1111  SetfN(n); SetUsedRows(n);
1112  fTable = (char *)arr;
1113 }
1114 
1121 
1122 Int_t TTable::AddAt(const void *row)
1123 {
1124  Int_t gap = GetTableSize() - GetNRows();
1125  // do we need to add an extra space?
1126  if (gap < 1) ReAllocate(GetTableSize() + TMath::Max(1,Int_t(0.3*GetTableSize())));
1127  Int_t indx = GetNRows();
1128  AddAt(row,indx);
1129  return indx;
1130 }
1137 
1138 void TTable::AddAt(const void *row, Int_t i)
1139 {
1140  if (!BoundsOk("TTable::AddAt", i))
1141  i = 0;
1142  if (row) memcpy(fTable+i*fSize,row,fSize);
1143  else memset(fTable+i*fSize,127,fSize);
1144  SetUsedRows(TMath::Max((Int_t)i+1,Int_t(fMaxIndex)));
1145 }
1146 
1150 
1151 void TTable::CopyStruct(Char_t *dest, const Char_t *src)
1152 {
1153  ::memcpy(dest,src,fSize*fN);
1154 }
1157 
1159 {
1160  array.Set(fN);
1161  CopyStruct(array.fTable,fTable);
1162 }
1165 
1166 const Char_t *TTable::GetColumnComment(Int_t columnIndex) const {
1167  TDataSetIter nextComment(GetRowDescriptors()->MakeCommentField(kFALSE));
1168  TDataSet *nxc = 0;
1169  for (int i=0; i<= columnIndex; i++) nxc = nextComment();
1170  return nxc ? nxc->GetTitle() : 0;
1171 }
1177 
1178 Long_t TTable::AppendRows(const void *row, UInt_t nRows)
1179 {
1180  if (!TestBit(kIsNotOwn) && row && nRows ) {
1181  Int_t indx = GetNRows();
1182  ReAllocate(nRows);
1183  // Copy (insert) the extra staff in
1184  ::memmove(fTable+indx*fSize,row,fSize*nRows);
1185  }
1186  return TestBit(kIsNotOwn) ? 0 : GetSize();
1187 }
1202 
1203 Long_t TTable::InsertRows(const void *row, Long_t indx, UInt_t nRows)
1204 {
1205  Long_t nShifted = 0;
1206  if (nRows > 0) {
1207  // Shift the table down
1208  nShifted = CopyRows(this, indx, indx+nRows, GetNRows()+nRows);
1209  // Copy (insert) the extra staff in
1210  ::memmove(fTable+indx*fSize,row,fSize*nRows);
1211  }
1212  return nShifted;
1213 
1214 }
1221 
1223 {
1224  ReAlloc(GetNRows()+1);
1225  return (void *)fTable;
1226 }
1233 
1234 void *TTable::ReAllocate(Int_t newsize)
1235 {
1236  if (newsize > fN) ReAlloc(newsize);
1237  return (void *)fTable;
1238 }
1239 
1242 
1243 void TTable::ReAlloc(Int_t newsize)
1244 {
1245  if (!TestBit(kIsNotOwn) && newsize > 0) {
1246  void *arr = 0;
1247  Int_t sleepCounter = 0;
1248  while (!(arr = realloc(fTable,fSize*newsize))) {
1249  sleepCounter++;
1250  Warning("ReAlloc",
1251  "Not enough memory to Reallocate %d bytes for table <%s::%s>. Please cancel some jobs",
1252  newsize, GetType(),GetName());
1253  gSystem->Sleep(1000*600);
1254  if (sleepCounter > 30) {
1255  Error("ReAlloc","I can not wait anymore. Good bye");
1256  assert(0);
1257  }
1258  }
1259  SetfN(newsize);
1260  fTable = (char *)arr;
1261  }
1262 }
1263 
1267 
1269 {
1270  if (!fTable) {
1271  void *ptr = 0;
1272  Int_t sleepCounter = 0;
1273  while (!(ptr = malloc(fSize*fN))) {
1274  sleepCounter++;
1275  Warning("Create",
1276  "Not enough memory to allocate %d rows for table <%s::%s>. Please cancel some jobs",
1277  fN, GetType(),GetName());
1278  gSystem->Sleep(1000*600);
1279  if (sleepCounter > 30){
1280  Error("Create","I can not wait anymore. Good bye");
1281  assert(0);
1282  }
1283  }
1284  fTable = (Char_t *)ptr;
1285  // make sure all link-columns are zero
1286  memset(fTable,0,fSize*fN);
1287  }
1288  return fTable;
1289 }
1290 
1293 
1294 void TTable::Browse(TBrowser *b){
1295  if (!b) return;
1296  TDataSet::Browse(b);
1297  Int_t nrows = TMath::Min(Int_t(GetNRows()),6);
1298  if (nrows == 0) nrows = 1;
1299  Print(0,nrows);
1300  // Add the table columns to the browser
1301  UInt_t nCol = GetNumberOfColumns();
1302  for (UInt_t i = 0;i<nCol;i++){
1303  TColumnView *view = 0;
1304  UInt_t nDim = GetDimensions(i);
1305  const Char_t *colName = GetColumnName(i);
1306  if (!nDim) { // scalar
1307  // This will cause a small memory leak
1308  // unless TBrowser recognizes kCanDelete bit
1309  if( GetColumnType(i)== kPtr) {
1310  UInt_t offset = GetOffset(i);
1311  TTableMap *m = *(TTableMap **)(((char *)GetArray())+offset);
1312  if (m) {
1313  TString nameMap = "*";
1314  nameMap += m->Table()->GetName();
1315  b->Add(m,nameMap.Data());
1316  }
1317  } else {
1318  view = new TColumnView(GetColumnName(i),this);
1319  view->SetBit(kCanDelete);
1320  b->Add(view,view->GetName());
1321  }
1322  } else { // array
1323  const UInt_t *indx = GetIndexArray(i);
1324  UInt_t totalSize = 1;
1325  UInt_t k;
1326  for (k=0;k<nDim; k++) totalSize *= indx[k];
1327  for (k=0;k<totalSize;k++) {
1328  TString buffer;
1329  buffer.Form("%s[%d]",colName,k);
1330  view = new TColumnView(buffer,this);
1331  view->SetBit(kCanDelete);
1332  b->Add(view,view->GetName());
1333  }
1334  }
1335  }
1336 }
1337 
1341 
1342 void TTable::Clear(Option_t *opt)
1343 {
1344  if (!fTable) return;
1345  Bool_t dtor = kFALSE;
1346  dtor = opt && (strcmp(opt,gDtorName)==0);
1347  if (!opt || !opt[0] || dtor ) {
1348  if (! TestBit(kIsNotOwn)) {
1349  if (!dtor) ResetMap();
1350  free(fTable);
1351  }
1352  fTable = 0;
1353  fMaxIndex = 0;
1354  SetfN(0);
1355  return;
1356  }
1357 }
1358 
1365 
1366 void TTable::Delete(Option_t *opt)
1367 {
1368  Clear(gDtorName);
1369  TDataSet::Delete(opt);
1370 }
1371 
1374 
1375 TClass *TTable::GetRowClass() const
1376 {
1377  TClass *cl = 0;
1379  if (dsc) cl = dsc->RowClass();
1380  else Error("GetRowClass()","Table descriptor of <%s::%s> table lost",
1381  GetName(),GetType());
1382  return cl;
1383 }
1384 
1387 
1388 Long_t TTable::GetNRows() const {
1389  return fMaxIndex;
1390 }
1391 
1394 
1395 Long_t TTable::GetRowSize() const {
1396  return fSize;
1397 }
1398 
1401 
1402 Long_t TTable::GetTableSize() const {
1403  return fN;
1404 }
1405 
1421 
1422 void TTable::Fit(const char *formula ,const char *varexp, const char *selection,Option_t *option ,Option_t *goption,Int_t nentries, Int_t firstentry)
1423 {
1424  TString opt(option);
1425  opt += "goff";
1426 
1427  Draw(varexp,selection,opt,nentries,firstentry);
1428 
1429  TH1 *hfit = gCurrentTableHist;
1430  if (hfit) {
1431  Printf("hname=%s, formula=%s, option=%s, goption=%s\n",hfit->GetName(),formula,option,goption);
1432  // remove bit temporary
1433  Bool_t canDeleteBit = hfit->TestBit(kCanDelete);
1434  if (canDeleteBit) hfit->ResetBit(kCanDelete);
1435  hfit->Fit(formula,option,goption);
1436  if (TestBit(canDeleteBit)) hfit->SetBit(kCanDelete);
1437  }
1438  else Printf("ERROR hfit=0\n");
1439 }
1440 
1443 
1444 const Char_t *TTable::GetType() const
1445 {
1446  return GetTitle();
1447 }
1448 
1455 
1456 Bool_t TTable::IsFolder() const {
1457  return kTRUE; // to provide the "fake" folder bit to workaround TKey::Browse()
1458 
1459 #if 0
1460  // this became useless due TKey::Browse new implementation
1461  return
1462  (fList && fList->Last() ? kTRUE : kFALSE)
1463  ||
1464  (GetNRows() > 0);
1465 #endif
1466 }
1467 
1473 
1475 {
1476  EColumnType code;
1477  char const *cell,*colname,*table;
1478  double word;
1479  int icol,irow,colsize,wordsize,nwords,iword,nerr,offset;
1480 
1481  TTableDescriptor *rowDes = GetRowDescriptors();
1482  assert(rowDes!=0);
1483  table = (const char*)GetArray();
1484 
1485  int ncols = rowDes->GetNumberOfColumns();
1486 
1487  int lrow = GetRowSize();
1488  int nrows = GetNRows ();
1489  nerr =0;
1490  for (icol=0; icol < ncols; icol++) {// loop over cols
1491  code = rowDes->GetColumnType(icol);
1492  if (code!=kFloat && code!=kDouble) continue;
1493 
1494  offset = rowDes->GetOffset (icol);
1495  colsize = rowDes->GetColumnSize(icol);
1496  wordsize = rowDes->GetTypeSize (icol);
1497  nwords = colsize/wordsize;
1498  for (irow=0; irow < nrows; irow++) { //loop over rows
1499  cell = table + offset + irow*lrow;
1500  for (iword=0;iword<nwords; iword++,cell+=wordsize) { //words in col
1501  word = (code==kDouble) ? *(double*)cell : *(float*)cell;
1502  if (TMath::Finite(word)) continue;
1503 // ERROR FOUND
1504  nerr++; colname = rowDes->GetColumnName(icol);
1505  Warning("NaN"," Table %s.%s.%d\n",GetName(),colname,irow);
1506  }
1507  }
1508  }
1509  return nerr;
1510 }
1511 
1514 
1515 TTable *TTable::New(const Char_t *name, const Char_t *type, void *array, UInt_t size)
1516 {
1517  TTable *table = 0;
1518  if (type && name) {
1519  TString tableType(type);
1520  TString t = tableType.Strip();
1521 
1522  TString classname("St_");
1523  classname += t;
1524  TClass *cl = TClass::GetClass(classname);
1525  if (cl) {
1526  table = (TTable *)cl->New();
1527  if (table) {
1528  table->SetTablePointer(array);
1529  table->SetName(name);
1530  table->SetfN(size);
1531  table->SetUsedRows(size);
1532  }
1533  }
1534  }
1535  return table;
1536 }
1539 
1540 Bool_t TTable::OutOfBoundsError(const char *where, Int_t i) const
1541 {
1542  Error(where, "index %d out of bounds (size: %d, this: 0x%lx)", i, fN, (Long_t)this);
1543  return kFALSE;
1544 }
1547 
1548 Char_t *TTable::Print(Char_t *strbuf,Int_t lenbuf) const
1549 {
1550  Int_t iOut = 0;
1551 
1553  if (!dscT ) {
1554  Error("Print"," No dictionary entry for <%s> structure", GetTitle());
1555  if (lenbuf>0) iOut += snprintf(strbuf,lenbuf," *** Errror ***");
1556  return strbuf;
1557  }
1558 
1559  TROOT::IndentLevel();
1560  if (lenbuf>0) {
1561  // cut of the "_st" suffix
1562  Char_t *typenam = new Char_t [strlen(dscT->GetName())+1];
1563  strlcpy(typenam,dscT->GetName(),strlen(dscT->GetName())+1);
1564  // look for the last "_"
1565  Char_t *last = strrchr(typenam,'_');
1566  // Check whether it is "_st"
1567  Char_t *eon = 0;
1568  if (last) eon = strstr(last,"_st");
1569  // Cut it off if any
1570  if (eon) *eon = '\0';
1571  iOut += snprintf(strbuf+iOut,lenbuf-iOut,"struct %s {",typenam);
1572  delete [] typenam;
1573  } else {
1574  std::cout << "struct " << dscT->GetName() << " {" << std::endl;
1575  }
1576 
1577  TTableDescriptor::iterator dsc = dscT->begin();
1578  TTableDescriptor::iterator dscE = dscT->end();
1579  TDataSetIter nextComment(dscT->MakeCommentField(kFALSE));
1580  for (;dsc != dscE; ++dsc) {
1581  TROOT::IndentLevel();
1582  TString name = GetTypeName(EColumnType((*dsc).fType));
1583  if (lenbuf>0) {
1584  // convert C type names to CORBA type names
1585  name.ReplaceAll("unsigned char","octet");
1586  name.ReplaceAll("int","long");
1587  iOut += snprintf(strbuf+iOut,lenbuf-iOut," %s %s",name.Data(),(*dsc).fColumnName);
1588  } else
1589  std::cout << '\t'<< name.Data() << '\t'<< (*dsc).fColumnName;
1590 
1591  Int_t indx;
1592  Int_t dim = (*dsc).fDimensions;
1593  for (indx = 0; indx < dim; indx++) {
1594  if (lenbuf>0)
1595  iOut += snprintf(strbuf+iOut,lenbuf-iOut,"[%d]",(*dsc).fIndexArray[indx]);
1596  else
1597  std::cout << "[" << std::dec << (*dsc).fIndexArray[indx]<<"]";
1598  }
1599  // print comment if any
1600  TDataSet *nxc = nextComment();
1601  if (lenbuf>0)
1602  iOut += snprintf(strbuf+iOut,lenbuf-iOut, ";");
1603  else {
1604  const char *title = nxc ? nxc->GetTitle() : " ";
1605  std::cout << ";\t//" << title << std::endl;
1606  }
1607  } /* dsc */
1608 
1609  TROOT::IndentLevel();
1610  if (lenbuf>0)
1611  iOut += snprintf(strbuf+iOut,lenbuf-iOut, "}");
1612  else
1613  std::cout << "}" << std::endl;
1614  return strbuf;
1615 }
1616 
1619 
1620 const Char_t *TTable::PrintHeader() const
1621 {
1622  std::cout << std::endl << " ---------------------------------------------------------------------------------------" << std::endl
1623  << " " << Path()
1624  <<" Allocated rows: "<<fN
1625  <<"\t Used rows: "<<fMaxIndex
1626  <<"\t Row size: " << fSize << " bytes"
1627  <<std::endl;
1628  return 0;
1629 }
1630 
1639 
1640 const Char_t *TTable::Print(Int_t row, Int_t rownumber, const Char_t *, const Char_t *) const
1641 {
1642  // Check bounds and adjust it
1643  Int_t const width = 8;
1644  Int_t rowStep = 10; // The maximun values to print per line
1645  Int_t rowNumber = rownumber;
1646  if (row > Int_t(GetSize()) || GetSize() == UInt_t(0)) {
1647  PrintHeader();
1648  std::cout << " ======================================================================================" << std::endl
1649  << " There are " << GetSize() << " allocated rows for this table only" << std::endl
1650  << " ======================================================================================" << std::endl;
1651  return 0;
1652  }
1653  if (rowNumber > Int_t(GetSize()-row)) rowNumber = GetSize()-row;
1654  if (!rowNumber) return 0;
1655  rowStep = TMath::Min(rowStep,rowNumber);
1656 
1657  Int_t cdate = 0;
1658  Int_t ctime = 0;
1659  UInt_t *cdatime = 0;
1660  Bool_t isdate = kFALSE;
1661 
1663  if (!dscT ) return 0;
1664 
1665  // 3. Loop by "rowStep x lines"
1666 
1667  const Char_t *startRow = (const Char_t *)GetArray() + row*GetRowSize();
1668  Int_t rowCount = rowNumber;
1669  Int_t thisLoopLenth = 0;
1670  const Char_t *nextRow = 0;
1671  while (rowCount) {
1672  PrintHeader();
1673  if (GetNRows() == 0) {// to Print empty table header
1674  std::cout << " ======================================================================================" << std::endl
1675  << " There is NO filled row in this table" << std::endl
1676  << " ======================================================================================" << std::endl;
1677  return 0;
1678  }
1679  std::cout << " Table: " << dscT->GetName()<< "\t";
1680  for (Int_t j = row+rowNumber-rowCount; j<row+rowNumber-rowCount+rowStep && j < row+rowNumber ;j++) {
1681  Int_t hW = width-2;
1682  if (j>=10) hW -= (int)TMath::Log10(float(j))-1;
1683  std::cout << std::setw(hW) << "["<<j<<"]";
1684  std::cout << " :" ;
1685  }
1686  std::cout << std::endl
1687  << " ======================================================================================" << std::endl;
1688  TTableDescriptor::iterator member = dscT->begin();
1689  TTableDescriptor::iterator dscE = dscT->end();
1690  TDataSetIter nextComment(dscT->MakeCommentField(kFALSE));
1691 
1692  for (; member != dscE; ++member){
1693  TString membertype = GetTypeName(EColumnType((*member).fType));
1694  isdate = kFALSE;
1695  if (strcmp((*member).fColumnName,"fDatime") == 0 && EColumnType((*member).fType) == kUInt)
1696  isdate = kTRUE;
1697  std::cout << membertype.Data();
1698 
1699  // Add the dimensions to "array" members
1700  Int_t dim = (*member).fDimensions;
1701  Int_t indx = 0;
1702  UInt_t *arrayLayout = 0;
1703  if (dim) {
1704  arrayLayout = new UInt_t[dim];
1705  memset(arrayLayout,0,dim*sizeof(Int_t));
1706  }
1707  Int_t arrayLength = 1;
1708  while (indx < dim ){ // Take in account the room this index will occupy
1709  arrayLength *= (*member).fIndexArray[indx];
1710  indx++;
1711  }
1712  // Encode data value or pointer value
1713  Int_t offset = (*member).fOffset;
1714  Int_t thisStepRows;
1715  thisLoopLenth = TMath::Min(rowCount,rowStep);
1716  Int_t indexOffset;
1717  Bool_t breakLoop = kFALSE;
1718 
1719  for (indexOffset=0; indexOffset < arrayLength && !breakLoop; indexOffset++) {
1720  nextRow = startRow;
1721 
1722  if (!indexOffset) std::cout << "\t" << (*member).fColumnName;
1723  else std::cout << "\t" << std::setw(strlen((*member).fColumnName)) << " ";
1724 
1725  if (dim) {
1726  for (Int_t i=0;i<dim;i++) std::cout << "["<<std::dec<<arrayLayout[i]<<"]";
1727  ArrayLayout(arrayLayout,(*member).fIndexArray,dim);
1728  }
1729  std::cout << "\t";
1730  if ( strlen((*member).fColumnName)+3*dim < 8) std::cout << "\t";
1731 
1732  for (thisStepRows = 0;thisStepRows < thisLoopLenth; thisStepRows++,nextRow += GetRowSize()) {
1733  const char *pointer = nextRow + offset + indexOffset*(*member).fTypeSize;
1734  if (isdate) {
1735  cdatime = (UInt_t*)pointer;
1736  TDatime::GetDateTime(cdatime[0],cdate,ctime);
1737  std::cout << cdate << "/" << ctime;
1738  } else if ((*member).fType == kChar && dim == 1) {
1739  char charbuffer[11];
1740  strlcpy(charbuffer,pointer,TMath::Min(10,arrayLength)+1);
1741  charbuffer[10] = 0;
1742  std::cout << "\"" << charbuffer;
1743  if (arrayLength > 10)
1744  std::cout << " . . . ";
1745  std::cout << "\"";
1746  breakLoop = kTRUE;
1747  } else {
1748  AsString((void *)pointer,EColumnType((*member).fType),width,std::cout);
1749  std::cout << " :";
1750  }
1751  }
1752  // Encode the column's comment
1753  if (indexOffset==0) {
1754  TDataSet *nxc = nextComment();
1755  std::cout << " " << (const char *)(nxc ? nxc->GetTitle() : "no comment");
1756  }
1757  std::cout << std::endl;
1758  }
1759  if (arrayLayout) delete [] arrayLayout;
1760  }
1761  rowCount -= thisLoopLenth;
1762  startRow = nextRow;
1763  }
1764  std::cout << "---------------------------------------------------------------------------------------" << std::endl;
1765  return 0;
1766 }
1769 
1770 void TTable::PrintContents(Option_t *) const
1771 {
1773  TROOT::IndentLevel();
1774  Printf("\tclass %s: public TTable\t --> Allocated rows: %d\t Used rows: %d\t Row size: %d bytes\n",
1775  IsA()->GetName(),int(fN),int(fMaxIndex),int(fSize));
1776 
1777 }
1778 
1786 
1787 void TTable::Project(const char *hname, const char *varexp, const char *selection, Option_t *option,Int_t nentries, Int_t firstentry)
1788 {
1789  TString var;
1790  var.Form("%s>>%s",varexp,hname);
1791 
1792  TString opt(option);
1793  opt += "goff";
1794 
1795  Draw(var,selection,opt,nentries,firstentry);
1796 }
1797 
1800 
1801 Int_t TTable::Purge(Option_t *opt)
1802 {
1803  ReAllocate();
1804  return TDataSet::Purge(opt);
1805 }
1806 
1809 
1810 void TTable::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
1811 {
1812  UInt_t arrayLayout[10],arraySize[10];
1813  const unsigned char *pointer=0,*startRow=0;
1814  int i,rowCount;unsigned char ic;
1815 
1816  out << "TDataSet *CreateTable() { " << std::endl;
1817 
1818  Int_t rowNumber = GetNRows();
1820 
1821 // Is anything Wrong??
1822  if (!rowNumber || !dscT ) {//
1823  out << "// The output table was bad-defined!" << std::endl
1824  << " fprintf(stderr, \"Bad table found. Please remove me\\n\");" << std::endl
1825  << " return 0; } " << std::endl;
1826  return;
1827  }
1828 
1829  startRow = (const UChar_t *)GetArray();
1830  assert(startRow!=0);
1831 
1832  const Char_t *rowId = "row";
1833  const Char_t *tableId = "tableSet";
1834 
1835 // Generate the header
1836 
1837  const char *className = IsA()->GetName();
1838 
1839  out << "// -----------------------------------------------------------------" << std::endl;
1840  out << "// " << Path()
1841  << " Allocated rows: "<< rowNumber
1842  <<" Used rows: "<< rowNumber
1843  <<" Row size: " << fSize << " bytes" << std::endl;
1844  out << "// " << " Table: " << dscT->GetName()<<"[0]--> "
1845  << dscT->GetName()<<"["<<rowNumber-1 <<"]" << std::endl;
1846  out << "// ====================================================================" << std::endl;
1847  out << "// ------ Test whether this table share library was loaded ------" << std::endl;
1848  out << " if (!TClass::GetClass(\"" << className << "\")) return 0;" << std::endl;
1849  out << dscT->GetName() << " " << rowId << ";" << std::endl
1850  << className << " *" << tableId << " = new "
1851  << className
1852  << "(\""<<GetName()<<"\"," << GetNRows() << ");" << std::endl
1853  << "//" <<std::endl ;
1854 
1855 // Row loop
1856  TDataSetIter nextComment(dscT->MakeCommentField(kFALSE));
1857  for (rowCount=0;rowCount<rowNumber; rowCount++,startRow += fSize, nextComment.Reset()) { //row loop
1858  out << "memset(" << "&" << rowId << ",0," << tableId << "->GetRowSize()" << ");" << std::endl ;
1859 
1860 // Member loop
1861  TTableDescriptor::iterator member = dscT->begin();
1862  TTableDescriptor::iterator dscE = dscT->end();
1863  for (; member != dscE; ++member) { //LOOP over members
1864  TString memberType = GetTypeName(EColumnType((*member).fType));
1865  TString memberName((*member).fColumnName);
1866 
1867  // Encode the column's comment
1868  TDataSet *nxc = nextComment();
1869  TString memberTitle(nxc ? nxc->GetTitle() : "no comment");
1870 
1871  Int_t offset = (*member).fOffset;
1872  int mayBeName = 0;
1873  if (memberName.Index("name",0,TString::kIgnoreCase)>=0) mayBeName=1999;
1874  if (memberName.Index("file",0,TString::kIgnoreCase)>=0) mayBeName=1999;
1875  int typeSize = (*member).fTypeSize;
1876 
1877 // Add the dimensions to "array" members
1878  Int_t dim = (*member).fDimensions;
1879  if (dim) memset(arrayLayout,0,dim*sizeof(Int_t));
1880  Int_t arrayLength = 1;
1881  for (int indx=0;indx < dim ;indx++){
1882  arraySize[indx] = (*member).fIndexArray[indx];;
1883  arrayLength *= arraySize[indx];
1884  }
1885 
1886 // Special case, character array
1887  int charLen = (memberType.CompareTo("char")==0);
1888  if (charLen) { //Char case
1889  charLen=arrayLength;
1890  pointer = startRow + offset;
1891 // Actual size of char array
1892  if (mayBeName) {
1893  charLen = strlen((const char*)pointer)+1;
1894  if (charLen>arrayLength) charLen = arrayLength;
1895  } else {
1896  for(;charLen && !pointer[charLen-1];charLen--){;}
1897  if (!charLen) charLen=1;
1898  }
1899 
1900  out << " memcpy(&" << rowId << "." << (const char*)memberName;
1901  out << ",\"";
1902  for (int ii=0; ii<charLen;ii++) {
1903  ic = pointer[ii];
1904  if (ic && (isalnum(ic)
1905  || strchr("!#$%&()*+-,./:;<>=?@{}[]_|~",ic))) {//printable
1906  out << ic;
1907  } else { //nonprintable
1908  out << "\\x" << std::setw(2) << std::setfill('0') << std::hex << (unsigned)ic ;
1909  out << std::setw(1) << std::setfill(' ') << std::dec;
1910  }
1911  }
1912  out << "\"," << std::dec << charLen << ");";
1913  out << "// " << (const char*)memberTitle << std::endl;
1914  continue;
1915  } //EndIf of char case
1916 
1917 // Normal member
1918  Int_t indexOffset;
1919  for (indexOffset=0; indexOffset < arrayLength ; indexOffset++) {//array loop
1920  out << std::setw(3) << " " ;
1921  out << " " << rowId << "." << (const char*)memberName;
1922 
1923  if (dim) {
1924  for (i=0;i<dim;i++) {out << "["<<std::dec<<arrayLayout[i]<<"]";}
1925  ArrayLayout(arrayLayout,arraySize,dim);}
1926 
1927 // Generate "="
1928  out << "\t = ";
1929 
1930  pointer = startRow + offset + indexOffset*typeSize;
1931 
1932  AsString((void *)pointer,EColumnType((*member).fType),10,out);
1933 
1934 // Encode data member title
1935  if (indexOffset==0) out << "; // " << (const char*)memberTitle;
1936  out << ";" << std::endl;
1937  }//end array loop
1938  }//end of member loop
1939 
1940  out << tableId << "->AddAt(&" << rowId <<");" << std::endl;
1941 
1942  }//end of row loop
1943  out << "// ----------------- end of code ---------------" << std::endl
1944  << " return (TDataSet *)tableSet;" << std::endl
1945  << "}" << std::endl;
1946  return;
1947 }
1948 
1951 
1952 void TTable::Set(Int_t n)
1953 {
1954  if (n < 0) return;
1955  if (fN != n) Clear();
1956  SetfN(n);
1957  if (fN == 0) return;
1958  Create();
1959  if (TTable::GetNRows()) Reset();
1960 }
1963 
1964 void TTable::SetTablePointer(void *table)
1965 {
1966  if (fTable) free(fTable);
1967  fTable = (Char_t *)table;
1968 }
1969 
1972 
1973 void TTable::SetType(const char *const type)
1974 {
1975  SetTitle(type);
1976 }
1977 
1980 
1981 static Char_t *GetExpressionFileName()
1982 {
1983  const Char_t *tempDirs = gSystem->Getenv("TEMP");
1984  if (!tempDirs) tempDirs = gSystem->Getenv("TMP");
1985  if (!tempDirs) tempDirs = "/tmp";
1986  if (gSystem->AccessPathName(tempDirs)) tempDirs = ".";
1987  if (gSystem->AccessPathName(tempDirs)) return 0;
1988  TString fileName;
1989  fileName.Form("Selection.C.%d.tmp",gSystem->GetPid());
1990  return gSystem->ConcatFileName(tempDirs,fileName.Data());
1991 }
1992 
2002 
2003 Char_t *TTable::MakeExpression(const Char_t *expressions[],Int_t nExpressions)
2004 {
2005  const Char_t *typeNames[] = {"NAN","float", "int", "long", "short", "double"
2006  ,"unsigned int","unsigned long", "unsigned short","unsigned char"
2007  ,"char", "TTableMap &"};
2008  const char *resID = "results";
2009  const char *addressID = "address";
2010  Char_t *fileName = GetExpressionFileName();
2011  if (!fileName) {
2012  Error("MakeExpression","Can not create a temporary file");
2013  return 0;
2014  }
2015 
2016  std::ofstream str;
2017  str.open(fileName);
2018  if (str.bad() ) {
2019  Error("MakeExpression","Can not open the temporary file <%s>",fileName);
2020  delete [] fileName;
2021  return 0;
2022  }
2023 
2025  const tableDescriptor_st *descTable = dsc->GetTable();
2026  // Create function
2027  str << "void SelectionQWERTY(float *"<<resID<<", float **"<<addressID<< ", int& i$, int& n$ )" << std::endl;
2028  str << "{" << std::endl;
2029  int i = 0;
2030  for (i=0; i < dsc->GetNRows(); i++,descTable++ ) {
2031  // Take the column name
2032  const Char_t *columnName = descTable->fColumnName;
2033  const Char_t *type = 0;
2034  // First check whether we do need this column
2035  for (Int_t exCount = 0; exCount < nExpressions; exCount++) {
2036  if (expressions[exCount] && expressions[exCount][0] && strstr(expressions[exCount],columnName)) goto LETSTRY;
2037  }
2038  continue;
2039 LETSTRY:
2040  Bool_t isScalar = !(descTable->fDimensions);
2041  Bool_t isFloat = descTable->fType == kFloat;
2042  type = typeNames[descTable->fType];
2043  str << type << " ";
2044  if (!isScalar) str << "*";
2045 
2046  str << columnName << " = " ;
2047  if (isScalar) str << "*(";
2048  if (!isFloat) str << "(" << type << "*)";
2049  str << addressID << "[" << i << "]";
2050  if (isScalar) str << ")" ;
2051  str << ";" << std::endl;
2052  }
2053  // Create expressions
2054  for (i=0; i < nExpressions; i++ ) {
2055  if (expressions[i] && expressions[i][0])
2056  str << " "<<resID<<"["<<i<<"]=(float)(" << expressions[i] << ");" << std::endl;
2057 // if (i == nExpressions-1 && i !=0 )
2058 // str << " if ("<<resID<<"["<<i<<"] == 0){ return; }" << std::endl;
2059  };
2060  str << "}" << std::endl;
2061  str.close();
2062  // Create byte code and check syntax
2063  if (str.good()) return fileName;
2064  delete [] fileName;
2065  return 0;
2066 }
2067 
2071 
2072 void TTable::Reset(Int_t c)
2073 {
2074  if (fTable) {
2075  ResetMap(kTRUE);
2076  ::memset(fTable,c,fSize*fN);
2077  if (c) ResetMap(kFALSE);
2078  }
2079 }
2080 
2086 
2087 void TTable::ResetMap(Bool_t wipe)
2088 {
2089  piterator links = pbegin();
2090  piterator lastLinks = pend();
2091  for (;links != lastLinks;links++) {
2092  TTableMap **mp = (TTableMap **)(*links);
2093  if (wipe) delete *mp;
2094  *mp = 0;
2095  }
2096 }
2100 
2101 void TTable::Set(Int_t n, Char_t *array)
2102 {
2103  if (n < 0) return;
2104  if (fN < n) Clear();
2105 
2106  SetfN(n);
2107 
2108  if (fN == 0) return;
2109  Create();
2110  CopyStruct(fTable,array);
2111  fMaxIndex = n;
2112 }
2113 
2116 
2117 void TTable::StreamerTable(TBuffer &b,Version_t version)
2118 {
2119  if (b.IsReading()) {
2120  TDataSet::Streamer(b);
2121  b >> fN;
2122  StreamerHeader(b,version);
2123  // Create a table to fit nok rows
2124  Set(fMaxIndex);
2125  } else {
2126  TDataSet::Streamer(b);
2127  b << fN;
2128  StreamerHeader(b,version);
2129  }
2130 }
2131 
2134 
2135 void TTable::StreamerHeader(TBuffer &b, Version_t version)
2136 {
2137  if (b.IsReading()) {
2138  Long_t rbytes;
2139  if (version) { } // version to remove compiler warning
2140 #ifdef __STAR__
2141  if (version < 3) {
2142  // skip obsolete STAR fields (for the sake of the backward compatibility)
2143  // char name[20]; /* table name */
2144  // char type[20]; /* table type */
2145  // long maxlen; /* # rows allocated */
2146  long len = b.Length() + (20+4) + (20+4) + 4;
2147  b.SetBufferOffset(len);
2148  }
2149 #endif
2150  b >> fMaxIndex; // fTableHeader->nok; /* # rows filled */
2151  b >> rbytes; /* number of bytes per row */
2152  if (GetRowSize() == -1) fSize = rbytes;
2153  if (rbytes - GetRowSize()) {
2154  Warning("StreamerHeader","Schema evolution warning: row size mismatch: expected %ld, read %ld bytes\n",GetRowSize(),rbytes);
2155  }
2156 
2157 #ifdef __STAR__
2158  if (version < 3) {
2159  // skip obsolete STAR fields (for the sake of the backward compatibility)
2160  // long dsl_pointer; /* swizzled (DS_DATASET_T*) */
2161  // long data_pointer; /* swizzled (char*) */
2162  long len = b.Length() + (4) + (4);
2163  b.SetBufferOffset(len);
2164  }
2165 #endif
2166  } else {
2167  b << fMaxIndex; //fTableHeader->nok; /* # rows filled */
2168  b << fSize; // fTableHeader->rbytes; /* number of bytes per row */
2169  }
2170 }
2173 
2174 Int_t TTable::SetfN(Long_t len)
2175 {
2176  fN = len;
2177  return fN;
2178 }
2180 
2181 #ifdef StreamElelement
2182 #define __StreamElelement__ StreamElelement
2183 #undef StreamElelement
2184 #endif
2185 
2186 #define StreamElementIn(type) case TTableDescriptor::_NAME2_(k,type): \
2187 if (evolutionOn) { \
2188  if (nextCol->fDimensions) { \
2189  if (nextCol->fOffset != UInt_t(-1)) { \
2190  R__b.ReadFastArray((_NAME2_(type,_t) *)(row+nextCol->fOffset),nextCol->fSize/sizeof(_NAME2_(type,_t))); \
2191  } else { \
2192  _NAME2_(type,_t) *readPtrV = new _NAME2_(type,_t)[nextCol->fSize/sizeof(_NAME2_(type,_t))]; \
2193  R__b.ReadFastArray((_NAME2_(type,_t) *)(row+nextCol->fOffset),nextCol->fSize/sizeof(_NAME2_(type,_t))); \
2194  delete [] readPtrV; \
2195  readPtrV = 0; \
2196  } \
2197  } \
2198  else { \
2199  _NAME2_(type,_t) skipBuffer; \
2200  _NAME2_(type,_t) *readPtr = (_NAME2_(type,_t) *)(row+nextCol->fOffset); \
2201  if (nextCol->fOffset == UInt_t(-1)) readPtr = &skipBuffer; \
2202  R__b >> *readPtr; \
2203  } \
2204 } else { \
2205  if (nextCol->fDimensions) { \
2206  R__b.ReadFastArray ((_NAME2_(type,_t) *)(row+nextCol->fOffset),nextCol->fSize/sizeof(_NAME2_(type,_t))); \
2207  } else \
2208  R__b >> *(_NAME2_(type,_t) *)(row+nextCol->fOffset); \
2209 } \
2210 break
2211 
2212 #define StreamElementOut(type) case TTableDescriptor::_NAME2_(k,type): \
2213 if (nextCol->fDimensions) \
2214  R__b.WriteFastArray((_NAME2_(type,_t) *)(row+nextCol->fOffset), nextCol->fSize/sizeof(_NAME2_(type,_t))); \
2215 else \
2216  R__b << *(_NAME2_(type,_t) *)(row+nextCol->fOffset); \
2217 break
2218 
2221 
2223 {
2224  TTableDescriptor *dsc = 0;
2225  if (IsA()) dsc = GetDescriptorPointer();
2226  if (!dsc) {
2227  Error("GetRowDescriptors()","%s has no dictionary !",GetName());
2228  dsc = GetTableDescriptors();
2229  ((TTableDescriptor *)this)->SetDescriptorPointer(dsc);
2230  }
2231  return dsc;
2232 }
2235 
2237 {
2238  assert(0);
2239  return 0;
2240 }
2241 
2244 
2246 {
2247  assert(0);
2248 }
2249 
2252 
2253 void TTable::Streamer(TBuffer &R__b)
2254 {
2255  TTableDescriptor *ioDescriptor = GetRowDescriptors();
2256  TTableDescriptor *currentDescriptor = ioDescriptor;
2257  Version_t R__v = 0;
2258  if (R__b.IsReading()) {
2259  // Check whether the file is the "obsolete" one
2260  R__v = R__b.ReadVersion();
2261  Bool_t evolutionOn = kFALSE;
2262  if (R__v>=2) {
2263  if (IsA() != TTableDescriptor::Class()) {
2264  if (R__v>3) {
2265  R__b >> ioDescriptor;
2266  } else { // backward compatibility
2267  ioDescriptor = new TTableDescriptor();
2268  ioDescriptor->Streamer(R__b);
2269  }
2270  if (!currentDescriptor) {
2271  currentDescriptor = ioDescriptor;
2272  SetDescriptorPointer(currentDescriptor);
2273  }
2274  if (currentDescriptor->fSecondDescriptor != ioDescriptor) {
2275  // Protection against of memory leak.
2276  delete currentDescriptor->fSecondDescriptor;
2277  currentDescriptor->fSecondDescriptor = ioDescriptor;
2278  }
2279 
2280  // compare two descriptors
2281  evolutionOn = (Bool_t)ioDescriptor->UpdateOffsets(currentDescriptor);
2282  }
2283  }
2284  TTable::StreamerTable(R__b,R__v);
2285  if (fMaxIndex <= 0) return;
2286  char *row= fTable;
2287  Int_t maxColumns = ioDescriptor->NumberOfColumns();
2288  Int_t rowSize = GetRowSize();
2289  if (evolutionOn) Reset(0); // Clean table
2290  for (Int_t indx=0;indx<fMaxIndex;indx++,row += rowSize) {
2291  tableDescriptor_st *nextCol = ioDescriptor->GetTable();
2292  for (Int_t colCounter=0; colCounter < maxColumns; colCounter++,nextCol++) {
2293  // Stream one table row supplied
2294  switch(nextCol->fType) {
2295  StreamElementIn(Float);
2296  StreamElementIn(Int);
2297  StreamElementIn(Long);
2298  StreamElementIn(Short);
2299  StreamElementIn(Double);
2300  StreamElementIn(UInt);
2301  StreamElementIn(ULong);
2302  StreamElementIn(UChar);
2303  StreamElementIn(Char);
2304  StreamElementIn(Bool);
2305  case TTableDescriptor::kPtr: {
2306  Ptr_t readPtr;
2307  R__b >> readPtr;
2308  if (evolutionOn) {
2309  // TTableMap skipBuffer;
2310  // R__b >> readPtr;
2311  if (nextCol->fOffset == UInt_t(-1)) delete readPtr; // skip this member
2312  else *(Ptr_t *)(row+nextCol->fOffset) = readPtr;
2313  } else {
2314  *(Ptr_t *)(row+nextCol->fOffset) = readPtr;
2315  }
2316  break;
2317  }
2318  default:
2319  break;
2320  };
2321  }
2322  }
2323  } else {
2324  TSeqCollection *save = fList;
2325  R__b.WriteVersion(TTable::IsA());
2326 
2327  // if (Class_Version()==2)
2328  if (IsA() != TTableDescriptor::Class()) {
2329  if ( Class_Version()>3 ) {
2330  R__b << ioDescriptor;
2331  } else { // backward compatibility
2332  ioDescriptor->Streamer(R__b);
2333  }
2334  } else {
2335  if ( Class_Version()<=3 ) fList = 0;
2336  }
2337 
2338  TTable::StreamerTable(R__b);
2339  if (fMaxIndex <= 0) return;
2340  char *row= fTable;
2341  Int_t maxColumns = ioDescriptor->NumberOfColumns();
2342  Int_t rowSize = GetRowSize();
2343  for (Int_t indx=0;indx<fMaxIndex;indx++,row += rowSize) {
2344  tableDescriptor_st *nextCol = ioDescriptor->GetTable();
2345  for (Int_t colCounter=0; colCounter < maxColumns; colCounter++,nextCol++) {
2346  // Stream one table row supplied
2347  switch(nextCol->fType) {
2348  StreamElementOut(Float);
2349  StreamElementOut(Int);
2350  StreamElementOut(Long);
2351  StreamElementOut(Short);
2352  StreamElementOut(Double);
2353  StreamElementOut(UInt);
2354  StreamElementOut(ULong);
2355  StreamElementOut(UChar);
2356  StreamElementOut(Char);
2357  StreamElementOut(Bool);
2358  case TTableDescriptor::kPtr:
2359  R__b << *(Ptr_t *)(row+nextCol->fOffset);
2360  break;
2361  default:
2362  break;
2363  };
2364  }
2365  }
2366  fList = save;
2367  }
2368 }
2369 #ifdef __StreamElelement__
2370 #define StreamElelement __StreamElelement__
2371 #undef __StreamElelement__
2372 #endif
2373 
2376 
2378 {
2379 }
2380 
2384 
2385 void TTable::Update(TDataSet *set, UInt_t opt)
2386 {
2387  if (set->HasData()) {
2388  // Check whether the new table has the same type
2389  if (strcmp(GetTitle(),set->GetTitle()) == 0 ) {
2390  TTable *table = (TTable *)set;
2391  Adopt(table->GetSize(),table->GetArray());
2392  // Adopt can not distniguish the "allocated" and "used"
2393  // rows,
2394  // correct the corrupted number of the "used" rows
2395  SetUsedRows(table->GetNRows());
2396  // mark that object lost the STAF table and can not delete it anymore
2397  table->SetBit(kIsNotOwn);
2398  // mark we took over of this STAF table
2399  ResetBit(kIsNotOwn);
2400  } else
2401  Error("Update",
2402  "This table is <%s> but the updating one has a wrong type <%s>",GetTitle(),set->GetTitle());
2403  }
2404  TDataSet::Update(set,opt);
2405 }
2409 
2410 const char *TTable::TableDictionary(const char *className,const char *structName,TTableDescriptor *&ColDescriptors)
2411 {
2412  if (className){/*NotUsed*/};
2413  TClass *r = TClass::GetClass(structName,1);
2414  ColDescriptors = new TTableDescriptor(r);
2415  return structName;
2416 }
2417 
2418 
2419  // ---- Table descriptor service ------
2420 Int_t TTable::GetColumnIndex(const Char_t *columnName) const {return GetRowDescriptors()->ColumnByName(columnName);}
2421 const Char_t *TTable::GetColumnName(Int_t columnIndex) const {return GetRowDescriptors()->ColumnName(columnIndex); }
2422 const UInt_t *TTable::GetIndexArray(Int_t columnIndex) const {return GetRowDescriptors()->IndexArray(columnIndex); }
2423 UInt_t TTable::GetNumberOfColumns() const {return GetRowDescriptors()->NumberOfColumns(); }
2424 
2425 UInt_t TTable::GetOffset(Int_t columnIndex) const {return GetRowDescriptors()->Offset(columnIndex); }
2426 Int_t TTable::GetOffset(const Char_t *columnName) const {return GetRowDescriptors()->Offset(columnName); }
2427 
2428 UInt_t TTable::GetColumnSize(Int_t columnIndex) const {return GetRowDescriptors()->ColumnSize(columnIndex); }
2429 Int_t TTable::GetColumnSize(const Char_t *columnName) const {return GetRowDescriptors()->ColumnSize(columnName); }
2430 
2431 UInt_t TTable::GetTypeSize(Int_t columnIndex) const {return GetRowDescriptors()->TypeSize(columnIndex); }
2432 Int_t TTable::GetTypeSize(const Char_t *columnName) const {return GetRowDescriptors()->TypeSize(columnName); }
2433 
2434 UInt_t TTable::GetDimensions(Int_t columnIndex) const {return GetRowDescriptors()->Dimensions(columnIndex); }
2435 Int_t TTable::GetDimensions(const Char_t *columnName) const {return GetRowDescriptors()->Dimensions(columnName); }
2436 
2437 TTable::EColumnType TTable::GetColumnType(Int_t columnIndex) const {return GetRowDescriptors()->ColumnType(columnIndex); }
2438 TTable::EColumnType TTable::GetColumnType(const Char_t *columnName) const {return GetRowDescriptors()->ColumnType(columnName); }
2439 
2440 // pointer iterator
2443 
2444 TTable::piterator::piterator(const TTable *t,EColumnType type): fCurrentRowIndex(0),fCurrentColIndex(0),fRowSize(0),fCurrentRowPtr(0),fCurrentColPtr(0)
2445 {
2446  Int_t sz = 0;
2447  if (t) sz = t->GetNRows();
2448  if (sz) {
2449  fRowSize = t->GetRowSize();
2450  fCurrentRowPtr = (const Char_t *)t->GetArray();
2451 
2452  TTableDescriptor *tabsDsc = t->GetRowDescriptors();
2453  TTableDescriptor::iterator ptr = tabsDsc->begin();
2454  TTableDescriptor::iterator lastPtr = tabsDsc->end();
2455  UInt_t i =0;
2456  for( i = 0; ptr != lastPtr; ++ptr,++i)
2457  if ( tabsDsc->ColumnType(i) == type ) fPtrs.push_back(tabsDsc->Offset(i));
2458  if (fPtrs.size()==0) {
2459  MakeEnd(t->GetNRows());
2460  } else {
2461  column();
2462  }
2463  } else {
2464  MakeEnd(0);
2465  }
2466 } // piterator(TTable *)
2467 
2468 void TTable::iterator::operator++() { ++fCurrentRow; }
2469 void TTable::iterator::operator++(int) { fCurrentRow++; }
2470 void TTable::iterator::operator--() { --fCurrentRow; }
2471 void TTable::iterator::operator--(int) { fCurrentRow--; }
2472 TTable::iterator TTable::iterator::operator+(Int_t idx) { std::vector<Long_t>::iterator addition = fCurrentRow+idx; return TTable::iterator(*fThisTable,addition); }
2473 TTable::iterator TTable::iterator::operator-(Int_t idx) { std::vector<Long_t>::iterator subtraction = fCurrentRow-idx; return TTable::iterator(*fThisTable,subtraction); }
2474 void TTable::iterator::operator+=(Int_t idx) { fCurrentRow+=idx; }
2475 void TTable::iterator::operator-=(Int_t idx) { fCurrentRow-=idx; }
2476 void *TTable::iterator::rowPtr() const { return (void *)(((const char *)fThisTable->GetArray()) + (*fCurrentRow)*fRowSize ); }
2477 TTable::iterator::operator void *() const { return rowPtr(); }
2478 Int_t TTable::iterator::operator-(const iterator &it) const { return (*fCurrentRow)-(*(it.fCurrentRow)); }
2479 Long_t TTable::iterator::operator *() const { return *fCurrentRow; }
2480 Bool_t TTable::iterator::operator==(const iterator &t) const { return ( (fCurrentRow == t.fCurrentRow) && (fThisTable == t.fThisTable) ); }
2481 Bool_t TTable::iterator::operator!=(const iterator &t) const { return !operator==(t); }
virtual Long_t InsertRows(const void *rows, Long_t indx, UInt_t nRows=1)
Definition: TTable.cxx:1203
Int_t SetfN(Long_t len)
to be documented
Definition: TTable.cxx:2174
Definition: FJcore.h:367
virtual TClass * GetRowClass() const
to be documented
Definition: TTable.cxx:1375
void * ReAllocate()
Definition: TTable.cxx:1222
virtual Long_t GetRowSize() const
Returns the size (in bytes) of one table row.
Definition: TTable.cxx:1395
virtual void PrintContents(Option_t *opt="") const
Definition: TDataSet.cxx:618
virtual const Char_t * GetType() const
Returns the type of the wrapped C-structure kept as the TNamed title.
Definition: TTable.cxx:1444
void StreamerHeader(TBuffer &b, Version_t version=3)
Read &quot;table parameters first&quot;.
Definition: TTable.cxx:2135
virtual void Delete(Option_t *opt="")
Definition: TDataSet.cxx:320
virtual Int_t UpdateOffsets(const TTableDescriptor *newDesciptor)
TTable & operator=(const TTable &rhs)
Definition: TTable.cxx:1083
virtual void Browse(TBrowser *b)
Browse this dataset (called by TBrowser).
Definition: TDataSet.cxx:297
virtual void Browse(TBrowser *b)
Wrap each table coulumn with TColumnView object to browse.
Definition: TTable.cxx:1294
virtual const Char_t * PrintHeader() const
Print general table inforamtion.
Definition: TTable.cxx:1620
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream &quot;out&quot;.
Definition: TTable.cxx:1810
TTable(const char *name=0, Int_t size=0)
Default TTable ctor.
Definition: TTable.cxx:1031
virtual void PrintContents(Option_t *opt="") const
to be documented
Definition: TTable.cxx:1770
Int_t ColumnByName(const Char_t *columnName=0) const
Find the column index but the column name.
static const char * TableDictionary(const char *className, const char *structName, TTableDescriptor *&ColDescriptors)
Definition: TTable.cxx:2410
virtual void Set(Int_t n)
Set array size of TTable object to n longs. If n&lt;0 leave array unchanged.
Definition: TTable.cxx:1952
Int_t CopyRows(const TTable *srcTable, Long_t srcRow=0, Long_t dstRow=0, Long_t nRows=0, Bool_t expand=kFALSE)
Definition: TTable.cxx:332
virtual Bool_t EntryLoop(const Char_t *exprFileName, Int_t &action, TObject *obj, Int_t nentries=1000000000, Int_t firstentry=0, Option_t *option="")
Definition: TTable.cxx:785
virtual TTableDescriptor * GetRowDescriptors() const
to be documented
Definition: TTable.cxx:2222
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
Bool_t OutOfBoundsError(const char *where, Int_t i) const
Generate an out-of-bounds error. Always returns false.
Definition: TTable.cxx:1540
virtual Int_t AddAt(const void *c)
Definition: TTable.cxx:1122
virtual Long_t AppendRows(const void *row, UInt_t nRows)
Definition: TTable.cxx:1178
virtual void Fit(const char *formula, const char *varexp, const char *selection="", Option_t *option="", Option_t *goption="", Int_t nentries=1000000000, Int_t firstentry=0)
Definition: TTable.cxx:1422
virtual void Update()
to be documented
Definition: TTable.cxx:2377
Int_t NaN()
Definition: TTable.cxx:1474
virtual void ResetMap(Bool_t wipe=kTRUE)
Definition: TTable.cxx:2087
virtual void DeleteRows(Long_t indx, UInt_t nRows=1)
Definition: TTable.cxx:364
virtual ~TTable()
Delete TTable object.
Definition: TTable.cxx:1098
virtual TTableDescriptor * GetTableDescriptors() const
protected: create a new TTableDescriptor descriptor for this table
Definition: TTable.cxx:214
void StreamerTable(TBuffer &b, Version_t version=3)
Stream an object of class TTable.
Definition: TTable.cxx:2117
virtual Int_t Purge(Option_t *opt="")
Definition: TDataSet.cxx:758
void SetTablePointer(void *table)
to be documented
Definition: TTable.cxx:1964
void CopyStruct(Char_t *dest, const Char_t *src)
Definition: TTable.cxx:1151
static EColumnType GetTypeId(const char *typeName)
Definition: TTable.cxx:292
static TTable * New(const Char_t *name, const Char_t *type, void *array, UInt_t size)
This static method creates a new TTable object if provided.
Definition: TTable.cxx:1515
virtual Long_t GetTableSize() const
Returns the number of the allocated rows.
Definition: TTable.cxx:1402
Definition: TTable.h:48
virtual Char_t * MakeExpression(const Char_t *expressions[], Int_t nExpressions)
Definition: TTable.cxx:2003
static const char * GetTypeName(EColumnType type)
return table type name
Definition: TTable.cxx:282
virtual void Update()
Definition: TDataSet.cxx:864
virtual void Project(const char *hname, const char *varexp, const char *selection="", Option_t *option="", Int_t nentries=1000000000, Int_t firstentry=0)
Definition: TTable.cxx:1787
Char_t * Create()
Definition: TTable.cxx:1268
const void * At(Int_t i) const
Returns a pointer to the i-th row of the table.
Definition: TTable.cxx:303
virtual TString Path() const
return the full path of this data set
Definition: TDataSet.cxx:626
virtual TTableDescriptor * GetDescriptorPointer() const
to be documented
Definition: TTable.cxx:2236
virtual void SetDescriptorPointer(TTableDescriptor *list)
to be documented
Definition: TTable.cxx:2245
piterator(const TTable *t=0, EColumnType type=kPtr)
to be documented
Definition: TTable.cxx:2444
virtual void Delete(Option_t *opt="")
Definition: TTable.cxx:1366
virtual Bool_t IsFolder() const
Definition: TTable.cxx:1456
virtual void Clear(Option_t *opt="")
Definition: TTable.cxx:1342
virtual Char_t * Print(Char_t *buf, Int_t n) const
Create IDL table defintion (to be used for XDF I/O)
Definition: TTable.cxx:1548
virtual void Adopt(Int_t n, void *array)
Definition: TTable.cxx:1107
TDataSet * MakeCommentField(Bool_t createFlag=kTRUE)
Instantiate a comment dataset if any.
virtual void CopySet(TTable &array)
to be documented
Definition: TTable.cxx:1158
void ReAlloc(Int_t newsize)
The table is reallocated if it is an owner of the internal array.
Definition: TTable.cxx:1243
virtual const Char_t * GetColumnComment(Int_t columnIndex) const
Get a comment from the table descriptor.
Definition: TTable.cxx:1166
virtual void AsString(void *buf, EColumnType type, Int_t width, std::ostream &out) const
Definition: TTable.cxx:229
virtual void Reset(Int_t c=0)
Fill the entire table with byte &quot;c&quot; ; / c=0 &quot;be default&quot;
Definition: TTable.cxx:2072
virtual Int_t Purge(Option_t *opt="")
Shrink the table to free the unused but still allocated rows.
Definition: TTable.cxx:1801