CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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 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   /*std::cout << "Booking " << method_.Name() 
00018             << " from " << method_.DeclaringType().Name() 
00019             << " with " << args_.size() << " arguments"
00020             << " (were " << ints.size() << ")"
00021             << std::endl;*/
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   /*std::cout << "Invoking " << method_.Name() 
00047             << " from " << method_.DeclaringType().Name(QUALIFIED) 
00048             << " on an instance of " << o.DynamicType().Name(QUALIFIED) 
00049             << " at " << o.Address()
00050             << " with " << args_.size() << " arguments"
00051             << std::endl; */
00052   Type retType;
00053   if(isFunction_) {
00054      method_.Invoke(o, &ret, args_);
00055      retType = method_.TypeOf().ReturnType(); // this is correct, it takes pointers and refs into account
00056   } else {
00057      ret = method_.Get(o);
00058      retType = method_.TypeOf();
00059   }
00060   void * addr = ret.Address(); 
00061   //std::cout << "Stored result of " <<  method_.Name() << " (type " << method_.TypeOf().ReturnType().Name(QUALIFIED) << ") at " << addr << std::endl;
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   //std::cout << "Return type is " << retType.Name(QUALIFIED) << std::endl;
00067    
00068   if(retType.IsPointer() || retType.IsReference()) { // both need (void **)->(void *) conversion
00069       if (retType.IsPointer()) {
00070         retType = retType.ToType(); // for Pointers, I get the real type this way
00071       } else {
00072         retType = Type(retType, 0); // strip cv & ref flags
00073       }
00074       while (retType.IsTypedef()) retType = retType.ToType();
00075       ret = Object(retType, *static_cast<void **>(addr));
00076       //std::cout << "Now type is " << retType.Name(QUALIFIED) << std::endl;
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     //std::cout << "LazyInvoker for " << name_ << " called on type " << type.Name(QUALIFIED|SCOPED) << std::endl;
00100     SingleInvokerPtr & invoker = invokers_[type.Id()];
00101     if (!invoker) {
00102         //std::cout << "  Making new invoker for " << name_ << " on type " << type.Name(QUALIFIED|SCOPED) << std::endl;
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     //std::cerr  << "SingleInvoker on type " <<  type.Name(QUALIFIED|SCOPED) << ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") << std::endl;
00144     storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, invokers_.front().method());
00145     retType_ = reco::typeCode(typeStack[1]); // typeStack[0] = type of self, typeStack[1] = type of ret
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     /* std::cerr << "[SingleInvoker::invoke] member " << invokers_.front().method().Name(QUALIFIED|SCOPED) << 
00157                                        " of type " << o.TypeOf().Name(QUALIFIED|SCOPED) <<
00158                                        (!isRefGet_ ? " is one shot" : " needs another round") << std::endl; */
00159     pair<Object,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00160     if (storageNeedsDestructor_) {
00161         //std::cout << "Storage type: " << storage_.TypeOf().Name(QUALIFIED|SCOPED) << ", I have to call the destructor." << std::endl;
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 }