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 {
ConstexprStringutils::ConstexprString18 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
operator std::string_viewutils::ConstexprString26 constexpr operator std::string_view() const
27 {
28 return {s.data(), s.size()};
29 }
30
31 std::array<char, N> s;
32 };
33
throwConversionError(std::string_view propertyName)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>
toEnum(std::underlying_type_t<T> x)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>
toUnderlying(T value)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
minEnumValue(std::array<std::pair<std::string_view,T>,N> data)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
maxEnumValue(std::array<std::pair<std::string_view,T>,N> data)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>
toEnum(const std::array<std::pair<std::string_view,T>,N> & data,const std::string & value)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
enumToString(const std::array<std::pair<std::string_view,T>,N> & data,T value)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