Go to the documentation of this file.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 Reflex;
00011 using namespace std;
00012
00013 MethodInvoker::MethodInvoker(const Member & method, const vector<AnyMethodArgument> & ints) :
00014 method_(method), ints_(ints), isFunction_(method.IsFunctionMember())
00015 {
00016 setArgs();
00017
00018
00019
00020
00021
00022 }
00023
00024 MethodInvoker::MethodInvoker(const MethodInvoker & other) :
00025 method_(other.method_), ints_(other.ints_), isFunction_(other.isFunction_) {
00026 setArgs();
00027 }
00028
00029 MethodInvoker & MethodInvoker::operator=(const MethodInvoker & other) {
00030 method_ = other.method_;
00031 ints_ = other.ints_;
00032 isFunction_ = other.isFunction_;
00033 setArgs();
00034 return *this;
00035 }
00036
00037 void MethodInvoker::setArgs() {
00038 for(size_t i = 0; i < ints_.size(); ++i) {
00039 args_.push_back( boost::apply_visitor( AnyMethodArgument2VoidPtr(), ints_[i] ) );
00040 }
00041 }
00042
00043 Reflex::Object
00044 MethodInvoker::invoke(const Object & o, Reflex::Object &retstore) const {
00045 Reflex::Object ret = retstore;
00046
00047
00048
00049
00050
00051
00052 Type retType;
00053 if(isFunction_) {
00054 method_.Invoke(o, &ret, args_);
00055 retType = method_.TypeOf().ReturnType();
00056 } else {
00057 ret = method_.Get(o);
00058 retType = method_.TypeOf();
00059 }
00060 void * addr = ret.Address();
00061
00062 if(addr==0)
00063 throw edm::Exception(edm::errors::InvalidReference)
00064 << "method \"" << method_.Name() << "\" called with " << args_.size()
00065 << " arguments returned a null pointer ";
00066
00067
00068 if(retType.IsPointer() || retType.IsReference()) {
00069 if (retType.IsPointer()) {
00070 retType = retType.ToType();
00071 } else {
00072 retType = Type(retType, 0);
00073 }
00074 while (retType.IsTypedef()) retType = retType.ToType();
00075 ret = Object(retType, *static_cast<void **>(addr));
00076
00077 }
00078 if(!ret)
00079 throw edm::Exception(edm::errors::Configuration)
00080 << "method \"" << method_.Name()
00081 << "\" returned void invoked on object of type \""
00082 << o.TypeOf().Name(QUALIFIED) << "\"\n";
00083 return ret;
00084 }
00085
00086 LazyInvoker::LazyInvoker(const std::string &name, const std::vector<AnyMethodArgument> & args) :
00087 name_(name),
00088 argsBeforeFixups_(args)
00089 {
00090 }
00091
00092 LazyInvoker::~LazyInvoker()
00093 {
00094 }
00095
00096 const SingleInvoker &
00097 LazyInvoker::invoker(const Reflex::Type & type) const
00098 {
00099
00100 SingleInvokerPtr & invoker = invokers_[type.Id()];
00101 if (!invoker) {
00102
00103 invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_));
00104 }
00105 return * invoker;
00106 }
00107
00108 Object
00109 LazyInvoker::invoke(const Reflex::Object & o, std::vector<Reflex::Object> &v) const
00110 {
00111 pair<Object, bool> ret(o,false);
00112 do {
00113 Type type = ret.first.TypeOf();
00114 if (type.IsClass()) type = ret.first.DynamicType();
00115 ret = invoker(type).invoke(Object(type, ret.first.Address()), v);
00116 } while (ret.second == false);
00117 return ret.first;
00118 }
00119
00120 double
00121 LazyInvoker::invokeLast(const Reflex::Object & o, std::vector<Reflex::Object> &v) const
00122 {
00123 pair<Object, bool> ret(o,false);
00124 const SingleInvoker *i = 0;
00125 do {
00126 Type type = ret.first.TypeOf();
00127 if (type.IsClass()) type = ret.first.DynamicType();
00128 i = & invoker(type);
00129 ret = i->invoke(Object(type, ret.first.Address()), v);
00130 } while (ret.second == false);
00131 return i->retToDouble(ret.first);
00132 }
00133
00134 SingleInvoker::SingleInvoker(const Reflex::Type &type,
00135 const std::string &name,
00136 const std::vector<AnyMethodArgument> &args)
00137 {
00138 TypeStack typeStack(1, type);
00139 LazyMethodStack dummy;
00140 MethodArgumentStack dummy2;
00141 MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
00142 isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
00143
00144 storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, invokers_.front().method());
00145 retType_ = reco::typeCode(typeStack[1]);
00146 }
00147
00148 SingleInvoker::~SingleInvoker()
00149 {
00150 ExpressionVar::delStorage(storage_);
00151 }
00152
00153 pair<Object,bool>
00154 SingleInvoker::invoke(const Reflex::Object & o, std::vector<Reflex::Object> &v) const
00155 {
00156
00157
00158
00159 pair<Object,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00160 if (storageNeedsDestructor_) {
00161
00162 v.push_back(storage_);
00163 }
00164 return ret;
00165 }
00166
00167 double
00168 SingleInvoker::retToDouble(const Reflex::Object & o) const {
00169 if (!ExpressionVar::isValidReturnType(retType_)) {
00170 throwFailedConversion(o);
00171 }
00172 return ExpressionVar::objToDouble(o, retType_);
00173 }
00174
00175 void
00176 SingleInvoker::throwFailedConversion(const Reflex::Object & o) const {
00177 throw edm::Exception(edm::errors::Configuration)
00178 << "member \"" << invokers_.back().method().Name(QUALIFIED)
00179 << "\" return type is \"" << invokers_.back().method().TypeOf().Name(QUALIFIED)
00180 << "\" retured a \"" << o.TypeOf().Name(QUALIFIED)
00181 << "\" which is not convertible to double.";
00182 }