1 #pragma once 2 3 #include "errors.hpp" 4 5 #include <sdbusplus/exception.hpp> 6 7 #include <algorithm> 8 #include <array> 9 #include <stdexcept> 10 #include <string> 11 12 namespace utils 13 { 14 15 template <size_t N> 16 struct ConstexprString 17 { 18 constexpr ConstexprString(const char (&data)[N]) : s() 19 { 20 for (size_t i = 0; i < N; ++i) 21 { 22 s[i] = data[i]; 23 } 24 } 25 26 constexpr operator std::string_view() const 27 { 28 return {s.data(), s.size()}; 29 } 30 31 std::array<char, N> s; 32 }; 33 34 [[noreturn]] inline void throwConversionError(std::string_view propertyName) 35 { 36 throw errors::InvalidArgument(propertyName, "Cannot convert."); 37 } 38 39 template <class T> 40 struct EnumTraits; 41 42 template <class T, T first, T last> 43 inline T toEnum(std::underlying_type_t<T> x) 44 { 45 if (x < static_cast<std::underlying_type_t<T>>(first) || 46 x > static_cast<std::underlying_type_t<T>>(last)) 47 { 48 throwConversionError(EnumTraits<T>::propertyName); 49 } 50 return static_cast<T>(x); 51 } 52 53 template <class T> 54 constexpr inline std::underlying_type_t<T> toUnderlying(T value) 55 { 56 return static_cast<std::underlying_type_t<T>>(value); 57 } 58 59 template <class T, size_t N> 60 constexpr inline T 61 minEnumValue(std::array<std::pair<std::string_view, T>, N> data) 62 { 63 auto min = data[0].second; 64 for (auto [key, value] : data) 65 { 66 if (toUnderlying(min) > toUnderlying(value)) 67 { 68 min = value; 69 } 70 } 71 return min; 72 } 73 74 template <class T, size_t N> 75 constexpr inline T 76 maxEnumValue(std::array<std::pair<std::string_view, T>, N> data) 77 { 78 auto max = data[0].second; 79 for (auto [key, value] : data) 80 { 81 if (toUnderlying(max) < toUnderlying(value)) 82 { 83 max = value; 84 } 85 } 86 return max; 87 } 88 89 template <class T, size_t N> 90 inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data, 91 const std::string& value) 92 { 93 auto it = std::find_if(std::begin(data), std::end(data), 94 [&value](const auto& item) { 95 return item.first == value; 96 }); 97 if (it == std::end(data)) 98 { 99 throwConversionError(EnumTraits<T>::propertyName); 100 } 101 return it->second; 102 } 103 104 template <class T, size_t N> 105 inline std::string_view 106 enumToString(const std::array<std::pair<std::string_view, T>, N>& data, 107 T value) 108 { 109 auto it = std::find_if(std::begin(data), std::end(data), 110 [value](const auto& item) { 111 return item.second == value; 112 }); 113 if (it == std::end(data)) 114 { 115 throwConversionError(EnumTraits<T>::propertyName); 116 } 117 return it->first; 118 } 119 120 } // namespace utils 121