00001 #ifndef CommonTools_Utils_AnyMethodArgument_h
00002 #define CommonTools_Utils_AnyMethodArgument_h
00003
00004 #include "Reflex/Object.h"
00005 #include "Reflex/Member.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
00023
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
00034
00035
00036
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 Reflex::Type rflxType_;
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
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); }
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(Reflex::Type type) :
00078 rflxType_(type),
00079 type_(type.Name() == "string" ? typeid(std::string) : type.TypeInfo())
00080 {
00081 while (rflxType_.IsTypedef()) rflxType_ = rflxType_.ToType();
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 }
00092
00093
00094 template<typename I>
00095 typename boost::enable_if<boost::is_integral<I>, std::pair<AnyMethodArgument,int> >::type
00096 operator()(const I &t) const { return doInt(t); }
00097
00098 template<typename F>
00099 typename boost::enable_if<boost::is_floating_point<F>, std::pair<AnyMethodArgument,int> >::type
00100 operator()(const F &t) const {
00101 if (type_ == typeid(double)) { return retOk_<F,double>(t,0); }
00102 if (type_ == typeid(float)) { return retOk_<F,float> (t,0); }
00103 return std::pair<AnyMethodArgument,int>(t,-1);
00104 }
00105
00106 std::pair<AnyMethodArgument,int> operator()(const std::string &t) const {
00107 if (type_ == typeid(std::string)) { return std::pair<AnyMethodArgument,int>(t,0); }
00108 if (rflxType_.IsEnum()) {
00109 if (rflxType_.MemberSize() == 0) {
00110 throw parser::Exception(t.c_str()) << "Enumerator '" << rflxType_.Name() << "' has no keys.\nPerhaps the reflex dictionary is missing?\n";
00111 }
00112 Reflex::Member value = rflxType_.MemberByName(t);
00113
00114 if (!value)
00115 return std::pair<AnyMethodArgument,int>(t,-1);
00116
00117
00118 if (value.TypeOf().TypeInfo() != typeid(int))
00119 throw parser::Exception(t.c_str()) << "Enumerator '" << rflxType_.Name() << "' is not implemented by type 'int' !!??\n";
00120
00121 int ival = * reinterpret_cast<const int *>(value.Get().Address());
00122
00123 return std::pair<AnyMethodArgument,int>(ival,1);
00124 }
00125 return std::pair<AnyMethodArgument,int>(t,-1);
00126 }
00127
00128 };
00129
00130 class AnyMethodArgument2VoidPtr : public boost::static_visitor<void *> {
00131 public:
00132 template<typename T>
00133 void * operator()(const T &t) const { return const_cast<void*>(static_cast<const void *>(&t)); }
00134 };
00135 }
00136 }
00137
00138 #endif