00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <ctype.h>
00016 #include <algorithm>
00017
00018 #include "Reflex/Member.h"
00019 #include "Reflex/Base.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 ROOT::Reflex::Member& );
00054 OptionNode(const std::string& iDescription,
00055 unsigned long iSubstitutionEnd,
00056 const ROOT::Reflex::Type& 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 ROOT::Reflex::Type&,
00084 std::vector<boost::shared_ptr<OptionNode> >& );
00085 private:
00086 ROOT::Reflex::Type 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 ROOT::Reflex::Type& iType);
00092 };
00093
00094 OptionNode::OptionNode(const std::string& iDescription,
00095 unsigned long iSubstitutionEnd,
00096 const ROOT::Reflex::Type& 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 ROOT::Reflex::Member& iMember)
00106 {
00107 std::string typeString = iMember.TypeOf().Name();
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 ROOT::Reflex::Member& 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 ROOT::Reflex::Type& iType,
00128 std::vector<boost::shared_ptr<OptionNode> >& oOptions)
00129 {
00130 ROOT::Reflex::Type type = iType;
00131 if(type.IsPointer()) {
00132 type = type.ToType();
00133 }
00134
00135 oOptions.reserve(oOptions.size()+type.FunctionMemberSize());
00136 for(ROOT::Reflex::Member_Iterator m = type.FunctionMember_Begin(); m != type.FunctionMember_End(); ++m ) {
00137 if(!m->TypeOf().IsConst() ||
00138 m->IsConstructor() ||
00139 m->IsDestructor() ||
00140 m->IsOperator() ||
00141 !m->IsPublic() ||
00142 m->Name().substr(0,2)=="__") {continue;}
00143 oOptions.push_back(boost::shared_ptr<OptionNode>(new OptionNode(*m)));
00144 }
00145
00146 for(ROOT::Reflex::Base_Iterator b = type.Base_Begin(); b != type.Base_End(); ++b) {
00147 fillOptionForType(b->ToType(),oOptions);
00148 }
00149 }
00150
00151 bool OptionNode::typeHasOptions(const ROOT::Reflex::Type& iType) {
00152 return iType.IsClass();
00153 }
00154
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164 #define FUN1(_fun_) \
00165 m_builtins.push_back(boost::shared_ptr<OptionNode>( new OptionNode( # _fun_ "(float):float", strlen( # _fun_ )+1,s_float)))
00166
00167 #define FUN2(_fun_) \
00168 m_builtins.push_back(boost::shared_ptr<OptionNode>( new OptionNode( # _fun_ "(float,float):float", strlen( # _fun_ )+1,s_float)))
00169
00170 FWExpressionValidator::FWExpressionValidator()
00171 {
00172 using fireworks::OptionNode;
00173 static const ROOT::Reflex::Type s_float(ROOT::Reflex::Type::ByTypeInfo(typeid(float)));
00174 FUN1(abs);
00175 FUN1(acos);
00176 FUN1(asin);
00177 FUN1(atan);
00178 FUN1(cos);
00179 FUN1(cosh);
00180 FUN1(exp);
00181 FUN1(log);
00182 FUN1(log10);
00183 FUN1(sin);
00184 FUN1(sinh);
00185 FUN1(sqrt);
00186 FUN1(tan);
00187 FUN1(tanh);
00188 FUN2(atan2);
00189 FUN2(chi2prob);
00190 FUN2(pow);
00191 FUN2(min);
00192 FUN2(max);
00193 std::sort(m_builtins.begin(),m_builtins.end(),
00194 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00195
00196 }
00197
00198
00199
00200
00201
00202
00203 FWExpressionValidator::~FWExpressionValidator()
00204 {
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void
00223 FWExpressionValidator::setType(const ROOT::Reflex::Type& iType)
00224 {
00225 using fireworks::OptionNode;
00226 m_type=iType;
00227 m_options.clear();
00228 m_options=m_builtins;
00229 OptionNode::fillOptionForType(iType, m_options);
00230 std::sort(m_options.begin(),m_options.end(),
00231 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00232 std::vector<boost::shared_ptr<OptionNode> >::iterator it=
00233 std::unique(m_options.begin(),m_options.end(),
00234 fireworks::OptionNodePtrEqual<boost::shared_ptr<OptionNode> >());
00235 m_options.erase(it, m_options.end());
00236 }
00237
00238
00239
00240
00241 namespace {
00242 void dummyDelete(void*) {
00243 }
00244
00245 void findTypeDelimiters(const char*& ioBegin,
00246 const char* iEnd,
00247 std::vector<const char*>& oDelimeters)
00248 {
00249 oDelimeters.clear();
00250 if(ioBegin==iEnd) { return; }
00251 const char* it = iEnd-1;
00252 const char* itEnd = ioBegin-1;
00253 for(; it != itEnd; --it) {
00254 if(isalnum(*it)) { continue;}
00255 bool shouldStop=false;
00256 switch(*it) {
00257 case '_': break;
00258 case '.':
00259 oDelimeters.push_back(it);
00260 break;
00261 default:
00262 shouldStop=true;
00263 }
00264 if(shouldStop) { break;}
00265 }
00266 ioBegin = it+1;
00267 std::reverse(oDelimeters.begin(),oDelimeters.end());
00268 }
00269 }
00270
00271 void
00272 FWExpressionValidator::fillOptions(const char* iBegin, const char* iEnd,
00273 std::vector<std::pair<boost::shared_ptr<std::string>, std::string> >& oOptions) const
00274 {
00275 using fireworks::OptionNode;
00276 oOptions.clear();
00277 std::vector<const char*> delimeters;
00278 findTypeDelimiters(iBegin, iEnd, delimeters);
00279
00280 const Options* nodes = &m_options;
00281 const char* begin = iBegin;
00282 for(std::vector<const char*>::iterator it = delimeters.begin(), itEnd = delimeters.end();
00283 it != itEnd; ++it) {
00284 OptionNode temp(std::string(begin,*it),
00285 *it-begin,
00286 ROOT::Reflex::Type());
00287
00288 boost::shared_ptr<OptionNode> comp(&temp, dummyDelete);
00289 Options::const_iterator itFind =std::lower_bound(nodes->begin(),
00290 nodes->end(),
00291 comp,
00292 fireworks::OptionNodePtrCompare<boost::shared_ptr<OptionNode> >());
00293
00294 if(itFind == nodes->end() || *comp < *(*itFind) ) {
00295
00296 return;
00297 }
00298 nodes = &((*itFind)->options());
00299 begin = (*it)+1;
00300 }
00301
00302
00303 std::string part(begin,iEnd);
00304 unsigned int part_size = part.size();
00305 for(Options::const_iterator it = nodes->begin(), itEnd = nodes->end();
00306 it != itEnd;
00307 ++it) {
00308 if(part == (*it)->description().substr(0,part_size) ) {
00309 oOptions.push_back(std::make_pair(boost::shared_ptr<std::string>(const_cast<std::string*>(&((*it)->description())), dummyDelete),
00310 (*it)->description().substr(part_size,(*it)->substitutionEnd()-part_size)));
00311 }
00312 }
00313 }
00314
00315
00316
00317