CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/CommonTools/Utils/src/AnyMethodArgument.h

Go to the documentation of this file.
00001 #ifndef CommonTools_Utils_AnyMethodArgument_h
00002 #define CommonTools_Utils_AnyMethodArgument_h
00003 
00004 #include "FWCore/Utilities/interface/ObjectWithDict.h"
00005 #include "FWCore/Utilities/interface/MemberWithDict.h"
00006 #include "FWCore/Utilities/interface/TypeWithDict.h"
00007 #include "CommonTools/Utils/interface/Exception.h"
00008 
00009 #include <algorithm>
00010 #include <string>
00011 #include <stdint.h>
00012 
00013 #include <boost/variant.hpp>
00014 #include <boost/type_traits/is_same.hpp>
00015 #include <boost/type_traits/is_integral.hpp>
00016 #include <boost/type_traits/is_floating_point.hpp>
00017 #include <boost/utility/enable_if.hpp>
00018 #include <boost/mpl/if.hpp>
00019 
00020 namespace reco {
00021   namespace parser {
00022 
00023     // true if T matches one of the integral types in the default
00024     // AnyMethodArgument variant
00025     template <typename T>
00026     struct matches_another_integral_type {
00027         static bool const value = 
00028             boost::is_same<T, int8_t>::value  || boost::is_same<T, uint8_t>::value  ||
00029             boost::is_same<T, int16_t>::value || boost::is_same<T, uint16_t>::value ||
00030             boost::is_same<T, int32_t>::value || boost::is_same<T, uint32_t>::value ||
00031             boost::is_same<T, int64_t>::value || boost::is_same<T, uint64_t>::value;
00032     };
00033 
00034     // size_t on 32-bit Os X is type unsigned long, which doesn't match uint32_t,
00035     // so add unsigned long if it doesn't match any of the other integral types.
00036     // Use "unsigned long" rather than size_t as PtrVector has unsigned long as
00037     // size_type
00038     typedef boost::mpl::if_<matches_another_integral_type<unsigned long>,
00039         boost::variant<int8_t, uint8_t,
00040                        int16_t, uint16_t,
00041                        int32_t, uint32_t,
00042                        int64_t, uint64_t,
00043                        double,float,
00044                        std::string>,
00045         boost::variant<int8_t, uint8_t,
00046                        int16_t, uint16_t,
00047                        int32_t, uint32_t,
00048                        int64_t, uint64_t,
00049                        unsigned long,
00050                        double,float,
00051                        std::string> >::type AnyMethodArgument;
00052 
00053     class AnyMethodArgumentFixup : public boost::static_visitor<std::pair<AnyMethodArgument, int> > {
00054         private:
00055             edm::TypeWithDict dataType_;
00056             const std::type_info & type_;
00057             template<typename From, typename To>
00058             std::pair<AnyMethodArgument, int> retOk_(const From &f, int cast) const {
00059                 return std::pair<AnyMethodArgument,int>(AnyMethodArgument(static_cast<To>(f)), cast);
00060             }
00061 
00062             // correct return for each int output type
00063             std::pair<AnyMethodArgument,int> doInt(int t) const {
00064                 if (type_ == typeid(int8_t))   { return retOk_<int,int8_t>  (t,0); }
00065                 if (type_ == typeid(uint8_t))  { return retOk_<int,uint8_t> (t,0); }
00066                 if (type_ == typeid(int16_t))  { return retOk_<int,int16_t> (t,0); }
00067                 if (type_ == typeid(uint16_t)) { return retOk_<int,uint16_t>(t,0); }
00068                 if (type_ == typeid(int32_t))  { return retOk_<int,int32_t> (t,0); }
00069                 if (type_ == typeid(uint32_t)) { return retOk_<int,uint32_t>(t,0); }
00070                 if (type_ == typeid(int64_t))  { return retOk_<int,int64_t> (t,0); }
00071                 if (type_ == typeid(uint64_t)) { return retOk_<int,uint64_t>(t,0); }
00072                 if (type_ == typeid(unsigned long)) { return retOk_<int,unsigned long>  (t,0); } // harmless if unsigned long matches another type
00073                 if (type_ == typeid(double))   { return retOk_<int,double>  (t,1); }
00074                 if (type_ == typeid(float))    { return retOk_<int,float>   (t,1); }
00075                 return std::pair<AnyMethodArgument,int>(t,-1);
00076             }
00077         public:
00078             AnyMethodArgumentFixup(edm::TypeWithDict type) : 
00079                 dataType_(type),
00080                 type_(type.name() == "string" ? typeid(std::string) : type.typeInfo()) // Otherwise Root does this wrong :-(
00081             {
00082                 while (dataType_.isTypedef()) dataType_ = dataType_.toType();
00083                 /* // Code to print out enum table 
00084                 if (dataType_.isEnum()) {
00085                     std::cerr << "Enum conversion: [" << dataType_.name() <<  "] => [" << type_.name() << "]" << std::endl;
00086                     std::cerr << "Enum has " << dataType_.dataMemberSize() << ", members." << std::endl;
00087                     TypeDataMembers members(dataType_);
00088                     for(auto const& member : members) {
00089                         edm::MemberWithDict mem(member);
00090                         std::cerr << " member #"<<i<<", name = " << mem.name() << ", dataType_ = " << mem.typeOf().name() << std::endl; 
00091                     }
00092                 } // */
00093             }
00094 
00095             // we handle all integer types through 'int', as that's the way they are parsed by boost::spirit
00096             template<typename I>
00097             typename boost::enable_if<boost::is_integral<I>, std::pair<AnyMethodArgument,int> >::type
00098             operator()(const I &t) const { return doInt(t); }
00099 
00100             template<typename F>
00101             typename boost::enable_if<boost::is_floating_point<F>, std::pair<AnyMethodArgument,int> >::type
00102             operator()(const F &t) const { 
00103                 if (type_ == typeid(double)) { return retOk_<F,double>(t,0); }
00104                 if (type_ == typeid(float))  { return retOk_<F,float> (t,0); }
00105                 return std::pair<AnyMethodArgument,int>(t,-1);
00106             }
00107 
00108             std::pair<AnyMethodArgument,int> operator()(const std::string &t) const { 
00109                 if (type_ == typeid(std::string)) { return std::pair<AnyMethodArgument,int>(t,0); }
00110                 if (dataType_.isEnum()) {
00111                     if (dataType_.dataMemberSize() == 0) {
00112                         throw parser::Exception(t.c_str()) << "Enumerator '" << dataType_.name() << "' has no keys.\nPerhaps the dictionary is missing?\n";
00113                     }
00114                     edm::MemberWithDict value = dataType_.dataMemberByName(t);
00115                     //std::cerr << "Trying to convert '" << t << "'  to a value for enumerator '" << dataType_.name() << "'" << std::endl;
00116                     if (!value) // check for existing value
00117                         return std::pair<AnyMethodArgument,int>(t,-1);
00118                         // throw parser::Exception(t.c_str()) << "Can't convert '" << t << "' to a value for enumerator '" << dataType_.name() << "'\n";
00119                     //std::cerr << "  found member of type '" << value.typeOf().name() << "'" << std::endl;
00120                     if (value.typeOf().typeInfo() != typeid(int)) // check is backed by an Int
00121                         throw parser::Exception(t.c_str()) << "Enumerator '" << dataType_.name() << "' is not implemented by type 'int' !!??\n";
00122                     //std::cerr << "  value is @ " <<   reinterpret_cast<const int *>(value.get().address()) << std::endl;
00123                     int ival = * reinterpret_cast<const int *>(value.get().address());
00124                     //std::cerr << "  value is = " << ival << std::endl;
00125                     return std::pair<AnyMethodArgument,int>(ival,1);
00126                 }
00127                 return std::pair<AnyMethodArgument,int>(t,-1);
00128             }
00129 
00130     };
00131     
00132     class AnyMethodArgument2VoidPtr : public boost::static_visitor<void *> {
00133         public:
00134             template<typename T>
00135             void * operator()(const T &t) const { return const_cast<void*>(static_cast<const void *>(&t)); }
00136     };
00137   }
00138 }
00139 
00140 #endif