Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-17 23:10:24

0001 #ifndef CommonTools_Utils_AnyMethodArgument_h
0002 #define CommonTools_Utils_AnyMethodArgument_h
0003 
0004 #include "FWCore/Reflection/interface/TypeWithDict.h"
0005 #include "FWCore/Utilities/interface/TypeID.h"
0006 #include "CommonTools/Utils/interface/Exception.h"
0007 
0008 #include <algorithm>
0009 #include <cstdint>
0010 #include <string>
0011 #include <type_traits>
0012 #include <variant>
0013 
0014 namespace reco {
0015   namespace parser {
0016 
0017     // true if T matches one of the integral types in the default
0018     // AnyMethodArgument variant
0019     template <typename T>
0020     struct matches_another_integral_type {
0021       static bool const value = std::is_same<T, int8_t>::value || std::is_same<T, uint8_t>::value ||
0022                                 std::is_same<T, int16_t>::value || std::is_same<T, uint16_t>::value ||
0023                                 std::is_same<T, int32_t>::value || std::is_same<T, uint32_t>::value ||
0024                                 std::is_same<T, int64_t>::value || std::is_same<T, uint64_t>::value;
0025     };
0026 
0027     // size_t on 32-bit Os X is type unsigned long, which doesn't match uint32_t,
0028     // so add unsigned long if it doesn't match any of the other integral types.
0029     // Use "unsigned long" rather than size_t as PtrVector has unsigned long as
0030     // size_type
0031     typedef std::conditional<
0032         matches_another_integral_type<unsigned long>::value,
0033         std::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, double, float, std::string>,
0034         std::variant<int8_t,
0035                      uint8_t,
0036                      int16_t,
0037                      uint16_t,
0038                      int32_t,
0039                      uint32_t,
0040                      int64_t,
0041                      uint64_t,
0042                      unsigned long,
0043                      double,
0044                      float,
0045                      std::string> >::type AnyMethodArgument;
0046 
0047     class AnyMethodArgumentFixup {
0048     private:
0049       edm::TypeWithDict dataType_;
0050       template <typename From, typename To>
0051       std::pair<AnyMethodArgument, int> retOk_(const From &f, int cast) const {
0052         return std::pair<AnyMethodArgument, int>(AnyMethodArgument(static_cast<To>(f)), cast);
0053       }
0054 
0055       // correct return for each int output type
0056       std::pair<AnyMethodArgument, int> doInt(int t) const {
0057         if (dataType_ == typeid(int8_t)) {
0058           return retOk_<int, int8_t>(t, 0);
0059         }
0060         if (dataType_ == typeid(uint8_t)) {
0061           return retOk_<int, uint8_t>(t, 0);
0062         }
0063         if (dataType_ == typeid(int16_t)) {
0064           return retOk_<int, int16_t>(t, 0);
0065         }
0066         if (dataType_ == typeid(uint16_t)) {
0067           return retOk_<int, uint16_t>(t, 0);
0068         }
0069         if (dataType_ == typeid(int32_t)) {
0070           return retOk_<int, int32_t>(t, 0);
0071         }
0072         if (dataType_ == typeid(uint32_t)) {
0073           return retOk_<int, uint32_t>(t, 0);
0074         }
0075         if (dataType_ == typeid(int64_t)) {
0076           return retOk_<int, int64_t>(t, 0);
0077         }
0078         if (dataType_ == typeid(uint64_t)) {
0079           return retOk_<int, uint64_t>(t, 0);
0080         }
0081         if (dataType_ == typeid(unsigned long)) {
0082           return retOk_<int, unsigned long>(t, 0);
0083         }  // harmless if unsigned long matches another type
0084         if (dataType_ == typeid(double)) {
0085           return retOk_<int, double>(t, 1);
0086         }
0087         if (dataType_ == typeid(float)) {
0088           return retOk_<int, float>(t, 1);
0089         }
0090         return std::pair<AnyMethodArgument, int>(t, -1);
0091       }
0092 
0093     public:
0094       AnyMethodArgumentFixup(const edm::TypeWithDict &type) : dataType_(type) {}
0095 
0096       // we handle all integer types through 'int', as that's the way they are parsed by boost::spirit
0097       template <typename I>
0098       typename std::enable_if<std::is_integral<I>::value, std::pair<AnyMethodArgument, int> >::type operator()(
0099           const I &t) const {
0100         return doInt(t);
0101       }
0102 
0103       template <typename F>
0104       typename std::enable_if<std::is_floating_point<F>::value, std::pair<AnyMethodArgument, int> >::type operator()(
0105           const F &t) const {
0106         if (dataType_ == typeid(double)) {
0107           return retOk_<F, double>(t, 0);
0108         }
0109         if (dataType_ == typeid(float)) {
0110           return retOk_<F, float>(t, 0);
0111         }
0112         return std::pair<AnyMethodArgument, int>(t, -1);
0113       }
0114 
0115       std::pair<AnyMethodArgument, int> operator()(const std::string &t) const {
0116         if (dataType_.isEnum()) {
0117           if (dataType_.dataMemberSize() == 0) {
0118             throw parser::Exception(t.c_str())
0119                 << "Enumerator '" << dataType_.name() << "' has no keys.\nPerhaps the dictionary is missing?\n";
0120           }
0121           int ival = dataType_.stringToEnumValue(t);
0122           // std::cerr << "  value is = " << dataType_.stringToEnumValue(t) << std::endl;
0123           return std::pair<AnyMethodArgument, int>(ival, 1);
0124         }
0125         if (dataType_ == typeid(std::string)) {
0126           return std::pair<AnyMethodArgument, int>(t, 0);
0127         }
0128         return std::pair<AnyMethodArgument, int>(t, -1);
0129       }
0130     };
0131 
0132     class AnyMethodArgument2VoidPtr {
0133     public:
0134       template <typename T>
0135       void *operator()(const T &t) const {
0136         return const_cast<void *>(static_cast<const void *>(&t));
0137       }
0138     };
0139   }  // namespace parser
0140 }  // namespace reco
0141 
0142 #endif