CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/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().name(edm::TypeNameHandling::Qualified) << 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        //remove any typedefs if any. If we do not do this it appears that we get a memory leak
00048        // because typedefs do not have 'destructors'
00049        if(it->isFunction()) {
00050           edm::TypeWithDict retType = it->method().returnType().finalType();
00051           needsDestructor_.push_back(makeStorage(*itobj, retType));
00052        } else {
00053           *itobj = edm::ObjectWithDict();
00054           needsDestructor_.push_back(false);
00055        }
00056     }
00057 }
00058 
00059 bool
00060 ExpressionVar::makeStorage(edm::ObjectWithDict &obj, const edm::TypeWithDict &retType) {
00061     bool ret = false;
00062     static edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void"));
00063     if (retType == tVoid) {
00064         obj = edm::ObjectWithDict(tVoid);
00065     } else if (retType.isPointer() || retType.isReference()) {
00066         // in this case, I have to allocate a void *, not an object!
00067         obj = edm::ObjectWithDict(retType, new void *);
00068     } else {
00069         obj = edm::ObjectWithDict(retType, retType.allocate());
00070         ret = retType.isClass();
00071         //std::cout << "ExpressionVar: reserved memory at "  << obj.address() << " for a " << retType.name(edm::TypeNameHandling::Qualified) << " returned by " << member.name() << std::endl;
00072     }
00073     return ret;
00074 }
00075 
00076 bool ExpressionVar::isValidReturnType(method::TypeCode retType)
00077 {
00078    using namespace method;
00079    bool ret = false;
00080    switch(retType) {
00081       case(doubleType) : ret = true; break;
00082       case(floatType ) : ret = true; break;
00083       case(intType   ) : ret = true; break;
00084       case(uIntType  ) : ret = true; break;
00085       case(shortType ) : ret = true; break;
00086       case(uShortType) : ret = true; break;
00087       case(longType  ) : ret = true; break;
00088       case(uLongType ) : ret = true; break;
00089       case(charType  ) : ret = true; break;
00090       case(uCharType ) : ret = true; break;
00091       case(boolType  ) : ret = true; break;
00092       case(enumType  ) : ret = true; break;
00093       case(invalid):
00094       default:
00095         break;
00096    }
00097    return ret;
00098 }
00099 
00100 double ExpressionVar::value(const edm::ObjectWithDict & o) const {
00101   edm::ObjectWithDict ro = o;
00102   std::vector<MethodInvoker>::const_iterator itm, end = methods_.end();
00103   std::vector<edm::ObjectWithDict>::iterator      ito;
00104   for(itm = methods_.begin(), ito = objects_.begin(); itm != end; ++itm, ++ito) {
00105       ro = itm->invoke(ro, *ito);
00106   }
00107   double ret = objToDouble(ro, retType_);
00108   std::vector<edm::ObjectWithDict>::reverse_iterator rito, rend = objects_.rend();;
00109   std::vector<bool>::const_reverse_iterator ritb;
00110   for(rito = objects_.rbegin(), ritb = needsDestructor_.rbegin(); rito != rend; ++rito, ++ritb) {
00111       if (*ritb) rito->typeOf().destruct(rito->address(), false);
00112   }
00113   return ret;
00114 }
00115 
00116 double
00117 ExpressionVar::objToDouble(const edm::ObjectWithDict &obj, method::TypeCode type) {
00118   using namespace method;
00119   void * addr = obj.address();
00120   double ret = 0;
00121   switch(type) {
00122   case(doubleType) : ret = * static_cast<double         *>(addr); break;
00123   case(floatType ) : ret = * static_cast<float          *>(addr); break;
00124   case(intType   ) : ret = * static_cast<int            *>(addr); break;
00125   case(uIntType  ) : ret = * static_cast<unsigned int   *>(addr); break;
00126   case(shortType ) : ret = * static_cast<short          *>(addr); break;
00127   case(uShortType) : ret = * static_cast<unsigned short *>(addr); break;
00128   case(longType  ) : ret = * static_cast<long           *>(addr); break;
00129   case(uLongType ) : ret = * static_cast<unsigned long  *>(addr); break;
00130   case(charType  ) : ret = * static_cast<char           *>(addr); break;
00131   case(uCharType ) : ret = * static_cast<unsigned char  *>(addr); break;
00132   case(boolType  ) : ret = * static_cast<bool           *>(addr); break;
00133   case(enumType  ) : ret = * static_cast<int            *>(addr); break;
00134   default:
00135   assert(false);
00136   };
00137   return ret;
00138 }
00139 
00140 ExpressionLazyVar::ExpressionLazyVar(const std::vector<LazyInvoker> & methods) :
00141     methods_(methods)
00142 {
00143 }
00144 
00145 ExpressionLazyVar::~ExpressionLazyVar()
00146 {
00147 }
00148 
00149 double
00150 ExpressionLazyVar::value(const edm::ObjectWithDict & o) const {
00151     std::vector<LazyInvoker>::const_iterator it, ed = methods_.end()-1;
00152     edm::ObjectWithDict ro = o;
00153     for (it = methods_.begin(); it < ed; ++it) {
00154         ro = it->invoke(ro, objects_);
00155     }
00156     double ret = it->invokeLast(ro, objects_);
00157     std::vector<edm::ObjectWithDict>::reverse_iterator rit, red = objects_.rend();
00158     for (rit = objects_.rbegin(); rit != red; ++rit) {
00159         rit->typeOf().destruct(rit->address(), false);
00160     }
00161     objects_.clear();
00162     return ret;
00163 }
00164