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
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 }
0032
0033 MethodInvoker::MethodInvoker(const edm::MemberWithDict& member)
0034 : method_(), member_(member), ints_(), isFunction_(false) {
0035 setArgs();
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
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
0097
0098
0099
0100
0101
0102 method_.invoke(o, &ret, args_);
0103
0104 retType = retTypeFinal_;
0105 } else {
0106
0107
0108
0109
0110
0111
0112 ret = member_.get(o);
0113 retType = member_.typeOf();
0114 }
0115 void* addr = ret.address();
0116
0117
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
0123 if (retType.isPointer() || retType.isReference()) {
0124
0125 if (retType.isPointer()) {
0126 retType = retType.toType();
0127 } else {
0128
0129
0130
0131 retType = retType.stripConstRef();
0132 }
0133 ret = edm::ObjectWithDict(retType, *static_cast<void**>(addr));
0134
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
0151
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
0197
0198
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
0207
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
0216
0217
0218
0219
0220
0221 pair<edm::ObjectWithDict, bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
0222 if (storageNeedsDestructor_) {
0223
0224
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 }