CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/Fireworks/Core/src/FWExpressionValidator.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Core
00004 // Class  :     FWExpressionValidator
00005 //
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Fri Aug 22 20:42:51 EDT 2008
00011 // $Id: FWExpressionValidator.cc,v 1.7 2010/06/18 10:17:15 yana Exp $
00012 //
00013 
00014 // system include files
00015 #include <ctype.h>
00016 #include <algorithm>
00017 
00018 #include "Reflex/Member.h"
00019 #include "Reflex/Base.h"
00020 #include <cstring>
00021 
00022 // user include files
00023 #include "Fireworks/Core/src/FWExpressionValidator.h"
00024 #include "CommonTools/Utils/src/returnType.h"
00025 
00026 //
00027 // constants, enums and typedefs
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       // first look in base scope
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 // static data member definitions
00159 //
00160 
00161 //
00162 // constructors and destructor
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 // FWExpressionValidator::FWExpressionValidator(const FWExpressionValidator& rhs)
00199 // {
00200 //    // do actual copying here;
00201 // }
00202 
00203 FWExpressionValidator::~FWExpressionValidator()
00204 {
00205 }
00206 
00207 //
00208 // assignment operators
00209 //
00210 // const FWExpressionValidator& FWExpressionValidator::operator=(const FWExpressionValidator& rhs)
00211 // {
00212 //   //An exception safe implementation is
00213 //   FWExpressionValidator temp(rhs);
00214 //   swap(rhs);
00215 //
00216 //   return *this;
00217 // }
00218 
00219 //
00220 // member functions
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 // const member functions
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    //must find correct OptionNode
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          //no match so we have an error
00296          return;
00297       }
00298       nodes = &((*itFind)->options());
00299       begin = (*it)+1;
00300    }
00301 
00302    //only use add items which begin with the part of the member we are trying to match
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 // static member functions
00317 //