CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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/TypeWithDict.h"
00005 #include "FWCore/Utilities/interface/TypeID.h"
00006 #include "CommonTools/Utils/interface/Exception.h"
00007 
00008 #include <algorithm>
00009 #include <string>
00010 #include <stdint.h>
00011 
00012 #include <boost/variant.hpp>
00013 #include <boost/type_traits/is_same.hpp>
00014 #include <boost/type_traits/is_integral.hpp>
00015 #include <boost/type_traits/is_floating_point.hpp>
00016 #include <boost/utility/enable_if.hpp>
00017 #include <boost/mpl/if.hpp>
00018 
00019 namespace reco {
00020   namespace parser {
00021 
00022     // true if T matches one of the integral types in the default
00023     // AnyMethodArgument variant
00024     template <typename T>
00025     struct matches_another_integral_type {
00026         static bool const value = 
00027             boost::is_same<T, int8_t>::value  || boost::is_same<T, uint8_t>::value  ||
00028             boost::is_same<T, int16_t>::value || boost::is_same<T, uint16_t>::value ||
00029             boost::is_same<T, int32_t>::value || boost::is_same<T, uint32_t>::value ||
00030             boost::is_same<T, int64_t>::value || boost::is_same<T, uint64_t>::value;
00031     };
00032 
00033     // size_t on 32-bit Os X is type unsigned long, which doesn't match uint32_t,
00034     // so add unsigned long if it doesn't match any of the other integral types.
00035     // Use "unsigned long" rather than size_t as PtrVector has unsigned long as
00036     // size_type
00037     typedef boost::mpl::if_<matches_another_integral_type<unsigned long>,
00038         boost::variant<int8_t, uint8_t,
00039                        int16_t, uint16_t,
00040                        int32_t, uint32_t,
00041                        int64_t, uint64_t,
00042                        double,float,
00043                        std::string>,
00044         boost::variant<int8_t, uint8_t,
00045                        int16_t, uint16_t,
00046                        int32_t, uint32_t,
00047                        int64_t, uint64_t,
00048                        unsigned long,
00049                        double,float,
00050                        std::string> >::type AnyMethodArgument;
00051 
00052     class AnyMethodArgumentFixup : public boost::static_visitor<std::pair<AnyMethodArgument, int> > {
00053         private:
00054             edm::TypeWithDict dataType_;
00055             const std::type_info & type_;
00056             template<typename From, typename To>
00057             std::pair<AnyMethodArgument, int> retOk_(const From &f, int cast) const {
00058                 return std::pair<AnyMethodArgument,int>(AnyMethodArgument(static_cast<To>(f)), cast);
00059             }
00060 
00061             // correct return for each int output type
00062             std::pair<AnyMethodArgument,int> doInt(int t) const {
00063                 if (type_ == typeid(int8_t))   { return retOk_<int,int8_t>  (t,0); }
00064                 if (type_ == typeid(uint8_t))  { return retOk_<int,uint8_t> (t,0); }
00065                 if (type_ == typeid(int16_t))  { return retOk_<int,int16_t> (t,0); }
00066                 if (type_ == typeid(uint16_t)) { return retOk_<int,uint16_t>(t,0); }
00067                 if (type_ == typeid(int32_t))  { return retOk_<int,int32_t> (t,0); }
00068                 if (type_ == typeid(uint32_t)) { return retOk_<int,uint32_t>(t,0); }
00069                 if (type_ == typeid(int64_t))  { return retOk_<int,int64_t> (t,0); }
00070                 if (type_ == typeid(uint64_t)) { return retOk_<int,uint64_t>(t,0); }
00071                 if (type_ == typeid(unsigned long)) { return retOk_<int,unsigned long>  (t,0); } // harmless if unsigned long matches another type
00072                 if (type_ == typeid(double))   { return retOk_<int,double>  (t,1); }
00073                 if (type_ == typeid(float))    { return retOk_<int,float>   (t,1); }
00074                 return std::pair<AnyMethodArgument,int>(t,-1);
00075             }
00076         public:
00077             AnyMethodArgumentFixup(edm::TypeWithDict type) : 
00078                 dataType_(type),
00079                 type_(type.typeInfo())
00080             {
00081             }
00082 
00083             // we handle all integer types through 'int', as that's the way they are parsed by boost::spirit
00084             template<typename I>
00085             typename boost::enable_if<boost::is_integral<I>, std::pair<AnyMethodArgument,int> >::type
00086             operator()(const I &t) const { return doInt(t); }
00087 
00088             template<typename F>
00089             typename boost::enable_if<boost::is_floating_point<F>, std::pair<AnyMethodArgument,int> >::type
00090             operator()(const F &t) const { 
00091                 if (type_ == typeid(double)) { return retOk_<F,double>(t,0); }
00092                 if (type_ == typeid(float))  { return retOk_<F,float> (t,0); }
00093                 return std::pair<AnyMethodArgument,int>(t,-1);
00094             }
00095 
00096             std::pair<AnyMethodArgument,int> operator()(const std::string &t) const { 
00097                 if (type_ == typeid(std::string)) { return std::pair<AnyMethodArgument,int>(t,0); }
00098                 if (dataType_.isEnum()) {
00099                     if (dataType_.dataMemberSize() == 0) {
00100                         throw parser::Exception(t.c_str()) << "Enumerator '" << dataType_.name() << "' has no keys.\nPerhaps the dictionary is missing?\n";
00101                     }
00102                     int ival = dataType_.stringToEnumValue(t);
00103                     // std::cerr << "  value is = " << dataType_.stringToEnumValue(t) << std::endl;
00104                     return std::pair<AnyMethodArgument,int>(ival,1);
00105                 }
00106                 return std::pair<AnyMethodArgument,int>(t,-1);
00107             }
00108 
00109     };
00110     
00111     class AnyMethodArgument2VoidPtr : public boost::static_visitor<void *> {
00112         public:
00113             template<typename T>
00114             void * operator()(const T &t) const { return const_cast<void*>(static_cast<const void *>(&t)); }
00115     };
00116   }
00117 }
00118 
00119 #endif