00001 #include "CommonTools/Utils/src/MethodInvoker.h"
00002 #include "CommonTools/Utils/src/findMethod.h"
00003 #include "CommonTools/Utils/src/returnType.h"
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "CommonTools/Utils/src/MethodSetter.h"
00006 #include "CommonTools/Utils/src/ExpressionVar.h"
00007
00008 #include <algorithm>
00009 using namespace reco::parser;
00010 using namespace std;
00011
00012 MethodInvoker::MethodInvoker(const edm::FunctionWithDict & method, const vector<AnyMethodArgument> & ints) :
00013 method_(method), member_(), ints_(ints), isFunction_(true)
00014 {
00015 setArgs();
00016
00017
00018
00019
00020
00021 }
00022
00023 MethodInvoker::MethodInvoker(const edm::MemberWithDict & member) :
00024 method_(), member_(member), ints_(), isFunction_(false)
00025 {
00026 setArgs();
00027
00028
00029
00030
00031
00032 }
00033
00034 MethodInvoker::MethodInvoker(const MethodInvoker & other) :
00035 method_(other.method_), member_(other.member_), ints_(other.ints_), isFunction_(other.isFunction_) {
00036 setArgs();
00037 }
00038
00039 MethodInvoker & MethodInvoker::operator=(const MethodInvoker & other) {
00040 method_ = other.method_;
00041 member_ = other.member_;
00042 ints_ = other.ints_;
00043 isFunction_ = other.isFunction_;
00044 setArgs();
00045 return *this;
00046 }
00047
00048 void MethodInvoker::setArgs() {
00049 for(size_t i = 0; i < ints_.size(); ++i) {
00050 args_.push_back( boost::apply_visitor( AnyMethodArgument2VoidPtr(), ints_[i] ) );
00051 }
00052 }
00053
00054 std::string
00055 MethodInvoker::methodName() const {
00056 if(isFunction_) {
00057 return method_.name();
00058 }
00059 return member_.name();
00060 }
00061
00062 std::string
00063 MethodInvoker::returnTypeName() const {
00064 if(isFunction_) {
00065 return method_.typeOf().name(edm::TypeNameHandling::Qualified);
00066 }
00067 return member_.typeOf().name(edm::TypeNameHandling::Qualified);
00068 }
00069
00070 edm::ObjectWithDict
00071 MethodInvoker::invoke(const edm::ObjectWithDict & o, edm::ObjectWithDict &retstore) const {
00072 edm::ObjectWithDict ret = retstore;
00073 edm::TypeWithDict retType;
00074 if(isFunction_) {
00075
00076
00077
00078
00079
00080
00081 method_.invoke(o, &ret, args_);
00082 retType = method_.returnType();
00083 } else {
00084
00085
00086
00087
00088
00089
00090 ret = member_.get(o);
00091 retType = member_.typeOf();
00092 }
00093 void * addr = ret.address();
00094
00095 if(addr==0) {
00096 throw edm::Exception(edm::errors::InvalidReference)
00097 << "method \"" << methodName() << "\" called with " << args_.size()
00098 << " arguments returned a null pointer ";
00099 }
00100
00101
00102 if(retType.isPointer() || retType.isReference()) {
00103 if (retType.isPointer()) {
00104 retType = retType.toType();
00105 } else {
00106 retType = edm::TypeWithDict(retType, edm::TypeModifiers::NoMod);
00107 }
00108 while (retType.isTypedef()) retType = retType.toType();
00109 ret = edm::ObjectWithDict(retType, *static_cast<void **>(addr));
00110
00111 }
00112 if(!ret) {
00113 throw edm::Exception(edm::errors::Configuration)
00114 << "method \"" << methodName()
00115 << "\" returned void invoked on object of type \""
00116 << o.typeOf().name(edm::TypeNameHandling::Qualified) << "\"\n";
00117 }
00118 return ret;
00119 }
00120
00121 LazyInvoker::LazyInvoker(const std::string &name, const std::vector<AnyMethodArgument> & args) :
00122 name_(name),
00123 argsBeforeFixups_(args)
00124 {
00125 }
00126
00127 LazyInvoker::~LazyInvoker()
00128 {
00129 }
00130
00131 const SingleInvoker &
00132 LazyInvoker::invoker(const edm::TypeWithDict & type) const
00133 {
00134
00135 SingleInvokerPtr & invoker = invokers_[type.id()];
00136 if (!invoker) {
00137
00138 invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_));
00139 }
00140 return * invoker;
00141 }
00142
00143 edm::ObjectWithDict
00144 LazyInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00145 {
00146 pair<edm::ObjectWithDict, bool> ret(o,false);
00147 do {
00148 edm::TypeWithDict type = ret.first.typeOf();
00149 if (type.isClass()) type = ret.first.dynamicType();
00150 ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00151 } while (ret.second == false);
00152 return ret.first;
00153 }
00154
00155 double
00156 LazyInvoker::invokeLast(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00157 {
00158 pair<edm::ObjectWithDict, bool> ret(o,false);
00159 const SingleInvoker *i = 0;
00160 do {
00161 edm::TypeWithDict type = ret.first.typeOf();
00162 if (type.isClass()) type = ret.first.dynamicType();
00163 i = & invoker(type);
00164 ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00165 } while (ret.second == false);
00166 return i->retToDouble(ret.first);
00167 }
00168
00169 SingleInvoker::SingleInvoker(const edm::TypeWithDict &type,
00170 const std::string &name,
00171 const std::vector<AnyMethodArgument> &args)
00172 {
00173 TypeStack typeStack(1, type);
00174 LazyMethodStack dummy;
00175 MethodArgumentStack dummy2;
00176 MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
00177 isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
00178
00179
00180
00181 if(invokers_.front().isFunction()) {
00182 edm::TypeWithDict retType = invokers_.front().method().returnType().finalType();
00183 storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType);
00184 } else {
00185 storage_ = edm::ObjectWithDict();
00186 storageNeedsDestructor_ = false;
00187 }
00188 retType_ = reco::typeCode(typeStack[1]);
00189 }
00190
00191 SingleInvoker::~SingleInvoker()
00192 {
00193 ExpressionVar::delStorage(storage_);
00194 }
00195
00196 pair<edm::ObjectWithDict,bool>
00197 SingleInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00198 {
00199
00200
00201
00202 pair<edm::ObjectWithDict,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00203 if (storageNeedsDestructor_) {
00204
00205 v.push_back(storage_);
00206 }
00207 return ret;
00208 }
00209
00210 double
00211 SingleInvoker::retToDouble(const edm::ObjectWithDict & o) const {
00212 if (!ExpressionVar::isValidReturnType(retType_)) {
00213 throwFailedConversion(o);
00214 }
00215 return ExpressionVar::objToDouble(o, retType_);
00216 }
00217
00218 void
00219 SingleInvoker::throwFailedConversion(const edm::ObjectWithDict & o) const {
00220 throw edm::Exception(edm::errors::Configuration)
00221 << "member \"" << invokers_.back().methodName()
00222 << "\" return type is \"" << invokers_.back().returnTypeName()
00223 << "\" retured a \"" << o.typeOf().name(edm::TypeNameHandling::Qualified)
00224 << "\" which is not convertible to double.";
00225 }