Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-17 23:10:25

0001 #include "CommonTools/Utils/src/ExpressionVar.h"
0002 #include "CommonTools/Utils/interface/MethodInvoker.h"
0003 
0004 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0005 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0006 #include "FWCore/Reflection/interface/MemberWithDict.h"
0007 #include "FWCore/Reflection/interface/TypeWithDict.h"
0008 
0009 #include <cassert>
0010 #include <map>
0011 
0012 using namespace reco::parser;
0013 using namespace std;
0014 
0015 void ExpressionVar::initObjects_() {
0016   objects_.resize(methods_.size());
0017   std::vector<edm::ObjectWithDict>::iterator IO = objects_.begin();
0018   for (std::vector<MethodInvoker>::const_iterator I = methods_.begin(), E = methods_.end(); I != E; ++IO, ++I) {
0019     if (I->isFunction()) {
0020       edm::TypeWithDict retType = I->method().finalReturnType();
0021       needsDestructor_.push_back(makeStorage(*IO, retType));
0022     } else {
0023       *IO = edm::ObjectWithDict();
0024       needsDestructor_.push_back(false);
0025     }
0026   }
0027 }
0028 
0029 ExpressionVar::ExpressionVar(const vector<MethodInvoker>& methods, method::TypeCode retType)
0030     : methods_(methods), retType_(retType) {
0031   initObjects_();
0032 }
0033 
0034 ExpressionVar::ExpressionVar(const ExpressionVar& rhs) : methods_(rhs.methods_), retType_(rhs.retType_) {
0035   initObjects_();
0036 }
0037 
0038 ExpressionVar::~ExpressionVar() {
0039   for (std::vector<edm::ObjectWithDict>::iterator I = objects_.begin(), E = objects_.end(); I != E; ++I) {
0040     delStorage(*I);
0041   }
0042   objects_.clear();
0043 }
0044 
0045 void ExpressionVar::delStorage(edm::ObjectWithDict& obj) {
0046   if (!obj.address()) {
0047     return;
0048   }
0049   if (obj.typeOf().isPointer() || obj.typeOf().isReference()) {
0050     // just delete a void*, as that's what it was
0051     void** p = static_cast<void**>(obj.address());
0052     delete p;
0053   } else {
0054     //std::cout << "Calling Destruct on a " <<
0055     //  obj.typeOf().qualifiedName() << std::endl;
0056     obj.typeOf().deallocate(obj.address());
0057   }
0058 }
0059 
0060 bool ExpressionVar::makeStorage(edm::ObjectWithDict& obj, const edm::TypeWithDict& retType) {
0061   static const edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void"));
0062   bool ret = false;
0063   if (retType == tVoid) {
0064     obj = edm::ObjectWithDict::byType(tVoid);
0065   } else if (retType.isPointer() || retType.isReference()) {
0066     // in this case, I have to allocate a void*, not an object!
0067     obj = edm::ObjectWithDict(retType, new void*);
0068   } else {
0069     obj = edm::ObjectWithDict(retType, retType.allocate());
0070     ret = retType.isClass();
0071     //std::cout << "ExpressionVar: reserved memory at "  << obj.address() <<
0072     //  " for a " << retType.qualifiedName() << " returned by " <<
0073     //  member.name() << std::endl;
0074   }
0075   return ret;
0076 }
0077 
0078 bool ExpressionVar::isValidReturnType(method::TypeCode retType) {
0079   using namespace method;
0080   bool ret = false;
0081   switch (retType) {
0082     case (doubleType):
0083       ret = true;
0084       break;
0085     case (floatType):
0086       ret = true;
0087       break;
0088     case (intType):
0089       ret = true;
0090       break;
0091     case (uIntType):
0092       ret = true;
0093       break;
0094     case (shortType):
0095       ret = true;
0096       break;
0097     case (uShortType):
0098       ret = true;
0099       break;
0100     case (longType):
0101       ret = true;
0102       break;
0103     case (uLongType):
0104       ret = true;
0105       break;
0106     case (charType):
0107       ret = true;
0108       break;
0109     case (uCharType):
0110       ret = true;
0111       break;
0112     case (boolType):
0113       ret = true;
0114       break;
0115     case (enumType):
0116       ret = true;
0117       break;
0118     case (invalid):
0119     default:
0120       break;
0121   }
0122   return ret;
0123 }
0124 
0125 double ExpressionVar::value(const edm::ObjectWithDict& obj) const {
0126   edm::ObjectWithDict val(obj);
0127   std::vector<edm::ObjectWithDict>::iterator IO = objects_.begin();
0128   for (std::vector<MethodInvoker>::const_iterator I = methods_.begin(), E = methods_.end(); I != E; ++I, ++IO) {
0129     val = I->invoke(val, *IO);
0130   }
0131   double ret = objToDouble(val, retType_);
0132   std::vector<bool>::const_reverse_iterator RIB = needsDestructor_.rbegin();
0133   for (std::vector<edm::ObjectWithDict>::reverse_iterator RI = objects_.rbegin(), RE = objects_.rend(); RI != RE;
0134        ++RIB, ++RI) {
0135     if (*RIB) {
0136       RI->destruct(false);
0137     }
0138   }
0139   return ret;
0140 }
0141 
0142 double ExpressionVar::objToDouble(const edm::ObjectWithDict& obj, method::TypeCode type) {
0143   using namespace method;
0144   void* addr = obj.address();
0145   double ret = 0.0;
0146   switch (type) {
0147     case doubleType:
0148       ret = *static_cast<double*>(addr);
0149       break;
0150     case floatType:
0151       ret = *static_cast<float*>(addr);
0152       break;
0153     case intType:
0154       ret = *static_cast<int*>(addr);
0155       break;
0156     case uIntType:
0157       ret = *static_cast<unsigned int*>(addr);
0158       break;
0159     case shortType:
0160       ret = *static_cast<short*>(addr);
0161       break;
0162     case uShortType:
0163       ret = *static_cast<unsigned short*>(addr);
0164       break;
0165     case longType:
0166       ret = *static_cast<long*>(addr);
0167       break;
0168     case uLongType:
0169       ret = *static_cast<unsigned long*>(addr);
0170       break;
0171     case charType:
0172       ret = *static_cast<char*>(addr);
0173       break;
0174     case uCharType:
0175       ret = *static_cast<unsigned char*>(addr);
0176       break;
0177     case boolType:
0178       ret = *static_cast<bool*>(addr);
0179       break;
0180     case enumType:
0181       ret = *static_cast<int*>(addr);
0182       break;
0183     default:
0184       //FIXME: Error not caught in production build!
0185       assert(false && "objToDouble: invalid type!");
0186       break;
0187   };
0188   return ret;
0189 }
0190 
0191 ExpressionLazyVar::ExpressionLazyVar(const std::vector<LazyInvoker>& methods) : methods_(methods) {}
0192 
0193 ExpressionLazyVar::~ExpressionLazyVar() {}
0194 
0195 double ExpressionLazyVar::value(const edm::ObjectWithDict& o) const {
0196   edm::ObjectWithDict val = o;
0197   std::vector<LazyInvoker>::const_iterator I = methods_.begin();
0198   std::vector<LazyInvoker>::const_iterator E = methods_.end() - 1;
0199   for (; I < E; ++I) {
0200     val = I->invoke(val, objects_);
0201   }
0202   double ret = I->invokeLast(val, objects_);
0203   for (std::vector<edm::ObjectWithDict>::reverse_iterator RI = objects_.rbegin(), RE = objects_.rend(); RI != RE;
0204        ++RI) {
0205     RI->destruct(false);
0206   }
0207   objects_.clear();
0208   return ret;
0209 }