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
00024
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
00035
00036
00037
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
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); }
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())
00081 {
00082 while (dataType_.isTypedef()) dataType_ = dataType_.toType();
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 }
00094
00095
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
00116 if (!value)
00117 return std::pair<AnyMethodArgument,int>(t,-1);
00118
00119
00120 if (value.typeOf().typeInfo() != typeid(int))
00121 throw parser::Exception(t.c_str()) << "Enumerator '" << dataType_.name() << "' is not implemented by type 'int' !!??\n";
00122
00123 int ival = * reinterpret_cast<const int *>(value.get().address());
00124
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