Logo ROOT   6.16/01
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
14This class registers for all classes their name, id and dictionary
15function in a hash table. Classes are automatically added by the
16ctor of a special init class when a global of this init class is
17initialized 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
42using namespace ROOT;
43
45
46TClassAlt **TClassTable::fgAlternate;
47TClassRec **TClassTable::fgTable;
54
56
57////////////////////////////////////////////////////////////////////////////////
58
59namespace 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 }
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
280void 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//______________________________________________________________________________
333//______________________________________________________________________________
335
336namespace 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
342void 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
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
431}
432
433////////////////////////////////////////////////////////////////////////////////
434
435void 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
458Bool_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
483void 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--;
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
513TClassRec *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
535TClassRec *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
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
587DictFuncPtr_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
664extern "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;
753 }
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Global function called by the ctor of a class's init class
758/// (see the ClassImp macro).
759
760void 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
782void 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
805void 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
837void 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
862TNamed *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}
ROOT::R::TRInterface & r
Definition: Object.C:4
#define SafeDelete(p)
Definition: RConfig.hxx:529
#define b(i)
Definition: RSha256.hxx:100
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
short Short_t
Definition: RtypesCore.h:35
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
TClass *(* DictFuncPtr_t)()
Definition: Rtypes.h:77
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
TClassTable * gClassTable
Definition: TClassTable.cxx:44
static int ClassComp(const void *a, const void *b)
ROOT::TMapTypeToTClass IdMap_t
Definition: TClass.h:72
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
#define Printf
Definition: TGeoToOCC.h:18
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
#define gROOT
Definition: TROOT.h:410
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2465
const char * proto
Definition: civetweb.c:16604
This class registers for all classes their name, id and dictionary function in a hash table.
Definition: TClassTable.h:36
static void PrintTable()
Print the class table.
static Int_t GetPragmaBits(const char *name)
Returns the pragma bits as specified in the LinkDef.h file.
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
static Version_t GetID(const char *cname)
Returns the ID of a class.
ROOT::TMapTypeToClassRec IdMap_t
Definition: TClassTable.h:42
static void SortTable()
Sort the class table by ascending class ID's.
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
static DictFuncPtr_t GetDictNorm(const char *cname)
Given the normalized class name returns the Dictionary() function of a class (uses hash of name).
static void AddAlternate(const char *normname, const char *alternate)
static ROOT::TClassAlt ** fgAlternate
Definition: TClassTable.h:44
static ROOT::TClassRec * FindElementImpl(const char *cname, Bool_t insert)
Find a class by name in the class table (using hash of name).
static void Terminate()
Deletes the class table (this static class function calls the dtor).
void Print(Option_t *option="") const
Print the class table.
static TProtoClass * GetProto(const char *cname)
Given the class name returns the TClassProto object for the class.
TClassTable()
TClassTable is a singleton (i.e. only one can exist per application).
static char * Next()
Returns next class from sorted class table.
static char * At(UInt_t index)
Returns class at index from sorted class table.
static Bool_t Check(const char *cname, std::string &normname)
static void Init()
static void Remove(const char *cname)
Remove a class from the class table.
static ROOT::TClassRec ** fgSortedTable
Definition: TClassTable.h:46
static ROOT::TClassRec ** fgTable
Definition: TClassTable.h:45
static IdMap_t * fgIdMap
Definition: TClassTable.h:47
static Bool_t CheckClassTableInit()
Return true fs the table exist.
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).
~TClassTable()
TClassTable singleton is deleted in Terminate().
static Bool_t fgSorted
Definition: TClassTable.h:50
static UInt_t fgTally
Definition: TClassTable.h:49
static UInt_t fgSize
Definition: TClassTable.h:48
static ROOT::TClassRec * FindElement(const char *cname, Bool_t insert=kFALSE)
Find a class by name in the class table (using hash of name).
static UInt_t fgCursor
Definition: TClassTable.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
Version_t fClassVersion
Definition: TClass.h:195
void SetUnloaded()
Call this method to indicate that the shared library containing this class's code has been removed (u...
Definition: TClass.cxx:6023
void SetClassVersion(Version_t version)
Private function.
Definition: TClass.cxx:5437
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition: TClass.h:227
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
virtual void RegisterTClassUpdate(TClass *oldcl, DictFuncPtr_t dict)=0
A doubly linked list.
Definition: TList.h:44
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Collectable string class.
Definition: TObjString.h:28
TString & String()
Definition: TObjString.h:49
Mother of all ROOT objects.
Definition: TObject.h:37
UInt_t fBits
bit field status word
Definition: TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Class used by TMap to store (key,value) pairs.
Definition: TMap.h:102
Persistent version of a TClass.
Definition: TProtoClass.h:35
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2859
Regular expression class.
Definition: TRegexp.h:31
TLine * line
const Int_t n
Definition: legend1.C:16
void Add(RHist< DIMENSIONS, PRECISION_TO, STAT_TO... > &to, const RHist< DIMENSIONS, PRECISION_FROM, STAT_FROM... > &from)
Add two histograms.
Definition: RHist.hxx:310
R__EXTERN TROOT * gROOTLocal
Definition: TROOT.h:383
void Print(std::ostream &os, const OptionType &opt)
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
std::vector< std::pair< const char *, const char * > > & GetDelayedAddClassAlternate()
std::vector< std::unique_ptr< TClassRec > > & GetDelayedAddClass()
void AddClassAlternate(const char *normName, const char *alternate)
Global function called by GenerateInitInstance.
void RemoveClass(const char *cname)
Global function called by the dtor of a class's init class (see the ClassImp macro).
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's init class (see the ClassImp macro).
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....
static UInt_t ClassTableHash(const char *name, UInt_t size)
void ResetClassVersion(TClass *, const char *, Short_t)
Global function to update the version number.
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:798
static constexpr double s
UInt_t Find(std::list< std::pair< const Node< T > *, Float_t > > &nlist, const Node< T > *node, const T &event, UInt_t nfind)
Definition: file.py:1
void table()
Definition: table.C:85
auto * a
Definition: textangle.C:12