CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/CommonTools/Utils/src/MethodSetter.cc

Go to the documentation of this file.
00001 #include "CommonTools/Utils/src/MethodSetter.h"
00002 #include "CommonTools/Utils/src/returnType.h"
00003 #include "CommonTools/Utils/src/findMethod.h"
00004 #include "CommonTools/Utils/src/findDataMember.h"
00005 #include "CommonTools/Utils/src/ErrorCodes.h"
00006 #include "CommonTools/Utils/interface/Exception.h"
00007 #include <string>
00008 using namespace reco::parser;
00009 using namespace std;
00010 
00011 void MethodSetter::operator()(const char * begin, const char * end) const {
00012   string name(begin, end);
00013   string::size_type parenthesis = name.find_first_of('(');
00014   if (*begin == '[' || *begin == '(') {
00015     name.insert(0, "operator..");           // operator..[arg];
00016     parenthesis = 10;                       //           ^--- idx = 10
00017     name[8] = *begin;                       // operator[.[arg];
00018     name[9] =  name[name.size()-1];         // operator[][arg];
00019     name[10] = '(';                         // operator[](arg];
00020     name[name.size()-1] = ')';              // operator[](arg);    
00021     // we don't actually need the last two, but just for extra care
00022     //std::cout << "Transformed {" << string(begin,end) << "} into {"<< name <<"}" << std::endl;
00023   }
00024   std::vector<AnyMethodArgument> args;
00025   if(parenthesis != string::npos) {
00026     name.erase(parenthesis, name.size());
00027     if(intStack_.size()==0)
00028       throw Exception(begin)
00029         << "expected method argument, but non given.";    
00030     for(vector<AnyMethodArgument>::const_iterator i = intStack_.begin(); i != intStack_.end(); ++i)
00031       args.push_back(*i);
00032     intStack_.clear();
00033   }
00034   string::size_type endOfExpr = name.find_last_of(' ');
00035   if(endOfExpr != string::npos)
00036     name.erase(endOfExpr, name.size());
00037   //std::cerr << "Pushing [" << name << "] with " << args.size() << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
00038   if (lazy_) lazyMethStack_.push_back(LazyInvoker(name, args)); // for lazy parsing we just push method name and arguments
00039   else push(name, args,begin);  // otherwise we really have to resolve the method
00040   //std::cerr << "Pushed [" << name << "] with " << args.size() << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
00041 }
00042 
00043 bool MethodSetter::push(const string & name, const vector<AnyMethodArgument> & args, const char* begin,bool deep) const {
00044   edm::TypeWithDict type = typeStack_.back();
00045   vector<AnyMethodArgument> fixups;
00046   int error;
00047   pair<edm::FunctionWithDict, bool> mem = reco::findMethod(type, name, args, fixups,begin,error);
00048   if(mem.first) {
00049      edm::TypeWithDict retType = reco::returnType(mem.first);
00050      if(!retType) {
00051         throw Exception(begin)
00052         << "member \"" << mem.first.name() << "\" return type is invalid:\n" 
00053         << "  member type: \"" <<  mem.first.typeOf().qualifiedName() << "\"\n"
00054         << "  return type: \"" << mem.first.returnType().qualifiedName() << "\"\n";
00055         
00056      }
00057      typeStack_.push_back(retType);
00058      // check for edm::Ref, edm::RefToBase, edm::Ptr
00059      if(mem.second) {
00060         //std::cout << "Mem.second, so book " << mem.first.name() << " without fixups." << std::endl;
00061         methStack_.push_back(MethodInvoker(mem.first));
00062         if (deep) push(name, args,begin); // note: we have not found the method, so we have not fixupped the arguments
00063         else return false;
00064       } else {
00065         //std::cout << "Not mem.second, so book " << mem.first.name() << " with #args = " << fixups.size() << std::endl;
00066         methStack_.push_back(MethodInvoker(mem.first, fixups));
00067       }
00068   } else {
00069      if(error != reco::parser::kNameDoesNotExist) {
00070         switch(error) {
00071            case reco::parser::kIsNotPublic:
00072             throw Exception(begin)
00073               << "method named \"" << name << "\" for type \"" 
00074               <<type.name() << "\" is not publically accessible.";
00075             break;
00076            case reco::parser::kIsStatic:
00077              throw Exception(begin)
00078                << "method named \"" << name << "\" for type \"" 
00079                <<type.name() << "\" is static.";
00080              break;
00081            case reco::parser::kIsNotConst:
00082               throw Exception(begin)
00083                 << "method named \"" << name << "\" for type \"" 
00084                 <<type.name() << "\" is not const.";
00085               break;
00086            case reco::parser::kWrongNumberOfArguments:
00087                throw Exception(begin)
00088                  << "method named \"" << name << "\" for type \"" 
00089                  <<type.name() << "\" was passed the wrong number of arguments.";
00090                break;
00091            case reco::parser::kWrongArgumentType:
00092                throw Exception(begin)
00093                      << "method named \"" << name << "\" for type \"" 
00094                      <<type.name() << "\" was passed the wrong types of arguments.";
00095                break;
00096            default:  
00097             throw Exception(begin)
00098              << "method named \"" << name << "\" for type \"" 
00099              <<type.name() << "\" is not usable in this context.";
00100         }
00101      }
00102      //see if it is a member data
00103      int error;
00104     edm::MemberWithDict member(reco::findDataMember(type,name,error));
00105      if(!member) {
00106         switch(error) {
00107            case reco::parser::kNameDoesNotExist:
00108             throw Exception(begin)
00109                << "no method or data member named \"" << name << "\" found for type \"" 
00110                <<type.name() << "\"";
00111             break;
00112            case reco::parser::kIsNotPublic:
00113             throw Exception(begin)
00114               << "data member named \"" << name << "\" for type \"" 
00115               <<type.name() << "\" is not publically accessible.";
00116             break;
00117            default:
00118            throw Exception(begin)
00119              << "data member named \"" << name << "\" for type \"" 
00120              <<type.name() << "\" is not usable in this context.";
00121            break;
00122         }
00123      }
00124      typeStack_.push_back(member.typeOf());
00125      methStack_.push_back(MethodInvoker(member));
00126   }
00127   return true;
00128 }
00129