Logo ROOT   6.16/01
Reference Guide
TClass.cxx
Go to the documentation of this file.
1// @(#)root/meta:$Id: 7109cb45f1219c2aae6be19906ae5a63e31972ef $
2// Author: Rene Brun 07/01/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 TClass
13The ROOT global object gROOT contains a list of all defined
14classes. This list is build when a reference to a class dictionary
15is made. When this happens, the static "class"::Dictionary()
16function is called to create a TClass object describing the
17class. The Dictionary() function is defined in the ClassDef
18macro and stored (at program startup or library load time) together
19with the class name in the TClassTable singleton object.
20For a description of all dictionary classes see TDictionary.
21
22The name of the class as registered in the TClass object and in the
23list of class is the "normalized name" and is defined as:
24
25The name of the type as accessible from the global scope to which
26a 'using namespace std;' has been applied to and with:
27 - all typedefs disagreed except for Double32_t, Float16_t,
28 Long64_t, ULong64_t and std::string.
29 - default template parameters removed for STL collections and
30 added for any other class templates instances.
31 - Fully qualified both for the class name itself and all of its
32 component, except that, at least for moment, all 'std::' are
33 stripped.
34*/
35
36//*-*x7.5 macros/layout_class
37
38#include "TClass.h"
39
40#include "Riostream.h"
41#include "TBaseClass.h"
42#include "TBrowser.h"
43#include "TBuffer.h"
44#include "TClassGenerator.h"
45#include "TClassEdit.h"
46#include "TClassMenuItem.h"
47#include "TClassRef.h"
48#include "TClassTable.h"
49#include "TDataMember.h"
50#include "TDataType.h"
51#include "TEnum.h"
52#include "TError.h"
53#include "TExMap.h"
54#include "TFunctionTemplate.h"
55#include "THashList.h"
56#include "TInterpreter.h"
57#include "TMemberInspector.h"
58#include "TMethod.h"
59#include "TMethodArg.h"
60#include "TMethodCall.h"
61#include "TObjArray.h"
62#include "TProtoClass.h"
63#include "TROOT.h"
64#include "TRealData.h"
65#include "TCheckHashRecursiveRemoveConsistency.h" // Private header
66#include "TStreamer.h"
67#include "TStreamerElement.h"
70#include "TVirtualIsAProxy.h"
71#include "TVirtualRefProxy.h"
72#include "TVirtualMutex.h"
73#include "TVirtualPad.h"
74#include "THashTable.h"
75#include "TSchemaRuleSet.h"
76#include "TGenericClassInfo.h"
77#include "TIsAProxy.h"
78#include "TSchemaRule.h"
79#include "TSystem.h"
80#include "TThreadSlots.h"
81
82#include <cstdio>
83#include <cctype>
84#include <set>
85#include <sstream>
86#include <string>
87#include <map>
88#include <typeinfo>
89#include <cmath>
90#include <assert.h>
91#include <vector>
92#include <memory>
93
94#include "TSpinLockGuard.h"
95
96#ifdef WIN32
97#include <io.h>
98#include "Windows4Root.h"
99#include <Psapi.h>
100#define RTLD_DEFAULT ((void *)::GetModuleHandle(NULL))
101#define dlsym(library, function_name) ::GetProcAddress((HMODULE)library, function_name)
102#else
103#include <dlfcn.h>
104#endif
105
106#include "TListOfDataMembers.h"
107#include "TListOfFunctions.h"
109#include "TListOfEnums.h"
110#include "TListOfEnumsWithLock.h"
111#include "TViewPubDataMembers.h"
112#include "TViewPubFunctions.h"
113#include "TArray.h"
114#include "TClonesArray.h"
115#include "TRef.h"
116#include "TRefArray.h"
117
118using namespace std;
119
120// Mutex to protect CINT and META operations
121// (exported to be used for similar cases in related classes)
122
124
125namespace {
126 class TMmallocDescTemp {
127 private:
128 void *fSave;
129 public:
130 TMmallocDescTemp(void *value = 0) :
132 ~TMmallocDescTemp() { ROOT::Internal::gMmallocDesc = fSave; }
133 };
134}
135
136std::atomic<Int_t> TClass::fgClassCount;
137
138// Implementation of the TDeclNameRegistry
139
140////////////////////////////////////////////////////////////////////////////////
141/// TDeclNameRegistry class constructor.
142
144{
145 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
146 std::atomic_flag_clear( &fSpinLock );
147}
148
149////////////////////////////////////////////////////////////////////////////////
150/// Extract this part of the name
151/// 1. Templates ns::ns2::,,,::THISPART<...
152/// 2. Namespaces,classes ns::ns2::,,,::THISPART
153
155{
156 // Sanity check
157 auto strLen = strlen(name);
158 if (strLen == 0) return;
159 // find <. If none, put end of string
160 const char* endCharPtr = strchr(name, '<');
161 endCharPtr = !endCharPtr ? &name[strLen] : endCharPtr;
162 // find last : before the <. If not found, put begin of string
163 const char* beginCharPtr = endCharPtr;
164 while (beginCharPtr!=name){
165 if (*beginCharPtr==':'){
166 beginCharPtr++;
167 break;
168 }
169 beginCharPtr--;
170 }
171 beginCharPtr = beginCharPtr!=endCharPtr ? beginCharPtr : name;
172 std::string s(beginCharPtr, endCharPtr);
173 if (fVerbLevel>1)
174 printf("TDeclNameRegistry::AddQualifiedName Adding key %s for class/namespace %s\n", s.c_str(), name);
175 ROOT::Internal::TSpinLockGuard slg(fSpinLock);
176 fClassNamesSet.insert(s);
177}
178
179////////////////////////////////////////////////////////////////////////////////
180
182{
183 Bool_t found = false;
184 {
185 ROOT::Internal::TSpinLockGuard slg(fSpinLock);
186 found = fClassNamesSet.find(name) != fClassNamesSet.end();
187 }
188 return found;
189}
190
191////////////////////////////////////////////////////////////////////////////////
192
194{
195 if (fVerbLevel > 1) {
196 printf("TDeclNameRegistry Destructor. List of %lu names:\n",
197 (long unsigned int)fClassNamesSet.size());
198 for (auto const & key: fClassNamesSet) {
199 printf(" - %s\n", key.c_str());
200 }
201 }
202}
203
204////////////////////////////////////////////////////////////////////////////////
205
207 const char *name,
208 TDeclNameRegistry &emuRegistry): fState(state),fName(name), fNoInfoOrEmuOrFwdDeclNameRegistry(emuRegistry) {}
209
210////////////////////////////////////////////////////////////////////////////////
211
213 if (fState == TClass::kNoInfo ||
217 }
218 }
219
220// Initialise the global member of TClass
222
223//Intent of why/how TClass::New() is called
224//[Not a static data member because MacOS does not support static thread local data member ... who knows why]
226 TTHREAD_TLS(TClass::ENewType) fgCallingNew = TClass::kRealNew;
227 return fgCallingNew;
228}
229
230struct ObjRepoValue {
231 ObjRepoValue(const TClass *what, Version_t version) : fClass(what),fVersion(version) {}
232 const TClass *fClass;
233 Version_t fVersion;
234};
235
237typedef std::multimap<void*, ObjRepoValue> RepoCont_t;
239
240static void RegisterAddressInRepository(const char * /*where*/, void *location, const TClass *what)
241{
242 // Register the object for special handling in the destructor.
243
244 Version_t version = what->GetClassVersion();
245// if (!gObjectVersionRepository.count(location)) {
246// Info(where, "Registering address %p of class '%s' version %d", location, what->GetName(), version);
247// } else {
248// Warning(where, "Registering address %p again of class '%s' version %d", location, what->GetName(), version);
249// }
250 {
252 gObjectVersionRepository.insert(RepoCont_t::value_type(location, RepoCont_t::mapped_type(what,version)));
253 }
254#if 0
255 // This code could be used to prevent an address to be registered twice.
256 std::pair<RepoCont_t::iterator, Bool_t> tmp = gObjectVersionRepository.insert(RepoCont_t::value_type>(location, RepoCont_t::mapped_type(what,version)));
257 if (!tmp.second) {
258 Warning(where, "Reregistering an object of class '%s' version %d at address %p", what->GetName(), version, p);
259 gObjectVersionRepository.erase(tmp.first);
260 tmp = gObjectVersionRepository.insert(RepoCont_t::value_type>(location, RepoCont_t::mapped_type(what,version)));
261 if (!tmp.second) {
262 Warning(where, "Failed to reregister an object of class '%s' version %d at address %p", what->GetName(), version, location);
263 }
264 }
265#endif
266}
267
268static void UnregisterAddressInRepository(const char * /*where*/, void *location, const TClass *what)
269{
270 // Remove an address from the repository of address/object.
271
273 RepoCont_t::iterator cur = gObjectVersionRepository.find(location);
274 for (; cur != gObjectVersionRepository.end();) {
275 RepoCont_t::iterator tmp = cur++;
276 if ((tmp->first == location) && (tmp->second.fVersion == what->GetClassVersion())) {
277 // -- We still have an address, version match.
278 // Info(where, "Unregistering address %p of class '%s' version %d", location, what->GetName(), what->GetClassVersion());
279 gObjectVersionRepository.erase(tmp);
280 } else {
281 // -- No address, version match, we've reached the end.
282 break;
283 }
284 }
285}
286
287static void MoveAddressInRepository(const char * /*where*/, void *oldadd, void *newadd, const TClass *what)
288{
289 // Register in the repository that an object has moved.
290
291 // Move not only the object itself but also any base classes or sub-objects.
292 size_t objsize = what->Size();
293 long delta = (char*)newadd - (char*)oldadd;
295 RepoCont_t::iterator cur = gObjectVersionRepository.find(oldadd);
296 for (; cur != gObjectVersionRepository.end();) {
297 RepoCont_t::iterator tmp = cur++;
298 if (oldadd <= tmp->first && tmp->first < ( ((char*)oldadd) + objsize) ) {
299 // The location is within the object, let's move it.
300
301 gObjectVersionRepository.insert(RepoCont_t::value_type(((char*)tmp->first)+delta, RepoCont_t::mapped_type(tmp->second.fClass,tmp->second.fVersion)));
302 gObjectVersionRepository.erase(tmp);
303
304 } else {
305 // -- No address, version match, we've reached the end.
306 break;
307 }
308 }
309}
310
311//______________________________________________________________________________
312//______________________________________________________________________________
313namespace ROOT {
314#define R__USE_STD_MAP
315 class TMapTypeToTClass {
316#if defined R__USE_STD_MAP
317 // This wrapper class allow to avoid putting #include <map> in the
318 // TROOT.h header file.
319 public:
320 typedef std::map<std::string,TClass*> IdMap_t;
321 typedef IdMap_t::key_type key_type;
322 typedef IdMap_t::const_iterator const_iterator;
323 typedef IdMap_t::size_type size_type;
324#ifdef R__WIN32
325 // Window's std::map does NOT defined mapped_type
326 typedef TClass* mapped_type;
327#else
328 typedef IdMap_t::mapped_type mapped_type;
329#endif
330
331 private:
332 IdMap_t fMap;
333
334 public:
335 void Add(const key_type &key, mapped_type &obj)
336 {
337 // Add the <key,obj> pair to the map.
338 fMap[key] = obj;
339 }
340 mapped_type Find(const key_type &key) const
341 {
342 // Find the type corresponding to the key.
343 IdMap_t::const_iterator iter = fMap.find(key);
344 mapped_type cl = 0;
345 if (iter != fMap.end()) cl = iter->second;
346 return cl;
347 }
348 void Remove(const key_type &key) {
349 // Remove the type corresponding to the key.
350 fMap.erase(key);
351 }
352#else
353 private:
354 TMap fMap;
355
356 public:
357#ifdef R__COMPLETE_MEM_TERMINATION
358 TMapTypeToTClass() {
359 TIter next(&fMap);
360 TObjString *key;
361 while((key = (TObjString*)next())) {
362 delete key;
363 }
364 }
365#endif
366 void Add(const char *key, TClass *&obj) {
367 TObjString *realkey = new TObjString(key);
368 fMap.Add(realkey, obj);
369 }
370 TClass* Find(const char *key) const {
371 const TPair *a = (const TPair *)fMap.FindObject(key);
372 if (a) return (TClass*) a->Value();
373 return 0;
374 }
375 void Remove(const char *key) {
376 TObjString realkey(key);
377 TObject *actual = fMap.Remove(&realkey);
378 delete actual;
379 }
380#endif
381 };
382
383 class TMapDeclIdToTClass {
384 // Wrapper class for the multimap of DeclId_t and TClass.
385 public:
386 typedef multimap<TDictionary::DeclId_t, TClass*> DeclIdMap_t;
387 typedef DeclIdMap_t::key_type key_type;
388 typedef DeclIdMap_t::mapped_type mapped_type;
389 typedef DeclIdMap_t::const_iterator const_iterator;
390 typedef std::pair <const_iterator, const_iterator> equal_range;
391 typedef DeclIdMap_t::size_type size_type;
392
393 private:
394 DeclIdMap_t fMap;
395
396 public:
397 void Add(const key_type &key, mapped_type obj)
398 {
399 // Add the <key,obj> pair to the map.
400 std::pair<const key_type, mapped_type> pair = make_pair(key, obj);
401 fMap.insert(pair);
402 }
403 size_type CountElementsWithKey(const key_type &key)
404 {
405 return fMap.count(key);
406 }
407 equal_range Find(const key_type &key) const
408 {
409 // Find the type corresponding to the key.
410 return fMap.equal_range(key);
411 }
412 void Remove(const key_type &key) {
413 // Remove the type corresponding to the key.
414 fMap.erase(key);
415 }
416 };
417}
418
420
421#ifdef R__COMPLETE_MEM_TERMINATION
422 static IdMap_t gIdMapObject;
423 return &gIdMapObject;
424#else
425 static IdMap_t *gIdMap = new IdMap_t;
426 return gIdMap;
427#endif
428}
429
431
432#ifdef R__COMPLETE_MEM_TERMINATION
433 static DeclIdMap_t gDeclIdMapObject;
434 return &gDeclIdMapObject;
435#else
436 static DeclIdMap_t *gDeclIdMap = new DeclIdMap_t;
437 return gDeclIdMap;
438#endif
439}
440
441////////////////////////////////////////////////////////////////////////////////
442/// static: Add a class to the list and map of classes.
443
445{
446 if (!cl) return;
447
449 gROOT->GetListOfClasses()->Add(cl);
450 if (cl->GetTypeInfo()) {
451 GetIdMap()->Add(cl->GetTypeInfo()->name(),cl);
452 }
453 if (cl->fClassInfo) {
454 GetDeclIdMap()->Add((void*)(cl->fClassInfo), cl);
455 }
456}
457
458////////////////////////////////////////////////////////////////////////////////
459/// static: Add a TClass* to the map of classes.
460
462{
463 if (!cl || !id) return;
464 GetDeclIdMap()->Add(id, cl);
465}
466
467////////////////////////////////////////////////////////////////////////////////
468/// static: Remove a class from the list and map of classes
469
471{
472 if (!oldcl) return;
473
475 gROOT->GetListOfClasses()->Remove(oldcl);
476 if (oldcl->GetTypeInfo()) {
477 GetIdMap()->Remove(oldcl->GetTypeInfo()->name());
478 }
479 if (oldcl->fClassInfo) {
480 //GetDeclIdMap()->Remove((void*)(oldcl->fClassInfo));
481 }
482}
483
484////////////////////////////////////////////////////////////////////////////////
485
487{
488 if (!id) return;
489 GetDeclIdMap()->Remove(id);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Indirect call to the implementation of ShowMember allowing [forward]
494/// declaration with out a full definition of the TClass class.
495
496void ROOT::Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector&insp)
497{
498 gInterpreter->InspectMembers(insp, obj, cl, kFALSE);
499}
500
501//______________________________________________________________________________
502//______________________________________________________________________________
503
504class TDumpMembers : public TMemberInspector {
505 bool fNoAddr;
506public:
507 TDumpMembers(bool noAddr): fNoAddr(noAddr) { }
508
510 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
511};
512
513////////////////////////////////////////////////////////////////////////////////
514/// Print value of member mname.
515///
516/// This method is called by the ShowMembers() method for each
517/// data member when object.Dump() is invoked.
518///
519/// - cl is the pointer to the current class
520/// - pname is the parent name (in case of composed objects)
521/// - mname is the data member name
522/// - add is the data member address
523
524void TDumpMembers::Inspect(TClass *cl, const char *pname, const char *mname, const void *add, Bool_t /* isTransient */)
525{
526 const Int_t kvalue = 30;
527#ifdef R__B64
528 const Int_t ktitle = 50;
529#else
530 const Int_t ktitle = 42;
531#endif
532 const Int_t kline = 1024;
533 Int_t cdate = 0;
534 Int_t ctime = 0;
535 UInt_t *cdatime = 0;
536 char line[kline];
537
538 TDataType *membertype;
539 EDataType memberDataType = kNoType_t;
540 const char *memberName;
541 const char *memberFullTypeName;
542 const char *memberTitle;
543 Bool_t isapointer;
544 Bool_t isbasic;
545
546 if (TDataMember *member = cl->GetDataMember(mname)) {
547 if (member->GetDataType()) {
548 memberDataType = (EDataType)member->GetDataType()->GetType();
549 }
550 memberName = member->GetName();
551 memberFullTypeName = member->GetFullTypeName();
552 memberTitle = member->GetTitle();
553 isapointer = member->IsaPointer();
554 isbasic = member->IsBasic();
555 membertype = member->GetDataType();
556 } else if (!cl->IsLoaded()) {
557 // The class is not loaded, hence it is 'emulated' and the main source of
558 // information is the StreamerInfo.
560 if (!info) return;
561 const char *cursor = mname;
562 while ( (*cursor)=='*' ) ++cursor;
563 TString elname( cursor );
564 Ssiz_t pos = elname.Index("[");
565 if ( pos != kNPOS ) {
566 elname.Remove( pos );
567 }
568 TStreamerElement *element = (TStreamerElement*)info->GetElements()->FindObject(elname.Data());
569 if (!element) return;
570 memberFullTypeName = element->GetTypeName();
571
572 memberDataType = (EDataType)element->GetType();
573
574 memberName = element->GetName();
575 memberTitle = element->GetTitle();
576 isapointer = element->IsaPointer() || element->GetType() == TVirtualStreamerInfo::kCharStar;
577 membertype = gROOT->GetType(memberFullTypeName);
578
579 isbasic = membertype !=0;
580 } else {
581 return;
582 }
583
584
585 Bool_t isdate = kFALSE;
586 if (strcmp(memberName,"fDatime") == 0 && memberDataType == kUInt_t) {
587 isdate = kTRUE;
588 }
589 Bool_t isbits = kFALSE;
590 if (strcmp(memberName,"fBits") == 0 && memberDataType == kUInt_t) {
591 isbits = kTRUE;
592 }
593 TClass * dataClass = TClass::GetClass(memberFullTypeName);
594 Bool_t isTString = (dataClass == TString::Class());
595 static TClassRef stdClass("std::string");
596 Bool_t isStdString = (dataClass == stdClass);
597
598 Int_t i;
599 for (i = 0;i < kline; i++) line[i] = ' ';
600 line[kline-1] = 0;
601 snprintf(line,kline,"%s%s ",pname,mname);
602 i = strlen(line); line[i] = ' ';
603
604 // Encode data value or pointer value
605 char *pointer = (char*)add;
606 char **ppointer = (char**)(pointer);
607
608 if (isapointer) {
609 char **p3pointer = (char**)(*ppointer);
610 if (!p3pointer)
611 snprintf(&line[kvalue],kline-kvalue,"->0");
612 else if (!isbasic) {
613 if (!fNoAddr) {
614 snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
615 }
616 } else if (membertype) {
617 if (!strcmp(membertype->GetTypeName(), "char")) {
618 i = strlen(*ppointer);
619 if (kvalue+i > kline) i=kline-1-kvalue;
620 Bool_t isPrintable = kTRUE;
621 for (Int_t j = 0; j < i; j++) {
622 if (!std::isprint((*ppointer)[j])) {
623 isPrintable = kFALSE;
624 break;
625 }
626 }
627 if (isPrintable) {
628 strncpy(line + kvalue, *ppointer, i);
629 line[kvalue+i] = 0;
630 } else {
631 line[kvalue] = 0;
632 }
633 } else {
634 strncpy(&line[kvalue], membertype->AsString(p3pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(p3pointer))));
635 }
636 } else if (!strcmp(memberFullTypeName, "char*") ||
637 !strcmp(memberFullTypeName, "const char*")) {
638 i = strlen(*ppointer);
639 if (kvalue+i >= kline) i=kline-1-kvalue;
640 Bool_t isPrintable = kTRUE;
641 for (Int_t j = 0; j < i; j++) {
642 if (!std::isprint((*ppointer)[j])) {
643 isPrintable = kFALSE;
644 break;
645 }
646 }
647 if (isPrintable) {
648 strncpy(line + kvalue, *ppointer, std::min( i, kline - kvalue));
649 line[kvalue+i] = 0;
650 } else {
651 line[kvalue] = 0;
652 }
653 } else {
654 if (!fNoAddr) {
655 snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
656 }
657 }
658 } else if (membertype) {
659 if (isdate) {
660 cdatime = (UInt_t*)pointer;
661 TDatime::GetDateTime(cdatime[0],cdate,ctime);
662 snprintf(&line[kvalue],kline-kvalue,"%d/%d",cdate,ctime);
663 } else if (isbits) {
664 snprintf(&line[kvalue],kline-kvalue,"0x%08x", *(UInt_t*)pointer);
665 } else {
666 strncpy(&line[kvalue], membertype->AsString(pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(pointer))));
667 }
668 } else {
669 if (isStdString) {
670 std::string *str = (std::string*)pointer;
671 snprintf(&line[kvalue],kline-kvalue,"%s",str->c_str());
672 } else if (isTString) {
673 TString *str = (TString*)pointer;
674 snprintf(&line[kvalue],kline-kvalue,"%s",str->Data());
675 } else {
676 if (!fNoAddr) {
677 snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)pointer);
678 }
679 }
680 }
681 // Encode data member title
682 if (isdate == kFALSE && strcmp(memberFullTypeName, "char*") && strcmp(memberFullTypeName, "const char*")) {
683 i = strlen(&line[0]); line[i] = ' ';
684 assert(250 > ktitle);
685 strlcpy(&line[ktitle],memberTitle,250-ktitle+1); // strlcpy copy 'size-1' characters.
686 }
687 Printf("%s", line);
688}
689
691
692//______________________________________________________________________________
693//______________________________________________________________________________
694////////////////////////////////////////////////////////////////////////////////
695
696TClass::TNameMapNode::TNameMapNode (const char* typedf, const char* orig)
697 : TObjString (typedf),
698 fOrigName (orig)
699{
700}
701
702//______________________________________________________________________________
703
704class TBuildRealData : public TMemberInspector {
705
706private:
707 void *fRealDataObject;
708 TClass *fRealDataClass;
709
710public:
711 TBuildRealData(void *obj, TClass *cl) {
712 // Main constructor.
713 fRealDataObject = obj;
714 fRealDataClass = cl;
715 }
717 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
718
719};
720
721////////////////////////////////////////////////////////////////////////////////
722/// This method is called from ShowMembers() via BuildRealdata().
723
724void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add, Bool_t isTransient)
725{
726 TDataMember* dm = cl->GetDataMember(mname);
727 if (!dm) {
728 return;
729 }
730
731 Bool_t isTransientMember = kFALSE;
732
733 if (!dm->IsPersistent()) {
734 // For the DataModelEvolution we need access to the transient member.
735 // so we now record them in the list of RealData.
736 isTransientMember = kTRUE;
737 isTransient = kTRUE;
738 }
739
740 TString rname( pname );
741 // Take into account cases like TPaveStats->TPaveText->TPave->TBox.
742 // Check that member is in a derived class or an object in the class.
743 if (cl != fRealDataClass) {
744 if (!fRealDataClass->InheritsFrom(cl)) {
745 Ssiz_t dot = rname.Index('.');
746 if (dot == kNPOS) {
747 return;
748 }
749 rname[dot] = '\0';
750 if (!fRealDataClass->GetDataMember(rname)) {
751 //could be a data member in a base class like in this example
752 // class Event : public Data {
753 // class Data : public TObject {
754 // EventHeader fEvtHdr;
755 // class EventHeader {
756 // Int_t fEvtNum;
757 // Int_t fRun;
758 // Int_t fDate;
759 // EventVertex fVertex;
760 // class EventVertex {
761 // EventTime fTime;
762 // class EventTime {
763 // Int_t fSec;
764 // Int_t fNanoSec;
765 if (!fRealDataClass->GetBaseDataMember(rname)) {
766 return;
767 }
768 }
769 rname[dot] = '.';
770 }
771 }
772
773 Long_t offset = Long_t(((Long_t) add) - ((Long_t) fRealDataObject));
774
775 if (TClassEdit::IsStdArray(dm->GetTypeName())){ // We tackle the std array case
776 TString rdName;
777 TRealData::GetName(rdName,dm);
778 rname += rdName;
779 TRealData* rd = new TRealData(rname.Data(), offset, dm);
780 fRealDataClass->GetListOfRealData()->Add(rd);
781 return;
782 }
783
784 rname += mname;
785
786 if (dm->IsaPointer()) {
787 // Data member is a pointer.
788 TRealData* rd = new TRealData(rname, offset, dm);
789 if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
790 fRealDataClass->GetListOfRealData()->Add(rd);
791 } else {
792 // Data Member is a basic data type.
793 TRealData* rd = new TRealData(rname, offset, dm);
794 if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
795 if (!dm->IsBasic()) {
796 rd->SetIsObject(kTRUE);
797
798 // Make sure that BuildReadData is called for any abstract
799 // bases classes involved in this object, i.e for all the
800 // classes composing this object (base classes, type of
801 // embedded object and same for their data members).
802 //
803 TClass* dmclass = TClass::GetClass(dm->GetTypeName(), kTRUE, isTransient);
804 if (!dmclass) {
805 dmclass = TClass::GetClass(dm->GetTrueTypeName(), kTRUE, isTransient);
806 }
807 if (dmclass) {
808 if ((dmclass != cl) && !dm->IsaPointer()) {
809 if (dmclass->GetCollectionProxy()) {
810 TClass* valcl = dmclass->GetCollectionProxy()->GetValueClass();
811 // We create the real data for the content of the collection to help the case
812 // of split branches in a TTree (where the node for the data member itself
813 // might have been elided). However, in some cases, like transient members
814 // and/or classes, the content might not be create-able. An example is the
815 // case of a map<A,B> where either A or B does not have default constructor
816 // and thus the compilation of the default constructor for pair<A,B> will
817 // fail (noisily) [This could also apply to any template instance, where it
818 // might have a default constructor definition that can not be compiled due
819 // to the template parameter]
820 if (valcl) {
821 Bool_t wantBuild = kTRUE;
822 if (valcl->Property() & kIsAbstract) wantBuild = kFALSE;
823 if ( (isTransient)
825 && (!valcl->IsLoaded()) ) {
826 // Case where the collection dictionary was not requested and
827 // the content's dictionary was also not requested.
828 // [This is a super set of what we need, but we can't really detect it :(]
829 wantBuild = kFALSE;
830 }
831
832 if (wantBuild) valcl->BuildRealData(0, isTransient);
833 }
834 } else {
835 void* addrForRecursion = 0;
836 if (GetObjectValidity() == kValidObjectGiven)
837 addrForRecursion = const_cast<void*>(add);
838
839 dmclass->BuildRealData(addrForRecursion, isTransient);
840 }
841 }
842 }
843 }
844 fRealDataClass->GetListOfRealData()->Add(rd);
845 }
846}
847
848//______________________________________________________________________________
849//______________________________________________________________________________
850//______________________________________________________________________________
851
852////////////////////////////////////////////////////////////////////////////////
853
854class TAutoInspector : public TMemberInspector {
855public:
856 Int_t fCount;
857 TBrowser *fBrowser;
858
859 TAutoInspector(TBrowser *b) {
860 // main constructor.
861 fBrowser = b; fCount = 0; }
862 virtual ~TAutoInspector() { }
864 virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
865 virtual Bool_t IsTreatingNonAccessibleTypes() {return kFALSE;}
866};
867
868////////////////////////////////////////////////////////////////////////////////
869/// This method is called from ShowMembers() via AutoBrowse().
870
871void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
872 const void *addr, Bool_t /* isTransient */)
873{
874 if(tit && strchr(tit,'.')) return ;
875 if (fCount && !fBrowser) return;
876
877 TString ts;
878
879 if (!cl) return;
880 //if (*(cl->GetName()) == 'T') return;
881 if (*name == '*') name++;
882 int ln = strcspn(name,"[ ");
883 TString iname(name,ln);
884
885 ClassInfo_t *classInfo = cl->GetClassInfo();
886 if (!classInfo) return;
887
888 // Browse data members
889 DataMemberInfo_t *m = gCling->DataMemberInfo_Factory(classInfo);
890 TString mname;
891
892 int found=0;
893 while (gCling->DataMemberInfo_Next(m)) { // MemberLoop
894 mname = gCling->DataMemberInfo_Name(m);
895 mname.ReplaceAll("*","");
896 if ((found = (iname==mname))) break;
897 }
898 assert(found);
899
900 // we skip: non static members and non objects
901 // - the member G__virtualinfo inserted by the CINT RTTI system
902
903 //Long_t prop = m.Property() | m.Type()->Property();
905 if (prop & kIsStatic) return;
906 if (prop & kIsFundamental) return;
907 if (prop & kIsEnum) return;
908 if (mname == "G__virtualinfo") return;
909
910 int size = sizeof(void*);
911
912 int nmax = 1;
913 if (prop & kIsArray) {
914 for (int dim = 0; dim < gCling->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCling->DataMemberInfo_MaxIndex(m,dim);
915 }
916
919 TClass * clm = TClass::GetClass(clmName.c_str());
920 R__ASSERT(clm);
921 if (!(prop & kIsPointer)) {
922 size = clm->Size();
923 if (size==0) size = gCling->DataMemberInfo_TypeSize(m);
924 }
925
926
929
930 for(int i=0; i<nmax; i++) {
931
932 char *ptr = (char*)addr + i*size;
933
934 void *obj = (prop & kIsPointer) ? *((void**)ptr) : (TObject*)ptr;
935
936 if (!obj) continue;
937
938 fCount++;
939 if (!fBrowser) return;
940
941 TString bwname;
942 TClass *actualClass = clm->GetActualClass(obj);
943 if (clm->IsTObject()) {
944 TObject *tobj = (TObject*)clm->DynamicCast(TObject::Class(),obj);
945 bwname = tobj->GetName();
946 } else {
947 bwname = actualClass->GetName();
948 bwname += "::";
949 bwname += mname;
950 }
951
952 if (!clm->IsTObject() ||
953 bwname.Length()==0 ||
954 strcmp(bwname.Data(),actualClass->GetName())==0) {
955 bwname = name;
956 int l = strcspn(bwname.Data(),"[ ");
957 if (l<bwname.Length() && bwname[l]=='[') {
958 char cbuf[13]; snprintf(cbuf,13,"[%02d]",i);
959 ts.Replace(0,999,bwname,l);
960 ts += cbuf;
961 bwname = (const char*)ts;
962 }
963 }
964
965 if (proxy==0) {
966
967 fBrowser->Add(obj,clm,bwname);
968
969 } else {
970 TClass *valueCl = proxy->GetValueClass();
971
972 if (valueCl==0) {
973
974 fBrowser->Add( obj, clm, bwname );
975
976 } else {
977 TVirtualCollectionProxy::TPushPop env(proxy, obj);
978 TClass *actualCl = 0;
979
980 int sz = proxy->Size();
981
982 char fmt[] = {"#%09d"};
983 fmt[3] = '0'+(int)log10(double(sz))+1;
984 char buf[20];
985 for (int ii=0;ii<sz;ii++) {
986 void *p = proxy->At(ii);
987
988 if (proxy->HasPointers()) {
989 p = *((void**)p);
990 if(!p) continue;
991 actualCl = valueCl->GetActualClass(p);
992 p = actualCl->DynamicCast(valueCl,p,0);
993 }
994 fCount++;
995 snprintf(buf,20,fmt,ii);
996 ts = bwname;
997 ts += buf;
998 fBrowser->Add( p, actualCl, ts );
999 }
1000 }
1001 }
1002 }
1003}
1004
1005//______________________________________________________________________________
1006//______________________________________________________________________________
1007//______________________________________________________________________________
1008
1010
1011////////////////////////////////////////////////////////////////////////////////
1012
1014 TDictionary(),
1015 fPersistentRef(0),
1017 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1020 fInstanceCount(0), fOnHeap(0),
1022 fTypeInfo(0), fShowMembers(0),
1023 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1028 fState(kNoInfo),
1031
1032{
1033 // Default ctor.
1034
1036 {
1037 TMmallocDescTemp setreset;
1038 fStreamerInfo = new TObjArray(1, -2);
1039 }
1040 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1041}
1042
1043////////////////////////////////////////////////////////////////////////////////
1044/// Create a TClass object. This object contains the full dictionary
1045/// of a class. It has list to baseclasses, datamembers and methods.
1046/// Use this ctor to create a standalone TClass object. Most useful
1047/// to get a TClass interface to an interpreted class. Used by TTabCom.
1048/// Normally you would use TClass::GetClass("class") to get access to a
1049/// TClass object for a certain class.
1050
1051TClass::TClass(const char *name, Bool_t silent) :
1053 fPersistentRef(0),
1054 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1055 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1056 fAllPubMethod(0), fClassMenuList(0),
1057 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1058 fInstanceCount(0), fOnHeap(0),
1059 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1060 fTypeInfo(0), fShowMembers(0),
1061 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1062 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1063 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1064 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1065 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1066 fState(kNoInfo),
1067 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1068 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1069{
1071
1072 if (!gROOT)
1073 ::Fatal("TClass::TClass", "ROOT system not initialized");
1074
1075 {
1076 TMmallocDescTemp setreset;
1077 fStreamerInfo = new TObjArray(1, -2);
1078 }
1079 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1080
1082 if (!gInterpreter)
1083 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1084
1085 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1086 if (!silent && !fClassInfo && fName.First('@')==kNPOS)
1087 ::Warning("TClass::TClass", "no dictionary for class %s is available", name);
1089
1092}
1093
1094////////////////////////////////////////////////////////////////////////////////
1095/// Create a TClass object. This object contains the full dictionary
1096/// of a class. It has list to baseclasses, datamembers and methods.
1097
1098TClass::TClass(const char *name, Version_t cversion, Bool_t silent) :
1100 fPersistentRef(0),
1101 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1102 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1103 fAllPubMethod(0), fClassMenuList(0),
1104 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1105 fInstanceCount(0), fOnHeap(0),
1106 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1107 fTypeInfo(0), fShowMembers(0),
1108 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1109 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1110 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1111 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1112 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1113 fState(kNoInfo),
1114 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1115 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1116{
1118 Init(name, cversion, 0, 0, 0, 0, -1, -1, 0, silent);
1119}
1120
1121////////////////////////////////////////////////////////////////////////////////
1122/// Create a TClass object. This object does not contain anything. We mimic
1123/// the case of a class fwd declared in the interpreter.
1124
1125TClass::TClass(const char *name, Version_t cversion, EState theState, Bool_t silent) :
1127 fPersistentRef(0),
1128 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1129 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1130 fAllPubMethod(0), fClassMenuList(0),
1131 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1132 fInstanceCount(0), fOnHeap(0),
1133 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1134 fTypeInfo(0), fShowMembers(0),
1135 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1136 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1137 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1138 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1139 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1140 fState(theState),
1141 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1142 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1143{
1145
1146 // Treat the case in which a TClass instance is created for a namespace
1147 if (theState == kNamespaceForMeta){
1149 theState = kForwardDeclared; // it immediately decays in kForwardDeclared
1150 }
1151
1152 if (theState != kForwardDeclared && theState != kEmulated)
1153 ::Fatal("TClass::TClass",
1154 "A TClass entry cannot be initialized in a state different from kForwardDeclared or kEmulated.");
1155 Init(name, cversion, 0, 0, 0, 0, -1, -1, 0, silent);
1156}
1157
1158////////////////////////////////////////////////////////////////////////////////
1159/// Create a TClass object. This object contains the full dictionary
1160/// of a class. It has list to baseclasses, datamembers and methods.
1161/// Use this ctor to create a standalone TClass object. Most useful
1162/// to get a TClass interface to an interpreted class. Used by TTabCom.
1163/// Normally you would use TClass::GetClass("class") to get access to a
1164/// TClass object for a certain class.
1165///
1166/// This copies the ClassInfo (i.e. does *not* take ownership of it).
1167
1168TClass::TClass(ClassInfo_t *classInfo, Version_t cversion,
1169 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1170 TDictionary(""),
1171 fPersistentRef(0),
1172 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1173 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1174 fAllPubMethod(0), fClassMenuList(0),
1175 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1176 fInstanceCount(0), fOnHeap(0),
1177 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1178 fTypeInfo(0), fShowMembers(0),
1179 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1180 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1181 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1182 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1183 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1184 fState(kNoInfo),
1185 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1186 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1187{
1189
1190 if (!gROOT)
1191 ::Fatal("TClass::TClass", "ROOT system not initialized");
1192
1193 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1194
1196 if (!gInterpreter)
1197 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1198
1199 if (!classInfo || !gInterpreter->ClassInfo_IsValid(classInfo)) {
1200 MakeZombie();
1201 fState = kNoInfo;
1202 } else {
1203 fName = gInterpreter->ClassInfo_FullName(classInfo);
1204
1206 Init(fName, cversion, 0, 0, dfil, ifil, dl, il, classInfo, silent);
1207 }
1209
1211}
1212
1213
1214////////////////////////////////////////////////////////////////////////////////
1215/// Create a TClass object. This object contains the full dictionary
1216/// of a class. It has list to baseclasses, datamembers and methods.
1217
1218TClass::TClass(const char *name, Version_t cversion,
1219 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1221 fPersistentRef(0),
1222 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1223 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1224 fAllPubMethod(0), fClassMenuList(0),
1225 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1226 fInstanceCount(0), fOnHeap(0),
1227 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1228 fTypeInfo(0), fShowMembers(0),
1229 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1230 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1231 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1232 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1233 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1234 fState(kNoInfo),
1235 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1236 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1237{
1239 Init(name,cversion, 0, 0, dfil, ifil, dl, il, 0, silent);
1240}
1241
1242////////////////////////////////////////////////////////////////////////////////
1243/// Create a TClass object. This object contains the full dictionary
1244/// of a class. It has list to baseclasses, datamembers and methods.
1245
1246TClass::TClass(const char *name, Version_t cversion,
1247 const std::type_info &info, TVirtualIsAProxy *isa,
1248 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1249 Bool_t silent) :
1251 fPersistentRef(0),
1252 fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
1253 fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1254 fAllPubMethod(0),
1255 fClassMenuList(0),
1256 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1257 fInstanceCount(0), fOnHeap(0),
1258 fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
1259 fTypeInfo(0), fShowMembers(0),
1260 fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
1261 fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
1262 fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
1263 fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1264 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1265 fState(kHasTClassInit),
1266 fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
1267 fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
1268{
1270 // use info
1271 Init(name, cversion, &info, isa, dfil, ifil, dl, il, 0, silent);
1272}
1273
1274////////////////////////////////////////////////////////////////////////////////
1275/// we found at least one equivalent.
1276/// let's force a reload
1277
1279{
1280 TClass::RemoveClass(oldcl);
1281
1282 if (oldcl->CanIgnoreTObjectStreamer()) {
1284 }
1285
1287 TIter next(oldcl->GetStreamerInfos());
1288 while ((info = (TVirtualStreamerInfo*)next())) {
1289 info->Clear("build");
1290 info->SetClass(this);
1292 }
1293 oldcl->fStreamerInfo->Clear();
1294
1295 oldcl->ReplaceWith(this);
1296 delete oldcl;
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Initialize a TClass object. This object contains the full dictionary
1301/// of a class. It has list to baseclasses, datamembers and methods.
1302
1303void TClass::Init(const char *name, Version_t cversion,
1304 const std::type_info *typeinfo, TVirtualIsAProxy *isa,
1305 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1306 ClassInfo_t *givenInfo,
1307 Bool_t silent)
1308{
1309 if (!gROOT)
1310 ::Fatal("TClass::TClass", "ROOT system not initialized");
1311 if (!name || !name[0]) {
1312 ::Error("TClass::Init", "The name parameter is invalid (null or empty)");
1313 MakeZombie();
1314 return;
1315 }
1316 // Always strip the default STL template arguments (from any template argument or the class name)
1318 fClassVersion = cversion;
1319 fDeclFileName = dfil ? dfil : "";
1320 fImplFileName = ifil ? ifil : "";
1321 fDeclFileLine = dl;
1322 fImplFileLine = il;
1323 fTypeInfo = typeinfo;
1324 fIsA = isa;
1325 if ( fIsA ) fIsA->SetClass(this);
1326 // See also TCling::GenerateTClass() which will update fClassVersion after creation!
1327 fStreamerInfo = new TObjArray(fClassVersion+2+10,-1); // +10 to read new data by old
1328 fProperty = -1;
1329 fClassProperty = 0;
1330
1332
1333 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
1334
1336
1337 if (oldcl && oldcl->TestBit(kLoading)) {
1338 // Do not recreate a class while it is already being created!
1339
1340 // We can no longer reproduce this case, to check whether we are, we use
1341 // this code:
1342 // Fatal("Init","A bad replacement for %s was requested\n",name);
1343 return;
1344 }
1345
1346 TClass **persistentRef = 0;
1347 if (oldcl) {
1348
1349 persistentRef = oldcl->fPersistentRef.exchange(0);
1350
1351 // The code from here is also in ForceReload.
1352 TClass::RemoveClass(oldcl);
1353 // move the StreamerInfo immediately so that there are
1354 // properly updated!
1355
1356 if (oldcl->CanIgnoreTObjectStreamer()) {
1358 }
1360
1361 TIter next(oldcl->GetStreamerInfos());
1362 while ((info = (TVirtualStreamerInfo*)next())) {
1363 // We need to force a call to BuildOld
1364 info->Clear("build");
1365 info->SetClass(this);
1367 }
1368 oldcl->fStreamerInfo->Clear();
1369 // The code diverges here from ForceReload.
1370
1371 // Move the Schema Rules too.
1372 fSchemaRules = oldcl->fSchemaRules;
1373 oldcl->fSchemaRules = 0;
1374 }
1375
1377 // Advertise ourself as the loading class for this class name
1378 TClass::AddClass(this);
1379
1381
1382 if (!gInterpreter)
1383 ::Fatal("TClass::Init", "gInterpreter not initialized");
1384
1385 if (givenInfo) {
1386 bool invalid = !gInterpreter->ClassInfo_IsValid(givenInfo);
1387 bool notloaded = !gInterpreter->ClassInfo_IsLoaded(givenInfo);
1388 auto property = gInterpreter->ClassInfo_Property(givenInfo);
1389
1390 if (invalid || (notloaded && (property & kIsNamespace)) ||
1391 !(property & (kIsClass | kIsStruct | kIsNamespace))) {
1392 if (!TClassEdit::IsSTLCont(fName.Data())) {
1393 MakeZombie();
1394 fState = kNoInfo;
1395 TClass::RemoveClass(this);
1396 return;
1397 }
1398 }
1399
1400 fClassInfo = gInterpreter->ClassInfo_Factory(givenInfo);
1401 fCanLoadClassInfo = false; // avoids calls to LoadClassInfo() if info is already loaded
1402 }
1403
1404 // We need to check if the class it is not fwd declared for the cases where we
1405 // created a TClass directly in the kForwardDeclared state. Indeed in those cases
1406 // fClassInfo will always be nullptr.
1408
1409 if (fState == kHasTClassInit) {
1410 // If the TClass is being generated from a ROOT dictionary,
1411 // even though we do not seem to have a CINT dictionary for
1412 // the class, we will will try to load it anyway UNLESS
1413 // the class is an STL container (or string).
1414 // This is because we do not expect the CINT dictionary
1415 // to be present for all STL classes (and we can handle
1416 // the lack of CINT dictionary in that cases).
1417 // However, the cling the dictionary no longer carries
1418 // an instantiation with it, unless we request the loading
1419 // here *or* the user explicitly instantiate the template
1420 // we would not have a ClassInfo for the template
1421 // instantiation.
1423 // Here we check and grab the info from the rootpcm.
1425 if (proto && proto->FillTClass(this)) {
1427 }
1428 }
1429 if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE)) {
1430 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1431 if (fClassInfo) {
1432 // This should be moved out of GetCheckSum itself however the last time
1433 // we tried this cause problem, in particular in the end-of-process operation.
1434 // fCheckSum = GetCheckSum(kLatestCheckSum);
1435 } else {
1436 if (!fClassInfo) {
1437 if (IsZombie()) {
1438 TClass::RemoveClass(this);
1439 return;
1440 }
1441 }
1442 }
1443 }
1444 }
1445 if (!silent && (!fClassInfo && !fCanLoadClassInfo) && !isStl && fName.First('@')==kNPOS &&
1447 if (fState == kHasTClassInit) {
1448 if (fImplFileLine == -1 && fClassVersion == 0) {
1449 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
1450 // information. Since it is transient, it is more than likely that the lack
1451 // will be harmles.
1452 } else {
1453 ::Error("TClass::Init", "no interpreter information for class %s is available even though it has a TClass "
1454 "initialization routine.",
1455 fName.Data());
1456 }
1457 } else {
1458 // In this case we initialised this TClass instance starting from the fwd declared state
1459 // and we know we have no dictionary: no need to warn
1460 ::Warning("TClass::Init", "no dictionary for class %s is available", fName.Data());
1461 }
1462 }
1463
1464 fgClassCount++;
1466
1467 // Make the typedef-expanded -> original hash table entries.
1468 // There may be several entries for any given key.
1469 // We only make entries if the typedef-expanded name
1470 // is different from the original name.
1471 TString resolvedThis;
1472 if (!givenInfo && strchr (name, '<')) {
1473 if ( fName != name) {
1474 if (!fgClassTypedefHash) {
1475 fgClassTypedefHash = new THashTable (100, 5);
1477 }
1478
1481
1482 }
1483 resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
1484 if (resolvedThis != name) {
1485 if (!fgClassTypedefHash) {
1486 fgClassTypedefHash = new THashTable (100, 5);
1488 }
1489
1490 fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
1492 }
1493
1494 }
1495
1496 //In case a class with the same name had been created by TVirtualStreamerInfo
1497 //we must delete the old class, importing only the StreamerInfo structure
1498 //from the old dummy class.
1499 if (oldcl) {
1500
1501 oldcl->ReplaceWith(this);
1502 delete oldcl;
1503
1504 } else if (!givenInfo && resolvedThis.Length() > 0 && fgClassTypedefHash) {
1505
1506 // Check for existing equivalent.
1507
1508 if (resolvedThis != fName) {
1509 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
1510 if (oldcl && oldcl != this) {
1511 persistentRef = oldcl->fPersistentRef.exchange(0);
1512 ForceReload (oldcl);
1513 }
1514 }
1515 TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
1516 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1517 if (resolvedThis != htmp->String()) continue;
1518 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName); // gROOT->GetClass (htmp->fOrigName, kFALSE);
1519 if (oldcl && oldcl != this) {
1520 persistentRef = oldcl->fPersistentRef.exchange(0);
1521 ForceReload (oldcl);
1522 }
1523 }
1524 }
1525 if (fClassInfo) {
1527 if ( fDeclFileName == 0 || fDeclFileName[0] == '\0' ) {
1528 fDeclFileName = gInterpreter->ClassInfo_FileName( fClassInfo );
1529 // Missing interface:
1530 // fDeclFileLine = gInterpreter->ClassInfo_FileLine( fClassInfo );
1531
1532 // But really do not want to set ImplFileLine as it is currently the
1533 // marker of being 'loaded' or not (reminder loaded == has a TClass bootstrap).
1534 }
1535 }
1536
1537 if (persistentRef) {
1538 fPersistentRef = persistentRef;
1539 } else {
1540 fPersistentRef = new TClass*;
1541 }
1542 *fPersistentRef = this;
1543
1544 if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
1545 if (fState != kHasTClassInit) {
1546 // If we have a TClass compiled initialization, we can safely assume that
1547 // there will also be a collection proxy.
1549 if (fCollectionProxy) {
1551
1552 // Numeric Collections have implicit conversions:
1554
1555 } else if (!silent) {
1556 Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
1557 }
1558 if (fStreamer==0) {
1560 }
1561 }
1562 } else if (!strncmp(GetName(),"std::pair<",10) || !strncmp(GetName(),"pair<",5) ) {
1563 // std::pairs have implicit conversions
1565 }
1566
1568}
1569
1570////////////////////////////////////////////////////////////////////////////////
1571/// TClass dtor. Deletes all list that might have been created.
1572
1574{
1576
1577 // Remove from the typedef hashtables.
1579 TString resolvedThis = TClassEdit::ResolveTypedef (GetName(), kTRUE);
1580 TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
1581 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1582 if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
1583 fgClassTypedefHash->Remove (htmp);
1584 delete htmp;
1585 break;
1586 }
1587 }
1588 }
1589
1590 // Not owning lists, don't call Delete()
1591 // But this still need to be done first because the TList destructor
1592 // does access the object contained (via GetObject()->TestBit(kCanDelete))
1593 delete fStreamer; fStreamer =0;
1594 delete fAllPubData; fAllPubData =0;
1595 delete fAllPubMethod; fAllPubMethod=0;
1596
1597 delete fPersistentRef.load();
1598
1599 if (fBase.load())
1600 (*fBase).Delete();
1601 delete fBase.load(); fBase = 0;
1602
1603 if (fData)
1604 fData->Delete();
1605 delete fData; fData = 0;
1606
1607 if (fEnums.load())
1608 (*fEnums).Delete();
1609 delete fEnums.load(); fEnums = 0;
1610
1611 if (fFuncTemplate)
1613 delete fFuncTemplate; fFuncTemplate = 0;
1614
1615 if (fMethod.load())
1616 (*fMethod).Delete();
1617 delete fMethod.load(); fMethod=0;
1618
1619 if (fRealData)
1620 fRealData->Delete();
1621 delete fRealData; fRealData=0;
1622
1623 if (fStreamerInfo)
1625 delete fStreamerInfo; fStreamerInfo = nullptr;
1626
1627 if (fDeclFileLine >= -1)
1628 TClass::RemoveClass(this);
1629
1631 fClassInfo=0;
1632
1633 if (fClassMenuList)
1636
1638
1639 if ( fIsA ) delete fIsA;
1640
1641 if ( fRefProxy ) fRefProxy->Release();
1642 fRefProxy = 0;
1643
1644 delete fStreamer;
1645 delete fCollectionProxy;
1646 delete fIsAMethod.load();
1647 delete fSchemaRules;
1648 if (fConversionStreamerInfo.load()) {
1649 std::map<std::string, TObjArray*>::iterator it;
1650 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
1651 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
1652 delete it->second;
1653 }
1654 delete fConversionStreamerInfo.load();
1655 }
1656}
1657
1658////////////////////////////////////////////////////////////////////////////////
1659
1660namespace {
1661 Int_t ReadRulesContent(FILE *f)
1662 {
1663 // Read a class.rules file which contains one rule per line with comment
1664 // starting with a #
1665 // Returns the number of rules loaded.
1666 // Returns -1 in case of error.
1667
1668 R__ASSERT(f!=0);
1669 TString rule(1024);
1670 int c, state = 0;
1671 Int_t count = 0;
1672
1673 while ((c = fgetc(f)) != EOF) {
1674 if (c == 13) // ignore CR
1675 continue;
1676 if (c == '\n') {
1677 if (state != 3) {
1678 state = 0;
1679 if (rule.Length() > 0) {
1680 if (TClass::AddRule(rule)) {
1681 ++count;
1682 }
1683 rule.Clear();
1684 }
1685 }
1686 continue;
1687 }
1688 switch (state) {
1689 case 0: // start of line
1690 switch (c) {
1691 case ' ':
1692 case '\t':
1693 break;
1694 case '#':
1695 state = 1;
1696 break;
1697 default:
1698 state = 2;
1699 break;
1700 }
1701 break;
1702
1703 case 1: // comment
1704 break;
1705
1706 case 2: // rule
1707 switch (c) {
1708 case '\\':
1709 state = 3; // Continuation request
1710 default:
1711 break;
1712 }
1713 break;
1714 }
1715 switch (state) {
1716 case 2:
1717 rule.Append(c);
1718 break;
1719 }
1720 }
1721 return count;
1722 }
1723}
1724
1725////////////////////////////////////////////////////////////////////////////////
1726/// Read the class.rules files from the default location:.
1727/// $ROOTSYS/etc/class.rules (or ROOTETCDIR/class.rules)
1728
1730{
1731 static const char *suffix = "class.rules";
1732 TString sname = suffix;
1734
1735 Int_t res = -1;
1736
1737 FILE * f = fopen(sname,"r");
1738 if (f != 0) {
1739 res = ReadRulesContent(f);
1740 fclose(f);
1741 } else {
1742 ::Error("TClass::ReadRules()", "Cannot find rules file %s", sname.Data());
1743 }
1744 return res;
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////
1748/// Read a class.rules file which contains one rule per line with comment
1749/// starting with a #
1750/// - Returns the number of rules loaded.
1751/// - Returns -1 in case of error.
1752
1753Int_t TClass::ReadRules( const char *filename )
1754{
1755 if (!filename || !filename[0]) {
1756 ::Error("TClass::ReadRules", "no file name specified");
1757 return -1;
1758 }
1759
1760 FILE * f = fopen(filename,"r");
1761 if (f == 0) {
1762 ::Error("TClass::ReadRules","Failed to open %s\n",filename);
1763 return -1;
1764 }
1765 Int_t count = ReadRulesContent(f);
1766
1767 fclose(f);
1768 return count;
1769
1770}
1771
1772////////////////////////////////////////////////////////////////////////////////
1773/// Add a schema evolution customization rule.
1774/// The syntax of the rule can be either the short form:
1775/// ~~~ {.cpp}
1776/// [type=Read] classname membername [attributes=... ] [version=[...] ] [checksum=[...] ] [oldtype=...] [code={...}]
1777/// ~~~
1778/// or the long form
1779/// ~~~ {.cpp}
1780/// [type=Read] sourceClass=classname [targetclass=newClassname] [ source="type membername; [type2 membername2]" ]
1781/// [target="membername3;membername4"] [attributes=... ] [version=...] [checksum=...] [code={...}|functionname]
1782/// ~~~
1783///
1784/// For example to set HepMC::GenVertex::m_event to _not_ owned the object it is pointing to:
1785/// HepMC::GenVertex m_event attributes=NotOwner
1786///
1787/// Semantic of the tags:
1788/// - type : the type of the rule, valid values: Read, ReadRaw, Write, WriteRaw, the default is 'Read'.
1789/// - sourceClass : the name of the class as it is on the rule file
1790/// - targetClass : the name of the class as it is in the current code ; defaults to the value of sourceClass
1791/// - source : the types and names of the data members from the class on file that are needed, the list is separated by semi-colons ';'
1792/// - oldtype: in the short form only, indicates the type on disk of the data member.
1793/// - target : the names of the data members updated by this rule, the list is separated by semi-colons ';'
1794/// - attributes : list of possible qualifiers among: Owner, NotOwner
1795/// - version : list of the version of the class layout that this rule applies to. The syntax can be [1,4,5] or [2-] or [1-3] or [-3]
1796/// - checksum : comma delimited list of the checksums of the class layout that this rule applies to.
1797/// - code={...} : code to be executed for the rule or name of the function implementing it.
1798
1799Bool_t TClass::AddRule( const char *rule )
1800{
1801 ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
1802 if (! ruleobj->SetFromRule( rule ) ) {
1803 delete ruleobj;
1804 return kFALSE;
1805 }
1806
1808
1809 TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
1810 if (!cl) {
1811 // Create an empty emulated class for now.
1812 cl = gInterpreter->GenerateTClass(ruleobj->GetTargetClass(), /* emulation = */ kTRUE, /*silent = */ kTRUE);
1813 }
1815
1816 TString errmsg;
1817 if( !rset->AddRule( ruleobj, ROOT::Detail::TSchemaRuleSet::kCheckConflict, &errmsg ) ) {
1818 ::Warning( "TClass::AddRule", "The rule for class: \"%s\": version, \"%s\" and data members: \"%s\" has been skipped because it conflicts with one of the other rules (%s).",
1819 ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString(), errmsg.Data() );
1820 delete ruleobj;
1821 return kFALSE;
1822 }
1823 return kTRUE;
1824}
1825
1826////////////////////////////////////////////////////////////////////////////////
1827/// Adopt a new set of Data Model Evolution rules.
1828
1830{
1832
1833 delete fSchemaRules;
1834 fSchemaRules = rules;
1835 fSchemaRules->SetClass( this );
1836}
1837
1838////////////////////////////////////////////////////////////////////////////////
1839/// Return the set of the schema rules if any.
1840
1842{
1843 return fSchemaRules;
1844}
1845
1846////////////////////////////////////////////////////////////////////////////////
1847/// Return the set of the schema rules if any.
1848/// If create is true, create an empty set
1849
1851{
1852 if (create && fSchemaRules == 0) {
1854 fSchemaRules->SetClass( this );
1855 }
1856 return fSchemaRules;
1857}
1858
1859////////////////////////////////////////////////////////////////////////////////
1860
1861void TClass::AddImplFile(const char* filename, int line) {
1862 // Currently reset the implementation file and line.
1863 // In the close future, it will actually add this file and line
1864 // to a "list" of implementation files.
1865
1866 fImplFileName = filename;
1868}
1869
1870////////////////////////////////////////////////////////////////////////////////
1871/// Browse external object inherited from TObject.
1872/// It passes through inheritance tree and calls TBrowser::Add
1873/// in appropriate cases. Static function.
1874
1876{
1877 if (!obj) return 0;
1878
1879 TAutoInspector insp(b);
1880 obj->ShowMembers(insp);
1881 return insp.fCount;
1882}
1883
1884////////////////////////////////////////////////////////////////////////////////
1885/// Browse objects of of the class described by this TClass object.
1886
1887Int_t TClass::Browse(void *obj, TBrowser *b) const
1888{
1889 if (!obj) return 0;
1890
1891 TClass *actual = GetActualClass(obj);
1892 if (IsTObject()) {
1893 // Call TObject::Browse.
1894
1895 if (!fIsOffsetStreamerSet) {
1897 }
1898 TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
1899 realTObject->Browse(b);
1900 return 1;
1901 } else if (actual != this) {
1902 return actual->Browse(obj, b);
1903 } else if (GetCollectionProxy()) {
1904
1905 // do something useful.
1906
1907 } else {
1908 TAutoInspector insp(b);
1909 CallShowMembers(obj,insp,kFALSE);
1910 return insp.fCount;
1911 }
1912
1913 return 0;
1914}
1915
1916////////////////////////////////////////////////////////////////////////////////
1917/// This method is called by a browser to get the class information.
1918
1920{
1921 if (!HasInterpreterInfo()) return;
1922
1923 if (b) {
1924 if (!fRealData) BuildRealData();
1925
1926 b->Add(GetListOfDataMembers(), "Data Members");
1927 b->Add(GetListOfRealData(), "Real Data Members");
1928 b->Add(GetListOfMethods(), "Methods");
1929 b->Add(GetListOfBases(), "Base Classes");
1930 }
1931}
1932
1933////////////////////////////////////////////////////////////////////////////////
1934/// Build a full list of persistent data members.
1935/// Scans the list of all data members in the class itself and also
1936/// in all base classes. For each persistent data member, inserts a
1937/// TRealData object in the list fRealData.
1938///
1939
1940void TClass::BuildRealData(void* pointer, Bool_t isTransient)
1941{
1942
1944
1945 // Only do this once.
1946 if (fRealData) {
1947 return;
1948 }
1949
1950 if (fClassVersion == 0) {
1951 isTransient = kTRUE;
1952 }
1953
1954 // When called via TMapFile (e.g. Update()) make sure that the dictionary
1955 // gets allocated on the heap and not in the mapped file.
1956 TMmallocDescTemp setreset;
1957
1958 // Handle emulated classes and STL containers specially.
1960 // We are an emulated class or an STL container.
1961 fRealData = new TList;
1962 BuildEmulatedRealData("", 0, this);
1963 return;
1964 }
1965
1966 // return early on string
1967 static TClassRef clRefString("std::string");
1968 if (clRefString == this) {
1969 return;
1970 }
1971
1972 // Complain about stl classes ending up here (unique_ptr etc) - except for
1973 // pair where we will build .first, .second just fine
1974 // and those for which the user explicitly requested a dictionary.
1975 if (!isTransient && GetState() != kHasTClassInit
1977 && strncmp(GetName(), "pair<", 5) != 0) {
1978 Error("BuildRealData", "Inspection for %s not supported!", GetName());
1979 }
1980
1981 // The following statement will recursively call
1982 // all the subclasses of this class.
1983 fRealData = new TList;
1984 TBuildRealData brd(pointer, this);
1985
1986 // CallShowMember will force a call to InheritsFrom, which indirectly
1987 // calls TClass::GetClass. It forces the loading of new typedefs in
1988 // case some of them were not yet loaded.
1989 if ( ! CallShowMembers(pointer, brd, isTransient) ) {
1990 if ( isTransient ) {
1991 // This is a transient data member, so it is probably fine to not have
1992 // access to its content. However let's no mark it as definitively setup,
1993 // since another class might use this class for a persistent data member and
1994 // in this case we really want the error message.
1995 delete fRealData;
1996 fRealData = 0;
1997 } else {
1998 Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
1999 }
2000 }
2001
2002 // Take this opportunity to build the real data for base classes.
2003 // In case one base class is abstract, it would not be possible later
2004 // to create the list of real data for this abstract class.
2005 TBaseClass* base = 0;
2006 TIter next(GetListOfBases());
2007 while ((base = (TBaseClass*) next())) {
2008 if (base->IsSTLContainer()) {
2009 continue;
2010 }
2011 TClass* c = base->GetClassPointer();
2012 if (c) {
2013 c->BuildRealData(0, isTransient);
2014 }
2015 }
2016}
2017
2018////////////////////////////////////////////////////////////////////////////////
2019/// Build the list of real data for an emulated class
2020
2021void TClass::BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
2022{
2024
2026 if (Property() & kIsAbstract) {
2028 } else {
2029 info = GetStreamerInfo();
2030 }
2031 if (!info) {
2032 // This class is abstract, but we don't yet have a SteamerInfo for it ...
2033 Error("BuildEmulatedRealData","Missing StreamerInfo for %s",GetName());
2034 // Humm .. no information ... let's bail out
2035 return;
2036 }
2037
2038 TIter next(info->GetElements());
2039 TStreamerElement *element;
2040 while ((element = (TStreamerElement*)next())) {
2041 Int_t etype = element->GetType();
2042 Long_t eoffset = element->GetOffset();
2043 TClass *cle = element->GetClassPointer();
2044 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2045 //base class are skipped in this loop, they will be added at the end.
2046 continue;
2047 } else if (etype == TVirtualStreamerInfo::kTObject ||
2050 etype == TVirtualStreamerInfo::kAny) {
2051 //member class
2052 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2053 TRealData *rd = new TRealData(rdname,offset+eoffset,0);
2054 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2055 cl->GetListOfRealData()->Add(rd);
2056 // Now we a dot
2057 rdname.Form("%s%s.",name,element->GetFullName());
2058 if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl);
2059 } else {
2060 //others
2061 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2062 TRealData *rd = new TRealData(rdname,offset+eoffset,0);
2063 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2064 cl->GetListOfRealData()->Add(rd);
2065 }
2066 //if (fClassInfo==0 && element->IsBase()) {
2067 // if (fBase==0) fBase = new TList;
2068 // TClass *base = element->GetClassPointer();
2069 // fBase->Add(new TBaseClass(this, cl, eoffset));
2070 //}
2071 }
2072 // The base classes must added last on the list of real data (to help with ambiguous data member names)
2073 next.Reset();
2074 while ((element = (TStreamerElement*)next())) {
2075 Int_t etype = element->GetType();
2076 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2077 //base class
2078 Long_t eoffset = element->GetOffset();
2079 TClass *cle = element->GetClassPointer();
2080 if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl);
2081 }
2082 }
2083}
2084
2085
2086////////////////////////////////////////////////////////////////////////////////
2087/// Calculate the offset between an object of this class to
2088/// its base class TObject. The pointer can be adjusted by
2089/// that offset to access any virtual method of TObject like
2090/// Streamer() and ShowMembers().
2091
2093{
2096 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2097 // gets allocated on the heap and not in the mapped file.
2098
2099 TMmallocDescTemp setreset;
2101 if (fStreamerType == kTObject) {
2103 }
2105 }
2106}
2107
2108
2109////////////////////////////////////////////////////////////////////////////////
2110/// Call ShowMembers() on the obj of this class type, passing insp and parent.
2111/// isATObject is -1 if unknown, 0 if it is not a TObject, and 1 if it is a TObject.
2112/// The function returns whether it was able to call ShowMembers().
2113
2114Bool_t TClass::CallShowMembers(const void* obj, TMemberInspector &insp, Bool_t isTransient) const
2115{
2116 if (fShowMembers) {
2117 // This should always works since 'pointer' should be pointing
2118 // to an object of the actual type of this TClass object.
2119 fShowMembers(obj, insp, isTransient);
2120 return kTRUE;
2121 } else {
2122
2124 if (fClassInfo) {
2125
2126 if (strcmp(GetName(), "string") == 0) {
2127 // For std::string we know that we do not have a ShowMembers
2128 // function and that it's okay.
2129 return kTRUE;
2130 }
2131 // Since we do have some dictionary information, let's
2132 // call the interpreter's ShowMember.
2133 // This works with Cling to support interpreted classes.
2134 gInterpreter->InspectMembers(insp, obj, this, isTransient);
2135 return kTRUE;
2136
2137 } else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
2138 sinfo->CallShowMembers(obj, insp, isTransient);
2139 return kTRUE;
2140 } // isATObject
2141 } // fShowMembers is set
2142
2143 return kFALSE;
2144}
2145
2146////////////////////////////////////////////////////////////////////////////////
2147/// Do a ShowMembers() traversal of all members and base classes' members
2148/// using the reflection information from the interpreter. Works also for
2149/// interpreted objects.
2150
2151void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp, Bool_t isTransient)
2152{
2153 return gInterpreter->InspectMembers(insp, obj, this, isTransient);
2154}
2155
2157{
2158 if (fCanSplit >= 0) {
2159 return ! ( fCanSplit & 0x2 );
2160 }
2161
2163
2164 if (GetCollectionProxy() != nullptr) {
2165 // A collection can never affect its derived class 'splittability'
2166 return kTRUE;
2167 }
2168
2169 if (this == TRef::Class()) { fCanSplit = 2; return kFALSE; }
2170 if (this == TRefArray::Class()) { fCanSplit = 2; return kFALSE; }
2171 if (this == TArray::Class()) { fCanSplit = 2; return kFALSE; }
2172 if (this == TClonesArray::Class()) { fCanSplit = 1; return kTRUE; }
2173 if (this == TCollection::Class()) { fCanSplit = 2; return kFALSE; }
2174
2175 // TTree is not always available (for example in rootcling), so we need
2176 // to grab it silently.
2177 auto refTreeClass( TClass::GetClass("TTree",kTRUE,kTRUE) );
2178 if (this == refTreeClass) { fCanSplit = 2; return kFALSE; }
2179
2180 if (!HasDataMemberInfo()) {
2181 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
2182 if (sinfo==0) sinfo = GetStreamerInfo();
2183 TIter next(sinfo->GetElements());
2184 TStreamerElement *element;
2185 while ((element = (TStreamerElement*)next())) {
2186 if (element->IsA() == TStreamerBase::Class()) {
2187 TClass *clbase = element->GetClassPointer();
2188 if (!clbase) {
2189 // If there is a missing base class, we can't split the immediate
2190 // derived class.
2191 fCanSplit = 0;
2192 return kFALSE;
2193 } else if (!clbase->CanSplitBaseAllow()) {
2194 fCanSplit = 2;
2195 return kFALSE;
2196 }
2197 }
2198 }
2199 }
2200
2201 // If we don't have data member info there is no more information
2202 // we can find out.
2203 if (!HasDataMemberInfo()) return kTRUE;
2204
2205 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : 0;
2206
2207 // Look at inheritance tree
2208 while (lnk) {
2209 TClass *c;
2210 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2211 c = base->GetClassPointer();
2212 if(!c) {
2213 // If there is a missing base class, we can't split the immediate
2214 // derived class.
2215 fCanSplit = 0;
2216 return kFALSE;
2217 } else if (!c->CanSplitBaseAllow()) {
2218 fCanSplit = 2;
2219 return kFALSE;
2220 }
2221 lnk = lnk->Next();
2222 }
2223 return kTRUE;
2224}
2225
2226////////////////////////////////////////////////////////////////////////////////
2227/// Return true if the data member of this TClass can be saved separately.
2228
2230{
2231 // Note: add the possibility to set it for the class and the derived class.
2232 // save the info in TVirtualStreamerInfo
2233 // deal with the info in MakeProject
2234 if (fCanSplit >= 0) {
2235 // The user explicitly set the value
2236 return (fCanSplit & 0x1) == 1;
2237 }
2238
2240 TClass *This = const_cast<TClass*>(this);
2241
2242 if (this == TObject::Class()) { This->fCanSplit = 1; return kTRUE; }
2243 if (fName == "TClonesArray") { This->fCanSplit = 1; return kTRUE; }
2244 if (fRefProxy) { This->fCanSplit = 0; return kFALSE; }
2245 if (fName.BeginsWith("TVectorT<")) { This->fCanSplit = 0; return kFALSE; }
2246 if (fName.BeginsWith("TMatrixT<")) { This->fCanSplit = 0; return kFALSE; }
2247 if (fName == "string") { This->fCanSplit = 0; return kFALSE; }
2248 if (fName == "std::string") { This->fCanSplit = 0; return kFALSE; }
2249
2250 if (GetCollectionProxy()!=0) {
2251 // For STL collection we need to look inside.
2252
2253 // However we do not split collections of collections
2254 // nor collections of strings
2255 // nor collections of pointers (unless explicit request (see TBranchSTL)).
2256
2257 if (GetCollectionProxy()->HasPointers()) { This->fCanSplit = 0; return kFALSE; }
2258
2259 TClass *valueClass = GetCollectionProxy()->GetValueClass();
2260 if (valueClass == 0) { This->fCanSplit = 0; return kFALSE; }
2261 static TClassRef stdStringClass("std::string");
2262 if (valueClass==TString::Class() || valueClass==stdStringClass)
2263 { This->fCanSplit = 0; return kFALSE; }
2264 if (!valueClass->CanSplit()) { This->fCanSplit = 0; return kFALSE; }
2265 if (valueClass->GetCollectionProxy() != 0) { This->fCanSplit = 0; return kFALSE; }
2266
2267 Int_t stl = -TClassEdit::IsSTLCont(GetName(), 0);
2268 if ((stl==ROOT::kSTLmap || stl==ROOT::kSTLmultimap)
2269 && !valueClass->HasDataMemberInfo()==0)
2270 {
2271 This->fCanSplit = 0;
2272 return kFALSE;
2273 }
2274
2275 This->fCanSplit = 1;
2276 return kTRUE;
2277
2278 }
2279
2280 if (GetStreamer() != nullptr || fStreamerFunc != nullptr) {
2281
2282 // We have an external custom streamer provided by the user, we must not
2283 // split it.
2284 This->fCanSplit = 0;
2285 return kFALSE;
2286
2288
2289 // We have a custom member function streamer or
2290 // an older (not StreamerInfo based) automatic streamer.
2291 This->fCanSplit = 0;
2292 return kFALSE;
2293 }
2294
2295 if (Size()==1) {
2296 // 'Empty' class there is nothing to split!.
2297 This->fCanSplit = 0;
2298 return kFALSE;
2299 }
2300
2301
2302 if ( !This->CanSplitBaseAllow() ) {
2303 return kFALSE;
2304 }
2305
2306 This->fCanSplit = 1;
2307 return kTRUE;
2308}
2309
2310////////////////////////////////////////////////////////////////////////////////
2311/// Return the C++ property of this class, eg. is abstract, has virtual base
2312/// class, see EClassProperty in TDictionary.h
2313
2315{
2316 if (fProperty == -1) Property();
2317 return fClassProperty;
2318}
2319
2320////////////////////////////////////////////////////////////////////////////////
2321/// Create a Clone of this TClass object using a different name but using the same 'dictionary'.
2322/// This effectively creates a hard alias for the class name.
2323
2324TObject *TClass::Clone(const char *new_name) const
2325{
2326 if (new_name == 0 || new_name[0]=='\0' || fName == new_name) {
2327 Error("Clone","The name of the class must be changed when cloning a TClass object.");
2328 return 0;
2329 }
2330
2331 // Need to lock access to TROOT::GetListOfClasses so the cloning happens atomically
2333 // Temporarily remove the original from the list of classes.
2334 TClass::RemoveClass(const_cast<TClass*>(this));
2335
2336 TClass *copy;
2337 if (fTypeInfo) {
2338 copy = new TClass(GetName(),
2340 *fTypeInfo,
2341 new TIsAProxy(*fTypeInfo),
2345 GetImplFileLine());
2346 } else {
2347 copy = new TClass(GetName(),
2352 GetImplFileLine());
2353 }
2354 copy->fShowMembers = fShowMembers;
2355 // Remove the copy before renaming it
2356 TClass::RemoveClass(copy);
2357 copy->fName = new_name;
2358 TClass::AddClass(copy);
2359
2360 copy->SetNew(fNew);
2361 copy->SetNewArray(fNewArray);
2362 copy->SetDelete(fDelete);
2368 if (fStreamer) {
2370 }
2371 // If IsZombie is true, something went wrong and we will not be
2372 // able to properly copy the collection proxy
2373 if (fCollectionProxy && !copy->IsZombie()) {
2375 }
2376 copy->SetClassSize(fSizeof);
2377 if (fRefProxy) {
2379 }
2380 TClass::AddClass(const_cast<TClass*>(this));
2381 return copy;
2382}
2383
2384////////////////////////////////////////////////////////////////////////////////
2385/// Copy the argument.
2386
2388{
2389// // This code was used too quickly test the STL Emulation layer
2390// Int_t k = TClassEdit::IsSTLCont(GetName());
2391// if (k==1||k==-1) return;
2392
2393 delete fCollectionProxy;
2394 fCollectionProxy = orig.Generate();
2395}
2396
2397////////////////////////////////////////////////////////////////////////////////
2398/// Draw detailed class inheritance structure.
2399/// If a class B inherits from a class A, the description of B is drawn
2400/// on the right side of the description of A.
2401/// Member functions overridden by B are shown in class A with a blue line
2402/// erasing the corresponding member function
2403
2405{
2406 if (!HasInterpreterInfo()) return;
2407
2408 TVirtualPad *padsav = gPad;
2409
2410 // Should we create a new canvas?
2411 TString opt=option;
2412 if (!padsav || !opt.Contains("same")) {
2413 TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
2414 if (!padclass) {
2415 gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
2416 } else {
2417 padclass->cd();
2418 }
2419 }
2420
2421 if (gPad) gPad->DrawClassObject(this,option);
2422
2423 if (padsav) padsav->cd();
2424}
2425
2426////////////////////////////////////////////////////////////////////////////////
2427/// Dump contents of object on stdout.
2428/// Using the information in the object dictionary
2429/// each data member is interpreted.
2430/// If a data member is a pointer, the pointer value is printed
2431/// 'obj' is assume to point to an object of the class describe by this TClass
2432///
2433/// The following output is the Dump of a TArrow object:
2434/// ~~~ {.cpp}
2435/// fAngle 0 Arrow opening angle (degrees)
2436/// fArrowSize 0.2 Arrow Size
2437/// fOption.*fData
2438/// fX1 0.1 X of 1st point
2439/// fY1 0.15 Y of 1st point
2440/// fX2 0.67 X of 2nd point
2441/// fY2 0.83 Y of 2nd point
2442/// fUniqueID 0 object unique identifier
2443/// fBits 50331648 bit field status word
2444/// fLineColor 1 line color
2445/// fLineStyle 1 line style
2446/// fLineWidth 1 line width
2447/// fFillColor 19 fill area color
2448/// fFillStyle 1001 fill area style
2449/// ~~~
2450///
2451/// If noAddr is true, printout of all pointer values is skipped.
2452
2453void TClass::Dump(const void *obj, Bool_t noAddr /*=kFALSE*/) const
2454{
2455
2456 Long_t prObj = noAddr ? 0 : (Long_t)obj;
2457 if (IsTObject()) {
2458 if (!fIsOffsetStreamerSet) {
2460 }
2461 TObject *tobj = (TObject*)((Long_t)obj + fOffsetStreamer);
2462
2463
2464 if (sizeof(this) == 4)
2465 Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2466 else
2467 Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2468 } else {
2469
2470 if (sizeof(this) == 4)
2471 Printf("==> Dumping object at: 0x%08lx, class=%s\n",prObj,GetName());
2472 else
2473 Printf("==> Dumping object at: 0x%016lx, class=%s\n",prObj,GetName());
2474 }
2475
2476 TDumpMembers dm(noAddr);
2477 if (!CallShowMembers(obj, dm, kFALSE)) {
2478 Info("Dump", "No ShowMembers function, dumping disabled");
2479 }
2480}
2481
2482////////////////////////////////////////////////////////////////////////////////
2483/// Introduce an escape character (@) in front of a special chars.
2484/// You need to use the result immediately before it is being overwritten.
2485
2486char *TClass::EscapeChars(const char *text) const
2487{
2488 static const UInt_t maxsize = 255;
2489 static char name[maxsize+2]; //One extra if last char needs to be escaped
2490
2491 UInt_t nch = strlen(text);
2492 UInt_t icur = 0;
2493 for (UInt_t i = 0; i < nch && icur < maxsize; ++i, ++icur) {
2494 if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
2495 text[i] == ']' || text[i] == '&' || text[i] == '#' ||
2496 text[i] == '!' || text[i] == '^' || text[i] == '<' ||
2497 text[i] == '?' || text[i] == '>') {
2498 name[icur] = '@';
2499 ++icur;
2500 }
2501 name[icur] = text[i];
2502 }
2503 name[icur] = 0;
2504 return name;
2505}
2506
2507////////////////////////////////////////////////////////////////////////////////
2508/// Return a pointer the the real class of the object.
2509/// This is equivalent to object->IsA() when the class has a ClassDef.
2510/// It is REQUIRED that object is coming from a proper pointer to the
2511/// class represented by 'this'.
2512/// Example: Special case:
2513/// ~~~ {.cpp}
2514/// class MyClass : public AnotherClass, public TObject
2515/// ~~~
2516/// then on return, one must do:
2517/// ~~~ {.cpp}
2518/// TObject *obj = (TObject*)((void*)myobject)directory->Get("some object of MyClass");
2519/// MyClass::Class()->GetActualClass(obj); // this would be wrong!!!
2520/// ~~~
2521/// Also if the class represented by 'this' and NONE of its parents classes
2522/// have a virtual ptr table, the result will be 'this' and NOT the actual
2523/// class.
2524
2525TClass *TClass::GetActualClass(const void *object) const
2526{
2527 if (object==0) return (TClass*)this;
2528 if (fIsA) {
2529 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2530 } else if (fGlobalIsA) {
2531 return fGlobalIsA(this,object);
2532 } else {
2533 if (IsTObject()) {
2534
2535 if (!fIsOffsetStreamerSet) {
2537 }
2538 TObject* realTObject = (TObject*)((size_t)object + fOffsetStreamer);
2539
2540 return realTObject->IsA();
2541 }
2542
2543 if (HasInterpreterInfo()) {
2544
2545 TVirtualIsAProxy *isa = 0;
2547 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TInstrumentedIsAProxy<%s>(0);",GetName()));
2548 }
2549 else {
2550 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TIsAProxy(typeid(%s));",GetName()));
2551 }
2552 if (isa) {
2554 const_cast<TClass*>(this)->fIsA = isa;
2555 }
2556 if (fIsA) {
2557 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2558 }
2559 }
2561 if (sinfo) {
2562 return sinfo->GetActualClass(object);
2563 }
2564 return (TClass*)this;
2565 }
2566}
2567
2568////////////////////////////////////////////////////////////////////////////////
2569/// Return pointer to the base class "classname". Returns 0 in case
2570/// "classname" is not a base class. Takes care of multiple inheritance.
2571
2572TClass *TClass::GetBaseClass(const char *classname)
2573{
2574 // check if class name itself is equal to classname
2575 if (strcmp(GetName(), classname) == 0) return this;
2576
2577 if (!HasDataMemberInfo()) return 0;
2578
2579 // Make sure we deal with possible aliases, we could also have normalized
2580 // the name.
2581 TClass *search = TClass::GetClass(classname,kTRUE,kTRUE);
2582
2583 if (search) return GetBaseClass(search);
2584 else return 0;
2585}
2586
2587////////////////////////////////////////////////////////////////////////////////
2588/// Return pointer to the base class "cl". Returns 0 in case "cl"
2589/// is not a base class. Takes care of multiple inheritance.
2590
2592{
2593 // check if class name itself is equal to classname
2594 if (cl == this) return this;
2595
2596 if (!HasDataMemberInfo()) return 0;
2597
2598 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : 0;
2599
2600 // otherwise look at inheritance tree
2601 while (lnk) {
2602 TClass *c, *c1;
2603 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2604 c = base->GetClassPointer();
2605 if (c) {
2606 if (cl == c) return c;
2607 c1 = c->GetBaseClass(cl);
2608 if (c1) return c1;
2609 }
2610 lnk = lnk->Next();
2611 }
2612 return 0;
2613}
2614
2615////////////////////////////////////////////////////////////////////////////////
2616/// Return data member offset to the base class "cl".
2617/// - Returns -1 in case "cl" is not a base class.
2618/// - Returns -2 if cl is a base class, but we can't find the offset
2619/// because it's virtual.
2620/// Takes care of multiple inheritance.
2621
2623{
2624 // check if class name itself is equal to classname
2625 if (cl == this) return 0;
2626
2627 if (!fBase.load()) {
2629 // If the information was not provided by the root pcm files and
2630 // if we can not find the ClassInfo, we have to fall back to the
2631 // StreamerInfo
2632 if (!fClassInfo) {
2634 if (!sinfo) return -1;
2635 TStreamerElement *element;
2636 Int_t offset = 0;
2637
2638 TObjArray &elems = *(sinfo->GetElements());
2639 Int_t size = elems.GetLast()+1;
2640 for(Int_t i=0; i<size; i++) {
2641 element = (TStreamerElement*)elems[i];
2642 if (element->IsBase()) {
2643 if (element->IsA() == TStreamerBase::Class()) {
2644 TStreamerBase *base = (TStreamerBase*)element;
2645 TClass *baseclass = base->GetClassPointer();
2646 if (!baseclass) return -1;
2647 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2648 if (subOffset == -2) return -2;
2649 if (subOffset != -1) return offset+subOffset;
2650 offset += baseclass->Size();
2651 } else if (element->IsA() == TStreamerSTL::Class()) {
2652 TStreamerSTL *base = (TStreamerSTL*)element;
2653 TClass *baseclass = base->GetClassPointer();
2654 if (!baseclass) return -1;
2655 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2656 if (subOffset == -2) return -2;
2657 if (subOffset != -1) return offset+subOffset;
2658 offset += baseclass->Size();
2659
2660 } else {
2661 Error("GetBaseClassOffsetRecurse","Unexpected element type for base class: %s\n",element->IsA()->GetName());
2662 }
2663 }
2664 }
2665 return -1;
2666 }
2667 }
2668
2669 TClass *c;
2670 Int_t off;
2671 TBaseClass *inh;
2672 TObjLink *lnk = 0;
2673 if (fBase.load() == 0)
2674 lnk = GetListOfBases()->FirstLink();
2675 else
2676 lnk = fBase.load()->FirstLink();
2677
2678 // otherwise look at inheritance tree
2679 while (lnk) {
2680 inh = (TBaseClass *)lnk->GetObject();
2681 //use option load=kFALSE to avoid a warning like:
2682 //"Warning in <TClass::TClass>: no dictionary for class TRefCnt is available"
2683 //We can not afford to not have the class if it exist, so we
2684 //use kTRUE.
2685 c = inh->GetClassPointer(kTRUE); // kFALSE);
2686 if (c) {
2687 if (cl == c) {
2688 if ((inh->Property() & kIsVirtualBase) != 0)
2689 return -2;
2690 return inh->GetDelta();
2691 }
2692 off = c->GetBaseClassOffsetRecurse(cl);
2693 if (off == -2) return -2;
2694 if (off != -1) {
2695 return off + inh->GetDelta();
2696 }
2697 }
2698 lnk = lnk->Next();
2699 }
2700 return -1;
2701}
2702
2703////////////////////////////////////////////////////////////////////////////////
2704/// - Return data member offset to the base class "cl".
2705/// - Returns -1 in case "cl" is not a base class.
2706/// Takes care of multiple inheritance.
2707
2708Int_t TClass::GetBaseClassOffset(const TClass *toBase, void *address, bool isDerivedObject)
2709{
2710 // Warning("GetBaseClassOffset","Requires the use of fClassInfo for %s to %s",GetName(),toBase->GetName());
2711
2712 if (this == toBase) return 0;
2713
2714 if ((!address /* || !has_virtual_base */) &&
2716 // At least of the ClassInfo have not been loaded in memory yet and
2717 // since there is no virtual base class (or we don't have enough so it
2718 // would not make a difference) we can use the 'static' information
2719 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2720 if (offset != -2) {
2721 return offset;
2722 }
2723 return offset;
2724 }
2725
2726 ClassInfo_t* derived = GetClassInfo();
2727 ClassInfo_t* base = toBase->GetClassInfo();
2728 if(derived && base) {
2729 // TClingClassInfo::GetBaseOffset takes the lock.
2730 return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject);
2731 }
2732 else {
2733 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2734 if (offset != -2) {
2735 return offset;
2736 }
2737 }
2738 return -1;
2739}
2740
2741////////////////////////////////////////////////////////////////////////////////
2742/// Return pointer to (base) class that contains datamember.
2743
2744TClass *TClass::GetBaseDataMember(const char *datamember)
2745{
2746 if (!HasDataMemberInfo()) return 0;
2747
2748 // Check if data member exists in class itself
2749 TDataMember *dm = GetDataMember(datamember);
2750 if (dm) return this;
2751
2752 // if datamember not found in class, search in next base classes
2753 TBaseClass *inh;
2754 TIter next(GetListOfBases());
2755 while ((inh = (TBaseClass *) next())) {
2756 TClass *c = inh->GetClassPointer();
2757 if (c) {
2758 TClass *cdm = c->GetBaseDataMember(datamember);
2759 if (cdm) return cdm;
2760 }
2761 }
2762
2763 return 0;
2764}
2765
2766namespace {
2767 // A local Helper class used to keep 2 pointer (the collection proxy
2768 // and the class streamer) in the thread local storage.
2769
2770 struct TClassLocalStorage {
2771 TClassLocalStorage() : fCollectionProxy(0), fStreamer(0) {};
2772
2773 TVirtualCollectionProxy *fCollectionProxy;
2774 TClassStreamer *fStreamer;
2775
2776 static TClassLocalStorage *GetStorage(const TClass *cl)
2777 {
2778 // Return the thread storage for the TClass.
2779
2780 void **thread_ptr = (*gThreadTsd)(0,ROOT::kClassThreadSlot);
2781 if (thread_ptr) {
2782 if (*thread_ptr==0) *thread_ptr = new TExMap();
2783 TExMap *lmap = (TExMap*)(*thread_ptr);
2784 ULong_t hash = TString::Hash(&cl, sizeof(void*));
2785 ULong_t local = 0;
2786 UInt_t slot;
2787 if ((local = (ULong_t)lmap->GetValue(hash, (Long_t)cl, slot)) != 0) {
2788 } else {
2789 local = (ULong_t) new TClassLocalStorage();
2790 lmap->AddAt(slot, hash, (Long_t)cl, local);
2791 }
2792 return (TClassLocalStorage*)local;
2793 }
2794 return 0;
2795 }
2796 };
2797}
2798
2799////////////////////////////////////////////////////////////////////////////////
2800/// Return the 'type' of the STL the TClass is representing.
2801/// and return ROOT::kNotSTL if it is not representing an STL collection.
2802
2804{
2805 auto proxy = GetCollectionProxy();
2806 if (proxy) return (ROOT::ESTLType)proxy->GetCollectionType();
2807 return ROOT::kNotSTL;
2808}
2809
2810
2811////////////////////////////////////////////////////////////////////////////////
2812/// Return the proxy describing the collection (if any).
2813
2815{
2816 // Use assert, so that this line (slow because of the TClassEdit) is completely
2817 // removed in optimized code.
2818 //assert(TestBit(kLoading) || !TClassEdit::IsSTLCont(fName) || fCollectionProxy || 0 == "The TClass for the STL collection has no collection proxy!");
2820 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2821 if (local == 0) return fCollectionProxy;
2822 if (local->fCollectionProxy==0) local->fCollectionProxy = fCollectionProxy->Generate();
2823 return local->fCollectionProxy;
2824 }
2825 return fCollectionProxy;
2826}
2827
2828////////////////////////////////////////////////////////////////////////////////
2829/// Return the Streamer Class allowing streaming (if any).
2830
2832{
2833 if (gThreadTsd && fStreamer) {
2834 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2835 if (local==0) return fStreamer;
2836 if (local->fStreamer==0) {
2837 local->fStreamer = fStreamer->Generate();
2838 const std::type_info &orig = ( typeid(*fStreamer) );
2839 if (!local->fStreamer) {
2840 Warning("GetStreamer","For %s, the TClassStreamer (%s) passed's call to Generate failed!",GetName(),orig.name());
2841 } else {
2842 const std::type_info &copy = ( typeid(*local->fStreamer) );
2843 if (strcmp(orig.name(),copy.name())!=0) {
2844 Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s)\n",GetName(),orig.name(),copy.name());
2845 }
2846 }
2847 }
2848 return local->fStreamer;
2849 }
2850 return fStreamer;
2851}
2852
2853////////////////////////////////////////////////////////////////////////////////
2854/// Get a wrapper/accessor function around this class custom streamer (member function).
2855
2857{
2858 return fStreamerFunc;
2859}
2860
2861////////////////////////////////////////////////////////////////////////////////
2862/// Get a wrapper/accessor function around this class custom conversion streamer (member function).
2863
2865{
2866 return fConvStreamerFunc;
2867}
2868
2869////////////////////////////////////////////////////////////////////////////////
2870/// Return the proxy implementing the IsA functionality.
2871
2873{
2874 return fIsA;
2875}
2876
2877////////////////////////////////////////////////////////////////////////////////
2878/// Static method returning pointer to TClass of the specified class name.
2879/// If load is true an attempt is made to obtain the class by loading
2880/// the appropriate shared library (directed by the rootmap file).
2881/// If silent is 'true', do not warn about missing dictionary for the class.
2882/// (typically used for class that are used only for transient members)
2883/// Returns 0 in case class is not found.
2884
2885TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
2886{
2887 if (!name || !name[0]) return 0;
2888
2889 if (strstr(name, "(anonymous)")) return 0;
2890 if (strncmp(name,"class ",6)==0) name += 6;
2891 if (strncmp(name,"struct ",7)==0) name += 7;
2892
2893 if (!gROOT->GetListOfClasses()) return 0;
2894
2895 // FindObject will take the read lock before actually getting the
2896 // TClass pointer so we will need not get a partially initialized
2897 // object.
2898 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2899
2900 // Early return to release the lock without having to execute the
2901 // long-ish normalization.
2902 if (cl && (cl->IsLoaded() || cl->TestBit(kUnloading))) return cl;
2903
2905
2906 // Now that we got the write lock, another thread may have constructed the
2907 // TClass while we were waiting, so we need to do the checks again.
2908
2909 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2910 if (cl) {
2911 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
2912
2913 // We could speed-up some of the search by adding (the equivalent of)
2914 //
2915 // if (cl->GetState() == kInterpreter) return cl
2916 //
2917 // In this case, if a ROOT dictionary was available when the TClass
2918 // was first requested it would have been used and if a ROOT dictionary is
2919 // loaded later on TClassTable::Add will take care of updating the TClass.
2920 // So as far as ROOT dictionary are concerned, if the current TClass is
2921 // in interpreted state, we are sure there is nothing to load.
2922 //
2923 // However (see TROOT::LoadClass), the TClass can also be loaded/provided
2924 // by a user provided TClassGenerator. We have no way of knowing whether
2925 // those do (or even can) behave the same way as the ROOT dictionary and
2926 // have the 'dictionary is now available for use' step informs the existing
2927 // TClass that their dictionary is now available.
2928
2929 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
2930 load = kTRUE;
2931 }
2932
2933 // To avoid spurious auto parsing, let's check if the name as-is is
2934 // known in the TClassTable.
2936 if (dict) {
2937 // The name is normalized, so the result of the first search is
2938 // authoritative.
2939 if (!cl && !load) return 0;
2940
2941 TClass *loadedcl = (dict)();
2942 if (loadedcl) {
2943 loadedcl->PostLoadCheck();
2944 return loadedcl;
2945 }
2946
2947 // We should really not fall through to here, but if we do, let's just
2948 // continue as before ...
2949 }
2950
2951 std::string normalizedName;
2952 Bool_t checkTable = kFALSE;
2953
2954 if (!cl) {
2955 int oldAutoloadVal = gCling->SetClassAutoloading(false);
2956 TClassEdit::GetNormalizedName(normalizedName, name);
2957 gCling->SetClassAutoloading(oldAutoloadVal);
2958 // Try the normalized name.
2959 if (normalizedName != name) {
2960 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(normalizedName.c_str());
2961
2962 if (cl) {
2963 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
2964
2965 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
2966 load = kTRUE;
2967 }
2968 checkTable = kTRUE;
2969 }
2970 } else {
2971 normalizedName = cl->GetName(); // Use the fact that all TClass names are normalized.
2972 checkTable = load && (normalizedName != name);
2973 }
2974
2975 if (!load) return 0;
2976
2977// This assertion currently fails because of
2978// TClass *c1 = TClass::GetClass("basic_iostream<char,char_traits<char> >");
2979// TClass *c2 = TClass::GetClass("std::iostream");
2980// where the TClassEdit normalized name of iostream is basic_iostream<char>
2981// i.e missing the addition of the default parameter. This is because TClingLookupHelper
2982// uses only 'part' of TMetaUtils::GetNormalizedName.
2983
2984// if (!cl) {
2985// TDataType* dataType = (TDataType*)gROOT->GetListOfTypes()->FindObject(name);
2986// TClass *altcl = dataType ? (TClass*)gROOT->GetListOfClasses()->FindObject(dataType->GetFullTypeName()) : 0;
2987// if (altcl && normalizedName != altcl->GetName())
2988// ::Fatal("TClass::GetClass","The existing name (%s) for %s is different from the normalized name: %s\n",
2989// altcl->GetName(), name, normalizedName.c_str());
2990// }
2991
2992 TClass *loadedcl = 0;
2993 if (checkTable) {
2994 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
2995 } else {
2996 if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
2997 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
2998 }
2999 // Maybe this was a typedef: let's try to see if this is the case
3000 if (!loadedcl){
3001 if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3002 // We have a typedef: we get the name of the underlying type
3003 auto underlyingTypeName = theDataType->GetTypeName();
3004 // We see if we can bootstrap a class with it
3005 auto underlyingTypeDict = TClassTable::GetDictNorm(underlyingTypeName.Data());
3006 if (underlyingTypeDict){
3007 loadedcl = underlyingTypeDict();
3008 }
3009
3010 }
3011 }
3012 }
3013 if (loadedcl) return loadedcl;
3014
3015 // See if the TClassGenerator can produce the TClass we need.
3016 loadedcl = LoadClassCustom(normalizedName.c_str(),silent);
3017 if (loadedcl) return loadedcl;
3018
3019 // We have not been able to find a loaded TClass, return the Emulated
3020 // TClass if we have one.
3021 if (cl) return cl;
3022
3023 if (TClassEdit::IsSTLCont( normalizedName.c_str() )) {
3024
3025 return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
3026 }
3027
3028 // Check the interpreter only after autoparsing the template if any.
3029 {
3030 std::string::size_type posLess = normalizedName.find('<');
3031 if (posLess != std::string::npos) {
3032 gCling->AutoParse(normalizedName.substr(0, posLess).c_str());
3033 }
3034 }
3035
3036 //last attempt. Look in CINT list of all (compiled+interpreted) classes
3037 if (gDebug>0){
3038 printf("TClass::GetClass: Header Parsing - The representation of %s was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting %s in the linkdef/selection file.\n",normalizedName.c_str(), normalizedName.c_str());
3039 }
3040 if (normalizedName.length()) {
3041 auto cci = gInterpreter->CheckClassInfo(normalizedName.c_str(), kTRUE /* autoload */,
3042 kTRUE /*Only class, structs and ns*/);
3043
3044 // We could have an interpreted class with an inline ClassDef, in this case we do not
3045 // want to create an 'interpreted' TClass but we want the one triggered via the call to
3046 // the Dictionary member. If we go ahead and generate the 'interpreted' version it will
3047 // replace if/when there is a call to IsA on an object of this type.
3048
3050 auto ci = gInterpreter->ClassInfo_Factory(normalizedName.c_str());
3051 auto funcDecl = gInterpreter->GetFunctionWithPrototype(ci, "Dictionary", "", false, ROOT::kExactMatch);
3052 auto method = gInterpreter->MethodInfo_Factory(funcDecl);
3053 typedef void (*tcling_callfunc_Wrapper_t)(void *, int, void **, void *);
3054 auto funcPtr = (tcling_callfunc_Wrapper_t)gInterpreter->MethodInfo_InterfaceMethod(method);
3055
3056 TClass *res = nullptr;
3057 if (funcPtr)
3058 funcPtr(0, 0, nullptr, &res);
3059 // else
3060 // We could fallback to the interpreted case ...
3061 // For now just 'fail' (return nullptr)
3062
3063 gInterpreter->MethodInfo_Delete(method);
3064 gInterpreter->ClassInfo_Delete(ci);
3065
3066 return res;
3067 } else if (cci) {
3068 // Get the normalized name based on the decl (currently the only way
3069 // to get the part to add or drop the default arguments as requested by the user)
3070 std::string alternative;
3071 gInterpreter->GetInterpreterTypeName(normalizedName.c_str(), alternative, kTRUE);
3072 const char *altname = alternative.c_str();
3073 if (strncmp(altname, "std::", 5) == 0) {
3074 // For namespace (for example std::__1), GetInterpreterTypeName does
3075 // not strip std::, so we must do it explicitly here.
3076 altname += 5;
3077 }
3078 if (altname != normalizedName && strcmp(altname, name) != 0) {
3079 // altname now contains the full name of the class including a possible
3080 // namespace if there has been a using namespace statement.
3081
3082 // At least in the case C<string [2]> (normalized) vs C<string[2]> (altname)
3083 // the TClassEdit normalization and the TMetaUtils normalization leads to
3084 // two different space layout. To avoid an infinite recursion, we also
3085 // add the test on (altname != name)
3086
3087 return GetClass(altname, load);
3088 }
3089
3090 TClass *ncl = gInterpreter->GenerateTClass(normalizedName.c_str(), /* emulation = */ kFALSE, silent);
3091 if (!ncl->IsZombie()) {
3092 return ncl;
3093 }
3094 delete ncl;
3095 }
3096 }
3097 return nullptr;
3098}
3099
3100////////////////////////////////////////////////////////////////////////////////
3101/// Return pointer to class with name.
3102
3103TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */)
3104{
3105 if (!gROOT->GetListOfClasses())
3106 return 0;
3107
3108 //protect access to TROOT::GetIdMap
3110
3111 TClass* cl = GetIdMap()->Find(typeinfo.name());
3112
3113 if (cl && cl->IsLoaded()) return cl;
3114
3116
3117 // Now that we got the write lock, another thread may have constructed the
3118 // TClass while we were waiting, so we need to do the checks again.
3119
3120 cl = GetIdMap()->Find(typeinfo.name());
3121
3122 if (cl) {
3123 if (cl->IsLoaded()) return cl;
3124 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3125 load = kTRUE;
3126 } else {
3127 // Note we might need support for typedefs and simple types!
3128
3129 // TDataType *objType = GetType(name, load);
3130 //if (objType) {
3131 // const char *typdfName = objType->GetTypeName();
3132 // if (typdfName && strcmp(typdfName, name)) {
3133 // cl = GetClass(typdfName, load);
3134 // return cl;
3135 // }
3136 // }
3137 }
3138
3139 if (!load) return 0;
3140
3141 DictFuncPtr_t dict = TClassTable::GetDict(typeinfo);
3142 if (dict) {
3143 cl = (dict)();
3144 if (cl) cl->PostLoadCheck();
3145 return cl;
3146 }
3147 if (cl) return cl;
3148
3149 TIter next(gROOT->GetListOfClassGenerators());
3150 TClassGenerator *gen;
3151 while( (gen = (TClassGenerator*) next()) ) {
3152 cl = gen->GetClass(typeinfo,load);
3153 if (cl) {
3154 cl->PostLoadCheck();
3155 return cl;
3156 }
3157 }
3158
3159 // try autoloading the typeinfo
3160 int autoload_old = gCling->SetClassAutoloading(1);
3161 if (!autoload_old) {
3162 // Re-disable, we just meant to test
3164 }
3165 if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
3166 // Disable autoload to avoid potential infinite recursion
3168 cl = GetClass(typeinfo, load);
3170 if (cl) {
3171 return cl;
3172 }
3173 }
3174
3175 // last attempt. Look in the interpreter list of all (compiled+interpreted)
3176 // classes
3177 cl = gInterpreter->GetClass(typeinfo, load);
3178
3179 return cl; // Can be zero.
3180}
3181
3182////////////////////////////////////////////////////////////////////////////////
3183/// Static method returning pointer to TClass of the specified ClassInfo.
3184/// If load is true an attempt is made to obtain the class by loading
3185/// the appropriate shared library (directed by the rootmap file).
3186/// If silent is 'true', do not warn about missing dictionary for the class.
3187/// (typically used for class that are used only for transient members)
3188/// Returns 0 in case class is not found.
3189
3190TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
3191{
3192 if (!info || !gCling->ClassInfo_IsValid(info)) return 0;
3193 if (!gROOT->GetListOfClasses()) return 0;
3194
3195 // Technically we need the write lock only for the call to ClassInfo_FullName
3196 // and GenerateTClass but FindObject will take the read lock (and LoadClass will
3197 // take the write lock). Since taking/releasing the lock is expensive, let just
3198 // take the write guard and keep it.
3200
3201 // Get the normalized name.
3202 TString name( gCling->ClassInfo_FullName(info) );
3203
3204 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
3205
3206 if (cl) {
3207 if (cl->IsLoaded()) return cl;
3208
3209 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3210 load = kTRUE;
3211
3212 }
3213
3214 if (!load) return 0;
3215
3216 TClass *loadedcl = 0;
3217 if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
3218 else loadedcl = gROOT->LoadClass(name,silent);
3219
3220 if (loadedcl) return loadedcl;
3221
3222 if (cl) return cl; // If we found the class but we already have a dummy class use it.
3223
3224 // We did not find a proper TClass but we do know (we have a valid
3225 // ClassInfo) that the class is known to the interpreter.
3226 TClass *ncl = gInterpreter->GenerateTClass(info, silent);
3227 if (!ncl->IsZombie()) {
3228 return ncl;
3229 } else {
3230 delete ncl;
3231 return 0;
3232 }
3233}
3234
3235////////////////////////////////////////////////////////////////////////////////
3236
3239}
3240
3241////////////////////////////////////////////////////////////////////////////////
3242
3243Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
3244{
3245 if (!gROOT->GetListOfClasses()) return 0;
3246
3247 DeclIdMap_t* map = GetDeclIdMap();
3248 // Get all the TClass pointer that have the same DeclId.
3249 DeclIdMap_t::equal_range iter = map->Find(id);
3250 if (iter.first == iter.second) return false;
3251 std::vector<TClass*>::iterator vectIt = classes.begin();
3252 for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
3253 vectIt = classes.insert(vectIt, it->second);
3254 return true;
3255}
3256
3257////////////////////////////////////////////////////////////////////////////////
3258/// Return a pointer to the dictionary loading function generated by
3259/// rootcint
3260
3262{
3263 return TClassTable::GetDict(cname);
3264}
3265
3266////////////////////////////////////////////////////////////////////////////////
3267/// Return a pointer to the dictionary loading function generated by
3268/// rootcint
3269
3270DictFuncPtr_t TClass::GetDict (const std::type_info& info)
3271{
3272 return TClassTable::GetDict(info);
3273}
3274
3275////////////////////////////////////////////////////////////////////////////////
3276/// Return pointer to datamember object with name "datamember".
3277
3278TDataMember *TClass::GetDataMember(const char *datamember) const
3279{
3280 if ((!(fData && fData->IsLoaded()) && !HasInterpreterInfo())
3281 || datamember == 0) return 0;
3282
3283 // Strip off leading *'s and trailing [
3284 const char *start_name = datamember;
3285 while (*start_name == '*') ++start_name;
3286
3287 // Empty name are 'legal', they represent anonymous unions.
3288 // if (*start_name == 0) return 0;
3289
3290 if (const char *s = strchr(start_name, '[')){
3291 UInt_t len = s-start_name;
3292 TString name(start_name,len);
3293 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(name.Data());
3294 } else {
3295 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(start_name);
3296 }
3297}
3298
3299////////////////////////////////////////////////////////////////////////////////
3300/// return offset for member name. name can be a data member in
3301/// the class itself, one of its base classes, or one member in
3302/// one of the aggregated classes.
3303///
3304/// In case of an emulated class, the list of emulated TRealData is built
3305
3307{
3308 TRealData *rd = GetRealData(name);
3309 if (rd) return rd->GetThisOffset();
3310 if (strchr(name,'[')==0) {
3311 // If this is a simple name there is a chance to find it in the
3312 // StreamerInfo even if we did not find it in the RealData.
3313 // For example an array name would be fArray[3] in RealData but
3314 // just fArray in the streamerInfo.
3315 TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
3316 if (info) {
3317 return info->GetOffset(name);
3318 }
3319 }
3320 return 0;
3321}
3322
3323////////////////////////////////////////////////////////////////////////////////
3324/// Return pointer to TRealData element with name "name".
3325///
3326/// Name can be a data member in the class itself,
3327/// one of its base classes, or a member in
3328/// one of the aggregated classes.
3329///
3330/// In case of an emulated class, the list of emulated TRealData is built.
3331
3333{
3334 if (!fRealData) {
3335 const_cast<TClass*>(this)->BuildRealData();
3336 }
3337
3338 if (!fRealData) {
3339 return 0;
3340 }
3341
3342 if (!name) {
3343 return 0;
3344 }
3345
3346 // First try just the whole name.
3348 if (rd) {
3349 return rd;
3350 }
3351
3352 std::string givenName(name);
3353
3354 // Try ignoring the array dimensions.
3355 std::string::size_type firstBracket = givenName.find_first_of("[");
3356 if (firstBracket != std::string::npos) {
3357 // -- We are looking for an array data member.
3358 std::string nameNoDim(givenName.substr(0, firstBracket));
3359 TObjLink* lnk = fRealData->FirstLink();
3360 while (lnk) {
3361 TObject* obj = lnk->GetObject();
3362 std::string objName(obj->GetName());
3363 std::string::size_type pos = objName.find_first_of("[");
3364 // Only match arrays to arrays for now.
3365 if (pos != std::string::npos) {
3366 objName.erase(pos);
3367 if (objName == nameNoDim) {
3368 return static_cast<TRealData*>(obj);
3369 }
3370 }
3371 lnk = lnk->Next();
3372 }
3373 }
3374
3375 // Now try it as a pointer.
3376 std::ostringstream ptrname;
3377 ptrname << "*" << givenName;
3378 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3379 if (rd) {
3380 return rd;
3381 }
3382
3383 // Check for a dot in the name.
3384 std::string::size_type firstDot = givenName.find_first_of(".");
3385 if (firstDot == std::string::npos) {
3386 // -- Not found, a simple name, all done.
3387 return 0;
3388 }
3389
3390 //
3391 // At this point the name has a dot in it, so it is the name
3392 // of some contained sub-object.
3393 //
3394
3395 // May be a pointer like in TH1: fXaxis.fLabels (in TRealdata is named fXaxis.*fLabels)
3396 std::string::size_type lastDot = givenName.find_last_of(".");
3397 std::ostringstream starname;
3398 starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
3399 rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
3400 if (rd) {
3401 return rd;
3402 }
3403
3404 // Strip the first component, it may be the name of
3405 // the branch (old TBranchElement code), and try again.
3406 std::string firstDotName(givenName.substr(firstDot + 1));
3407
3408 // New attempt starting after the first "." if any,
3409 // this allows for the case that the first component
3410 // may have been a branch name (for TBranchElement).
3411 rd = (TRealData*) fRealData->FindObject(firstDotName.c_str());
3412 if (rd) {
3413 return rd;
3414 }
3415
3416 // New attempt starting after the first "." if any,
3417 // but this time try ignoring the array dimensions.
3418 // Again, we are allowing for the case that the first
3419 // component may have been a branch name (for TBranchElement).
3420 std::string::size_type firstDotBracket = firstDotName.find_first_of("[");
3421 if (firstDotBracket != std::string::npos) {
3422 // -- We are looking for an array data member.
3423 std::string nameNoDim(firstDotName.substr(0, firstDotBracket));
3424 TObjLink* lnk = fRealData->FirstLink();
3425 while (lnk) {
3426 TObject* obj = lnk->GetObject();
3427 std::string objName(obj->GetName());
3428 std::string::size_type pos = objName.find_first_of("[");
3429 // Only match arrays to arrays for now.
3430 if (pos != std::string::npos) {
3431 objName.erase(pos);
3432 if (objName == nameNoDim) {
3433 return static_cast<TRealData*>(obj);
3434 }
3435 }
3436 lnk = lnk->Next();
3437 }
3438 }
3439
3440 // New attempt starting after the first "." if any,
3441 // but this time check for a pointer type. Again, we
3442 // are allowing for the case that the first component
3443 // may have been a branch name (for TBranchElement).
3444 ptrname.str("");
3445 ptrname << "*" << firstDotName;
3446 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3447 if (rd) {
3448 return rd;
3449 }
3450
3451 // Last attempt in case a member has been changed from
3452 // a static array to a pointer, for example the member
3453 // was arr[20] and is now *arr.
3454 //
3455 // Note: In principle, one could also take into account
3456 // the opposite situation where a member like *arr has
3457 // been converted to arr[20].
3458 //
3459 // FIXME: What about checking after the first dot as well?
3460 //
3461 std::string::size_type bracket = starname.str().find_first_of("[");
3462 if (bracket == std::string::npos) {
3463 return 0;
3464 }
3465 rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
3466 if (rd) {
3467 return rd;
3468 }
3469
3470 // Not found;
3471 return 0;
3472}
3473
3474////////////////////////////////////////////////////////////////////////////////
3475
3477{
3478 if (!gInterpreter || !HasInterpreterInfo()) return 0;
3479
3480 // The following
3482
3484}
3485
3486////////////////////////////////////////////////////////////////////////////////
3487/// Get the list of shared libraries containing the code for class cls.
3488/// The first library in the list is the one containing the class, the
3489/// others are the libraries the first one depends on. Returns 0
3490/// in case the library is not found.
3491
3493{
3494 if (!gInterpreter) return 0;
3495
3496 if (fSharedLibs.IsNull())
3497 fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
3498
3499 return !fSharedLibs.IsNull() ? fSharedLibs.Data() : 0;
3500}
3501
3502////////////////////////////////////////////////////////////////////////////////
3503/// Return list containing the TBaseClass(es) of a class.
3504
3506{
3507 if (!fBase.load()) {
3508 if (fCanLoadClassInfo) {
3509 if (fState == kHasTClassInit) {
3510
3512 // NOTE: Add test to prevent redo if another thread has already done the work.
3513 // if (!fHasRootPcmInfo) {
3514
3515 // The bases are in our ProtoClass; we don't need the class info.
3517 if (proto && proto->FillTClass(this)) {
3518 // Not sure this code is still needed
3519 // R__ASSERT(kFALSE);
3520
3522 }
3523 }
3524 // We test again on fCanLoadClassInfo has another thread may have executed it.
3526 LoadClassInfo();
3527 }
3528 }
3529 if (!fClassInfo) return 0;
3530
3531 if (!gInterpreter)
3532 Fatal("GetListOfBases", "gInterpreter not initialized");
3533
3535 if (!fBase.load()) {
3536 gInterpreter->CreateListOfBaseClasses(this);
3537 }
3538 }
3539 return fBase;
3540}
3541
3542////////////////////////////////////////////////////////////////////////////////
3543/// Return a list containing the TEnums of a class.
3544///
3545/// The list returned is safe to use from multiple thread without explicitly
3546/// taking the ROOT global lock.
3547///
3548/// In the case the TClass represents a namespace, the returned list will
3549/// implicit take the ROOT global lock upon any access (see TListOfEnumsWithLock)
3550///
3551/// In the case the TClass represents a class or struct and requestListLoading
3552/// is true, the list is immutable (and thus safe to access from multiple thread
3553/// without taking the global lock at all).
3554///
3555/// In the case the TClass represents a class or struct and requestListLoading
3556/// is false, the list is mutable and thus we return a TListOfEnumsWithLock
3557/// which will implicit take the ROOT global lock upon any access.
3558
3559TList *TClass::GetListOfEnums(Bool_t requestListLoading /* = kTRUE */)
3560{
3561 auto temp = fEnums.load();
3562 if (temp) {
3563 if (requestListLoading) {
3564 if (fProperty == -1) Property();
3565 if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
3567 temp->Load();
3568 } else if ( temp->IsA() == TListOfEnumsWithLock::Class() ) {
3569 // We have a class for which the list was not loaded fully at
3570 // first use.
3572 temp->Load();
3573 }
3574 }
3575 return temp;
3576 }
3577
3578 if (!requestListLoading) {
3579 if (fProperty == -1) Property();
3581 if (fEnums.load()) {
3582 return fEnums.load();
3583 }
3584
3585 static bool fromRootCling = dlsym(RTLD_DEFAULT, "usedToIdentifyRootClingByDlSym");
3586
3587 if (fromRootCling) // rootcling is single thread (this save some space in the rootpcm).
3588 fEnums = new TListOfEnums(this);
3589 else
3590 fEnums = new TListOfEnumsWithLock(this);
3591 return fEnums;
3592 }
3593
3595 if (fEnums.load()) {
3596 (*fEnums).Load();
3597 return fEnums.load();
3598 }
3599 if (fProperty == -1) Property();
3600 if ( (kIsClass | kIsStruct | kIsUnion) & fProperty) {
3601 // For this case, the list will be immutable
3602 temp = new TListOfEnums(this);
3603 } else {
3604 //namespaces can have enums added to them
3605 temp = new TListOfEnumsWithLock(this);
3606 }
3607 temp->Load();
3608 fEnums = temp;
3609 return temp;
3610}
3611
3612////////////////////////////////////////////////////////////////////////////////
3613/// Return list containing the TDataMembers of a class.
3614
3616{
3618
3619 if (!fData) {
3621 // NOTE: Add test to prevent redo if another thread has already done the work.
3622 // if (!fHasRootPcmInfo) {
3623
3624 // The members are in our ProtoClass; we don't need the class info.
3626 if (proto && proto->FillTClass(this)) {
3627 // Not sure this code is still needed
3628 // R__ASSERT(kFALSE);
3629
3631 return fData;
3632 }
3633 }
3634 fData = new TListOfDataMembers(this);
3635 }
3636 if (Property() & (kIsClass|kIsStruct|kIsUnion)) {
3637 // If the we have a class or struct or union, the order
3638 // of data members is the list is essential since it determines their
3639 // order on file. So we must always load. Also, the list is fixed
3640 // since the language does not allow to add members.
3641 if (!fData->IsLoaded()) fData->Load();
3642
3643 } else if (load) fData->Load();
3644 return fData;
3645}
3646
3647////////////////////////////////////////////////////////////////////////////////
3648/// Return list containing the TEnums of a class.
3649
3651{
3653
3655 if (load) fFuncTemplate->Load();
3656 return fFuncTemplate;
3657}
3658
3659////////////////////////////////////////////////////////////////////////////////
3660/// Return list containing the TMethods of a class.
3661/// If load is true, the list is populated with all the defined function
3662/// and currently instantiated function template.
3663
3665{
3667
3668 if (!fMethod.load()) GetMethodList();
3669 if (load) {
3670 if (gDebug>0) Info("GetListOfMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3671 (*fMethod).Load();
3672 }
3673 return fMethod;
3674}
3675
3676////////////////////////////////////////////////////////////////////////////////
3677/// Return the collection of functions named "name".
3678
3680{
3681 return const_cast<TClass*>(this)->GetMethodList()->GetListForObject(name);
3682}
3683
3684
3685////////////////////////////////////////////////////////////////////////////////
3686/// Returns a list of all public methods of this class and its base classes.
3687/// Refers to a subset of the methods in GetListOfMethods() so don't do
3688/// GetListOfAllPublicMethods()->Delete().
3689/// Algorithm used to get the list is:
3690/// - put all methods of the class in the list (also protected and private
3691/// ones).
3692/// - loop over all base classes and add only those methods not already in the
3693/// list (also protected and private ones).
3694/// - once finished, loop over resulting list and remove all private and
3695/// protected methods.
3696
3698{
3700
3702 if (load) {
3703 if (gDebug>0) Info("GetListOfAllPublicMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3705 }
3706 return fAllPubMethod;
3707}
3708
3709////////////////////////////////////////////////////////////////////////////////
3710/// Returns a list of all public data members of this class and its base
3711/// classes. Refers to a subset of the data members in GetListOfDatamembers()
3712/// so don't do GetListOfAllPublicDataMembers()->Delete().
3713
3715{
3717
3719 if (load) fAllPubData->Load();
3720 return fAllPubData;
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Returns list of methods accessible by context menu.
3725
3727{
3728 if (!HasInterpreterInfo()) return;
3729
3730 // get the base class
3731 TIter nextBase(GetListOfBases(), kIterBackward);
3732 TBaseClass *baseClass;
3733 while ((baseClass = (TBaseClass *) nextBase())) {
3734 TClass *base = baseClass->GetClassPointer();
3735 if (base) base->GetMenuItems(list);
3736 }
3737
3738 // remove methods redefined in this class with no menu
3739 TMethod *method, *m;
3741 while ((method = (TMethod*)next())) {
3742 m = (TMethod*)list->FindObject(method->GetName());
3743 if (method->IsMenuItem() != kMenuNoMenu) {
3744 if (!m)
3745 list->AddFirst(method);
3746 } else {
3747 if (m && m->GetNargs() == method->GetNargs())
3748 list->Remove(m);
3749 }
3750 }
3751}
3752
3753////////////////////////////////////////////////////////////////////////////////
3754/// Check whether a class has a dictionary or not.
3755/// This is equivalent to ask if a class is coming from a bootstrapping
3756/// procedure initiated during the loading of a library.
3757
3759{
3760 return IsLoaded();
3761}
3762
3763////////////////////////////////////////////////////////////////////////////////
3764/// Check whether a class has a dictionary or ROOT can load one.
3765/// This is equivalent to ask HasDictionary() or whether a library is known
3766/// where it can be loaded from, or whether a Dictionary function is
3767/// available because the class's dictionary library was already loaded.
3768
3770{
3771 if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(clname))
3772 return cl->IsLoaded();
3773 return gClassTable->GetDict(clname) || gInterpreter->GetClassSharedLibs(clname);
3774}
3775
3776////////////////////////////////////////////////////////////////////////////////
3777/// Verify the base classes always.
3778
3780{
3781 TList* lb = GetListOfBases();
3782 if (!lb) return;
3783 TIter nextBase(lb);
3784 TBaseClass* base = 0;
3785 while ((base = (TBaseClass*)nextBase())) {
3786 TClass* baseCl = base->GetClassPointer();
3787 if (baseCl) {
3788 baseCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3789 }
3790 }
3791}
3792
3793////////////////////////////////////////////////////////////////////////////////
3794/// Verify the Data Members.
3795
3797{
3799 if (!ldm) return ;
3800 TIter nextMemb(ldm);
3801 TDataMember * dm = 0;
3802 while ((dm = (TDataMember*)nextMemb())) {
3803 // If it is a transient
3804 if(!dm->IsPersistent()) {
3805 continue;
3806 }
3807 if (dm->Property() & kIsStatic) {
3808 continue;
3809 }
3810 // If it is a built-in data type.
3811 TClass* dmTClass = 0;
3812 if (dm->GetDataType()) {
3813 // We have a basic datatype.
3814 dmTClass = nullptr;
3815 // Otherwise get the string representing the type.
3816 } else if (dm->GetTypeName()) {
3817 dmTClass = TClass::GetClass(dm->GetTypeName());
3818 }
3819 if (dmTClass) {
3820 dmTClass->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3821 }
3822 }
3823}
3824
3826{
3827 // Pair is a special case and we have to check its elements for missing dictionaries
3828 // Pair is a transparent container so we should always look at its.
3829
3831 for (int i = 0; i < 2; i++) {
3832 TClass* pairElement = ((TStreamerElement*)SI->GetElements()->At(i))->GetClass();
3833 if (pairElement) {
3834 pairElement->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3835 }
3836 }
3837}
3838
3839////////////////////////////////////////////////////////////////////////////////
3840/// From the second level of recursion onwards it is different state check.
3841
3843{
3844 if (result.FindObject(this) || visited.FindObject(this)) return;
3845
3846 static TClassRef sCIString("string");
3847 if (this == sCIString) return;
3848
3849 TClassEdit::TSplitType splitType(fName);
3850 if (splitType.IsTemplate()) {
3851 // We now treat special cases:
3852 // - pair
3853 // - unique_ptr
3854 // - array
3855 // - tuple
3856
3857 // Small helper to get the TClass instance from a classname and recursively
3858 // investigate it
3859 auto checkDicts = [&](const string &clName){
3860 auto cl = TClass::GetClass(clName.c_str());
3861 if (!cl) {
3862 // We try to remove * and const from the type name if any
3863 const auto clNameShortType = TClassEdit::ShortType(clName.c_str(), 1);
3864 cl = TClass::GetClass(clNameShortType.c_str());
3865 }
3866 if (cl && !cl->HasDictionary()) {
3867 cl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3868 }
3869 };
3870
3871 const auto &elements = splitType.fElements;
3872 const auto &templName = elements[0];
3873
3874 // Special treatment for pair.
3875 if (templName == "pair") {
3876 GetMissingDictionariesForPairElements(result, visited, recurse);
3877 return;
3878 }
3879
3880 // Special treatment of unique_ptr or array
3881 // They are treated together since they have 1 single template argument
3882 // which is interesting when checking for missing dictionaries.
3883 if (templName == "unique_ptr" || templName == "array") {
3884 checkDicts(elements[1]);
3885 return;
3886 }
3887
3888 // Special treatment of tuple
3889 // This type must be treated separately since it can have N template
3890 // arguments which are interesting, unlike unique_ptr or array.
3891 if (templName == "tuple") {
3892 // -1 because the elements end with a list of the "stars", i.e. number of
3893 // * after the type name
3894 const auto nTemplArgs = elements.size() - 1;
3895 // loop starts at 1 because the first element is the template name
3896 for (auto iTemplArg = 1U; iTemplArg < nTemplArgs; ++iTemplArg) {
3897 checkDicts(elements[iTemplArg]);
3898 }
3899 return;
3900 }
3901 } // this is not a template
3902
3903 if (!HasDictionary()) {
3904 result.Add(this);
3905 }
3906
3907 visited.Add(this);
3908 //Check whether a custom streamer
3910 if (GetCollectionProxy()) {
3911 // We need to look at the collection's content
3912 // The collection has different kind of elements the check would be required.
3913 TClass* t = 0;
3914 if ((t = GetCollectionProxy()->GetValueClass())) {
3915 if (!t->HasDictionary()) {
3916 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3917 }
3918 }
3919 } else {
3920 if (recurse) {
3921 GetMissingDictionariesForMembers(result, visited, recurse);
3922 }
3923 GetMissingDictionariesForBaseClasses(result, visited, recurse);
3924 }
3925 }
3926}
3927
3928////////////////////////////////////////////////////////////////////////////////
3929/// Get the classes that have a missing dictionary starting from this one.
3930/// - With recurse = false the classes checked for missing dictionaries are:
3931/// the class itself, all base classes, direct data members,
3932/// and for collection proxies the container's
3933/// elements without iterating over the element's data members;
3934/// - With recurse = true the classes checked for missing dictionaries are:
3935/// the class itself, all base classes, recursing on the data members,
3936/// and for the collection proxies recursion on the elements of the
3937/// collection and iterating over the element's data members.
3938
3940{
3941 // Top level recursion it different from the following levels of recursion.
3942
3943 if (result.FindObject(this)) return;
3944
3945 static TClassRef sCIString("string");
3946 if (this == sCIString) return;
3947
3948 THashTable visited;
3949
3950 if (strncmp(fName, "pair<", 5) == 0) {
3951 GetMissingDictionariesForPairElements(result, visited, recurse);
3952 return;
3953 }
3954
3955 if (!HasDictionary()) {
3956 result.Add(this);
3957 }
3958
3959 visited.Add(this);
3960
3961 //Check whether a custom streamer
3963 if (GetCollectionProxy()) {
3964 // We need to look at the collection's content
3965 // The collection has different kind of elements the check would be required.
3966 TClass* t = 0;
3967 if ((t = GetCollectionProxy()->GetValueClass())) {
3968 if (!t->HasDictionary()) {
3969 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3970 }
3971 }
3972 } else {
3973 GetMissingDictionariesForMembers(result, visited, recurse);
3974 GetMissingDictionariesForBaseClasses(result, visited, recurse);
3975 }
3976 }
3977}
3978
3979////////////////////////////////////////////////////////////////////////////////
3980/// Return kTRUE if the class has elements.
3981
3982Bool_t TClass::IsFolder(void *obj) const
3983{
3984 return Browse(obj,(TBrowser*)0);
3985}
3986
3987//______________________________________________________________________________
3988//______________________________________________________________________________
3989void TClass::ReplaceWith(TClass *newcl) const
3990{
3991 // Inform the other objects to replace this object by the new TClass (newcl)
3992
3994 //we must update the class pointers pointing to 'this' in all TStreamerElements
3995 TIter nextClass(gROOT->GetListOfClasses());
3996 TClass *acl;
3998 TList tobedeleted;
3999
4000 // Since we are in the process of replacing a TClass by a TClass
4001 // coming from a dictionary, there is no point in loading any
4002 // libraries during this search.
4003 Bool_t autoload = gInterpreter->SetClassAutoloading(kFALSE);
4004
4005 while ((acl = (TClass*)nextClass())) {
4006 if (acl == newcl) continue;
4007
4008 TIter nextInfo(acl->GetStreamerInfos());
4009 while ((info = (TVirtualStreamerInfo*)nextInfo())) {
4010
4011 info->Update(this, newcl);
4012 }
4013 }
4014
4015 TIter delIter( &tobedeleted );
4016 while ((acl = (TClass*)delIter())) {
4017 delete acl;
4018 }
4019 gInterpreter->UnRegisterTClassUpdate(this);
4020
4021 gInterpreter->SetClassAutoloading(autoload);
4022}
4023
4024////////////////////////////////////////////////////////////////////////////////
4025/// Make sure that the current ClassInfo is up to date.
4026
4028{
4029 Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
4030}
4031
4032////////////////////////////////////////////////////////////////////////////////
4033/// Make sure that the current ClassInfo is up to date.
4034
4036{
4038
4040
4041 if (fClassInfo) {
4043 gInterpreter->ClassInfo_Delete(fClassInfo);
4044 fClassInfo = 0;
4045 }
4046 // We can not check at this point whether after the unload there will
4047 // still be interpreter information about this class (as v5 was doing),
4048 // instead this function must only be called if the definition is (about)
4049 // to be unloaded.
4050
4051 ResetCaches();
4052
4053 // We got here because the definition Decl is about to be unloaded.
4055 if (fStreamerInfo->GetEntries() != 0) {
4057 } else {
4059 }
4060 } else {
4061 // if the ClassInfo was loaded for a class with a TClass Init and it
4062 // gets unloaded, should we guess it can be reloaded?
4064 }
4065}
4066
4067////////////////////////////////////////////////////////////////////////////////
4068/// To clean out all caches.
4069
4071{
4072 R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
4073
4074 // Not owning lists, don't call Delete(), but unload
4075 if (fData)
4076 fData->Unload();
4077 if (fEnums.load())
4078 (*fEnums).Unload();
4079 if (fMethod.load())
4080 (*fMethod).Unload();
4081
4082 delete fAllPubData; fAllPubData = 0;
4083
4084 if (fBase.load())
4085 (*fBase).Delete();
4086 delete fBase.load(); fBase = 0;
4087
4088 if (fRealData)
4089 fRealData->Delete();
4090 delete fRealData; fRealData=0;
4091}
4092
4093////////////////////////////////////////////////////////////////////////////////
4094/// Resets the menu list to it's standard value.
4095
4097{
4098 if (fClassMenuList)
4100 else
4101 fClassMenuList = new TList();
4103}
4104
4105////////////////////////////////////////////////////////////////////////////////
4106/// The ls function lists the contents of a class on stdout. Ls output
4107/// is typically much less verbose then Dump().
4108/// If options contains 'streamerinfo', run ls on the list of streamerInfos
4109/// and the list of conversion streamerInfos.
4110
4111void TClass::ls(Option_t *options) const
4112{
4113 TNamed::ls(options);
4114 if (options==0 || options[0]==0) return;
4115
4116 if (strstr(options,"streamerinfo")!=0) {
4117 GetStreamerInfos()->ls(options);
4118
4119 if (fConversionStreamerInfo.load()) {
4120 std::map<std::string, TObjArray*>::iterator it;
4121 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
4122 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
4123 it->second->ls(options);
4124 }
4125 }
4126 }
4127}
4128
4129////////////////////////////////////////////////////////////////////////////////
4130/// Makes a customizable version of the popup menu list, i.e. makes a list
4131/// of TClassMenuItem objects of methods accessible by context menu.
4132/// The standard (and different) way consists in having just one element
4133/// in this list, corresponding to the whole standard list.
4134/// Once the customizable version is done, one can remove or add elements.
4135
4137{
4139 TClassMenuItem *menuItem;
4140
4141 // Make sure fClassMenuList is initialized and empty.
4142 GetMenuList()->Delete();
4143
4144 TList* methodList = new TList;
4145 GetMenuItems(methodList);
4146
4147 TMethod *method;
4148 TMethodArg *methodArg;
4149 TClass *classPtr = 0;
4150 TIter next(methodList);
4151
4152 while ((method = (TMethod*) next())) {
4153 // if go to a mother class method, add separator
4154 if (classPtr != method->GetClass()) {
4155 menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
4156 fClassMenuList->AddLast(menuItem);
4157 classPtr = method->GetClass();
4158 }
4159 // Build the signature of the method
4160 TString sig;
4161 TList* margsList = method->GetListOfMethodArgs();
4162 TIter nextarg(margsList);
4163 while ((methodArg = (TMethodArg*)nextarg())) {
4164 sig = sig+","+methodArg->GetFullTypeName();
4165 }
4166 if (sig.Length()!=0) sig.Remove(0,1); // remove first comma
4168 method->GetName(), method->GetName(),0,
4169 sig.Data(),-1,TClassMenuItem::kIsSelf);
4170 if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
4171 fClassMenuList->Add(menuItem);
4172 }
4173 delete methodList;
4174}
4175
4176////////////////////////////////////////////////////////////////////////////////
4177/// Register the fact that an object was moved from the memory location
4178/// 'arenaFrom' to the memory location 'arenaTo'.
4179
4180void TClass::Move(void *arenaFrom, void *arenaTo) const
4181{
4182 // If/when we have access to a copy constructor (or better to a move
4183 // constructor), this function should also perform the data move.
4184 // For now we just information the repository.
4185
4186 if ((GetState() <= kEmulated) && !fCollectionProxy) {
4187 MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
4188 }
4189}
4190
4191////////////////////////////////////////////////////////////////////////////////
4192/// Return the list of menu items associated with the class.
4193
4195 if (!fClassMenuList) {
4196 fClassMenuList = new TList();
4198 }
4199 return fClassMenuList;
4200}
4201
4202////////////////////////////////////////////////////////////////////////////////
4203/// Return (create an empty one if needed) the list of functions.
4204/// The major difference with GetListOfMethod is that this returns
4205/// the internal type of fMethod and thus can not be made public.
4206/// It also never 'loads' the content of the list.
4207
4209{
4210 if (!fMethod.load()) {
4211 std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
4212 TListOfFunctions* expected = nullptr;
4213 if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
4214 temp.release();
4215 }
4216 }
4217 return fMethod;
4218}
4219
4220
4221////////////////////////////////////////////////////////////////////////////////
4222/// Return pointer to method without looking at parameters.
4223/// Does not look in (possible) base classes.
4224/// Has the side effect of loading all the TMethod object in the list
4225/// of the class.
4226
4227TMethod *TClass::GetMethodAny(const char *method)
4228{
4229 if (!HasInterpreterInfo()) return 0;
4230 return (TMethod*) GetMethodList()->FindObject(method);
4231}
4232
4233////////////////////////////////////////////////////////////////////////////////
4234/// Return pointer to method without looking at parameters.
4235/// Does look in all base classes.
4236
4238{
4239 if (!HasInterpreterInfo()) return 0;
4240
4241 TMethod* m = GetMethodAny(method);
4242 if (m) return m;
4243
4244 TBaseClass *base;
4245 TIter nextb(GetListOfBases());
4246 while ((base = (TBaseClass *) nextb())) {
4247 TClass *c = base->GetClassPointer();
4248 if (c) {
4249 m = c->GetMethodAllAny(method);
4250 if (m) return m;
4251 }
4252 }
4253
4254 return 0;
4255}
4256
4257////////////////////////////////////////////////////////////////////////////////
4258/// Find the best method (if there is one) matching the parameters.
4259/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4260/// The function invokes GetClassMethod to search for a possible method
4261/// in the class itself or in its base classes. Returns 0 in case method
4262/// is not found.
4263
4264TMethod *TClass::GetMethod(const char *method, const char *params,
4265 Bool_t objectIsConst /* = kFALSE */)
4266{
4268 if (!fClassInfo) return 0;
4269
4270 if (!gInterpreter)
4271 Fatal("GetMethod", "gInterpreter not initialized");
4272
4273 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4274 method, params,
4275 objectIsConst);
4276
4277 if (!decl) return 0;
4278
4279 // search recursively in this class or its base classes
4281 if (f) return f;
4282
4283 Error("GetMethod",
4284 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4285 method,params,objectIsConst ? "const " : "", GetName());
4286 return 0;
4287}
4288
4289
4290////////////////////////////////////////////////////////////////////////////////
4291/// Find a method with decl id in this class or its bases.
4292
4294 if (TFunction* method = GetMethodList()->Get(declId))
4295 return static_cast<TMethod *>(method);
4296
4297 for (auto item : *GetListOfBases())
4298 if (auto base = static_cast<TBaseClass *>(item)->GetClassPointer())
4299 if (TFunction* method = base->FindClassOrBaseMethodWithId(declId))
4300 return static_cast<TMethod *>(method);
4301
4302 return nullptr;
4303}
4304
4305////////////////////////////////////////////////////////////////////////////////
4306/// Find the method with a given prototype. The proto string must be of the
4307/// form: "char*,int,double". Returns 0 in case method is not found.
4308
4309TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto,
4310 Bool_t objectIsConst /* = kFALSE */,
4311 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4312{
4314 if (!fClassInfo) return 0;
4315
4316 if (!gInterpreter)
4317 Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
4318
4319 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4320 method, proto,
4321 objectIsConst, mode);
4322
4323 if (!decl) return 0;
4325 if (f) return f;
4326 Error("GetMethodWithPrototype",
4327 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4328 method,proto,objectIsConst ? "const " : "", GetName());
4329 return 0;
4330}
4331
4332////////////////////////////////////////////////////////////////////////////////
4333/// Look for a method in this class that has the interface function
4334/// address faddr.
4335
4337{
4338 if (!HasInterpreterInfo()) return 0;
4339
4340 TMethod *m;
4341 TIter next(GetListOfMethods());
4342 while ((m = (TMethod *) next())) {
4343 if (faddr == (Long_t)m->InterfaceMethod())
4344 return m;
4345 }
4346 return 0;
4347}
4348
4349////////////////////////////////////////////////////////////////////////////////
4350/// Look for a method in this class that has the name and matches the parameters.
4351/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4352/// Returns 0 in case method is not found.
4353/// See TClass::GetMethod to also search the base classes.
4354
4355TMethod *TClass::GetClassMethod(const char *name, const char* params,
4356 Bool_t objectIsConst /* = kFALSE */)
4357{
4359 if (!fClassInfo) return 0;
4360
4361 if (!gInterpreter)
4362 Fatal("GetClassMethod", "gInterpreter not initialized");
4363
4364 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4365 name, params,
4366 objectIsConst);
4367
4368 if (!decl) return 0;
4369
4370 TFunction *f = GetMethodList()->Get(decl);
4371
4372 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4373}
4374
4375////////////////////////////////////////////////////////////////////////////////
4376/// Find the method with a given prototype. The proto string must be of the
4377/// form: "char*,int,double". Returns 0 in case method is not found.
4378/// See TClass::GetMethodWithPrototype to also search the base classes.
4379
4381 Bool_t objectIsConst /* = kFALSE */,
4382 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4383{
4385 if (!fClassInfo) return 0;
4386
4387 if (!gInterpreter)
4388 Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
4389
4390 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4391 name, proto,
4392 objectIsConst,
4393 mode);
4394
4395 if (!decl) return 0;
4396
4397 TFunction *f = GetMethodList()->Get(decl);
4398
4399 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4400}
4401
4402////////////////////////////////////////////////////////////////////////////////
4403/// Return the number of data members of this class
4404/// Note that in case the list of data members is not yet created, it will be done
4405/// by GetListOfDataMembers().
4406
4408{
4409 if (!HasDataMemberInfo()) return 0;
4410
4412 if (lm)
4413 return lm->GetSize();
4414 else
4415 return 0;
4416}
4417
4418////////////////////////////////////////////////////////////////////////////////
4419/// Return the number of methods of this class
4420/// Note that in case the list of methods is not yet created, it will be done
4421/// by GetListOfMethods().
4422/// This will also load/populate the list of methods, to get 'just' the
4423/// number of currently loaded methods use:
4424/// cl->GetListOfMethods(false)->GetSize();
4425
4427{
4428 if (!HasInterpreterInfo()) return 0;
4429
4430 TList *lm = GetListOfMethods();
4431 if (lm)
4432 return lm->GetSize();
4433 else
4434 return 0;
4435}
4436
4437////////////////////////////////////////////////////////////////////////////////
4438/// returns a pointer to the TVirtualStreamerInfo object for version
4439/// If the object does not exist, it is created
4440///
4441/// Note: There are two special version numbers:
4442///
4443/// - 0: Use the class version from the currently loaded class library.
4444/// - -1: Assume no class library loaded (emulated class).
4445///
4446/// Warning: If we create a new streamer info, whether or not the build
4447/// optimizes is controlled externally to us by a global variable!
4448/// Don't call us unless you have set that variable properly
4449/// with TStreamer::Optimize()!
4450///
4451
4453{
4455
4456 // Version 0 is special, it means the currently loaded version.
4457 // We need to set it at the beginning to be able to guess it correctly.
4458
4459 if (version == 0)
4460 version = fClassVersion;
4461
4462 // If the StreamerInfo is assigned to the fLastReadInfo, we are
4463 // guaranteed it was built and compiled.
4464 if (sinfo && sinfo->GetClassVersion() == version)
4465 return sinfo;
4466
4467 // Note that the access to fClassVersion above is technically not thread-safe with a low probably of problems.
4468 // fClassVersion is not an atomic and is modified TClass::SetClassVersion (called from RootClassVersion via
4469 // ROOT::ResetClassVersion) and is 'somewhat' protected by the atomic fVersionUsed.
4470 // However, direct access to fClassVersion should be replaced by calls to GetClassVersion to set fVersionUsed.
4471 // Even with such a change the code here and in these functions need to be reviewed as a cursory look seem
4472 // to indicates they are not yet properly protection against mutli-thread access.
4473 //
4474 // However, the use of these functions is rare and mostly done at library loading time which should
4475 // in almost all cases preceeds the possibility of GetStreamerInfo being called from multiple thread
4476 // on that same TClass object.
4477 //
4478 // Summary: need careful review but risk of problem is extremely low.
4479
4481
4482 // Warning: version may be -1 for an emulated class, or -2 if the
4483 // user requested the emulated streamerInfo for an abstract
4484 // base class, even though we have a dictionary for it.
4485
4486 if ((version < -1) || (version >= fStreamerInfo->GetSize())) {
4487 Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
4488 // FIXME: Shouldn't we go to -1 here, or better just abort?
4489 version = fClassVersion;
4490 }
4491
4492 sinfo = (TVirtualStreamerInfo *)fStreamerInfo->At(version);
4493
4494 if (!sinfo && (version != fClassVersion)) {
4495 // When the requested version does not exist we return
4496 // the TVirtualStreamerInfo for the currently loaded class version.
4497 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4498 // Note: This is done for STL collections
4499 // Note: fClassVersion could be -1 here (for an emulated class).
4500 // This is also the code path take for unversioned classes.
4502 }
4503
4504 if (!sinfo) {
4505 // We just were not able to find a streamer info, we have to make a new one.
4506 TMmallocDescTemp setreset;
4507 sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
4509 if (gDebug > 0) {
4510 printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
4511 }
4513 // If we do not have a StreamerInfo for this version and we do not
4514 // have dictionary information nor a proxy, there is nothing to build!
4515 sinfo->Build();
4516 }
4517 } else {
4518 if (!sinfo->IsCompiled()) {
4519 // Streamer info has not been compiled, but exists.
4520 // Therefore it was read in from a file and we have to do schema evolution?
4521 // Or it didn't have a dictionary before, but does now?
4522 sinfo->BuildOld();
4523 }
4524 }
4525
4526 // Cache the current info if we now have it.
4527 if (version == fClassVersion)
4528 fCurrentInfo = sinfo;
4529
4530 // If the compilation succeeded, remember this StreamerInfo.
4531 if (sinfo->IsCompiled())
4532 fLastReadInfo = sinfo;
4533
4534 return sinfo;
4535}
4536
4537////////////////////////////////////////////////////////////////////////////////
4538/// For the case where the requestor class is emulated and this class is abstract,
4539/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4540/// representation whether or not the class is loaded.
4541///
4542/// If the object does not exist, it is created
4543///
4544/// Note: There are two special version numbers:
4545///
4546/// - 0: Use the class version from the currently loaded class library.
4547/// - -1: Assume no class library loaded (emulated class).
4548///
4549/// Warning: If we create a new streamer info, whether or not the build
4550/// optimizes is controlled externally to us by a global variable!
4551/// Don't call us unless you have set that variable properly
4552/// with TStreamer::Optimize()!
4553///
4554
4556{
4557 TVirtualStreamerInfo *sinfo = nullptr;
4558
4559 TString newname(GetName());
4560 newname += "@@emulated";
4561
4563
4564 TClass *emulated = TClass::GetClass(newname);
4565
4566 if (emulated)
4567 sinfo = emulated->GetStreamerInfo(version);
4568
4569 if (!sinfo) {
4570 // The emulated version of the streamerInfo is explicitly requested and has
4571 // not been built yet.
4572
4573 sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
4574
4575 if (!sinfo && (version != fClassVersion)) {
4576 // When the requested version does not exist we return
4577 // the TVirtualStreamerInfo for the currently loaded class version.
4578 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4580 }
4581
4582 if (!sinfo) {
4583 // Let's take the first available StreamerInfo as a start
4584 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4585 for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4587 }
4588
4589 if (sinfo) {
4590 sinfo = dynamic_cast<TVirtualStreamerInfo *>(sinfo->Clone());
4591 if (sinfo) {
4592 sinfo->SetClass(0);
4593 sinfo->SetName(newname);
4594 sinfo->BuildCheck();
4595 sinfo->BuildOld();
4596 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4597 } else {
4598 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4599 }
4600 }
4601 }
4602 return sinfo;
4603}
4604
4605////////////////////////////////////////////////////////////////////////////////
4606/// For the case where the requestor class is emulated and this class is abstract,
4607/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4608/// representation whether or not the class is loaded.
4609///
4610/// If the object does not exist, it is created
4611///
4612/// Warning: If we create a new streamer info, whether or not the build
4613/// optimizes is controlled externally to us by a global variable!
4614/// Don't call us unless you have set that variable properly
4615/// with TStreamer::Optimize()!
4616///
4617
4619{
4620 TVirtualStreamerInfo *sinfo = nullptr;
4621
4622 TString newname(GetName());
4623 newname += "@@emulated";
4624
4626
4627 TClass *emulated = TClass::GetClass(newname);
4628
4629 if (emulated)
4630 sinfo = emulated->FindStreamerInfo(checksum);
4631
4632 if (!sinfo) {
4633 // The emulated version of the streamerInfo is explicitly requested and has
4634 // not been built yet.
4635
4636 sinfo = (TVirtualStreamerInfo*) FindStreamerInfo(checksum);
4637
4638 if (!sinfo && (checksum != fCheckSum)) {
4639 // When the requested version does not exist we return
4640 // the TVirtualStreamerInfo for the currently loaded class version.
4641 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4643 }
4644
4645 if (!sinfo) {
4646 // Let's take the first available StreamerInfo as a start
4647 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4648 for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4650 }
4651
4652 if (sinfo) {
4653 sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
4654 if (sinfo) {
4655 sinfo->SetClass(0);
4656 sinfo->SetName( newname );
4657 sinfo->BuildCheck();
4658 sinfo->BuildOld();
4659 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4660 } else {
4661 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4662 }
4663 }
4664 }
4665 return sinfo;
4666}
4667
4668////////////////////////////////////////////////////////////////////////////////
4669/// When the class kIgnoreTObjectStreamer bit is set, the automatically
4670/// generated Streamer will not call TObject::Streamer.
4671/// This option saves the TObject space overhead on the file.
4672/// However, the information (fBits, fUniqueID) of TObject is lost.
4673///
4674/// Note that to be effective for objects streamed object-wise this function
4675/// must be called for the class deriving directly from TObject, eg, assuming
4676/// that BigTrack derives from Track and Track derives from TObject, one must do:
4677/// ~~~ {.cpp}
4678/// Track::Class()->IgnoreTObjectStreamer();
4679/// ~~~
4680/// and not:
4681/// ~~~ {.cpp}
4682/// BigTrack::Class()->IgnoreTObjectStreamer();
4683/// ~~~
4684/// To be effective for object streamed member-wise or split in a TTree,
4685/// this function must be called for the most derived class (i.e. BigTrack).
4686
4688{
4689 // We need to tak the lock since we are test and then setting fBits
4690 // and TStreamerInfo::fBits (and the StreamerInfo state in general)
4691 // which can also be modified by another thread.
4693
4694 if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
4695 if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
4697 if (sinfo) {
4698 if (sinfo->IsCompiled()) {
4699 // -- Warn the user that what they are doing cannot work.
4700 // Note: The reason is that TVirtualStreamerInfo::Build() examines
4701 // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
4702 // type for the TObject base class streamer element it creates
4703 // to -1 as a flag. Later on the TStreamerInfo::Compile()
4704 // member function sees the flag and does not insert the base
4705 // class element into the compiled streamer info. None of this
4706 // machinery works correctly if we are called after the streamer
4707 // info has already been built and compiled.
4708 Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
4709 return;
4710 }
4711 }
4712 if (doIgnore) SetBit (kIgnoreTObjectStreamer);
4714}
4715
4716////////////////////////////////////////////////////////////////////////////////
4717/// Return kTRUE if this class inherits from a class with name "classname".
4718/// note that the function returns kTRUE in case classname is the class itself
4719
4720Bool_t TClass::InheritsFrom(const char *classname) const
4721{
4722 if (strcmp(GetName(), classname) == 0) return kTRUE;
4723
4724 return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
4725}
4726
4727////////////////////////////////////////////////////////////////////////////////
4728/// Return kTRUE if this class inherits from class cl.
4729/// note that the function returns KTRUE in case cl is the class itself
4730
4732{
4733 if (!cl) return kFALSE;
4734 if (cl == this) return kTRUE;
4735
4736 if (!HasDataMemberInfo()) {
4737 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
4738 if (sinfo==0) sinfo = GetStreamerInfo();
4739 TIter next(sinfo->GetElements());
4740 TStreamerElement *element;
4741 while ((element = (TStreamerElement*)next())) {
4742 if (element->IsA() == TStreamerBase::Class()) {
4743 TClass *clbase = element->GetClassPointer();
4744 if (!clbase) return kFALSE; //missing class
4745 if (clbase->InheritsFrom(cl)) return kTRUE;
4746 }
4747 }
4748 return kFALSE;
4749 }
4750 // cast const away (only for member fBase which can be set in GetListOfBases())
4751 if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
4752 return kFALSE;
4753}
4754
4755////////////////////////////////////////////////////////////////////////////////
4756/// Cast obj of this class type up to baseclass cl if up is true.
4757/// Cast obj of this class type down from baseclass cl if up is false.
4758/// If this class is not a baseclass of cl return 0, else the pointer
4759/// to the cl part of this (up) or to this (down).
4760
4761void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
4762{
4763 if (cl == this) return obj;
4764
4765 if (!HasDataMemberInfo()) return 0;
4766
4767 Int_t off;
4768 if ((off = GetBaseClassOffset(cl, obj)) != -1) {
4769 if (up)
4770 return (void*)((Long_t)obj+off);
4771 else
4772 return (void*)((Long_t)obj-off);
4773 }
4774 return 0;
4775}
4776
4777////////////////////////////////////////////////////////////////////////////////
4778/// Cast obj of this class type up to baseclass cl if up is true.
4779/// Cast obj of this class type down from baseclass cl if up is false.
4780/// If this class is not a baseclass of cl return 0, else the pointer
4781/// to the cl part of this (up) or to this (down).
4782
4783const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
4784{
4785 return DynamicCast(cl,const_cast<void*>(obj),up);
4786}
4787
4788////////////////////////////////////////////////////////////////////////////////
4789/// Return a pointer to a newly allocated object of this class.
4790/// The class must have a default constructor. For meaning of
4791/// defConstructor, see TClass::IsCallingNew().
4792///
4793/// If quiet is true, do no issue a message via Error on case
4794/// of problems, just return 0.
4795///
4796/// The constructor actually called here can be customized by
4797/// using the rootcint pragma:
4798/// ~~~ {.cpp}
4799/// #pragma link C++ ioctortype UserClass;
4800/// ~~~
4801/// For example, with this pragma and a class named MyClass,
4802/// this method will called the first of the following 3
4803/// constructors which exists and is public:
4804/// ~~~ {.cpp}
4805/// MyClass(UserClass*);
4806/// MyClass(TRootIOCtor*);
4807/// MyClass(); // Or a constructor with all its arguments defaulted.
4808/// ~~~
4809///
4810/// When more than one pragma ioctortype is used, the first seen as priority
4811/// For example with:
4812/// ~~~ {.cpp}
4813/// #pragma link C++ ioctortype UserClass1;
4814/// #pragma link C++ ioctortype UserClass2;
4815/// ~~~
4816/// We look in the following order:
4817/// ~~~ {.cpp}
4818/// MyClass(UserClass1*);
4819/// MyClass(UserClass2*);
4820/// MyClass(TRootIOCtor*);
4821/// MyClass(); // Or a constructor with all its arguments defaulted.
4822/// ~~~
4823
4824void *TClass::New(ENewType defConstructor, Bool_t quiet) const
4825{
4826 void* p = 0;
4827
4828 if (fNew) {
4829 // We have the new operator wrapper function,
4830 // so there is a dictionary and it was generated
4831 // by rootcint, so there should be a default
4832 // constructor we can call through the wrapper.
4833 TClass__GetCallingNew() = defConstructor;
4834 p = fNew(0);
4836 if (!p && !quiet) {
4837 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4838 Error("New", "cannot create object of class %s", GetName());
4839 }
4840 } else if (HasInterpreterInfo()) {
4841 // We have the dictionary but do not have the
4842 // constructor wrapper, so the dictionary was
4843 // not generated by rootcint. Let's try to
4844 // create the object by having the interpreter
4845 // call the new operator, hopefully the class
4846 // library is loaded and there will be a default
4847 // constructor we can call.
4848 // [This is very unlikely to work, but who knows!]
4849 TClass__GetCallingNew() = defConstructor;
4852 if (!p && !quiet) {
4853 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4854 Error("New", "cannot create object of class %s", GetName());
4855 }
4856 } else if (!HasInterpreterInfo() && fCollectionProxy) {
4857 // There is no dictionary at all, so this is an emulated
4858 // class; however we do have the services of a collection proxy,
4859 // so this is an emulated STL class.
4860 TClass__GetCallingNew() = defConstructor;
4861 p = fCollectionProxy->New();
4863 if (!p && !quiet) {
4864 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4865 Error("New", "cannot create object of class %s", GetName());
4866 }
4867 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4868 // There is no dictionary at all and we do not have
4869 // the services of a collection proxy available, so
4870 // use the streamer info to approximate calling a
4871 // constructor (basically we just make sure that the
4872 // pointer data members are null, unless they are marked
4873 // as preallocated with the "->" comment, in which case
4874 // we default-construct an object to point at).
4875
4876 // Do not register any TObject's that we create
4877 // as a result of creating this object.
4878 // FIXME: Why do we do this?
4879 // FIXME: Partial Answer: Is this because we may never actually deregister them???
4880
4881 Bool_t statsave = GetObjectStat();
4882 if(statsave) {
4884 }
4886 if (!sinfo && !quiet) {
4887 Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
4888 return 0;
4889 }
4890
4891 TClass__GetCallingNew() = defConstructor;
4892 p = sinfo->New();
4894
4895 // FIXME: Mistake? See note above at the GetObjectStat() call.
4896 // Allow TObject's to be registered again.
4897 if(statsave) {
4898 SetObjectStat(statsave);
4899 }
4900
4901 // Register the object for special handling in the destructor.
4902 if (p) {
4903 RegisterAddressInRepository("New",p,this);
4904 } else {
4905 Error("New", "Failed to construct class '%s' using streamer info", GetName());
4906 }
4907 } else {
4908 Fatal("New", "This cannot happen!");
4909 }
4910
4911 return p;
4912}
4913
4914////////////////////////////////////////////////////////////////////////////////
4915/// Return a pointer to a newly allocated object of this class.
4916/// The class must have a default constructor. For meaning of
4917/// defConstructor, see TClass::IsCallingNew().
4918
4919void *TClass::New(void *arena, ENewType defConstructor) const
4920{
4921 void* p = 0;
4922
4923 if (fNew) {
4924 // We have the new operator wrapper function,
4925 // so there is a dictionary and it was generated
4926 // by rootcint, so there should be a default
4927 // constructor we can call through the wrapper.
4928 TClass__GetCallingNew() = defConstructor;
4929 p = fNew(arena);
4931 if (!p) {
4932 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4933 }
4934 } else if (HasInterpreterInfo()) {
4935 // We have the dictionary but do not have the
4936 // constructor wrapper, so the dictionary was
4937 // not generated by rootcint. Let's try to
4938 // create the object by having the interpreter
4939 // call the new operator, hopefully the class
4940 // library is loaded and there will be a default
4941 // constructor we can call.
4942 // [This is very unlikely to work, but who knows!]
4943 TClass__GetCallingNew() = defConstructor;
4944 p = gCling->ClassInfo_New(GetClassInfo(),arena);
4946 if (!p) {
4947 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4948 }
4949 } else if (!HasInterpreterInfo() && fCollectionProxy) {
4950 // There is no dictionary at all, so this is an emulated
4951 // class; however we do have the services of a collection proxy,
4952 // so this is an emulated STL class.
4953 TClass__GetCallingNew() = defConstructor;
4954 p = fCollectionProxy->New(arena);
4956 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4957 // There is no dictionary at all and we do not have
4958 // the services of a collection proxy available, so
4959 // use the streamer info to approximate calling a
4960 // constructor (basically we just make sure that the
4961 // pointer data members are null, unless they are marked
4962 // as preallocated with the "->" comment, in which case
4963 // we default-construct an object to point at).
4964
4965 // ???BUG??? ???WHY???
4966 // Do not register any TObject's that we create
4967 // as a result of creating this object.
4968 Bool_t statsave = GetObjectStat();
4969 if(statsave) {
4971 }
4972
4974 if (!sinfo) {
4975 Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
4976 return 0;
4977 }
4978
4979 TClass__GetCallingNew() = defConstructor;
4980 p = sinfo->New(arena);
4982
4983 // ???BUG???
4984 // Allow TObject's to be registered again.
4985 if(statsave) {
4986 SetObjectStat(statsave);
4987 }
4988
4989 // Register the object for special handling in the destructor.
4990 if (p) {
4991 RegisterAddressInRepository("TClass::New with placement",p,this);
4992 }
4993 } else {
4994 Error("New with placement", "This cannot happen!");
4995 }
4996
4997 return p;
4998}
4999
5000////////////////////////////////////////////////////////////////////////////////
5001/// Return a pointer to a newly allocated array of objects
5002/// of this class.
5003/// The class must have a default constructor. For meaning of
5004/// defConstructor, see TClass::IsCallingNew().
5005
5006void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
5007{
5008 void* p = 0;
5009
5010 if (fNewArray) {
5011 // We have the new operator wrapper function,
5012 // so there is a dictionary and it was generated
5013 // by rootcint, so there should be a default
5014 // constructor we can call through the wrapper.
5015 TClass__GetCallingNew() = defConstructor;
5016 p = fNewArray(nElements, 0);
5018 if (!p) {
5019 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5020 }
5021 } else if (HasInterpreterInfo()) {
5022 // We have the dictionary but do not have the
5023 // constructor wrapper, so the dictionary was
5024 // not generated by rootcint. Let's try to
5025 // create the object by having the interpreter
5026 // call the new operator, hopefully the class
5027 // library is loaded and there will be a default
5028 // constructor we can call.
5029 // [This is very unlikely to work, but who knows!]
5030 TClass__GetCallingNew() = defConstructor;
5031 p = gCling->ClassInfo_New(GetClassInfo(),nElements);
5033 if (!p) {
5034 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5035 }
5036 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5037 // There is no dictionary at all, so this is an emulated
5038 // class; however we do have the services of a collection proxy,
5039 // so this is an emulated STL class.
5040 TClass__GetCallingNew() = defConstructor;
5041 p = fCollectionProxy->NewArray(nElements);
5043 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5044 // There is no dictionary at all and we do not have
5045 // the services of a collection proxy available, so
5046 // use the streamer info to approximate calling a
5047 // constructor (basically we just make sure that the
5048 // pointer data members are null, unless they are marked
5049 // as preallocated with the "->" comment, in which case
5050 // we default-construct an object to point at).
5051
5052 // ???BUG??? ???WHY???
5053 // Do not register any TObject's that we create
5054 // as a result of creating this object.
5055 Bool_t statsave = GetObjectStat();
5056 if(statsave) {
5058 }
5059
5061 if (!sinfo) {
5062 Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5063 return 0;
5064 }
5065
5066 TClass__GetCallingNew() = defConstructor;
5067 p = sinfo->NewArray(nElements);
5069
5070 // ???BUG???
5071 // Allow TObject's to be registered again.
5072 if(statsave) {
5073 SetObjectStat(statsave);
5074 }
5075
5076 // Register the object for special handling in the destructor.
5077 if (p) {
5078 RegisterAddressInRepository("TClass::NewArray",p,this);
5079 }
5080 } else {
5081 Error("NewArray", "This cannot happen!");
5082 }
5083
5084 return p;
5085}
5086
5087////////////////////////////////////////////////////////////////////////////////
5088/// Return a pointer to a newly allocated object of this class.
5089/// The class must have a default constructor. For meaning of
5090/// defConstructor, see TClass::IsCallingNew().
5091
5092void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
5093{
5094 void* p = 0;
5095
5096 if (fNewArray) {
5097 // We have the new operator wrapper function,
5098 // so there is a dictionary and it was generated
5099 // by rootcint, so there should be a default
5100 // constructor we can call through the wrapper.
5101 TClass__GetCallingNew() = defConstructor;
5102 p = fNewArray(nElements, arena);
5104 if (!p) {
5105 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5106 }
5107 } else if (HasInterpreterInfo()) {
5108 // We have the dictionary but do not have the constructor wrapper,
5109 // so the dictionary was not generated by rootcint (it was made either
5110 // by cint or by some external mechanism). Let's try to create the
5111 // object by having the interpreter call the new operator, either the
5112 // class library is loaded and there is a default constructor we can
5113 // call, or the class is interpreted and we will call the default
5114 // constructor that way, or no default constructor is available and
5115 // we fail.
5116 TClass__GetCallingNew() = defConstructor;
5117 p = gCling->ClassInfo_New(GetClassInfo(),nElements, arena);
5119 if (!p) {
5120 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5121 }
5122 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5123 // There is no dictionary at all, so this is an emulated
5124 // class; however we do have the services of a collection proxy,
5125 // so this is an emulated STL class.
5126 TClass__GetCallingNew() = defConstructor;
5127 p = fCollectionProxy->NewArray(nElements, arena);
5129 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5130 // There is no dictionary at all and we do not have
5131 // the services of a collection proxy available, so
5132 // use the streamer info to approximate calling a
5133 // constructor (basically we just make sure that the
5134 // pointer data members are null, unless they are marked
5135 // as preallocated with the "->" comment, in which case
5136 // we default-construct an object to point at).
5137
5138 // ???BUG??? ???WHY???
5139 // Do not register any TObject's that we create
5140 // as a result of creating this object.
5141 Bool_t statsave = GetObjectStat();
5142 if(statsave) {
5144 }
5145
5147 if (!sinfo) {
5148 Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5149 return 0;
5150 }
5151
5152 TClass__GetCallingNew() = defConstructor;
5153 p = sinfo->NewArray(nElements, arena);
5155
5156 // ???BUG???
5157 // Allow TObject's to be registered again.
5158 if(statsave) {
5159 SetObjectStat(statsave);
5160 }
5161
5163 // We always register emulated objects, we need to always
5164 // use the streamer info to destroy them.
5165 }
5166
5167 // Register the object for special handling in the destructor.
5168 if (p) {
5169 RegisterAddressInRepository("TClass::NewArray with placement",p,this);
5170 }
5171 } else {
5172 Error("NewArray with placement", "This cannot happen!");
5173 }
5174
5175 return p;
5176}
5177
5178////////////////////////////////////////////////////////////////////////////////
5179/// Explicitly call destructor for object.
5180
5181void TClass::Destructor(void *obj, Bool_t dtorOnly)
5182{
5183 // Do nothing if passed a null pointer.
5184 if (obj == 0) return;
5185
5186 void* p = obj;
5187
5188 if (dtorOnly && fDestructor) {
5189 // We have the destructor wrapper, use it.
5190 fDestructor(p);
5191 } else if ((!dtorOnly) && fDelete) {
5192 // We have the delete wrapper, use it.
5193 fDelete(p);
5194 } else if (HasInterpreterInfo()) {
5195 // We have the dictionary but do not have the
5196 // destruct/delete wrapper, so the dictionary was
5197 // not generated by rootcint (it could have been
5198 // created by cint or by some external mechanism).
5199 // Let's have the interpreter call the destructor,
5200 // either the code will be in a loaded library,
5201 // or it will be interpreted, otherwise we fail
5202 // because there is no destructor code at all.
5203 if (dtorOnly) {
5205 } else {
5207 }
5208 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5209 // There is no dictionary at all, so this is an emulated
5210 // class; however we do have the services of a collection proxy,
5211 // so this is an emulated STL class.
5212 fCollectionProxy->Destructor(p, dtorOnly);
5213 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5214 // There is no dictionary at all and we do not have
5215 // the services of a collection proxy available, so
5216 // use the streamer info to approximate calling a
5217 // destructor.
5218
5219 Bool_t inRepo = kTRUE;
5220 Bool_t verFound = kFALSE;
5221
5222 // Was this object allocated through TClass?
5223 std::multiset<Version_t> knownVersions;
5225
5226 {
5227 RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5228 if (iter == gObjectVersionRepository.end()) {
5229 // No, it wasn't, skip special version handling.
5230 //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
5231 inRepo = kFALSE;
5232 } else {
5233 //objVer = iter->second;
5234 for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5235 Version_t ver = iter->second.fVersion;
5236 knownVersions.insert(ver);
5237 if (ver == fClassVersion && this == iter->second.fClass) {
5238 verFound = kTRUE;
5239 }
5240 }
5241 }
5242 }
5243
5244 if (!inRepo || verFound) {
5245 // The object was allocated using code for the same class version
5246 // as is loaded now. We may proceed without worry.
5248 if (si) {
5249 si->Destructor(p, dtorOnly);
5250 } else {
5251 Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
5252 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5254 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5255 Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5256 if (fStreamerInfo->At(i) != 0) {
5257 Error("Destructor", "Doing Dump() ...");
5259 }
5260 }
5261 }
5262 } else {
5263 // The loaded class version is not the same as the version of the code
5264 // which was used to allocate this object. The best we can do is use
5265 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5266 Error("Destructor", "Loaded class %s version %d is not registered for addr %p", GetName(), fClassVersion, p);
5267#if 0
5269 if (si) {
5270 si->Destructor(p, dtorOnly);
5271 } else {
5272 Error("Destructor2", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
5273 Error("Destructor2", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5275 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5276 Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5277 if (fStreamerInfo->At(i) != 0) {
5278 // Do some debugging output.
5279 Error("Destructor2", "Doing Dump() ...");
5281 }
5282 }
5283 }
5284#endif
5285 }
5286
5287 if (inRepo && verFound && p) {
5288 UnregisterAddressInRepository("TClass::Destructor",p,this);
5289 }
5290 } else {
5291 Error("Destructor", "This cannot happen! (class %s)", GetName());
5292 }
5293}
5294
5295////////////////////////////////////////////////////////////////////////////////
5296/// Explicitly call operator delete[] for an array.
5297
5298void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
5299{
5300 // Do nothing if passed a null pointer.
5301 if (ary == 0) return;
5302
5303 // Make a copy of the address.
5304 void* p = ary;
5305
5306 if (fDeleteArray) {
5307 if (dtorOnly) {
5308 Error("DeleteArray", "Destructor only is not supported!");
5309 } else {
5310 // We have the array delete wrapper, use it.
5311 fDeleteArray(ary);
5312 }
5313 } else if (HasInterpreterInfo()) {
5314 // We have the dictionary but do not have the
5315 // array delete wrapper, so the dictionary was
5316 // not generated by rootcint. Let's try to
5317 // delete the array by having the interpreter
5318 // call the array delete operator, hopefully
5319 // the class library is loaded and there will be
5320 // a destructor we can call.
5321 gCling->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
5322 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5323 // There is no dictionary at all, so this is an emulated
5324 // class; however we do have the services of a collection proxy,
5325 // so this is an emulated STL class.
5326 fCollectionProxy->DeleteArray(ary, dtorOnly);
5327 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5328 // There is no dictionary at all and we do not have
5329 // the services of a collection proxy available, so
5330 // use the streamer info to approximate calling the
5331 // array destructor.
5332
5333 Bool_t inRepo = kTRUE;
5334 Bool_t verFound = kFALSE;
5335
5336 // Was this array object allocated through TClass?
5337 std::multiset<Version_t> knownVersions;
5338 {
5340 RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5341 if (iter == gObjectVersionRepository.end()) {
5342 // No, it wasn't, we cannot know what to do.
5343 //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
5344 inRepo = kFALSE;
5345 } else {
5346 for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5347 Version_t ver = iter->second.fVersion;
5348 knownVersions.insert(ver);
5349 if (ver == fClassVersion && this == iter->second.fClass ) {
5350 verFound = kTRUE;
5351 }
5352 }
5353 }
5354 }
5355
5356 if (!inRepo || verFound) {
5357 // The object was allocated using code for the same class version
5358 // as is loaded now. We may proceed without worry.
5360 if (si) {
5361 si->DeleteArray(ary, dtorOnly);
5362 } else {
5363 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
5364 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5366 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5367 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5368 if (fStreamerInfo->At(i)) {
5369 Error("DeleteArray", "Doing Dump() ...");
5371 }
5372 }
5373 }
5374 } else {
5375 // The loaded class version is not the same as the version of the code
5376 // which was used to allocate this array. The best we can do is use
5377 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5378 Error("DeleteArray", "Loaded class version %d is not registered for addr %p", fClassVersion, p);
5379
5380
5381
5382#if 0
5384 if (si) {
5385 si->DeleteArray(ary, dtorOnly);
5386 } else {
5387 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
5388 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5390 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5391 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5392 if (fStreamerInfo->At(i)) {
5393 // Print some debugging info.
5394 Error("DeleteArray", "Doing Dump() ...");
5396 }
5397 }
5398 }
5399#endif
5400
5401
5402 }
5403
5404 // Deregister the object for special handling in the destructor.
5405 if (inRepo && verFound && p) {
5406 UnregisterAddressInRepository("TClass::DeleteArray",p,this);
5407 }
5408 } else {
5409 Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
5410 }
5411}
5412
5413////////////////////////////////////////////////////////////////////////////////
5414/// Set the splitability of this class:
5415/// - -1: Use the default calculation
5416/// - 0: Disallow splitting
5417/// - 1: Always allow splitting.
5418/// - 2: Disallow splitting of the class and splitting of any it's derived classes.
5419
5421{
5422 fCanSplit = splitmode;
5423}
5424
5425////////////////////////////////////////////////////////////////////////////////
5426/// Private function. Set the class version for the 'class' represented by
5427/// this TClass object. See the public interface:
5428/// ROOT::ResetClassVersion
5429/// defined in TClassTable.cxx
5430///
5431/// Note on class version numbers:
5432/// - If no class number has been specified, TClass::GetVersion will return -1
5433/// - The Class Version 0 request the whole object to be transient
5434/// - The Class Version 1, unless specified via ClassDef indicates that the
5435/// I/O should use the TClass checksum to distinguish the layout of the class
5436
5438{
5439 fClassVersion = version;
5440 fCurrentInfo = 0;
5441}
5442
5443////////////////////////////////////////////////////////////////////////////////
5444/// Determine and set pointer to current TVirtualStreamerInfo
5445
5447{
5448 if(!fCurrentInfo.load()) {
5451 }
5452 return fCurrentInfo;
5453}
5454
5455////////////////////////////////////////////////////////////////////////////////
5456/// Set pointer to current TVirtualStreamerInfo
5457
5459{
5460 fCurrentInfo = info;
5461}
5462
5463////////////////////////////////////////////////////////////////////////////////
5464/// Return size of object of this class.
5465
5467{
5468 if (fSizeof!=-1) return fSizeof;
5471 return GetStreamerInfo()->GetSize();
5472}
5473
5474////////////////////////////////////////////////////////////////////////////////
5475/// Load class description from I/O buffer and return class object.
5476
5478{
5479 UInt_t maxsize = 256;
5480 char *s = new char[maxsize];
5481
5482 Int_t pos = b.Length();
5483
5484 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5485 while (strlen(s) == (maxsize - 1)) {
5486 // The classname is too large, try again with a large buffer.
5487 b.SetBufferOffset(pos);
5488 maxsize = 2*maxsize;
5489 delete [] s;
5490 s = new char[maxsize];
5491 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5492 }
5493
5495 if (!cl)
5496 ::Error("TClass::Load", "dictionary of class %s not found", s);
5497
5498 delete [] s;
5499 return cl;
5500}
5501
5502////////////////////////////////////////////////////////////////////////////////
5503/// Helper function used by TClass::GetClass().
5504/// This function attempts to load the dictionary for 'classname'
5505/// either from the TClassTable or from the list of generator.
5506/// If silent is 'true', do not warn about missing dictionary for the class.
5507/// (typically used for class that are used only for transient members)
5508///
5509/// The 'requestedname' is expected to be already normalized.
5510
5511TClass *TClass::LoadClass(const char *requestedname, Bool_t silent)
5512{
5513 // This function does not (and should not) attempt to check in the
5514 // list of loaded classes or in the typedef.
5515
5517
5518 TClass *result = LoadClassDefault(requestedname, silent);
5519
5520 if (result) return result;
5521 else return LoadClassCustom(requestedname,silent);
5522}
5523
5524////////////////////////////////////////////////////////////////////////////////
5525/// Helper function used by TClass::GetClass().
5526/// This function attempts to load the dictionary for 'classname' from
5527/// the TClassTable or the autoloader.
5528/// If silent is 'true', do not warn about missing dictionary for the class.
5529/// (typically used for class that are used only for transient members)
5530///
5531/// The 'requestedname' is expected to be already normalized.
5532
5533TClass *TClass::LoadClassDefault(const char *requestedname, Bool_t /* silent */)
5534{
5535 // This function does not (and should not) attempt to check in the
5536 // list of loaded classes or in the typedef.
5537
5538 DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
5539
5540 if (!dict) {
5541 if (gInterpreter->AutoLoad(requestedname,kTRUE)) {
5542 dict = TClassTable::GetDictNorm(requestedname);
5543 }
5544 }
5545
5546 if (dict) {
5547 TClass *ncl = (dict)();
5548 if (ncl) ncl->PostLoadCheck();
5549 return ncl;
5550 }
5551 return 0;
5552}
5553
5554////////////////////////////////////////////////////////////////////////////////
5555/// Helper function used by TClass::GetClass().
5556/// This function attempts to load the dictionary for 'classname'
5557/// from the list of generator.
5558/// If silent is 'true', do not warn about missing dictionary for the class.
5559/// (typically used for class that are used only for transient members)
5560///
5561/// The 'requestedname' is expected to be already normalized.
5562
5563TClass *TClass::LoadClassCustom(const char *requestedname, Bool_t silent)
5564{
5565 // This function does not (and should not) attempt to check in the
5566 // list of loaded classes or in the typedef.
5567
5568 TIter next(gROOT->GetListOfClassGenerators());
5569 TClassGenerator *gen;
5570 while ((gen = (TClassGenerator*) next())) {
5571 TClass *cl = gen->GetClass(requestedname, kTRUE, silent);
5572 if (cl) {
5573 cl->PostLoadCheck();
5574 return cl;
5575 }
5576 }
5577 return 0;
5578}
5579
5580////////////////////////////////////////////////////////////////////////////////
5581/// Try to load the ClassInfo if available. This function may require parsing
5582/// the header file and/or loading data from the clang pcm. If further calls to
5583/// this function cannot affect the value of fClassInfo, fCanLoadClassInfo is set
5584/// to false.
5585
5587{
5589
5590 // Return if another thread already loaded the info
5591 // while we were waiting for the lock
5592 if (!fCanLoadClassInfo)
5593 return;
5594
5595 bool autoParse = !gInterpreter->IsAutoParsingSuspended();
5596
5597 if (autoParse)
5598 gInterpreter->AutoParse(GetName());
5599
5600 if (!fClassInfo)
5601 gInterpreter->SetClassInfo(const_cast<TClass *>(this));
5602
5603 if (autoParse && !fClassInfo) {
5604 if (fImplFileLine == -1 && fClassVersion == 0) {
5605 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
5606 // information. Since it is transient, it is more than likely that the lack
5607 // will be harmles.
5608 } else {
5609 ::Error("TClass::LoadClassInfo", "no interpreter information for class %s is available"
5610 " even though it has a TClass initialization routine.",
5611 fName.Data());
5612 }
5613 return;
5614 }
5615
5616 fCanLoadClassInfo = false;
5617}
5618
5619////////////////////////////////////////////////////////////////////////////////
5620/// Store class description on I/O buffer.
5621
5623{
5624 b.WriteString(GetName());
5625}
5626
5627////////////////////////////////////////////////////////////////////////////////
5628/// Global function called by a class' static Dictionary() method
5629/// (see the ClassDef macro).
5630
5631TClass *ROOT::CreateClass(const char *cname, Version_t id,
5632 const std::type_info &info, TVirtualIsAProxy *isa,
5633 const char *dfil, const char *ifil,
5634 Int_t dl, Int_t il)
5635{
5636 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5637 // gets allocated on the heap and not in the mapped file.
5638 TMmallocDescTemp setreset;
5639 return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
5640}
5641
5642////////////////////////////////////////////////////////////////////////////////
5643/// Global function called by a class' static Dictionary() method
5644/// (see the ClassDef macro).
5645
5646TClass *ROOT::CreateClass(const char *cname, Version_t id,
5647 const char *dfil, const char *ifil,
5648 Int_t dl, Int_t il)
5649{
5650 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5651 // gets allocated on the heap and not in the mapped file.
5652 TMmallocDescTemp setreset;
5653 return new TClass(cname, id, dfil, ifil, dl, il);
5654}
5655
5656////////////////////////////////////////////////////////////////////////////////
5657/// Static method returning the defConstructor flag passed to TClass::New().
5658/// New type is either:
5659/// - TClass::kRealNew - when called via plain new
5660/// - TClass::kClassNew - when called via TClass::New()
5661/// - TClass::kDummyNew - when called via TClass::New() but object is a dummy,
5662/// in which case the object ctor might take short cuts
5663
5665{
5666 return TClass__GetCallingNew();
5667}
5668
5669////////////////////////////////////////////////////////////////////////////////
5670/// Return true if the shared library of this class is currently in the a
5671/// process's memory. Return false, after the shared library has been
5672/// unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
5673
5675{
5676 return fState == kHasTClassInit;
5677}
5678
5679////////////////////////////////////////////////////////////////////////////////
5680/// Returns true if this class inherits from TObject and if the start of
5681/// the TObject parts is at the very beginning of the objects.
5682/// Concretely this means that the following code is proper for this class:
5683/// ~~~ {.cpp}
5684/// ThisClass *ptr;
5685/// void *void_ptr = (void)ptr;
5686/// TObject *obj = (TObject*)void_ptr;
5687/// ~~~
5688/// This code would be wrong if 'ThisClass' did not inherit 'first' from
5689/// TObject.
5690
5692{
5693 if (fProperty==(-1)) Property();
5694 return TestBit(kStartWithTObject);
5695}
5696
5697////////////////////////////////////////////////////////////////////////////////
5698/// Return kTRUE is the class inherits from TObject.
5699
5701{
5702 if (fProperty==(-1)) Property();
5703 return TestBit(kIsTObject);
5704}
5705
5706////////////////////////////////////////////////////////////////////////////////
5707/// Return kTRUE is the class is Foreign (the class does not have a Streamer method).
5708
5710{
5711 if (fProperty==(-1)) Property();
5712 return TestBit(kIsForeign);
5713}
5714
5715////////////////////////////////////////////////////////////////////////////////
5716/// Do the initialization that can only be done after the CINT dictionary has
5717/// been fully populated and can not be delayed efficiently.
5718
5720{
5721 // In the case of a Foreign class (loaded class without a Streamer function)
5722 // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
5723 // be confused with a previously loaded streamerInfo.
5724
5725 if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 /*&& fStreamerInfo
5726 && fStreamerInfo->At(1)*/ && IsForeign() )
5727 {
5728 SetClassVersion(-1);
5729 }
5730 // Note: We are careful to check the class version first because checking
5731 // for foreign can trigger an AutoParse.
5732 else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && ((fClassVersion > 1) || !IsForeign()))
5733 {
5735
5737 // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
5738 // loaded from a file) is consistent with the definition in the library we just loaded.
5739 // BuildCheck is not appropriate here since it check a streamerinfo against the
5740 // 'current streamerinfo' which, at time point, would be the same as 'info'!
5741 if (info && GetListOfDataMembers() && !GetCollectionProxy()
5742 && (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,0,kFALSE,kFALSE, 0) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
5743 {
5744 Bool_t warn = ! TestBit(kWarned);
5745 if (warn && info->GetOldVersion()<=2) {
5746 // Names of STL base classes was modified in vers==3. Allocators removed
5747 //
5748 TIter nextBC(GetListOfBases());
5749 TBaseClass *bc;
5750 while ((bc=(TBaseClass*)nextBC()))
5751 {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
5752 }
5753
5754 if (warn) {
5755 if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
5756 Warning("PostLoadCheck","\n\
5757 The class %s transitioned from not having a specified class version\n\
5758 to having a specified class version (the current class version is %d).\n\
5759 However too many different non-versioned layouts of the class have\n\
5760 already been loaded so far. To work around this problem you can\n\
5761 load fewer 'old' file in the same ROOT session or load the C++ library\n\
5762 describing the class %s before opening the files or increase the version\n\
5763 number of the class for example ClassDef(%s,%d).\n\
5764 Do not try to write objects with the current class definition,\n\
5765 the files might not be readable.\n",
5767 } else {
5768 Warning("PostLoadCheck","\n\
5769 The StreamerInfo version %d for the class %s which was read\n\
5770 from a file previously opened has the same version as the active class\n\
5771 but a different checksum. You should update the version to ClassDef(%s,%d).\n\
5772 Do not try to write objects with the current class definition,\n\
5773 the files will not be readable.\n"
5775 }
5776 info->CompareContent(this,0,kTRUE,kTRUE,0);
5777 SetBit(kWarned);
5778 }
5779 }
5780 }
5781}
5782
5783////////////////////////////////////////////////////////////////////////////////
5784/// Set TObject::fBits and fStreamerType to cache information about the
5785/// class. The bits are
5786/// ~~~ {.cpp}
5787/// kIsTObject : the class inherits from TObject
5788/// kStartWithTObject: TObject is the left-most class in the inheritance tree
5789/// kIsForeign : the class doe not have a Streamer method
5790/// ~~~
5791/// The value of fStreamerType are
5792/// ~~~ {.cpp}
5793/// kTObject : the class inherits from TObject
5794/// kForeign : the class does not have a Streamer method
5795/// kInstrumented: the class does have a Streamer method
5796/// kExternal: the class has a free standing way of streaming itself
5797/// kEmulatedStreamer: the class is missing its shared library.
5798/// ~~~
5799
5801{
5802 // Check if we can return without taking the lock,
5803 // this is valid since fProperty is atomic and set as
5804 // the last operation before return.
5805 if (fProperty!=(-1)) return fProperty;
5806
5808
5809 // Check if another thread set fProperty while we
5810 // were waiting.
5811 if (fProperty!=(-1)) return fProperty;
5812
5813 // Avoid asking about the class when it is still building
5814 if (TestBit(kLoading)) return fProperty;
5815
5816 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5817 // gets allocated on the heap and not in the mapped file.
5818 TMmallocDescTemp setreset;
5819
5820 TClass *kl = const_cast<TClass*>(this);
5821
5824
5826 kl->SetBit(kIsTObject);
5827
5828 // Is it DIRECT inheritance from TObject?
5830 if (delta==0) kl->SetBit(kStartWithTObject);
5831
5832 kl->fStreamerType = kTObject;
5834 }
5835
5836 if (HasInterpreterInfo()) {
5837
5838 // This code used to use ClassInfo_Has|IsValidMethod but since v6
5839 // they return true if the routine is defined in the class or any of
5840 // its parent. We explicitly want to know whether the function is
5841 // defined locally.
5842 if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
5843
5844 kl->SetBit(kIsForeign);
5845 kl->fStreamerType = kForeign;
5847
5848 } else if ( kl->fStreamerType == TClass::kDefault ) {
5849 if (kl->fConvStreamerFunc) {
5852 } else if (kl->fStreamerFunc) {
5855 } else {
5856 // We have an automatic streamer using the StreamerInfo .. no need to go through the
5857 // Streamer method function itself.
5860 }
5861 }
5862
5863 if (fStreamer) {
5866 }
5867
5868 if (const_cast<TClass *>(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) {
5870 }
5871
5872 if (GetClassInfo()) {
5873 // In the case where the TClass for one of ROOT's core class
5874 // (eg TClonesArray for map<int,TClonesArray*>) is requested
5875 // during the execution of rootcling, we could end up in a situation
5876 // where we should have the information (since TClonesArray has
5877 // a dictionary as part of libCore) but do not because the user
5878 // only include a forward declaration of TClonesArray and we do not
5879 // forcefully load the header file either (because the autoparsing
5880 // is intentionally disabled).
5882 // Must set this last since other threads may read fProperty
5883 // and think all test bits have been properly set.
5885 }
5886 } else {
5887
5888 if (fStreamer) {
5891 }
5892
5894 kl->SetStreamerImpl();
5895 // fProperty was *not* set so that it can be forced to be recalculated
5896 // next time.
5897 return 0;
5898 }
5899
5900 return fProperty;
5901}
5902
5903////////////////////////////////////////////////////////////////////////////////
5904/// Internal routine to set calculate the class properties that can only be
5905/// known at run-time, for example whether the Hash member function and the
5906/// destructor are consistent.
5907
5909{
5910 // For now, no need to lock this routines as fRuntimeProperties is
5911 // the only atomic set here and this is done at the end
5912 // and there is no downside if the execution is done twice.
5913
5914 // Note SetRuntimeProperties is set to const as it is technically
5915 // thread-safe.
5916
5917 UChar_t properties = static_cast<UChar_t>(ERuntimeProperties::kSet);
5918
5920 properties |= static_cast<UChar_t>(ERuntimeProperties::kConsistentHash);
5921
5922 const_cast<TClass *>(this)->fRuntimeProperties = properties;
5923}
5924
5925////////////////////////////////////////////////////////////////////////////////
5926/// Internal routine to set fStreamerImpl based on the value of
5927/// fStreamerType.
5928
5930{
5931 switch (fStreamerType) {
5935 case kInstrumented: {
5939 break;
5940 }
5941
5942 case kEmulatedStreamer: // intentional fall through
5943 case kForeign|kEmulatedStreamer: // intentional fall through
5948 default:
5949 Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
5950 }
5951}
5952
5953
5954////////////////////////////////////////////////////////////////////////////////
5955/// Create the collection proxy object (and the streamer object) from
5956/// using the information in the TCollectionProxyInfo.
5957
5959{
5961
5962 delete fCollectionProxy;
5963
5964 // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
5965 // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
5966 // set correctly.
5967
5969 fCollectionProxy = p;
5970
5971 AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
5972
5974 // Numeric Collections have implicit conversions:
5976 }
5977 fCanSplit = -1;
5978}
5979
5980////////////////////////////////////////////////////////////////////////////////
5981/// Change (i.e. set) the title of the TNamed.
5982
5983void TClass::SetContextMenuTitle(const char *title)
5984{
5985 fContextMenuTitle = title;
5986}
5987
5988////////////////////////////////////////////////////////////////////////////////
5989/// This function installs a global IsA function for this class.
5990/// The global IsA function will be used if there is no local IsA function (fIsA)
5991///
5992/// A global IsA function has the signature:
5993///
5994/// ~~~ {.cpp}
5995/// TClass *func( TClass *cl, const void *obj);
5996/// ~~~
5997///
5998/// 'cl' is a pointer to the TClass object that corresponds to the
5999/// 'pointer type' used to retrieve the value 'obj'
6000///
6001/// For example with:
6002/// ~~~ {.cpp}
6003/// TNamed * m = new TNamed("example","test");
6004/// TObject* o = m
6005/// ~~~
6006/// and
6007/// the global IsA function would be called with TObject::Class() as
6008/// the first parameter and the exact numerical value in the pointer
6009/// 'o'.
6010///
6011/// In other word, inside the global IsA function. it is safe to C-style
6012/// cast the value of 'obj' into a pointer to the class described by 'cl'.
6013
6015{
6016 fGlobalIsA = func;
6017}
6018
6019////////////////////////////////////////////////////////////////////////////////
6020/// Call this method to indicate that the shared library containing this
6021/// class's code has been removed (unloaded) from the process's memory
6022
6024{
6025 if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
6026 // Don't redo the work.
6027 return;
6028 }
6030
6031 //R__ASSERT(fState == kLoaded);
6032 if (fState != kLoaded) {
6033 Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
6034 GetName(),(int)fState);
6035 }
6036
6037 // Make sure SetClassInfo, re-calculated the state.
6039
6040 delete fIsA; fIsA = 0;
6041 // Disable the autoloader while calling SetClassInfo, to prevent
6042 // the library from being reloaded!
6043 {
6044 int autoload_old = gCling->SetClassAutoloading(0);
6046
6047 gInterpreter->SetClassInfo(this,kTRUE);
6048
6049 gCling->SetClassAutoloading(autoload_old);
6050 }
6051 fDeclFileName = 0;
6052 fDeclFileLine = 0;
6053 fImplFileName = 0;
6054 fImplFileLine = 0;
6055 fTypeInfo = 0;
6056
6057 if (fMethod.load()) {
6058 (*fMethod).Unload();
6059 }
6060 if (fData) {
6061 fData->Unload();
6062 }
6063 if (fEnums.load()) {
6064 (*fEnums).Unload();
6065 }
6066
6067 if (fState <= kForwardDeclared && fStreamerInfo->GetEntries() != 0) {
6068 fState = kEmulated;
6069 }
6070
6073}
6074
6075////////////////////////////////////////////////////////////////////////////////
6076/// Info is a string describing the names and types of attributes
6077/// written by the class Streamer function.
6078/// If info is an empty string (when called by TObject::StreamerInfo)
6079/// the default Streamer info string is build. This corresponds to
6080/// the case of an automatically generated Streamer.
6081/// In case of user defined Streamer function, it is the user responsibility
6082/// to implement a StreamerInfo function (override TObject::StreamerInfo).
6083/// The user must call IsA()->SetStreamerInfo(info) from this function.
6084
6085TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
6086{
6087 // info is specified, nothing to do, except that we should verify
6088 // that it contains a valid descriptor.
6089
6090/*
6091 TDataMember *dm;
6092 Int_t nch = strlen(info);
6093 Bool_t update = kTRUE;
6094 if (nch != 0) {
6095 //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
6096 char *save, *temp, *blank, *colon, *comma;
6097 save = new char[10000];
6098 temp = save;
6099 strlcpy(temp,info,10000);
6100 //remove heading and trailing blanks
6101 while (*temp == ' ') temp++;
6102 while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
6103 if (nch == 0) {delete [] save; return;}
6104 if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
6105 //remove blanks around , or ;
6106 while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
6107 while ((blank = strstr(temp," ;"))) strcpy(blank, blank+1);
6108 while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
6109 while ((blank = strstr(temp," ,"))) strcpy(blank, blank+1);
6110 while ((blank = strstr(temp," "))) strcpy(blank, blank+1);
6111 //loop on tokens separated by ;
6112 char *final = new char[1000];
6113 char token[100];
6114 while ((colon=strchr(temp,';'))) {
6115 *colon = 0;
6116 strlcpy(token,temp,100);
6117 blank = strchr(token,' ');
6118 if (blank) {
6119 *blank = 0;
6120 if (!gROOT->GetType(token)) {
6121 Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
6122 return;
6123 }
6124 while (blank) {
6125 strlcat(final,token,1000);
6126 strlcat(final," ",1000);
6127 comma = strchr(blank+1,','); if (comma) *comma=0;
6128 strlcat(final,blank+1,1000);
6129 strlcat(final,";",1000);
6130 blank = comma;
6131 }
6132
6133 } else {
6134 if (TClass::GetClass(token,update)) {
6135 //a class name
6136 strlcat(final,token,1000); strlcat(final,";",1000);
6137 } else {
6138 //a data member name
6139 dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
6140 if (dm) {
6141 strlcat(final,dm->GetFullTypeName(),1000);
6142 strlcat(final," ",1000);
6143 strlcat(final,token,1000); strlcat(final,";",1000);
6144 } else {
6145 Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
6146 return;
6147 }
6148 }
6149 update = kFALSE;
6150 }
6151 temp = colon+1;
6152 if (*temp == 0) break;
6153 }
6154 //// fStreamerInfo = final;
6155 delete [] final;
6156 delete [] save;
6157 return;
6158 }
6159
6160 //info is empty. Let's build the default Streamer descriptor
6161
6162 char *temp = new char[10000];
6163 temp[0] = 0;
6164 char local[100];
6165
6166 //add list of base classes
6167 TIter nextb(GetListOfBases());
6168 TBaseClass *base;
6169 while ((base = (TBaseClass*) nextb())) {
6170 snprintf(local,100,"%s;",base->GetName());
6171 strlcat(temp,local,10000);
6172 }
6173
6174 //add list of data members and types
6175 TIter nextd(GetListOfDataMembers());
6176 while ((dm = (TDataMember *) nextd())) {
6177 if (dm->IsEnum()) continue;
6178 if (!dm->IsPersistent()) continue;
6179 Long_t property = dm->Property();
6180 if (property & kIsStatic) continue;
6181 TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
6182 update = kFALSE;
6183 if (acl) {
6184 if (acl->GetClassVersion() == 0) continue;
6185 }
6186
6187 // dm->GetArrayIndex() returns an empty string if it does not
6188 // applies
6189 const char * index = dm->GetArrayIndex();
6190 if (strlen(index)==0)
6191 snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
6192 else
6193 snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
6194 strlcat(temp,local,10000);
6195 }
6196 //fStreamerInfo = temp;
6197 delete [] temp;
6198*/
6199 return 0;
6200}
6201
6202////////////////////////////////////////////////////////////////////////////////
6203/// Return true if the checksum passed as argument is one of the checksum
6204/// value produced by the older checksum calculation algorithm.
6205
6207{
6208 for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
6209 if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
6210 }
6211 return kFALSE;
6212}
6213
6214////////////////////////////////////////////////////////////////////////////////
6215/// Call GetCheckSum with validity check.
6216
6218{
6219 bool isvalid;
6220 return GetCheckSum(code,isvalid);
6221}
6222
6223////////////////////////////////////////////////////////////////////////////////
6224/// Return GetCheckSum(kCurrentCheckSum,isvalid);
6225
6227{
6228 return GetCheckSum(kCurrentCheckSum,isvalid);
6229}
6230
6231////////////////////////////////////////////////////////////////////////////////
6232/// Compute and/or return the class check sum.
6233///
6234/// isvalid is set to false, if the function is unable to calculate the
6235/// checksum.
6236///
6237/// The class ckecksum is used by the automatic schema evolution algorithm
6238/// to uniquely identify a class version.
6239/// The check sum is built from the names/types of base classes and
6240/// data members.
6241/// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
6242///
6243/// The valid range of code is determined by ECheckSum.
6244///
6245/// - kNoEnum: data members of type enum are not counted in the checksum
6246/// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
6247/// - kWithTypeDef: use the sugared type name in the calculation.
6248///
6249/// This is needed for backward compatibility.
6250///
6251/// WARNING: this function must be kept in sync with TStreamerInfo::GetCheckSum.
6252/// They are both used to handle backward compatibility and should both return the same values.
6253/// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
6254/// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
6255
6257{
6258 // fCheckSum is an atomic variable. Also once it has
6259 // transition from a zero Value it never changes. If two
6260 // thread reach past this if statement and calculated the
6261 // 'kLastestCheckSum', they will by definition obtain the
6262 // same value, so technically we could simply have:
6263 // if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
6264 // However save a little bit of barrier time by calling load()
6265 // only once.
6266
6267 isvalid = kTRUE;
6268
6269 UInt_t currentChecksum = fCheckSum.load();
6270 if (currentChecksum && code == kCurrentCheckSum) return currentChecksum;
6271
6273
6274 // kCurrentCheckSum (0) is the default parameter value and should be kept
6275 // for backward compatibility, too be able to use the inequality checks,
6276 // we need to set the code to the largest value.
6277 if (code == kCurrentCheckSum) code = kLatestCheckSum;
6278
6279 UInt_t id = 0;
6280
6281 int il;
6282 TString name = GetName();
6283 TString type;
6284 il = name.Length();
6285 for (int i=0; i<il; i++) id = id*3+name[i];
6286
6287 // Here we skip he base classes in case this is a pair or STL collection,
6288 // otherwise, on some STL implementations, it can happen that pair has
6289 // base classes which are an internal implementation detail.
6290 TList *tlb = ((TClass*)this)->GetListOfBases();
6291 if (tlb && !GetCollectionProxy() && strncmp(GetName(), "pair<", 5)) {
6292 // Loop over bases if not a proxied collection or a pair
6293
6294 TIter nextBase(tlb);
6295
6296 TBaseClass *tbc=0;
6297 while((tbc=(TBaseClass*)nextBase())) {
6298 name = tbc->GetName();
6300 if (isSTL)
6302 il = name.Length();
6303 for (int i=0; i<il; i++) id = id*3+name[i];
6304 if (code > kNoBaseCheckSum && !isSTL) {
6305 if (tbc->GetClassPointer() == 0) {
6306 Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
6307 GetName(),tbc->GetName());
6308 isvalid = kFALSE;
6309 return 0;
6310 } else
6311 id = id*3 + tbc->GetClassPointer()->GetCheckSum();
6312 }
6313 }/*EndBaseLoop*/
6314 }
6315 TList *tlm = ((TClass*)this)->GetListOfDataMembers();
6316 if (tlm) { // Loop over members
6317 TIter nextMemb(tlm);
6318 TDataMember *tdm=0;
6319 Long_t prop = 0;
6320 while((tdm=(TDataMember*)nextMemb())) {
6321 if (!tdm->IsPersistent()) continue;
6322 // combine properties
6323 prop = (tdm->Property());
6324 TDataType* tdt = tdm->GetDataType();
6325 if (tdt) prop |= tdt->Property();
6326
6327 if ( prop&kIsStatic) continue;
6328 name = tdm->GetName(); il = name.Length();
6329 if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
6330 id = id*3 + 1;
6331
6332 int i;
6333 for (i=0; i<il; i++) id = id*3+name[i];
6334
6335 if (code > kWithTypeDef || code == kReflexNoComment) {
6336 type = tdm->GetTrueTypeName();
6337 // GetTrueTypeName uses GetFullyQualifiedName which already drops
6338 // the default template parameter, so we no longer need to do this.
6339 //if (TClassEdit::IsSTLCont(type))
6340 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6341 if (code == kReflex || code == kReflexNoComment) {
6342 if (prop&kIsEnum) {
6343 type = "int";
6344 } else {
6345 type.ReplaceAll("ULong64_t","unsigned long long");
6346 type.ReplaceAll("Long64_t","long long");
6347 type.ReplaceAll("<signed char","<char");
6348 type.ReplaceAll(",signed char",",char");
6349 if (type=="signed char") type = "char";
6350 }
6351 }
6352 } else {
6353 type = tdm->GetFullTypeName();
6354 // GetFullTypeName uses GetFullyQualifiedName which already drops
6355 // the default template parameter, so we no longer need to do this.
6356 //if (TClassEdit::IsSTLCont(type))
6357 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6358 }
6359
6360 il = type.Length();
6361 for (i=0; i<il; i++) id = id*3+type[i];
6362
6363 int dim = tdm->GetArrayDim();
6364 if (prop&kIsArray) {
6365 for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
6366 }
6367 if (code > kNoRange) {
6368 const char *left;
6369 if (code > TClass::kNoRangeCheck)
6371 else
6372 left = strstr(tdm->GetTitle(),"[");
6373 if (left) {
6374 const char *right = strstr(left,"]");
6375 if (right) {
6376 ++left;
6377 while (left != right) {
6378 id = id*3 + *left;
6379 ++left;
6380 }
6381 }
6382 }
6383 }
6384 }/*EndMembLoop*/
6385 }
6386 // This should be moved to Initialization time however the last time
6387 // we tried this cause problem, in particular in the end-of-process operation.
6388 if (code==kLatestCheckSum) fCheckSum = id;
6389 return id;
6390}
6391
6392////////////////////////////////////////////////////////////////////////////////
6393/// Adopt the Reference proxy pointer to indicate that this class
6394/// represents a reference.
6395/// When a new proxy is adopted, the old one is deleted.
6396
6398{
6400
6401 if ( fRefProxy ) {
6402 fRefProxy->Release();
6403 }
6404 fRefProxy = proxy;
6405 if ( fRefProxy ) {
6406 fRefProxy->SetClass(this);
6407 }
6408 fCanSplit = -1;
6409}
6410
6411////////////////////////////////////////////////////////////////////////////////
6412/// Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
6413/// member name.
6414
6416{
6417 if (!fRealData) return;
6418
6420
6421 TIter next(fRealData);
6422 TRealData *rd;
6423 while ((rd = (TRealData*)next())) {
6424 if (strcmp(rd->GetName(),name) == 0) {
6425 // If there is a TStreamerElement that took a pointer to the
6426 // streamer we should inform it!
6427 rd->AdoptStreamer(p);
6428 break;
6429 }
6430 }
6431
6432// NOTE: This alternative was proposed but not is not used for now,
6433// One of the major difference with the code above is that the code below
6434// did not require the RealData to have been built
6435// if (!fData) return;
6436// const char *n = name;
6437// while (*n=='*') n++;
6438// TString ts(n);
6439// int i = ts.Index("[");
6440// if (i>=0) ts.Remove(i,999);
6441// TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
6442// if (!dm) {
6443// Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
6444// return;
6445// }
6446// dm->SetStreamer(p);
6447 return;
6448}
6449
6450////////////////////////////////////////////////////////////////////////////////
6451/// Install a new member streamer (p will be copied).
6452
6454{
6456}
6457
6458////////////////////////////////////////////////////////////////////////////////
6459/// Function called by the Streamer functions to deserialize information
6460/// from buffer b into object at p.
6461/// This function assumes that the class version and the byte count information
6462/// have been read.
6463/// - version is the version number of the class
6464/// - start is the starting position in the buffer b
6465/// - count is the number of bytes for this object in the buffer
6466
6467Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
6468{
6469 return b.ReadClassBuffer(this,pointer,version,start,count);
6470}
6471
6472////////////////////////////////////////////////////////////////////////////////
6473/// Function called by the Streamer functions to deserialize information
6474/// from buffer b into object at p.
6475
6477{
6478 return b.ReadClassBuffer(this,pointer);
6479}
6480
6481////////////////////////////////////////////////////////////////////////////////
6482/// Function called by the Streamer functions to serialize object at p
6483/// to buffer b. The optional argument info may be specified to give an
6484/// alternative StreamerInfo instead of using the default StreamerInfo
6485/// automatically built from the class definition.
6486/// For more information, see class TVirtualStreamerInfo.
6487
6488Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
6489{
6490 b.WriteClassBuffer(this,pointer);
6491 return 0;
6492}
6493
6494////////////////////////////////////////////////////////////////////////////////
6495///There is special streamer for the class
6496
6497void TClass::StreamerExternal(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6498{
6499 // case kExternal:
6500 // case kExternal|kEmulatedStreamer:
6501
6502 TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
6503 streamer->Stream(b,object,onfile_class);
6504}
6505
6506////////////////////////////////////////////////////////////////////////////////
6507/// Case of TObjects
6508
6509void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6510{
6511 // case kTObject:
6512
6513 if (!pThis->fIsOffsetStreamerSet) {
6514 pThis->CalculateStreamerOffset();
6515 }
6516 TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6517 tobj->Streamer(b);
6518}
6519
6520////////////////////////////////////////////////////////////////////////////////
6521/// Case of TObjects when fIsOffsetStreamerSet is known to have been set.
6522
6523void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6524{
6525 TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6526 tobj->Streamer(b);
6527}
6528
6529////////////////////////////////////////////////////////////////////////////////
6530/// Case of TObjects when we do not have the library defining the class.
6531
6532void TClass::StreamerTObjectEmulated(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6533{
6534 // case kTObject|kEmulatedStreamer :
6535 if (b.IsReading()) {
6536 b.ReadClassEmulated(pThis, object, onfile_class);
6537 } else {
6538 b.WriteClassBuffer(pThis, object);
6539 }
6540}
6541
6542////////////////////////////////////////////////////////////////////////////////
6543/// Case of instrumented class with a library
6544
6545void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6546{
6547 // case kInstrumented:
6548 pThis->fStreamerFunc(b,object);
6549}
6550
6551////////////////////////////////////////////////////////////////////////////////
6552/// Case of instrumented class with a library
6553
6554void TClass::ConvStreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6555{
6556 // case kInstrumented:
6557 pThis->fConvStreamerFunc(b,object,onfile_class);
6558}
6559
6560////////////////////////////////////////////////////////////////////////////////
6561/// Case of where we should directly use the StreamerInfo.
6562/// - case kForeign:
6563/// - case kForeign|kEmulatedStreamer:
6564/// - case kInstrumented|kEmulatedStreamer:
6565/// - case kEmulatedStreamer:
6566
6567void TClass::StreamerStreamerInfo(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6568{
6569 if (b.IsReading()) {
6570 b.ReadClassBuffer(pThis, object, onfile_class);
6571 //ReadBuffer (b, object);
6572 } else {
6573 //WriteBuffer(b, object);
6574 b.WriteClassBuffer(pThis, object);
6575 }
6576}
6577
6578////////////////////////////////////////////////////////////////////////////////
6579/// Default streaming in cases where either we have no way to know what to do
6580/// or if Property() has not yet been called.
6581
6582void TClass::StreamerDefault(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6583{
6584 if (pThis->fProperty==(-1)) {
6585 pThis->Property();
6586 }
6587
6588 // We could get here because after this thread started StreamerDefault
6589 // *and* before check fProperty, another thread might have call Property
6590 // and this fProperty when we read it, is not -1 and fStreamerImpl is
6591 // supposed to be set properly (no longer pointing to the default).
6592 if (pThis->fStreamerImpl.load() == &TClass::StreamerDefault) {
6593 pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
6594 } else {
6595 (*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
6596 }
6597}
6598
6599////////////////////////////////////////////////////////////////////////////////
6600/// Adopt a TClassStreamer object. Ownership is transfered to this TClass
6601/// object.
6602
6604{
6605// // This code can be used to quickly test the STL Emulation layer
6606// Int_t k = TClassEdit::IsSTLCont(GetName());
6607// if (k==1||k==-1) { delete str; return; }
6608
6610
6611 if (fStreamer) delete fStreamer;
6612 if (str) {
6614 fStreamer = str;
6616 } else if (fStreamer) {
6617 // Case where there was a custom streamer and it is hereby removed,
6618 // we need to reset fStreamerType
6619 fStreamer = str;
6621 if (fProperty != -1) {
6622 fProperty = -1;
6623 Property();
6624 }
6625 }
6626}
6627
6628////////////////////////////////////////////////////////////////////////////////
6629/// Set a wrapper/accessor function around this class custom streamer.
6630
6632{
6634 if (fProperty != -1 && !fConvStreamerFunc &&
6635 ( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) )
6636 {
6637 fStreamerFunc = strm;
6638
6639 // Since initialization has already been done, make sure to tweak it
6640 // for the new state.
6644 }
6645 } else {
6646 fStreamerFunc = strm;
6647 }
6648 fCanSplit = -1;
6649}
6650
6651////////////////////////////////////////////////////////////////////////////////
6652/// Set a wrapper/accessor function around this class custom conversion streamer.
6653
6655{
6657 if (fProperty != -1 &&
6658 ( (fConvStreamerFunc == 0 && strm != 0) || (fConvStreamerFunc != 0 && strm == 0) ) )
6659 {
6660 fConvStreamerFunc = strm;
6661
6662 // Since initialization has already been done, make sure to tweak it
6663 // for the new state.
6667 }
6668 } else {
6669 fConvStreamerFunc = strm;
6670 }
6671 fCanSplit = -1;
6672}
6673
6674
6675////////////////////////////////////////////////////////////////////////////////
6676/// Install a new wrapper around 'Merge'.
6677
6679{
6680 fMerge = newMerge;
6681}
6682
6683////////////////////////////////////////////////////////////////////////////////
6684/// Install a new wrapper around 'ResetAfterMerge'.
6685
6687{
6688 fResetAfterMerge = newReset;
6689}
6690
6691////////////////////////////////////////////////////////////////////////////////
6692/// Install a new wrapper around 'new'.
6693
6695{
6696 fNew = newFunc;
6697}
6698
6699////////////////////////////////////////////////////////////////////////////////
6700/// Install a new wrapper around 'new []'.
6701
6703{
6704 fNewArray = newArrayFunc;
6705}
6706
6707////////////////////////////////////////////////////////////////////////////////
6708/// Install a new wrapper around 'delete'.
6709
6711{
6712 fDelete = deleteFunc;
6713}
6714
6715////////////////////////////////////////////////////////////////////////////////
6716/// Install a new wrapper around 'delete []'.
6717
6719{
6720 fDeleteArray = deleteArrayFunc;
6721}
6722
6723////////////////////////////////////////////////////////////////////////////////
6724/// Install a new wrapper around the destructor.
6725
6727{
6728 fDestructor = destructorFunc;
6729}
6730
6731////////////////////////////////////////////////////////////////////////////////
6732/// Install a new wrapper around the directory auto add function..
6733/// The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
6734/// and should register 'obj' to the directory if dir is not null
6735/// and unregister 'obj' from its current directory if dir is null
6736
6738{
6739 fDirAutoAdd = autoAddFunc;
6740}
6741
6742////////////////////////////////////////////////////////////////////////////////
6743/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6744
6746{
6748 if (guess && guess->GetCheckSum() == checksum) {
6749 return guess;
6750 } else {
6751 if (fCheckSum == checksum) return GetStreamerInfo();
6752
6754 Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
6755 for (Int_t i=-1;i<ninfos;++i) {
6756 // TClass::fStreamerInfos has a lower bound not equal to 0,
6757 // so we have to use At and should not use UncheckedAt
6759 if (info && info->GetCheckSum() == checksum) {
6760 // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6761 info->BuildOld();
6762 if (info->IsCompiled()) fLastReadInfo = info;
6763 return info;
6764 }
6765 }
6766 return 0;
6767 }
6768}
6769
6770////////////////////////////////////////////////////////////////////////////////
6771/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6772
6774{
6776 Int_t ninfos = arr->GetEntriesFast()-1;
6777 for (Int_t i=-1;i<ninfos;i++) {
6778 // TClass::fStreamerInfos has a lower bound not equal to 0,
6779 // so we have to use At and should not use UncheckedAt
6781 if (!info) continue;
6782 if (info->GetCheckSum() == checksum) {
6783 R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6784 return info;
6785 }
6786 }
6787 return 0;
6788}
6789
6790////////////////////////////////////////////////////////////////////////////////
6791/// Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
6792
6793TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
6794{
6795 TClass *cl = TClass::GetClass( classname );
6796 if( !cl )
6797 return 0;
6798 return GetConversionStreamerInfo( cl, version );
6799}
6800
6801////////////////////////////////////////////////////////////////////////////////
6802/// Return a Conversion StreamerInfo from the class represented by cl for version number 'version' to this class, if any.
6803
6805{
6806 //----------------------------------------------------------------------------
6807 // Check if the classname was specified correctly
6808 /////////////////////////////////////////////////////////////////////////////
6809
6810 if( !cl )
6811 return 0;
6812
6813 if( cl == this )
6814 return GetStreamerInfo( version );
6815
6816 //----------------------------------------------------------------------------
6817 // Check if we already have it
6818 /////////////////////////////////////////////////////////////////////////////
6819
6820 TObjArray* arr = 0;
6821 if (fConversionStreamerInfo.load()) {
6822 std::map<std::string, TObjArray*>::iterator it;
6824
6825 it = (*fConversionStreamerInfo).find( cl->GetName() );
6826
6827 if( it != (*fConversionStreamerInfo).end() ) {
6828 arr = it->second;
6829 }
6830
6831 if( arr && version > -1 && version < arr->GetSize() && arr->At( version ) )
6832 return (TVirtualStreamerInfo*) arr->At( version );
6833 }
6834
6836
6837 //----------------------------------------------------------------------------
6838 // We don't have the streamer info so find it in other class
6839 /////////////////////////////////////////////////////////////////////////////
6840
6841 const TObjArray *clSI = cl->GetStreamerInfos();
6842 TVirtualStreamerInfo* info = 0;
6843 if( version >= -1 && version < clSI->GetSize() )
6844 info = (TVirtualStreamerInfo*)clSI->At( version );
6845
6846 if (!info && cl->GetCollectionProxy()) {
6847 info = cl->GetStreamerInfo(); // instantiate the StreamerInfo for STL collections.
6848 }
6849
6850 if( !info )
6851 return 0;
6852
6853 //----------------------------------------------------------------------------
6854 // We have the right info so we need to clone it to create new object with
6855 // non artificial streamer elements and we should build it for current class
6856 /////////////////////////////////////////////////////////////////////////////
6857
6858 info = (TVirtualStreamerInfo*)info->Clone();
6859
6860 if( !info->BuildFor( this ) ) {
6861 delete info;
6862 return 0;
6863 }
6864
6865 if (!info->IsCompiled()) {
6866 // Streamer info has not been compiled, but exists.
6867 // Therefore it was read in from a file and we have to do schema evolution?
6868 // Or it didn't have a dictionary before, but does now?
6869 info->BuildOld();
6870 }
6871
6872 //----------------------------------------------------------------------------
6873 // Cache this streamer info
6874 /////////////////////////////////////////////////////////////////////////////
6875
6876 if (!arr) {
6877 arr = new TObjArray(version+10, -1);
6878 if (!fConversionStreamerInfo.load()) {
6879 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6880 }
6881 (*fConversionStreamerInfo)[cl->GetName()] = arr;
6882 }
6883 arr->AddAtAndExpand( info, info->GetClassVersion() );
6884 return info;
6885}
6886
6887////////////////////////////////////////////////////////////////////////////////
6888/// Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
6889
6890TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
6891{
6892 TClass *cl = TClass::GetClass( classname );
6893 if( !cl )
6894 return 0;
6895 return FindConversionStreamerInfo( cl, checksum );
6896}
6897
6898////////////////////////////////////////////////////////////////////////////////
6899/// Return a Conversion StreamerInfo from the class represented by cl for the layout represented by 'checksum' to this class, if any.
6900
6902{
6903 //---------------------------------------------------------------------------
6904 // Check if the classname was specified correctly
6905 /////////////////////////////////////////////////////////////////////////////
6906
6907 if( !cl )
6908 return 0;
6909
6910 if( cl == this )
6911 return FindStreamerInfo( checksum );
6912
6913 //----------------------------------------------------------------------------
6914 // Check if we already have it
6915 /////////////////////////////////////////////////////////////////////////////
6916
6917 TObjArray* arr = 0;
6918 TVirtualStreamerInfo* info = 0;
6919 if (fConversionStreamerInfo.load()) {
6920 std::map<std::string, TObjArray*>::iterator it;
6921
6923
6924 it = (*fConversionStreamerInfo).find( cl->GetName() );
6925
6926 if( it != (*fConversionStreamerInfo).end() ) {
6927 arr = it->second;
6928 }
6929 if (arr) {
6930 info = FindStreamerInfo( arr, checksum );
6931 }
6932 }
6933
6934 if( info )
6935 return info;
6936
6938
6939 //----------------------------------------------------------------------------
6940 // Get it from the foreign class
6941 /////////////////////////////////////////////////////////////////////////////
6942
6943 info = cl->FindStreamerInfo( checksum );
6944
6945 if( !info )
6946 return 0;
6947
6948 //----------------------------------------------------------------------------
6949 // We have the right info so we need to clone it to create new object with
6950 // non artificial streamer elements and we should build it for current class
6951 /////////////////////////////////////////////////////////////////////////////
6952
6953 info = (TVirtualStreamerInfo*)info->Clone();
6954 if( !info->BuildFor( this ) ) {
6955 delete info;
6956 return 0;
6957 }
6958
6959 if (!info->IsCompiled()) {
6960 // Streamer info has not been compiled, but exists.
6961 // Therefore it was read in from a file and we have to do schema evolution?
6962 // Or it didn't have a dictionary before, but does now?
6963 info->BuildOld();
6964 }
6965
6966 //----------------------------------------------------------------------------
6967 // Cache this streamer info
6968 /////////////////////////////////////////////////////////////////////////////
6969
6970 if (!arr) {
6971 arr = new TObjArray(16, -2);
6972 if (!fConversionStreamerInfo.load()) {
6973 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6974 }
6975 (*fConversionStreamerInfo)[cl->GetName()] = arr;
6976 }
6977 arr->AddAtAndExpand( info, info->GetClassVersion() );
6978
6979 return info;
6980}
6981
6982////////////////////////////////////////////////////////////////////////////////
6983/// Register the StreamerInfo in the given slot, change the State of the
6984/// TClass as appropriate.
6985
6987{
6988 if (info) {
6990 Int_t slot = info->GetClassVersion();
6992 && fStreamerInfo->At(slot) != 0
6993 && fStreamerInfo->At(slot) != info) {
6994 Error("RegisterStreamerInfo",
6995 "Register StreamerInfo for %s on non-empty slot (%d).",
6996 GetName(),slot);
6997 }
6998 fStreamerInfo->AddAtAndExpand(info, slot);
6999 if (fState <= kForwardDeclared) {
7000 fState = kEmulated;
7001 if (fCheckSum==0 && slot==fClassVersion) fCheckSum = info->GetCheckSum();
7002 }
7003 }
7004}
7005
7006////////////////////////////////////////////////////////////////////////////////
7007/// Remove and delete the StreamerInfo in the given slot.
7008/// Update the slot accordingly.
7009
7011{
7012 if (fStreamerInfo->GetSize() >= slot) {
7016 delete info;
7017 if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
7019 }
7020 }
7021}
7022
7023////////////////////////////////////////////////////////////////////////////////
7024/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7025/// classes in the class hierarchy that overload TObject::Hash do call
7026/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7027/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7028/// This routines is used for a small subset of the class for which we need
7029/// the answer before gROOT is properly initialized.
7030
7032{
7033 // Hand selection of correct classes, those classes should be
7034 // cross-checked in testHashRecursiveRemove.cxx
7035 static const char *handVerified[] = {
7036 "TEnvRec", "TDataType", "TObjArray", "TList", "THashList",
7037 "TClass", "TCling", "TInterpreter", "TMethod", "ROOT::Internal::TCheckHashRecursiveRemoveConsistency",
7038 "TCheckHashRecursiveRemoveConsistency", "TGWindow",
7039 "TDirectory", "TDirectoryFile", "TObject", "TH1",
7040 "TQClass", "TGlobal" };
7041
7042 if (cname && cname[0]) {
7043 for (auto cursor : handVerified) {
7044 if (strcmp(cname, cursor) == 0)
7045 return true;
7046 }
7047 }
7048 return false;
7049}
7050
7051////////////////////////////////////////////////////////////////////////////////
7052/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7053/// classes in the class hierarchy that overload TObject::Hash do call
7054/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7055/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7056
7058{
7059 return clRef.HasConsistentHashMember();
7060}
7061
7062////////////////////////////////////////////////////////////////////////////////
7063/// Return true if we have access to a constructor useable for I/O. This is
7064/// typically the default constructor but can also be a constructor specifically
7065/// marked for I/O (for example a constructor taking a TRootIOCtor* as an
7066/// argument). In other words, if this routine returns true, TClass::New is
7067/// guarantee to succeed.
7068/// To know if the class described by this TClass has a default constructor
7069/// (public or not), use
7070/// \code{.cpp}
7071/// cl->GetProperty() & kClassHasDefaultCtor
7072/// \code
7073/// To know if the class described by this TClass has a public default
7074/// constructor use:
7075/// \code{.cpp}
7076/// gInterpreter->ClassInfo_HasDefaultConstructor(aClass->GetClassInfo());
7077/// \code
7078
7080{
7081
7082 if (fNew) return kTRUE;
7083
7084 if (HasInterpreterInfo()) {
7087 }
7088 if (fCollectionProxy) {
7089 return kTRUE;
7090 }
7091 if (fCurrentInfo.load()) {
7092 // Emulated class, we know how to construct them via the TStreamerInfo
7093 return kTRUE;
7094 }
7095 return kFALSE;
7096}
7097
7098////////////////////////////////////////////////////////////////////////////////
7099/// Returns true if this class has an definition and/or overload of the
7100/// member function Hash.
7101///
7102/// For example to test if the class overload TObject::Hash use
7103/// ~~~ {.cpp}
7104/// if (cl->IsTObject() && cl->HasLocalHashMember())
7105/// ~~~
7106
7108{
7109 if (fProperty == (-1))
7110 Property();
7112}
7113
7114////////////////////////////////////////////////////////////////////////////////
7115/// Return the wrapper around Merge.
7116
7118{
7119 return fMerge;
7120}
7121
7122////////////////////////////////////////////////////////////////////////////////
7123/// Return the wrapper around Merge.
7124
7126{
7127 return fResetAfterMerge;
7128}
7129
7130////////////////////////////////////////////////////////////////////////////////
7131/// Return the wrapper around new ThisClass().
7132
7134{
7135 return fNew;
7136}
7137
7138////////////////////////////////////////////////////////////////////////////////
7139/// Return the wrapper around new ThisClass[].
7140
7142{
7143 return fNewArray;
7144}
7145
7146////////////////////////////////////////////////////////////////////////////////
7147/// Return the wrapper around delete ThiObject.
7148
7150{
7151 return fDelete;
7152}
7153
7154////////////////////////////////////////////////////////////////////////////////
7155/// Return the wrapper around delete [] ThiObject.
7156
7158{
7159 return fDeleteArray;
7160}
7161
7162////////////////////////////////////////////////////////////////////////////////
7163/// Return the wrapper around the destructor
7164
7166{
7167 return fDestructor;
7168}
7169
7170////////////////////////////////////////////////////////////////////////////////
7171/// Return the wrapper around the directory auto add function.
7172
7174{
7175 return fDirAutoAdd;
7176}
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned char UChar_t
Definition: RtypesCore.h:34
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
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
void(* MemberStreamerFunc_t)(TBuffer &, void *, Int_t)
Definition: Rtypes.h:71
TClass *(* IsAGlobalFunc_t)(const TClass *, const void *obj)
Definition: Rtypes.h:97
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
void(* ClassStreamerFunc_t)(TBuffer &, void *)
Definition: Rtypes.h:69
void(* ClassConvStreamerFunc_t)(TBuffer &, void *, const TClass *)
Definition: Rtypes.h:70
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:95
TVirtualMutex * gInterpreterMutex
Definition: TClass.cxx:123
static TVirtualMutex * gOVRMutex
Definition: TClass.cxx:236
static void UnregisterAddressInRepository(const char *, void *location, const TClass *what)
Definition: TClass.cxx:268
static void RegisterAddressInRepository(const char *, void *location, const TClass *what)
Definition: TClass.cxx:240
TClass::ENewType & TClass__GetCallingNew()
Definition: TClass.cxx:225
std::multimap< void *, ObjRepoValue > RepoCont_t
Definition: TClass.cxx:237
static RepoCont_t gObjectVersionRepository
Definition: TClass.cxx:238
static void MoveAddressInRepository(const char *, void *oldadd, void *newadd, const TClass *what)
Definition: TClass.cxx:287
ROOT::TMapDeclIdToTClass DeclIdMap_t
Definition: TClass.h:73
ROOT::TMapTypeToTClass IdMap_t
Definition: TClass.h:72
const Bool_t kIterBackward
Definition: TCollection.h:41
EDataType
Definition: TDataType.h:28
@ kNoType_t
Definition: TDataType.h:33
@ kUInt_t
Definition: TDataType.h:30
@ kIsPointer
Definition: TDictionary.h:77
@ kIsClass
Definition: TDictionary.h:65
@ kIsEnum
Definition: TDictionary.h:68
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsAbstract
Definition: TDictionary.h:71
@ kIsArray
Definition: TDictionary.h:78
@ kIsStatic
Definition: TDictionary.h:79
@ kIsStruct
Definition: TDictionary.h:66
@ kIsUnion
Definition: TDictionary.h:67
@ kIsNamespace
Definition: TDictionary.h:91
@ kIsVirtualBase
Definition: TDictionary.h:87
#define R__ASSERT(e)
Definition: TError.h:96
int type
Definition: TGX11.cxx:120
#define Printf
Definition: TGeoToOCC.h:18
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
#define gInterpreter
Definition: TInterpreter.h:538
double log10(double)
@ kMenuToggle
Definition: TMethod.h:34
@ kMenuNoMenu
Definition: TMethod.h:32
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
#define gROOT
Definition: TROOT.h:410
@ kDefault
Definition: TSocket.h:51
typedef void((*Func_t)())
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
Definition: TThreadSlots.h:40
#define R__LOCKGUARD2(mutex)
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:286
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
const char * proto
Definition: civetweb.c:16604
#define snprintf
Definition: civetweb.c:1540
Bool_t AddRule(TSchemaRule *rule, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=0)
The consistency check always fails if the TClass object was not set! if checkConsistency is: kNoCheck...
void SetClass(TClass *cls)
Set the TClass associated with this rule set.
A spin mutex-as-code-guard class.
Bool_t SetFromRule(const char *rule)
Set the content fot this object from the rule See TClass::AddRule for details on the syntax.
const char * GetTargetString() const
Get the target data members of this rule as a simple string (i.e. the in memory data member).
const char * GetVersion() const
Get the version string.
const char * GetTargetClass() const
Get the targte class of this rule (i.e. the in memory class).
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
Int_t GetDelta()
Get offset from "this" to part of base class.
Definition: TBaseClass.cxx:75
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TBaseClass.cxx:134
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Objects following this interface can be passed onto the TROOT object to implement a user customized w...
virtual TClass * GetClass(const char *classname, Bool_t load)=0
Describes one element of the context menu associated to a class The menu item may describe.
virtual void SetToggle(Bool_t toggle=kTRUE)
TClassRef is used to implement a permanent reference to a TClass object.
Definition: TClassRef.h:29
virtual void Stream(TBuffer &b, void *objp, const TClass *onfileClass)
virtual TClassStreamer * Generate() const
ClassStreamerFunc_t fStreamer
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
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).
InsertTClassInRegistryRAII(TClass::EState &state, const char *name, TDeclNameRegistry &emuRegistry)
Definition: TClass.cxx:206
Bool_t HasDeclName(const char *name) const
Definition: TClass.cxx:181
void AddQualifiedName(const char *name)
Extract this part of the name.
Definition: TClass.cxx:154
TDeclNameRegistry(Int_t verbLevel=0)
TDeclNameRegistry class constructor.
Definition: TClass.cxx:143
std::atomic_flag fSpinLock
Definition: TClass.h:145
TNameMapNode(const char *typedf, const char *orig)
Definition: TClass.cxx:696
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:6217
ShowMembersFunc_t fShowMembers
Definition: TClass.h:199
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3278
TVirtualIsAProxy * fIsA
Definition: TClass.h:203
void ForceReload(TClass *oldcl)
we found at least one equivalent.
Definition: TClass.cxx:1278
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4452
ROOT::DelArrFunc_t fDeleteArray
Definition: TClass.h:212
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2229
TClassStreamer * fStreamer
Definition: TClass.h:200
void SetDirectoryAutoAdd(ROOT::DirAutoAdd_t dirAutoAddFunc)
Install a new wrapper around the directory auto add function.
Definition: TClass.cxx:6737
Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition: TClass.h:485
void * NewArray(Long_t nElements, ENewType defConstructor=kClassNew) const
Return a pointer to a newly allocated array of objects of this class.
Definition: TClass.cxx:5006
static TDeclNameRegistry fNoInfoOrEmuOrFwdDeclNameRegistry
Definition: TClass.h:294
TListOfFunctionTemplates * fFuncTemplate
Definition: TClass.h:180
ClassStreamerFunc_t fStreamerFunc
Definition: TClass.h:215
void AdoptReferenceProxy(TVirtualRefProxy *proxy)
Adopt the Reference proxy pointer to indicate that this class represents a reference.
Definition: TClass.cxx:6397
TVirtualStreamerInfo * DetermineCurrentStreamerInfo()
Determine and set pointer to current TVirtualStreamerInfo.
Definition: TClass.cxx:5446
EState GetState() const
Definition: TClass.h:458
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2803
void AdoptMemberStreamer(const char *name, TMemberStreamer *strm)
Adopt the TMemberStreamer pointer to by p and use it to Stream non basic member name.
Definition: TClass.cxx:6415
void ResetInstanceCount()
Definition: TClass.h:510
ClassStreamerFunc_t GetStreamerFunc() const
Get a wrapper/accessor function around this class custom streamer (member function).
Definition: TClass.cxx:2856
void RemoveStreamerInfo(Int_t slot)
Remove and delete the StreamerInfo in the given slot.
Definition: TClass.cxx:7010
void SetCanSplit(Int_t splitmode)
Set the splitability of this class:
Definition: TClass.cxx:5420
TObject * Clone(const char *newname="") const
Create a Clone of this TClass object using a different name but using the same 'dictionary'.
Definition: TClass.cxx:2324
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4555
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4824
void SetMerge(ROOT::MergeFunc_t mergeFunc)
Install a new wrapper around 'Merge'.
Definition: TClass.cxx:6678
ConvSIMap_t fConversionStreamerInfo
Definition: TClass.h:174
ROOT::DirAutoAdd_t fDirAutoAdd
Definition: TClass.h:214
Bool_t HasDataMemberInfo() const
Definition: TClass.h:378
TVirtualRefProxy * fRefProxy
cached streamer info used in the last read.
Definition: TClass.h:245
TList * GetMenuList() const
Return the list of menu items associated with the class.
Definition: TClass.cxx:4194
ROOT::MergeFunc_t fMerge
saved info to call a IsA member function
Definition: TClass.h:207
TMethod * GetMethod(const char *method, const char *params, Bool_t objectIsConst=kFALSE)
Find the best method (if there is one) matching the parameters.
Definition: TClass.cxx:4264
virtual void Browse(TBrowser *b)
This method is called by a browser to get the class information.
Definition: TClass.cxx:1919
static TClass * Load(TBuffer &b)
Load class description from I/O buffer and return class object.
Definition: TClass.cxx:5477
EState fState
cached of the streaming method to use
Definition: TClass.h:242
ROOT::DesFunc_t GetDestructor() const
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition: TClass.cxx:4309
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition: TClass.cxx:2387
Int_t fStreamerType
saved info to call Streamer
Definition: TClass.h:241
TList * fRealData
Definition: TClass.h:175
UInt_t fOnHeap
Definition: TClass.h:192
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
std::atomic< TList * > fBase
Definition: TClass.h:176
Bool_t HasDictionary() const
Check whether a class has a dictionary or not.
Definition: TClass.cxx:3758
Long_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition: TClass.cxx:3306
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
Definition: TClass.cxx:3697
TMethod * GetClassMethod(Long_t faddr)
Look for a method in this class that has the interface function address faddr.
Definition: TClass.cxx:4336
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition: TClass.cxx:3714
void BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
Build the list of real data for an emulated class.
Definition: TClass.cxx:2021
static void AddClassToDeclIdMap(TDictionary::DeclId_t id, TClass *cl)
static: Add a TClass* to the map of classes.
Definition: TClass.cxx:461
virtual ~TClass()
TClass dtor. Deletes all list that might have been created.
Definition: TClass.cxx:1573
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5181
Version_t fClassVersion
Definition: TClass.h:195
std::atomic< TVirtualStreamerInfo * > fCurrentInfo
Current 'state' of the class (Emulated,Interpreted,Loaded)
Definition: TClass.h:243
TList * GetListOfFunctionTemplates(Bool_t load=kTRUE)
Return list containing the TEnums of a class.
Definition: TClass.cxx:3650
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition: TClass.cxx:4761
const char * fImplFileName
Definition: TClass.h:188
void RegisterStreamerInfo(TVirtualStreamerInfo *info)
Register the StreamerInfo in the given slot, change the State of the TClass as appropriate.
Definition: TClass.cxx:6986
std::atomic< UInt_t > fCheckSum
Definition: TClass.h:193
std::atomic< TListOfFunctions * > fMethod
Definition: TClass.h:181
static void RemoveClassDeclId(TDictionary::DeclId_t id)
Definition: TClass.cxx:486
void SetNewArray(ROOT::NewArrFunc_t newArrayFunc)
Install a new wrapper around 'new []'.
Definition: TClass.cxx:6702
Bool_t CallShowMembers(const void *obj, TMemberInspector &insp, Bool_t isTransient=kFALSE) const
Call ShowMembers() on the obj of this class type, passing insp and parent.
Definition: TClass.cxx:2114
const char * fDeclFileName
Definition: TClass.h:187
void SetCollectionProxy(const ROOT::Detail::TCollectionProxyInfo &)
Create the collection proxy object (and the streamer object) from using the information in the TColle...
Definition: TClass.cxx:5958
Int_t fCanSplit
Definition: TClass.h:219
static Bool_t HasDictionarySelection(const char *clname)
Check whether a class has a dictionary or ROOT can load one.
Definition: TClass.cxx:3769
void AdoptSchemaRules(ROOT::Detail::TSchemaRuleSet *rules)
Adopt a new set of Data Model Evolution rules.
Definition: TClass.cxx:1829
static void StreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition: TClass.cxx:6545
TVirtualStreamerInfo * SetStreamerInfo(Int_t version, const char *info="")
Info is a string describing the names and types of attributes written by the class Streamer function.
Definition: TClass.cxx:6085
static std::atomic< Int_t > fgClassCount
Definition: TClass.h:292
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition: TClass.h:410
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
void AddImplFile(const char *filename, int line)
Definition: TClass.cxx:1861
TCollection * GetListOfMethodOverloads(const char *name) const
Return the collection of functions named "name".
Definition: TClass.cxx:3679
std::atomic< TListOfEnums * > fEnums
Definition: TClass.h:179
static Bool_t HasNoInfoOrEmuOrFwdDeclaredDecl(const char *)
Definition: TClass.cxx:3237
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition: TClass.cxx:3559
Bool_t IsStartingWithTObject() const
Returns true if this class inherits from TObject and if the start of the TObject parts is at the very...
Definition: TClass.cxx:5691
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3664
TClass()
Definition: TClass.cxx:1013
Short_t fDeclFileLine
Definition: TClass.h:189
Int_t GetNmethods()
Return the number of methods of this class Note that in case the list of methods is not yet created,...
Definition: TClass.cxx:4426
std::atomic< Bool_t > fIsOffsetStreamerSet
Indicates whether the ClassInfo is supposed to be available.
Definition: TClass.h:226
void IgnoreTObjectStreamer(Bool_t ignore=kTRUE)
When the class kIgnoreTObjectStreamer bit is set, the automatically generated Streamer will not call ...
Definition: TClass.cxx:4687
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2831
static IdMap_t * GetIdMap()
Definition: TClass.cxx:419
void SetDelete(ROOT::DelFunc_t deleteFunc)
Install a new wrapper around 'delete'.
Definition: TClass.cxx:6710
static Int_t AutoBrowse(TObject *obj, TBrowser *browser)
Browse external object inherited from TObject.
Definition: TClass.cxx:1875
ROOT::NewFunc_t GetNew() const
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition: TClass.cxx:2572
Int_t GetNdata()
Return the number of data members of this class Note that in case the list of data members is not yet...
Definition: TClass.cxx:4407
void SetDestructor(ROOT::DesFunc_t destructorFunc)
Install a new wrapper around the destructor.
Definition: TClass.cxx:6726
Bool_t HasDefaultConstructor() const
virtual void PostLoadCheck()
Do the initialization that can only be done after the CINT dictionary has been fully populated and ca...
Definition: TClass.cxx:5719
void LoadClassInfo() const
Try to load the ClassInfo if available.
Definition: TClass.cxx:5586
void SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t resetFunc)
Install a new wrapper around 'ResetAfterMerge'.
Definition: TClass.cxx:6686
Bool_t MatchLegacyCheckSum(UInt_t checksum) const
Return true if the checksum passed as argument is one of the checksum value produced by the older che...
Definition: TClass.cxx:6206
TViewPubFunctions * fAllPubMethod
Definition: TClass.h:184
Bool_t HasInterpreterInfo() const
Definition: TClass.h:381
static void AddClass(TClass *cl)
static: Add a class to the list and map of classes.
Definition: TClass.cxx:444
void GetMissingDictionariesForBaseClasses(TCollection &result, TCollection &visited, bool recurse)
Verify the base classes always.
Definition: TClass.cxx:3779
ROOT::Detail::TSchemaRuleSet * fSchemaRules
Pointer to reference proxy if this class represents a reference.
Definition: TClass.h:246
std::atomic< Long_t > fProperty
Indicates whether this class can be split or not.
Definition: TClass.h:220
static void StreamerDefault(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Default streaming in cases where either we have no way to know what to do or if Property() has not ye...
Definition: TClass.cxx:6582
void SetUnloaded()
Call this method to indicate that the shared library containing this class's code has been removed (u...
Definition: TClass.cxx:6023
ROOT::DelArrFunc_t GetDeleteArray() const
Bool_t HasInterpreterInfoInMemory() const
Definition: TClass.h:380
TList * fClassMenuList
Definition: TClass.h:185
ClassConvStreamerFunc_t fConvStreamerFunc
Definition: TClass.h:216
void SetRuntimeProperties()
Internal routine to set calculate the class properties that can only be known at run-time,...
Definition: TClass.cxx:5908
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5511
TString fSharedLibs
Definition: TClass.h:201
const std::type_info * GetTypeInfo() const
Definition: TClass.h:466
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3615
ENewType
Definition: TClass.h:101
@ kRealNew
Definition: TClass.h:101
void Move(void *arenaFrom, void *arenaTo) const
Register the fact that an object was moved from the memory location 'arenaFrom' to the memory locatio...
Definition: TClass.cxx:4180
static DeclIdMap_t * GetDeclIdMap()
Definition: TClass.cxx:430
Short_t GetDeclFileLine() const
Definition: TClass.h:400
void SetStreamerFunc(ClassStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom streamer.
Definition: TClass.cxx:6631
const char * GetImplFileName() const
Definition: TClass.h:426
TList * GetListOfRealData() const
Definition: TClass.h:423
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5466
void SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
Set pointer to current TVirtualStreamerInfo.
Definition: TClass.cxx:5458
static DictFuncPtr_t GetDict(const char *cname)
Return a pointer to the dictionary loading function generated by rootcint.
Definition: TClass.cxx:3261
Int_t fSizeof
Definition: TClass.h:217
ROOT::NewArrFunc_t GetNewArray() const
static void StreamerTObjectEmulated(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects when we do not have the library defining the class.
Definition: TClass.cxx:6532
ROOT::NewFunc_t fNew
Definition: TClass.h:209
ROOT::ResetAfterMergeFunc_t GetResetAfterMerge() const
TMethod * GetClassMethodWithPrototype(const char *name, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition: TClass.cxx:4380
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
void SetGlobalIsA(IsAGlobalFunc_t)
This function installs a global IsA function for this class.
Definition: TClass.cxx:6014
void GetMissingDictionariesForMembers(TCollection &result, TCollection &visited, bool recurse)
Verify the Data Members.
Definition: TClass.cxx:3796
TObjArray * fStreamerInfo
Definition: TClass.h:173
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1841
TVirtualCollectionProxy * fCollectionProxy
Definition: TClass.h:194
static ENewType IsCallingNew()
Static method returning the defConstructor flag passed to TClass::New().
Definition: TClass.cxx:5664
void ls(Option_t *opt="") const
The ls function lists the contents of a class on stdout.
Definition: TClass.cxx:4111
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3505
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition: TClass.cxx:5622
void InterpretedShowMembers(void *obj, TMemberInspector &insp, Bool_t isTransient)
Do a ShowMembers() traversal of all members and base classes' members using the reflection informatio...
Definition: TClass.cxx:2151
static THashTable * fgClassTypedefHash
Definition: TClass.h:323
void Init(const char *name, Version_t cversion, const std::type_info *info, TVirtualIsAProxy *isa, const char *dfil, const char *ifil, Int_t dl, Int_t il, ClassInfo_t *classInfo, Bool_t silent)
Initialize a TClass object.
Definition: TClass.cxx:1303
static void StreamerStreamerInfo(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of where we should directly use the StreamerInfo.
Definition: TClass.cxx:6567
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:462
void SetClassVersion(Version_t version)
Private function.
Definition: TClass.cxx:5437
char * EscapeChars(const char *text) const
Introduce an escape character (@) in front of a special chars.
Definition: TClass.cxx:2486
const std::type_info * fTypeInfo
Definition: TClass.h:198
std::atomic< TVirtualStreamerInfo * > fLastReadInfo
cached current streamer info.
Definition: TClass.h:244
static void StreamerTObject(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects.
Definition: TClass.cxx:6509
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5674
@ kDefault
Definition: TClass.h:300
@ kEmulatedStreamer
Definition: TClass.h:300
@ kExternal
Definition: TClass.h:300
@ kForeign
Definition: TClass.h:300
@ kInstrumented
Definition: TClass.h:300
@ kTObject
Definition: TClass.h:300
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition: TClass.cxx:1799
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5700
static void RemoveClass(TClass *cl)
static: Remove a class from the list and map of classes
Definition: TClass.cxx:470
Bool_t HasLocalHashMember() const
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition: TClass.cxx:5298
ClassConvStreamerFunc_t GetConvStreamerFunc() const
Get a wrapper/accessor function around this class custom conversion streamer (member function).
Definition: TClass.cxx:2864
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition: TClass.cxx:5709
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:404
ROOT::DelFunc_t fDelete
Definition: TClass.h:211
TViewPubDataMembers * fAllPubData
Definition: TClass.h:183
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2708
void Dump() const
Dump contents of object on stdout.
Definition: TClass.h:370
ClassInfo_t * fClassInfo
Definition: TClass.h:196
Bool_t HasConsistentHashMember()
Return 'true' if we can guarantee that if this class (or any class in this class inheritance hierarch...
Definition: TClass.h:471
void AdoptStreamer(TClassStreamer *strm)
Adopt a TClassStreamer object.
Definition: TClass.cxx:6603
TClass * GetBaseDataMember(const char *datamember)
Return pointer to (base) class that contains datamember.
Definition: TClass.cxx:2744
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5800
ECheckSum
Definition: TClass.h:102
@ kLatestCheckSum
Definition: TClass.h:111
@ kNoRange
Definition: TClass.h:106
@ kCurrentCheckSum
Definition: TClass.h:103
@ kNoBaseCheckSum
Definition: TClass.h:110
@ kReflex
Definition: TClass.h:108
@ kReflexNoComment
Definition: TClass.h:105
@ kWithTypeDef
Definition: TClass.h:107
@ kNoRangeCheck
Definition: TClass.h:109
@ kNoEnum
Definition: TClass.h:104
Long_t fOffsetStreamer
Properties that can only be evaluated at run-time.
Definition: TClass.h:240
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
void ResetCaches()
To clean out all caches.
Definition: TClass.cxx:4070
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition: TClass.h:227
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Definition: TClass.cxx:2314
void SetStreamerImpl()
Internal routine to set fStreamerImpl based on the value of fStreamerType.
Definition: TClass.cxx:5929
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition: TClass.cxx:3492
void CalculateStreamerOffset() const
Calculate the offset between an object of this class to its base class TObject.
Definition: TClass.cxx:2092
void GetMissingDictionariesForPairElements(TCollection &result, TCollection &visited, bool recurse)
Definition: TClass.cxx:3825
void ReplaceWith(TClass *newcl) const
Definition: TClass.cxx:3989
void GetMenuItems(TList *listitems)
Returns list of methods accessible by context menu.
Definition: TClass.cxx:3726
void SetNew(ROOT::NewFunc_t newFunc)
Install a new wrapper around 'new'.
Definition: TClass.cxx:6694
void Draw(Option_t *option="")
Draw detailed class inheritance structure.
Definition: TClass.cxx:2404
std::atomic< TMethodCall * > fIsAMethod
Definition: TClass.h:205
static Int_t ReadRules()
Read the class.rules files from the default location:.
Definition: TClass.cxx:1729
Bool_t CanSplitBaseAllow()
Pointer to the function implementing streaming for this class.
Definition: TClass.cxx:2156
std::atomic< StreamerImpl_t > fStreamerImpl
Definition: TClass.h:252
void SetContextMenuTitle(const char *title)
Change (i.e. set) the title of the TNamed.
Definition: TClass.cxx:5983
void SetMemberStreamer(const char *name, MemberStreamerFunc_t strm)
Install a new member streamer (p will be copied).
Definition: TClass.cxx:6453
std::atomic< TClass ** > fPersistentRef
Definition: TClass.h:169
IsAGlobalFunc_t fGlobalIsA
pointer to the class's IsA proxy.
Definition: TClass.h:204
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6793
Short_t GetImplFileLine() const
Definition: TClass.h:427
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4237
std::atomic< UChar_t > fRuntimeProperties
Definition: TClass.h:238
EState
Definition: TClass.h:115
@ kHasTClassInit
Definition: TClass.h:121
@ kEmulated
Definition: TClass.h:119
@ kNoInfo
Definition: TClass.h:116
@ kLoaded
Definition: TClass.h:124
@ kForwardDeclared
Definition: TClass.h:118
@ kNamespaceForMeta
Definition: TClass.h:125
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' ...
Definition: TClass.cxx:6890
Int_t GetBaseClassOffsetRecurse(const TClass *toBase)
Return data member offset to the base class "cl".
Definition: TClass.cxx:2622
ROOT::DelFunc_t GetDelete() const
static TClass * LoadClassDefault(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5533
void SetClassSize(Int_t sizof)
Definition: TClass.h:273
TMethod * FindClassOrBaseMethodWithId(DeclId_t faddr)
Find a method with decl id in this class or its bases.
Definition: TClass.cxx:4293
static void StreamerExternal(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
There is special streamer for the class.
Definition: TClass.cxx:6497
Long_t fClassProperty
Property.
Definition: TClass.h:221
TString fContextMenuTitle
Definition: TClass.h:197
static void StreamerTObjectInitialized(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects when fIsOffsetStreamerSet is known to have been set.
Definition: TClass.cxx:6523
static void ConvStreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition: TClass.cxx:6554
TListOfDataMembers * fData
Definition: TClass.h:177
std::atomic< Bool_t > fCanLoadClassInfo
Whether info was loaded from a root pcm.
Definition: TClass.h:225
void SetConvStreamerFunc(ClassConvStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom conversion streamer.
Definition: TClass.cxx:6654
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6773
void GetMissingDictionaries(THashTable &result, bool recurse=false)
Get the classes that have a missing dictionary starting from this one.
Definition: TClass.cxx:3939
void MakeCustomMenuList()
Makes a customizable version of the popup menu list, i.e.
Definition: TClass.cxx:4136
@ kLoading
Definition: TClass.h:298
@ kUnloading
Definition: TClass.h:298
TVirtualStreamerInfo * FindStreamerInfoAbstractEmulated(UInt_t checksum) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4618
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4227
TVirtualIsAProxy * GetIsAProxy() const
Return the proxy implementing the IsA functionality.
Definition: TClass.cxx:2872
Version_t GetClassVersion() const
Definition: TClass.h:391
ROOT::MergeFunc_t GetMerge() const
ROOT::ResetAfterMergeFunc_t fResetAfterMerge
Definition: TClass.h:208
UInt_t fInstanceCount
Definition: TClass.h:191
std::atomic< Bool_t > fHasRootPcmInfo
C++ Property of the class (is abstract, has virtual table, etc.)
Definition: TClass.h:224
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4720
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2525
ROOT::DesFunc_t fDestructor
Definition: TClass.h:213
const char * GetDeclFileName() const
Definition: TClass.h:399
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3332
void SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
Install a new wrapper around 'delete []'.
Definition: TClass.cxx:6718
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition: TClass.cxx:3476
void ResetClassInfo()
Make sure that the current ClassInfo is up to date.
Definition: TClass.cxx:4035
ROOT::NewArrFunc_t fNewArray
Definition: TClass.h:210
Int_t ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
Function called by the Streamer functions to deserialize information from buffer b into object at p.
Definition: TClass.cxx:6467
void GetMissingDictionariesWithRecursionCheck(TCollection &result, TCollection &visited, bool recurse)
From the second level of recursion onwards it is different state check.
Definition: TClass.cxx:3842
@ kHasLocalHashMember
Definition: TClass.h:89
@ kHasNameMapNode
Definition: TClass.h:98
@ kIgnoreTObjectStreamer
Definition: TClass.h:90
@ kUnloaded
Definition: TClass.h:91
@ kHasCustomStreamerMember
Definition: TClass.h:99
@ kWarned
Definition: TClass.h:97
@ kStartWithTObject
Definition: TClass.h:96
@ kIsTObject
Definition: TClass.h:93
@ kIsForeign
Definition: TClass.h:94
TListOfFunctions * GetMethodList()
Return (create an empty one if needed) the list of functions.
Definition: TClass.cxx:4208
void ResetMenuList()
Resets the menu list to it's standard value.
Definition: TClass.cxx:4096
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
Int_t WriteBuffer(TBuffer &b, void *pointer, const char *info="")
Function called by the Streamer functions to serialize object at p to buffer b.
Definition: TClass.cxx:6488
static TClass * LoadClassCustom(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5563
Short_t fImplFileLine
Definition: TClass.h:190
Collection abstract base class.
Definition: TCollection.h:63
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void Add(TObject *obj)=0
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Int_t GetArrayDim() const
Return number of array dimensions.
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition: TDataMember.h:74
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TDataType.cxx:287
const char * AsString(void *buf) const
Return string containing value in buffer formatted according to the basic data type.
Definition: TDataType.cxx:235
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition: TDatime.cxx:434
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:159
const void * DeclId_t
Definition: TDictionary.h:206
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:173
void AddAt(UInt_t slot, ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table.
Definition: TExMap.cxx:116
Dictionary for function template This class describes one single function template.
Global functions class (global functions are obtained from CINT).
Definition: TFunction.h:28
Int_t GetNargs() const
Number of function arguments.
Definition: TFunction.cxx:164
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:35
TObject * Remove(TObject *obj)
Remove object from the hashtable.
Definition: THashTable.cxx:417
const TList * GetListForObject(const char *name) const
Return the TList corresponding to object's name based hash value.
Definition: THashTable.cxx:268
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:92
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:238
virtual Bool_t ClassInfo_HasMethod(ClassInfo_t *, const char *) const
Definition: TInterpreter.h:392
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:448
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:446
virtual int DataMemberInfo_TypeSize(DataMemberInfo_t *) const
Definition: TInterpreter.h:445
virtual Long_t ClassInfo_GetBaseOffset(ClassInfo_t *, ClassInfo_t *, void *=0, bool=true) const
Definition: TInterpreter.h:388
virtual void * ClassInfo_New(ClassInfo_t *) const
Definition: TInterpreter.h:404
virtual Bool_t ClassInfo_IsValid(ClassInfo_t *) const
Definition: TInterpreter.h:400
virtual Int_t AutoParse(const char *cls)=0
virtual int SetClassAutoloading(int) const
Definition: TInterpreter.h:247
virtual void ClassInfo_Delete(ClassInfo_t *) const
Definition: TInterpreter.h:380
virtual void ClassInfo_DeleteArray(ClassInfo_t *, void *, bool) const
Definition: TInterpreter.h:382
virtual Long_t ClassInfo_Property(ClassInfo_t *) const
Definition: TInterpreter.h:408
virtual Bool_t ClassInfo_HasDefaultConstructor(ClassInfo_t *) const
Definition: TInterpreter.h:391
virtual DataMemberInfo_t * DataMemberInfo_Factory(ClassInfo_t *=0) const
Definition: TInterpreter.h:436
virtual int ClassInfo_Size(ClassInfo_t *) const
Definition: TInterpreter.h:409
virtual const char * ClassInfo_FullName(ClassInfo_t *) const
Definition: TInterpreter.h:412
virtual const char * ClassInfo_Title(ClassInfo_t *) const
Definition: TInterpreter.h:414
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:444
virtual int DataMemberInfo_Next(DataMemberInfo_t *) const
Definition: TInterpreter.h:441
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:443
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:434
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:435
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:440
TDictionary::DeclId_t DeclId_t
Definition: TInterpreter.h:268
virtual Long_t ClassInfo_ClassProperty(ClassInfo_t *) const
Definition: TInterpreter.h:379
virtual void ClassInfo_Destruct(ClassInfo_t *, void *) const
Definition: TInterpreter.h:383
TIsAProxy implementation class.
Definition: TIsAProxy.h:27
void Reset()
Definition: TCollection.h:252
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
Bool_t IsLoaded() const
virtual void Delete(Option_t *option="")
Delete all TDataMember object files.
void Unload()
Mark 'all func' as being unloaded.
void Load()
Load all the DataMembers known to the interpreter for the scope 'fClass' into this collection.
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
Definition: TListOfEnums.h:33
A collection of TFunction objects designed for fast access given a DeclId_t and for keep track of TFu...
virtual TObject * FindObject(const char *name) const
Specialize FindObject to do search for the a function just by name or create it if its not already in...
void Load()
Load all the functions known to the interpreter for the scope 'fClass' into this collection.
virtual void Delete(Option_t *option="")
Delete all TFunction object files.
A collection of TFunction objects designed for fast access given a DeclId_t and for keep track of TFu...
TFunction * Get(DeclId_t id)
Return (after creating it if necessary) the TMethod or TFunction describing the function correspondin...
virtual TObject * FindObject(const TObject *obj) const
Find object using its hash value (returned by its Hash() member).
virtual TList * GetListForObject(const char *name) const
Return the set of overloads for this name, collecting all available ones.
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:97
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual TObjLink * FirstLink() const
Definition: TList.h:108
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:149
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
Abstract base class for accessing the data-members of a class.
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr)
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition: TMethodArg.h:31
const char * GetFullTypeName() const
Get full type description of method argument, e.g.: "class TDirectory*".
Definition: TMethodArg.cxx:75
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
TClass * GetClass() const
Definition: TMethod.h:55
EMenuItemKind IsMenuItem() const
Definition: TMethod.h:56
virtual TList * GetListOfMethodArgs()
Returns methodarg list and additionally updates fDataMember in TMethod by calling FindDataMember();.
Definition: TMethod.cxx:306
virtual void ls(Option_t *option="") const
List TNamed name and title.
Definition: TNamed.cxx:113
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:414
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
Int_t LowerBound() const
Definition: TObjArray.h:96
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Collectable string class.
Definition: TObjString.h:28
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Inspect() const
Dump contents of this object in a graphics canvas.
Definition: TObject.cxx:464
static void SetObjectStat(Bool_t stat)
Turn on/off tracking of objects in the TObjectTable.
Definition: TObject.cxx:961
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual void Browse(TBrowser *b)
Browse object. May be overridden for another default action.
Definition: TObject.cxx:119
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
static Bool_t GetObjectStat()
Get status of object stat flag.
Definition: TObject.cxx:954
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
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
void MakeZombie()
Definition: TObject.h:49
void ResetBit(UInt_t f)
Definition: TObject.h:171
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 const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:3010
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
void AdoptStreamer(TMemberStreamer *p)
Definition: TRealData.cxx:67
@ kTransient
Definition: TRealData.h:44
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
Long_t GetThisOffset() const
Definition: TRealData.h:55
void SetIsObject(Bool_t isObject)
Definition: TRealData.h:57
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetType() const
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual Bool_t IsaPointer() const
const char * GetTypeName() const
Int_t GetOffset() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:626
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2286
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
View implementing the TList interface and giving access all the TDictionary describing public data me...
void Load()
Load all the DataMembers known to the interpreter for the scope 'fClass' and all its bases classes.
void Delete(Option_t *option="")
Delete is not allowed in this class.
View implementing the TList interface and giving access all the TFunction describing public methods i...
void Load()
Load all the functions known to the interpreter for the scope 'fClass' and all its bases classes.
virtual Int_t GetProperties() const
virtual UInt_t Sizeof() const =0
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
virtual void * New() const
virtual void DeleteArray(void *p, Bool_t dtorOnly=kFALSE) const
virtual TClass * GetValueClass() const =0
virtual void * At(UInt_t idx)=0
virtual Int_t GetCollectionType() const =0
virtual UInt_t Size() const =0
virtual void * NewArray(Int_t nElements) const
virtual TVirtualCollectionProxy * Generate() const =0
virtual Bool_t HasPointers() const =0
virtual void SetClass(TClass *cl)=0
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:50
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual void Release()=0
virtual void SetClass(TClass *classptr)=0
virtual TVirtualRefProxy * Clone() const =0
Abstract Interface class describing Streamer information for one class.
virtual void DeleteArray(void *p, Bool_t dtorOnly=kFALSE)=0
virtual TClassStreamer * GenEmulatedClassStreamer(const char *class_name, Bool_t silent)=0
virtual void BuildCheck(TFile *file=0)=0
virtual TVirtualStreamerInfo * NewInfo(TClass *cl)=0
virtual TClass * GetActualClass(const void *obj) const =0
virtual UInt_t GetCheckSum() const =0
virtual Int_t GetOffset(const char *) const =0
static const char * GetElementCounterStart(const char *dmTitle)
Given a comment/title declaring an array counter, for example:
virtual Bool_t BuildFor(const TClass *cl)=0
virtual TVirtualCollectionProxy * GenExplicitProxy(const ::ROOT::Detail::TCollectionProxyInfo &info, TClass *cl)=0
virtual void Clear(Option_t *)=0
Set name and title to empty strings ("").
virtual TVirtualCollectionProxy * GenEmulatedProxy(const char *class_name, Bool_t silent)=0
virtual void SetClass(TClass *cl)=0
virtual void * NewArray(Long_t nElements, void *ary=0)=0
virtual TObjArray * GetElements() const =0
virtual Int_t GetSize() const =0
virtual void BuildOld()=0
static TVirtualStreamerInfo * Factory()
Static function returning a pointer to a new TVirtualStreamerInfo object.
virtual void Build()=0
virtual Version_t GetOldVersion() const =0
virtual void * New(void *obj=0)=0
virtual Int_t GetOnFileClassVersion() const =0
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE)=0
virtual Bool_t CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete, TFile *file)=0
virtual Int_t GetClassVersion() const =0
virtual void Update(const TClass *oldClass, TClass *newClass)=0
virtual TClass * GetClass() const =0
TText * text
TLine * line
return c1
Definition: legend1.C:41
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 void * gMmallocDesc
Definition: TStorage.h:126
Bool_t HasConsistentHashMember(TClass &clRef)
Return true is the Hash/RecursiveRemove setup is consistent, i.e.
Definition: TClass.cxx:7057
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:114
R__EXTERN TVirtualRWMutex * gCoreMutex
void(* ResetAfterMergeFunc_t)(void *, TFileMergeInfo *)
Definition: Rtypes.h:116
@ kClassThreadSlot
Definition: TThreadSlots.h:30
void(* DesFunc_t)(void *)
Definition: Rtypes.h:113
TClass * CreateClass(const char *cname, Version_t id, const std::type_info &info, TVirtualIsAProxy *isa, const char *dfil, const char *ifil, Int_t dl, Int_t il)
Global function called by a class' static Dictionary() method (see the ClassDef macro).
Definition: TClass.cxx:5631
void(* DelFunc_t)(void *)
Definition: Rtypes.h:111
ESTLType
Definition: ESTLType.h:28
@ kSTLmap
Definition: ESTLType.h:33
@ kNotSTL
Definition: ESTLType.h:29
@ kSTLmultimap
Definition: ESTLType.h:34
void *(* NewArrFunc_t)(Long_t size, void *arena)
Definition: Rtypes.h:110
void Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector &)
Indirect call to the implementation of ShowMember allowing [forward] declaration with out a full defi...
Definition: TClass.cxx:496
EFunctionMatchMode
Definition: TDictionary.h:152
@ kExactMatch
Definition: TDictionary.h:153
void(* DelArrFunc_t)(void *)
Definition: Rtypes.h:112
void *(* NewFunc_t)(void *)
Definition: Rtypes.h:109
Long64_t(* MergeFunc_t)(void *, TCollection *, TFileMergeInfo *)
Definition: Rtypes.h:115
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
bool IsStdArray(std::string_view name)
Definition: TClassEdit.h:184
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
bool IsInterpreterDetail(const char *type)
Return true if the type is one the interpreter details which are only forward declared (ClassInfo_t e...
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:798
@ kDropTrailStar
Definition: TClassEdit.h:76
@ kDropStlDefault
Definition: TClassEdit.h:81
bool IsSTLBitset(const char *type)
Return true is the name is std::bitset<number> or bitset<number>
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)
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Definition: first.py:1
STL namespace.
bool IsTemplate()
Check if the type is a template.
Definition: TClassEdit.cxx:469
std::vector< std::string > fElements
Definition: TClassEdit.h:138
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12