diff --git a/CommonTools/Utils/src/ExpressionVar.cc b/CommonTools/Utils/src/ExpressionVar.cc index 441bbd75227cb..acb2aa5df5243 100755 --- a/CommonTools/Utils/src/ExpressionVar.cc +++ b/CommonTools/Utils/src/ExpressionVar.cc @@ -1,142 +1,217 @@ #include "CommonTools/Utils/src/ExpressionVar.h" +#include "CommonTools/Utils/src/MethodInvoker.h" + #include "FWCore/Utilities/interface/ObjectWithDict.h" #include "FWCore/Utilities/interface/FunctionWithDict.h" #include "FWCore/Utilities/interface/MemberWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" + +#include #include -#include + using namespace reco::parser; using namespace std; -ExpressionVar::ExpressionVar(const vector& methods, method::TypeCode retType) : - methods_(methods), retType_(retType) { - initObjects_(); +void ExpressionVar::initObjects_() +{ + objects_.resize(methods_.size()); + std::vector::iterator IO = objects_.begin(); + for (std::vector::const_iterator I = methods_.begin(), E = methods_.end(); I != E; ++IO, ++I) { + if (I->isFunction()) { + edm::TypeWithDict retType = I->method().finalReturnType(); + needsDestructor_.push_back(makeStorage(*IO, retType)); + } + else { + *IO = edm::ObjectWithDict(); + needsDestructor_.push_back(false); + } + } } -ExpressionVar::ExpressionVar(const ExpressionVar &other) : - methods_(other.methods_), retType_(other.retType_) { - initObjects_(); +ExpressionVar::ExpressionVar(const vector& methods, + method::TypeCode retType) + : methods_(methods) + , retType_(retType) +{ + initObjects_(); } -ExpressionVar::~ExpressionVar() { - for(std::vector::iterator it = objects_.begin(); it != objects_.end(); ++it) { - delStorage(*it); - } - objects_.clear(); +ExpressionVar::ExpressionVar(const ExpressionVar& rhs) + : methods_(rhs.methods_) + , retType_(rhs.retType_) +{ + initObjects_(); } -void -ExpressionVar::delStorage(edm::ObjectWithDict &obj) { - if (obj.address() != 0) { - if (obj.typeOf().isPointer() || obj.typeOf().isReference()) { - // just delete a void *, as that's what it was - void **p = static_cast(obj.address()); - delete p; - } else { - //std::cout << "Calling Destruct on a " << obj.typeOf().qualifiedName() << std::endl; - obj.typeOf().deallocate(obj.address()); - } - } +ExpressionVar::~ExpressionVar() +{ + for (std::vector::iterator I = objects_.begin(), + E = objects_.end(); I != E; ++I) { + delStorage(*I); + } + objects_.clear(); } -void ExpressionVar::initObjects_() { - objects_.resize(methods_.size()); - std::vector::const_iterator it = methods_.begin(), ed = methods_.end(); - std::vector::iterator itobj = objects_.begin(); - for (; it != ed; ++it, ++itobj) { - if(it->isFunction()) { - edm::TypeWithDict retType = it->method().finalReturnType(); - needsDestructor_.push_back(makeStorage(*itobj, retType)); - } else { - *itobj = edm::ObjectWithDict(); - needsDestructor_.push_back(false); - } - } +void +ExpressionVar::delStorage(edm::ObjectWithDict& obj) +{ + if (!obj.address()) { + return; + } + if (obj.typeOf().isPointer() || obj.typeOf().isReference()) { + // just delete a void*, as that's what it was + void** p = static_cast(obj.address()); + delete p; + } + else { + //std::cout << "Calling Destruct on a " << + // obj.typeOf().qualifiedName() << std::endl; + obj.typeOf().deallocate(obj.address()); + } } bool -ExpressionVar::makeStorage(edm::ObjectWithDict &obj, const edm::TypeWithDict &retType) { - bool ret = false; - static edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void")); - if (retType == tVoid) { - obj = edm::ObjectWithDict::byType(tVoid); - } else if (retType.isPointer() || retType.isReference()) { - // in this case, I have to allocate a void *, not an object! - obj = edm::ObjectWithDict(retType, new void *); - } else { - obj = edm::ObjectWithDict(retType, retType.allocate()); - ret = retType.isClass(); - //std::cout << "ExpressionVar: reserved memory at " << obj.address() << " for a " << retType.qualifiedName() << " returned by " << member.name() << std::endl; - } - return ret; +ExpressionVar::makeStorage(edm::ObjectWithDict& obj, + const edm::TypeWithDict& retType) +{ + static edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void")); + bool ret = false; + if (retType == tVoid) { + obj = edm::ObjectWithDict::byType(tVoid); + } + else if (retType.isPointer() || retType.isReference()) { + // in this case, I have to allocate a void*, not an object! + obj = edm::ObjectWithDict(retType, new void*); + } + else { + obj = edm::ObjectWithDict(retType, retType.allocate()); + ret = retType.isClass(); + //std::cout << "ExpressionVar: reserved memory at " << obj.address() << + // " for a " << retType.qualifiedName() << " returned by " << + // member.name() << std::endl; + } + return ret; } bool ExpressionVar::isValidReturnType(method::TypeCode retType) { - using namespace method; - bool ret = false; - switch(retType) { - case(doubleType) : ret = true; break; - case(floatType ) : ret = true; break; - case(intType ) : ret = true; break; - case(uIntType ) : ret = true; break; - case(shortType ) : ret = true; break; - case(uShortType) : ret = true; break; - case(longType ) : ret = true; break; - case(uLongType ) : ret = true; break; - case(charType ) : ret = true; break; - case(uCharType ) : ret = true; break; - case(boolType ) : ret = true; break; - case(enumType ) : ret = true; break; - case(invalid): - default: - break; - } - return ret; + using namespace method; + bool ret = false; + switch (retType) { + case (doubleType) : + ret = true; + break; + case (floatType) : + ret = true; + break; + case (intType) : + ret = true; + break; + case (uIntType) : + ret = true; + break; + case (shortType) : + ret = true; + break; + case (uShortType) : + ret = true; + break; + case (longType) : + ret = true; + break; + case (uLongType) : + ret = true; + break; + case (charType) : + ret = true; + break; + case (uCharType) : + ret = true; + break; + case (boolType) : + ret = true; + break; + case (enumType) : + ret = true; + break; + case (invalid): + default: + break; + } + return ret; } -double ExpressionVar::value(const edm::ObjectWithDict & o) const { - edm::ObjectWithDict ro = o; - std::vector::const_iterator itm, end = methods_.end(); - std::vector::iterator ito; - for(itm = methods_.begin(), ito = objects_.begin(); itm != end; ++itm, ++ito) { - ro = itm->invoke(ro, *ito); +double ExpressionVar::value(const edm::ObjectWithDict& obj) const +{ + edm::ObjectWithDict val(obj); + std::vector::iterator IO = objects_.begin(); + for (std::vector::const_iterator I = methods_.begin(), E = methods_.end(); I != E; ++I, ++IO) { + val = I->invoke(val, *IO); } - double ret = objToDouble(ro, retType_); - std::vector::reverse_iterator rito, rend = objects_.rend();; - std::vector::const_reverse_iterator ritb; - for(rito = objects_.rbegin(), ritb = needsDestructor_.rbegin(); rito != rend; ++rito, ++ritb) { - if (*ritb) rito->typeOf().destruct(rito->address(), false); + double ret = objToDouble(val, retType_); + std::vector::const_reverse_iterator RIB = needsDestructor_.rbegin(); + for (std::vector::reverse_iterator RI = objects_.rbegin(), RE = objects_.rend(); RI != RI; ++RIB, ++RI) { + if (*RIB) { + RI->destruct(false); + } } return ret; } double -ExpressionVar::objToDouble(const edm::ObjectWithDict &obj, method::TypeCode type) { +ExpressionVar::objToDouble(const edm::ObjectWithDict& obj, + method::TypeCode type) +{ using namespace method; - void * addr = obj.address(); - double ret = 0; - switch(type) { - case(doubleType) : ret = * static_cast(addr); break; - case(floatType ) : ret = * static_cast(addr); break; - case(intType ) : ret = * static_cast(addr); break; - case(uIntType ) : ret = * static_cast(addr); break; - case(shortType ) : ret = * static_cast(addr); break; - case(uShortType) : ret = * static_cast(addr); break; - case(longType ) : ret = * static_cast(addr); break; - case(uLongType ) : ret = * static_cast(addr); break; - case(charType ) : ret = * static_cast(addr); break; - case(uCharType ) : ret = * static_cast(addr); break; - case(boolType ) : ret = * static_cast(addr); break; - case(enumType ) : ret = * static_cast(addr); break; - default: - assert(false); + void* addr = obj.address(); + double ret = 0.0; + switch (type) { + case doubleType: + ret = *static_cast(addr); + break; + case floatType: + ret = *static_cast(addr); + break; + case intType: + ret = *static_cast(addr); + break; + case uIntType: + ret = *static_cast(addr); + break; + case shortType: + ret = *static_cast(addr); + break; + case uShortType: + ret = *static_cast(addr); + break; + case longType: + ret = *static_cast(addr); + break; + case uLongType: + ret = *static_cast(addr); + break; + case charType: + ret = *static_cast(addr); + break; + case uCharType: + ret = *static_cast(addr); + break; + case boolType: + ret = *static_cast(addr); + break; + case enumType: + ret = *static_cast(addr); + break; + default: + //FIXME: Error not caught in production build! + assert(false && "objToDouble: invalid type!"); + break; }; return ret; } -ExpressionLazyVar::ExpressionLazyVar(const std::vector & methods) : - methods_(methods) +ExpressionLazyVar::ExpressionLazyVar(const std::vector& methods) + : methods_(methods) { } @@ -145,18 +220,20 @@ ExpressionLazyVar::~ExpressionLazyVar() } double -ExpressionLazyVar::value(const edm::ObjectWithDict & o) const { - std::vector::const_iterator it, ed = methods_.end()-1; - edm::ObjectWithDict ro = o; - for (it = methods_.begin(); it < ed; ++it) { - ro = it->invoke(ro, objects_); - } - double ret = it->invokeLast(ro, objects_); - std::vector::reverse_iterator rit, red = objects_.rend(); - for (rit = objects_.rbegin(); rit != red; ++rit) { - rit->typeOf().destruct(rit->address(), false); - } - objects_.clear(); - return ret; +ExpressionLazyVar::value(const edm::ObjectWithDict& o) const +{ + edm::ObjectWithDict val = o; + std::vector::const_iterator I = methods_.begin(); + std::vector::const_iterator E = methods_.end() - 1; + for (; I < E; ++I) { + val = I->invoke(val, objects_); + } + double ret = I->invokeLast(val, objects_); + for (std::vector::reverse_iterator RI = + objects_.rbegin(), RE = objects_.rend(); RI != RE; ++RI) { + RI->destruct(false); + } + objects_.clear(); + return ret; } diff --git a/CommonTools/Utils/src/ExpressionVar.h b/CommonTools/Utils/src/ExpressionVar.h index 359d5ddca0a12..3dfdd3b22cf53 100755 --- a/CommonTools/Utils/src/ExpressionVar.h +++ b/CommonTools/Utils/src/ExpressionVar.h @@ -1,66 +1,74 @@ #ifndef CommonTools_Utils_ExpressionVar_h #define CommonTools_Utils_ExpressionVar_h + /* \class reco::parser::ExpressionVar * * Variable expression * - * \author original version: Chris Jones, Cornell, + * \author original version: Chris Jones, Cornell, * adapted by Luca Lista, INFN * - * \version $Revision: 1.6 $ - * */ + #include "CommonTools/Utils/src/ExpressionBase.h" -#include "CommonTools/Utils/src/TypeCode.h" #include "CommonTools/Utils/src/MethodInvoker.h" +#include "CommonTools/Utils/src/TypeCode.h" + #include namespace reco { - namespace parser { - /// Evaluate an object's method or datamember (or chain of them) to get a number - struct ExpressionVar : public ExpressionBase { - ExpressionVar(const std::vector & methods, method::TypeCode retType); +namespace parser { - ~ExpressionVar() ; - ExpressionVar(const ExpressionVar &var) ; +/// Evaluate an object's method or datamember (or chain of them) to get a number +class ExpressionVar : public ExpressionBase { +private: // Private Data Members + std::vector methods_; + mutable std::vector objects_; + mutable std::vector needsDestructor_; + method::TypeCode retType_; - virtual double value(const edm::ObjectWithDict & o) const; +private: // Private Methods + void initObjects_(); - static bool isValidReturnType(method::TypeCode); - /// performs the needed conversion from void * to double - /// this method is used also from the ExpressionLazyVar code - static double objToDouble(const edm::ObjectWithDict &obj, method::TypeCode type) ; +public: // Public Static Methods + static bool isValidReturnType(method::TypeCode); - /// allocate an object to hold the result of a given member (if needed) - /// this method is used also from the LazyInvoker code - /// returns true if objects returned from this will require a destructor - static bool makeStorage(edm::ObjectWithDict &obj, const edm::TypeWithDict &retType) ; - /// delete an objecty, if needed - /// this method is used also from the LazyInvoker code - static void delStorage(edm::ObjectWithDict &obj); + /// performs the needed conversion from void* to double + /// this method is used also from the ExpressionLazyVar code + static double objToDouble(const edm::ObjectWithDict& obj, + method::TypeCode type); - private: - std::vector methods_; - mutable std::vector objects_; - mutable std::vector needsDestructor_; - method::TypeCode retType_; - void initObjects_(); - }; + /// allocate an object to hold the result of a given member (if needed) + /// this method is used also from the LazyInvoker code + /// returns true if objects returned from this will require a destructor + static bool makeStorage(edm::ObjectWithDict& obj, + const edm::TypeWithDict& retType); - /// Same as ExpressionVar but with lazy resolution of object methods - /// using the final type of the object, and not the one fixed at compile time - struct ExpressionLazyVar : public ExpressionBase { - ExpressionLazyVar(const std::vector & methods); - ~ExpressionLazyVar() ; + /// delete an objecty, if needed + /// this method is used also from the LazyInvoker code + static void delStorage(edm::ObjectWithDict&); - virtual double value(const edm::ObjectWithDict & o) const; +public: // Public Methods + ExpressionVar(const std::vector& methods, + method::TypeCode retType); + ExpressionVar(const ExpressionVar&); + ~ExpressionVar(); + virtual double value(const edm::ObjectWithDict&) const; +}; - private: - std::vector methods_; - mutable std::vector objects_; - }; +/// Same as ExpressionVar but with lazy resolution of object methods +/// using the dynamic type of the object, and not the one fixed at compile time +class ExpressionLazyVar : public ExpressionBase { +private: // Private Data Members + std::vector methods_; + mutable std::vector objects_; +public: + ExpressionLazyVar(const std::vector& methods); + ~ExpressionLazyVar(); + virtual double value(const edm::ObjectWithDict&) const; +}; - } -} +} // namespace parser +} // namespace reco -#endif +#endif // CommonTools_Utils_ExpressionVar_h diff --git a/CommonTools/Utils/src/MethodArgumentStack.h b/CommonTools/Utils/src/MethodArgumentStack.h index b3d483e433705..158f970d9366f 100644 --- a/CommonTools/Utils/src/MethodArgumentStack.h +++ b/CommonTools/Utils/src/MethodArgumentStack.h @@ -1,21 +1,21 @@ #ifndef CommonTools_Utils_MethodArgumentStack_h #define CommonTools_Utils_MethodArgumentStack_h + /* \class reco::parser::MethodArgumentStack * * Stack of method arguments * * \author Giovanni Petrucciani, SNS * - * \version $Revision: 1.1 $ - * */ + #include "CommonTools/Utils/src/MethodInvoker.h" #include namespace reco { - namespace parser { - typedef std::vector MethodArgumentStack; - } -} +namespace parser { +typedef std::vector MethodArgumentStack; +} // namespace reco +} // namespace parser -#endif +#endif // CommonTools_Utils_MethodArgumentStack_h diff --git a/CommonTools/Utils/src/MethodInvoker.cc b/CommonTools/Utils/src/MethodInvoker.cc index 5ea89b922aa49..a767ad96700c0 100755 --- a/CommonTools/Utils/src/MethodInvoker.cc +++ b/CommonTools/Utils/src/MethodInvoker.cc @@ -1,222 +1,304 @@ #include "CommonTools/Utils/src/MethodInvoker.h" + +#include "CommonTools/Utils/src/ExpressionVar.h" +#include "CommonTools/Utils/src/MethodSetter.h" #include "CommonTools/Utils/src/findMethod.h" #include "CommonTools/Utils/src/returnType.h" #include "FWCore/Utilities/interface/EDMException.h" -#include "CommonTools/Utils/src/MethodSetter.h" -#include "CommonTools/Utils/src/ExpressionVar.h" #include + using namespace reco::parser; using namespace std; -MethodInvoker::MethodInvoker(const edm::FunctionWithDict & method, const vector & ints) : - method_(method), member_(), ints_(ints), isFunction_(true) -{ +MethodInvoker:: +MethodInvoker(const edm::FunctionWithDict& method, + const vector& ints) + : method_(method) + , member_() + , ints_(ints) + , isFunction_(true) +{ setArgs(); - /*std::cout << "Booking " << methodName() - << " from " << method_.declaringType().name() - << " with " << args_.size() << " arguments" - << " (were " << ints.size() << ")" - << std::endl;*/ + //std::cout << + // "Booking " << + // methodName() << + // " from " << + // method_.declaringType().name() << + // " with " << + // args_.size() << + // " arguments" << + // " (were " << + // ints.size() << + // ")" << + // std::endl; } -MethodInvoker::MethodInvoker(const edm::MemberWithDict & member) : - method_(), member_(member), ints_(), isFunction_(false) -{ +MethodInvoker:: +MethodInvoker(const edm::MemberWithDict& member) + : method_() + , member_(member) + , ints_() + , isFunction_(false) +{ setArgs(); - /*std::cout << "Booking " << methodName() - << " from " << member_.declaringType().name() - << " with " << args_.size() << " arguments" - << " (were " << ints.size() << ")" - << std::endl;*/ + //std::cout << + // "Booking " << + // methodName() << + // " from " << + // member_.declaringType().name() << + // " with " << + // args_.size() << + // " arguments" << + // " (were " << + // ints.size() << + // ")" << + // std::endl; } -MethodInvoker::MethodInvoker(const MethodInvoker & other) : - method_(other.method_), member_(other.member_), ints_(other.ints_), isFunction_(other.isFunction_) { +MethodInvoker:: +MethodInvoker(const MethodInvoker& rhs) + : method_(rhs.method_) + , member_(rhs.member_) + , ints_(rhs.ints_) + , isFunction_(rhs.isFunction_) +{ setArgs(); } -MethodInvoker & MethodInvoker::operator=(const MethodInvoker & other) { - method_ = other.method_; - member_ = other.member_; - ints_ = other.ints_; - isFunction_ = other.isFunction_; - setArgs(); +MethodInvoker& +MethodInvoker:: +operator=(const MethodInvoker& rhs) +{ + if (this != &rhs) { + method_ = rhs.method_; + member_ = rhs.member_; + ints_ = rhs.ints_; + isFunction_ = rhs.isFunction_; + setArgs(); + } return *this; } -void MethodInvoker::setArgs() { - for(size_t i = 0; i < ints_.size(); ++i) { - args_.push_back( boost::apply_visitor( AnyMethodArgument2VoidPtr(), ints_[i] ) ); +void +MethodInvoker:: +setArgs() +{ + for (size_t i = 0; i < ints_.size(); ++i) { + args_.push_back(boost::apply_visitor(AnyMethodArgument2VoidPtr(), ints_[i])); } } std::string -MethodInvoker::methodName() const { - if(isFunction_) { - return method_.name(); +MethodInvoker:: +methodName() const +{ + if (isFunction_) { + return method_.name(); } return member_.name(); } std::string -MethodInvoker::returnTypeName() const { - if(isFunction_) { - return method_.typeOf().qualifiedName(); +MethodInvoker:: +returnTypeName() const +{ + if (isFunction_) { + return method_.typeOf().qualifiedName(); } return member_.typeOf().qualifiedName(); } edm::ObjectWithDict -MethodInvoker::invoke(const edm::ObjectWithDict & o, edm::ObjectWithDict &retstore) const { +MethodInvoker:: +invoke(const edm::ObjectWithDict& o, edm::ObjectWithDict& retstore) const +{ edm::ObjectWithDict ret = retstore; edm::TypeWithDict retType; - if(isFunction_) { - /*std::cout << "Invoking " << methodName() - << " from " << method_.declaringType().qualifiedName() - << " on an instance of " << o.dynamicType().qualifiedName() - << " at " << o.address() - << " with " << args_.size() << " arguments" - << std::endl; */ - method_.invoke(o, &ret, args_); - retType = method_.finalReturnType(); // this is correct, it takes pointers and refs into account - } else { - /*std::cout << "Invoking " << methodName() - << " from " << member_.declaringType().qualifiedName() - << " on an instance of " << o.dynamicType().qualifiedName() - << " at " << o.address() - << " with " << args_.size() << " arguments" - << std::endl; */ - ret = member_.get(o); - retType = member_.typeOf(); - } - void * addr = ret.address(); - //std::cout << "Stored result of " << methodName() << " (type " << returnTypeName() << ") at " << addr << std::endl; - if(addr==0) { + if (isFunction_) { + //std::cout << "Invoking " << methodName() + // << " from " << method_.declaringType().qualifiedName() + // << " on an instance of " << o.dynamicType().qualifiedName() + // << " at " << o.address() + // << " with " << args_.size() << " arguments" + // << std::endl; + method_.invoke(o, &ret, args_); + // this is correct, it takes pointers and refs into account + retType = method_.finalReturnType(); + } + else { + //std::cout << "Invoking " << methodName() + // << " from " << member_.declaringType().qualifiedName() + // << " on an instance of " << o.dynamicType().qualifiedName() + // << " at " << o.address() + // << " with " << args_.size() << " arguments" + // << std::endl; + ret = member_.get(o); + retType = member_.typeOf(); + } + void* addr = ret.address(); + //std::cout << "Stored result of " << methodName() << " (type " << + // returnTypeName() << ") at " << addr << std::endl; + if (addr == 0) { throw edm::Exception(edm::errors::InvalidReference) - << "method \"" << methodName() << "\" called with " << args_.size() - << " arguments returned a null pointer "; + << "method \"" << methodName() << "\" called with " << args_.size() + << " arguments returned a null pointer "; } //std::cout << "Return type is " << retType.qualifiedName() << std::endl; - - if(retType.isPointer() || retType.isReference()) { // both need (void **)->(void *) conversion - if (retType.isPointer()) { - retType = retType.toType(); // for Pointers, I get the real type this way - } else { - retType = edm::TypeWithDict(retType, 0L); // strip cv & ref flags - } - ret = edm::ObjectWithDict(retType, *static_cast(addr)); - //std::cout << "Now type is " << retType.qualifiedName() << std::endl; - } - if(!ret) { - throw edm::Exception(edm::errors::Configuration) - << "method \"" << methodName() - << "\" returned void invoked on object of type \"" - << o.typeOf().qualifiedName() << "\"\n"; + if (retType.isPointer() || retType.isReference()) { + // both need void** -> void* conversion + if (retType.isPointer()) { + retType = retType.toType(); + } + else { + // strip cv & ref flags + // FIXME: This is only true if the propery passed to the constructor + // overrides the const and reference flags. + retType = edm::TypeWithDict(retType, 0L); + } + ret = edm::ObjectWithDict(retType, *static_cast(addr)); + //std::cout << "Now type is " << retType.qualifiedName() << std::endl; + } + if (!bool(ret)) { + throw edm::Exception(edm::errors::Configuration) + << "method \"" << methodName() + << "\" returned void invoked on object of type \"" + << o.typeOf().qualifiedName() << "\"\n"; } return ret; } -LazyInvoker::LazyInvoker(const std::string &name, const std::vector & args) : - name_(name), - argsBeforeFixups_(args) +LazyInvoker:: +LazyInvoker(const std::string& name, + const std::vector& args) + : name_(name) + , argsBeforeFixups_(args) { } -LazyInvoker::~LazyInvoker() +LazyInvoker::~LazyInvoker() { } -const SingleInvoker & -LazyInvoker::invoker(const edm::TypeWithDict & type) const +const SingleInvoker& +LazyInvoker:: +invoker(const edm::TypeWithDict& type) const { - //std::cout << "LazyInvoker for " << name_ << " called on type " << type.qualifiedName() << std::endl; - SingleInvokerPtr & invoker = invokers_[edm::TypeID(type.id())]; - if (!invoker) { - //std::cout << " Making new invoker for " << name_ << " on type " << type.qualifiedName() << std::endl; - invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_)); - } - return * invoker; + //std::cout << "LazyInvoker for " << name_ << " called on type " << + // type.qualifiedName() << std::endl; + SingleInvokerPtr& invoker = invokers_[edm::TypeID(type.id())]; + if (!invoker) { + //std::cout << " Making new invoker for " << name_ << " on type " << + // type.qualifiedName() << std::endl; + invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_)); + } + return *invoker; } edm::ObjectWithDict -LazyInvoker::invoke(const edm::ObjectWithDict & o, std::vector &v) const +LazyInvoker:: +invoke(const edm::ObjectWithDict& o, std::vector& v) const { - pair ret(o,false); - do { - edm::TypeWithDict type = ret.first.typeOf(); - if (type.isClass()) type = ret.first.dynamicType(); - ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v); - } while (ret.second == false); - return ret.first; + pair ret(o, false); + do { + edm::TypeWithDict type = ret.first.typeOf(); + if (type.isClass()) { + type = ret.first.dynamicType(); + } + ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v); + } + while (ret.second == false); + return ret.first; } double -LazyInvoker::invokeLast(const edm::ObjectWithDict & o, std::vector &v) const -{ - pair ret(o,false); - const SingleInvoker *i = 0; - do { - edm::TypeWithDict type = ret.first.typeOf(); - if (type.isClass()) type = ret.first.dynamicType(); - i = & invoker(type); - ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v); - } while (ret.second == false); - return i->retToDouble(ret.first); -} - -SingleInvoker::SingleInvoker(const edm::TypeWithDict &type, - const std::string &name, - const std::vector &args) -{ - TypeStack typeStack(1, type); - LazyMethodStack dummy; - MethodArgumentStack dummy2; - MethodSetter setter(invokers_, dummy, typeStack, dummy2, false); - isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false); - //std::cerr << "SingleInvoker on type " << type.qualifiedName() << ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") << std::endl; - if(invokers_.front().isFunction()) { - edm::TypeWithDict retType = invokers_.front().method().finalReturnType(); - storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType); - } else { - storage_ = edm::ObjectWithDict(); - storageNeedsDestructor_ = false; +LazyInvoker:: +invokeLast(const edm::ObjectWithDict& o, + std::vector& v) const +{ + pair ret(o, false); + const SingleInvoker* i = 0; + do { + edm::TypeWithDict type = ret.first.typeOf(); + if (type.isClass()) { + type = ret.first.dynamicType(); } - retType_ = reco::typeCode(typeStack[1]); // typeStack[0] = type of self, typeStack[1] = type of ret + i = &invoker(type); + ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v); + } + while (ret.second == false); + return i->retToDouble(ret.first); } -SingleInvoker::~SingleInvoker() +SingleInvoker:: +SingleInvoker(const edm::TypeWithDict& type, const std::string& name, + const std::vector& args) { - ExpressionVar::delStorage(storage_); + TypeStack typeStack(1, type); + LazyMethodStack dummy; + MethodArgumentStack dummy2; + MethodSetter setter(invokers_, dummy, typeStack, dummy2, false); + isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false); + //std::cerr << "SingleInvoker on type " << type.qualifiedName() << + // ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") << + // std::endl; + if (invokers_.front().isFunction()) { + edm::TypeWithDict retType = invokers_.front().method().finalReturnType(); + storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType); + } + else { + storage_ = edm::ObjectWithDict(); + storageNeedsDestructor_ = false; + } + // typeStack[0] = type of self + // typeStack[1] = type of ret + retType_ = reco::typeCode(typeStack[1]); } -pair -SingleInvoker::invoke(const edm::ObjectWithDict & o, std::vector &v) const +SingleInvoker:: +~SingleInvoker() { - /* std::cerr << "[SingleInvoker::invoke] member " << invokers_.front().method().qualifiedName() << - " of type " << o.typeOf().qualifiedName() << - (!isRefGet_ ? " is one shot" : " needs another round") << std::endl; */ - pair ret(invokers_.front().invoke(o, storage_), !isRefGet_); - if (storageNeedsDestructor_) { - //std::cout << "Storage type: " << storage_.typeOf().qualifiedName() << ", I have to call the destructor." << std::endl; - v.push_back(storage_); - } - return ret; + ExpressionVar::delStorage(storage_); +} + +pair +SingleInvoker:: +invoke(const edm::ObjectWithDict& o, std::vector& v) const +{ + // std::cerr << "[SingleInvoker::invoke] member " << + // invokers_.front().method().qualifiedName() << + // " of type " << + // o.typeOf().qualifiedName() << + // (!isRefGet_ ? " is one shot" : " needs another round") << + // std::endl; + pair + ret(invokers_.front().invoke(o, storage_), !isRefGet_); + if (storageNeedsDestructor_) { + //std::cerr << "Storage type: " << storage_.typeOf().qualifiedName() << + // ", I have to call the destructor." << std::endl; + v.push_back(storage_); + } + return ret; } double -SingleInvoker::retToDouble(const edm::ObjectWithDict & o) const { - if (!ExpressionVar::isValidReturnType(retType_)) { - throwFailedConversion(o); - } - return ExpressionVar::objToDouble(o, retType_); +SingleInvoker:: +retToDouble(const edm::ObjectWithDict& o) const +{ + if (!ExpressionVar::isValidReturnType(retType_)) { + throwFailedConversion(o); + } + return ExpressionVar::objToDouble(o, retType_); } void -SingleInvoker::throwFailedConversion(const edm::ObjectWithDict & o) const { - throw edm::Exception(edm::errors::Configuration) - << "member \"" << invokers_.back().methodName() - << "\" return type is \"" << invokers_.back().returnTypeName() - << "\" retured a \"" << o.typeOf().qualifiedName() - << "\" which is not convertible to double."; +SingleInvoker:: +throwFailedConversion(const edm::ObjectWithDict& o) const +{ + throw edm::Exception(edm::errors::Configuration) + << "member \"" << invokers_.back().methodName() + << "\" return type is \"" << invokers_.back().returnTypeName() + << "\" retured a \"" << o.typeOf().qualifiedName() + << "\" which is not convertible to double."; } + diff --git a/CommonTools/Utils/src/MethodInvoker.h b/CommonTools/Utils/src/MethodInvoker.h index 493e87c834fa9..a6feb4514e196 100755 --- a/CommonTools/Utils/src/MethodInvoker.h +++ b/CommonTools/Utils/src/MethodInvoker.h @@ -1,95 +1,121 @@ #ifndef CommonTools_Utils_MethodInvoker_h #define CommonTools_Utils_MethodInvoker_h -#include "FWCore/Utilities/interface/ObjectWithDict.h" + +#include "CommonTools/Utils/src/AnyMethodArgument.h" +#include "CommonTools/Utils/src/TypeCode.h" #include "FWCore/Utilities/interface/FunctionWithDict.h" #include "FWCore/Utilities/interface/MemberWithDict.h" +#include "FWCore/Utilities/interface/ObjectWithDict.h" #include "FWCore/Utilities/interface/TypeID.h" -#include "CommonTools/Utils/src/AnyMethodArgument.h" -#include "CommonTools/Utils/src/TypeCode.h" -#include + #include -#include +#include + #include +#include namespace reco { - namespace parser { - - struct MethodInvoker { - explicit MethodInvoker(const edm::FunctionWithDict & method, - const std::vector & ints = std::vector() ); - explicit MethodInvoker(const edm::MemberWithDict & member); - MethodInvoker(const MethodInvoker &); - - /// Invokes the method, putting the result in retval. - /// Returns the Object that points to the result value, after removing any "*" and "&" - /// Caller code is responsible for allocating retstore before calling 'invoke', and of deallocating it afterwards - edm::ObjectWithDict - invoke(const edm::ObjectWithDict & o, edm::ObjectWithDict &retstore) const; - edm::FunctionWithDict const method() const {return method_;} - edm::MemberWithDict const member() const {return member_;} - MethodInvoker & operator=(const MethodInvoker &); - bool isFunction() const {return isFunction_;} - std::string methodName() const; - std::string returnTypeName() const; - private: - edm::FunctionWithDict method_; - edm::MemberWithDict member_; - std::vector ints_; // already fixed to the correct type - std::vector args_; - bool isFunction_; - void setArgs(); - }; - - /// A bigger brother of the MethodInvoker: - /// - it owns also the object in which to store the result - /// - it handles by itself the popping out of Refs and Ptrs - /// in this way, it can map 1-1 to a name and set of args - struct SingleInvoker : boost::noncopyable { - SingleInvoker(const edm::TypeWithDict &t, - const std::string &name, - const std::vector &args) ; - ~SingleInvoker(); - - /// If the member is found in object o, evaluate and return (value,true) - /// If the member is not found but o is a Ref/RefToBase/Ptr, (return o.get(), false) - /// the actual edm::ObjectWithDict where the result is stored will be pushed in vector - /// so that, if needed, its destructor can be called - std::pair invoke(const edm::ObjectWithDict & o, std::vector &v) const; - - // convert the output of invoke to a double, if possible - double retToDouble(const edm::ObjectWithDict & o) const; - void throwFailedConversion(const edm::ObjectWithDict & o) const; - private: - method::TypeCode retType_; - std::vector invokers_; - mutable edm::ObjectWithDict storage_; - bool storageNeedsDestructor_; - /// true if this invoker just pops out a ref and returns (ref.get(), false) - bool isRefGet_; - }; - - - /// Keeps different SingleInvokers for each dynamic type of the objects passed to invoke() - struct LazyInvoker { - explicit LazyInvoker(const std::string &name, - const std::vector &args); - ~LazyInvoker(); - /// invoke method, returns object that points to result (after stripping '*' and '&') - /// the object is still owned by the LazyInvoker - /// the actual edm::ObjectWithDict where the result is stored will be pushed in vector - /// so that, if needed, its destructor can be called - edm::ObjectWithDict invoke(const edm::ObjectWithDict & o, std::vector &v) const; - /// invoke and coerce result to double - double invokeLast(const edm::ObjectWithDict & o, std::vector &v) const; - private: - std::string name_; - std::vector argsBeforeFixups_; - typedef boost::shared_ptr SingleInvokerPtr; // the shared ptr is only to make the code exception safe - mutable std::map invokers_; // otherwise I think it could leak if the constructor of - const SingleInvoker & invoker(const edm::TypeWithDict &t) const ; // SingleInvoker throws an exception (which can happen) - }; - - } -} - -#endif +namespace parser { + +class MethodInvoker { +private: // Private Data Members + edm::FunctionWithDict method_; + edm::MemberWithDict member_; + std::vector ints_; // already fixed to the correct type + std::vector args_; + bool isFunction_; +private: // Private Function Members + void setArgs(); +public: // Public Function Members + explicit MethodInvoker(const edm::FunctionWithDict& method, + const std::vector& ints = + std::vector()); + explicit MethodInvoker(const edm::MemberWithDict&); + MethodInvoker(const MethodInvoker&); + MethodInvoker& operator=(const MethodInvoker&); + + edm::FunctionWithDict const method() const { return method_; } + edm::MemberWithDict const member() const { return member_; } + bool isFunction() const { return isFunction_; } + std::string methodName() const; + std::string returnTypeName() const; + + /// Invokes the method, putting the result in retval. + /// Returns the Object that points to the result value, + /// after removing any "*" and "&" + /// Caller code is responsible for allocating retstore + /// before calling 'invoke', and of deallocating it afterwards + edm::ObjectWithDict invoke(const edm::ObjectWithDict& obj, + edm::ObjectWithDict& retstore) const; +}; + +/// A bigger brother of the MethodInvoker: +/// - it owns also the object in which to store the result +/// - it handles by itself the popping out of Refs and Ptrs +/// in this way, it can map 1-1 to a name and set of args +struct SingleInvoker : boost::noncopyable { +private: // Private Data Members + method::TypeCode retType_; + std::vector invokers_; + mutable edm::ObjectWithDict storage_; + bool storageNeedsDestructor_; + /// true if this invoker just pops out a ref and returns (ref.get(), false) + bool isRefGet_; +public: + SingleInvoker(const edm::TypeWithDict&, const std::string& name, + const std::vector& args); + ~SingleInvoker(); + + /// If the member is found in object o, evaluate and + /// return (value,true) + /// If the member is not found but o is a Ref/RefToBase/Ptr, + /// (return o.get(), false) + /// the actual edm::ObjectWithDict where the result is stored + /// will be pushed in vector so that, if needed, its destructor + /// can be called + std::pair + invoke(const edm::ObjectWithDict& o, + std::vector& v) const; + + /// convert the output of invoke to a double, if possible + double retToDouble(const edm::ObjectWithDict&) const; + + void throwFailedConversion(const edm::ObjectWithDict&) const; +}; + + +/// Keeps different SingleInvokers for each dynamic type of the objects passed to invoke() +struct LazyInvoker { +private: // Private Data Members + std::string name_; + std::vector argsBeforeFixups_; + // the shared ptr is only to make the code exception safe + // otherwise I think it could leak if the constructor of + // SingleInvoker throws an exception (which can happen) + typedef boost::shared_ptr SingleInvokerPtr; + mutable std::map invokers_; +private: // Private Function Members + const SingleInvoker& invoker(const edm::TypeWithDict&) const; +public: // Public Function Members + explicit LazyInvoker(const std::string& name, + const std::vector& args); + ~LazyInvoker(); + + /// invoke method, returns object that points to result + /// (after stripping '*' and '&') + /// the object is still owned by the LazyInvoker + /// the actual edm::ObjectWithDict where the result is + /// stored will be pushed in vector + /// so that, if needed, its destructor can be called + edm::ObjectWithDict invoke(const edm::ObjectWithDict& o, + std::vector& v) const; + + /// invoke and coerce result to double + double invokeLast(const edm::ObjectWithDict& o, + std::vector& v) const; +}; + +} // namesapce parser +} // namespace reco + +#endif // CommonTools_Utils_MethodInvoker_h diff --git a/CommonTools/Utils/src/MethodSetter.cc b/CommonTools/Utils/src/MethodSetter.cc index 071785066d801..b832a93ae0727 100755 --- a/CommonTools/Utils/src/MethodSetter.cc +++ b/CommonTools/Utils/src/MethodSetter.cc @@ -1,129 +1,171 @@ #include "CommonTools/Utils/src/MethodSetter.h" -#include "CommonTools/Utils/src/returnType.h" -#include "CommonTools/Utils/src/findMethod.h" -#include "CommonTools/Utils/src/findDataMember.h" -#include "CommonTools/Utils/src/ErrorCodes.h" + #include "CommonTools/Utils/interface/Exception.h" +#include "CommonTools/Utils/src/ErrorCodes.h" +#include "CommonTools/Utils/src/MethodInvoker.h" +#include "CommonTools/Utils/src/findDataMember.h" +#include "CommonTools/Utils/src/findMethod.h" +#include "CommonTools/Utils/src/returnType.h" + #include + using namespace reco::parser; using namespace std; -void MethodSetter::operator()(const char * begin, const char * end) const { +void +MethodSetter:: +operator()(const char* begin, const char* end) const +{ string name(begin, end); string::size_type parenthesis = name.find_first_of('('); - if (*begin == '[' || *begin == '(') { - name.insert(0, "operator.."); // operator..[arg]; - parenthesis = 10; // ^--- idx = 10 - name[8] = *begin; // operator[.[arg]; - name[9] = name[name.size()-1]; // operator[][arg]; - name[10] = '('; // operator[](arg]; - name[name.size()-1] = ')'; // operator[](arg); + if ((*begin == '[') || (*begin == '(')) { + name.insert(0, "operator.."); // operator..[arg]; + parenthesis = 10; // ^--- idx = 10 + name[8] = *begin; // operator[.[arg]; + name[9] = name[name.size() - 1]; // operator[][arg]; + name[10] = '('; // operator[](arg]; + name[name.size() - 1] = ')'; // operator[](arg); // we don't actually need the last two, but just for extra care - //std::cout << "Transformed {" << string(begin,end) << "} into {"<< name <<"}" << std::endl; + //std::cout << "Transformed {" << string(begin,end) << "} into + // {"<< name <<"}" << std::endl; } std::vector args; - if(parenthesis != string::npos) { + if (parenthesis != string::npos) { name.erase(parenthesis, name.size()); - if(intStack_.size()==0) + if (intStack_.size() == 0) { throw Exception(begin) - << "expected method argument, but non given."; - for(vector::const_iterator i = intStack_.begin(); i != intStack_.end(); ++i) + << "expected method argument, but non given."; + } + for (vector::const_iterator i = intStack_.begin(); + i != intStack_.end(); ++i) { args.push_back(*i); + } intStack_.clear(); } string::size_type endOfExpr = name.find_last_of(' '); - if(endOfExpr != string::npos) + if (endOfExpr != string::npos) { name.erase(endOfExpr, name.size()); - //std::cerr << "Pushing [" << name << "] with " << args.size() << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl; - if (lazy_) lazyMethStack_.push_back(LazyInvoker(name, args)); // for lazy parsing we just push method name and arguments - else push(name, args,begin); // otherwise we really have to resolve the method - //std::cerr << "Pushed [" << name << "] with " << args.size() << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl; + } + //std::cerr << "Pushing [" << name << "] with " << args.size() + // << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl; + if (lazy_) { + // for lazy parsing we just push method name and arguments + lazyMethStack_.push_back(LazyInvoker(name, args)); + } + else { + // otherwise we really have to resolve the method + push(name, args, begin); + } + //std::cerr << "Pushed [" << name << "] with " << args.size() << + // " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl; } -bool MethodSetter::push(const string & name, const vector & args, const char* begin,bool deep) const { +bool +MethodSetter:: +push(const string& name, const vector& args, + const char* begin, bool deep) const +{ edm::TypeWithDict type = typeStack_.back(); vector fixups; - int error; - pair mem = reco::findMethod(type, name, args, fixups,begin,error); - if(mem.first) { - edm::TypeWithDict retType = reco::returnType(mem.first); - if(!retType) { - throw Exception(begin) - << "member \"" << mem.first.name() << "\" return type is invalid:\n" - << " member type: \"" << mem.first.typeOf().qualifiedName() << "\"\n" - << " return type: \"" << mem.first.returnType().qualifiedName() << "\"\n"; - - } - typeStack_.push_back(retType); - // check for edm::Ref, edm::RefToBase, edm::Ptr - if(mem.second) { - //std::cout << "Mem.second, so book " << mem.first.name() << " without fixups." << std::endl; - methStack_.push_back(MethodInvoker(mem.first)); - if (deep) push(name, args,begin); // note: we have not found the method, so we have not fixupped the arguments - else return false; - } else { - //std::cout << "Not mem.second, so book " << mem.first.name() << " with #args = " << fixups.size() << std::endl; - methStack_.push_back(MethodInvoker(mem.first, fixups)); + int error = 0; + pair mem = + reco::findMethod(type, name, args, fixups, begin, error); + if (bool(mem.first)) { + // We found the method. + edm::TypeWithDict retType = reco::returnType(mem.first); + if (!bool(retType)) { + // Invalid return type, fatal error, throw. + throw Exception(begin) + << "member \"" << mem.first.name() + << "\" return type is invalid:\n" + << " member type: \"" + << mem.first.typeOf().qualifiedName() << "\"\n" + << " return type: \"" + << mem.first.returnType().qualifiedName() << "\"\n"; + } + typeStack_.push_back(retType); + // check for edm::Ref, edm::RefToBase, edm::Ptr + if (mem.second) { + // Without fixups. + //std::cout << "Mem.second, so book " << mem.first.name() << + // " without fixups." << std::endl; + methStack_.push_back(MethodInvoker(mem.first)); + if (!deep) { + return false; } - } else { - if(error != reco::parser::kNameDoesNotExist) { - switch(error) { - case reco::parser::kIsNotPublic: - throw Exception(begin) - << "method named \"" << name << "\" for type \"" - <&,const char*,bool deep=true) const; - private: - MethodStack & methStack_; - LazyMethodStack & lazyMethStack_; - TypeStack & typeStack_; - MethodArgumentStack & intStack_; - bool lazy_; - }; +namespace parser { + +class MethodSetter { +private: + MethodStack& methStack_; + LazyMethodStack& lazyMethStack_; + TypeStack& typeStack_; + MethodArgumentStack& intStack_; + bool lazy_; +public: + explicit + MethodSetter(MethodStack& methStack, LazyMethodStack& lazyMethStack, + TypeStack& typeStack, MethodArgumentStack& intStack, + bool lazy = false) + : methStack_(methStack) + , lazyMethStack_(lazyMethStack) + , typeStack_(typeStack) + , intStack_(intStack) + , lazy_(lazy) + { } -} -#endif + void operator()(const char*, const char*) const; + + /// Resolve the name to either a function member or a data member, + /// push a MethodInvoker on the MethodStack, and its return type to + /// the TypeStack (after stripping "*" and "&"). + /// + /// This method is used also by the LazyInvoker to perform the fetch once + /// the final type is known. + /// + /// If the object is an edm::Ref/Ptr/RefToBase and the method is not + /// found in the class: + /// + /// 1) it pushes a no-argument 'get()' method + /// + /// 2) if deep = true, it attempts to resolve and push the method on + /// the object to which the edm ref points to. In that case, the + /// MethodStack will contain two more items after this call instead + /// of just one. This behaviour is what you want for non-lazy parsing. + /// + /// 2b) if instead deep = false, it just pushes the 'get' on the stack. + /// this will allow the LazyInvoker to then re-discover the runtime + /// type of the pointee + /// + /// The method will: + /// - throw exception, if the member can't be resolved + /// - return 'false' if deep = false and it only pushed + // a 'get' on the stack + /// - return true otherwise + /// + bool push(const std::string&, const std::vector&, + const char*, bool deep = true) const; +}; + +} // namespace parser +} // namespace reco + +#endif // CommonTools_Utils_MethodSetter_h diff --git a/CommonTools/Utils/src/MethodStack.h b/CommonTools/Utils/src/MethodStack.h index c16da0ff6f26a..75a11029b65ab 100755 --- a/CommonTools/Utils/src/MethodStack.h +++ b/CommonTools/Utils/src/MethodStack.h @@ -1,22 +1,22 @@ #ifndef CommonTools_Utils_MethodStack_h #define CommonTools_Utils_MethodStack_h + /* \class reco::parser::MethodStack * * Stack of methods * * \author Luca Lista, INFN * - * \version $Revision: 1.3 $ - * */ + #include "CommonTools/Utils/src/MethodInvoker.h" #include namespace reco { - namespace parser { - typedef std::vector MethodStack; - typedef std::vector LazyMethodStack; - } -} +namespace parser { +typedef std::vector MethodStack; +typedef std::vector LazyMethodStack; +} // namespace parser +} // namespace reco -#endif +#endif // CommonTools_Utils_MethodStack_h diff --git a/CommonTools/Utils/src/findDataMember.cc b/CommonTools/Utils/src/findDataMember.cc index aeddb0ce4ce20..0af6b259de262 100644 --- a/CommonTools/Utils/src/findDataMember.cc +++ b/CommonTools/Utils/src/findDataMember.cc @@ -2,7 +2,7 @@ // // Package: Utilities // Class : findDataMember -// +// // Implementation: // // @@ -23,34 +23,43 @@ // namespace reco { - edm::MemberWithDict findDataMember(const edm::TypeWithDict& iType, const std::string& iName, int& oError) { - edm::MemberWithDict returnValue; - oError = parser::kNameDoesNotExist; - edm::TypeWithDict type = iType; - if(type) { - if(type.isPointer()) { - type = type.toType(); // for Pointers, I get the real type this way - } - returnValue = type.dataMemberByName(iName); - if(!returnValue) { - //check inheriting classes - edm::TypeBases bases(type); - for(auto const& base : bases) { - returnValue = findDataMember(edm::BaseWithDict(base).typeOf(), iName, oError); - //only stop if we found it or some other error happened - if(returnValue || parser::kNameDoesNotExist != oError) { - break; - } - } - } - if(returnValue && !returnValue.isPublic()) { - returnValue = edm::MemberWithDict(); - oError = parser::kIsNotPublic; - } - } - if(returnValue) { - oError = parser::kNoError; + +edm:: +MemberWithDict +findDataMember(const edm::TypeWithDict& iType, + const std::string& iName, + int& oError) +{ + edm::MemberWithDict ret; + oError = parser::kNameDoesNotExist; + edm::TypeWithDict type = iType; + if (!bool(type)) { + return ret; + } + if (type.isPointer()) { + type = type.toType(); + } + ret = type.dataMemberByName(iName); + if (!bool(ret)) { + // check base classes + edm::TypeBases bases(type); + for (auto const& B : bases) { + ret = findDataMember(edm::BaseWithDict(B).typeOf(), iName, oError); + //only stop if we found it or some other error happened + if (bool(ret) || (oError != parser::kNameDoesNotExist)) { + break; } - return returnValue; - } + } + } + if (bool(ret) && !ret.isPublic()) { + ret = edm::MemberWithDict(); + oError = parser::kIsNotPublic; + } + else if (bool(ret)) { + oError = parser::kNoError; + } + return ret; } + +} // namespace reco + diff --git a/CommonTools/Utils/src/findMethod.cc b/CommonTools/Utils/src/findMethod.cc index 8f823419f2e23..0c89ecdb5ee2c 100755 --- a/CommonTools/Utils/src/findMethod.cc +++ b/CommonTools/Utils/src/findMethod.cc @@ -1,183 +1,266 @@ #include "CommonTools/Utils/src/findMethod.h" + #include "CommonTools/Utils/src/ErrorCodes.h" #include "CommonTools/Utils/interface/Exception.h" #include "FWCore/Utilities/interface/BaseWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" + #include using namespace std; using reco::parser::AnyMethodArgument; -//Checks for errors which show we got the correct function be we just can't use it -static bool fatalErrorCondition(int iError) +/// Checks for errors which show we got the correct function +/// but we cannot use it. +static +bool +fatalErrorCondition(const int err) { - return (reco::parser::kIsNotPublic==iError || - reco::parser::kIsStatic==iError || - reco::parser::kIsFunctionAddedByROOT==iError || - reco::parser::kIsConstructor==iError || - reco::parser::kIsDestructor==iError || - reco::parser::kIsOperator==iError); - + return (err == reco::parser::kIsNotPublic) || + (err == reco::parser::kIsStatic) || + (err == reco::parser::kIsFunctionAddedByROOT) || + (err == reco::parser::kIsConstructor) || + (err == reco::parser::kIsDestructor) || + (err == reco::parser::kIsOperator); } + namespace reco { - int checkMethod(const edm::FunctionWithDict & mem, - const edm::TypeWithDict & type, - const std::vector &args, std::vector &fixuppedArgs) { - int casts = 0; - if (mem.isConstructor()) return -1*parser::kIsConstructor; - if (mem.isDestructor()) return -1*parser::kIsDestructor; - //if (mem.isOperator()) return -1*parser::kIsOperator; // no, some operators are allowed, e.g. operator[] - if (! mem.isPublic()) return -1*parser::kIsNotPublic; - if (mem.isStatic()) return -1*parser::kIsStatic; - if ( ! mem.isConst() ) return -1*parser::kIsNotConst; - if (mem.name().substr(0, 2) == "__") return -1*parser::kIsFunctionAddedByROOT; - if (mem.declaringType().id() != type.id()) { - /*std::cerr << "\nMETHOD OVERLOAD " << mem.name() << - " by " << type.Name(QUALITIED|SCOPED) << - " from " << mem.declaringTy[e().Name(QUALIFIED|SCOPED) << std::endl; */ - return -1*parser::kOverloaded; - } - size_t minArgs = mem.functionParameterSize(true), maxArgs = mem.functionParameterSize(false); - if ((args.size() < minArgs) || (args.size() > maxArgs)) return -1*parser::kWrongNumberOfArguments; - /*std::cerr << "\nMETHOD " << mem.name() << " of " << mem.declaringType().name() - << ", min #args = " << minArgs << ", max #args = " << maxArgs - << ", args = " << args.size() << std::endl;*/ - if (!args.empty()) { - std::vector tmpFixups; - size_t i = 0; - for (auto const& param : mem) { - edm::TypeWithDict parameter(param); - std::pair fixup = boost::apply_visitor( reco::parser::AnyMethodArgumentFixup(parameter), args[i] ); - //std::cerr << "\t ARG " << i << " type is " << parameter.name() << " conversion = " << fixup.second << std::endl; - if (fixup.second >= 0) { - tmpFixups.push_back(fixup.first); - casts += fixup.second; - } else { - return -1*parser::kWrongArgumentType; - } - if(++i == args.size()) { - break; - } - } - fixuppedArgs.swap(tmpFixups); - } - /*std::cerr << "\nMETHOD " << mem.name() << " of " << mem.declaringType().name() - << ", min #args = " << minArgs << ", max #args = " << maxArgs - << ", args = " << args.size() << " fixupped args = " << fixuppedArgs.size() << "(" << casts << " implicit casts)" << std::endl; */ - return casts; - } - typedef pair OK; - bool nCasts(OK const& a, OK const& b) { - return a.first < b.first; +int +checkMethod(const edm::FunctionWithDict& mem, + const edm::TypeWithDict& type, + const std::vector& args, + std::vector& fixuppedArgs) +{ + int casts = 0; + if (mem.isConstructor()) { + return -1 * parser::kIsConstructor; } - - - pair findMethod(const edm::TypeWithDict & t, - const string & name, - const std::vector &args, - std::vector &fixuppedArgs, - const char* iIterator, - int& oError) { - oError = parser::kNameDoesNotExist; - edm::TypeWithDict type = t; - if (! type) - throw parser::Exception(iIterator) - << "No dictionary for class \"" << type.name() << "\"."; - while(type.isPointer() || type.isTypedef()) type = type.toType(); - type = edm::TypeWithDict(type, 0L); // strip const, volatile, c++ ref, .. - - pair mem; mem.second = false; - - // suitable members and number of integer->real casts required to get them - vector > oks; - - // first look in base scope - edm::TypeFunctionMembers functions(type); - for(auto const& function : functions) { - edm::FunctionWithDict m(function); - if(m.name()==name) { - int casts = checkMethod(m, type, args, fixuppedArgs); - if (casts > -1) { - oks.push_back( make_pair(casts,m) ); - } else { - oError = -1*casts; - //is this a show stopper error? - if(fatalErrorCondition(oError)) { - return mem; - } - } + if (mem.isDestructor()) { + return -1 * parser::kIsDestructor; + } + //No, some operators are allowed, e.g. operator[]. + //if (mem.isOperator()) { + // return -1 * parser::kIsOperator; + //} + if (! mem.isPublic()) { + return -1 * parser::kIsNotPublic; + } + if (mem.isStatic()) { + return -1 * parser::kIsStatic; + } + if (!mem.isConst()) { + return -1 * parser::kIsNotConst; + } + if (mem.name().substr(0, 2) == "__") { + return -1 * parser::kIsFunctionAddedByROOT; + } + if (mem.declaringType().id() != type.id()) { + //std::cerr << + // "\nMETHOD OVERLOAD " << + // mem.name() << + // " by " << + // type.Name(QUALITIED|SCOPED) << + // " from " << + // mem.declaringType().Name(QUALIFIED|SCOPED) << + // std::endl; + return -1 * parser::kOverloaded; + } + size_t minArgs = mem.functionParameterSize(true); + size_t maxArgs = mem.functionParameterSize(false); + if ((args.size() < minArgs) || (args.size() > maxArgs)) { + return -1 * parser::kWrongNumberOfArguments; + } + //std::cerr << + // "\nMETHOD " << + // mem.name() << + // " of " << + // mem.declaringType().name() << + // ", min #args = " << + // minArgs << + // ", max #args = " << + // maxArgs << + // ", args = " << + // args.size() << + // std::endl; + if (!args.empty()) { + std::vector tmpFixups; + size_t i = 0; + for (auto const& param : mem) { + edm::TypeWithDict parameter(param); + std::pair fixup = + boost::apply_visitor(reco::parser::AnyMethodArgumentFixup(parameter), + args[i]); + //std::cerr << + // "\t ARG " << + // i << + // " type is " << + // parameter.name() << + // " conversion = " << + // fixup.second << + // std::endl; + if (fixup.second >= 0) { + tmpFixups.push_back(fixup.first); + casts += fixup.second; + } + else { + return -1 * parser::kWrongArgumentType; + } + if (++i == args.size()) { + break; } } - //std::cout << "At base scope (type " << (type.name()) << ") found " << oks.size() << " methods." << std::endl; - // found at least one method - if (!oks.empty()) { - if (oks.size() > 1) { - // sort by number of conversions needed - sort(oks.begin(), oks.end(), nCasts); + fixuppedArgs.swap(tmpFixups); + } + //std::cerr << + // "\nMETHOD " << + // mem.name() << + // " of " << + // mem.declaringType().name() << + // ", min #args = " << + // minArgs << + // ", max #args = " << + // maxArgs << + // ", args = " << + // args.size() << + // " fixupped args = " << + // fixuppedArgs.size() << + // "(" << casts << + // " implicit casts)" << + // std::endl; + return casts; +} - if (oks[0].first == oks[1].first) { // two methods with same ambiguity - throw parser::Exception(iIterator) - << "Can't resolve method \"" << name << "\" for class \"" << type.name() << "\", the two candidates " - << oks[0].second.name() << " and " << oks[1].second.name() - << " require the same number of integer->real conversions (" << oks[0].first << ")."; - } +typedef pair OK; - // I should fixup again the args, as both good methods have pushed them on fixuppedArgs - fixuppedArgs.clear(); - checkMethod(oks.front().second, type, args, fixuppedArgs); - } - mem.first = oks.front().second; - } +bool +nCasts(const OK& a, const OK& b) +{ + return a.first < b.first; +} - // if nothing was found, look in parent scopes (without checking for cross-scope overloading, as it's not allowed) - int baseError=parser::kNameDoesNotExist; - if(! mem.first) { - edm::TypeBases bases(type); - for(auto const& base : bases) { - if((mem = findMethod(edm::BaseWithDict(base).typeOf(), name, args, fixuppedArgs,iIterator,baseError)).first) break; - if(fatalErrorCondition(baseError)) { - oError = baseError; - return mem; - } +pair +findMethod(const edm::TypeWithDict& t, /*class=in*/ + const string& name, /*function member name=in*/ + const std::vector& args, /*args=in*/ + std::vector& fixuppedArgs, /*args=out*/ + const char* iIterator, /*???=out*/ + int& oError) /*err code=out*/ +{ + oError = parser::kNameDoesNotExist; + edm::TypeWithDict type = t; + if (!bool(type)) { + throw parser::Exception(iIterator) << "No dictionary for class \"" << + type.name() << "\"."; + } + while (type.isTypedef() || type.isPointer()) { + type = type.toType(); + } + // strip const, volatile, c++ ref, .. + type = edm::TypeWithDict(type, 0L); + // Create our return value. + pair mem; + //FIXME: We must initialize mem.first! + mem.second = false; + // suitable members and number of integer->real casts required to get them + vector > oks; + // first look in base scope + edm::TypeFunctionMembers functions(type); + for (auto const& F : functions) { + edm::FunctionWithDict f(F); + if (f.name() != name) { + continue; + } + int casts = checkMethod(f, type, args, fixuppedArgs); + if (casts > -1) { + oks.push_back(make_pair(casts, f)); + } + else { + oError = -1 * casts; + //is this a show stopper error? + if (fatalErrorCondition(oError)) { + return mem; } } - - // otherwise see if this object is just a Ref or Ptr and we should pop it out - if(!mem.first) { - // check for edm::Ref or edm::RefToBase or edm::Ptr - // std::cout << "Mem.first is null, so looking for templates from type " << type.name() << std::endl; - if(type.isTemplateInstance()) { - std::string name = type.templateName(); - if(name.compare("edm::Ref") == 0 || - name.compare("edm::RefToBase") == 0 || - name.compare("edm::Ptr") == 0) { - // in this case i think 'get' should be taken with no arguments! - std::vector empty, empty2; - int error; - mem = findMethod(type, "get", empty, empty2,iIterator,error); - if(!mem.first) { - throw parser::Exception(iIterator) - << "No member \"get\" in reference of type \"" << type.name() << "\"."; - } - mem.second = true; - } + } + //std::cout << "At base scope (type " << (type.name()) << ") found " << + // oks.size() << " methods." << std::endl; + // found at least one method + if (!oks.empty()) { + if (oks.size() > 1) { + // sort by number of conversions needed + sort(oks.begin(), oks.end(), nCasts); + if (oks[0].first == oks[1].first) { // two methods with same ambiguity + throw parser::Exception(iIterator) << "Can't resolve method \"" << + name << "\" for class \"" << type.name() << + "\", the two candidates " << oks[0].second.name() << " and " << + oks[1].second.name() << + " require the same number of integer->real conversions (" << + oks[0].first << ")."; } + // We must fixup the args again, as both good methods + // have pushed them on fixuppedArgs. + fixuppedArgs.clear(); + checkMethod(oks.front().second, type, args, fixuppedArgs); } - /* - if(!mem.first) { - throw edm::Exception(edm::errors::Configuration) - << "member \""" << name << "\"" not found in class \"" << type.name() << "\""; + mem.first = oks.front().second; + } + // if nothing was found, look in parent scopes without + // checking for cross-scope overloading, as it is not + // allowed + int baseError = parser::kNameDoesNotExist; + if (!bool(mem.first)) { + edm::TypeBases bases(type); + for (auto const& B : bases) { + mem = findMethod(edm::BaseWithDict(B).typeOf(), name, args, + fixuppedArgs, iIterator, baseError); + if (bool(mem.first)) { + break; + } + if (fatalErrorCondition(baseError)) { + oError = baseError; + return mem; + } } - */ - if(mem.first) { - oError = parser::kNoError; - } else { - //use error from base check if we never found function in primary class - if(oError == parser::kNameDoesNotExist) { - oError = baseError; - } + } + // otherwise see if this object is just a Ref or Ptr and we should pop it out + if (!bool(mem.first)) { + // check for edm::Ref or edm::RefToBase or edm::Ptr + // std::cout << "Mem.first is null, so looking for templates from type " << + // type.name() << std::endl; + if (type.isTemplateInstance()) { + std::string name = type.templateName(); + if (!name.compare("edm::Ref") || !name.compare("edm::RefToBase") || + !name.compare("edm::Ptr")) { + // in this case i think 'get' should be taken with no arguments! + std::vector empty; + std::vector empty2; + int error = 0; + mem = findMethod(type, "get", empty, empty2, iIterator, error); + if (!bool(mem.first)) { + throw parser::Exception(iIterator) << + "No member \"get\" in reference of type \"" << + type.name() << "\"."; + } + mem.second = true; + } } - return mem; } + //if (!bool(mem.first)) { + // throw edm::Exception(edm::errors::Configuration) << "member \""" << + // name << "\"" not found in class \"" << type.name() << "\""; + //} + if (bool(mem.first)) { + oError = parser::kNoError; + } + else { + // use error from base check if we never found function in primary class + if (oError == parser::kNameDoesNotExist) { + oError = baseError; + } + } + return mem; } + +} // namespace reco + diff --git a/CommonTools/Utils/src/returnType.cc b/CommonTools/Utils/src/returnType.cc index 6819713679b01..39015cada23e8 100755 --- a/CommonTools/Utils/src/returnType.cc +++ b/CommonTools/Utils/src/returnType.cc @@ -1,25 +1,31 @@ #include "CommonTools/Utils/src/returnType.h" -#include + +#include "FWCore/Utilities/interface/FunctionWithDict.h" +#include "FWCore/Utilities/interface/TypeWithDict.h" + #include -#include #include -using namespace std; +#include +#include + using namespace reco::method; +using namespace std; namespace reco { - edm::TypeWithDict returnType(const edm::FunctionWithDict & mem) { - return mem.finalReturnType(); + + edm::TypeWithDict returnType(const edm::FunctionWithDict& func) { + return func.finalReturnType(); } - TypeCode returnTypeCode(const edm::FunctionWithDict & mem) { - return typeCode(returnType(mem)); + TypeCode returnTypeCode(const edm::FunctionWithDict& func) { + return typeCode(returnType(func)); } //this is already alphabetized - static const std::vector > retTypeVec { - {"bool",boolType}, - {"char",charType}, - {"double",doubleType}, + static const std::vector > retTypeVec { + {"bool", boolType}, + {"char", charType}, + {"double", doubleType}, {"float", floatType}, {"int", intType}, {"long", longType}, @@ -30,20 +36,24 @@ namespace reco { {"unsigned char", uCharType}, {"unsigned int", uIntType}, {"unsigned long", uLongType}, - {"unsigned long int",uLongType}, - {"unsigned short",uShortType}, - {"unsigned short int",uShortType} + {"unsigned long int", uLongType}, + {"unsigned short", uShortType}, + {"unsigned short int", uShortType} }; - TypeCode typeCode(const edm::TypeWithDict & t) { - - typedef std::pair Values; + TypeCode typeCode(const edm::TypeWithDict& t) { + typedef std::pair Values; const char* name = t.name().c_str(); - auto f = std::equal_range(retTypeVec.begin(),retTypeVec.end(),Values{name,enumType}, - [] ( Values const& iLHS, Values const& iRHS) -> bool{ - return std::strcmp(iLHS.first,iRHS.first)<0; - }); - if (f.first == f.second) return (t.isEnum() ? enumType : invalid); - else return f.first->second; + auto f = std::equal_range(retTypeVec.begin(), retTypeVec.end(), + Values{name, enumType}, + [](const Values& iLHS, const Values& iRHS) -> bool { + return std::strcmp(iLHS.first, iRHS.first) < 0; + }); + if (f.first == f.second) { + return t.isEnum() ? enumType : invalid; + } + return f.first->second; } -} + +} // namespace reco + diff --git a/CommonTools/Utils/src/returnType.h b/CommonTools/Utils/src/returnType.h index 7c26ba8625ab2..b02719ea81f75 100755 --- a/CommonTools/Utils/src/returnType.h +++ b/CommonTools/Utils/src/returnType.h @@ -1,20 +1,23 @@ #ifndef CommonTools_Utils_returnType_h #define CommonTools_Utils_returnType_h + /* \function returnType * * \author Luca Lista, INFN * - * \version $Id: returnType.h,v 1.3 2012/08/03 18:08:11 wmtan Exp $ */ #include "CommonTools/Utils/src/TypeCode.h" -#include "FWCore/Utilities/interface/FunctionWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" +namespace edm { +class FunctionWithDict; +} + namespace reco { - edm::TypeWithDict returnType(const edm::FunctionWithDict &); - method::TypeCode returnTypeCode(const edm::FunctionWithDict &); - method::TypeCode typeCode(const edm::TypeWithDict &); + edm::TypeWithDict returnType(const edm::FunctionWithDict&); + method::TypeCode returnTypeCode(const edm::FunctionWithDict&); + method::TypeCode typeCode(const edm::TypeWithDict&); } -#endif +#endif // CommonTools_Utils_returnType_h diff --git a/DataFormats/FWLite/interface/InternalDataKey.h b/DataFormats/FWLite/interface/InternalDataKey.h index 75a69d0d227ae..bd2fc635167da 100644 --- a/DataFormats/FWLite/interface/InternalDataKey.h +++ b/DataFormats/FWLite/interface/InternalDataKey.h @@ -87,7 +87,7 @@ namespace fwlite { edm::WrapperInterfaceBase * interface_; ~Data() { - obj_.typeOf().destruct(obj_.address(), true); + obj_.destruct(true); } }; diff --git a/DataFormats/FWLite/src/DataGetterHelper.cc b/DataFormats/FWLite/src/DataGetterHelper.cc index f121f50aa5744..802801a2f5a1a 100644 --- a/DataFormats/FWLite/src/DataGetterHelper.cc +++ b/DataFormats/FWLite/src/DataGetterHelper.cc @@ -25,6 +25,7 @@ #include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/FunctionWithDict.h" #include "FWCore/Utilities/interface/TypeID.h" #include "FWCore/Utilities/interface/TypeWithDict.h" #include "FWCore/Utilities/interface/WrappedClassName.h" @@ -113,21 +114,19 @@ namespace fwlite { { GetterOperate op(iGetter); -#if 0 - //WORK AROUND FOR ROOT!! - //Create a new instance so that we can clear any cache the object uses - //this slows the code down - edm::ObjectWithDict obj = iData.obj_; - iData.obj_ = iData.obj_.construct(); - iData.pObj_ = iData.obj_.address(); - iData.branch_->SetAddress(&(iData.pObj_)); - //If a REF to this was requested in the past, we might as well do the work now - if(0!=iData.pProd_) { - iData.pProd_ = iData.obj_.address(); - } - obj.destruct(); - //END OF WORK AROUND -#endif + ////WORK AROUND FOR ROOT!! + ////Create a new instance so that we can clear any cache the object uses + ////this slows the code down + //edm::ObjectWithDict obj = iData.obj_; + //iData.obj_ = iData.obj_.construct(); + //iData.pObj_ = iData.obj_.address(); + //iData.branch_->SetAddress(&(iData.pObj_)); + ////If a REF to this was requested in the past, we might as well do the work now + //if(0!=iData.pProd_) { + // iData.pProd_ = iData.obj_.address(); + //} + //obj.destruct(); + ////END OF WORK AROUND TTreeCache* tcache = dynamic_cast (branchMap_->getFile()->GetCacheRead()); @@ -250,7 +249,7 @@ namespace fwlite { newData->pProd_ = 0; branch->SetAddress(&(newData->pObj_)); newData->interface_ = 0; - type.invokeByName(newData->interface_, std::string("getInterface")); + edm::invokeByName(newData->interface_, std::string("getInterface")); theData = newData; } itFind = data_.insert(std::make_pair(newKey, theData)).first; diff --git a/DataFormats/PatCandidates/interface/UserData.h b/DataFormats/PatCandidates/interface/UserData.h index 7ab9793d54fa9..25886100bc671 100644 --- a/DataFormats/PatCandidates/interface/UserData.h +++ b/DataFormats/PatCandidates/interface/UserData.h @@ -57,7 +57,6 @@ namespace pat { protected: /// Get out the data (can't template non virtual functions) virtual const void * data_ () const = 0; - static std::string demangleName(const char* iMangledName); private: static void checkDictionaries(const std::type_info &type) ; @@ -97,7 +96,9 @@ std::auto_ptr pat::UserData::make(const T &value, bool transientO template const std::string & pat::UserHolder::typeName_() { - static const std::string name(demangleName(typeid(T).name())); + static int status = 0; + static const char * demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status); + static const std::string name(status == 0 ? demangled : "[UNKNOWN]"); return name; } diff --git a/DataFormats/PatCandidates/src/UserData.cc b/DataFormats/PatCandidates/src/UserData.cc index f875fcc28b3a4..60d9a376e79bd 100644 --- a/DataFormats/PatCandidates/src/UserData.cc +++ b/DataFormats/PatCandidates/src/UserData.cc @@ -24,11 +24,3 @@ void pat::UserData::checkDictionaries(const std::type_info &type) { << " you need to specify them in classes_def.xml.\n"; } // check for dictionary } - -std::string pat::UserData::demangleName(const char* iMangledName) { - int status = 0; - char * demangled = abi::__cxa_demangle(iMangledName, 0, 0, &status); - const std::string name(status == 0 ? demangled : "[UNKNOWN]"); - if((status ==0) and (nullptr != demangled)) { free(demangled);} - return name; -} \ No newline at end of file diff --git a/DataFormats/Provenance/src/BranchDescription.cc b/DataFormats/Provenance/src/BranchDescription.cc index 2dee086a3380f..fce744460065d 100644 --- a/DataFormats/Provenance/src/BranchDescription.cc +++ b/DataFormats/Provenance/src/BranchDescription.cc @@ -179,9 +179,9 @@ namespace edm { setBasketSize(invalidBasketSize); return; } +#if 0 wrappedType().invokeByName(wrapperInterfaceBase(), "getInterface"); assert(wrapperInterfaceBase() != 0); -/* Reflex::PropertyList wp = Reflex::Type::ByTypeInfo(wrappedType().typeInfo()).Properties(); setTransient((wp.HasProperty("persistent") ? wp.PropertyAsString("persistent") == std::string("false") : false)); if(transient()) { @@ -208,7 +208,8 @@ namespace edm { } else { setBasketSize(invalidBasketSize); } -*/ +#endif // 0 + //-- } void diff --git a/FWCore/Modules/src/EventContentAnalyzer.cc b/FWCore/Modules/src/EventContentAnalyzer.cc index 1a351f055fdcb..481af38e75dcd 100644 --- a/FWCore/Modules/src/EventContentAnalyzer.cc +++ b/FWCore/Modules/src/EventContentAnalyzer.cc @@ -228,7 +228,7 @@ namespace edm { << iEx.what() << ")>\n"; } if(!isRef) { - atReturnType.destruct(contained.address(), true); + contained.destruct(true); } } return true; diff --git a/FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h b/FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h index f7c2c5097be46..1dea147cf18a9 100644 --- a/FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h +++ b/FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h @@ -1,5 +1,6 @@ #ifndef LibraryLoader_RootAutoLibraryLoader_h #define LibraryLoader_RootAutoLibraryLoader_h + /**\class RootAutoLibraryLoader * * ROOT helper class which can automatically load the @@ -8,38 +9,37 @@ * \author Chris Jones, Cornell * */ + #include "TClassGenerator.h" #include "RVersion.h" +#include #include class DummyClassToStopCompilerWarning; namespace edm { + class RootAutoLibraryLoader : public TClassGenerator { friend class DummyClassToStopCompilerWarning; -public: - /// return class type - virtual TClass *GetClass(char const* classname, Bool_t load); - /// return class type - virtual TClass *GetClass(type_info const& typeinfo, Bool_t load); - /// interface for TClass generators - //ClassDef(RootAutoLibraryLoader,1); +private: // Private Data Members + std::string classNameAttemptingToLoad_; +private: // Private Function Members + RootAutoLibraryLoader(); + RootAutoLibraryLoader(RootAutoLibraryLoader const&); // NOT IMPLEMENTED + RootAutoLibraryLoader const& operator=(RootAutoLibraryLoader const&); // NOT IMPLEMENTED +public: // Public Static Function Members /// enable automatic library loading static void enable(); - /// load all known libraries holding dictionaries static void loadAll(); - -private: - char const* classNameAttemptingToLoad_; //! - RootAutoLibraryLoader(); - RootAutoLibraryLoader(RootAutoLibraryLoader const&); // stop default - RootAutoLibraryLoader const& operator=(RootAutoLibraryLoader const&); // stop default -#if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6) - bool isInitializingCintex_; -#endif +public: // Public Function Members + /// return class type + virtual TClass* GetClass(const char* classname, Bool_t load); + /// return class type + virtual TClass* GetClass(const type_info& typeinfo, Bool_t load); }; -} -#endif +} // namespace edm + +#endif // LibraryLoader_RootAutoLibraryLoader_h diff --git a/FWCore/RootAutoLibraryLoader/src/RootAutoLibraryLoader.cc b/FWCore/RootAutoLibraryLoader/src/RootAutoLibraryLoader.cc index eed9e719d654b..f78445d2af5e0 100644 --- a/FWCore/RootAutoLibraryLoader/src/RootAutoLibraryLoader.cc +++ b/FWCore/RootAutoLibraryLoader/src/RootAutoLibraryLoader.cc @@ -10,428 +10,260 @@ // Created: Wed Nov 30 14:55:01 EST 2005 // -// system include files -#include -#include -#include -#include "TROOT.h" -#include "TInterpreter.h" -//#include "G__ci.h" - -// user include files #include "FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h" -#include "FWCore/RootAutoLibraryLoader/src/stdNamespaceAdder.h" +#include "FWCore/PluginManager/interface/PluginCapabilities.h" #include "FWCore/PluginManager/interface/PluginManager.h" #include "FWCore/PluginManager/interface/ProblemTracker.h" -#include "FWCore/PluginManager/interface/PluginCapabilities.h" +#include "FWCore/RootAutoLibraryLoader/src/stdNamespaceAdder.h" #include "FWCore/Utilities/interface/DictionaryTools.h" #include "FWCore/Utilities/interface/Exception.h" #include "TClass.h" +#include "TInterpreter.h" +#include "TROOT.h" -// We cannot use the MessageLogger here because this is also used by standalones that do not have the logger. - -// -// constants, enums and typedefs -// -namespace { - //Based on http://root.cern.ch/lxr/source/cintex/src/CINTSourceFile.h - // If a Cint dictionary is accidently loaded as a side effect of loading a CMS - // library Cint must have a file name assigned to that dictionary else Cint may crash - class RootLoadFileSentry { - public: - RootLoadFileSentry() { - //G__setfilecontext("{CMS auto library loader}", &oldIFile_); - } +#include +#include +#include - ~RootLoadFileSentry() { - //G__input_file* ifile = G__get_ifile(); - //if (ifile) { - // *ifile = oldIFile_; - // } - } +using CallbackPtr = int (*)(const char*); +static void* gPrevious = nullptr; - private: - //G__input_file oldIFile_; - }; +/// Check if the class name is known to the ROOT interpreter. +static +bool +interpreterLookupClass(const std::string& name) +{ + ClassInfo_t* ci = gInterpreter->ClassInfo_Factory(name.c_str()); + return gInterpreter->ClassInfo_IsValid(ci); } -// -// static data member definitions -// -//hold onto the previous autolibrary loader -typedef int (*CallbackPtr)(char*, char*); -static CallbackPtr gPrevious = nullptr; -static char const* kDummyLibName = "*dummy"; - -//This is actually defined within ROOT's v6_struct.cxx file but is not declared static -// I want to use it so that if the autoloading is already turned on, I can call the previously declared routine -//extern CallbackPtr G__p_class_autoloading; - -namespace ROOT { - namespace Cintex { - std::string CintName(std::string const&); +/// Use the SEAL Capabilities plugin to load a library which +/// provides the definition of a class, and verify that the +/// ROOT interpreter now knows about the class. +static +bool +loadLibraryForClass(const char* classname) +{ + if (classname == nullptr) { + return false; } -} - -namespace edm { - namespace { - - std::map& - cintToReflexSpecialCasesMap() { - static std::map s_map; - return s_map; - } - - void - addWrapperOfVectorOfBuiltin(std::map& iMap, char const* iBuiltin) { - static std::string const sReflexPrefix("edm::Wrapper >"); - - //Wrapper > > - static std::string const sCintPrefix("Wrapper > >"); - - std::string type(iBuiltin); - iMap.insert(make_pair(sCintPrefix + type + sCintMiddle + type + sCintPostfix, - sReflexPrefix + type + sReflexPostfix)); - } - - std::string - classNameForRoot(std::string const& classname) { - // Converts the name to the name known by CINT (e.g. strips out "std::") - //return ROOT::Cintex::CintName(classname); - return classname; - } - - bool - isDictionaryLoaded(std::string const& rootclassname) { - // This checks if the class name is known to the interpreter. - // In this context, this will be true if and only if the dictionary has been loaded (and converted to CINT). - // This code is independent of the identity of the interpreter. - ClassInfo_t* info = gInterpreter->ClassInfo_Factory(rootclassname.c_str()); - return gInterpreter->ClassInfo_IsValid(info); + const std::string& cPrefix = edm::dictionaryPlugInPrefix(); + std::string name(classname); + try { + if (edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name)) { + // We loaded a library, now check to see if we got the class. + if (!interpreterLookupClass(name)) { + // Nope, did not get it. + return false; } + // Good, library loaded for class and the interpreter knows it now. + return true; + } + // Try adding a std namespace qualifier. + std::string stdName = edm::root::stdNamespaceAdder(name); + if (!edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + stdName)) { + // Bad, we did not load a library for the class. + return false; + } + // We loaded a library, now check to see if we got the class. + if (!interpreterLookupClass(stdName)) { + // Nope, did not get it. + return false; + } + // Good, library loaded for class and the interpreter knows it now. + return true; + } + catch (cms::Exception& e) { + // Bad, loading threw a known CMS exception. + return false; + } + // Note: Cannot happen! + return true; +} - bool loadLibraryForClass(char const* classname) { - //std::cout << "loadLibaryForClass" << std::endl; - if(nullptr == classname) { - return false; - } - //std::cout << "asking to find " << classname << std::endl; - std::string const& cPrefix = dictionaryPlugInPrefix(); - //std::cout << "asking to find " << cPrefix + classname << std::endl; - std::string rootclassname = classNameForRoot(classname); - try { - //give ROOT a name for the file we are loading - RootLoadFileSentry sentry; - if(edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + classname)) { - if(!isDictionaryLoaded(rootclassname)) { - //would be nice to issue a warning here. Not sure the remainder of this comment is correct. - // this message happens too often (too many false positives) to be useful plus ROOT will complain about a missing dictionary - //std::cerr << "Warning: ROOT knows about type '" << classname << "' but has no dictionary for it." << std::endl; - return false; - } - } else { - //see if adding a std namespace helps - std::string name = root::stdNamespaceAdder(classname); - //std::cout << "see if std helps" << std::endl; - if (not edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name)) { - // Too many false positives on built-in types here. - return false; - } - if(!isDictionaryLoaded(rootclassname)) { - //would be nice to issue a warning here - return false; - } - } - } catch(cms::Exception& e) { - //would be nice to issue a warning here - return false; - } - //std::cout << "loaded " << classname << std::endl; - return true; - } - - //Based on code in ROOT's TCint.cxx file - - int ALL_AutoLoadCallback(char* c, char* l) { - //NOTE: if the library (i.e. 'l') is an empty string this means we are dealing with a namespace - // These checks appear to avoid a crash of ROOT during shutdown of the application - if(nullptr == c || nullptr == l || l[0] == 0) { - return 0; - } - //ULong_t varp = G__getgvp(); - //G__setgvp((long)G__PVOID); - int result = loadLibraryForClass(c) ? 1:0; - //G__setgvp(varp); - //NOTE: the check for the library is done since we can have a failure - // if a CMS library has an incomplete set of reflex dictionaries where - // the remaining dictionaries can be found by Cint. If the library with - // the reflex dictionaries is loaded first, then the Cint library then any - // requests for a Type from the reflex library will fail because for - // some reason the loading of the Cint library causes reflex to forget about - // what types it already loaded from the reflex library. This problem was - // seen for libDataFormatsMath and libMathCore. I do not print an error message - // since the dictionaries are actually loaded so things work fine. - if(!result && 0 != strcmp(l, kDummyLibName) && gPrevious) { - result = gPrevious(c, l); - } - return result; - } - - //Cint requires that we register the type and library containing the type - // before the autoloading will work - struct CompareFirst { - bool operator()(std::pair const& iLHS, - std::pair const& iRHS) const{ - return iLHS.first > iRHS.first; - } - }; - - void registerTypes() { - edmplugin::PluginManager* db = edmplugin::PluginManager::get(); - - typedef edmplugin::PluginManager::CategoryToInfos CatToInfos; - - CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability"); - - if(itFound == db->categoryToInfos().end()) { - return; - } - - //in order to determine if a name is from a class or a namespace, we will order - // all the classes in descending order so that embedded classes will be seen before - // their containing classes, that way we can say the containing class is a namespace - // before finding out it is actually a class - typedef std::vector > ClassAndLibraries; - ClassAndLibraries classes; - classes.reserve(1000); - std::string lastClass; - - //find where special cases come from - std::map specialsToLib; - std::map const& specials = cintToReflexSpecialCasesMap(); - for(auto const& special : specials) { - specialsToLib[classNameForRoot(special.second)]; - } - std::string const& cPrefix = dictionaryPlugInPrefix(); - for(auto const& info : itFound->second) { - if (lastClass == info.name_) { - continue; - } - lastClass = info.name_; - if(cPrefix == lastClass.substr(0, cPrefix.size())) { - std::string className = classNameForRoot(lastClass.c_str() + cPrefix.size()); - classes.emplace_back(className, info.loadable_.string()); - std::map::iterator iFound = specialsToLib.find(className); - if(iFound != specialsToLib.end()) { - // std::cout << "Found " << lastClass << " : " << className << std::endl; - iFound->second = info.loadable_.string(); - } - } - } - //sort_all(classes, std::greater()); - //sort_all(classes, CompareFirst()); - //the values are already sorted by less, so just need to reverse to get greater - for(ClassAndLibraries::reverse_iterator itClass = classes.rbegin(), itClassEnd = classes.rend(); - itClass != itClassEnd; - ++itClass) { - - std::string const& className = itClass->first; - //std::string const& libraryName = itClass->second; - //need to register namespaces and figure out if we have an embedded class - static std::string const toFind(":<"); - std::string::size_type pos = 0; - while(std::string::npos != (pos = className.find_first_of(toFind, pos))) { - if (className[pos] == '<') {break;} - if (className.size() <= pos + 1 || className[pos + 1] != ':') {break;} - //should check to see if this is a class or not - //G__set_class_autoloading_table(const_cast(className.substr(0, pos).c_str()), const_cast("")); - //std::cout << "namespace " << className.substr(0, pos).c_str() << std::endl; - pos += 2; - } - //G__set_class_autoloading_table(const_cast(className.c_str()), const_cast(libraryName.c_str())); - //std::cout << "class " << className.c_str() << std::endl; - } - - //now handle the special cases - for(auto const& special : specials) { - std::string const& name = special.second; - std::string rootname = classNameForRoot(name); - //std::cout << "registering special " << itSpecial->first << " " << name << " " << std::endl << " " << specialsToLib[rootname] << std::endl; - //force loading of specials - if(specialsToLib[rootname].size()) { - //std::cout << "&&&&& found special case " << itSpecial->first << std::endl; - if(!isDictionaryLoaded(rootname) and - (not edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name))) { - std::cout << "failed to load plugin for " << cPrefix + name << std::endl; - continue; - } else { - //need to construct the Class ourselves - if(!isDictionaryLoaded(rootname)) { - std::cout << "dictionary did not build " << name << std::endl; - continue; - } - TClass* namedClass = TClass::GetClass(rootname.c_str()); - if(nullptr == namedClass) { - std::cout << "failed to get TClass for " << name << std::endl; - continue; - } - namedClass->Clone(special.first.c_str()); - std::string magictypedef("namespace edm { typedef "); - magictypedef += rootname + " " + special.first + "; }"; - // std::cout << "Magic typedef " << magictypedef << std::endl; - gROOT->ProcessLine(magictypedef.c_str()); - } - } - } - } - } - - // - // constructors and destructor - // - RootAutoLibraryLoader::RootAutoLibraryLoader() : -#if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6) - classNameAttemptingToLoad_(nullptr), - isInitializingCintex_(true) { -#else - classNameAttemptingToLoad_(nullptr) { -#endif - AssertHandler h; - gROOT->AddClassGenerator(this); -#if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6) - isInitializingCintex_ =false; -#endif - //set the special cases - std::map& specials = cintToReflexSpecialCasesMap(); - if(specials.empty()) { - addWrapperOfVectorOfBuiltin(specials,"bool"); - - addWrapperOfVectorOfBuiltin(specials,"char"); - addWrapperOfVectorOfBuiltin(specials,"unsigned char"); - addWrapperOfVectorOfBuiltin(specials,"signed char"); - addWrapperOfVectorOfBuiltin(specials,"short"); - addWrapperOfVectorOfBuiltin(specials,"unsigned short"); - addWrapperOfVectorOfBuiltin(specials,"int"); - addWrapperOfVectorOfBuiltin(specials,"unsigned int"); - addWrapperOfVectorOfBuiltin(specials,"long"); - addWrapperOfVectorOfBuiltin(specials,"unsigned long"); - addWrapperOfVectorOfBuiltin(specials,"long long"); - addWrapperOfVectorOfBuiltin(specials,"unsigned long long"); +/// Callback for the ROOT interpreter to invoke when it fails +/// during lookup of a class name. We try to load a library +/// that provides the definition of the class using the SEAL +/// Capabilities plugin. +static +int +AutoLoadCallback(const char* c) +{ + if (c == nullptr) { + return 0; + } + int result = loadLibraryForClass(c); + if (result) { + // Good, library loaded and class is now known by the interpreter. + return result; + } + // Failed, chain to next callback. + if (gPrevious) { + result = (*reinterpret_cast(gPrevious))(c); + } + return result; +} - addWrapperOfVectorOfBuiltin(specials,"float"); - addWrapperOfVectorOfBuiltin(specials,"double"); +#if 0 + +static +void +registerTypes() +{ + // + // Setup the CINT autoloading table so that it knows which + // library to load for every SEAL Capability dictionary + // plugin class. + // + //-- + // Get the list of SEAL Capability plugins from the plugin manager. + edmplugin::PluginManager *db = edmplugin::PluginManager::get(); + auto itFound = db->categoryToInfos().find("Capability"); + if (itFound == db->categoryToInfos().end()) { + return; + } + std::string const& cPrefix = edm::dictionaryPlugInPrefix(); + using ClassAndLibraries = std::vector>; + ClassAndLibraries classesAndLibs; + classesAndLibs.reserve(1000); + { + std::string prev; + // Loop over all the plugins. + for (auto const & info : itFound->second) { + if (prev == info.name_) { + continue; } - //std::cout << "my loader" << std::endl; - //remember if the callback was already set so we can chain together our results - //gPrevious = G__p_class_autoloading; - //G__set_class_autoloading_callback(&ALL_AutoLoadCallback); - registerTypes(); - } - - // - // member functions - // - - TClass* - RootAutoLibraryLoader::GetClass(char const* classname, Bool_t load) { - TClass* returnValue = nullptr; - if(classNameAttemptingToLoad_ != nullptr && !strcmp(classname, classNameAttemptingToLoad_)) { - // We can try to see if the class name contains "basic_string". - // If so, we replace "basic_string" with "string" and try again. - std::string className(classname); - std::string::size_type idx = className.find("basic_string"); - if (idx != std::string::npos) { - className.replace(idx, 18, std::string("string")); - //if basic_string was the last argument to a templated class - // then there would be an extra space to separate the two '>' - if(className.size() > idx + 6 && className[idx + 6] == ' ') { - className.replace(idx + 6, 1, ""); - } - classNameAttemptingToLoad_ = className.c_str(); - returnValue = gROOT->GetClass(className.c_str(), kTRUE); - classNameAttemptingToLoad_ = classname; - return returnValue; - } - //NOTE: As of ROOT 5.27.06 this warning generates false positives for HepMC classes because - // ROOT has special handling for them built into class.rules - //std::cerr << "WARNING[RootAutoLibraryLoader]: ROOT failed to create CINT dictionary for " << classname << std::endl; - return nullptr; + prev = info.name_; + if (info.name_.substr(0, cPrefix.size() != cPrefix)) { + // Ignore plugins that are not dictionary plugins. + continue; } - //std::cout << "looking for " << classname << " load " << (load? "T":"F") << std::endl; - if (load) { - //std::cout << " going to call loadLibraryForClass" << std::endl; - //[ROOT 5.28] When Cintex is in its 'Enable' method it will register callbacks to build - // TClasses. During this phase we do not want to actually force TClasses to have to - // come into existence. -#if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6) - if (not isInitializingCintex_ and loadLibraryForClass(classname)) { -#else - if (loadLibraryForClass(classname)) { -#endif - //use this to check for infinite recursion attempt - classNameAttemptingToLoad_ = classname; - // This next call will create the TClass object for the class. - // It will also attempt to load the dictionary for the class - // if the second argument is kTRUE. This is the default, so it - // need not be explicitly specified. - returnValue = gROOT->GetClass(classname, kTRUE); - classNameAttemptingToLoad_ = nullptr; - } + std::string className(info.name_, cPrefix.size()); + classesAndLibs.emplace_back(className, info.loadable_.string()); + } + } + // FIXME: Probably not needed anymore. + // In order to determine if a name is from a class or a + // namespace, we will order all the classes in descending + // order so that embedded classes will be seen before their + // containing classes, that way we can say the containing + // class is a namespace before finding out it is actually + // a class. + for (auto I = classesAndLibs.rbegin(), E = classesAndLibs.rend(); I != E; + ++I) { + const std::string& className = I->first; + const std::string& libraryName = I->second; + // We need to register namespaces and to figure out if we + // have an embedded class. + static const std::string toFind(":<"); + auto pos = className.find_first_of(toFind, pos); + while (pos != std::string::npos) { + // We are at a namespace boundary, or a template argument boundary. + if (className[pos] == '<') { + // Template argument boundary, no need to scan further + // for namespace names, and we now register the whole + // class name (Note: We may do this multiple times!). + break; } - return returnValue; - } - - TClass* - RootAutoLibraryLoader::GetClass(type_info const& typeinfo, Bool_t load) { - //std::cout << "looking for type " << typeinfo.name() << std::endl; - TClass* returnValue = nullptr; - if(load) { - return GetClass(typeinfo.name(), load); + if ((className.size() <= (pos + 1)) || (className[pos+1] != ':')) { + break; } - return returnValue; - } - - void - RootAutoLibraryLoader::enable() { - //static BareRootProductGetter s_getter; - //static EDProductGetter::Operate s_op(&s_getter); - static RootAutoLibraryLoader s_loader; - } - - void - RootAutoLibraryLoader::loadAll() { - // std::cout << "LoadAllDictionaries" << std::endl; - enable(); - - edmplugin::PluginManager* db = edmplugin::PluginManager::get(); + // FIXME: This does bad things if a template argument is qualified! + // FIXME: if className.substr(0, pos).find('<') { bad } + // We have found a "::" in the name, register a namespace. + G__set_class_autoloading_table(className.substr(0, pos).c_str(), ""); + pos += 2; + } + G__set_class_autoloading_table(className.c_str(), libraryName.c_str()); + // Continue scanning from here. + pos = className.find_first_of(toFind, pos); + } +} +#endif // 0 - typedef edmplugin::PluginManager::CategoryToInfos CatToInfos; +namespace edm { - CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability"); +RootAutoLibraryLoader:: +RootAutoLibraryLoader() + : classNameAttemptingToLoad_() +{ + // Note: The only thing AssertHandler really does is call + // PluginManager::configure() with the default configuration. + AssertHandler h; + // Register our ROOT TClass::GetClass(std::type_info) and + // TROOT::LoadClass(name, silent) hook. + gROOT->AddClassGenerator(this); + // Register our ROOT interpreter class-name-not-found hook. + gPrevious = gInterpreter->GetAutoLoadCallBack(); + gInterpreter->SetAutoLoadCallBack(reinterpret_cast(&AutoLoadCallback)); + //registerTypes(); +} - if(itFound == db->categoryToInfos().end()) { - return; - } - std::string lastClass; +TClass* +RootAutoLibraryLoader:: +GetClass(char const* classname, bool load) +{ + if (!strcmp(classname, classNameAttemptingToLoad_.c_str())) { + // Recursive call to ourselves detected. We could not load + // the class and ROOT could not load the class. + return nullptr; + } + if (!load) { + return nullptr; + } + // Try to load a library which provides the class definition + // using the SEAL Capability plugin. + if (!loadLibraryForClass(classname)) { + // Bad, we could not load a library. + return nullptr; + } + // Good, library was loaded, now have ROOT provide the TClass. + // Note: Here we guard against a recursive call to ourselves. + classNameAttemptingToLoad_ = classname; + auto ret = gROOT->GetClass(classname, true); + classNameAttemptingToLoad_.clear(); + return ret; +} - //give ROOT a name for the file we are loading - RootLoadFileSentry sentry; +TClass* +RootAutoLibraryLoader:: +GetClass(const type_info& typeinfo, bool load) +{ + if (!load) { + return nullptr; + } + // FIXME: demangle the name here! + return GetClass(typeinfo.name(), load); +} - for(auto const& info : itFound->second) { - if (lastClass == info.name_) { - continue; - } +void +RootAutoLibraryLoader:: +enable() +{ + static RootAutoLibraryLoader singleton; +} - lastClass = info.name_; - edmplugin::PluginCapabilities::get()->load(lastClass); - //NOTE: since we have the library already, we could be more efficient if we just load it ourselves - } - } +void +RootAutoLibraryLoader:: +loadAll() +{ + enable(); + auto db = edmplugin::PluginManager::get(); + auto itFound = db->categoryToInfos().find("Capability"); + if (itFound == db->categoryToInfos().end()) { + return; + } + std::string prev; + for (auto const& plugin_info : itFound->second) { + if (plugin_info.name_ == prev) { + continue; + } + edmplugin::PluginCapabilities::get()->load(plugin_info.name_); + prev = plugin_info.name_; + } } -//ClassImp(RootAutoLibraryLoader) +} // namespace edm + diff --git a/FWCore/Utilities/interface/BaseWithDict.h b/FWCore/Utilities/interface/BaseWithDict.h index 0f178b701b809..4fdc3f5c6c6c2 100644 --- a/FWCore/Utilities/interface/BaseWithDict.h +++ b/FWCore/Utilities/interface/BaseWithDict.h @@ -2,35 +2,33 @@ #define FWCore_Utilities_BaseWithDict_h /*---------------------------------------------------------------------- - + BaseWithDict: A holder for a base class ----------------------------------------------------------------------*/ + #include class TBaseClass; namespace edm { - class TypeWithDict; - - class BaseWithDict { - public: - BaseWithDict(); - - explicit BaseWithDict(TBaseClass* baseClass); - - std::string name() const; - - TypeWithDict typeOf() const; +class TypeWithDict; - bool isPublic() const; +class BaseWithDict { +private: + TBaseClass* baseClass_; +public: + BaseWithDict(); + explicit BaseWithDict(TBaseClass*); + bool isPublic() const; + std::string name() const; + TypeWithDict typeOf() const; +}; - private: +} // namespace edm - TBaseClass* baseClass_; - }; +#include "FWCore/Utilities/interface/TypeWithDict.h" -} -#endif +#endif // FWCore_Utilities_BaseWithDict_h diff --git a/FWCore/Utilities/interface/DictionaryTools.h b/FWCore/Utilities/interface/DictionaryTools.h index d4c6e2fc2536c..5ee926ab43743 100644 --- a/FWCore/Utilities/interface/DictionaryTools.h +++ b/FWCore/Utilities/interface/DictionaryTools.h @@ -14,55 +14,59 @@ the CMS event model. namespace edm { - class TypeWithDict; - typedef std::set StringSet; - - bool - find_nested_type_named(std::string const& nested_type, - TypeWithDict const& type_to_search, - TypeWithDict& found_type); - bool - find_nested_type_named(std::string const& nested_type, - TypeWithDict const& type_to_search, - TypeWithDict& found_type); - - inline - bool - value_type_of(TypeWithDict const& t, TypeWithDict& found_type) { - return find_nested_type_named("value_type", t, found_type); - } - - - inline - bool - wrapper_type_of(TypeWithDict const& possible_wrapper, - TypeWithDict& found_wrapped_type) { - return find_nested_type_named("wrapped_type", - possible_wrapper, - found_wrapped_type); - } - - bool - is_RefVector(TypeWithDict const& possible_ref_vector, - TypeWithDict& value_type); - - bool - is_PtrVector(TypeWithDict const& possible_ref_vector, - TypeWithDict& value_type); - bool - is_RefToBaseVector(TypeWithDict const& possible_ref_vector, - TypeWithDict& value_type); - - void checkDictionaries(std::string const& name, bool noComponents = false); - void throwMissingDictionariesException(); - void loadMissingDictionaries(); - StringSet& missingTypes(); - StringSet& foundTypes(); - - void public_base_classes(TypeWithDict const& type, - std::vector& baseTypes); - - std::string const& dictionaryPlugInPrefix(); +class TypeWithDict; +using StringSet = std::set; + +bool +find_nested_type_named(std::string const& nested_type, + TypeWithDict const& type_to_search, + TypeWithDict& found_type); + +bool +find_nested_type_named(std::string const& nested_type, + TypeWithDict const& type_to_search, + TypeWithDict& found_type); + +inline +bool +value_type_of(const TypeWithDict& t, TypeWithDict& found_type) +{ + return find_nested_type_named("value_type", t, found_type); } -#endif + +inline +bool +wrapper_type_of(const TypeWithDict& possible_wrapper, + TypeWithDict& found_wrapped_type) +{ + return find_nested_type_named("wrapped_type", + possible_wrapper, + found_wrapped_type); +} + +bool +is_RefVector(const TypeWithDict& possible_ref_vector, + TypeWithDict& value_type); + +bool +is_PtrVector(const TypeWithDict& possible_ref_vector, + TypeWithDict& value_type); +bool +is_RefToBaseVector(const TypeWithDict& possible_ref_vector, + TypeWithDict& value_type); + +void checkDictionaries(const std::string& name, bool noComponents = false); +void throwMissingDictionariesException(); +void loadMissingDictionaries(); +StringSet& missingTypes(); +StringSet& foundTypes(); + +void public_base_classes(const TypeWithDict& type, + std::vector& baseTypes); + +const std::string& dictionaryPlugInPrefix(); + +} // namespace edm + +#endif // FWCore_Utilities_DictionaryTools_h diff --git a/FWCore/Utilities/interface/FunctionWithDict.h b/FWCore/Utilities/interface/FunctionWithDict.h index 5573a02d6fc81..450340958a3f5 100644 --- a/FWCore/Utilities/interface/FunctionWithDict.h +++ b/FWCore/Utilities/interface/FunctionWithDict.h @@ -2,75 +2,78 @@ #define FWCore_Utilities_FunctionWithDict_h /*---------------------------------------------------------------------- - + FunctionWithDict: A holder for a class member function ----------------------------------------------------------------------*/ -#include +#include "FWCore/Utilities/interface/IterWithDict.h" + +#include "TMethod.h" +#include "TMethodArg.h" + #include #include -namespace Reflex { - class Member; - class Type_Iterator; -} - namespace edm { - class ObjectWithDict; - class TypeWithDict; - - class FunctionWithDict { - public: - FunctionWithDict(); - - explicit FunctionWithDict(Reflex::Member const& function); - - std::string name() const; - - std::string typeName() const; - - TypeWithDict declaringType() const; - - TypeWithDict typeOf() const; - - bool isConst() const; - - bool isConstructor() const; +class ObjectWithDict; +class TypeWithDict; + +class FunctionWithDict { +private: + TMethod* function_; +public: + FunctionWithDict(); + explicit FunctionWithDict(TMethod*); + explicit operator bool() const; + std::string name() const; + std::string typeName() const; + TypeWithDict typeOf() const; + TypeWithDict returnType() const; + TypeWithDict finalReturnType() const; + bool isConst() const; + bool isConstructor() const; + bool isDestructor() const; + bool isOperator() const; + bool isPublic() const; + bool isStatic() const; + TypeWithDict declaringType() const; + size_t functionParameterSize(bool required = false) const; + size_t size() const; + void invoke(const ObjectWithDict& obj, ObjectWithDict* ret = nullptr, const std::vector& values = std::vector()) const; + void invoke(ObjectWithDict* ret = nullptr, const std::vector& values = std::vector()) const; + IterWithDict begin() const; + IterWithDict end() const; +}; + +} // namespace edm + +#include "FWCore/Utilities/interface/ObjectWithDict.h" +#include "FWCore/Utilities/interface/TypeWithDict.h" - bool isDestructor() const; - - bool isOperator() const; - - bool isPublic() const; - - bool isStatic() const; - - TypeWithDict returnType() const; - - TypeWithDict finalReturnType() const; - - size_t functionParameterSize(bool required = false) const; - - void invoke(ObjectWithDict const& obj, ObjectWithDict* ret, std::vector const& values = std::vector()) const; - - //Reflex::Type_Iterator begin() const; - //Reflex::Type_Iterator end() const; - size_t size() const { - return functionParameterSize(); - } - -#ifndef __GCCXML__ - explicit operator bool() const; -#endif - - Reflex::Member const& function() const; +namespace edm { - private: +/// Call a static function of class T, derived from the type +/// of the return value, by name with no arguments. +template +inline +void +invokeByName(T& retval, const std::string& name) +{ + TypeWithDict theType(typeid(T)); + FunctionWithDict func = theType.functionMemberByName(name); + if (!bool(func)) { + return; + } + if (func.functionParameterSize(true) != 0) { + // FIXME: We should throw or write an error message here! + return; + } + ObjectWithDict retobj(typeid(T), &retval); + func.invoke(retobj); +} - Reflex::Member* function_; - }; +} // namespace edm -} -#endif +#endif // FWCore_Utilities_FunctionWithDict_h diff --git a/FWCore/Utilities/interface/IterWithDict.h b/FWCore/Utilities/interface/IterWithDict.h index 3221a7976d49a..13bc4234c5ade 100644 --- a/FWCore/Utilities/interface/IterWithDict.h +++ b/FWCore/Utilities/interface/IterWithDict.h @@ -2,7 +2,7 @@ #define FWCore_Utilities_IterWithDict_h /*---------------------------------------------------------------------- - + IterWithDict: An iterator for a TList so a range for loop can be used ----------------------------------------------------------------------*/ @@ -11,33 +11,33 @@ IterWithDict: An iterator for a TList so a range for loop can be used namespace edm { - class IterWithDictBase { - public: - IterWithDictBase(); - explicit IterWithDictBase(TList* list); - bool operator!=(IterWithDictBase const &) const; - - protected: - void advance(); - TIter const& iter() const; - - private: - TIter iter_; - bool atEnd_; - }; - - template - class IterWithDict : public IterWithDictBase { - public: - IterWithDict() : IterWithDictBase() {} - explicit IterWithDict(TList* list) : IterWithDictBase(list) {} - IterWithDict& operator++() { - advance(); - return *this; - } - T* operator*() const { - return static_cast(*iter()); - } - }; -} -#endif +class IterWithDictBase { +private: + TIter iter_; + bool atEnd_; +protected: + void advance(); + const TIter& iter() const; +public: + IterWithDictBase(); + explicit IterWithDictBase(TList*); + bool operator!=(const IterWithDictBase&) const; +}; + +template +class IterWithDict : public IterWithDictBase { +public: + IterWithDict() : IterWithDictBase() {} + explicit IterWithDict(TList* list) : IterWithDictBase(list) {} + IterWithDict& operator++() { + advance(); + return *this; + } + T* operator*() const { + return static_cast(*iter()); + } +}; + +} // namespace edm + +#endif // FWCore_Utilities_IterWithDict_h diff --git a/FWCore/Utilities/interface/MemberWithDict.h b/FWCore/Utilities/interface/MemberWithDict.h index 31805d4799129..d6cd71e8e5fc0 100644 --- a/FWCore/Utilities/interface/MemberWithDict.h +++ b/FWCore/Utilities/interface/MemberWithDict.h @@ -2,54 +2,43 @@ #define FWCore_Utilities_MemberWithDict_h /*---------------------------------------------------------------------- - + MemberWithDict: A holder for a class member ----------------------------------------------------------------------*/ + #include class TDataMember; namespace edm { - class ObjectWithDict; - class TypeWithDict; - - class MemberWithDict { - public: - MemberWithDict(); - - explicit MemberWithDict(TDataMember* dataMember); - - std::string name() const; - - ObjectWithDict get() const; - - ObjectWithDict get(ObjectWithDict const& obj) const; - - TypeWithDict declaringType() const; - - TypeWithDict typeOf() const; - - bool isConst() const; - - bool isPublic() const; - - bool isStatic() const; - - bool isTransient() const; - - size_t offset() const; - -#ifndef __GCCXML__ - explicit operator bool() const; -#endif - - private: - - TDataMember* dataMember_; - }; - -} -#endif +class ObjectWithDict; +class TypeWithDict; + +class MemberWithDict { +private: + TDataMember* dataMember_; +public: + MemberWithDict(); + explicit MemberWithDict(TDataMember*); + explicit operator bool() const; + std::string name() const; + bool isConst() const; + bool isPublic() const; + bool isStatic() const; + bool isTransient() const; + size_t offset() const; + TypeWithDict declaringType() const; + TypeWithDict typeOf() const; + ObjectWithDict get() const; + ObjectWithDict get(const ObjectWithDict&) const; +}; + +} // namespace edm + +#include "FWCore/Utilities/interface/ObjectWithDict.h" +#include "FWCore/Utilities/interface/TypeWithDict.h" + +#endif // FWCore_Utilities_MemberWithDict_h diff --git a/FWCore/Utilities/interface/ObjectWithDict.h b/FWCore/Utilities/interface/ObjectWithDict.h index 73862b8abfe56..ae6a30842b36e 100644 --- a/FWCore/Utilities/interface/ObjectWithDict.h +++ b/FWCore/Utilities/interface/ObjectWithDict.h @@ -2,51 +2,47 @@ #define FWCore_Utilities_ObjectWithDict_h /*---------------------------------------------------------------------- - + ObjectWithDict: A holder for an object and its type information. ----------------------------------------------------------------------*/ + +#include "TInterpreter.h" + #include #include -#include "FWCore/Utilities/interface/TypeWithDict.h" - namespace edm { - class ObjectWithDict { - public: - ObjectWithDict(); - - ObjectWithDict(TypeWithDict const& type, void* address); - - ObjectWithDict(std::type_info const& typeID, void* address); - - static ObjectWithDict byType(TypeWithDict const& type); +class TypeWithDict; + +class ObjectWithDict { +private: + TType* type_; + void* address_; +public: + static ObjectWithDict byType(const TypeWithDict&); +public: + ObjectWithDict(); + explicit ObjectWithDict(const TypeWithDict&, void* address); + explicit ObjectWithDict(const std::type_info&, void* address); + explicit operator bool() const; + void* address() const; + TypeWithDict typeOf() const; + TypeWithDict dynamicType() const; + ObjectWithDict get(const std::string& memberName) const; + //ObjectWithDict construct() const; + void destruct(bool dealloc) const; + template + T + objectCast() + { + return *reinterpret_cast(address_); + } +}; + +} // namespace edm - void* address() const; - - TypeWithDict const& typeOf() const; - - TypeWithDict dynamicType() const; - - ObjectWithDict get(std::string const& memberName) const; - -#ifndef __GCCXML__ - explicit operator bool() const; -#endif - - template T objectCast() { - return *reinterpret_cast(address_); - } - - private: - friend class FunctionWithDict; - friend class MemberWithDict; - friend class TypeWithDict; - - TypeWithDict type_; - void* address_; - }; +#include "FWCore/Utilities/interface/TypeWithDict.h" -} -#endif +#endif // FWCore_Utilities_ObjectWithDict_h diff --git a/FWCore/Utilities/interface/TypeWithDict.h b/FWCore/Utilities/interface/TypeWithDict.h index 0014d9111b3b2..7b75b5dafcb6e 100644 --- a/FWCore/Utilities/interface/TypeWithDict.h +++ b/FWCore/Utilities/interface/TypeWithDict.h @@ -2,32 +2,29 @@ #define FWCore_Utilities_TypeWithDict_h /*---------------------------------------------------------------------- - + TypeWithDict: A unique identifier for a C++ type, with the dictionary information The identifier is unique within an entire program, but can not be persisted across invocations of the program. ----------------------------------------------------------------------*/ -#include -#include -#include -#include +#include "FWCore/Utilities/interface/IterWithDict.h" #include "TBaseClass.h" #include "TClass.h" #include "TDataMember.h" #include "TDataType.h" +#include "TEnum.h" #include "TMethod.h" +#include "TMethodArg.h" -#include "FWCore/Utilities/interface/IterWithDict.h" -//#include "Reflex/Member.h" -//#include "Reflex/Type.h" +#include +#include +#include +#include -class TBaseClass; -class TDataMember; -class TMethod; -class TMethodArg; +class TType; namespace Reflex { class Member; @@ -36,197 +33,146 @@ namespace Reflex { namespace edm { - class FunctionWithDict; - class MemberWithDict; - class ObjectWithDict; - -/* - enum TypeMemberQuery { - InheritedDefault = Reflex::INHERITEDMEMBERS_DEFAULT, - InheritedNo = Reflex::INHERITEDMEMBERS_NO, - InheritedAlso = Reflex::INHERITEDMEMBERS_ALSO - }; -*/ - - class TypeWithDict { - public: - - TypeWithDict(); - - explicit TypeWithDict(std::type_info const& t); - - explicit TypeWithDict(std::type_info const& t, Long_t property); - - explicit TypeWithDict(Reflex::Type const& type); - - explicit TypeWithDict(TypeWithDict const& type, Long_t property); - - explicit TypeWithDict(TClass* type, Long_t property = (Long_t)kIsClass); - - explicit TypeWithDict(TMethodArg* arg); - - static TypeWithDict - byName(std::string const& className); - - static TypeWithDict - byName(std::string const& className, Long_t property); - - // Print out the name of the type, using the dictionary class name. - void print(std::ostream& os) const; - - std::string qualifiedName() const; - - std::string unscopedName() const; - - std::string name() const; - - std::string userClassName() const; - - std::string friendlyClassName() const; - - bool hasDictionary() const; - - bool isClass() const; - - bool isConst() const; - - bool isEnum() const; - - bool isFundamental() const; - - bool isPointer() const; - - bool isReference() const; - - bool isTemplateInstance() const; - - bool isTypedef() const; - - bool isVirtual() const; - - TypeWithDict toType() const; - - TypeWithDict nestedType(char const* name) const; - - TypeWithDict nestedType(std::string const& name) const { - return nestedType(name.c_str()); - } - - int getBaseClassOffset(TypeWithDict const& baseClass) const; - - TypeWithDict templateArgumentAt(size_t index) const; - - std::string templateName() const; - - ObjectWithDict construct() const; - - void destruct(void* address, bool dealloc = true) const; - - void const* pointerToBaseType(void const* ptr, TypeWithDict const& derivedType) const; - - void const* pointerToContainedType(void const* ptr, TypeWithDict const& derivedType) const; - - template - void invokeByName(T& obj, std::string const& name) const { - //Reflex::Member theFunction = type_.FunctionMemberByName(name); - //theFunction.Invoke(obj); - } - -#ifndef __GCCXML__ - explicit operator bool() const; -#endif - - std::type_info const& typeInfo() const; - - std::type_info const& id() const; - - MemberWithDict dataMemberByName(std::string const& member) const; - - FunctionWithDict functionMemberByName(std::string const& member) const; - - //FunctionWithDict functionMemberByName(std::string const& member, TypeWithDict const& signature, int mods, TypeMemberQuery memberQuery) const; - - size_t dataMemberSize() const; - - size_t functionMemberSize() const; - - int stringToEnumValue(std::string const& enumMemberName) const; - - size_t size() const; - - void* allocate() const { - return new char[size()]; - } - - void deallocate(void * obj) const { - delete [] static_cast(obj); - } - - private: - friend class BaseWithDict; - friend class FunctionWithDict; - friend class MemberWithDict; - friend class ObjectWithDict; - friend class TypeBases; - friend class TypeDataMembers; - friend class TypeFunctionMembers; - - void setProperty(); - - std::type_info const* typeInfo_; - Reflex::Type* type_; // Ignore leak, as this goes away aith Reflex - TClass* class_; - TDataType* dataType_; - Long_t property_; - }; - - inline bool operator<(TypeWithDict const& a, TypeWithDict const& b) { - return a.typeInfo().before(b.typeInfo()); - } - - bool operator==(TypeWithDict const& a, TypeWithDict const& b); - - inline bool operator!=(TypeWithDict const& a, TypeWithDict const& b) { - return !(a == b); - } - - std::ostream& operator<<(std::ostream& os, TypeWithDict const& id); - - class TypeBases { - public: - explicit TypeBases(TypeWithDict const& type) : type_(*type.type_), class_(type.class_) {} - IterWithDict begin() const; - IterWithDict end() const; - size_t size() const; - private: - Reflex::Type const& type_; - TClass* class_; - }; +class FunctionWithDict; +class MemberWithDict; +class ObjectWithDict; + +class TypeBases; +class TypeDataMembers; +class TypeFunctionMembers; + +enum TypeMemberQuery { + //InheritedDefault = Reflex::INHERITEDMEMBERS_DEFAULT, + //InheritedNo = Reflex::INHERITEDMEMBERS_NO, + //InheritedAlso = Reflex::INHERITEDMEMBERS_ALSO +}; + +class TypeWithDict { + friend class TypeBases; + friend class TypeDataMembers; + friend class TypeFunctionMembers; +private: + const std::type_info* ti_; + TType* type_; + TClass* class_; + TEnum* enum_; + TDataType* dataType_; + long property_; +private: + void setProperty(); +public: + static TypeWithDict byName(std::string const& name, long property = 0L); +public: + TypeWithDict(); + TypeWithDict& operator=(const TypeWithDict&); + TypeWithDict(const TypeWithDict&); + // This copy constructor is for clearing const and reference. + explicit TypeWithDict(const TypeWithDict&, long property); + explicit TypeWithDict(const std::type_info&, long property = 0L); + explicit TypeWithDict(TClass* type, long property = 0L); + explicit TypeWithDict(TMethodArg* arg, long property = 0L); + explicit TypeWithDict(TType* type, long property = 0L); + //template TypeWithDict() : TypeWithDict(typeid(T)) {} + explicit operator bool() const; + bool hasDictionary() const; + std::type_info const& typeInfo() const; + std::type_info const& id() const; + TType* getType() const; + TClass* getClass() const; + TEnum* getEnum() const; + TDataType* getDataType() const; + long getProperty() const; + bool isClass() const; + bool isConst() const; + bool isEnum() const; + bool isFundamental() const; + bool isPointer() const; + bool isReference() const; + bool isTemplateInstance() const; + bool isTypedef() const; + bool isVirtual() const; + std::string qualifiedName() const; + std::string unscopedName() const; + std::string name() const; + std::string userClassName() const; + std::string friendlyClassName() const; + std::string templateName() const; + size_t size() const; + size_t dataMemberSize() const; + size_t functionMemberSize() const; + MemberWithDict dataMemberByName(const std::string&) const; + // Note: Used only by FWCore/Modules/src/EventContentAnalyzer.cc + FunctionWithDict functionMemberByName(const std::string&) const; + // Note: Used only by Fireworks/Core/src/FWModelContextMenuHandler.cc:262 + //FunctionWithDict functionMemberByName(const std::string& name, const TypeWithDict& signature, int mods, TypeMemberQuery memberQuery) const; + TypeWithDict nestedType(char const*) const; + TypeWithDict nestedType(const std::string&) const; + TypeWithDict toType() const; + void print(std::ostream& os) const; + bool hasBase(const std::string&) const; + bool hasBase(const TypeWithDict& basety) const; + int getBaseClassOffset(const TypeWithDict& baseClass) const; + TypeWithDict templateArgumentAt(size_t index) const; + const void* pointerToBaseType(const void* ptr, const TypeWithDict& derivedType) const; + const void* pointerToContainedType(const void* ptr, const TypeWithDict& derivedType) const; + int stringToEnumValue(const std::string&) const; + void* allocate() const; + void deallocate(void* address) const; + ObjectWithDict construct() const; + void destruct(void* address, bool dealloc = true) const; +}; + +inline bool operator<(const TypeWithDict& a, const TypeWithDict& b) +{ + return a.typeInfo().before(b.typeInfo()); +} - class TypeDataMembers { - public: - explicit TypeDataMembers(TypeWithDict const& type) : type_(*type.type_), class_(type.class_) {} - IterWithDict begin() const; - IterWithDict end() const; - size_t size() const; - private: - Reflex::Type const& type_; - TClass* class_; - }; +bool operator==(const TypeWithDict& a, const TypeWithDict& b); - class TypeFunctionMembers { - public: - explicit TypeFunctionMembers(TypeWithDict const& type) : type_(*type.type_), class_(type.class_) {} -/* - IterWithDict begin() const; - IterWithDict end() const; -*/ - //Reflex::Member_Iterator begin() const; - //Reflex::Member_Iterator end() const; - size_t size() const; - private: - Reflex::Type const& type_; - TClass* class_; - }; +inline bool operator!=(const TypeWithDict& a, const TypeWithDict& b) +{ + return !(a == b); } -#endif + +std::ostream& operator<<(std::ostream& os, const TypeWithDict& id); + +class TypeBases { +private: + TType* type_; + TClass* class_; +public: + explicit TypeBases(const TypeWithDict&); + IterWithDict begin() const; + IterWithDict end() const; + size_t size() const; +}; + +class TypeDataMembers { +private: + TType* type_; + TClass* class_; +public: + explicit TypeDataMembers(const TypeWithDict&); + IterWithDict begin() const; + IterWithDict end() const; + size_t size() const; +}; + +class TypeFunctionMembers { +private: + TType* type_; + TClass* class_; +public: + explicit TypeFunctionMembers(const TypeWithDict&); + IterWithDict begin() const; + IterWithDict end() const; + size_t size() const; +}; + +} // namespace edm + +#include "FWCore/Utilities/interface/FunctionWithDict.h" +#include "FWCore/Utilities/interface/MemberWithDict.h" +#include "FWCore/Utilities/interface/ObjectWithDict.h" + +#endif // FWCore_Utilities_TypeWithDict_h diff --git a/FWCore/Utilities/src/BaseWithDict.cc b/FWCore/Utilities/src/BaseWithDict.cc index e430eafe73be6..7c6d8dfa29ad8 100644 --- a/FWCore/Utilities/src/BaseWithDict.cc +++ b/FWCore/Utilities/src/BaseWithDict.cc @@ -1,28 +1,43 @@ - #include "FWCore/Utilities/interface/BaseWithDict.h" + #include "FWCore/Utilities/interface/TypeWithDict.h" #include "TBaseClass.h" namespace edm { - BaseWithDict::BaseWithDict() : baseClass_(nullptr) { - } - - BaseWithDict::BaseWithDict(TBaseClass* baseClass) : baseClass_(baseClass) { - } - - TypeWithDict - BaseWithDict::typeOf() const { - return TypeWithDict(baseClass_->GetClassPointer(), baseClass_->Property()); - } - - std::string - BaseWithDict::name() const { - return baseClass_->GetName(); - } - - bool - BaseWithDict::isPublic() const { - return (baseClass_->Property() & kIsPublic); - } + +BaseWithDict:: +BaseWithDict() + : baseClass_(nullptr) +{ +} + +BaseWithDict:: +BaseWithDict(TBaseClass* baseClass) + : baseClass_(baseClass) +{ +} + +bool +BaseWithDict:: +isPublic() const +{ + return baseClass_->Property() & kIsPublic; } + +std::string +BaseWithDict:: +name() const +{ + return baseClass_->GetName(); +} + +TypeWithDict +BaseWithDict:: +typeOf() const +{ + return TypeWithDict(baseClass_->GetClassPointer(), baseClass_->Property()); +} + +} // namespace edm + diff --git a/FWCore/Utilities/src/DictionaryTools.cc b/FWCore/Utilities/src/DictionaryTools.cc index 2fea72aed9c9a..3a40f90208b5f 100644 --- a/FWCore/Utilities/src/DictionaryTools.cc +++ b/FWCore/Utilities/src/DictionaryTools.cc @@ -1,10 +1,12 @@ #include "FWCore/Utilities/interface/DictionaryTools.h" + #include "FWCore/Utilities/interface/Algorithms.h" -#include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/Utilities/interface/BaseWithDict.h" +#include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/Utilities/interface/MemberWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" +#include "TInterpreter.h" #include "TROOT.h" #include "boost/algorithm/string.hpp" @@ -12,182 +14,218 @@ #include #include +#include namespace edm { - std::string const& dictionaryPlugInPrefix() { - static std::string const prefix("LCGReflex/"); - return prefix; - } - - static StringSet foundTypes_; - static StringSet missingTypes_; +const std::string& +dictionaryPlugInPrefix() +{ + static std::string const prefix("LCGReflex/"); + return prefix; +} - bool - find_nested_type_named(std::string const& nested_type, - TypeWithDict const& typeToSearch, - TypeWithDict& found_type) { - // Look for a sub-type named 'nested_type' - TypeWithDict foundType = typeToSearch.nestedType(nested_type); - if(bool(foundType)) { - found_type = foundType; - return true; - } +static StringSet foundTypes_; +static StringSet missingTypes_; + +bool +find_nested_type_named(const std::string& nested_type, + const TypeWithDict& typeToSearch, + TypeWithDict& found_type) +{ + // Look for a sub-type named 'nested_type' + TypeWithDict ty = typeToSearch.nestedType(nested_type); + if (!bool(ty)) { + found_type = TypeWithDict(); return false; } + found_type = ty; + return true; +} - bool - is_RefVector(TypeWithDict const& possibleRefVector, - TypeWithDict& value_type) { - - static std::string const template_name("edm::RefVector"); - static std::string const member_type("member_type"); - if(template_name == possibleRefVector.templateName()) { - return find_nested_type_named(member_type, possibleRefVector, value_type); - } +bool +is_RefVector(const TypeWithDict& possibleRefVector, + TypeWithDict& value_type) +{ + static const std::string template_name("edm::RefVector"); + static const std::string member_type("member_type"); + if (possibleRefVector.templateName() != template_name) { + value_type = TypeWithDict(); return false; } + return find_nested_type_named(member_type, possibleRefVector, value_type); +} - bool - is_PtrVector(TypeWithDict const& possibleRefVector, - TypeWithDict& value_type) { - - static std::string const template_name("edm::PtrVector"); - static std::string const member_type("member_type"); - static std::string const val_type("value_type"); - if(template_name == possibleRefVector.templateName()) { - TypeWithDict ptrType; - if(find_nested_type_named(val_type, possibleRefVector, ptrType)) { - return find_nested_type_named(val_type, ptrType, value_type); - } - } +bool +is_PtrVector(TypeWithDict const& possibleRefVector, + TypeWithDict& value_type) +{ + static const std::string template_name("edm::PtrVector"); + static const std::string member_type("member_type"); + static const std::string val_type("value_type"); + if (possibleRefVector.templateName() != template_name) { + value_type = TypeWithDict(); return false; } + TypeWithDict ptrType; + // FIXME: Is this right? + if (find_nested_type_named(val_type, possibleRefVector, ptrType)) { + return find_nested_type_named(val_type, ptrType, value_type); + } + return false; +} - bool - is_RefToBaseVector(TypeWithDict const& possibleRefVector, - TypeWithDict& value_type) { - - static std::string const template_name("edm::RefToBaseVector"); - static std::string const member_type("member_type"); - if(template_name == possibleRefVector.templateName()) { - return find_nested_type_named(member_type, possibleRefVector, value_type); - } +bool +is_RefToBaseVector(const TypeWithDict& possibleRefVector, + TypeWithDict& value_type) +{ + static const std::string template_name("edm::RefToBaseVector"); + static const std::string member_type("member_type"); + if (possibleRefVector.templateName() != template_name) { + value_type = TypeWithDict(); return false; } + return find_nested_type_named(member_type, possibleRefVector, value_type); +} - namespace { - - int const oneParamArraySize = 6; - std::string const oneParam[oneParamArraySize] = { - "vector", - "basic_string", - "set", - "list", - "deque", - "multiset" - }; - int const twoParamArraySize = 3; - std::string const twoParam[twoParamArraySize] = { - "map", - "pair", - "multimap" - }; - - // Checks if there is a dictionary for the Type t. - // If noComponents is false, checks members and base classes recursively. - // If noComponents is true, checks Type t only. - void - checkType(TypeWithDict t, bool noComponents = false) { - - // ToType strips const, volatile, array, pointer, reference, etc., - // and also translates typedefs. - // To be safe, we do this recursively until we either get a void type or the same type. - for(TypeWithDict x(t.toType()); x != t && x.typeInfo() != typeid(void); t = x, x = t.toType()) {} - - std::string name(t.name()); - boost::trim(name); +static int const oneParamArraySize = 6; +std::string const oneParam[oneParamArraySize] = { + "vector", + "basic_string", + "set", + "list", + "deque", + "multiset" +}; + +static int const twoParamArraySize = 3; + +static std::string const twoParam[twoParamArraySize] = { + "map", + "pair", + "multimap" +}; + +static +bool +hasCintDictionary(const std::string& name) +{ + ClassInfo_t* ci = gInterpreter->ClassInfo_Factory(name.c_str()); + return gInterpreter->ClassInfo_IsValid(ci); +} - if(foundTypes().end() != foundTypes().find(name) || missingTypes().end() != missingTypes().find(name)) { - // Already been processed. Prevents infinite loop. - return; +// Checks if there is a dictionary for the Type t. +// If noComponents is false, checks members and base classes recursively. +// If noComponents is true, checks Type t only. +static +void +checkType(TypeWithDict t, bool noComponents = false) +{ + // ToType strips const, volatile, array, pointer, reference, etc., + // and also translates typedefs. + // To be safe, we do this recursively until we either get a void type or the same type. + for (TypeWithDict x(t.toType()); x != t && + x.typeInfo() != typeid(void); t = x, x = t.toType()) {} + std::string name(t.name()); + boost::trim(name); + if (foundTypes().end() != foundTypes().find(name) || + missingTypes().end() != missingTypes().find(name)) { + // Already been processed. Prevents infinite loop. + return; + } + if (name.empty() || t.isFundamental() || t.isEnum() || + t.typeInfo() == typeid(void)) { + foundTypes().insert(name); + return; + } + if (!bool(t)) { + if (hasCintDictionary(name)) { + foundTypes().insert(name); + } + else { + missingTypes().insert(name); + } + return; + } + foundTypes().insert(name); + if (noComponents) { + return; + } + if (name.find("std::") == 0) { + if (t.isTemplateInstance()) { + std::string::size_type n = name.find('<'); + int cnt = 0; + if (std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, + n - 5)) != (oneParam + oneParamArraySize)) { + cnt = 1; } - - if(name.empty() || t.isFundamental() || t.isEnum() || t.typeInfo() == typeid(void)) { - foundTypes().insert(name); - return; + else if (std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, + n - 5)) != (twoParam + twoParamArraySize)) { + cnt = 2; } - - if(!bool(t)) { - missingTypes().insert(name); - return; + for (int i = 0; i < cnt; ++i) { + checkType(t.templateArgumentAt(i)); } - - foundTypes().insert(name); - if(noComponents) return; - - if(name.find("std::") == 0) { - if(t.isTemplateInstance()) { - std::string::size_type n = name.find('<'); - int cnt = 0; - if(std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) { - cnt = 1; - } else if(std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) { - cnt = 2; - } - for(int i = 0; i < cnt; ++i) { - checkType(t.templateArgumentAt(i)); - } - } - } else { - TypeDataMembers members(t); - for(auto const& member : members) { - MemberWithDict m(member); - if(!m.isTransient() && !m.isStatic()) { - checkType(m.typeOf()); - } - } - TypeBases bases(t); - for(auto const& base : bases) { - BaseWithDict b(base); - checkType(b.typeOf()); - } + } + } + else { + TypeDataMembers members(t); + for (auto const & m : members) { + MemberWithDict M(m); + if (!M.isTransient() && !M.isStatic()) { + checkType(M.typeOf()); } } - } // end unnamed namespace - - StringSet& missingTypes() { - return missingTypes_; + TypeBases bases(t); + for (auto const & b : bases) { + BaseWithDict B(b); + checkType(B.typeOf()); + } } +} - StringSet& foundTypes() { - // The only purpose of this cache is to stop infinite recursion. - // ROOT maintains its own internal cache. - return foundTypes_; - } +StringSet& +missingTypes() +{ + return missingTypes_; +} - void checkDictionaries(std::string const& name, bool noComponents) { - TypeWithDict null; - TypeWithDict t(TypeWithDict::byName(name)); - if(t == null) { - if(name == std::string("void")) { - foundTypes().insert(name); - } else { - missingTypes().insert(name); - } - return; - } - checkType(t, noComponents); +StringSet& + foundTypes() +{ + // The only purpose of this cache is to stop infinite recursion. + // ROOT maintains its own internal cache. + return foundTypes_; +} + +void +checkDictionaries(std::string const& name, bool noComponents) +{ + TypeWithDict null; + TypeWithDict t(TypeWithDict::byName(name)); + if (!bool(t)) { + //if (name == std::string("void")) { + // foundTypes().insert(name); + //} + //else { + missingTypes().insert(name); + //} + return; } + checkType(t, noComponents); +} - void throwMissingDictionariesException() { - if(!missingTypes().empty()) { - std::ostringstream ostr; - for (StringSet::const_iterator it = missingTypes().begin(), itEnd = missingTypes().end(); - it != itEnd; ++it) { - ostr << *it << "\n\n"; - } - throw Exception(errors::DictionaryNotFound) +void +throwMissingDictionariesException() +{ + if (!missingTypes().empty()) { + std::ostringstream ostr; + for (StringSet::const_iterator it = missingTypes().begin(), + itEnd = missingTypes().end(); + it != itEnd; ++it) { + ostr << *it << "\n\n"; + } + throw Exception(errors::DictionaryNotFound) << "No REFLEX data dictionary found for the following classes:\n\n" << ostr.str() << "Most likely each dictionary was never generated,\n" @@ -199,80 +237,84 @@ namespace edm { << "to define a dummy variable of this type in classes.h.\n" << "Also, if this class has any transient members,\n" << "you need to specify them in classes_def.xml."; - } } +} - void loadMissingDictionaries() { - while (!missingTypes().empty()) { - StringSet missing(missingTypes()); - for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end(); +void +loadMissingDictionaries() +{ + while (!missingTypes().empty()) { + StringSet missing(missingTypes()); + for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end(); it != itEnd; ++it) { - try { - gROOT->GetClass(it->c_str(), kTRUE); - } - // We don't want to fail if we can't load a plug-in. - catch(...) {} + try { + gROOT->GetClass(it->c_str(), kTRUE); } - missingTypes().clear(); - for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end(); + // We don't want to fail if we can't load a plug-in. + catch (...) {} + } + missingTypes().clear(); + for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end(); it != itEnd; ++it) { - checkDictionaries(*it); - } - if (missingTypes() == missing) { - break; - } + checkDictionaries(*it); } - if (missingTypes().empty()) { - return; + if (missingTypes() == missing) { + break; } - throwMissingDictionariesException(); } + if (missingTypes().empty()) { + return; + } + throwMissingDictionariesException(); +} - void public_base_classes(TypeWithDict const& typeID, - std::vector& baseTypes) { - - TypeWithDict type(typeID.typeInfo()); - if(type.isClass()) { - - TypeBases bases(type); - for(auto const& basex : bases) { - BaseWithDict base(basex); - if(base.isPublic()) { - - TypeWithDict baseRflxType = base.typeOf(); - if(bool(baseRflxType)) { - TypeWithDict baseType(baseRflxType.typeInfo()); - - // Check to make sure this base appears only once in the - // inheritance heirarchy. - if(!search_all(baseTypes, baseType)) { - // Save the type and recursive look for its base types - baseTypes.push_back(baseType); - public_base_classes(baseType, baseTypes); - } - // For now just ignore it if the class appears twice, - // After some more testing we may decide to uncomment the following - // exception. - /* - else { - throw Exception(errors::UnimplementedFeature) - << "DataFormats/Common/src/DictionaryTools.cc in function public_base_classes.\n" - << "Encountered class that has a public base class that appears\n" - << "multiple times in its inheritance heirarchy.\n" - << "Please contact the EDM Framework group with details about\n" - << "this exception. It was our hope that this complicated situation\n" - << "would not occur. There are three possible solutions. 1. Change\n" - << "the class design so the public base class does not appear multiple\n" - << "times in the inheritance heirarchy. In many cases, this is a\n" - << "sign of bad design. 2. Modify the code that supports Views to\n" - << "ignore these base classes, but not supply support for creating a\n" - << "View of this base class. 3. Improve the View infrastructure to\n" - << "deal with this case. Class name of base class: " << baseType.Name() << "\n\n"; - } - */ - } - } - } +void +public_base_classes(const TypeWithDict& typeID, + std::vector& baseTypes) +{ + TypeWithDict type(typeID.typeInfo()); + if (!type.isClass()) { + return; + } + TypeBases bases(type); + for (auto const & basex : bases) { + BaseWithDict base(basex); + if (!base.isPublic()) { + continue; } + TypeWithDict baseRflxType = base.typeOf(); + if (!bool(baseRflxType)) { + continue; + } + TypeWithDict baseType(baseRflxType.typeInfo()); + // Check to make sure this base appears only once in the + // inheritance heirarchy. + if (!search_all(baseTypes, baseType)) { + // Save the type and recursive look for its base types + baseTypes.push_back(baseType); + public_base_classes(baseType, baseTypes); + } + // For now just ignore it if the class appears twice, + // After some more testing we may decide to uncomment the following + // exception. + // + //else { + // throw Exception(errors::UnimplementedFeature) + // << "DataFormats/Common/src/DictionaryTools.cc in function public_base_classes.\n" + // << "Encountered class that has a public base class that appears\n" + // << "multiple times in its inheritance heirarchy.\n" + // << "Please contact the EDM Framework group with details about\n" + // << "this exception. It was our hope that this complicated situation\n" + // << "would not occur. There are three possible solutions. 1. Change\n" + // << "the class design so the public base class does not appear multiple\n" + // << "times in the inheritance heirarchy. In many cases, this is a\n" + // << "sign of bad design. 2. Modify the code that supports Views to\n" + // << "ignore these base classes, but not supply support for creating a\n" + // << "View of this base class. 3. Improve the View infrastructure to\n" + // << "deal with this case. Class name of base class: " << baseType.Name() << "\n\n"; + //} } } + +} // namespace edm + diff --git a/FWCore/Utilities/src/FunctionWithDict.cc b/FWCore/Utilities/src/FunctionWithDict.cc index 71edfe3ba5f2b..1a3a201713bd9 100644 --- a/FWCore/Utilities/src/FunctionWithDict.cc +++ b/FWCore/Utilities/src/FunctionWithDict.cc @@ -1,120 +1,182 @@ - -//#include "Reflex/Object.h" -//#include "Reflex/Member.h" -//#include "Reflex/Type.h" - #include "FWCore/Utilities/interface/FunctionWithDict.h" + +#include "FWCore/Utilities/interface/IterWithDict.h" #include "FWCore/Utilities/interface/ObjectWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" -namespace edm { +#include "TInterpreter.h" +#include "TMethod.h" +#include "TMethodArg.h" - FunctionWithDict::FunctionWithDict(){} +namespace edm { - FunctionWithDict::FunctionWithDict(Reflex::Member const& func) {} +FunctionWithDict:: +FunctionWithDict() + : function_(nullptr) +{ +} - Reflex::Member const& - FunctionWithDict::function() const { - return *function_; - } +FunctionWithDict:: +FunctionWithDict(TMethod* meth) + : function_(meth) +{ +} - std::string - FunctionWithDict::name() const { - //return function().Name(); - return std::string(); +FunctionWithDict:: +operator bool() const +{ + if (function_ == nullptr) { + return false; } + return function_->IsValid(); +} - std::string - FunctionWithDict::typeName() const { - //return function().TypeOf().Name(); - return std::string(); - } +std::string +FunctionWithDict:: +name() const +{ + return function_->GetName(); +} - TypeWithDict - FunctionWithDict::typeOf() const { - //return (TypeWithDict(function().TypeOf())); - return (TypeWithDict()); - } +std::string +FunctionWithDict:: +typeName() const +{ + return function_->GetReturnTypeName(); +} - TypeWithDict - FunctionWithDict::returnType() const { - //return (TypeWithDict(function().TypeOf().ReturnType())); - return (TypeWithDict()); - } +TypeWithDict +FunctionWithDict:: +typeOf() const +{ + return TypeWithDict::byName(function_->GetReturnTypeName()); +} - TypeWithDict - FunctionWithDict::finalReturnType() const { - //return (TypeWithDict(function().TypeOf().ReturnType().FinalType())); - return (TypeWithDict()); - } +TypeWithDict +FunctionWithDict:: +returnType() const +{ + return TypeWithDict::byName(function_->GetReturnTypeName()); +} - TypeWithDict - FunctionWithDict::declaringType() const { - //return (TypeWithDict(function().DeclaringType())); - return (TypeWithDict()); - } +TypeWithDict +FunctionWithDict:: +finalReturnType() const +{ + return TypeWithDict::byName(function_->GetReturnTypeNormalizedName()); +} - bool - FunctionWithDict::isConst() const { - //return function().IsConst(); - return false; - } +TypeWithDict +FunctionWithDict:: +declaringType() const +{ + return TypeWithDict(function_->GetClass()); +} - bool - FunctionWithDict::isConstructor() const { - //return function().IsConstructor(); - return false; - } +bool +FunctionWithDict:: +isConst() const +{ + return function_->Property() & kIsConstMethod; +} - bool - FunctionWithDict::isDestructor() const { - //return function().IsDestructor(); - return false; - } +bool +FunctionWithDict:: +isConstructor() const +{ + return function_->ExtraProperty() & kIsConstructor; +} - bool - FunctionWithDict::isOperator() const { - //return function().IsOperator(); - return false; - } +bool +FunctionWithDict:: +isDestructor() const +{ + return function_->ExtraProperty() & kIsDestructor; +} - bool - FunctionWithDict::isPublic() const { - //return function().IsPublic(); - return false; - } +bool +FunctionWithDict:: +isOperator() const +{ + return function_->ExtraProperty() & kIsOperator; +} - bool FunctionWithDict::isStatic() const { - //return function().IsStatic(); - return false; - } +bool +FunctionWithDict:: +isPublic() const +{ + return function_->Property() & kIsPublic; +} - size_t - FunctionWithDict::functionParameterSize(bool required) const { - //return function().FunctionParameterSize(required); - return 0U; - } +bool FunctionWithDict:: +isStatic() const +{ + return function_->Property() & kIsStatic; +} - void - FunctionWithDict::invoke(ObjectWithDict const& obj, ObjectWithDict* ret, std::vector const& values) const { - //Reflex::Object reflexReturn(ret->typeOf().type_, ret->address()); - //function().Invoke(Reflex::Object(obj.typeOf().type_, obj.address()), &reflexReturn, values); +size_t +FunctionWithDict:: +functionParameterSize(bool required/*= false*/) const +{ + if (required) { + return function_->GetNargs() - function_->GetNargsOpt(); } + return function_->GetNargs(); +} -/* - Reflex::Type_Iterator - FunctionWithDict::begin() const { - return function().TypeOf().FunctionParameter_Begin(); - } +size_t +FunctionWithDict:: +size() const +{ + return function_->GetNargs(); +} - Reflex::Type_Iterator - FunctionWithDict::end() const { - return function().TypeOf().FunctionParameter_End(); - } -*/ +/// Call a member function. +void +FunctionWithDict:: +invoke(const ObjectWithDict& obj, ObjectWithDict* ret/*=nullptr*/, + const std::vector& values/*=std::vector()*/) const +{ + //Reflex::Object reflexReturn(ret->typeOf().type_, ret->address()); + //function_.Invoke(Reflex::Object(obj.typeOf().type_, obj.address()), &reflexReturn, values); + if (ret == nullptr) { + gInterpreter->ExecuteWithArgsAndReturn(function_, obj.address(), values, 0); + return; + } + gInterpreter->ExecuteWithArgsAndReturn(function_, obj.address(), values, ret->address()); +} + +/// Call a static function. +void +FunctionWithDict:: +invoke(ObjectWithDict* ret/*=nullptr*/, + const std::vector& values/*=std::vector()*/) const +{ + //Reflex::Object reflexReturn(ret->typeOf().type_, ret->address()); + //function_.Invoke(obj.address()), &reflexReturn, values); + if (ret == nullptr) { + gInterpreter->ExecuteWithArgsAndReturn(function_, 0, values, 0); + return; + } + gInterpreter->ExecuteWithArgsAndReturn(function_, 0, values, ret->address()); +} - FunctionWithDict::operator bool() const { - return false; +IterWithDict +FunctionWithDict:: +begin() const +{ + if (function_ == nullptr) { + return IterWithDict(); } + return IterWithDict(function_->GetListOfMethodArgs()); +} +IterWithDict +FunctionWithDict:: +end() const +{ + return IterWithDict(); } + +} // namespace edm + diff --git a/FWCore/Utilities/src/IterWithDict.cc b/FWCore/Utilities/src/IterWithDict.cc index 8ffb3829f776b..87928911bcb01 100644 --- a/FWCore/Utilities/src/IterWithDict.cc +++ b/FWCore/Utilities/src/IterWithDict.cc @@ -3,45 +3,67 @@ namespace edm { - IterWithDictBase::IterWithDictBase() : iter_(static_cast(nullptr)), atEnd_(true) { - // This ctor is used by the framework for the end of a range, - // or for any type that does not have a TClass. - // An iterator constructed by this ctor must not be used - // as the left hand argument of operator!=(). +void +IterWithDictBase:: +advance() +{ + if (atEnd_) { + return; } - - IterWithDictBase::IterWithDictBase(TList* list) : iter_(list), atEnd_(false) { - // With a TIter, you must call Next() once to point to the first element. - advance(); + TObject* obj = iter_.Next(); + if (obj == nullptr) { + atEnd_ = true; } +} - bool - IterWithDictBase::operator!=(IterWithDictBase const& other) const { - // The special cases are needed because TIter::operator!=() - // dereferences a null pointer (i.e. segfaults) if the left hand TIter - // was constucted with a nullptr argument (the first constructor above). - if(atEnd_ != other.atEnd_) { - // one iterator at end, but not both - return true; - } else if(atEnd_) { - // both iterators at end - return false; - } - // neither iterator at end - return iter() != other.iter(); - } +const TIter& +IterWithDictBase:: +iter() const +{ + return iter_; +} - void - IterWithDictBase::advance() { - if(!atEnd_) { - TObject* obj = iter_.Next(); - if(obj == nullptr) atEnd_ = true; - } - } +IterWithDictBase:: +IterWithDictBase() + : iter_(static_cast(nullptr)) + , atEnd_(true) +{ + // This ctor is used by the framework for the end of a range, + // or for any type that does not have a TClass. + // An iterator constructed by this ctor must not be used + // as the left hand argument of operator!=(). +} - TIter const& - IterWithDictBase::iter() const { - return iter_; +IterWithDictBase:: +IterWithDictBase(TList* list) + : iter_(list) + , atEnd_(false) +{ + // With a TIter, you must call Next() once to point to the first element. + TObject* obj = iter_.Next(); + if (obj == nullptr) { + atEnd_ = true; } +} +bool +IterWithDictBase:: +operator!=(const IterWithDictBase& rhs) const +{ + // The special cases are needed because TIter::operator!=() + // dereferences a null pointer (i.e. segfaults) if the left hand TIter + // was constucted with a nullptr argument (the first constructor above). + if (atEnd_ != rhs.atEnd_) { + // one iterator at end, but not both + return true; + } + if (atEnd_) { + // both iterators at end + return false; + } + // neither iterator at end + return iter_ != rhs.iter_; } + +} // namespace edm + diff --git a/FWCore/Utilities/src/MemberWithDict.cc b/FWCore/Utilities/src/MemberWithDict.cc index 2dd8da4ab9155..c9fb386dbcf4b 100644 --- a/FWCore/Utilities/src/MemberWithDict.cc +++ b/FWCore/Utilities/src/MemberWithDict.cc @@ -1,70 +1,95 @@ - #include "FWCore/Utilities/interface/MemberWithDict.h" + #include "FWCore/Utilities/interface/ObjectWithDict.h" #include "FWCore/Utilities/interface/TypeWithDict.h" namespace edm { - MemberWithDict::MemberWithDict() : - dataMember_() { - } - - MemberWithDict::MemberWithDict(TDataMember* dataMember) : - dataMember_(dataMember) { - } - - std::string - MemberWithDict::name() const { - return dataMember_->GetName(); - } - - ObjectWithDict - MemberWithDict::get() const { - return (ObjectWithDict(typeOf(), reinterpret_cast(dataMember_->GetOffset()))); - } - - ObjectWithDict - MemberWithDict::get(ObjectWithDict const& obj) const { - return (ObjectWithDict(typeOf(), static_cast(obj.address()) + dataMember_->GetOffset())); - } - - TypeWithDict - MemberWithDict::typeOf() const { - return TypeWithDict::byName(dataMember_->GetTypeName(), dataMember_->Property()); - } - - TypeWithDict - MemberWithDict::declaringType() const { - return TypeWithDict(dataMember_->GetClass(), dataMember_->Property()); - } - - bool - MemberWithDict::isConst() const { - return (dataMember_->Property() & kIsConstant); - } - - bool - MemberWithDict::isPublic() const { - return (dataMember_->Property() & kIsPublic); - } - - bool - MemberWithDict::isStatic() const { - return (dataMember_->Property() & kIsStatic); - } - - bool - MemberWithDict::isTransient() const { - return !dataMember_->IsPersistent(); - } - - size_t - MemberWithDict::offset() const { - return (dataMember_->GetOffset()); - } - - MemberWithDict::operator bool() const { - return (dataMember_ != nullptr); - } +MemberWithDict::MemberWithDict() + : dataMember_() +{ +} + +MemberWithDict::MemberWithDict(TDataMember* dataMember) + : dataMember_(dataMember) +{ +} + +MemberWithDict:: +operator bool() const +{ + return dataMember_ != nullptr; +} + +std::string +MemberWithDict:: +name() const +{ + return dataMember_->GetName(); +} + +TypeWithDict +MemberWithDict:: +typeOf() const +{ + return TypeWithDict::byName(dataMember_->GetTypeName(), dataMember_->Property()); +} +TypeWithDict +MemberWithDict:: +declaringType() const +{ + return TypeWithDict(dataMember_->GetClass(), dataMember_->Property()); } + +bool +MemberWithDict:: +isConst() const +{ + return dataMember_->Property() & kIsConstant; +} + +bool +MemberWithDict:: +isPublic() const +{ + return dataMember_->Property() & kIsPublic; +} + +bool +MemberWithDict:: +isStatic() const +{ + return dataMember_->Property() & kIsStatic; +} + +bool +MemberWithDict:: +isTransient() const +{ + return !dataMember_->IsPersistent(); +} + +size_t +MemberWithDict:: +offset() const +{ + return dataMember_->GetOffset(); +} + +ObjectWithDict +MemberWithDict:: +get() const +{ + return ObjectWithDict(typeOf(), reinterpret_cast(dataMember_->GetOffset())); +} + +ObjectWithDict +MemberWithDict:: +get(ObjectWithDict const& obj) const +{ + return ObjectWithDict(typeOf(), reinterpret_cast(obj.address()) + dataMember_->GetOffset()); +} + +} // namespace edm + diff --git a/FWCore/Utilities/src/ObjectWithDict.cc b/FWCore/Utilities/src/ObjectWithDict.cc index 95f0b83771668..1407df066502c 100644 --- a/FWCore/Utilities/src/ObjectWithDict.cc +++ b/FWCore/Utilities/src/ObjectWithDict.cc @@ -1,54 +1,117 @@ -#include "FWCore/Utilities/interface/MemberWithDict.h" #include "FWCore/Utilities/interface/ObjectWithDict.h" +#include "FWCore/Utilities/interface/MemberWithDict.h" +#include "FWCore/Utilities/interface/TypeWithDict.h" + namespace edm { - ObjectWithDict::ObjectWithDict() : - type_(), - address_(nullptr) { - } +ObjectWithDict +ObjectWithDict:: +byType(const TypeWithDict& type) +{ + ObjectWithDict obj(type.construct()); + return obj; +} - ObjectWithDict - ObjectWithDict::byType(TypeWithDict const& type) { - ObjectWithDict obj(type.construct()); - return obj; - } +ObjectWithDict:: +ObjectWithDict() + : type_(nullptr) + , address_(nullptr) +{ +} - ObjectWithDict::ObjectWithDict(TypeWithDict const& type, void* address) : - type_(type), - address_(address) { - } +ObjectWithDict:: +ObjectWithDict(const TypeWithDict& type, void* address) + : type_(gInterpreter->Type_Factory(type.typeInfo())) + , address_(address) +{ +} - ObjectWithDict::ObjectWithDict(std::type_info const& typeID, void* address) : - type_(TypeWithDict(typeID)), - address_(address) { - } +ObjectWithDict::ObjectWithDict(const std::type_info& ti, void* address) + : type_(gInterpreter->Type_Factory(ti)) + , address_(address) +{ +} - TypeWithDict const& - ObjectWithDict::typeOf() const { - return type_; - } +ObjectWithDict:: +operator bool() const +{ + return gInterpreter->Type_Bool(type_) && (address_ != nullptr); +} - TypeWithDict - ObjectWithDict::dynamicType() const { - if(!type_.isVirtual()) { - return type_; - } - struct Dummy_t {virtual ~Dummy_t() {} }; - return TypeWithDict(typeid(*(Dummy_t*)address_)); - } +void* +ObjectWithDict:: +address() const +{ + return address_; +} - ObjectWithDict::operator bool() const { - return bool(type_) && address_ != nullptr; - } +TypeWithDict +ObjectWithDict:: +typeOf() const +{ + return TypeWithDict(type_); +} + +class DummyVT { +public: + virtual ~DummyVT(); +}; - void* - ObjectWithDict::address() const { - return address_; +DummyVT:: +~DummyVT() +{ +} + +TypeWithDict +ObjectWithDict:: +dynamicType() const +{ + if (!gInterpreter->Type_IsVirtual(type_)) { + return TypeWithDict(type_); } + // Use a dirty trick, force the typeid() operator + // to consult the virtual table stored at address_. + return TypeWithDict(typeid(*(DummyVT*)address_)); +} - ObjectWithDict - ObjectWithDict::get(std::string const& memberName) const { - return type_.dataMemberByName(memberName).get(*this); +ObjectWithDict +ObjectWithDict:: +get(const std::string& memberName) const +{ + return TypeWithDict(type_).dataMemberByName(memberName).get(*this); +} + +//ObjectWithDict +//ObjectWithDict:: +//construct() const +//{ +// TypeWithDict ty(type_); +// TClass* cl = ty.getClass(); +// if (cl != nullptr) { +// return ObjectWithDict(ty, cl->New()); +// } +// return ObjectWithDict(ty, new char[ty.size()]); +//} + +void +ObjectWithDict:: +destruct(bool dealloc) const +{ + TypeWithDict ty(type_); + TClass* cl = ty.getClass(); + if (cl != nullptr) { + cl->Destructor(address_, !dealloc); + //if (dealloc) { + // address_ = nullptr; + //} + return; + } + if (dealloc) { + delete[] reinterpret_cast(address_); + //address_ = nullptr; } } + +} // namespace edm + diff --git a/FWCore/Utilities/src/TypeWithDict.cc b/FWCore/Utilities/src/TypeWithDict.cc index 2ec1ba09b1a36..80c5553a90a1e 100644 --- a/FWCore/Utilities/src/TypeWithDict.cc +++ b/FWCore/Utilities/src/TypeWithDict.cc @@ -1,559 +1,984 @@ -/*---------------------------------------------------------------------- -, Long_t property -----------------------------------------------------------------------*/ -#include -#include +#include "FWCore/Utilities/interface/TypeWithDict.h" + +#include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/FriendlyName.h" #include "FWCore/Utilities/interface/FunctionWithDict.h" #include "FWCore/Utilities/interface/MemberWithDict.h" #include "FWCore/Utilities/interface/ObjectWithDict.h" -#include "FWCore/Utilities/interface/FriendlyName.h" -#include "FWCore/Utilities/interface/Exception.h" #include "FWCore/Utilities/interface/TypeDemangler.h" #include "FWCore/Utilities/interface/TypeID.h" -#include "FWCore/Utilities/interface/TypeWithDict.h" -#include "TROOT.h" + #include "TClass.h" #include "TDataType.h" +#include "TEnum.h" +#include "TEnumConstant.h" +#include "TInterpreter.h" #include "TMethodArg.h" -//#include "Reflex/Member.h" -//#include "Reflex/Object.h" +#include "TROOT.h" + #include "boost/thread/tss.hpp" -namespace { - int - toReflex(Long_t property) { -/* - int prop = 0; - if(property&(Long_t)kIsConstant) { - prop |= Reflex::CONST; - } - if(property&(Long_t)kIsReference) { - prop |= Reflex::REFERENCE; - } - return prop; -*/ - return 0; - } -} +#include +#include +#include +#include +#include + +#include + +using namespace std; namespace edm { - void - TypeWithDict::setProperty() { -/* - if(type_.IsClass()) { - property_ |= (Long_t)kIsClass; - } - if(type_.IsConst()) { - property_ |= (Long_t)kIsConstant; - } - if(type_.IsEnum()) { - property_ |= (Long_t)kIsEnum; - } - if(type_.IsTypedef()) { - property_ |= (Long_t)kIsTypedef; - } - if(dataType_ != nullptr || *typeInfo_ == typeid(void)) { - property_ |= (Long_t)kIsFundamental; - } - if(type_.IsPointer()) { - property_ |= (Long_t)kIsPointer; - } - if(type_.IsReference()) { - property_ |= (Long_t)kIsReference; - } - if(type_.IsStruct()) { - property_ |= (Long_t)kIsStruct; - } - if(type_.IsVirtual()) { - property_ |= (Long_t)kIsVirtual; - } -*/ - } - - TypeWithDict::TypeWithDict() : - typeInfo_(&typeid(void)), - type_(), - class_(nullptr), - dataType_(nullptr), - property_(0L) { - } - - TypeWithDict::TypeWithDict(Reflex::Type const& type) : - typeInfo_(nullptr), - type_(), - class_(nullptr), - //dataType_(TDataType::GetDataType(TDataType::GetType(*typeInfo_))), - dataType_(nullptr), - property_(0L) { - setProperty(); - if(!isFundamental() && !isEnum()) { - class_ = TClass::GetClass(*typeInfo_); - } + +TypeWithDict +TypeWithDict:: +byName(string const& name, long property /*= 0L*/) +{ + // Note: The property flag should include kIsConstant and + // kIsReference if needed since a typeid() expression + // ignores those properties, so we must store them + // separately. + TType* type = gInterpreter->Type_Factory(name); + if (!gInterpreter->Type_IsValid(type)) { + return TypeWithDict(); } + return TypeWithDict(type, property); +} - TypeWithDict::TypeWithDict(std::type_info const& t) : - TypeWithDict{t, 0L} { +void +TypeWithDict:: +setProperty() +{ + // Note: typeid() ignores const and volatile qualifiers, and + // cannot see references. + // So: + // typeid(int) == typeid(const int) + // == typeid(int&) + // == typeid(const int&) + // + if (type_ == nullptr) { + return; + } + if (gInterpreter->Type_IsConst(type_)) { + // Note: This is not possible if created by typeid. + property_ |= (long) kIsConstant; + } + if (gInterpreter->Type_IsReference(type_)) { + // Note: This is not possible if created by typeid. + property_ |= (long) kIsReference; } +} - TypeWithDict::TypeWithDict(std::type_info const& t, Long_t property) : - typeInfo_(&t), - //type_(Reflex::Type::ByTypeInfo(t), toReflex(property)), - type_(), - class_(nullptr), - dataType_(TDataType::GetDataType(TDataType::GetType(t))), - property_(property) { - setProperty(); - if(!isFundamental() && !isEnum()) { - class_ = TClass::GetClass(*typeInfo_); - } +TypeWithDict:: +TypeWithDict() + : ti_(&typeid(void)) + , type_(nullptr) + , class_(nullptr) + , enum_(nullptr) + , dataType_(nullptr) + , property_(0L) +{ +} + +TypeWithDict:: +TypeWithDict(const TypeWithDict& rhs) + : ti_(rhs.ti_) + , type_(rhs.type_) + , class_(rhs.class_) + , enum_(rhs.enum_) + , dataType_(rhs.dataType_) + , property_(rhs.property_) +{ +} + +TypeWithDict:: +TypeWithDict(TypeWithDict const& type, long prop) + : ti_(type.ti_) + , type_(type.type_) + , class_(type.class_) + , enum_(type.enum_) + , dataType_(type.dataType_) + , property_(type.property_) +{ + // Unconditionally modifies const and reference + // properties, and only those properties. + property_ &= ~((long) kIsConstant | (long) kIsReference); + if (prop & kIsConstant) { + property_ |= kIsConstant; + } + if (prop & kIsReference) { + property_ |= kIsReference; } +} - TypeWithDict::TypeWithDict(TClass* cl, Long_t property) : - typeInfo_(cl->GetTypeInfo()), - type_(), - class_(cl), - dataType_(nullptr), - property_(property) { - property_ |= (Long_t)kIsClass; - } - - TypeWithDict::TypeWithDict(TMethodArg* arg) : - typeInfo_(nullptr), - type_(), - class_(nullptr), - dataType_(nullptr), - property_(arg->Property()) { - TypeWithDict type(byName(arg->GetTypeName(), arg->Property())); - *this = std::move(type); - } - - TypeWithDict::TypeWithDict(TypeWithDict const& type, Long_t property) : - // Only modifies const and reference. - typeInfo_(type.typeInfo_), - type_(), - class_(type.class_), - dataType_(type.dataType_), - property_(type.property_) { - if(property&(Long_t)kIsConstant) { - property_ |= (Long_t)kIsConstant; - } else { - property_ &= ~(Long_t)kIsConstant; +TypeWithDict& +TypeWithDict:: +operator=(const TypeWithDict& rhs) +{ + if (this != &rhs) { + ti_ = rhs.ti_; + type_ = rhs.type_; + class_ = rhs.class_; + enum_ = rhs.enum_; + dataType_ = rhs.dataType_; + property_ = rhs.property_; + } + return *this; +} + +TypeWithDict:: +TypeWithDict(const type_info& ti, long property /*= 0L*/) + : ti_(&ti) + , type_(nullptr) + , class_(nullptr) + , enum_(nullptr) + , dataType_(nullptr) + , property_(property) +{ + type_ = gInterpreter->Type_Factory(ti); + if (!gInterpreter->Type_TypeInfo(type_)) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(const type_info&, long): " + "Type_TypeInfo returns nullptr!\n"); + abort(); + } + dataType_ = TDataType::GetDataType(TDataType::GetType(ti)); + if (!gInterpreter->Type_IsFundamental(type_) && + !gInterpreter->Type_IsEnum(type_)) { + // Must be a class, struct, or union. + class_ = TClass::GetClass(ti); + } + if (gInterpreter->Type_IsEnum(type_)) { + // Get the containing class, if any. + TType* TTy = gInterpreter->Type_GetParent(type_); + if (TTy != nullptr) { + // The enum is a class member. + TypeWithDict Tycl(*gInterpreter->Type_TypeInfo(TTy)); + if (Tycl.class_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(const type_info&, long): " + "Enum parent is not a class!\n"); + abort(); } - if(property&(Long_t)kIsReference) { - property_ |= (Long_t)kIsReference; - } else { - property_ &= ~(Long_t)kIsReference; + TObject* tobj = + Tycl.class_->GetListOfEnums()->FindObject(name().c_str()); + if (tobj == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(const type_info&, long): " + "Enum not found in containing class!\n"); + abort(); } - } - - void - TypeWithDict::print(std::ostream& os) const { - try { - os << name(); - } catch (cms::Exception const& e) { - os << typeInfo().name(); + enum_ = reinterpret_cast(tobj); + } + else { + // Must be a namespace member. + TObject* tobj = gROOT->GetListOfEnums()->FindObject(name().c_str()); + if (tobj == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(const type_info&, long): " + "Enum not found in global namespace!\n"); + abort(); + } + enum_ = reinterpret_cast(tobj); + } + if (enum_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(const type_info&, long): " + "enum_ not set for enum type!\n"); + abort(); } } +} - TypeWithDict - TypeWithDict::byName(std::string const& name) { - return byName(name, 0L); - } - - TypeWithDict - TypeWithDict::byName(std::string const& name, Long_t property) { - // static map for built in types - typedef std::map TypeMap; - static const TypeMap typeMap = { - {std::string("bool"), TypeWithDict(typeid(bool))}, - {std::string("char"), TypeWithDict(typeid(char))}, - {std::string("unsigned char"), TypeWithDict(typeid(unsigned char))}, - {std::string("short"), TypeWithDict(typeid(short))}, - {std::string("unsigned short"), TypeWithDict(typeid(unsigned short))}, - {std::string("int"), TypeWithDict(typeid(int))}, - {std::string("unsigned int"), TypeWithDict(typeid(unsigned int))}, - {std::string("long"), TypeWithDict(typeid(long))}, - {std::string("unsigned long"), TypeWithDict(typeid(unsigned long))}, - {std::string("long long"), TypeWithDict(typeid(int))}, - {std::string("unsigned long long"), TypeWithDict(typeid(int))}, - {std::string("float"), TypeWithDict(typeid(float))}, - {std::string("double"), TypeWithDict(typeid(double))}, - // {std::string("long double"), TypeWithDict(typeid(long double))}, // ROOT does not seem to know about long double - {std::string("string"), TypeWithDict(typeid(std::string))}, - {std::string("void"), TypeWithDict(typeid(void))} - }; - - //std::string cintName = ROOT::Cintex::CintName(name); - std::string cintName = name; - char last = *cintName.rbegin(); - if(last == '*') { - cintName = cintName.substr(0, cintName.size() - 1); - } +TypeWithDict:: +TypeWithDict(TClass* cl, long property /*= 0L*/) + : ti_(&typeid(void)) + , type_(nullptr) + , class_(cl) + , enum_(nullptr) + , dataType_(nullptr) + , property_((long) kIsClass | property) +{ + type_ = gInterpreter->Type_Factory(*cl->GetTypeInfo()); +} - TypeMap::const_iterator it = typeMap.find(cintName); - if(it != typeMap.end()) { - return TypeWithDict(it->second, property); - } +TypeWithDict:: +TypeWithDict(TMethodArg* arg, long property /*= 0L*/) + : TypeWithDict(byName(arg->GetTypeName(), arg->Property() | property)) +{ +} - TClass* cl = TClass::GetClass(cintName.c_str()); - if(cl != nullptr) { - // it's a class - std::type_info const* typeInfo = cl->GetTypeInfo(); - if(typeInfo == nullptr) { - return TypeWithDict(); +TypeWithDict:: +TypeWithDict(TType* ttype, long property /*= 0L*/) + : ti_(&typeid(void)) + , type_(ttype) + , class_(nullptr) + , enum_(nullptr) + , dataType_(nullptr) + , property_(property) +{ + if (!ttype) { + return; + } + { + const type_info* info = gInterpreter->Type_TypeInfo(ttype); + if (!info) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(TType*, property): " + "Type_TypeInfo returns nullptr!\n"); + abort(); + } + ti_ = info; + } + if (gInterpreter->Type_IsConst(ttype)) { + // Note: This is not possible if created by typeid. + property_ |= (long) kIsConstant; + } + if (gInterpreter->Type_IsReference(ttype)) { + // Note: This is not possible if created by typeid. + property_ |= (long) kIsReference; + } + dataType_ = TDataType::GetDataType(TDataType::GetType(*ti_)); + if (!gInterpreter->Type_IsFundamental(ttype) && + !gInterpreter->Type_IsEnum(ttype)) { + // Must be a class, struct, or union. + class_ = TClass::GetClass(*ti_); + } + if (gInterpreter->Type_IsEnum(ttype)) { + TType* TTy = gInterpreter->Type_GetParent(type_); + if (TTy != nullptr) { + TypeWithDict Tycl(*gInterpreter->Type_TypeInfo(TTy)); + if (Tycl.class_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(TType*, long): " + "Enum parent is not a class!\n"); + abort(); } - // it's a class with a dictionary - return TypeWithDict(cl, property); - } - // This is an enum, or a class without a CINT dictionary. We need Reflex to handle it. - //Reflex::Type t = Reflex::Type::ByName(name); - //return(bool(t) ? TypeWithDict(t) : TypeWithDict()); - return TypeWithDict(); - } - - std::string - TypeWithDict::qualifiedName() const { - std::string qname(name()); - if(isConst()) { - qname = "const " + qname; + TObject* tobj = + Tycl.class_->GetListOfEnums()->FindObject(name().c_str()); + if (tobj == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(TType*, long): " + "Enum not found in containing class!\n"); + abort(); + } + enum_ = reinterpret_cast(tobj); + } + else { + TObject* tobj = gROOT->GetListOfEnums()->FindObject(name().c_str()); + if (tobj == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(TType*, long): " + "Enum not found in global namespace!\n"); + abort(); + } + enum_ = reinterpret_cast(tobj); } - if(isReference()) { - qname += '&'; + if (enum_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict(TType*, long): " + "enum_ not set for enum type!\n"); + abort(); } - return qname; } +} - std::string - TypeWithDict::unscopedName() const { - return stripNamespace(name()); +TypeWithDict:: +operator bool() const +{ + if (*ti_ == typeid(void)) { + return true; } - - std::string - TypeWithDict::name() const { - if(isPointer()) { - return TypeID(typeInfo()).className() + '*'; - } - return TypeID(typeInfo()).className(); + if (type_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict::operator bool(): " + "type_ is nullptr!\n"); + abort(); } + return gInterpreter->Type_Bool(type_); +} - std::string - TypeWithDict::userClassName() const { - return TypeID(typeInfo()).userClassName(); +bool +TypeWithDict:: +hasDictionary() const +{ + if (*ti_ == typeid(void)) { + return true; } - - std::string - TypeWithDict::friendlyClassName() const { - return TypeID(typeInfo()).friendlyClassName(); + if (type_ == nullptr) { + // FIXME: Replace this with an exception! + fprintf(stderr, "TypeWithDict::hasDictionary(): " + "type_ is nullptr!\n"); + abort(); } + return gInterpreter->Type_Bool(type_); +} - bool - TypeWithDict::hasDictionary() const { - if(isEnum() || isTypedef() || isPointer()) { - return bool(type_); - } - if(isFundamental()) { - return true; - } - return ((class_ != nullptr && class_->GetTypeInfo() != nullptr)); - } +const type_info& +TypeWithDict:: +typeInfo() const +{ + return *ti_; +} - ObjectWithDict - TypeWithDict::construct() const { - if(class_ != nullptr) { - return ObjectWithDict(*this, class_->New()); - } - return ObjectWithDict(*this, new char[size()]); +const type_info& +TypeWithDict:: +id() const +{ + return *ti_; +} + +TType* +TypeWithDict:: +getType() const +{ + return type_; +} + +TClass* +TypeWithDict:: +getClass() const +{ + return class_; +} + +TEnum* +TypeWithDict:: +getEnum() const +{ + return enum_; +} + +TDataType* +TypeWithDict:: +getDataType() const +{ + return dataType_; +} + +long +TypeWithDict:: +getProperty() const +{ + return property_; +} + +bool +TypeWithDict:: +isClass() const +{ + // Note: This really means is class, struct, or union. + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsClass(type_); +} - void - TypeWithDict::destruct(void* address, bool dealloc) const { - if(class_ != nullptr) { - class_->Destructor(address, !dealloc); - } else if(dealloc) { - delete [] static_cast(address); - } +bool +TypeWithDict:: +isConst() const +{ + // Note: We must check the property flags here too because + // typeid() ignores const. + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsConst(type_) || (property_ & (long) kIsConstant); +} - void const* - TypeWithDict::pointerToBaseType(void const* ptr, TypeWithDict const& derivedType) const { - if(derivedType == *this) { - return ptr; - } - int offset = derivedType.getBaseClassOffset(*this); - if(offset < 0) return nullptr; - return static_cast(ptr) + offset; +bool +TypeWithDict:: +isEnum() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsEnum(type_); +} - void const* - TypeWithDict::pointerToContainedType(void const* ptr, TypeWithDict const& derivedType) const { - return pointerToBaseType(ptr, derivedType); +bool +TypeWithDict:: +isFundamental() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsFundamental(type_); +} - TypeWithDict::operator bool() const { - return hasDictionary(); +bool +TypeWithDict:: +isPointer() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsPointer(type_); +} + +bool +TypeWithDict:: +isReference() const +{ + // Note: We must check the property flags here too because + // typeid() ignores references. + if (type_ == nullptr) { + return false; + } + return gInterpreter->Type_IsReference(type_) || + (property_ & (long) kIsReference); +} - TypeWithDict - TypeWithDict::nestedType(char const* nestedName) const { - return byName(name() + "::" + nestedName); +bool +TypeWithDict:: +isTemplateInstance() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsTemplateInstance(type_); +} - MemberWithDict - TypeWithDict::dataMemberByName(std::string const& member) const { - if(class_ == nullptr) { - if(isEnum()) { - std::string fullName(name()); - size_t lastColon = fullName.find_last_of("::"); - assert(lastColon != std::string::npos && lastColon != 0U); - std::string theName(fullName.substr(0, lastColon - 1)); - TClass* cl = TClass::GetClass(theName.c_str()); - assert(cl != nullptr); - return MemberWithDict(cl->GetDataMember(member.c_str())); - } - return MemberWithDict(); - } - return MemberWithDict(class_->GetDataMember(member.c_str())); +bool +TypeWithDict:: +isTypedef() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsTypedef(type_); +} - FunctionWithDict - TypeWithDict::functionMemberByName(std::string const& member) const { - return FunctionWithDict(); +bool +TypeWithDict:: +isVirtual() const +{ + if (type_ == nullptr) { + return false; } + return gInterpreter->Type_IsVirtual(type_); +} -/* - // Implementation in ROOT +void +TypeWithDict:: +print(ostream& os) const +{ + os << name(); +} - TypeWithDict::functionMemberByName(std::string const& member) const { - if(class_ == nullptr) { - return FunctionWithDict(); - } - return FunctionWithDict(class_->GetMethodAny(ROOT::Cintex::CintName(member).c_str())); +string +TypeWithDict:: +qualifiedName() const +{ + if (type_ == nullptr) { + return "undefined"; } - - FunctionWithDict - TypeWithDict::functionMemberByName(std::string const& member, TypeWithDict const& signature, int mods, TypeMemberQuery memberQuery) const { - if(class_ == nullptr) { - return FunctionWithDict(); - } - // This is wrong. - return FunctionWithDict(class_->GetMethodAny(ROOT::Cintex::CintName(member).c_str())); + string qname(name()); + if (isConst()) { + qname = "const " + qname; } -*/ - - bool - TypeWithDict::isClass() const { - return property_&((Long_t)kIsClass|(Long_t)kIsStruct); + if (isReference()) { + qname += '&'; } + return qname; +} - bool - TypeWithDict::isConst() const { - return property_&(Long_t)kIsConstant; +string +TypeWithDict:: +unscopedName() const +{ + if (type_ == nullptr) { + return "undefined"; } + return stripNamespace(name()); +} - bool - TypeWithDict::isEnum() const { - return property_&(Long_t)kIsEnum; +string +TypeWithDict:: +name() const +{ + if (type_ == nullptr) { + return "undefined"; + } + if (isConst()) { + if (!isReference()) { + return "const " + TypeID(*ti_).className(); + } + return "const " + TypeID(*ti_).className() + "&"; } + if (isReference()) { + return TypeID(*ti_).className() + "&"; + } + return TypeID(*ti_).className(); +} - bool - TypeWithDict::isFundamental() const { - return property_ & (Long_t)kIsFundamental; +string +TypeWithDict:: +userClassName() const +{ + //FIXME: What about const and reference? + if (type_ == nullptr) { + return "undefined"; } + return TypeID(*ti_).userClassName(); +} - bool - TypeWithDict::isPointer() const { - return property_ & (Long_t)kIsPointer; +string +TypeWithDict:: +friendlyClassName() const +{ + //FIXME: What about const and reference? + if (type_ == nullptr) { + return "undefined"; } + return TypeID(*ti_).friendlyClassName(); +} - bool - TypeWithDict::isReference() const { - return property_ & (Long_t)kIsReference; +size_t +TypeWithDict:: +size() const +{ + if (type_ == nullptr) { + return 0; } + return gInterpreter->Type_Size(type_); +} - bool - TypeWithDict::isTypedef() const { - return property_ & (Long_t)kIsTypedef; +size_t +TypeWithDict:: +dataMemberSize() const +{ + if (class_ != nullptr) { + return class_->GetListOfDataMembers()->GetSize(); } + if (enum_ != nullptr) { + return enum_->GetConstants()->GetSize(); + } + return 0; +} - bool - TypeWithDict::isTemplateInstance() const { - return *name().rbegin() == '>'; +size_t +TypeWithDict:: +functionMemberSize() const +{ + if (class_ != nullptr) { + return class_->GetListOfMethods()->GetSize(); } + return 0; +} - bool - TypeWithDict::isVirtual() const { - return property_ & (Long_t)kIsVirtual; +const void* +TypeWithDict:: +pointerToBaseType(const void* ptr, const TypeWithDict& derivedType) const +{ + if (this == &derivedType) { + return ptr; + } + int offset = derivedType.getBaseClassOffset(*this); + if (offset < 0) { + return nullptr; } + return static_cast(ptr) + offset; +} - TypeWithDict - TypeWithDict::toType() const{ - return TypeWithDict(); +const void* +TypeWithDict:: +pointerToContainedType(const void* ptr, const TypeWithDict& derivedType) const +{ + return pointerToBaseType(ptr, derivedType); +} + +TypeWithDict +TypeWithDict:: +nestedType(char const* nestedName) const +{ + return byName(name() + "::" + nestedName); +} + +TypeWithDict +TypeWithDict:: +nestedType(const string& nestedName) const +{ + return byName(name() + "::" + nestedName); +} + +MemberWithDict +TypeWithDict:: +dataMemberByName(const string& member) const +{ + if (class_ != nullptr) { + return MemberWithDict(class_->GetDataMember(member.c_str())); + } + if (enum_ != nullptr) { + TClass* cl = enum_->GetClass(); + return MemberWithDict(cl->GetDataMember(member.c_str())); } + return MemberWithDict(); +} - std::string - TypeWithDict::templateName() const { - return std::string(); +FunctionWithDict +TypeWithDict:: +functionMemberByName(const string& member) const +{ + if (class_ == nullptr) { + return FunctionWithDict(); + } + TMethod* meth = reinterpret_cast( + class_->GetListOfMethods()->FindObject(member.c_str())); + if (meth == nullptr) { + return FunctionWithDict(); } + return FunctionWithDict(meth); +} - TypeWithDict - TypeWithDict::templateArgumentAt(size_t index) const { - std::string className = unscopedName(); - size_t begin = className.find('<'); - if(begin == std::string::npos) { - return TypeWithDict(); - } - ++begin; - size_t end = className.rfind('>'); - assert(end != std::string::npos); - assert(begin < end); - int depth = 0; - size_t argCount = 0; - for(size_t inx = begin; inx < end; ++inx) { - char c = className[inx]; - if(c == '<') { +//FunctionWithDict +//TypeWithDict:: +//functionMemberByName(string const& member, TypeWithDict const& signature, int mods, TypeMemberQuery memberQuery) const +//{ +// return FunctionWithDict(type_.FunctionMemberByName(member, signature.type_, +// mods, static_cast(memberQuery))); +//} + +TypeWithDict +TypeWithDict:: +toType() const +{ + TypeWithDict ret; + if (type_ == nullptr) { + return ret; + } + TType* ty = gInterpreter->Type_ToType(type_); + if (ty == nullptr) { + return ret; + } + const std::type_info* ti = gInterpreter->Type_TypeInfo(ty); + if (ti == nullptr) { + return ret; + } + ret = TypeWithDict(*ti); + return ret; +} + +string +TypeWithDict:: +templateName() const +{ + if (!isTemplateInstance()) { + return ""; + } + string templateName(name()); + auto begin = templateName.find('<'); + assert(begin != string::npos); + auto end = templateName.rfind('<'); + assert(end != string::npos); + assert(begin <= end); + if (begin < end) { + int depth = 1; + for (auto idx = begin + 1; idx <= end; ++idx) { + char c = templateName[idx]; + if (c == '<') { + if (depth == 0) { + begin = idx; + } ++depth; - } else if(c == '>') { + } + else if (c == '>') { --depth; assert(depth >= 0); - } else if(depth == 0 && c == ',') { - if(argCount < index) { - begin = inx + 1; - ++argCount; - } else { - end = inx; - break; - } } } - assert(depth == 0); - if(argCount < index) { - return TypeWithDict(); - } - return byName(className.substr(begin, end - begin)); } + return templateName.substr(0, begin); +} - std::type_info const& - TypeWithDict::typeInfo() const { - return *typeInfo_; +TypeWithDict +TypeWithDict:: +templateArgumentAt(size_t index) const +{ + string className(unscopedName()); + auto begin = className.find('<'); + if (begin == string::npos) { + return TypeWithDict(); } - - std::type_info const& - TypeWithDict::id() const { - return typeInfo(); + ++begin; + auto end = className.rfind('>'); + assert(end != string::npos); + assert(begin < end); + int depth = 0; + size_t argCount = 0; + for (auto idx = begin; idx < end; ++idx) { + char c = className[idx]; + if (c == '<') { + ++depth; + } + else if (c == '>') { + --depth; + assert(depth >= 0); + } + else if ((depth == 0) && (c == ',')) { + if (argCount < index) { + begin = idx + 1; + ++argCount; + } + else { + end = idx; + break; + } + } } - - int - TypeWithDict::getBaseClassOffset(TypeWithDict const& baseClass) const { - assert(class_ != nullptr); - assert(baseClass.class_ != nullptr); - //int offset = class_->GetBaseClassOffset(baseClass.class_); - //return offset; - return 0; + assert(depth == 0); + if (argCount < index) { + return TypeWithDict(); } + return byName(className.substr(begin, end - begin)); +} - int - TypeWithDict::stringToEnumValue(std::string const& enumMemberName) const { - return 0; - } +bool +TypeWithDict:: +hasBase(const string& basename) const +{ + if (class_ == nullptr) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::hasBase(basename): " + "type is not a class!\n"); + abort(); + } + TClass* cl = class_->GetBaseClass(basename.c_str()); + if (cl != nullptr) { + return true; + } + return false; +} - size_t - TypeWithDict::dataMemberSize() const { - return 0U; - } +bool +TypeWithDict:: +hasBase(const TypeWithDict& basety) const +{ + if (class_ == nullptr) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::hasBase(const TypeWithDict&): " + "type is not a class!\n"); + abort(); + } + if (basety.class_ == nullptr) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::hasBase(const TypeWithDict&): " + "basety is not a class!\n"); + abort(); + } + TClass* cl = class_->GetBaseClass(basety.name().c_str()); + if (cl != nullptr) { + return true; + } + return false; +} - size_t - TypeWithDict::functionMemberSize() const { - return 0U; - } +int +TypeWithDict:: +getBaseClassOffset(const TypeWithDict& baseClass) const +{ + if (class_ == nullptr) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::getBaseClassOffset(const TypeWithDict&): " + "type is not a class!\n"); + abort(); + } + if (baseClass.class_ == nullptr) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::getBaseClassOffset(const TypeWithDict&): " + "baseClass is not a class!\n"); + abort(); + } + int offset = class_->GetBaseClassOffset(baseClass.class_); + return offset; +} - size_t - TypeWithDict::size() const { - return 0U; - } +int +TypeWithDict:: +stringToEnumValue(const string& name) const +{ + if (enum_ == nullptr) { + fprintf(stderr, "TypeWithDict::stringToEnumValue(name): " + "type is not an enum!\n"); + abort(); + } + const TEnumConstant* ec = enum_->GetConstant(name.c_str()); + if (!ec) { + // FIXME: Turn this into a throw! + fprintf(stderr, "TypeWithDict::stringToEnumValue(name): " + "no enum constant named '%s'!\n", name.c_str()); + abort(); + } + return static_cast(ec->GetValue()); +} - bool - operator==(TypeWithDict const& a, TypeWithDict const& b) { - return a.typeInfo() == b.typeInfo(); - } +void* +TypeWithDict:: +allocate() const +{ + return new char[size()]; +} - std::ostream& - operator<<(std::ostream& os, TypeWithDict const& id) { - id.print(os); - return os; +void +TypeWithDict:: +deallocate(void* address) const +{ + delete[] reinterpret_cast(address); +} + +ObjectWithDict +TypeWithDict:: +construct() const +{ + if (class_ != nullptr) { + return ObjectWithDict(*this, class_->New()); } + return ObjectWithDict(*this, new char[size()]); +} - IterWithDict - TypeBases::begin() const { - if(class_ == nullptr) { - return IterWithDict(); - } - return IterWithDict(class_->GetListOfBases()); +void +TypeWithDict:: +destruct(void* address, bool dealloc) const +{ + if (class_ != nullptr) { + class_->Destructor(address, !dealloc); + return; + } + if (dealloc) { + delete[] reinterpret_cast(address); } +} - IterWithDict - TypeBases::end() const { +//------------------------------------------------------------- +// +// + +bool +operator==(const TypeWithDict& a, const TypeWithDict& b) +{ + return a.typeInfo() == b.typeInfo(); +} + +ostream& +operator<<(ostream& os, const TypeWithDict& ty) +{ + ty.print(os); + return os; +} + +//------------------------------------------------------------- +// +// + +TypeBases:: +TypeBases(const TypeWithDict& type) + : type_(type.type_) + , class_(type.class_) +{ +} + +IterWithDict +TypeBases:: +begin() const +{ + if (class_ == nullptr) { return IterWithDict(); } + return IterWithDict(class_->GetListOfBases()); +} - size_t - TypeBases::size() const { - return 0U; - } +IterWithDict +TypeBases:: +end() const +{ + return IterWithDict(); +} - IterWithDict - TypeDataMembers::begin() const { - if(class_ == nullptr) { - return IterWithDict(); - } - return IterWithDict(class_->GetListOfDataMembers()); +size_t +TypeBases:: +size() const +{ + if (class_ == nullptr) { + return 0; } + return class_->GetListOfBases()->GetSize(); +} - IterWithDict - TypeDataMembers::end() const { +//------------------------------------------------------------- +// +// + +TypeDataMembers:: +TypeDataMembers(const TypeWithDict& type) + : type_(type.type_) + , class_(type.class_) +{ +} + +IterWithDict +TypeDataMembers:: +begin() const +{ + if (class_ == nullptr) { return IterWithDict(); } + return IterWithDict(class_->GetListOfDataMembers()); +} - size_t - TypeDataMembers::size() const { - return 0U; - } +IterWithDict +TypeDataMembers:: +end() const +{ + return IterWithDict(); +} -/* - IterWithDict - TypeFunctionMembers::begin() const { - if(class_ == nullptr) { - return IterWithDict(); - } - return IterWithDict(class_->GetListOfMethods()); +size_t +TypeDataMembers:: +size() const +{ + if (class_ == nullptr) { + return 0; } + return class_->GetListOfDataMembers()->GetSize(); +} - IterWithDict - TypeFunctionMembers::end() const { - return IterWithDict(); - } +//------------------------------------------------------------- +// +// - Reflex::Member_Iterator - TypeFunctionMembers::begin() const { - return type_.FunctionMember_Begin(); - } +TypeFunctionMembers:: +TypeFunctionMembers(const TypeWithDict& type) + : type_(type.type_) + , class_(type.class_) +{ +} - Reflex::Member_Iterator - TypeFunctionMembers::end() const { - return type_.FunctionMember_End(); +IterWithDict +TypeFunctionMembers:: +begin() const +{ + if (class_ == nullptr) { + return IterWithDict(); } + return IterWithDict(class_->GetListOfMethods()); +} - size_t - TypeFunctionMembers::size() const { - if(class_ == nullptr) { - return 0U; - } - return class_->GetListOfMethods()->GetSize(); - } -*/ +IterWithDict +TypeFunctionMembers:: +end() const +{ + return IterWithDict(); +} - size_t - TypeFunctionMembers::size() const { - return 0U; +size_t +TypeFunctionMembers:: +size() const +{ + if (class_ == nullptr) { + return 0; } - + return class_->GetListOfMethods()->GetSize(); } + +} // namespace edm + diff --git a/Fireworks/Core/src/FWModelContextMenuHandler.cc b/Fireworks/Core/src/FWModelContextMenuHandler.cc index f1c5d18b4f8b7..c6d0953336d52 100644 --- a/Fireworks/Core/src/FWModelContextMenuHandler.cc +++ b/Fireworks/Core/src/FWModelContextMenuHandler.cc @@ -256,19 +256,19 @@ FWModelContextMenuHandler::showSelectedModelContext(Int_t iX, Int_t iY, FWViewCo if( m_selectionManager->selected().size()==1 ) { { - edm::TypeWithDict rtype(edm::TypeWithDict::byName(id.item()->modelType()->GetName())); - edm::ObjectWithDict o(rtype, const_cast(id.item()->modelData(id.index()))); - edm::TypeMemberQuery inh = edm::TypeMemberQuery::InheritedAlso; - if ( rtype.functionMemberByName("print",edm::TypeWithDict(edm::TypeWithDict::byName("void (std::ostream&)"), Long_t(kIsConstant)), 0, inh)) - { - m_modelPopup->EnableEntry(kPrint); + //edm::TypeWithDict rtype(edm::TypeWithDict::byName(id.item()->modelType()->GetName())); + //edm::ObjectWithDict o(rtype, const_cast(id.item()->modelData(id.index()))); + //edm::TypeMemberQuery inh = edm::TypeMemberQuery::InheritedAlso; + //if ( rtype.functionMemberByName("print",edm::TypeWithDict(edm::TypeWithDict::byName("void (std::ostream&)"), Long_t(kIsConstant)), 0, inh)) + //{ + //m_modelPopup->EnableEntry(kPrint); // std::cout << "Enable " <DisableEntry(kPrint); // printf("Disable print \n"); - } + //} } //add the detail view entries std::vector viewChoices = m_detailViewManager->detailViewsFor(*(m_selectionManager->selected().begin()));