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
0051 void** p = static_cast<void**>(obj.address());
0052 delete p;
0053 } else {
0054
0055
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
0067 obj = edm::ObjectWithDict(retType, new void*);
0068 } else {
0069 obj = edm::ObjectWithDict(retType, retType.allocate());
0070 ret = retType.isClass();
0071
0072
0073
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
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 }