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().qualifiedName();
00066 }
00067 return member_.typeOf().qualifiedName();
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_.finalReturnType();
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, 0L);
00107 }
00108 ret = edm::ObjectWithDict(retType, *static_cast<void **>(addr));
00109
00110 }
00111 if(!ret) {
00112 throw edm::Exception(edm::errors::Configuration)
00113 << "method \"" << methodName()
00114 << "\" returned void invoked on object of type \""
00115 << o.typeOf().qualifiedName() << "\"\n";
00116 }
00117 return ret;
00118 }
00119
00120 LazyInvoker::LazyInvoker(const std::string &name, const std::vector<AnyMethodArgument> & args) :
00121 name_(name),
00122 argsBeforeFixups_(args)
00123 {
00124 }
00125
00126 LazyInvoker::~LazyInvoker()
00127 {
00128 }
00129
00130 const SingleInvoker &
00131 LazyInvoker::invoker(const edm::TypeWithDict & type) const
00132 {
00133
00134 SingleInvokerPtr & invoker = invokers_[edm::TypeID(type.id())];
00135 if (!invoker) {
00136
00137 invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_));
00138 }
00139 return * invoker;
00140 }
00141
00142 edm::ObjectWithDict
00143 LazyInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00144 {
00145 pair<edm::ObjectWithDict, bool> ret(o,false);
00146 do {
00147 edm::TypeWithDict type = ret.first.typeOf();
00148 if (type.isClass()) type = ret.first.dynamicType();
00149 ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00150 } while (ret.second == false);
00151 return ret.first;
00152 }
00153
00154 double
00155 LazyInvoker::invokeLast(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00156 {
00157 pair<edm::ObjectWithDict, bool> ret(o,false);
00158 const SingleInvoker *i = 0;
00159 do {
00160 edm::TypeWithDict type = ret.first.typeOf();
00161 if (type.isClass()) type = ret.first.dynamicType();
00162 i = & invoker(type);
00163 ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00164 } while (ret.second == false);
00165 return i->retToDouble(ret.first);
00166 }
00167
00168 SingleInvoker::SingleInvoker(const edm::TypeWithDict &type,
00169 const std::string &name,
00170 const std::vector<AnyMethodArgument> &args)
00171 {
00172 TypeStack typeStack(1, type);
00173 LazyMethodStack dummy;
00174 MethodArgumentStack dummy2;
00175 MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
00176 isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
00177
00178 if(invokers_.front().isFunction()) {
00179 edm::TypeWithDict retType = invokers_.front().method().finalReturnType();
00180 storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType);
00181 } else {
00182 storage_ = edm::ObjectWithDict();
00183 storageNeedsDestructor_ = false;
00184 }
00185 retType_ = reco::typeCode(typeStack[1]);
00186 }
00187
00188 SingleInvoker::~SingleInvoker()
00189 {
00190 ExpressionVar::delStorage(storage_);
00191 }
00192
00193 pair<edm::ObjectWithDict,bool>
00194 SingleInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const
00195 {
00196
00197
00198
00199 pair<edm::ObjectWithDict,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00200 if (storageNeedsDestructor_) {
00201
00202 v.push_back(storage_);
00203 }
00204 return ret;
00205 }
00206
00207 double
00208 SingleInvoker::retToDouble(const edm::ObjectWithDict & o) const {
00209 if (!ExpressionVar::isValidReturnType(retType_)) {
00210 throwFailedConversion(o);
00211 }
00212 return ExpressionVar::objToDouble(o, retType_);
00213 }
00214
00215 void
00216 SingleInvoker::throwFailedConversion(const edm::ObjectWithDict & o) const {
00217 throw edm::Exception(edm::errors::Configuration)
00218 << "member \"" << invokers_.back().methodName()
00219 << "\" return type is \"" << invokers_.back().returnTypeName()
00220 << "\" retured a \"" << o.typeOf().qualifiedName()
00221 << "\" which is not convertible to double.";
00222 }