00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <ctype.h>
00016 #include <algorithm>
00017
00018 #include "FWCore/Utilities/interface/BaseWithDict.h"
00019 #include "FWCore/Utilities/interface/FunctionWithDict.h"
00020 #include <cstring>
00021
00022
00023 #include "Fireworks/Core/src/FWExpressionValidator.h"
00024 #include "CommonTools/Utils/src/returnType.h"
00025
00026
00027
00028
00029 typedef std::vector<boost::shared_ptr<fireworks::OptionNode> > Options;
00030
00031 namespace fireworks {
00032 template< class T>
00033 struct OptionNodePtrCompare {
00034 bool operator()(const T& iLHS,
00035 const T& iRHS) const
00036 {
00037 return *iLHS < *iRHS;
00038 }
00039 };
00040
00041 template< class T>
00042 struct OptionNodePtrEqual {
00043 bool operator()(const T& iLHS,
00044 const T& iRHS) const
00045 {
00046 return iLHS->description() == iRHS->description();
00047 }
00048 };
00049
00050
00051 class OptionNode {
00052 public:
00053 OptionNode(const edm::FunctionWithDict& );
00054 OptionNode(const std::string& iDescription,
00055 unsigned long iSubstitutionEnd,
00056 const edm::TypeWithDict& iType);
00057
00058 const std::string& description() const {
00059 return m_description;
00060 }
00061 unsigned long substitutionEnd() const {
00062 return m_endOfName;
00063 }
00064 const std::vector<boost::shared_ptr<OptionNode> >& options() const {
00065 if(m_hasSubOptions && m_subOptions.empty()) {
00066 fillOptionForType(m_type, m_subOptions);
00067 std::sort(m_subOptions.begin(),m_subOptions.end(),
00068 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00069 std::vector<boost::shared_ptr<OptionNode> >::iterator it=
00070 std::unique(m_subOptions.begin(),m_subOptions.end(),
00071 fireworks::OptionNodePtrEqual<boost::shared_ptr<OptionNode> >());
00072 m_subOptions.erase(it, m_subOptions.end());
00073
00074 m_hasSubOptions = !m_subOptions.empty();
00075 }
00076 return m_subOptions;
00077 }
00078
00079 bool operator<(const OptionNode& iRHS) const {
00080 return m_description.substr(0,m_endOfName) < iRHS.m_description.substr(0,iRHS.m_endOfName);
00081 }
00082
00083 static void fillOptionForType( const edm::TypeWithDict&,
00084 std::vector<boost::shared_ptr<OptionNode> >& );
00085 private:
00086 edm::TypeWithDict m_type;
00087 mutable std::string m_description;
00088 mutable std::string::size_type m_endOfName;
00089 mutable std::vector<boost::shared_ptr<OptionNode> > m_subOptions;
00090 mutable bool m_hasSubOptions;
00091 static bool typeHasOptions(const edm::TypeWithDict& iType);
00092 };
00093
00094 OptionNode::OptionNode(const std::string& iDescription,
00095 unsigned long iSubstitutionEnd,
00096 const edm::TypeWithDict& iType) :
00097 m_type(iType),
00098 m_description(iDescription),
00099 m_endOfName(iSubstitutionEnd),
00100 m_hasSubOptions(typeHasOptions(iType) )
00101 {
00102 }
00103
00104 namespace {
00105 std::string descriptionFromMember(const edm::FunctionWithDict& iMember)
00106 {
00107 std::string typeString = iMember.typeName();
00108 std::string::size_type index = typeString.find_first_of("(");
00109 if(index == std::string::npos) {
00110 return iMember.name()+":"+typeString;
00111 } else {
00112 return iMember.name()+typeString.substr(index,std::string::npos)+":"+
00113 typeString.substr(0,index);
00114 }
00115 }
00116 }
00117
00118 OptionNode::OptionNode(const edm::FunctionWithDict& iMember) :
00119 m_type(reco::returnType(iMember)),
00120 m_description(descriptionFromMember(iMember)),
00121 m_endOfName(iMember.name().size()),
00122 m_hasSubOptions(typeHasOptions(m_type))
00123 {
00124 }
00125
00126
00127 void OptionNode::fillOptionForType( const edm::TypeWithDict& iType,
00128 std::vector<boost::shared_ptr<OptionNode> >& oOptions)
00129 {
00130 edm::TypeWithDict type = iType;
00131 if(type.isPointer()) {
00132 type = type.toType();
00133 }
00134
00135 edm::TypeFunctionMembers functions(type);
00136 oOptions.reserve(oOptions.size()+functions.size());
00137 for(auto const& function : functions) {
00138 edm::FunctionWithDict m(function);
00139 if(!m.typeOf().isConst() ||
00140 m.isConstructor() ||
00141 m.isDestructor() ||
00142 m.isOperator() ||
00143 !m.isPublic() ||
00144 m.name().substr(0,2)=="__") {continue;}
00145 oOptions.push_back(boost::shared_ptr<OptionNode>(new OptionNode(m)));
00146 }
00147
00148 edm::TypeBases bases(type);
00149 for(auto const& base : bases) {
00150 fillOptionForType(edm::BaseWithDict(base).toType(),oOptions);
00151 }
00152 }
00153
00154 bool OptionNode::typeHasOptions(const edm::TypeWithDict& iType) {
00155 return iType.isClass();
00156 }
00157
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 #define FUN1(_fun_) \
00168 m_builtins.push_back(boost::shared_ptr<OptionNode>( new OptionNode( # _fun_ "(float):float", strlen( # _fun_ )+1,s_float)))
00169
00170 #define FUN2(_fun_) \
00171 m_builtins.push_back(boost::shared_ptr<OptionNode>( new OptionNode( # _fun_ "(float,float):float", strlen( # _fun_ )+1,s_float)))
00172
00173 FWExpressionValidator::FWExpressionValidator()
00174 {
00175 using fireworks::OptionNode;
00176 static const edm::TypeWithDict s_float(typeid(float));
00177 FUN1(abs);
00178 FUN1(acos);
00179 FUN1(asin);
00180 FUN1(atan);
00181 FUN1(cos);
00182 FUN1(cosh);
00183 FUN1(exp);
00184 FUN1(log);
00185 FUN1(log10);
00186 FUN1(sin);
00187 FUN1(sinh);
00188 FUN1(sqrt);
00189 FUN1(tan);
00190 FUN1(tanh);
00191 FUN2(atan2);
00192 FUN2(chi2prob);
00193 FUN2(pow);
00194 FUN2(min);
00195 FUN2(max);
00196 std::sort(m_builtins.begin(),m_builtins.end(),
00197 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00198
00199 }
00200
00201
00202
00203
00204
00205
00206 FWExpressionValidator::~FWExpressionValidator()
00207 {
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 void
00226 FWExpressionValidator::setType(const edm::TypeWithDict& iType)
00227 {
00228 using fireworks::OptionNode;
00229 m_type=iType;
00230 m_options.clear();
00231 m_options=m_builtins;
00232 OptionNode::fillOptionForType(iType, m_options);
00233 std::sort(m_options.begin(),m_options.end(),
00234 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00235 std::vector<boost::shared_ptr<OptionNode> >::iterator it=
00236 std::unique(m_options.begin(),m_options.end(),
00237 fireworks::OptionNodePtrEqual<boost::shared_ptr<OptionNode> >());
00238 m_options.erase(it, m_options.end());
00239 }
00240
00241
00242
00243
00244 namespace {
00245 void dummyDelete(void*) {
00246 }
00247
00248 void findTypeDelimiters(const char*& ioBegin,
00249 const char* iEnd,
00250 std::vector<const char*>& oDelimeters)
00251 {
00252 oDelimeters.clear();
00253 if(ioBegin==iEnd) { return; }
00254 const char* it = iEnd-1;
00255 const char* itEnd = ioBegin-1;
00256 for(; it != itEnd; --it) {
00257 if(isalnum(*it)) { continue;}
00258 bool shouldStop=false;
00259 switch(*it) {
00260 case '_': break;
00261 case '.':
00262 oDelimeters.push_back(it);
00263 break;
00264 default:
00265 shouldStop=true;
00266 }
00267 if(shouldStop) { break;}
00268 }
00269 ioBegin = it+1;
00270 std::reverse(oDelimeters.begin(),oDelimeters.end());
00271 }
00272 }
00273
00274 void
00275 FWExpressionValidator::fillOptions(const char* iBegin, const char* iEnd,
00276 std::vector<std::pair<boost::shared_ptr<std::string>, std::string> >& oOptions) const
00277 {
00278 using fireworks::OptionNode;
00279 oOptions.clear();
00280 std::vector<const char*> delimeters;
00281 findTypeDelimiters(iBegin, iEnd, delimeters);
00282
00283 const Options* nodes = &m_options;
00284 const char* begin = iBegin;
00285 for(std::vector<const char*>::iterator it = delimeters.begin(), itEnd = delimeters.end();
00286 it != itEnd; ++it) {
00287 OptionNode temp(std::string(begin,*it),
00288 *it-begin,
00289 edm::TypeWithDict());
00290
00291 boost::shared_ptr<OptionNode> comp(&temp, dummyDelete);
00292 Options::const_iterator itFind =std::lower_bound(nodes->begin(),
00293 nodes->end(),
00294 comp,
00295 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00296
00297 if(itFind == nodes->end() || *comp < *(*itFind) ) {
00298
00299 return;
00300 }
00301 nodes = &((*itFind)->options());
00302 begin = (*it)+1;
00303 }
00304
00305
00306 std::string part(begin,iEnd);
00307 unsigned int part_size = part.size();
00308 for(Options::const_iterator it = nodes->begin(), itEnd = nodes->end();
00309 it != itEnd;
00310 ++it) {
00311 if(part == (*it)->description().substr(0,part_size) ) {
00312 oOptions.push_back(std::make_pair(boost::shared_ptr<std::string>(const_cast<std::string*>(&((*it)->description())), dummyDelete),
00313 (*it)->description().substr(part_size,(*it)->substitutionEnd()-part_size)));
00314 }
00315 }
00316 }
00317
00318
00319
00320