Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-17 23:10:26

0001 #include "CommonTools/Utils/interface/MethodInvoker.h"
0002 
0003 #include "CommonTools/Utils/src/ExpressionVar.h"
0004 #include "CommonTools/Utils/interface/MethodSetter.h"
0005 #include "CommonTools/Utils/src/findMethod.h"
0006 #include "CommonTools/Utils/interface/returnType.h"
0007 #include "FWCore/Utilities/interface/EDMException.h"
0008 
0009 #include <algorithm>
0010 using namespace reco::parser;
0011 using namespace std;
0012 
0013 MethodInvoker::MethodInvoker(const edm::FunctionWithDict& method, const vector<AnyMethodArgument>& ints)
0014     : method_(method), member_(), ints_(ints), isFunction_(true) {
0015   setArgs();
0016   if (isFunction_) {
0017     retTypeFinal_ = method_.finalReturnType();
0018   }
0019   //std::cout <<
0020   //   "Booking " <<
0021   //   methodName() <<
0022   //   " from " <<
0023   //   method_.declaringType().name() <<
0024   //   " with " <<
0025   //   args_.size() <<
0026   //   " arguments" <<
0027   //   " (were " <<
0028   //   ints.size() <<
0029   //   ")" <<
0030   //   std::endl;
0031 }
0032 
0033 MethodInvoker::MethodInvoker(const edm::MemberWithDict& member)
0034     : method_(), member_(member), ints_(), isFunction_(false) {
0035   setArgs();
0036   //std::cout <<
0037   //  "Booking " <<
0038   //  methodName() <<
0039   //  " from " <<
0040   //  member_.declaringType().name() <<
0041   //  " with " <<
0042   //  args_.size() <<
0043   //  " arguments" <<
0044   //  " (were " <<
0045   //  ints.size() <<
0046   //  ")" <<
0047   //  std::endl;
0048 }
0049 
0050 MethodInvoker::MethodInvoker(const MethodInvoker& rhs)
0051     : method_(rhs.method_),
0052       member_(rhs.member_),
0053       ints_(rhs.ints_),
0054       isFunction_(rhs.isFunction_),
0055       retTypeFinal_(rhs.retTypeFinal_) {
0056   setArgs();
0057 }
0058 
0059 MethodInvoker& MethodInvoker::operator=(const MethodInvoker& rhs) {
0060   if (this != &rhs) {
0061     method_ = rhs.method_;
0062     member_ = rhs.member_;
0063     ints_ = rhs.ints_;
0064     isFunction_ = rhs.isFunction_;
0065     retTypeFinal_ = rhs.retTypeFinal_;
0066 
0067     setArgs();
0068   }
0069   return *this;
0070 }
0071 
0072 void MethodInvoker::setArgs() {
0073   for (size_t i = 0; i < ints_.size(); ++i) {
0074     args_.push_back(std::visit(AnyMethodArgument2VoidPtr(), ints_[i]));
0075   }
0076 }
0077 
0078 std::string MethodInvoker::methodName() const {
0079   if (isFunction_) {
0080     return method_.name();
0081   }
0082   return member_.name();
0083 }
0084 
0085 std::string MethodInvoker::returnTypeName() const {
0086   if (isFunction_) {
0087     return method_.typeName();
0088   }
0089   return member_.typeOf().qualifiedName();
0090 }
0091 
0092 edm::ObjectWithDict MethodInvoker::invoke(const edm::ObjectWithDict& o, edm::ObjectWithDict& retstore) const {
0093   edm::ObjectWithDict ret = retstore;
0094   edm::TypeWithDict retType;
0095   if (isFunction_) {
0096     //std::cout << "Invoking " << methodName()
0097     //  << " from " << method_.declaringType().qualifiedName()
0098     //  << " on an instance of " << o.dynamicType().qualifiedName()
0099     //  << " at " << o.address()
0100     //  << " with " << args_.size() << " arguments"
0101     //  << std::endl;
0102     method_.invoke(o, &ret, args_);
0103     // this is correct, it takes pointers and refs into account
0104     retType = retTypeFinal_;
0105   } else {
0106     //std::cout << "Invoking " << methodName()
0107     //  << " from " << member_.declaringType().qualifiedName()
0108     //  << " on an instance of " << o.dynamicType().qualifiedName()
0109     //  << " at " << o.address()
0110     //  << " with " << args_.size() << " arguments"
0111     //  << std::endl;
0112     ret = member_.get(o);
0113     retType = member_.typeOf();
0114   }
0115   void* addr = ret.address();
0116   //std::cout << "Stored result of " <<  methodName() << " (type " <<
0117   //  returnTypeName() << ") at " << addr << std::endl;
0118   if (addr == nullptr) {
0119     throw edm::Exception(edm::errors::InvalidReference)
0120         << "method \"" << methodName() << "\" called with " << args_.size() << " arguments returned a null pointer ";
0121   }
0122   //std::cout << "Return type is " << retType.qualifiedName() << std::endl;
0123   if (retType.isPointer() || retType.isReference()) {
0124     // both need void** -> void* conversion
0125     if (retType.isPointer()) {
0126       retType = retType.toType();
0127     } else {
0128       // strip cv & ref flags
0129       // FIXME: This is only true if the propery passed to the constructor
0130       //       overrides the const and reference flags.
0131       retType = retType.stripConstRef();
0132     }
0133     ret = edm::ObjectWithDict(retType, *static_cast<void**>(addr));
0134     //std::cout << "Now type is " << retType.qualifiedName() << std::endl;
0135   }
0136   if (!bool(ret)) {
0137     throw edm::Exception(edm::errors::Configuration)
0138         << "method \"" << methodName() << "\" returned void invoked on object of type \"" << o.typeOf().qualifiedName()
0139         << "\"\n";
0140   }
0141   return ret;
0142 }
0143 
0144 LazyInvoker::LazyInvoker(const std::string& name, const std::vector<AnyMethodArgument>& args)
0145     : name_(name), argsBeforeFixups_(args) {}
0146 
0147 LazyInvoker::~LazyInvoker() {}
0148 
0149 const SingleInvoker& LazyInvoker::invoker(const edm::TypeWithDict& type) const {
0150   //std::cout << "LazyInvoker for " << name_ << " called on type " <<
0151   //  type.qualifiedName() << std::endl;
0152   const edm::TypeID thetype(type.typeInfo());
0153   auto found = invokers_.find(thetype);
0154   if (found != invokers_.cend()) {
0155     return *(found->second);
0156   }
0157   auto to_add = std::make_shared<SingleInvoker>(type, name_, argsBeforeFixups_);
0158   auto emplace_result = invokers_.insert(std::make_pair(thetype, to_add));
0159   return *(emplace_result.first->second);
0160 }
0161 
0162 edm::ObjectWithDict LazyInvoker::invoke(const edm::ObjectWithDict& o, std::vector<edm::ObjectWithDict>& v) const {
0163   pair<edm::ObjectWithDict, bool> ret(o, false);
0164   do {
0165     edm::TypeWithDict type = ret.first.typeOf();
0166     if (type.isClass()) {
0167       type = ret.first.dynamicType();
0168     }
0169     ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0170   } while (ret.second == false);
0171   return ret.first;
0172 }
0173 
0174 double LazyInvoker::invokeLast(const edm::ObjectWithDict& o, std::vector<edm::ObjectWithDict>& v) const {
0175   pair<edm::ObjectWithDict, bool> ret(o, false);
0176   const SingleInvoker* i = nullptr;
0177   do {
0178     edm::TypeWithDict type = ret.first.typeOf();
0179     if (type.isClass()) {
0180       type = ret.first.dynamicType();
0181     }
0182     i = &invoker(type);
0183     ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0184   } while (ret.second == false);
0185   return i->retToDouble(ret.first);
0186 }
0187 
0188 SingleInvoker::SingleInvoker(const edm::TypeWithDict& type,
0189                              const std::string& name,
0190                              const std::vector<AnyMethodArgument>& args) {
0191   TypeStack typeStack(1, type);
0192   LazyMethodStack dummy;
0193   MethodArgumentStack dummy2;
0194   MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
0195   isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
0196   //std::cerr  << "SingleInvoker on type " <<  type.qualifiedName() <<
0197   //  ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") <<
0198   //  std::endl;
0199   if (invokers_.front().isFunction()) {
0200     edm::TypeWithDict retType = invokers_.front().method().finalReturnType();
0201     storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType);
0202   } else {
0203     storage_ = edm::ObjectWithDict();
0204     storageNeedsDestructor_ = false;
0205   }
0206   // typeStack[0] = type of self
0207   // typeStack[1] = type of ret
0208   retType_ = reco::typeCode(typeStack[1]);
0209 }
0210 
0211 SingleInvoker::~SingleInvoker() { ExpressionVar::delStorage(storage_); }
0212 
0213 pair<edm::ObjectWithDict, bool> SingleInvoker::invoke(const edm::ObjectWithDict& o,
0214                                                       std::vector<edm::ObjectWithDict>& v) const {
0215   // std::cerr << "[SingleInvoker::invoke] member " <<
0216   //   invokers_.front().method().qualifiedName() <<
0217   //   " of type " <<
0218   //   o.typeOf().qualifiedName() <<
0219   //   (!isRefGet_ ? " is one shot" : " needs another round") <<
0220   //   std::endl;
0221   pair<edm::ObjectWithDict, bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
0222   if (storageNeedsDestructor_) {
0223     //std::cerr << "Storage type: " << storage_.typeOf().qualifiedName() <<
0224     //  ", I have to call the destructor." << std::endl;
0225     v.push_back(storage_);
0226   }
0227   return ret;
0228 }
0229 
0230 double SingleInvoker::retToDouble(const edm::ObjectWithDict& o) const {
0231   if (!ExpressionVar::isValidReturnType(retType_)) {
0232     throwFailedConversion(o);
0233   }
0234   return ExpressionVar::objToDouble(o, retType_);
0235 }
0236 
0237 void SingleInvoker::throwFailedConversion(const edm::ObjectWithDict& o) const {
0238   throw edm::Exception(edm::errors::Configuration)
0239       << "member \"" << invokers_.back().methodName() << "\" return type is \"" << invokers_.back().returnTypeName()
0240       << "\" retured a \"" << o.typeOf().qualifiedName() << "\" which is not convertible to double.";
0241 }