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( 94 std::begin(data), std::end(data), 95 [&value](const auto& item) { return item.first == value; }); 96 if (it == std::end(data)) 97 { 98 throwConversionError(EnumTraits<T>::propertyName); 99 } 100 return it->second; 101 } 102 103 template <class T, size_t N> 104 inline std::string_view 105 enumToString(const std::array<std::pair<std::string_view, T>, N>& data, 106 T value) 107 { 108 auto it = std::find_if( 109 std::begin(data), std::end(data), 110 [value](const auto& item) { return item.second == value; }); 111 if (it == std::end(data)) 112 { 113 throwConversionError(EnumTraits<T>::propertyName); 114 } 115 return it->first; 116 } 117 118 } // namespace utils 119