File indexing completed on 2024-04-06 12:01:20
0001 #include "CommonTools/Utils/interface/parser/MethodInvoker.h"
0002
0003 #include "CommonTools/Utils/src/ExpressionVar.h"
0004 #include "CommonTools/Utils/interface/parser/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
0011 using namespace reco::parser;
0012 using namespace std;
0013
0014 MethodInvoker::MethodInvoker(const edm::FunctionWithDict& method, const vector<AnyMethodArgument>& ints)
0015 : method_(method), member_(), ints_(ints), isFunction_(true) {
0016 setArgs();
0017 if (isFunction_) {
0018 retTypeFinal_ = method_.finalReturnType();
0019 }
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 }
0033
0034 MethodInvoker::MethodInvoker(const edm::MemberWithDict& member)
0035 : method_(), member_(member), ints_(), isFunction_(false) {
0036 setArgs();
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 }
0050
0051 MethodInvoker::MethodInvoker(const MethodInvoker& rhs)
0052 : method_(rhs.method_),
0053 member_(rhs.member_),
0054 ints_(rhs.ints_),
0055 isFunction_(rhs.isFunction_),
0056 retTypeFinal_(rhs.retTypeFinal_) {
0057 setArgs();
0058 }
0059
0060 MethodInvoker& MethodInvoker::operator=(const MethodInvoker& rhs) {
0061 if (this != &rhs) {
0062 method_ = rhs.method_;
0063 member_ = rhs.member_;
0064 ints_ = rhs.ints_;
0065 isFunction_ = rhs.isFunction_;
0066 retTypeFinal_ = rhs.retTypeFinal_;
0067
0068 setArgs();
0069 }
0070 return *this;
0071 }
0072
0073 void MethodInvoker::setArgs() {
0074 for (size_t i = 0; i < ints_.size(); ++i) {
0075 args_.push_back(std::visit(AnyMethodArgument2VoidPtr(), ints_[i]));
0076 }
0077 }
0078
0079 std::string MethodInvoker::methodName() const {
0080 if (isFunction_) {
0081 return method_.name();
0082 }
0083 return member_.name();
0084 }
0085
0086 std::string MethodInvoker::returnTypeName() const {
0087 if (isFunction_) {
0088 return method_.typeName();
0089 }
0090 return member_.typeOf().qualifiedName();
0091 }
0092
0093 edm::ObjectWithDict MethodInvoker::invoke(const edm::ObjectWithDict& o, edm::ObjectWithDict& retstore) const {
0094 edm::ObjectWithDict ret = retstore;
0095 edm::TypeWithDict retType;
0096 if (isFunction_) {
0097
0098
0099
0100
0101
0102
0103 method_.invoke(o, &ret, args_);
0104
0105 retType = retTypeFinal_;
0106 } else {
0107
0108
0109
0110
0111
0112
0113 ret = member_.get(o);
0114 retType = member_.typeOf();
0115 }
0116 void* addr = ret.address();
0117
0118
0119 if (addr == nullptr) {
0120 throw edm::Exception(edm::errors::InvalidReference)
0121 << "method \"" << methodName() << "\" called with " << args_.size() << " arguments returned a null pointer ";
0122 }
0123
0124 if (retType.isPointer() || retType.isReference()) {
0125
0126 if (retType.isPointer()) {
0127 retType = retType.toType();
0128 } else {
0129
0130
0131
0132 retType = retType.stripConstRef();
0133 }
0134 ret = edm::ObjectWithDict(retType, *static_cast<void**>(addr));
0135
0136 }
0137 if (!bool(ret)) {
0138 throw edm::Exception(edm::errors::Configuration)
0139 << "method \"" << methodName() << "\" returned void invoked on object of type \"" << o.typeOf().qualifiedName()
0140 << "\"\n";
0141 }
0142 return ret;
0143 }
0144
0145 LazyInvoker::LazyInvoker(const std::string& name, const std::vector<AnyMethodArgument>& args)
0146 : name_(name), argsBeforeFixups_(args) {}
0147
0148 LazyInvoker::~LazyInvoker() {}
0149
0150 const SingleInvoker& LazyInvoker::invoker(const edm::TypeWithDict& type) const {
0151
0152
0153 const edm::TypeID thetype(type.typeInfo());
0154 auto found = invokers_.find(thetype);
0155 if (found != invokers_.cend()) {
0156 return *(found->second);
0157 }
0158 auto to_add = std::make_shared<SingleInvoker>(type, name_, argsBeforeFixups_);
0159 auto emplace_result = invokers_.insert(std::make_pair(thetype, to_add));
0160 return *(emplace_result.first->second);
0161 }
0162
0163 edm::ObjectWithDict LazyInvoker::invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const {
0164 pair<edm::ObjectWithDict, bool> ret(o, false);
0165 do {
0166 edm::TypeWithDict type = ret.first.typeOf();
0167 if (type.isClass()) {
0168 type = ret.first.dynamicType();
0169 }
0170 ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0171 } while (ret.second == false);
0172 return ret.first;
0173 }
0174
0175 double LazyInvoker::invokeLast(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const {
0176 pair<edm::ObjectWithDict, bool> ret(o, false);
0177 const SingleInvoker* i = nullptr;
0178 do {
0179 edm::TypeWithDict type = ret.first.typeOf();
0180 if (type.isClass()) {
0181 type = ret.first.dynamicType();
0182 }
0183 i = &invoker(type);
0184 ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0185 } while (ret.second == false);
0186 return i->retToDouble(ret.first);
0187 }
0188
0189 SingleInvoker::SingleInvoker(const edm::TypeWithDict& type,
0190 const std::string& name,
0191 const std::vector<AnyMethodArgument>& args) {
0192 TypeStack typeStack(1, type);
0193 LazyMethodStack dummy;
0194 MethodArgumentStack dummy2;
0195 MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
0196 isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
0197
0198
0199
0200 returnStorage(createStorage(storageNeedsDestructor_));
0201
0202
0203 retType_ = reco::typeCode(typeStack[1]);
0204 }
0205
0206 SingleInvoker::~SingleInvoker() {
0207 edm::ObjectWithDict stored;
0208 while (storage_.try_pop(stored)) {
0209
0210 ExpressionVar::delStorage(stored);
0211 }
0212 }
0213
0214 edm::ObjectWithDict SingleInvoker::createStorage(bool& needsDestructor) const {
0215 if (invokers_.front().isFunction()) {
0216 edm::TypeWithDict retType = invokers_.front().method().finalReturnType();
0217 edm::ObjectWithDict stored;
0218 needsDestructor = ExpressionVar::makeStorage(stored, retType);
0219 return stored;
0220 }
0221 needsDestructor = false;
0222 return edm::ObjectWithDict();
0223 }
0224
0225 edm::ObjectWithDict SingleInvoker::borrowStorage() const {
0226 edm::ObjectWithDict o;
0227 if (storage_.try_pop(o)) {
0228
0229 return o;
0230 }
0231 bool dummy;
0232 o = createStorage(dummy);
0233
0234 return o;
0235 }
0236
0237 void SingleInvoker::returnStorage(edm::ObjectWithDict&& o) const {
0238
0239 storage_.push(std::move(o));
0240 }
0241
0242 pair<edm::ObjectWithDict, bool> SingleInvoker::invoke(const edm::ObjectWithDict& o,
0243 std::vector<StorageManager>& v) const {
0244
0245
0246
0247
0248
0249
0250 auto storage = borrowStorage();
0251 pair<edm::ObjectWithDict, bool> ret(invokers_.front().invoke(o, storage), !isRefGet_);
0252 v.emplace_back(storage, this, storageNeedsDestructor_);
0253 return ret;
0254 }
0255
0256 double SingleInvoker::retToDouble(const edm::ObjectWithDict& o) const {
0257 if (!ExpressionVar::isValidReturnType(retType_)) {
0258 throwFailedConversion(o);
0259 }
0260 return ExpressionVar::objToDouble(o, retType_);
0261 }
0262
0263 void SingleInvoker::throwFailedConversion(const edm::ObjectWithDict& o) const {
0264 throw edm::Exception(edm::errors::Configuration)
0265 << "member \"" << invokers_.back().methodName() << "\" return type is \"" << invokers_.back().returnTypeName()
0266 << "\" retured a \"" << o.typeOf().qualifiedName() << "\" which is not convertible to double.";
0267 }
0268
0269 StorageManager::~StorageManager() {
0270 if (needsDestructor_) {
0271 object_.destruct(false);
0272 }
0273 if (invoker_) {
0274 invoker_->returnStorage(std::move(object_));
0275 }
0276 }