blob: ea37c4f5c08cf8a705dc399c81d8b50dd3162381 [file] [log] [blame]
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01001#pragma once
2
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +02003#include "errors.hpp"
4
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01005#include <sdbusplus/exception.hpp>
6
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00007#include <algorithm>
8#include <array>
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01009#include <stdexcept>
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000010#include <string>
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010011
12namespace utils
13{
14
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020015template <size_t N>
16struct ConstexprString
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010017{
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020018 constexpr ConstexprString(const char (&data)[N]) : s()
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010019 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020020 for (size_t i = 0; i < N; ++i)
21 {
22 s[i] = data[i];
23 }
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010024 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020025
26 constexpr operator std::string_view() const
27 {
28 return {s.data(), s.size()};
29 }
30
31 std::array<char, N> s;
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010032};
33
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020034[[noreturn]] inline void throwConversionError(std::string_view propertyName)
35{
36 throw errors::InvalidArgument(propertyName, "Cannot convert.");
37}
38
39template <class T>
40struct EnumTraits;
41
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010042template <class T, T first, T last>
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000043inline T toEnum(std::underlying_type_t<T> x)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010044{
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000045 if (x < static_cast<std::underlying_type_t<T>>(first) ||
46 x > static_cast<std::underlying_type_t<T>>(last))
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010047 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020048 throwConversionError(EnumTraits<T>::propertyName);
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010049 }
50 return static_cast<T>(x);
51}
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000052
53template <class T>
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010054constexpr inline std::underlying_type_t<T> toUnderlying(T value)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000055{
56 return static_cast<std::underlying_type_t<T>>(value);
57}
58
59template <class T, size_t N>
Patrick Williams583ba442025-02-03 14:28:19 -050060constexpr inline T minEnumValue(
61 std::array<std::pair<std::string_view, T>, N> data)
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010062{
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
74template <class T, size_t N>
Patrick Williams583ba442025-02-03 14:28:19 -050075constexpr inline T maxEnumValue(
76 std::array<std::pair<std::string_view, T>, N> data)
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010077{
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
89template <class T, size_t N>
90inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data,
91 const std::string& value)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000092{
Patrick Williamsc7935fa2023-10-20 11:19:30 -050093 auto it = std::find_if(
94 std::begin(data), std::end(data),
95 [&value](const auto& item) { return item.first == value; });
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000096 if (it == std::end(data))
97 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020098 throwConversionError(EnumTraits<T>::propertyName);
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000099 }
100 return it->second;
101}
102
103template <class T, size_t N>
Patrick Williams583ba442025-02-03 14:28:19 -0500104inline std::string_view enumToString(
105 const std::array<std::pair<std::string_view, T>, N>& data, T value)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000106{
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500107 auto it = std::find_if(
108 std::begin(data), std::end(data),
109 [value](const auto& item) { return item.second == value; });
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000110 if (it == std::end(data))
111 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200112 throwConversionError(EnumTraits<T>::propertyName);
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000113 }
114 return it->first;
115}
116
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100117} // namespace utils