Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:26

0001 #ifndef L1Trigger_L1TCommon_l1t_Parameter_h
0002 #define L1Trigger_L1TCommon_l1t_Parameter_h
0003 
0004 #include <map>
0005 #include <list>
0006 #include <vector>
0007 #include <string>
0008 #include <memory>
0009 #include <iostream>
0010 #include <algorithm>
0011 #include <stdexcept>
0012 #include <type_traits>
0013 #include <cstring>
0014 
0015 namespace l1t {
0016 
0017   // assuming string is castable to T (some specific cases are defined in the end)
0018   template <class T>
0019   T castTo(const char *arg);
0020 
0021   class Parameter {
0022   private:
0023     std::string id, type, procOrRole;   // attributes
0024     std::string scalarOrVector, delim;  // setting could be one single parameter
0025     std::map<std::string, std::vector<std::string> >
0026         table;  // or a map of columns, no multimap here: column names are assumed be unique!
0027     std::map<std::string, unsigned int> columnNameToIndex;  // remember original positions of the columns
0028 
0029   public:
0030     std::string getId(void) const noexcept { return id; }
0031     std::string getProcOrRole(void) const noexcept { return procOrRole; }
0032     std::string getType(void) const noexcept { return type; }
0033     std::string getValueAsStr(void) const noexcept { return scalarOrVector; }
0034 
0035     bool isScalar(void) const noexcept {
0036       if (type.find("vector") != std::string::npos || type.find("table") != std::string::npos)
0037         return false;
0038       return true;
0039     }
0040     bool isVector(void) const noexcept {
0041       if (type.find("vector") == std::string::npos)
0042         return false;
0043       return true;
0044     }
0045     bool isTable(void) const noexcept {
0046       if (type.find("table") == std::string::npos)
0047         return false;
0048       return true;
0049     }
0050 
0051     // cast underlying scalarOrVector string to scalar T type
0052     template <class T>
0053     T getValue(void) const {
0054       if (!isScalar())
0055         throw std::runtime_error("The registered type: '" + type +
0056                                  "' is not a scalar -> try getVector() or getTable()");
0057       return castTo<T>(scalarOrVector.c_str());
0058     }
0059     // cast underlying scalarOrVector string to a vector of elements of type T
0060     template <class T>
0061     std::vector<T> getVector(void) const {
0062       if (!isVector())
0063         throw std::runtime_error("The registered type: '" + type + "' is not a vector");
0064       // split the vector into elements
0065       const char *d = delim.c_str();
0066       std::list<T> elements;
0067       std::unique_ptr<char, void (*)(void *)> copy(strdup(scalarOrVector.c_str()), free);
0068       char *saveptr;
0069       for (const char *item = strtok_r(copy.get(), d, &saveptr); item != nullptr; item = strtok_r(nullptr, d, &saveptr))
0070         try {
0071           elements.push_back(castTo<T>(item));
0072         } catch (std::runtime_error &e) {
0073           throw std::runtime_error(std::string(e.what()) + "; check if delimeter '" + delim + "' is correct");
0074         }
0075       return std::vector<T>(elements.begin(), elements.end());
0076     }
0077     // cast each element of a column of table to a vector of elements of type T
0078     template <class T>
0079     std::vector<T> getTableColumn(const char *colName) const {
0080       const std::vector<std::string> &column = table.at(colName);
0081       std::vector<T> retval(column.size());
0082       std::transform(
0083           column.begin(), column.end(), retval.begin(), [](std::string a) -> T { return castTo<T>(a.c_str()); });
0084       return retval;
0085     }
0086     // cast each element of a row of table to a vector of elements of type T
0087     template <class T>
0088     std::map<std::string, T> getTableRow(unsigned long rowNum) const {
0089       std::map<std::string, T> retval;
0090       for (auto &column :
0091            table)  // insert below is never going to fail as the source map doesn't have duplicated by design
0092         retval.insert(std::make_pair(column.first, castTo<T>(column.second.at(rowNum).c_str())));
0093       return retval;
0094     }
0095     // in case the order of columns in original table is important - use function below
0096     std::map<std::string, unsigned int> getColumnIndices(void) const noexcept { return columnNameToIndex; }
0097 
0098     Parameter &operator=(const Parameter &s) = default;
0099     Parameter &operator=(Parameter &&s) = default;  // should be noexcept
0100     Parameter(const Parameter &s) = default;
0101     Parameter(Parameter &&s) = default;  // should be noexcept
0102 
0103     Parameter(const char *id, const char *procOrRole, const char *type, const char *value, const char *delimeter = ",");
0104     Parameter(const char *id,
0105               const char *procOrRole,
0106               const char *types,
0107               const char *columns,
0108               const std::vector<std::string> &rows,
0109               const char *delimeter = ",");
0110 
0111     Parameter(void) {}
0112     ~Parameter(void) {}
0113   };
0114 
0115   // specializations for most of the fundamental types are provided (also covers simple typedefs)
0116   template <>
0117   bool castTo<bool>(const char *arg);
0118   template <>
0119   char castTo<char>(const char *arg);
0120   template <>
0121   short castTo<short>(const char *arg);
0122   template <>
0123   int castTo<int>(const char *arg);
0124   template <>
0125   long castTo<long>(const char *arg);
0126   template <>
0127   long long castTo<long long>(const char *arg);
0128   template <>
0129   float castTo<float>(const char *arg);
0130   template <>
0131   double castTo<double>(const char *arg);
0132   template <>
0133   long double castTo<long double>(const char *arg);
0134   template <>
0135   unsigned char castTo<unsigned char>(const char *arg);
0136   template <>
0137   unsigned short castTo<unsigned short>(const char *arg);
0138   template <>
0139   unsigned int castTo<unsigned int>(const char *arg);
0140   template <>
0141   unsigned long castTo<unsigned long>(const char *arg);
0142   template <>
0143   unsigned long long castTo<unsigned long long>(const char *arg);
0144 
0145   // apart from the types above there may still be some numeric types left
0146   template <class T>
0147   T castToInt_impl(const char *arg, std::true_type);
0148   template <class T>
0149   T castToInt_impl(const char *arg, std::false_type);
0150   template <class T>
0151   T castTo_impl(const char *arg, std::true_type, std::false_type);
0152   template <class T>
0153   T castTo_impl(const char *arg, std::false_type, std::true_type);
0154   template <class T>
0155   T castTo_impl(const char *arg, std::false_type, std::false_type);
0156 
0157   //  try to guess the type trait first
0158   template <class T>
0159   T castTo(const char *arg) {
0160     return castTo_impl<T>(arg, std::is_integral<T>(), std::is_floating_point<T>());
0161   }
0162   // integral type can be signed and unsigned
0163   template <class T>
0164   T castTo_impl(const char *arg, std::true_type, std::false_type) {
0165     return castToInt_impl<T>(arg, std::is_unsigned<T>());
0166   }
0167   // unsigned case
0168   template <class T>
0169   T castToInt_impl(const char *arg, std::true_type) {
0170     return castTo<unsigned long long>(arg);
0171   }
0172   // signed case
0173   template <class T>
0174   T castToInt_impl(const char *arg, std::false_type) {
0175     return castTo<long long>(arg);
0176   }
0177   // floating point type
0178   template <class T>
0179   T castTo_impl(const char *arg, std::false_type, std::true_type) {
0180     return castTo<long double>(arg);
0181   }
0182   // last hope that a non-fundamental type T is initializable with a string
0183   template <class T>
0184   T castTo_impl(const char *arg, std::false_type, std::false_type) {
0185     return T(arg);
0186   }
0187 
0188 }  // namespace l1t
0189 
0190 #endif