CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 #include "CommonTools/Utils/src/ExpressionVar.h"
00002 #include "Reflex/Object.h"
00003 #include <Reflex/Builder/NewDelFunctions.h>
00004 #include <map>
00005 #include <assert.h>
00006 using namespace reco::parser;
00007 using namespace Reflex;
00008 using namespace std;
00009 
00010 ExpressionVar::ExpressionVar(const vector<MethodInvoker>& methods, method::TypeCode retType) : 
00011   methods_(methods), retType_(retType) { 
00012     initObjects_();
00013 }
00014 
00015 ExpressionVar::ExpressionVar(const ExpressionVar &other) :
00016   methods_(other.methods_), retType_(other.retType_) { 
00017     initObjects_();
00018 }
00019 
00020 ExpressionVar::~ExpressionVar() {
00021     for(std::vector<Reflex::Object>::iterator it = objects_.begin(); it != objects_.end(); ++it) {
00022         delStorage(*it);
00023     }
00024     objects_.clear();
00025 }
00026 
00027 void
00028 ExpressionVar::delStorage(Reflex::Object &obj) {
00029     if (obj.Address() != 0) {
00030         if (obj.TypeOf().IsPointer() || obj.TypeOf().IsReference()) {
00031             // just delete a void *, as that's what it was
00032             void **p = static_cast<void **>(obj.Address());
00033             delete p;
00034         } else {
00035             //std::cout << "Calling Destruct on a " << obj.TypeOf().Name(QUALIFIED) << std::endl;
00036             obj.TypeOf().Deallocate(obj.Address());
00037         }
00038     }
00039 }
00040 
00041 void ExpressionVar::initObjects_() {
00042     objects_.resize(methods_.size());
00043     std::vector<MethodInvoker>::const_iterator it = methods_.begin(), ed = methods_.end();
00044     std::vector<Reflex::Object>::iterator itobj = objects_.begin();
00045     for (; it != ed; ++it, ++itobj) {
00046         needsDestructor_.push_back(makeStorage(*itobj, it->method()));
00047     }
00048 }
00049 
00050 bool
00051 ExpressionVar::makeStorage(Reflex::Object &obj, const Reflex::Member &member) {
00052     bool ret = false;
00053     static Type tVoid = Type::ByName("void");
00054     if (member.IsFunctionMember()) {
00055         Reflex::Type retType = member.TypeOf().ReturnType();
00056         //remove any typedefs if any. If we do not do this it appears that we get a memory leak
00057         // because typedefs do not have 'destructors'
00058         retType = retType.FinalType();
00059         if (retType == tVoid) {
00060             obj = Reflex::Object(tVoid);
00061         } else if (retType.IsPointer() || retType.IsReference()) {
00062             // in this case, I have to allocate a void *, not an object!
00063             obj = Reflex::Object(retType, new void *);
00064         } else {
00065             obj = Reflex::Object(retType, retType.Allocate());
00066             ret = retType.IsClass();
00067             //std::cout << "ExpressionVar: reserved memory at "  << obj.Address() << " for a " << retType.Name(QUALIFIED) << " returned by " << member.Name() << std::endl;
00068         }
00069     } else { // no alloc, we don't need it
00070         obj = Reflex::Object();
00071     }
00072     return ret;
00073 }
00074 
00075 bool ExpressionVar::isValidReturnType(method::TypeCode retType)
00076 {
00077    using namespace method;
00078    bool ret = false;
00079    switch(retType) {
00080       case(doubleType) : ret = true; break;
00081       case(floatType ) : ret = true; break;
00082       case(intType   ) : ret = true; break;
00083       case(uIntType  ) : ret = true; break;
00084       case(shortType ) : ret = true; break;
00085       case(uShortType) : ret = true; break;
00086       case(longType  ) : ret = true; break;
00087       case(uLongType ) : ret = true; break;
00088       case(charType  ) : ret = true; break;
00089       case(uCharType ) : ret = true; break;
00090       case(boolType  ) : ret = true; break;
00091       case(enumType  ) : ret = true; break;
00092       case(invalid):
00093       default:
00094         break;
00095    }
00096    return ret;
00097 }
00098 
00099 double ExpressionVar::value(const Object & o) const {
00100   Object ro = o;
00101   std::vector<MethodInvoker>::const_iterator itm, end = methods_.end();
00102   std::vector<Reflex::Object>::iterator      ito;
00103   for(itm = methods_.begin(), ito = objects_.begin(); itm != end; ++itm, ++ito) {
00104       ro = itm->invoke(ro, *ito);
00105   }
00106   double ret = objToDouble(ro, retType_);
00107   std::vector<Reflex::Object>::reverse_iterator rito, rend = objects_.rend();;
00108   std::vector<bool>::const_reverse_iterator ritb;
00109   for(rito = objects_.rbegin(), ritb = needsDestructor_.rbegin(); rito != rend; ++rito, ++ritb) {
00110       if (*ritb) rito->TypeOf().Destruct(rito->Address(), false);
00111   }
00112   return ret;
00113 }
00114 
00115 double
00116 ExpressionVar::objToDouble(const Reflex::Object &obj, method::TypeCode type) {
00117   using namespace method;
00118   void * addr = obj.Address();
00119   double ret = 0;
00120   switch(type) {
00121   case(doubleType) : ret = * static_cast<double         *>(addr); break;
00122   case(floatType ) : ret = * static_cast<float          *>(addr); break;
00123   case(intType   ) : ret = * static_cast<int            *>(addr); break;
00124   case(uIntType  ) : ret = * static_cast<unsigned int   *>(addr); break;
00125   case(shortType ) : ret = * static_cast<short          *>(addr); break;
00126   case(uShortType) : ret = * static_cast<unsigned short *>(addr); break;
00127   case(longType  ) : ret = * static_cast<long           *>(addr); break;
00128   case(uLongType ) : ret = * static_cast<unsigned long  *>(addr); break;
00129   case(charType  ) : ret = * static_cast<char           *>(addr); break;
00130   case(uCharType ) : ret = * static_cast<unsigned char  *>(addr); break;
00131   case(boolType  ) : ret = * static_cast<bool           *>(addr); break;
00132   case(enumType  ) : ret = * static_cast<int            *>(addr); break;
00133   default:
00134   assert(false);
00135   };
00136   return ret;
00137 }
00138 
00139 void ExpressionVar::trueDelete(Reflex::Object & obj) {
00140      static std::map<void *, Reflex::NewDelFunctions *> deleters_;
00141      void * reflexTypeId = obj.TypeOf().Id();
00142      std::map<void *, Reflex::NewDelFunctions *>::iterator match = deleters_.find(reflexTypeId);
00143      if (match == deleters_.end()) {
00144          Reflex::NewDelFunctions *ptr;
00145          Reflex::Object newDel(Reflex::Type::ByTypeInfo(typeid(ptr)), &ptr);
00146          obj.Invoke("__getNewDelFunctions", &newDel);
00147          match = deleters_.insert(std::make_pair(reflexTypeId, ptr)).first;   
00148      }
00149      (*match->second->fDelete)(obj.Address());
00150 }
00151 
00152 ExpressionLazyVar::ExpressionLazyVar(const std::vector<LazyInvoker> & methods) :
00153     methods_(methods)
00154 {
00155 }
00156 
00157 ExpressionLazyVar::~ExpressionLazyVar()
00158 {
00159 }
00160 
00161 double
00162 ExpressionLazyVar::value(const Reflex::Object & o) const {
00163     std::vector<LazyInvoker>::const_iterator it, ed = methods_.end()-1;
00164     Reflex::Object ro = o;
00165     for (it = methods_.begin(); it < ed; ++it) {
00166         ro = it->invoke(ro, objects_);
00167     }
00168     double ret = it->invokeLast(ro, objects_);
00169     std::vector<Reflex::Object>::reverse_iterator rit, red = objects_.rend();
00170     for (rit = objects_.rbegin(); rit != red; ++rit) {
00171         rit->TypeOf().Destruct(rit->Address(), false);
00172     }
00173     objects_.clear();
00174     return ret;
00175 }
00176