File indexing completed on 2024-04-06 12:13:01
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 = nullptr;
0163 try {
0164 theClass = TClass::GetClass(name.c_str());
0165 } catch (cms::Exception& e) {
0166 e.addContext("Calling edm::TypeWithDict::byName()");
0167 e.addAdditionalInfo("Getting TClass for " + name);
0168 throw;
0169 }
0170 if (theClass != nullptr) {
0171 return TypeWithDict(theClass, property);
0172 }
0173
0174
0175 TEnum* theEnum = TEnum::GetEnum(name.c_str(), TEnum::kAutoload);
0176 if (theEnum) {
0177 return TypeWithDict(theEnum, property);
0178 }
0179
0180
0181 TDataType* theDataType = gROOT->GetType(name.c_str());
0182 if (theDataType) {
0183 switch (theDataType->GetType()) {
0184 case kUInt_t:
0185 return TypeWithDict(typeid(unsigned int), property);
0186 case kInt_t:
0187 return TypeWithDict(typeid(int), property);
0188 case kULong_t:
0189 return TypeWithDict(typeid(unsigned long), property);
0190 case kLong_t:
0191 return TypeWithDict(typeid(long), property);
0192 case kULong64_t:
0193 return TypeWithDict(typeid(unsigned long long), property);
0194 case kLong64_t:
0195 return TypeWithDict(typeid(long long), property);
0196 case kUShort_t:
0197 return TypeWithDict(typeid(unsigned short), property);
0198 case kShort_t:
0199 return TypeWithDict(typeid(short), property);
0200 case kUChar_t:
0201 return TypeWithDict(typeid(unsigned char), property);
0202 case kChar_t:
0203 return TypeWithDict(typeid(char), property);
0204 case kBool_t:
0205 return TypeWithDict(typeid(bool), property);
0206 case kFloat_t:
0207 return TypeWithDict(typeid(float), property);
0208 case kFloat16_t:
0209 return TypeWithDict(typeid(Float16_t), property);
0210 case kDouble_t:
0211 return TypeWithDict(typeid(double), property);
0212 case kDouble32_t:
0213 return TypeWithDict(typeid(Double32_t), property);
0214 case kCharStar:
0215 return TypeWithDict(typeid(char*), property);
0216 case kDataTypeAliasSignedChar_t:
0217 return TypeWithDict(typeid(signed char), property);
0218 }
0219 }
0220
0221 if (name == "void") {
0222 return TypeWithDict(typeid(void), property);
0223 }
0224
0225
0226
0227
0228 if (name == "std::type_info") {
0229 return TypeWithDict(typeid(std::type_info), property);
0230 }
0231
0232
0233
0234 if (stripNamespace(name) == "value_type") {
0235 size_t begin = name.find('<');
0236 size_t end = name.rfind('>');
0237 if (begin != std::string::npos && end != std::string::npos && end > ++begin) {
0238 return TypeWithDict::byName(name.substr(begin, end - begin), property);
0239 }
0240 }
0241
0242 return TypeWithDict();
0243 }
0244
0245 TypeWithDict::TypeWithDict()
0246 : ti_(&typeid(TypeWithDict::invalidType)),
0247 class_(nullptr),
0248 enum_(nullptr),
0249 dataType_(nullptr),
0250 arrayDimensions_(nullptr),
0251 property_(0L) {}
0252
0253 TypeWithDict::TypeWithDict(TypeWithDict const& rhs)
0254 : ti_(rhs.ti_),
0255 class_(rhs.class_),
0256 enum_(rhs.enum_),
0257 dataType_(rhs.dataType_),
0258 arrayDimensions_(rhs.arrayDimensions_),
0259 property_(rhs.property_) {}
0260
0261 TypeWithDict& TypeWithDict::stripConstRef() {
0262 if (isPointer()) {
0263 property_ &= ~((long)kIsReference | (long)kIsConstPointer);
0264 } else {
0265 property_ &= ~((long)kIsConstant | (long)kIsReference);
0266 }
0267 return *this;
0268 }
0269
0270 TypeWithDict& TypeWithDict::operator=(TypeWithDict const& rhs) {
0271 if (this != &rhs) {
0272 ti_ = rhs.ti_;
0273 class_ = rhs.class_;
0274 enum_ = rhs.enum_;
0275 dataType_ = rhs.dataType_;
0276 arrayDimensions_ = rhs.arrayDimensions_;
0277 property_ = rhs.property_;
0278 }
0279 return *this;
0280 }
0281
0282 TypeWithDict::TypeWithDict(std::type_info const& ti) : TypeWithDict(ti, 0L) {}
0283
0284 TypeWithDict::TypeWithDict(std::type_info const& ti, long property )
0285 : ti_(&ti),
0286 class_(TClass::GetClass(ti)),
0287 enum_(nullptr),
0288 dataType_(TDataType::GetDataType(TDataType::GetType(ti))),
0289 arrayDimensions_(nullptr),
0290 property_(property) {
0291 if (class_ != nullptr) {
0292 return;
0293 }
0294
0295
0296
0297 char lastChar = TypeID(*ti_).className().back();
0298 if (lastChar == '*' || lastChar == ']') {
0299 *this = TypeWithDict::byName(TypeID(*ti_).className());
0300 return;
0301 }
0302
0303 if (dataType_ != nullptr) {
0304 return;
0305 }
0306
0307 enum_ = TEnum::GetEnum(ti, TEnum::kAutoload);
0308 if (enum_ != nullptr) {
0309 return;
0310 }
0311
0312 if (ti == typeid(void)) {
0313
0314 dataType_ = gROOT->GetType("void");
0315 return;
0316 }
0317
0318
0319
0320 throwTypeException("TypeWithDict): ", name());
0321 }
0322
0323 TypeWithDict::TypeWithDict(TClass* cl) : TypeWithDict(cl, 0L) {}
0324
0325 TypeWithDict::TypeWithDict(TClass* cl, long property)
0326 : ti_(cl->GetTypeInfo()),
0327 class_(cl),
0328 enum_(nullptr),
0329 dataType_(nullptr),
0330 arrayDimensions_(nullptr),
0331 property_(property) {
0332 if (ti_ == nullptr) {
0333 ti_ = &typeid(TypeWithDict::dummyType);
0334 }
0335 }
0336
0337 TypeWithDict::TypeWithDict(TEnum* enm) : TypeWithDict(enm, 0L) {}
0338
0339 TypeWithDict::TypeWithDict(TEnum* enm, long property)
0340 : ti_(&typeid(TypeWithDict::dummyType)),
0341 class_(nullptr),
0342 enum_(enm),
0343 dataType_(nullptr),
0344 arrayDimensions_(nullptr),
0345 property_(property) {}
0346
0347 TypeWithDict::TypeWithDict(TMethodArg* arg) : TypeWithDict(arg, 0L) {}
0348
0349 TypeWithDict::TypeWithDict(TMethodArg* arg, long property)
0350 : TypeWithDict(byName(arg->GetTypeName(), arg->Property() | property)) {}
0351
0352 TypeWithDict::operator bool() const {
0353 if (*ti_ == typeid(invalidType)) {
0354 return false;
0355 }
0356 if (class_ != nullptr || dataType_ != nullptr || enum_ != nullptr) {
0357 return true;
0358 }
0359 return false;
0360 }
0361
0362 bool TypeWithDict::invalidTypeInfo() const { return *ti_ == typeid(dummyType) || isPointer() || isArray(); }
0363
0364 std::type_info const& TypeWithDict::typeInfo() const {
0365 if (*ti_ == typeid(dummyType) || isPointer() || isArray()) {
0366
0367 if (qualifiedName().c_str() != nullptr) {
0368 std::string category("unknown");
0369 if (isPointer()) {
0370 category = "a pointer";
0371 } else if (isArray()) {
0372 category = "an array";
0373 } else if (isEnum()) {
0374 category = "an enum";
0375 } else if (isClass()) {
0376 throw Exception(errors::DictionaryNotFound) << "No Dictionary for class: '" << name() << "'" << std::endl;
0377 }
0378 throw Exception(errors::LogicError)
0379 << "Function TypeWithDict::typeInfo: Type\n"
0380 << qualifiedName() << "\ndoes not have valid type_info information in ROOT\n"
0381 << "because it is " << category << ".\n";
0382 }
0383 }
0384 return *ti_;
0385 }
0386
0387 TClass* TypeWithDict::getClass() const {
0388 if (isPointer() || isArray()) {
0389 return nullptr;
0390 }
0391 return class_;
0392 }
0393
0394 TEnum* TypeWithDict::getEnum() const {
0395 if (isPointer() || isArray()) {
0396 return nullptr;
0397 }
0398 return enum_;
0399 }
0400
0401 TDataType* TypeWithDict::getDataType() const {
0402 if (isPointer() || isArray()) {
0403 return nullptr;
0404 }
0405 return dataType_;
0406 }
0407
0408 long TypeWithDict::getProperty() const { return property_; }
0409
0410 bool TypeWithDict::isClass() const {
0411
0412 return class_ != nullptr && !isPointer() && !isArray();
0413 }
0414
0415 bool TypeWithDict::isConst() const { return (property_ & (long)kIsConstant); }
0416
0417 bool TypeWithDict::isArray() const { return (property_ & (long)kIsArray); }
0418
0419 bool TypeWithDict::isEnum() const { return enum_ != nullptr && !isPointer() && !isArray(); }
0420
0421 bool TypeWithDict::isFundamental() const { return dataType_ != nullptr && !isPointer() && !isArray(); }
0422
0423 bool TypeWithDict::isPointer() const { return (property_ & (long)kIsPointer); }
0424
0425 bool TypeWithDict::isReference() const { return (property_ & (long)kIsReference); }
0426
0427 bool TypeWithDict::isTemplateInstance() const { return (isClass() && name().back() == '>'); }
0428
0429 bool TypeWithDict::isTypedef() const {
0430 if (class_ != nullptr || dataType_ != nullptr || enum_ != nullptr || *ti_ == typeid(invalidType)) {
0431 return false;
0432 }
0433 return true;
0434 }
0435
0436 bool TypeWithDict::isVirtual() const { return isClass() && (class_->ClassProperty() & (long)kClassHasVirtual); }
0437
0438 void TypeWithDict::print(std::ostream& os) const { os << name(); }
0439
0440 std::string TypeWithDict::cppName() const {
0441 std::string cName = qualifiedName();
0442
0443 replaceString(cName, "ULong64_t", "unsigned long long");
0444 replaceString(cName, "Long64_t", "long long");
0445 return cName;
0446 }
0447
0448 std::string TypeWithDict::qualifiedName() const {
0449 std::string qname(name());
0450 if (isConst() && !isPointer()) {
0451 qname = "const " + qname;
0452 } else if (property_ & kIsConstPointer) {
0453 qname += " const";
0454 }
0455 if (isReference()) {
0456 qname += '&';
0457 }
0458 return qname;
0459 }
0460
0461 std::string TypeWithDict::unscopedName() const { return stripNamespace(name()); }
0462
0463 std::string TypeWithDict::name() const {
0464 if (*ti_ == typeid(invalidType)) {
0465 return std::string();
0466 }
0467 std::ostringstream out;
0468 if (isPointer() && isConst()) {
0469 out << "const ";
0470 }
0471 if (enum_ != nullptr) {
0472 if (enum_->GetClass()) {
0473 out << std::string(enum_->GetClass()->GetName());
0474 out << "::";
0475 }
0476 out << enum_->GetName();
0477 } else if (*ti_ == typeid(dummyType) && isClass()) {
0478 out << class_->GetName();
0479 } else {
0480 out << TypeID(*ti_).className();
0481 }
0482 if (isPointer()) {
0483 out << '*';
0484 }
0485 if (isArray()) {
0486 for (size_t i = 0; i < arrayDimension(); ++i) {
0487 out << '[';
0488 out << std::dec << maximumIndex(i);
0489 out << ']';
0490 }
0491 }
0492 return out.str();
0493 }
0494
0495 std::string TypeWithDict::userClassName() const { return name(); }
0496
0497 std::string TypeWithDict::friendlyClassName() const { return friendlyname::friendlyName(name()); }
0498
0499 size_t TypeWithDict::size() const {
0500 size_t nBytes = 0;
0501 if (isPointer()) {
0502 nBytes = sizeof(void*);
0503 } else if (class_ != nullptr) {
0504 nBytes = class_->GetClassSize();
0505 } else if (dataType_ != nullptr) {
0506 nBytes = dataType_->Size();
0507 } else if (enum_ != nullptr) {
0508 nBytes = sizeof(int);
0509 }
0510 if (isArray()) {
0511 nBytes *= arrayLength();
0512 }
0513 return nBytes;
0514 }
0515
0516 size_t TypeWithDict::arrayLength() const {
0517 assert(isArray());
0518 size_t theLength = 1;
0519 for (size_t i = 0; i < arrayDimension(); ++i) {
0520 theLength *= maximumIndex(i);
0521 }
0522 return theLength;
0523 }
0524
0525 size_t TypeWithDict::arrayDimension() const {
0526 assert(isArray());
0527 return arrayDimensions_->size();
0528 }
0529
0530 size_t TypeWithDict::maximumIndex(size_t dim) const {
0531 assert(isArray());
0532 return (*arrayDimensions_)[dim];
0533 }
0534
0535 size_t TypeWithDict::dataMemberSize() const {
0536 if (isClass()) {
0537 return class_->GetListOfDataMembers()->GetSize();
0538 }
0539 if (isEnum()) {
0540 return enum_->GetConstants()->GetSize();
0541 }
0542 return 0;
0543 }
0544
0545 size_t TypeWithDict::functionMemberSize() const {
0546 if (isClass()) {
0547 return class_->GetListOfMethods()->GetSize();
0548 }
0549 return 0;
0550 }
0551
0552 void const* TypeWithDict::pointerToBaseType(void const* ptr, TypeWithDict const& derivedType) const {
0553 if (!isClass()) {
0554 return ptr;
0555 }
0556 if (this->ti_ == derivedType.ti_ || *this->ti_ == *derivedType.ti_) {
0557 return ptr;
0558 }
0559 int offset = derivedType.getBaseClassOffset(*this);
0560 if (offset < 0) {
0561 return nullptr;
0562 }
0563 return static_cast<char const*>(ptr) + offset;
0564 }
0565
0566 void const* TypeWithDict::pointerToContainedType(void const* ptr, TypeWithDict const& derivedType) const {
0567 if (!isClass()) {
0568 return ptr;
0569 }
0570 return pointerToBaseType(ptr, derivedType);
0571 }
0572
0573 TypeWithDict TypeWithDict::nestedType(char const* nestedName) const { return byName(name() + "::" + nestedName); }
0574
0575 TypeWithDict TypeWithDict::nestedType(std::string const& nestedName) const {
0576 return byName(name() + "::" + nestedName);
0577 }
0578
0579 MemberWithDict TypeWithDict::dataMemberByName(std::string const& member) const {
0580 if (isClass()) {
0581 TDataMember* dataMember = class_->GetDataMember(member.c_str());
0582 if (dataMember == nullptr) {
0583
0584 TRealData* realDataMember = class_->GetRealData(member.c_str());
0585 if (realDataMember != nullptr) {
0586 dataMember = realDataMember->GetDataMember();
0587 }
0588 }
0589 return MemberWithDict(dataMember);
0590 }
0591 if (isEnum()) {
0592 TClass* cl = enum_->GetClass();
0593 return MemberWithDict(cl->GetDataMember(member.c_str()));
0594 }
0595 return MemberWithDict();
0596 }
0597
0598 FunctionWithDict TypeWithDict::functionMemberByName(std::string const& member) const {
0599 if (!isClass()) {
0600 return FunctionWithDict();
0601 }
0602 TMethod* meth = reinterpret_cast<TMethod*>(class_->GetListOfMethods()->FindObject(member.c_str()));
0603 if (meth == nullptr) {
0604 return FunctionWithDict();
0605 }
0606 return FunctionWithDict(meth);
0607 }
0608
0609 FunctionWithDict TypeWithDict::functionMemberByName(std::string const& functionName,
0610 std::string const& proto,
0611 bool isConst) const {
0612 if (!isClass()) {
0613 return FunctionWithDict();
0614 }
0615 std::string const& key = name() + '#' + functionName + '#' + proto;
0616 auto const& item = functionMap.find(key);
0617 if (item != functionMap.end()) {
0618 return item->second;
0619 }
0620 TMethod* meth = class_->GetMethodWithPrototype(
0621 functionName.c_str(), proto.c_str(), isConst, ROOT::kConversionMatch);
0622 if (meth == nullptr) {
0623 return FunctionWithDict();
0624 }
0625 FunctionWithDict theFunction = FunctionWithDict(meth);
0626 functionMap.insert(std::make_pair(key, theFunction));
0627 return theFunction;
0628 }
0629
0630 TypeWithDict TypeWithDict::finalType() const {
0631 if (*ti_ == typeid(invalidType)) {
0632 return TypeWithDict();
0633 }
0634 if (!isClass() && !isFundamental()) {
0635 return *this;
0636 }
0637 return TypeWithDict(*ti_);
0638 }
0639
0640 TypeWithDict TypeWithDict::toType() const {
0641 if (*ti_ == typeid(invalidType)) {
0642 return TypeWithDict();
0643 }
0644 if (isReference()) {
0645 TypeWithDict newType = *this;
0646 newType.property_ &= ~((long)kIsReference);
0647 return newType;
0648 }
0649 if (isPointer()) {
0650 TypeWithDict newType = *this;
0651 newType.property_ &= ~((long)kIsPointer | (long)kIsConstPointer);
0652 return newType;
0653 }
0654 if (isArray()) {
0655 TypeWithDict newType = *this;
0656 size_t size = newType.arrayDimensions_->size();
0657 if (size == 1) {
0658 newType.property_ &= ~((long)kIsArray);
0659 value_ptr<std::vector<size_t> > emptyVec;
0660 newType.arrayDimensions_ = emptyVec;
0661 } else {
0662 std::vector<size_t>& dims = *newType.arrayDimensions_;
0663 for (size_t i = 0; i != size; ++i) {
0664 dims[i] = dims[i + 1];
0665 }
0666 newType.arrayDimensions_->resize(size - 1);
0667 }
0668 return newType;
0669 }
0670 return *this;
0671 }
0672
0673 std::string TypeWithDict::templateName() const {
0674 if (!isTemplateInstance()) {
0675 return "";
0676 }
0677 if (name() == "std::string") {
0678 return std::string("std::basic_string");
0679 }
0680 std::string templateName(name());
0681 auto begin = templateName.find('<');
0682 assert(begin != std::string::npos);
0683 auto end = templateName.rfind('<');
0684 assert(end != std::string::npos);
0685 assert(begin <= end);
0686 if (begin < end) {
0687 int depth = 1;
0688 for (auto idx = begin + 1; idx <= end; ++idx) {
0689 char c = templateName[idx];
0690 if (c == '<') {
0691 if (depth == 0) {
0692 begin = idx;
0693 }
0694 ++depth;
0695 } else if (c == '>') {
0696 --depth;
0697 assert(depth >= 0);
0698 }
0699 }
0700 }
0701 return templateName.substr(0, begin);
0702 }
0703
0704 TypeWithDict TypeWithDict::templateArgumentAt(size_t index) const {
0705 if (!isClass()) {
0706 return TypeWithDict();
0707 }
0708 std::string className(unscopedName());
0709 auto begin = className.find('<');
0710 if (begin == std::string::npos) {
0711 return TypeWithDict();
0712 }
0713 ++begin;
0714 auto end = className.rfind('>');
0715 assert(end != std::string::npos);
0716 assert(begin < end);
0717 int depth = 0;
0718 size_t argCount = 0;
0719 for (auto idx = begin; idx < end; ++idx) {
0720 char c = className[idx];
0721 if (c == '<') {
0722 ++depth;
0723 } else if (c == '>') {
0724 --depth;
0725 assert(depth >= 0);
0726 } else if ((depth == 0) && (c == ',')) {
0727 if (argCount < index) {
0728 begin = idx + 1;
0729 ++argCount;
0730 } else {
0731 end = idx;
0732 break;
0733 }
0734 }
0735 }
0736 assert(depth == 0);
0737 if (argCount < index) {
0738 return TypeWithDict();
0739 }
0740 return byName(className.substr(begin, end - begin));
0741 }
0742
0743 bool TypeWithDict::hasBase(std::string const& basename) const {
0744 if (!isClass()) {
0745 return false;
0746 }
0747 TClass* cl = class_->GetBaseClass(basename.c_str());
0748 if (cl != nullptr) {
0749 return true;
0750 }
0751 return false;
0752 }
0753
0754 bool TypeWithDict::hasBase(TypeWithDict const& basety) const {
0755 if (!isClass()) {
0756 return false;
0757 }
0758 if (basety.class_ == nullptr) {
0759 return false;
0760 }
0761 TClass* cl = class_->GetBaseClass(basety.name().c_str());
0762 if (cl != nullptr) {
0763 return true;
0764 }
0765 return false;
0766 }
0767
0768 int TypeWithDict::getBaseClassOffset(TypeWithDict const& baseClass) const {
0769 if (!isClass()) {
0770 throw Exception(errors::LogicError) << "Function TypeWithDict::getBaseClassOffset(), type\n"
0771 << name() << "\nis not a class\n";
0772 }
0773 if (baseClass.class_ == nullptr) {
0774 throw Exception(errors::LogicError) << "Function TypeWithDict::getBaseClassOffset(), base type\n"
0775 << name() << "\nis not a class\n";
0776 }
0777 int offset = class_->GetBaseClassOffset(baseClass.class_);
0778 return offset;
0779 }
0780
0781 int TypeWithDict::stringToEnumValue(std::string const& name) const {
0782 if (!isEnum()) {
0783 throw Exception(errors::LogicError) << "Function TypeWithDict::stringToEnumValue(), type\n"
0784 << name << "\nis not an enum\n";
0785 }
0786 TEnumConstant const* ec = enum_->GetConstant(name.c_str());
0787 if (!ec) {
0788 throw Exception(errors::LogicError) << "Function TypeWithDict::stringToEnumValue(), type\n"
0789 << name << "\nis not an enum constant\n";
0790 }
0791 return static_cast<int>(ec->GetValue());
0792 }
0793
0794 void* TypeWithDict::allocate() const { return new char[size()]; }
0795
0796 void TypeWithDict::deallocate(void* address) const { delete[] reinterpret_cast<char*>(address); }
0797
0798 ObjectWithDict TypeWithDict::construct() const {
0799 if (isClass()) {
0800 return ObjectWithDict(*this, class_->New());
0801 }
0802 return ObjectWithDict(*this, new char[size()]);
0803 }
0804
0805 void TypeWithDict::destruct(void* address, bool dealloc) const {
0806 if (isClass()) {
0807 class_->Destructor(address, !dealloc);
0808 return;
0809 }
0810 if (dealloc) {
0811 delete[] reinterpret_cast<char*>(address);
0812 }
0813 }
0814
0815
0816 bool hasDictionary(std::type_info const& ti) {
0817 if (ti.name()[1] == '\0') {
0818
0819 return true;
0820 }
0821 return (TClassTable::GetDict(ti) != nullptr);
0822 }
0823
0824 bool operator==(TypeWithDict const& a, TypeWithDict const& b) { return a.name() == b.name(); }
0825
0826 bool operator==(TypeWithDict const& a, std::type_info const& b) {
0827 if (*a.ti_ == typeid(TypeWithDict::dummyType) || a.isPointer() || a.isArray()) {
0828
0829 return a.name() == TypeID(b).className();
0830 }
0831 return *a.ti_ == b;
0832 }
0833
0834 std::ostream& operator<<(std::ostream& os, TypeWithDict const& ty) {
0835 ty.print(os);
0836 return os;
0837 }
0838
0839
0840
0841
0842
0843 TypeBases::TypeBases(TypeWithDict const& type) : class_(type.getClass()) {}
0844
0845 IterWithDict<TBaseClass> TypeBases::begin() const {
0846 if (class_ == nullptr) {
0847 return IterWithDict<TBaseClass>();
0848 }
0849 return IterWithDict<TBaseClass>(class_->GetListOfBases());
0850 }
0851
0852 IterWithDict<TBaseClass> TypeBases::end() const { return IterWithDict<TBaseClass>(); }
0853
0854 size_t TypeBases::size() const {
0855 if (class_ == nullptr) {
0856 return 0;
0857 }
0858 return class_->GetListOfBases()->GetSize();
0859 }
0860
0861
0862
0863
0864
0865 TypeDataMembers::TypeDataMembers(TypeWithDict const& type) : class_(type.getClass()) {}
0866
0867 IterWithDict<TDataMember> TypeDataMembers::begin() const {
0868 if (class_ == nullptr) {
0869 return IterWithDict<TDataMember>();
0870 }
0871 return IterWithDict<TDataMember>(class_->GetListOfDataMembers());
0872 }
0873
0874 IterWithDict<TDataMember> TypeDataMembers::end() const { return IterWithDict<TDataMember>(); }
0875
0876 size_t TypeDataMembers::size() const {
0877 if (class_ == nullptr) {
0878 return 0;
0879 }
0880 return class_->GetListOfDataMembers()->GetSize();
0881 }
0882
0883
0884
0885
0886
0887 TypeFunctionMembers::TypeFunctionMembers(TypeWithDict const& type) : class_(type.getClass()) {}
0888
0889 IterWithDict<TMethod> TypeFunctionMembers::begin() const {
0890 if (class_ == nullptr) {
0891 return IterWithDict<TMethod>();
0892 }
0893 return IterWithDict<TMethod>(class_->GetListOfMethods());
0894 }
0895
0896 IterWithDict<TMethod> TypeFunctionMembers::end() const { return IterWithDict<TMethod>(); }
0897
0898 size_t TypeFunctionMembers::size() const {
0899 if (class_ == nullptr) {
0900 return 0;
0901 }
0902 return class_->GetListOfMethods(kFALSE)->GetSize();
0903 }
0904
0905 }