blob: e92249a9ba181714f6d33ce88012dcb96dd42a06 [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>
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010060constexpr 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
74template <class T, size_t N>
75constexpr 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
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{
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 {
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>
104inline 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 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200113 throwConversionError(EnumTraits<T>::propertyName);
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000114 }
115 return it->first;
116}
117
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100118} // namespace utils