File indexing completed on 2023-10-25 09:36:17
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
0065 void** p = static_cast<void**>(obj.address());
0066 delete p;
0067 } else {
0068
0069
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
0081 obj = edm::ObjectWithDict(retType, new void*);
0082 } else {
0083 obj = edm::ObjectWithDict(retType, retType.allocate());
0084 ret = retType.isClass();
0085
0086
0087
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
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 }