CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/CommonTools/Utils/src/ExpressionVar.cc

Go to the documentation of this file.
00001 #include "CommonTools/Utils/src/ExpressionVar.h"
00002 #include "FWCore/Utilities/interface/ObjectWithDict.h"
00003 #include "FWCore/Utilities/interface/FunctionWithDict.h"
00004 #include "FWCore/Utilities/interface/MemberWithDict.h"
00005 #include "FWCore/Utilities/interface/TypeWithDict.h"
00006 #include <map>
00007 #include <assert.h>
00008 using namespace reco::parser;
00009 using namespace std;
00010 
00011 ExpressionVar::ExpressionVar(const vector<MethodInvoker>& methods, method::TypeCode retType) : 
00012   methods_(methods), retType_(retType) { 
00013     initObjects_();
00014 }
00015 
00016 ExpressionVar::ExpressionVar(const ExpressionVar &other) :
00017   methods_(other.methods_), retType_(other.retType_) { 
00018     initObjects_();
00019 }
00020 
00021 ExpressionVar::~ExpressionVar() {
00022     for(std::vector<edm::ObjectWithDict>::iterator it = objects_.begin(); it != objects_.end(); ++it) {
00023         delStorage(*it);
00024     }
00025     objects_.clear();
00026 }
00027 
00028 void
00029 ExpressionVar::delStorage(edm::ObjectWithDict &obj) {
00030     if (obj.address() != 0) {
00031         if (obj.typeOf().isPointer() || obj.typeOf().isReference()) {
00032             // just delete a void *, as that's what it was
00033             void **p = static_cast<void **>(obj.address());
00034             delete p;
00035         } else {
00036             //std::cout << "Calling Destruct on a " << obj.typeOf().qualifiedName() << std::endl;
00037             obj.typeOf().deallocate(obj.address());
00038         }
00039     }
00040 }
00041 
00042 void ExpressionVar::initObjects_() {
00043     objects_.resize(methods_.size());
00044     std::vector<MethodInvoker>::const_iterator it = methods_.begin(), ed = methods_.end();
00045     std::vector<edm::ObjectWithDict>::iterator itobj = objects_.begin();
00046     for (; it != ed; ++it, ++itobj) {
00047        if(it->isFunction()) {
00048           edm::TypeWithDict retType = it->method().finalReturnType();
00049           needsDestructor_.push_back(makeStorage(*itobj, retType));
00050        } else {
00051           *itobj = edm::ObjectWithDict();
00052           needsDestructor_.push_back(false);
00053        }
00054     }
00055 }
00056 
00057 bool
00058 ExpressionVar::makeStorage(edm::ObjectWithDict &obj, const edm::TypeWithDict &retType) {
00059     bool ret = false;
00060     static edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void"));
00061     if (retType == tVoid) {
00062         obj = edm::ObjectWithDict::byType(tVoid);
00063     } else if (retType.isPointer() || retType.isReference()) {
00064         // in this case, I have to allocate a void *, not an object!
00065         obj = edm::ObjectWithDict(retType, new void *);
00066     } else {
00067         obj = edm::ObjectWithDict(retType, retType.allocate());
00068         ret = retType.isClass();
00069         //std::cout << "ExpressionVar: reserved memory at "  << obj.address() << " for a " << retType.qualifiedName() << " returned by " << member.name() << std::endl;
00070     }
00071     return ret;
00072 }
00073 
00074 bool ExpressionVar::isValidReturnType(method::TypeCode retType)
00075 {
00076    using namespace method;
00077    bool ret = false;
00078    switch(retType) {
00079       case(doubleType) : ret = true; break;
00080       case(floatType ) : ret = true; break;
00081       case(intType   ) : ret = true; break;
00082       case(uIntType  ) : ret = true; break;
00083       case(shortType ) : ret = true; break;
00084       case(uShortType) : ret = true; break;
00085       case(longType  ) : ret = true; break;
00086       case(uLongType ) : ret = true; break;
00087       case(charType  ) : ret = true; break;
00088       case(uCharType ) : ret = true; break;
00089       case(boolType  ) : ret = true; break;
00090       case(enumType  ) : ret = true; break;
00091       case(invalid):
00092       default:
00093         break;
00094    }
00095    return ret;
00096 }
00097 
00098 double ExpressionVar::value(const edm::ObjectWithDict & o) const {
00099   edm::ObjectWithDict ro = o;
00100   std::vector<MethodInvoker>::const_iterator itm, end = methods_.end();
00101   std::vector<edm::ObjectWithDict>::iterator      ito;
00102   for(itm = methods_.begin(), ito = objects_.begin(); itm != end; ++itm, ++ito) {
00103       ro = itm->invoke(ro, *ito);
00104   }
00105   double ret = objToDouble(ro, retType_);
00106   std::vector<edm::ObjectWithDict>::reverse_iterator rito, rend = objects_.rend();;
00107   std::vector<bool>::const_reverse_iterator ritb;
00108   for(rito = objects_.rbegin(), ritb = needsDestructor_.rbegin(); rito != rend; ++rito, ++ritb) {
00109       if (*ritb) rito->typeOf().destruct(rito->address(), false);
00110   }
00111   return ret;
00112 }
00113 
00114 double
00115 ExpressionVar::objToDouble(const edm::ObjectWithDict &obj, method::TypeCode type) {
00116   using namespace method;
00117   void * addr = obj.address();
00118   double ret = 0;
00119   switch(type) {
00120   case(doubleType) : ret = * static_cast<double         *>(addr); break;
00121   case(floatType ) : ret = * static_cast<float          *>(addr); break;
00122   case(intType   ) : ret = * static_cast<int            *>(addr); break;
00123   case(uIntType  ) : ret = * static_cast<unsigned int   *>(addr); break;
00124   case(shortType ) : ret = * static_cast<short          *>(addr); break;
00125   case(uShortType) : ret = * static_cast<unsigned short *>(addr); break;
00126   case(longType  ) : ret = * static_cast<long           *>(addr); break;
00127   case(uLongType ) : ret = * static_cast<unsigned long  *>(addr); break;
00128   case(charType  ) : ret = * static_cast<char           *>(addr); break;
00129   case(uCharType ) : ret = * static_cast<unsigned char  *>(addr); break;
00130   case(boolType  ) : ret = * static_cast<bool           *>(addr); break;
00131   case(enumType  ) : ret = * static_cast<int            *>(addr); break;
00132   default:
00133   assert(false);
00134   };
00135   return ret;
00136 }
00137 
00138 ExpressionLazyVar::ExpressionLazyVar(const std::vector<LazyInvoker> & methods) :
00139     methods_(methods)
00140 {
00141 }
00142 
00143 ExpressionLazyVar::~ExpressionLazyVar()
00144 {
00145 }
00146 
00147 double
00148 ExpressionLazyVar::value(const edm::ObjectWithDict & o) const {
00149     std::vector<LazyInvoker>::const_iterator it, ed = methods_.end()-1;
00150     edm::ObjectWithDict ro = o;
00151     for (it = methods_.begin(); it < ed; ++it) {
00152         ro = it->invoke(ro, objects_);
00153     }
00154     double ret = it->invokeLast(ro, objects_);
00155     std::vector<edm::ObjectWithDict>::reverse_iterator rit, red = objects_.rend();
00156     for (rit = objects_.rbegin(); rit != red; ++rit) {
00157         rit->typeOf().destruct(rit->address(), false);
00158     }
00159     objects_.clear();
00160     return ret;
00161 }
00162