blob: fd3dbcbcea52cf34268dce66ff6f660855e098c4 [file] [log] [blame]
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01001#pragma once
2
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01003#include <sdbusplus/exception.hpp>
4
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00005#include <algorithm>
6#include <array>
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01007#include <stdexcept>
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00008#include <string>
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01009
10namespace utils
11{
12
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010013template <class T>
14struct EnumTraits
15{
16 [[noreturn]] static void throwConversionError()
17 {
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010018 throw sdbusplus::exception::SdBusError(
19 static_cast<int>(std::errc::invalid_argument),
20 "Invalid enum value");
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010021 }
22};
23
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010024template <class T, T first, T last>
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000025inline T toEnum(std::underlying_type_t<T> x)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010026{
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000027 if (x < static_cast<std::underlying_type_t<T>>(first) ||
28 x > static_cast<std::underlying_type_t<T>>(last))
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010029 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010030 EnumTraits<T>::throwConversionError();
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010031 }
32 return static_cast<T>(x);
33}
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000034
35template <class T>
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010036constexpr inline std::underlying_type_t<T> toUnderlying(T value)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000037{
38 return static_cast<std::underlying_type_t<T>>(value);
39}
40
41template <class T, size_t N>
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010042constexpr inline T
43 minEnumValue(std::array<std::pair<std::string_view, T>, N> data)
44{
45 auto min = data[0].second;
46 for (auto [key, value] : data)
47 {
48 if (toUnderlying(min) > toUnderlying(value))
49 {
50 min = value;
51 }
52 }
53 return min;
54}
55
56template <class T, size_t N>
57constexpr inline T
58 maxEnumValue(std::array<std::pair<std::string_view, T>, N> data)
59{
60 auto max = data[0].second;
61 for (auto [key, value] : data)
62 {
63 if (toUnderlying(max) < toUnderlying(value))
64 {
65 max = value;
66 }
67 }
68 return max;
69}
70
71template <class T, size_t N>
72inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data,
73 const std::string& value)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000074{
75 auto it = std::find_if(
76 std::begin(data), std::end(data),
77 [&value](const auto& item) { return item.first == value; });
78 if (it == std::end(data))
79 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010080 EnumTraits<T>::throwConversionError();
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000081 }
82 return it->second;
83}
84
85template <class T, size_t N>
86inline std::string_view
87 enumToString(const std::array<std::pair<std::string_view, T>, N>& data,
88 T value)
89{
90 auto it = std::find_if(
91 std::begin(data), std::end(data),
92 [value](const auto& item) { return item.second == value; });
93 if (it == std::end(data))
94 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010095 EnumTraits<T>::throwConversionError();
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000096 }
97 return it->first;
98}
99
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100100} // namespace utils