CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CommonTools/Utils/src/MethodInvoker.cc

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 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   /*std::cout << "Booking " << methodName() 
00017             << " from " << method_.declaringType().name() 
00018             << " with " << args_.size() << " arguments"
00019             << " (were " << ints.size() << ")"
00020             << std::endl;*/
00021 }
00022 
00023 MethodInvoker::MethodInvoker(const edm::MemberWithDict & member) :
00024   method_(), member_(member), ints_(), isFunction_(false)
00025 { 
00026   setArgs();
00027   /*std::cout << "Booking " << methodName() 
00028             << " from " << member_.declaringType().name() 
00029             << " with " << args_.size() << " arguments"
00030             << " (were " << ints.size() << ")"
00031             << std::endl;*/
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      /*std::cout << "Invoking " << methodName() 
00076             << " from " << method_.declaringType().qualifiedName() 
00077             << " on an instance of " << o.dynamicType().qualifiedName() 
00078             << " at " << o.address()
00079             << " with " << args_.size() << " arguments"
00080             << std::endl; */
00081      method_.invoke(o, &ret, args_);
00082      retType = method_.finalReturnType(); // this is correct, it takes pointers and refs into account
00083   } else {
00084      /*std::cout << "Invoking " << methodName() 
00085             << " from " << member_.declaringType().qualifiedName() 
00086             << " on an instance of " << o.dynamicType().qualifiedName() 
00087             << " at " << o.address()
00088             << " with " << args_.size() << " arguments"
00089             << std::endl; */
00090      ret = member_.get(o);
00091      retType = member_.typeOf();
00092   }
00093   void * addr = ret.address(); 
00094   //std::cout << "Stored result of " <<  methodName() << " (type " << returnTypeName() << ") at " << addr << std::endl;
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   //std::cout << "Return type is " << retType.qualifiedName() << std::endl;
00101    
00102   if(retType.isPointer() || retType.isReference()) { // both need (void **)->(void *) conversion
00103       if (retType.isPointer()) {
00104         retType = retType.toType(); // for Pointers, I get the real type this way
00105       } else {
00106         retType = edm::TypeWithDict(retType, 0L); // strip cv & ref flags
00107       }
00108       ret = edm::ObjectWithDict(retType, *static_cast<void **>(addr));
00109       //std::cout << "Now type is " << retType.qualifiedName() << std::endl;
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     //std::cout << "LazyInvoker for " << name_ << " called on type " << type.qualifiedName() << std::endl;
00134     SingleInvokerPtr & invoker = invokers_[edm::TypeID(type.id())];
00135     if (!invoker) {
00136         //std::cout << "  Making new invoker for " << name_ << " on type " << type.qualifiedName() << std::endl;
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     //std::cerr  << "SingleInvoker on type " <<  type.qualifiedName() << ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") << std::endl;
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]); // typeStack[0] = type of self, typeStack[1] = type of ret
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     /* std::cerr << "[SingleInvoker::invoke] member " << invokers_.front().method().qualifiedName() << 
00197                                        " of type " << o.typeOf().qualifiedName() <<
00198                                        (!isRefGet_ ? " is one shot" : " needs another round") << std::endl; */
00199     pair<edm::ObjectWithDict,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00200     if (storageNeedsDestructor_) {
00201         //std::cout << "Storage type: " << storage_.typeOf().qualifiedName() << ", I have to call the destructor." << std::endl;
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 }