CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/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.10 2012/08/28 22:25:42 wmtan Exp $
00012 //
00013 
00014 // system include files
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 // 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 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       // first look in base scope
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 // static data member definitions
00162 //
00163 
00164 //
00165 // constructors and destructor
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 // FWExpressionValidator::FWExpressionValidator(const FWExpressionValidator& rhs)
00202 // {
00203 //    // do actual copying here;
00204 // }
00205 
00206 FWExpressionValidator::~FWExpressionValidator()
00207 {
00208 }
00209 
00210 //
00211 // assignment operators
00212 //
00213 // const FWExpressionValidator& FWExpressionValidator::operator=(const FWExpressionValidator& rhs)
00214 // {
00215 //   //An exception safe implementation is
00216 //   FWExpressionValidator temp(rhs);
00217 //   swap(rhs);
00218 //
00219 //   return *this;
00220 // }
00221 
00222 //
00223 // member functions
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 // const member functions
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    //must find correct OptionNode
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          //no match so we have an error
00299          return;
00300       }
00301       nodes = &((*itFind)->options());
00302       begin = (*it)+1;
00303    }
00304 
00305    //only use add items which begin with the part of the member we are trying to match
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 // static member functions
00320 //