Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:19

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