CMS 3D CMS Logo

AnyMethodArgument.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_Utilities_AnyMethodArgument_h
00002 #define PhysicsTools_Utilities_AnyMethodArgument_h
00003 
00004 #include "Reflex/Object.h"
00005 #include "Reflex/Member.h"
00006 #include "PhysicsTools/Utilities/interface/Exception.h"
00007 #include <algorithm>
00008 
00009 #include <string>
00010 #include <boost/variant.hpp>
00011 
00012 namespace reco {
00013   namespace parser {
00014 
00015     typedef boost::variant<
00016                 int8_t, uint8_t,
00017                 int16_t, uint16_t,
00018                 int32_t, uint32_t,
00019                 int64_t, uint64_t,
00020                 double,float,
00021                 std::string> AnyMethodArgument;
00022 
00023     class AnyMethodArgumentFixup : public boost::static_visitor<std::pair<AnyMethodArgument, int> > {
00024         private:
00025             ROOT::Reflex::Type rflxType_;
00026             const std::type_info & type_;
00027             template<typename From, typename To>
00028             std::pair<AnyMethodArgument, int> retOk_(const From &f, int cast) const {
00029                 return std::pair<AnyMethodArgument,int>(AnyMethodArgument(static_cast<To>(f)), cast);
00030             }
00031 
00032             // correct return for each int output type
00033             std::pair<AnyMethodArgument,int> doInt(int t) const {
00034                 if (type_ == typeid(int8_t))   { return retOk_<int,int8_t>  (t,0); }
00035                 if (type_ == typeid(uint8_t))  { return retOk_<int,uint8_t> (t,0); }
00036                 if (type_ == typeid(int16_t))  { return retOk_<int,int16_t> (t,0); }
00037                 if (type_ == typeid(uint16_t)) { return retOk_<int,uint16_t>(t,0); }
00038                 if (type_ == typeid(int32_t))  { return retOk_<int,int32_t> (t,0); }
00039                 if (type_ == typeid(uint32_t)) { return retOk_<int,uint32_t>(t,0); }
00040                 if (type_ == typeid(int64_t))  { return retOk_<int,int64_t> (t,0); }
00041                 if (type_ == typeid(uint64_t)) { return retOk_<int,uint64_t>(t,0); }
00042                 if (type_ == typeid(double))   { return retOk_<int,double>  (t,1); }
00043                 if (type_ == typeid(float))    { return retOk_<int,float>   (t,1); }
00044                 return std::pair<AnyMethodArgument,int>(t,-1);
00045             }
00046         public:
00047             AnyMethodArgumentFixup(ROOT::Reflex::Type type) : 
00048                 rflxType_(type),
00049                 type_(type.Name() == "string" ? typeid(std::string) : type.TypeInfo()) // Otherwise Reflex does this wrong :-(
00050             {
00051                 while (rflxType_.IsTypedef()) rflxType_ = rflxType_.ToType();
00052                 /* // Code to print out enum table 
00053                 if (rflxType_.IsEnum()) {
00054                     std::cerr << "Enum conversion: [" << rflxType_.Name() <<  "] => [" << type_.name() << "]" << std::endl;
00055                     std::cerr << "Enum has " << rflxType_.MemberSize() << ", members." << std::endl;
00056                     for (size_t i = 0; i < rflxType_.MemberSize(); ++i) {
00057                         ROOT::Reflex::Member mem = rflxType_.MemberAt(i);
00058                         std::cerr << " member #"<<i<<", name = " << mem.Name() << ", rflxType_ = " << mem.TypeOf().Name() << std::endl; 
00059                     }
00060                 } // */
00061             }
00062 
00063             // we handle all integer types through 'int', as that's the way they are parsed by boost::spirit
00064             std::pair<AnyMethodArgument,int> operator()(const   int8_t &t) const { return doInt(t); }
00065             std::pair<AnyMethodArgument,int> operator()(const  uint8_t &t) const { return doInt(t); }
00066             std::pair<AnyMethodArgument,int> operator()(const  int16_t &t) const { return doInt(t); }
00067             std::pair<AnyMethodArgument,int> operator()(const uint16_t &t) const { return doInt(t); }
00068             std::pair<AnyMethodArgument,int> operator()(const  int32_t &t) const { return doInt(t); }
00069             std::pair<AnyMethodArgument,int> operator()(const uint32_t &t) const { return doInt(t); }
00070             std::pair<AnyMethodArgument,int> operator()(const  int64_t &t) const { return doInt(t); }
00071             std::pair<AnyMethodArgument,int> operator()(const uint64_t &t) const { return doInt(t); }
00072 
00073             std::pair<AnyMethodArgument,int> operator()(const float &t) const { 
00074                 if (type_ == typeid(double)) { return retOk_<float,double>(t,0); }
00075                 if (type_ == typeid(float))  { return retOk_<float,float> (t,0); }
00076                 return std::pair<AnyMethodArgument,int>(t,-1);
00077             }
00078             std::pair<AnyMethodArgument,int> operator()(const double &t) const { 
00079                 if (type_ == typeid(double)) { return retOk_<double,double>(t,0); }
00080                 if (type_ == typeid(float))  { return retOk_<double,float> (t,0); }
00081                 return std::pair<AnyMethodArgument,int>(t,-1);
00082             }
00083             std::pair<AnyMethodArgument,int> operator()(const std::string &t) const { 
00084                 if (type_ == typeid(std::string)) { return std::pair<AnyMethodArgument,int>(t,0); }
00085                 if (rflxType_.IsEnum()) {
00086                     ROOT::Reflex::Member value = rflxType_.MemberByName(t);
00087                     //std::cerr << "Trying to convert '" << t << "'  to a value for enumerator '" << rflxType_.Name() << "'" << std::endl;
00088                     if (!value) // check for existing value
00089                         throw parser::Exception(t.c_str()) << "Can't convert '" << t << "' to a value for enumerator '" << rflxType_.Name() << "'\n";
00090                     //std::cerr << "  found member of type '" << value.TypeOf().Name() << "'" << std::endl;
00091                     if (value.TypeOf().TypeInfo() != typeid(int)) // check is backed by an Int
00092                         throw parser::Exception(t.c_str()) << "Enumerator '" << rflxType_.Name() << "' is not implemented by type 'int' !!??\n";
00093                     //std::cerr << "  value is @ " <<   reinterpret_cast<const int *>(value.Get().Address()) << std::endl;
00094                     int ival = * reinterpret_cast<const int *>(value.Get().Address());
00095                     //std::cerr << "  value is = " << ival << std::endl;
00096                     return std::pair<AnyMethodArgument,int>(ival,1);
00097                 }
00098                 return std::pair<AnyMethodArgument,int>(t,-1);
00099             }
00100 
00101     };
00102     
00103     class AnyMethodArgument2VoidPtr : public boost::static_visitor<void *> {
00104         public:
00105             template<typename T>
00106             void * operator()(const T &t) const { return const_cast<void*>(static_cast<const void *>(&t)); }
00107     };
00108   }
00109 }
00110 
00111 #endif

Generated on Tue Jun 9 17:42:51 2009 for CMSSW by  doxygen 1.5.4