File indexing completed on 2023-03-17 11:03:36
0001 #include "FWCore/Reflection/interface/TypeWithDict.h"
0002
0003 #include "FWCore/Utilities/interface/EDMException.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "FWCore/Utilities/interface/FriendlyName.h"
0006 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0007 #include "FWCore/Reflection/interface/MemberWithDict.h"
0008 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0009 #include "FWCore/Utilities/interface/TypeDemangler.h"
0010 #include "FWCore/Utilities/interface/TypeID.h"
0011
0012 #include "TClass.h"
0013 #include "TClassTable.h"
0014 #include "TDataType.h"
0015 #include "TEnum.h"
0016 #include "TEnumConstant.h"
0017 #include "TMethodArg.h"
0018 #include "TRealData.h"
0019 #include "TROOT.h"
0020
0021 #include "oneapi/tbb/concurrent_unordered_map.h"
0022
0023 #include <cassert>
0024 #include <cstdio>
0025 #include <cstdlib>
0026 #include <ostream>
0027 #include <typeinfo>
0028 #include <typeindex>
0029
0030 #include <cxxabi.h>
0031
0032
0033 namespace edm {
0034
0035 namespace {
0036 using Map = oneapi::tbb::concurrent_unordered_map<std::string, TypeWithDict>;
0037 Map typeMap;
0038 using FunctionMap = oneapi::tbb::concurrent_unordered_map<std::string, FunctionWithDict>;
0039 FunctionMap functionMap;
0040
0041 struct TypeIndexHash {
0042 std::size_t operator()(std::type_index ti) const { return ti.hash_code(); }
0043 };
0044
0045 using TypeIndexMap = oneapi::tbb::concurrent_unordered_map<std::type_index, TypeWithDict, TypeIndexHash>;
0046 TypeIndexMap typeIndexMap;
0047 }
0048 static void throwTypeException(std::string const& function, std::string const& typeName) {
0049 throw Exception(errors::DictionaryNotFound) << "Function " << function << ",\n"
0050 << "no data dictionary found for type:\n\n"
0051 << typeName << "\nMost likely the dictionary was never generated,\n"
0052 << "but it may be that it was generated in the wrong package.\n"
0053 << "Please add (or move) the specification\n"
0054 << "<class name=\"whatever\"/>\n"
0055 << "to the appropriate classes_def.xml file.\n"
0056 << "If the class is a template instance, you may need\n"
0057 << "to define a dummy variable of this type in classes.h.\n"
0058 << "Also, if this class has any transient members,\n"
0059 << "you need to specify them in classes_def.xml.";
0060 }
0061
0062 TypeWithDict TypeWithDict::byTypeInfo(std::type_info const& ti) {
0063
0064 auto index = std::type_index(ti);
0065 auto const& item = typeIndexMap.find(index);
0066 if (item != typeIndexMap.end()) {
0067 return item->second;
0068 }
0069 TypeWithDict theType(ti, 0L);
0070 typeIndexMap.insert(std::make_pair(index, theType));
0071 return theType;
0072 }
0073
0074 TypeWithDict TypeWithDict::byName(std::string const& name) {
0075
0076 auto const& item = typeMap.find(name);
0077 if (item != typeMap.end()) {
0078 return item->second;
0079 }
0080 TypeWithDict theType = TypeWithDict::byName(name, 0L);
0081 typeMap.insert(std::make_pair(name, theType));
0082 return theType;
0083 }
0084
0085 TypeWithDict TypeWithDict::byName(std::string const& name, long property) {
0086
0087
0088 static std::string const constPrefix("const ");
0089 static std::string const constSuffix(" const");
0090 static size_t const constPrefixSize(constPrefix.size());
0091 static size_t const constSuffixSize(constSuffix.size());
0092
0093
0094 if (name.back() == '&') {
0095 assert(property == 0L);
0096 property |= kIsReference;
0097 return byName(name.substr(0, name.size() - 1), property);
0098 }
0099
0100
0101 if (name.size() > constSuffixSize && name.back() != '*') {
0102 if (name.substr(0, constPrefixSize) == constPrefix) {
0103 property |= kIsConstant;
0104 return byName(name.substr(constPrefixSize), property);
0105 }
0106 if (name.substr(name.size() - constSuffixSize) == constSuffix) {
0107 property |= kIsConstant;
0108 return byName(name.substr(0, name.size() - constSuffixSize), property);
0109 }
0110 }
0111
0112
0113 if (name.back() == '*') {
0114
0115 assert(!(property & (long)kIsPointer));
0116
0117 assert(!(property & (long)kIsArray));
0118 property |= kIsPointer;
0119 if (property & (long)kIsConstant) {
0120 property &= ~((long)kIsConstant);
0121 property |= kIsConstPointer;
0122 }
0123 return byName(name.substr(0, name.size() - 1), property);
0124 }
0125
0126
0127 if (name.back() == ']') {
0128
0129 assert(!(property & (long)kIsPointer));
0130
0131 size_t begin = name.find_last_of("<>:,()");
0132 if (begin == std::string::npos) {
0133 begin = 0;
0134 } else {
0135 ++begin;
0136 }
0137 size_t first = name.find('[', begin);
0138 assert(first != std::string::npos);
0139 assert(first != 0);
0140 TypeWithDict ret = TypeWithDict::byName(name.substr(0, first), property);
0141 ret.property_ |= kIsArray;
0142 ret.arrayDimensions_ = value_ptr<std::vector<size_t> >(new std::vector<size_t>);
0143 std::string const dimensions = name.substr(first);
0144 char const* s = dimensions.c_str();
0145 while (true) {
0146 size_t x = 0;
0147 int count = sscanf(s, "[%lu]", &x);
0148 assert(count == 1);
0149 ret.arrayDimensions_->push_back(x);
0150 ++s;
0151 while (*s != '\0' && *s != '[') {
0152 ++s;
0153 }
0154 if (*s == '\0') {
0155 break;
0156 }
0157 }
0158 return ret;
0159 }
0160
0161
0162 TClass* theClass = TClass::GetClass(name.c_str());
0163 if (theClass != nullptr) {
0164 return TypeWithDict(theClass, property);
0165 }
0166
0167
0168 TEnum* theEnum = TEnum::GetEnum(name.c_str(), TEnum::kAutoload);
0169 if (theEnum) {
0170 return TypeWithDict(theEnum, property);
0171 }
0172
0173
0174 TDataType* theDataType = gROOT->GetType(name.c_str());
0175 if (theDataType) {
0176 switch (theDataType->GetType()) {
0177 case kUInt_t:
0178 return TypeWithDict(typeid(unsigned int), property);
0179 case kInt_t:
0180 return TypeWithDict(typeid(int), property);
0181 case kULong_t:
0182 return TypeWithDict(typeid(unsigned long), property);
0183 case kLong_t:
0184 return TypeWithDict(typeid(long), property);
0185 case kULong64_t:
0186 return TypeWithDict(typeid(unsigned long long), property);
0187 case kLong64_t:
0188 return TypeWithDict(typeid(long long), property);
0189 case kUShort_t:
0190 return TypeWithDict(typeid(unsigned short), property);
0191 case kShort_t:
0192 return TypeWithDict(typeid(short), property);
0193 case kUChar_t:
0194 return TypeWithDict(typeid(unsigned char), property);
0195 case kChar_t:
0196 return TypeWithDict(typeid(char), property);
0197 case kBool_t:
0198 return TypeWithDict(typeid(bool), property);
0199 case kFloat_t:
0200 return TypeWithDict(typeid(float), property);
0201 case kFloat16_t:
0202 return TypeWithDict(typeid(Float16_t), property);
0203 case kDouble_t:
0204 return TypeWithDict(typeid(double), property);
0205 case kDouble32_t:
0206 return TypeWithDict(typeid(Double32_t), property);
0207 case kCharStar:
0208 return TypeWithDict(typeid(char*), property);
0209 case kDataTypeAliasSignedChar_t:
0210 return TypeWithDict(typeid(signed char), property);
0211 }
0212 }
0213
0214 if (name == "void") {
0215 return TypeWithDict(typeid(void), property);
0216 }
0217
0218
0219
0220
0221 if (name == "std::type_info") {
0222 return TypeWithDict(typeid(std::type_info), property);
0223 }
0224
0225
0226
0227 if (stripNamespace(name) == "value_type") {
0228 size_t begin = name.find('<');
0229 size_t end = name.rfind('>');
0230 if (begin != std::string::npos && end != std::string::npos && end > ++begin) {
0231 return TypeWithDict::byName(name.substr(begin, end - begin), property);
0232 }
0233 }
0234
0235 return TypeWithDict();
0236 }
0237
0238 TypeWithDict::TypeWithDict()
0239 : ti_(&typeid(TypeWithDict::invalidType)),
0240 class_(nullptr),
0241 enum_(nullptr),
0242 dataType_(nullptr),
0243 arrayDimensions_(nullptr),
0244 property_(0L) {}
0245
0246 TypeWithDict::TypeWithDict(TypeWithDict const& rhs)
0247 : ti_(rhs.ti_),
0248 class_(rhs.class_),
0249 enum_(rhs.enum_),
0250 dataType_(rhs.dataType_),
0251 arrayDimensions_(rhs.arrayDimensions_),
0252 property_(rhs.property_) {}
0253
0254 TypeWithDict& TypeWithDict::stripConstRef() {
0255 if (isPointer()) {
0256 property_ &= ~((long)kIsReference | (long)kIsConstPointer);
0257 } else {
0258 property_ &= ~((long)kIsConstant | (long)kIsReference);
0259 }
0260 return *this;
0261 }
0262
0263 TypeWithDict& TypeWithDict::operator=(TypeWithDict const& rhs) {
0264 if (this != &rhs) {
0265 ti_ = rhs.ti_;
0266 class_ = rhs.class_;
0267 enum_ = rhs.enum_;
0268 dataType_ = rhs.dataType_;
0269 arrayDimensions_ = rhs.arrayDimensions_;
0270 property_ = rhs.property_;
0271 }
0272 return *this;
0273 }
0274
0275 TypeWithDict::TypeWithDict(std::type_info const& ti) : TypeWithDict(ti, 0L) {}
0276
0277 TypeWithDict::TypeWithDict(std::type_info const& ti, long property )
0278 : ti_(&ti),
0279 class_(TClass::GetClass(ti)),
0280 enum_(nullptr),
0281 dataType_(TDataType::GetDataType(TDataType::GetType(ti))),
0282 arrayDimensions_(nullptr),
0283 property_(property) {
0284 if (class_ != nullptr) {
0285 return;
0286 }
0287
0288
0289
0290 char lastChar = TypeID(*ti_).className().back();
0291 if (lastChar == '*' || lastChar == ']') {
0292 *this = TypeWithDict::byName(TypeID(*ti_).className());
0293 return;
0294 }
0295
0296 if (dataType_ != nullptr) {
0297 return;
0298 }
0299
0300 enum_ = TEnum::GetEnum(ti, TEnum::kAutoload);
0301 if (enum_ != nullptr) {
0302 return;
0303 }
0304
0305 if (ti == typeid(void)) {
0306
0307 dataType_ = gROOT->GetType("void");
0308 return;
0309 }
0310
0311
0312
0313 throwTypeException("TypeWithDict): ", name());
0314 }
0315
0316 TypeWithDict::TypeWithDict(TClass* cl) : TypeWithDict(cl, 0L) {}
0317
0318 TypeWithDict::TypeWithDict(TClass* cl, long property)
0319 : ti_(cl->GetTypeInfo()),
0320 class_(cl),
0321 enum_(nullptr),
0322 dataType_(nullptr),
0323 arrayDimensions_(nullptr),
0324 property_(property) {
0325 if (ti_ == nullptr) {
0326 ti_ = &typeid(TypeWithDict::dummyType);
0327 }
0328 }
0329
0330 TypeWithDict::TypeWithDict(TEnum* enm) : TypeWithDict(enm, 0L) {}
0331
0332 TypeWithDict::TypeWithDict(TEnum* enm, long property)
0333 : ti_(&typeid(TypeWithDict::dummyType)),
0334 class_(nullptr),
0335 enum_(enm),
0336 dataType_(nullptr),
0337 arrayDimensions_(nullptr),
0338 property_(property) {}
0339
0340 TypeWithDict::TypeWithDict(TMethodArg* arg) : TypeWithDict(arg, 0L) {}
0341
0342 TypeWithDict::TypeWithDict(TMethodArg* arg, long property)
0343 : TypeWithDict(byName(arg->GetTypeName(), arg->Property() | property)) {}
0344
0345 TypeWithDict::operator bool() const {
0346 if (*ti_ == typeid(invalidType)) {
0347 return false;
0348 }
0349 if (class_ != nullptr || dataType_ != nullptr || enum_ != nullptr) {
0350 return true;
0351 }
0352 return false;
0353 }
0354
0355 bool TypeWithDict::invalidTypeInfo() const { return *ti_ == typeid(dummyType) || isPointer() || isArray(); }
0356
0357 std::type_info const& TypeWithDict::typeInfo() const {
0358 if (*ti_ == typeid(dummyType) || isPointer() || isArray()) {
0359
0360 if (qualifiedName().c_str() != nullptr) {
0361 std::string category("unknown");
0362 if (isPointer()) {
0363 category = "a pointer";
0364 } else if (isArray()) {
0365 category = "an array";
0366 } else if (isEnum()) {
0367 category = "an enum";
0368 } else if (isClass()) {
0369 throw Exception(errors::DictionaryNotFound) << "No Dictionary for class: '" << name() << "'" << std::endl;
0370 }
0371 throw Exception(errors::LogicError)
0372 << "Function TypeWithDict::typeInfo: Type\n"
0373 << qualifiedName() << "\ndoes not have valid type_info information in ROOT\n"
0374 << "because it is " << category << ".\n";
0375 }
0376 }
0377 return *ti_;
0378 }
0379
0380 TClass* TypeWithDict::getClass() const {
0381 if (isPointer() || isArray()) {
0382 return nullptr;
0383 }
0384 return class_;
0385 }
0386
0387 TEnum* TypeWithDict::getEnum() const {
0388 if (isPointer() || isArray()) {
0389 return nullptr;
0390 }
0391 return enum_;
0392 }
0393
0394 TDataType* TypeWithDict::getDataType() const {
0395 if (isPointer() || isArray()) {
0396 return nullptr;
0397 }
0398 return dataType_;
0399 }
0400
0401 long TypeWithDict::getProperty() const { return property_; }
0402
0403 bool TypeWithDict::isClass() const {
0404
0405 return class_ != nullptr && !isPointer() && !isArray();
0406 }
0407
0408 bool TypeWithDict::isConst() const { return (property_ & (long)kIsConstant); }
0409
0410 bool TypeWithDict::isArray() const { return (property_ & (long)kIsArray); }
0411
0412 bool TypeWithDict::isEnum() const { return enum_ != nullptr && !isPointer() && !isArray(); }
0413
0414 bool TypeWithDict::isFundamental() const { return dataType_ != nullptr && !isPointer() && !isArray(); }
0415
0416 bool TypeWithDict::isPointer() const { return (property_ & (long)kIsPointer); }
0417
0418 bool TypeWithDict::isReference() const { return (property_ & (long)kIsReference); }
0419
0420 bool TypeWithDict::isTemplateInstance() const { return (isClass() && name().back() == '>'); }
0421
0422 bool TypeWithDict::isTypedef() const {
0423 if (class_ != nullptr || dataType_ != nullptr || enum_ != nullptr || *ti_ == typeid(invalidType)) {
0424 return false;
0425 }
0426 return true;
0427 }
0428
0429 bool TypeWithDict::isVirtual() const { return isClass() && (class_->ClassProperty() & (long)kClassHasVirtual); }
0430
0431 void TypeWithDict::print(std::ostream& os) const { os << name(); }
0432
0433 std::string TypeWithDict::cppName() const {
0434 std::string cName = qualifiedName();
0435
0436 replaceString(cName, "ULong64_t", "unsigned long long");
0437 replaceString(cName, "Long64_t", "long long");
0438 return cName;
0439 }
0440
0441 std::string TypeWithDict::qualifiedName() const {
0442 std::string qname(name());
0443 if (isConst() && !isPointer()) {
0444 qname = "const " + qname;
0445 } else if (property_ & kIsConstPointer) {
0446 qname += " const";
0447 }
0448 if (isReference()) {
0449 qname += '&';
0450 }
0451 return qname;
0452 }
0453
0454 std::string TypeWithDict::unscopedName() const { return stripNamespace(name()); }
0455
0456 std::string TypeWithDict::name() const {
0457 if (*ti_ == typeid(invalidType)) {
0458 return std::string();
0459 }
0460 std::ostringstream out;
0461 if (isPointer() && isConst()) {
0462 out << "const ";
0463 }
0464 if (enum_ != nullptr) {
0465 if (enum_->GetClass()) {
0466 out << std::string(enum_->GetClass()->GetName());
0467 out << "::";
0468 }
0469 out << enum_->GetName();
0470 } else if (*ti_ == typeid(dummyType) && isClass()) {
0471 out << class_->GetName();
0472 } else {
0473 out << TypeID(*ti_).className();
0474 }
0475 if (isPointer()) {
0476 out << '*';
0477 }
0478 if (isArray()) {
0479 for (size_t i = 0; i < arrayDimension(); ++i) {
0480 out << '[';
0481 out << std::dec << maximumIndex(i);
0482 out << ']';
0483 }
0484 }
0485 return out.str();
0486 }
0487
0488 std::string TypeWithDict::userClassName() const { return name(); }
0489
0490 std::string TypeWithDict::friendlyClassName() const { return friendlyname::friendlyName(name()); }
0491
0492 size_t TypeWithDict::size() const {
0493 size_t nBytes = 0;
0494 if (isPointer()) {
0495 nBytes = sizeof(void*);
0496 } else if (class_ != nullptr) {
0497 nBytes = class_->GetClassSize();
0498 } else if (dataType_ != nullptr) {
0499 nBytes = dataType_->Size();
0500 } else if (enum_ != nullptr) {
0501 nBytes = sizeof(int);
0502 }
0503 if (isArray()) {
0504 nBytes *= arrayLength();
0505 }
0506 return nBytes;
0507 }
0508
0509 size_t TypeWithDict::arrayLength() const {
0510 assert(isArray());
0511 size_t theLength = 1;
0512 for (size_t i = 0; i < arrayDimension(); ++i) {
0513 theLength *= maximumIndex(i);
0514 }
0515 return theLength;
0516 }
0517
0518 size_t TypeWithDict::arrayDimension() const {
0519 assert(isArray());
0520 return arrayDimensions_->size();
0521 }
0522
0523 size_t TypeWithDict::maximumIndex(size_t dim) const {
0524 assert(isArray());
0525 return (*arrayDimensions_)[dim];
0526 }
0527
0528 size_t TypeWithDict::dataMemberSize() const {
0529 if (isClass()) {
0530 return class_->GetListOfDataMembers()->GetSize();
0531 }
0532 if (isEnum()) {
0533 return enum_->GetConstants()->GetSize();
0534 }
0535 return 0;
0536 }
0537
0538 size_t TypeWithDict::functionMemberSize() const {
0539 if (isClass()) {
0540 return class_->GetListOfMethods()->GetSize();
0541 }
0542 return 0;
0543 }
0544
0545 void const* TypeWithDict::pointerToBaseType(void const* ptr, TypeWithDict const& derivedType) const {
0546 if (!isClass()) {
0547 return ptr;
0548 }
0549 if (this->ti_ == derivedType.ti_ || *this->ti_ == *derivedType.ti_) {
0550 return ptr;
0551 }
0552 int offset = derivedType.getBaseClassOffset(*this);
0553 if (offset < 0) {
0554 return nullptr;
0555 }
0556 return static_cast<char const*>(ptr) + offset;
0557 }
0558
0559 void const* TypeWithDict::pointerToContainedType(void const* ptr, TypeWithDict const& derivedType) const {
0560 if (!isClass()) {
0561 return ptr;
0562 }
0563 return pointerToBaseType(ptr, derivedType);
0564 }
0565
0566 TypeWithDict TypeWithDict::nestedType(char const* nestedName) const { return byName(name() + "::" + nestedName); }
0567
0568 TypeWithDict TypeWithDict::nestedType(std::string const& nestedName) const {
0569 return byName(name() + "::" + nestedName);
0570 }
0571
0572 MemberWithDict TypeWithDict::dataMemberByName(std::string const& member) const {
0573 if (isClass()) {
0574 TDataMember* dataMember = class_->GetDataMember(member.c_str());
0575 if (dataMember == nullptr) {
0576
0577 TRealData* realDataMember = class_->GetRealData(member.c_str());
0578 if (realDataMember != nullptr) {
0579 dataMember = realDataMember->GetDataMember();
0580 }
0581 }
0582 return MemberWithDict(dataMember);
0583 }
0584 if (isEnum()) {
0585 TClass* cl = enum_->GetClass();
0586 return MemberWithDict(cl->GetDataMember(member.c_str()));
0587 }
0588 return MemberWithDict();
0589 }
0590
0591 FunctionWithDict TypeWithDict::functionMemberByName(std::string const& member) const {
0592 if (!isClass()) {
0593 return FunctionWithDict();
0594 }
0595 TMethod* meth = reinterpret_cast<TMethod*>(class_->GetListOfMethods()->FindObject(member.c_str()));
0596 if (meth == nullptr) {
0597 return FunctionWithDict();
0598 }
0599 return FunctionWithDict(meth);
0600 }
0601
0602 FunctionWithDict TypeWithDict::functionMemberByName(std::string const& functionName,
0603 std::string const& proto,
0604 bool isConst) const {
0605 if (!isClass()) {
0606 return FunctionWithDict();
0607 }
0608 std::string const& key = name() + '#' + functionName + '#' + proto;
0609 auto const& item = functionMap.find(key);
0610 if (item != functionMap.end()) {
0611 return item->second;
0612 }
0613 TMethod* meth = class_->GetMethodWithPrototype(
0614 functionName.c_str(), proto.c_str(), isConst, ROOT::kConversionMatch);
0615 if (meth == nullptr) {
0616 return FunctionWithDict();
0617 }
0618 FunctionWithDict theFunction = FunctionWithDict(meth);
0619 functionMap.insert(std::make_pair(key, theFunction));
0620 return theFunction;
0621 }
0622
0623 TypeWithDict TypeWithDict::finalType() const {
0624 if (*ti_ == typeid(invalidType)) {
0625 return TypeWithDict();
0626 }
0627 if (!isClass() && !isFundamental()) {
0628 return *this;
0629 }
0630 return TypeWithDict(*ti_);
0631 }
0632
0633 TypeWithDict TypeWithDict::toType() const {
0634 if (*ti_ == typeid(invalidType)) {
0635 return TypeWithDict();
0636 }
0637 if (isReference()) {
0638 TypeWithDict newType = *this;
0639 newType.property_ &= ~((long)kIsReference);
0640 return newType;
0641 }
0642 if (isPointer()) {
0643 TypeWithDict newType = *this;
0644 newType.property_ &= ~((long)kIsPointer | (long)kIsConstPointer);
0645 return newType;
0646 }
0647 if (isArray()) {
0648 TypeWithDict newType = *this;
0649 size_t size = newType.arrayDimensions_->size();
0650 if (size == 1) {
0651 newType.property_ &= ~((long)kIsArray);
0652 value_ptr<std::vector<size_t> > emptyVec;
0653 newType.arrayDimensions_ = emptyVec;
0654 } else {
0655 std::vector<size_t>& dims = *newType.arrayDimensions_;
0656 for (size_t i = 0; i != size; ++i) {
0657 dims[i] = dims[i + 1];
0658 }
0659 newType.arrayDimensions_->resize(size - 1);
0660 }
0661 return newType;
0662 }
0663 return *this;
0664 }
0665
0666 std::string TypeWithDict::templateName() const {
0667 if (!isTemplateInstance()) {
0668 return "";
0669 }
0670 if (name() == "std::string") {
0671 return std::string("std::basic_string");
0672 }
0673 std::string templateName(name());
0674 auto begin = templateName.find('<');
0675 assert(begin != std::string::npos);
0676 auto end = templateName.rfind('<');
0677 assert(end != std::string::npos);
0678 assert(begin <= end);
0679 if (begin < end) {
0680 int depth = 1;
0681 for (auto idx = begin + 1; idx <= end; ++idx) {
0682 char c = templateName[idx];
0683 if (c == '<') {
0684 if (depth == 0) {
0685 begin = idx;
0686 }
0687 ++depth;
0688 } else if (c == '>') {
0689 --depth;
0690 assert(depth >= 0);
0691 }
0692 }
0693 }
0694 return templateName.substr(0, begin);
0695 }
0696
0697 TypeWithDict TypeWithDict::templateArgumentAt(size_t index) const {
0698 if (!isClass()) {
0699 return TypeWithDict();
0700 }
0701 std::string className(unscopedName());
0702 auto begin = className.find('<');
0703 if (begin == std::string::npos) {
0704 return TypeWithDict();
0705 }
0706 ++begin;
0707 auto end = className.rfind('>');
0708 assert(end != std::string::npos);
0709 assert(begin < end);
0710 int depth = 0;
0711 size_t argCount = 0;
0712 for (auto idx = begin; idx < end; ++idx) {
0713 char c = className[idx];
0714 if (c == '<') {
0715 ++depth;
0716 } else if (c == '>') {
0717 --depth;
0718 assert(depth >= 0);
0719 } else if ((depth == 0) && (c == ',')) {
0720 if (argCount < index) {
0721 begin = idx + 1;
0722 ++argCount;
0723 } else {
0724 end = idx;
0725 break;
0726 }
0727 }
0728 }
0729 assert(depth == 0);
0730 if (argCount < index) {
0731 return TypeWithDict();
0732 }
0733 return byName(className.substr(begin, end - begin));
0734 }
0735
0736 bool TypeWithDict::hasBase(std::string const& basename) const {
0737 if (!isClass()) {
0738 return false;
0739 }
0740 TClass* cl = class_->GetBaseClass(basename.c_str());
0741 if (cl != nullptr) {
0742 return true;
0743 }
0744 return false;
0745 }
0746
0747 bool TypeWithDict::hasBase(TypeWithDict const& basety) const {
0748 if (!isClass()) {
0749 return false;
0750 }
0751 if (basety.class_ == nullptr) {
0752 return false;
0753 }
0754 TClass* cl = class_->GetBaseClass(basety.name().c_str());
0755 if (cl != nullptr) {
0756 return true;
0757 }
0758 return false;
0759 }
0760
0761 int TypeWithDict::getBaseClassOffset(TypeWithDict const& baseClass) const {
0762 if (!isClass()) {
0763 throw Exception(errors::LogicError) << "Function TypeWithDict::getBaseClassOffset(), type\n"
0764 << name() << "\nis not a class\n";
0765 }
0766 if (baseClass.class_ == nullptr) {
0767 throw Exception(errors::LogicError) << "Function TypeWithDict::getBaseClassOffset(), base type\n"
0768 << name() << "\nis not a class\n";
0769 }
0770 int offset = class_->GetBaseClassOffset(baseClass.class_);
0771 return offset;
0772 }
0773
0774 int TypeWithDict::stringToEnumValue(std::string const& name) const {
0775 if (!isEnum()) {
0776 throw Exception(errors::LogicError) << "Function TypeWithDict::stringToEnumValue(), type\n"
0777 << name << "\nis not an enum\n";
0778 }
0779 TEnumConstant const* ec = enum_->GetConstant(name.c_str());
0780 if (!ec) {
0781 throw Exception(errors::LogicError) << "Function TypeWithDict::stringToEnumValue(), type\n"
0782 << name << "\nis not an enum constant\n";
0783 }
0784 return static_cast<int>(ec->GetValue());
0785 }
0786
0787 void* TypeWithDict::allocate() const { return new char[size()]; }
0788
0789 void TypeWithDict::deallocate(void* address) const { delete[] reinterpret_cast<char*>(address); }
0790
0791 ObjectWithDict TypeWithDict::construct() const {
0792 if (isClass()) {
0793 return ObjectWithDict(*this, class_->New());
0794 }
0795 return ObjectWithDict(*this, new char[size()]);
0796 }
0797
0798 void TypeWithDict::destruct(void* address, bool dealloc) const {
0799 if (isClass()) {
0800 class_->Destructor(address, !dealloc);
0801 return;
0802 }
0803 if (dealloc) {
0804 delete[] reinterpret_cast<char*>(address);
0805 }
0806 }
0807
0808
0809 bool hasDictionary(std::type_info const& ti) {
0810 if (ti.name()[1] == '\0') {
0811
0812 return true;
0813 }
0814 return (TClassTable::GetDict(ti) != nullptr);
0815 }
0816
0817 bool operator==(TypeWithDict const& a, TypeWithDict const& b) { return a.name() == b.name(); }
0818
0819 bool operator==(TypeWithDict const& a, std::type_info const& b) {
0820 if (*a.ti_ == typeid(TypeWithDict::dummyType) || a.isPointer() || a.isArray()) {
0821
0822 return a.name() == TypeID(b).className();
0823 }
0824 return *a.ti_ == b;
0825 }
0826
0827 std::ostream& operator<<(std::ostream& os, TypeWithDict const& ty) {
0828 ty.print(os);
0829 return os;
0830 }
0831
0832
0833
0834
0835
0836 TypeBases::TypeBases(TypeWithDict const& type) : class_(type.getClass()) {}
0837
0838 IterWithDict<TBaseClass> TypeBases::begin() const {
0839 if (class_ == nullptr) {
0840 return IterWithDict<TBaseClass>();
0841 }
0842 return IterWithDict<TBaseClass>(class_->GetListOfBases());
0843 }
0844
0845 IterWithDict<TBaseClass> TypeBases::end() const { return IterWithDict<TBaseClass>(); }
0846
0847 size_t TypeBases::size() const {
0848 if (class_ == nullptr) {
0849 return 0;
0850 }
0851 return class_->GetListOfBases()->GetSize();
0852 }
0853
0854
0855
0856
0857
0858 TypeDataMembers::TypeDataMembers(TypeWithDict const& type) : class_(type.getClass()) {}
0859
0860 IterWithDict<TDataMember> TypeDataMembers::begin() const {
0861 if (class_ == nullptr) {
0862 return IterWithDict<TDataMember>();
0863 }
0864 return IterWithDict<TDataMember>(class_->GetListOfDataMembers());
0865 }
0866
0867 IterWithDict<TDataMember> TypeDataMembers::end() const { return IterWithDict<TDataMember>(); }
0868
0869 size_t TypeDataMembers::size() const {
0870 if (class_ == nullptr) {
0871 return 0;
0872 }
0873 return class_->GetListOfDataMembers()->GetSize();
0874 }
0875
0876
0877
0878
0879
0880 TypeFunctionMembers::TypeFunctionMembers(TypeWithDict const& type) : class_(type.getClass()) {}
0881
0882 IterWithDict<TMethod> TypeFunctionMembers::begin() const {
0883 if (class_ == nullptr) {
0884 return IterWithDict<TMethod>();
0885 }
0886 return IterWithDict<TMethod>(class_->GetListOfMethods());
0887 }
0888
0889 IterWithDict<TMethod> TypeFunctionMembers::end() const { return IterWithDict<TMethod>(); }
0890
0891 size_t TypeFunctionMembers::size() const {
0892 if (class_ == nullptr) {
0893 return 0;
0894 }
0895 return class_->GetListOfMethods(kFALSE)->GetSize();
0896 }
0897
0898 }