Logo ROOT   6.12/07
Reference Guide
TClassTable.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 11/08/95
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 /** \class TClassTable
13 \ingroup Containers
14 This class registers for all classes their name, id and dictionary
15 function in a hash table. Classes are automatically added by the
16 ctor of a special init class when a global of this init class is
17 initialized when the program starts (see the ClassImp macro).
18 */
19 
20 #include "TClassTable.h"
21 
22 #include "TClass.h"
23 #include "TClassEdit.h"
24 #include "TProtoClass.h"
25 #include "TROOT.h"
26 #include "TString.h"
27 #include "TError.h"
28 #include "TRegexp.h"
29 
30 #include "TObjString.h"
31 #include "TMap.h"
32 
33 #include "TInterpreter.h"
34 
35 #include <map>
36 #include <memory>
37 #include "Riostream.h"
38 #include <typeinfo>
39 #include <stdlib.h>
40 #include <string>
41 
42 using namespace ROOT;
43 
45 
46 TClassAlt **TClassTable::fgAlternate;
47 TClassRec **TClassTable::fgTable;
48 TClassRec **TClassTable::fgSortedTable;
54 
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 
59 namespace ROOT {
60  class TClassRec {
61  public:
62  TClassRec(TClassRec *next) :
63  fName(0), fId(0), fDict(0), fInfo(0), fProto(0), fNext(next)
64  {}
65 
66  ~TClassRec() {
67  // TClassTable::fgIdMap->Remove(r->fInfo->name());
68  delete [] fName;
69  delete fProto;
70  delete fNext;
71  }
72 
73  char *fName;
74  Version_t fId;
75  Int_t fBits;
76  DictFuncPtr_t fDict;
77  const std::type_info *fInfo;
78  TProtoClass *fProto;
79  TClassRec *fNext;
80  };
81 
82  class TClassAlt {
83  public:
84  TClassAlt(const char*alternate, const char *normName, TClassAlt *next) :
85  fName(alternate), fNormName(normName), fNext(next)
86  {}
87 
88  ~TClassAlt() {
89  // Nothing more to delete.
90  }
91 
92  const char *fName; // Do not own
93  const char *fNormName; // Do not own
94  std::unique_ptr<TClassAlt> fNext;
95  };
96 
97 #define R__USE_STD_MAP
98  class TMapTypeToClassRec {
99 #if defined R__USE_STD_MAP
100  // This wrapper class allow to avoid putting #include <map> in the
101  // TROOT.h header file.
102  public:
103  typedef std::map<std::string, TClassRec*> IdMap_t;
104  typedef IdMap_t::key_type key_type;
105  typedef IdMap_t::const_iterator const_iterator;
106  typedef IdMap_t::size_type size_type;
107 #ifdef R__WIN32
108  // Window's std::map does NOT defined mapped_type
109  typedef TClassRec* mapped_type;
110 #else
111  typedef IdMap_t::mapped_type mapped_type;
112 #endif
113 
114  private:
115  IdMap_t fMap;
116 
117  public:
118  void Add(const key_type &key, mapped_type &obj) {
119  fMap[key] = obj;
120  }
121 
122  mapped_type Find(const key_type &key) const {
123 
124  IdMap_t::const_iterator iter = fMap.find(key);
125  mapped_type cl = 0;
126  if (iter != fMap.end()) cl = iter->second;
127  return cl;
128  }
129 
130  void Remove(const key_type &key) { fMap.erase(key); }
131 
132  void Print() {
133  Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
134  for (const_iterator iter = fMap.begin(); iter != fMap.end(); ++iter) {
135  printf("Key: %40s 0x%lx\n", iter->first.c_str(), (unsigned long)iter->second);
136  }
137  }
138 #else
139  private:
140  TMap fMap;
141  public:
142 #ifdef R__COMPLETE_MEM_TERMINATION
143  ~TMapTypeToClassRec() {
144  TIter next(&fMap);
145  TObjString *key;
146  while((key = (TObjString*)next())) {
147  delete key;
148  }
149  }
150 #endif
151 
152  void Add(const char *key, TClassRec *&obj)
153  {
154  // Add <key,value> pair to the map.
155 
156  TObjString *realkey = new TObjString(key);
157  fMap.Add(realkey, (TObject*)obj);
158  }
159 
160  TClassRec *Find(const char *key) const {
161  // Find the value corresponding the key.
162  const TPair *a = (const TPair *)fMap.FindObject(key);
163  if (a) return (TClassRec*) a->Value();
164  return 0;
165  }
166 
167  void Remove(const char *key) {
168  // Remove the value corresponding the key.
169  TObjString realkey(key);
170  TObject *actual = fMap.Remove(&realkey);
171  delete actual;
172  }
173 
174  void Print() {
175  // Print the content of the map.
176  Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
177  TIter next(&fMap);
178  TObjString *key;
179  while((key = (TObjString*)next())) {
180  printf("Key: %s\n",key->String().Data());
181  TClassRec *data = (TClassRec*)fMap.GetValue(key);
182  if (data) {
183  printf(" class: %s %d\n",data->fName,data->fId);
184  } else {
185  printf(" no class: \n");
186  }
187  }
188  }
189 #endif
190  };
191 
192  static UInt_t ClassTableHash(const char *name, UInt_t size)
193  {
194  auto p = reinterpret_cast<const unsigned char*>( name );
195  UInt_t slot = 0;
196 
197  while (*p) slot = slot<<1 ^ *p++;
198  slot %= size;
199 
200  return slot;
201  }
202 
203  std::vector<std::unique_ptr<TClassRec>> &GetDelayedAddClass()
204  {
205  static std::vector<std::unique_ptr<TClassRec>> delayedAddClass;
206  return delayedAddClass;
207  }
208 
209  std::vector<std::pair<const char *, const char *>> &GetDelayedAddClassAlternate()
210  {
211  static std::vector<std::pair<const char *, const char *>> delayedAddClassAlternate;
212  return delayedAddClassAlternate;
213  }
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// TClassTable is a singleton (i.e. only one can exist per application).
218 
220 {
221  if (gClassTable) return;
222 
223  fgSize = 1009; //this is the result of (int)TMath::NextPrime(1000);
224  fgTable = new TClassRec* [fgSize];
225  fgAlternate = new TClassAlt* [fgSize];
226  fgIdMap = new IdMap_t;
227  memset(fgTable, 0, fgSize*sizeof(TClassRec*));
228  memset(fgAlternate, 0, fgSize*sizeof(TClassAlt*));
229  gClassTable = this;
230 
231  for (auto &&r : GetDelayedAddClass()) {
232  AddClass(r->fName, r->fId, *r->fInfo, r->fDict, r->fBits);
233  };
234  GetDelayedAddClass().clear();
235 
236  for (auto &&r : GetDelayedAddClassAlternate()) {
237  AddAlternate(r.first, r.second);
238  }
239  GetDelayedAddClassAlternate().clear();
240 }
241 
242 ////////////////////////////////////////////////////////////////////////////////
243 /// TClassTable singleton is deleted in Terminate().
244 
246 {
247  // Try to avoid spurious warning from memory leak checkers.
248  if (gClassTable != this) return;
249 
250  for (UInt_t i = 0; i < fgSize; i++) {
251  delete fgTable[i]; // Will delete all the elements in the chain.
252  }
253  delete [] fgTable; fgTable = 0;
254  delete [] fgSortedTable; fgSortedTable = 0;
255  delete fgIdMap; fgIdMap = 0;
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Return true fs the table exist.
260 /// If the table does not exist but the delayed list does, then
261 /// create the table and return true.
262 
264  if (!gClassTable || !fgTable) {
265  if (GetDelayedAddClass().size()) {
266  new TClassTable;
267  return kTRUE;
268  }
269  return kFALSE;
270  }
271  return kTRUE;
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 /// Print the class table. Before printing the table is sorted
276 /// alphabetically. Only classes specified in option are listed.
277 /// The default is to list all classes.
278 /// Standard wildcarding notation supported.
279 
280 void TClassTable::Print(Option_t *option) const
281 {
282  if (fgTally == 0 || !fgTable)
283  return;
284 
285  SortTable();
286 
287  int n = 0, ninit = 0, nl = 0;
288 
289  int nch = strlen(option);
290  TRegexp re(option, kTRUE);
291 
292  Printf("\nDefined classes");
293  Printf("class version bits initialized");
294  Printf("================================================================");
295  for (UInt_t i = 0; i < fgTally; i++) {
296  TClassRec *r = fgSortedTable[i];
297  if (!r) break;
298  n++;
299  TString s = r->fName;
300  if (nch && strcmp(option,r->fName) && s.Index(re) == kNPOS) continue;
301  nl++;
302  if (TClass::GetClass(r->fName, kFALSE)) {
303  ninit++;
304  Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
305  } else
306  Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
307  }
308  Printf("----------------------------------------------------------------");
309  Printf("Listed Classes: %4d Total classes: %4d initialized: %4d",nl, n, ninit);
310  Printf("================================================================\n");
311 }
312 
313 //---- static members --------------------------------------------------------
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Returns class at index from sorted class table. Don't use this iterator
317 /// while modifying the class table. The class table can be modified
318 /// when making calls like TClass::GetClass(), etc.
319 /// Returns 0 if index points beyond last class name.
320 
322 {
323  SortTable();
324  if (index < fgTally) {
325  TClassRec *r = fgSortedTable[index];
326  if (r) return r->fName;
327  }
328  return 0;
329 }
330 
331 //______________________________________________________________________________
332 int TClassTable::Classes() { return fgTally; }
333 //______________________________________________________________________________
334 void TClassTable::Init() { fgCursor = 0; SortTable(); }
335 
336 namespace ROOT { class TForNamespace {}; } // Dummy class to give a typeid to namespace (see also TGenericClassInfo)
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// Add a class to the class table (this is a static function).
340 /// Note that the given cname *must* be already normalized.
341 
342 void TClassTable::Add(const char *cname, Version_t id, const std::type_info &info,
343  DictFuncPtr_t dict, Int_t pragmabits)
344 {
345  if (!gClassTable)
346  new TClassTable;
347 
348  if (!cname || *cname == 0)
349  ::Fatal("TClassTable::Add()", "Failed to deduce type for '%s'", info.name());
350 
351  // check if already in table, if so return
352  TClassRec *r = FindElementImpl(cname, kTRUE);
353  if (r->fName && r->fInfo) {
354  if ( strcmp(r->fInfo->name(),typeid(ROOT::TForNamespace).name())==0
355  && strcmp(info.name(),typeid(ROOT::TForNamespace).name())==0 ) {
356  // We have a namespace being reloaded.
357  // This okay we just keep the old one.
358  return;
359  }
360  if (!TClassEdit::IsStdClass(cname)) {
361  // Warn only for class that are not STD classes
362  ::Warning("TClassTable::Add", "class %s already in TClassTable", cname);
363  }
364  return;
365  } else if (ROOT::Internal::gROOTLocal && gCling) {
366  TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
367  if (oldcl) { // && oldcl->GetClassInfo()) {
368  // As a work-around to ROOT-6012, we need to register the class even if
369  // it is not a template instance, because a forward declaration in the header
370  // files loaded by the current dictionary wil also de-activate the update
371  // class info mechanism!
372 
373  // The TClass exist and already has a class info, so it must
374  // correspond to a class template instantiation which the interpreter
375  // was able to make with the library containing the TClass Init.
376  // Because it is already known to the interpreter, the update class info
377  // will not be triggered, we need to force it.
378  gCling->RegisterTClassUpdate(oldcl,dict);
379  }
380  }
381 
382  if (!r->fName) r->fName = StrDup(cname);
383  r->fId = id;
384  r->fBits = pragmabits;
385  r->fDict = dict;
386  r->fInfo = &info;
387 
388  fgIdMap->Add(info.name(),r);
389 
390  fgSorted = kFALSE;
391 }
392 
393 ////////////////////////////////////////////////////////////////////////////////
394 /// Add a class to the class table (this is a static function).
395 
397 {
398  if (!gClassTable)
399  new TClassTable;
400 
401  // By definition the name in the TProtoClass is (must be) the normalized
402  // name, so there is no need to tweak it.
403  const char *cname = proto->GetName();
404 
405  // check if already in table, if so return
406  TClassRec *r = FindElementImpl(cname, kTRUE);
407  if (r->fName) {
408  if (r->fProto) delete r->fProto;
409  r->fProto = proto;
410  return;
411  } else if (ROOT::Internal::gROOTLocal && gCling) {
412  TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
413  if (oldcl) { // && oldcl->GetClassInfo()) {
414  // As a work-around to ROOT-6012, we need to register the class even if
415  // it is not a template instance, because a forward declaration in the header
416  // files loaded by the current dictionary wil also de-activate the update
417  // class info mechanism!
418 
419  ::Warning("TClassTable::Add(TProtoClass*)","Called for existing class without a prior call add the dictionary function.");
420  }
421  }
422 
423  r->fName = StrDup(cname);
424  r->fId = 0;
425  r->fBits = 0;
426  r->fDict = 0;
427  r->fInfo = 0;
428  r->fProto= proto;
429 
430  fgSorted = kFALSE;
431 }
432 
433 ////////////////////////////////////////////////////////////////////////////////
434 
435 void TClassTable::AddAlternate(const char *normName, const char *alternate)
436 {
437  if (!gClassTable)
438  new TClassTable;
439 
440  UInt_t slot = ROOT::ClassTableHash(alternate, fgSize);
441 
442  for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
443  if (strcmp(alternate,a->fName)==0) {
444  if (strcmp(normName,a->fNormName) != 0) {
445  fprintf(stderr,"Error in TClassTable::AddAlternate: "
446  "Second registration of %s with a different normalized name (old: '%s', new: '%s')\n",
447  alternate, a->fNormName, normName);
448  return;
449  }
450  }
451  }
452 
453  fgAlternate[slot] = new TClassAlt(alternate,normName,fgAlternate[slot]);
454 }
455 
456 ////////////////////////////////////////////////////////////////////////////////
457 
458 Bool_t TClassTable::Check(const char *cname, std::string &normname)
459 {
460  if (!CheckClassTableInit()) return kFALSE;
461 
462  UInt_t slot = ROOT::ClassTableHash(cname, fgSize);
463 
464  // Check if 'cname' is a known normalized name.
465  for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
466  if (strcmp(cname,r->fName)==0) return kTRUE;
467 
468  // See if 'cname' is register in the list of alternate names
469  for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
470  if (strcmp(cname,a->fName)==0) {
471  normname = a->fNormName;
472  return kTRUE;
473  }
474  }
475 
476  return kFALSE;
477 }
478 
479 ////////////////////////////////////////////////////////////////////////////////
480 /// Remove a class from the class table. This happens when a shared library
481 /// is unloaded (i.e. the dtor's of the global init objects are called).
482 
483 void TClassTable::Remove(const char *cname)
484 {
485  if (!CheckClassTableInit()) return;
486 
487  UInt_t slot = ROOT::ClassTableHash(cname,fgSize);
488 
489  TClassRec *r;
490  TClassRec *prev = 0;
491  for (r = fgTable[slot]; r; r = r->fNext) {
492  if (!strcmp(r->fName, cname)) {
493  if (prev)
494  prev->fNext = r->fNext;
495  else
496  fgTable[slot] = r->fNext;
497  fgIdMap->Remove(r->fInfo->name());
498  r->fNext = 0; // Do not delete the others.
499  delete r;
500  fgTally--;
501  fgSorted = kFALSE;
502  break;
503  }
504  prev = r;
505  }
506 }
507 
508 ////////////////////////////////////////////////////////////////////////////////
509 /// Find a class by name in the class table (using hash of name). Returns
510 /// 0 if the class is not in the table. Unless arguments insert is true in
511 /// which case a new entry is created and returned.
512 
513 TClassRec *TClassTable::FindElementImpl(const char *cname, Bool_t insert)
514 {
515  UInt_t slot = ROOT::ClassTableHash(cname,fgSize);
516 
517  for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
518  if (strcmp(cname,r->fName)==0) return r;
519 
520  if (!insert) return 0;
521 
522  fgTable[slot] = new TClassRec(fgTable[slot]);
523 
524  fgTally++;
525  return fgTable[slot];
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// Find a class by name in the class table (using hash of name). Returns
530 /// 0 if the class is not in the table. Unless arguments insert is true in
531 /// which case a new entry is created and returned.
532 /// cname can be any spelling of the class name. See FindElementImpl if the
533 /// name is already normalized.
534 
535 TClassRec *TClassTable::FindElement(const char *cname, Bool_t insert)
536 {
537  if (!CheckClassTableInit()) return nullptr;
538 
539  // The recorded name is normalized, let's make sure we convert the
540  // input accordingly.
541  std::string normalized;
542  TClassEdit::GetNormalizedName(normalized,cname);
543 
544  return FindElementImpl(normalized.c_str(), insert);
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Returns the ID of a class.
549 
550 Version_t TClassTable::GetID(const char *cname)
551 {
552  TClassRec *r = FindElement(cname);
553  if (r) return r->fId;
554  return -1;
555 }
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Returns the pragma bits as specified in the LinkDef.h file.
559 
561 {
562  TClassRec *r = FindElement(cname);
563  if (r) return r->fBits;
564  return 0;
565 }
566 
567 ////////////////////////////////////////////////////////////////////////////////
568 /// Given the class name returns the Dictionary() function of a class
569 /// (uses hash of name).
570 
572 {
573  if (gDebug > 9) {
574  ::Info("GetDict", "searches for %s", cname);
575  fgIdMap->Print();
576  }
577 
578  TClassRec *r = FindElement(cname);
579  if (r) return r->fDict;
580  return 0;
581 }
582 
583 ////////////////////////////////////////////////////////////////////////////////
584 /// Given the std::type_info returns the Dictionary() function of a class
585 /// (uses hash of std::type_info::name()).
586 
587 DictFuncPtr_t TClassTable::GetDict(const std::type_info& info)
588 {
589  if (!CheckClassTableInit()) return nullptr;
590 
591  if (gDebug > 9) {
592  ::Info("GetDict", "searches for %s at 0x%lx", info.name(), (Long_t)&info);
593  fgIdMap->Print();
594  }
595 
596  TClassRec *r = fgIdMap->Find(info.name());
597  if (r) return r->fDict;
598  return 0;
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////
602 /// Given the normalized class name returns the Dictionary() function of a class
603 /// (uses hash of name).
604 
606 {
607  if (!CheckClassTableInit()) return nullptr;
608 
609  if (gDebug > 9) {
610  ::Info("GetDict", "searches for %s", cname);
611  fgIdMap->Print();
612  }
613 
614  TClassRec *r = FindElementImpl(cname,kFALSE);
615  if (r) return r->fDict;
616  return 0;
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Given the class name returns the TClassProto object for the class.
621 /// (uses hash of name).
622 
624 {
625  if (gDebug > 9) {
626  ::Info("GetDict", "searches for %s", cname);
627  }
628 
629  if (!CheckClassTableInit()) return nullptr;
630 
631  if (gDebug > 9) {
632  ::Info("GetDict", "searches for %s", cname);
633  fgIdMap->Print();
634  }
635 
636  TClassRec *r = FindElement(cname);
637  if (r) return r->fProto;
638  return 0;
639 }
640 
641 ////////////////////////////////////////////////////////////////////////////////
642 /// Given the class normalized name returns the TClassProto object for the class.
643 /// (uses hash of name).
644 
646 {
647  if (gDebug > 9) {
648  ::Info("GetDict", "searches for %s", cname);
649  }
650 
651  if (!CheckClassTableInit()) return nullptr;
652 
653  if (gDebug > 9) {
654  fgIdMap->Print();
655  }
656 
657  TClassRec *r = FindElementImpl(cname,kFALSE);
658  if (r) return r->fProto;
659  return 0;
660 }
661 
662 ////////////////////////////////////////////////////////////////////////////////
663 
664 extern "C" {
665  static int ClassComp(const void *a, const void *b)
666  {
667  // Function used for sorting classes alphabetically.
668 
669  return strcmp((*(TClassRec **)a)->fName, (*(TClassRec **)b)->fName);
670  }
671 }
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Returns next class from sorted class table. Don't use this iterator
675 /// while modifying the class table. The class table can be modified
676 /// when making calls like TClass::GetClass(), etc.
677 
679 {
680  if (fgCursor < fgTally) {
681  TClassRec *r = fgSortedTable[fgCursor++];
682  return r->fName;
683  } else
684  return 0;
685 }
686 
687 ////////////////////////////////////////////////////////////////////////////////
688 /// Print the class table. Before printing the table is sorted
689 /// alphabetically.
690 
692 {
693  if (fgTally == 0 || !fgTable)
694  return;
695 
696  SortTable();
697 
698  int n = 0, ninit = 0;
699 
700  Printf("\nDefined classes");
701  Printf("class version bits initialized");
702  Printf("================================================================");
703  UInt_t last = fgTally;
704  for (UInt_t i = 0; i < last; i++) {
705  TClassRec *r = fgSortedTable[i];
706  if (!r) break;
707  n++;
708  // Do not use TClass::GetClass to avoid any risk of autoloading.
709  if (gROOT->GetListOfClasses()->FindObject(r->fName)) {
710  ninit++;
711  Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
712  } else
713  Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
714  }
715  Printf("----------------------------------------------------------------");
716  Printf("Total classes: %4d initialized: %4d", n, ninit);
717  Printf("================================================================\n");
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Sort the class table by ascending class ID's.
722 
724 {
725  if (!fgSorted) {
726  delete [] fgSortedTable;
727  fgSortedTable = new TClassRec* [fgTally];
728 
729  int j = 0;
730  for (UInt_t i = 0; i < fgSize; i++)
731  for (TClassRec *r = fgTable[i]; r; r = r->fNext)
732  fgSortedTable[j++] = r;
733 
734  ::qsort(fgSortedTable, fgTally, sizeof(TClassRec *), ::ClassComp);
735  fgSorted = kTRUE;
736  }
737 }
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 /// Deletes the class table (this static class function calls the dtor).
741 
743 {
744  if (gClassTable) {
745  for (UInt_t i = 0; i < fgSize; i++)
746  delete fgTable[i]; // Will delete all the elements in the chain.
747 
748  delete [] fgTable; fgTable = 0;
749  delete [] fgSortedTable; fgSortedTable = 0;
750  delete fgIdMap; fgIdMap = 0;
751  fgSize = 0;
752  SafeDelete(gClassTable);
753  }
754 }
755 
756 ////////////////////////////////////////////////////////////////////////////////
757 /// Global function called by the ctor of a class's init class
758 /// (see the ClassImp macro).
759 
760 void ROOT::AddClass(const char *cname, Version_t id,
761  const std::type_info& info,
762  DictFuncPtr_t dict,
763  Int_t pragmabits)
764 {
765  if (!TROOT::Initialized() && !gClassTable) {
766  auto r = std::unique_ptr<TClassRec>(new TClassRec(nullptr));
767  r->fName = StrDup(cname);
768  r->fId = id;
769  r->fBits = pragmabits;
770  r->fDict = dict;
771  r->fInfo = &info;
772  GetDelayedAddClass().emplace_back(std::move(r));
773  } else {
774  TClassTable::Add(cname, id, info, dict, pragmabits);
775  }
776 }
777 
778 ////////////////////////////////////////////////////////////////////////////////
779 /// Global function called by GenerateInitInstance.
780 /// (see the ClassImp macro).
781 
782 void ROOT::AddClassAlternate(const char *normName, const char *alternate)
783 {
784  if (!TROOT::Initialized() && !gClassTable) {
785  GetDelayedAddClassAlternate().emplace_back(normName, alternate);
786  } else {
787  TClassTable::AddAlternate(normName, alternate);
788  }
789 }
790 
791 ////////////////////////////////////////////////////////////////////////////////
792 /// Global function to update the version number.
793 /// This is called via the RootClassVersion macro.
794 ///
795 /// if cl!=0 and cname==-1, set the new class version if and only is
796 /// greater than the existing one and greater or equal to 2;
797 /// and also ignore the request if fVersionUsed is true.
798 ///
799 /// Note on class version number:
800 /// - If no class has been specified, TClass::GetVersion will return -1
801 /// - The Class Version 0 request the whole object to be transient
802 /// - The Class Version 1, unless specify via ClassDef indicates that the
803 /// I/O should use the TClass checksum to distinguish the layout of the class
804 
805 void ROOT::ResetClassVersion(TClass *cl, const char *cname, Short_t newid)
806 {
807  if (cname && cname!=(void*)-1) {
808  TClassRec *r = TClassTable::FindElement(cname,kFALSE);
809  if (r) r->fId = newid;
810  }
811  if (cl) {
812  if (cl->fVersionUsed) {
813  // Problem, the reset is called after the first usage!
814  if (cname!=(void*)-1)
815  Error("ResetClassVersion","Version number of %s can not be changed after first usage!",
816  cl->GetName());
817  } else {
818  if (newid < 0) {
819  Error("SetClassVersion","The class version (for %s) must be positive (value %d is ignored)",cl->GetName(),newid);
820  }
821  if (cname==(void*)-1) {
822  if (cl->fClassVersion<newid && 2<=newid) {
823  cl->SetClassVersion(newid);
824  }
825  } else {
826  cl->SetClassVersion(newid);
827  }
828  }
829  }
830 }
831 
832 
833 ////////////////////////////////////////////////////////////////////////////////
834 /// Global function called by the dtor of a class's init class
835 /// (see the ClassImp macro).
836 
837 void ROOT::RemoveClass(const char *cname)
838 {
839  // don't delete class information since it is needed by the I/O system
840  // to write the StreamerInfo to file
841  if (cname) {
842  // Let's still remove this information to allow reloading later.
843  // Anyway since the shared library has been unloaded, the dictionary
844  // pointer is now invalid ....
845  // We still keep the TClass object around because TFile needs to
846  // get to the TStreamerInfo.
847  if (gROOT && gROOT->GetListOfClasses()) {
848  TObject *pcname;
849  if ((pcname=gROOT->GetListOfClasses()->FindObject(cname))) {
850  TClass *cl = dynamic_cast<TClass*>(pcname);
851  if (cl) cl->SetUnloaded();
852  }
853  }
854  TClassTable::Remove(cname);
855  }
856 }
857 
858 ////////////////////////////////////////////////////////////////////////////////
859 /// Global function to register the implementation file and line of
860 /// a class template (i.e. NOT a concrete class).
861 
862 TNamed *ROOT::RegisterClassTemplate(const char *name, const char *file,
863  Int_t line)
864 {
865  static TList table;
866  static Bool_t isInit = kFALSE;
867  if (!isInit) {
868  table.SetOwner(kTRUE);
869  isInit = kTRUE;
870  }
871 
872  TString classname(name);
873  Ssiz_t loc = classname.Index("<");
874  if (loc >= 1) classname.Remove(loc);
875  if (file) {
876  TNamed *obj = new TNamed((const char*)classname, file);
877  obj->SetUniqueID(line);
878  table.Add(obj);
879  return obj;
880  } else {
881  return (TNamed*)table.FindObject(classname);
882  }
883 }
void AddClass(const char *cname, Version_t id, const std::type_info &info, DictFuncPtr_t dict, Int_t pragmabits)
Global function called by the ctor of a class&#39;s init class (see the ClassImp macro).
static ROOT::TClassRec ** fgSortedTable
Definition: TClassTable.h:46
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
short Version_t
Definition: RtypesCore.h:61
static Bool_t Check(const char *cname, std::string &normname)
TLine * line
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
Definition: TObjString.h:28
const char Option_t
Definition: RtypesCore.h:62
static int ClassComp(const void *a, const void *b)
static Version_t GetID(const char *cname)
Returns the ID of a class.
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
static void SortTable()
Sort the class table by ascending class ID&#39;s.
static TProtoClass * GetProto(const char *cname)
Given the class name returns the TClassProto object for the class.
void SetClassVersion(Version_t version)
Private function.
Definition: TClass.cxx:5405
static Bool_t CheckClassTableInit()
Return true fs the table exist.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Persistent version of a TClass.
Definition: TProtoClass.h:35
Regular expression class.
Definition: TRegexp.h:31
void Add(TObject *obj)
This function may not be used (but we need to provide it since it is a pure virtual in TCollection)...
Definition: TMap.cxx:53
std::vector< std::unique_ptr< TClassRec > > & GetDelayedAddClass()
#define gROOT
Definition: TROOT.h:402
ROOT::TMapTypeToClassRec IdMap_t
Definition: TClassTable.h:42
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
This class registers for all classes their name, id and dictionary function in a hash table...
Definition: TClassTable.h:36
virtual void RegisterTClassUpdate(TClass *oldcl, DictFuncPtr_t dict)=0
TClassTable()
TClassTable is a singleton (i.e. only one can exist per application).
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
static void Add(const char *cname, Version_t id, const std::type_info &info, DictFuncPtr_t dict, Int_t pragmabits)
Add a class to the class table (this is a static function).
static void Init()
#define SafeDelete(p)
Definition: RConfig.h:509
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2754
void AddClassAlternate(const char *normName, const char *alternate)
Global function called by GenerateInitInstance.
void Info(const char *location, const char *msgfmt,...)
XFontStruct * id
Definition: TGX11.cxx:108
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition: TClass.h:227
static ROOT::TClassRec ** fgTable
Definition: TClassTable.h:45
TClass *(* DictFuncPtr_t)()
Definition: Rtypes.h:73
TClassTable * gClassTable
Definition: TClassTable.cxx:44
TObject * Value() const
Definition: TMap.h:121
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
A doubly linked list.
Definition: TList.h:44
std::vector< std::pair< const char *, const char * > > & GetDelayedAddClassAlternate()
R__EXTERN TROOT * gROOTLocal
Definition: TROOT.h:375
void ResetClassVersion(TClass *, const char *, Short_t)
Global function to update the version number.
ROOT::R::TRInterface & r
Definition: Object.C:4
void RemoveClass(const char *cname)
Global function called by the dtor of a class&#39;s init class (see the ClassImp macro).
static void AddAlternate(const char *normname, const char *alternate)
static UInt_t fgTally
Definition: TClassTable.h:49
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:788
void Print(Option_t *option="") const
Print the class table.
TObject * Remove(TObject *key)
Remove the (key,value) pair with key from the map.
Definition: TMap.cxx:295
auto * a
Definition: textangle.C:12
void SetUnloaded()
Call this method to indicate that the shared library containing this class&#39;s code has been removed (u...
Definition: TClass.cxx:5991
static void Remove(const char *cname)
Remove a class from the class table.
unsigned int UInt_t
Definition: RtypesCore.h:42
short Short_t
Definition: RtypesCore.h:35
static Int_t GetPragmaBits(const char *name)
Returns the pragma bits as specified in the LinkDef.h file.
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
ROOT::TMapTypeToTClass IdMap_t
Definition: TClass.h:72
void Warning(const char *location, const char *msgfmt,...)
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
TString & String()
Definition: TObjString.h:49
#define Printf
Definition: TGeoToOCC.h:18
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2544
static UInt_t fgSize
Definition: TClassTable.h:48
const Bool_t kFALSE
Definition: RtypesCore.h:88
static void Terminate()
Deletes the class table (this static class function calls the dtor).
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
static IdMap_t * fgIdMap
Definition: TClassTable.h:47
Class used by TMap to store (key,value) pairs.
Definition: TMap.h:102
static ROOT::TClassRec * FindElement(const char *cname, Bool_t insert=kFALSE)
Find a class by name in the class table (using hash of name).
void Add(THist< DIMENSIONS, PRECISION_TO, STAT_TO... > &to, const THist< DIMENSIONS, PRECISION_FROM, STAT_FROM... > &from)
Add two histograms.
Definition: THist.hxx:308
static char * Next()
Returns next class from sorted class table.
#define ClassImp(name)
Definition: Rtypes.h:359
void Print(std::ostream &os, const OptionType &opt)
~TClassTable()
TClassTable singleton is deleted in Terminate().
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
static UInt_t fgCursor
Definition: TClassTable.h:51
static constexpr double s
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:2887
UInt_t Find(std::list< std::pair< const Node< T > *, Float_t > > &nlist, const Node< T > *node, const T &event, UInt_t nfind)
Mother of all ROOT objects.
Definition: TObject.h:37
static void PrintTable()
Print the class table.
Version_t fClassVersion
Definition: TClass.h:195
TObject * FindObject(const char *keyname) const
Check if a (key,value) pair exists with keyname as name of the key.
Definition: TMap.cxx:214
virtual void Add(TObject *obj)
Definition: TList.h:87
static ROOT::TClassRec * FindElementImpl(const char *cname, Bool_t insert)
Find a class by name in the class table (using hash of name).
Definition: file.py:1
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
const char * proto
Definition: civetweb.c:11652
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
static Bool_t fgSorted
Definition: TClassTable.h:50
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:528
TNamed * RegisterClassTemplate(const char *name, const char *file, Int_t line)
Global function to register the implementation file and line of a class template (i.e.
const Bool_t kTRUE
Definition: RtypesCore.h:87
static char * At(UInt_t index)
Returns class at index from sorted class table.
static DictFuncPtr_t GetDictNorm(const char *cname)
Given the normalized class name returns the Dictionary() function of a class (uses hash of name)...
const Int_t n
Definition: legend1.C:16
char name[80]
Definition: TGX11.cxx:109
static UInt_t ClassTableHash(const char *name, UInt_t size)
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
static ROOT::TClassAlt ** fgAlternate
Definition: TClassTable.h:44