xref: /openbmc/telemetry/src/utils/conversion.hpp (revision c7935fa1)
1d960e1f3SWludzik, Jozef #pragma once
2d960e1f3SWludzik, Jozef 
362c08e9bSKrzysztof Grobelny #include "errors.hpp"
462c08e9bSKrzysztof Grobelny 
5b8cc78ddSKrzysztof Grobelny #include <sdbusplus/exception.hpp>
6b8cc78ddSKrzysztof Grobelny 
7e8fc5751SKrzysztof Grobelny #include <algorithm>
8e8fc5751SKrzysztof Grobelny #include <array>
9d960e1f3SWludzik, Jozef #include <stdexcept>
10e8fc5751SKrzysztof Grobelny #include <string>
11d960e1f3SWludzik, Jozef 
12d960e1f3SWludzik, Jozef namespace utils
13d960e1f3SWludzik, Jozef {
14d960e1f3SWludzik, Jozef 
1562c08e9bSKrzysztof Grobelny template <size_t N>
1662c08e9bSKrzysztof Grobelny struct ConstexprString
1751497a0cSKrzysztof Grobelny {
ConstexprStringutils::ConstexprString1862c08e9bSKrzysztof Grobelny     constexpr ConstexprString(const char (&data)[N]) : s()
1951497a0cSKrzysztof Grobelny     {
2062c08e9bSKrzysztof Grobelny         for (size_t i = 0; i < N; ++i)
2162c08e9bSKrzysztof Grobelny         {
2262c08e9bSKrzysztof Grobelny             s[i] = data[i];
2351497a0cSKrzysztof Grobelny         }
2462c08e9bSKrzysztof Grobelny     }
2562c08e9bSKrzysztof Grobelny 
operator std::string_viewutils::ConstexprString2662c08e9bSKrzysztof Grobelny     constexpr operator std::string_view() const
2762c08e9bSKrzysztof Grobelny     {
2862c08e9bSKrzysztof Grobelny         return {s.data(), s.size()};
2962c08e9bSKrzysztof Grobelny     }
3062c08e9bSKrzysztof Grobelny 
3162c08e9bSKrzysztof Grobelny     std::array<char, N> s;
3251497a0cSKrzysztof Grobelny };
3351497a0cSKrzysztof Grobelny 
throwConversionError(std::string_view propertyName)3462c08e9bSKrzysztof Grobelny [[noreturn]] inline void throwConversionError(std::string_view propertyName)
3562c08e9bSKrzysztof Grobelny {
3662c08e9bSKrzysztof Grobelny     throw errors::InvalidArgument(propertyName, "Cannot convert.");
3762c08e9bSKrzysztof Grobelny }
3862c08e9bSKrzysztof Grobelny 
3962c08e9bSKrzysztof Grobelny template <class T>
4062c08e9bSKrzysztof Grobelny struct EnumTraits;
4162c08e9bSKrzysztof Grobelny 
42d960e1f3SWludzik, Jozef template <class T, T first, T last>
toEnum(std::underlying_type_t<T> x)43e8fc5751SKrzysztof Grobelny inline T toEnum(std::underlying_type_t<T> x)
44d960e1f3SWludzik, Jozef {
45e8fc5751SKrzysztof Grobelny     if (x < static_cast<std::underlying_type_t<T>>(first) ||
46e8fc5751SKrzysztof Grobelny         x > static_cast<std::underlying_type_t<T>>(last))
47d960e1f3SWludzik, Jozef     {
4862c08e9bSKrzysztof Grobelny         throwConversionError(EnumTraits<T>::propertyName);
49d960e1f3SWludzik, Jozef     }
50d960e1f3SWludzik, Jozef     return static_cast<T>(x);
51d960e1f3SWludzik, Jozef }
52e8fc5751SKrzysztof Grobelny 
53e8fc5751SKrzysztof Grobelny template <class T>
toUnderlying(T value)5451497a0cSKrzysztof Grobelny constexpr inline std::underlying_type_t<T> toUnderlying(T value)
55e8fc5751SKrzysztof Grobelny {
56e8fc5751SKrzysztof Grobelny     return static_cast<std::underlying_type_t<T>>(value);
57e8fc5751SKrzysztof Grobelny }
58e8fc5751SKrzysztof Grobelny 
59e8fc5751SKrzysztof Grobelny template <class T, size_t N>
6051497a0cSKrzysztof Grobelny constexpr inline T
minEnumValue(std::array<std::pair<std::string_view,T>,N> data)6151497a0cSKrzysztof Grobelny     minEnumValue(std::array<std::pair<std::string_view, T>, N> data)
6251497a0cSKrzysztof Grobelny {
6351497a0cSKrzysztof Grobelny     auto min = data[0].second;
6451497a0cSKrzysztof Grobelny     for (auto [key, value] : data)
6551497a0cSKrzysztof Grobelny     {
6651497a0cSKrzysztof Grobelny         if (toUnderlying(min) > toUnderlying(value))
6751497a0cSKrzysztof Grobelny         {
6851497a0cSKrzysztof Grobelny             min = value;
6951497a0cSKrzysztof Grobelny         }
7051497a0cSKrzysztof Grobelny     }
7151497a0cSKrzysztof Grobelny     return min;
7251497a0cSKrzysztof Grobelny }
7351497a0cSKrzysztof Grobelny 
7451497a0cSKrzysztof Grobelny template <class T, size_t N>
7551497a0cSKrzysztof Grobelny constexpr inline T
maxEnumValue(std::array<std::pair<std::string_view,T>,N> data)7651497a0cSKrzysztof Grobelny     maxEnumValue(std::array<std::pair<std::string_view, T>, N> data)
7751497a0cSKrzysztof Grobelny {
7851497a0cSKrzysztof Grobelny     auto max = data[0].second;
7951497a0cSKrzysztof Grobelny     for (auto [key, value] : data)
8051497a0cSKrzysztof Grobelny     {
8151497a0cSKrzysztof Grobelny         if (toUnderlying(max) < toUnderlying(value))
8251497a0cSKrzysztof Grobelny         {
8351497a0cSKrzysztof Grobelny             max = value;
8451497a0cSKrzysztof Grobelny         }
8551497a0cSKrzysztof Grobelny     }
8651497a0cSKrzysztof Grobelny     return max;
8751497a0cSKrzysztof Grobelny }
8851497a0cSKrzysztof Grobelny 
8951497a0cSKrzysztof Grobelny template <class T, size_t N>
toEnum(const std::array<std::pair<std::string_view,T>,N> & data,const std::string & value)9051497a0cSKrzysztof Grobelny inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data,
91e8fc5751SKrzysztof Grobelny                 const std::string& value)
92e8fc5751SKrzysztof Grobelny {
93*c7935fa1SPatrick Williams     auto it = std::find_if(
94*c7935fa1SPatrick Williams         std::begin(data), std::end(data),
95*c7935fa1SPatrick Williams         [&value](const auto& item) { return item.first == value; });
96e8fc5751SKrzysztof Grobelny     if (it == std::end(data))
97e8fc5751SKrzysztof Grobelny     {
9862c08e9bSKrzysztof Grobelny         throwConversionError(EnumTraits<T>::propertyName);
99e8fc5751SKrzysztof Grobelny     }
100e8fc5751SKrzysztof Grobelny     return it->second;
101e8fc5751SKrzysztof Grobelny }
102e8fc5751SKrzysztof Grobelny 
103e8fc5751SKrzysztof Grobelny template <class T, size_t N>
104e8fc5751SKrzysztof Grobelny inline std::string_view
enumToString(const std::array<std::pair<std::string_view,T>,N> & data,T value)105e8fc5751SKrzysztof Grobelny     enumToString(const std::array<std::pair<std::string_view, T>, N>& data,
106e8fc5751SKrzysztof Grobelny                  T value)
107e8fc5751SKrzysztof Grobelny {
108*c7935fa1SPatrick Williams     auto it = std::find_if(
109*c7935fa1SPatrick Williams         std::begin(data), std::end(data),
110*c7935fa1SPatrick Williams         [value](const auto& item) { return item.second == value; });
111e8fc5751SKrzysztof Grobelny     if (it == std::end(data))
112e8fc5751SKrzysztof Grobelny     {
11362c08e9bSKrzysztof Grobelny         throwConversionError(EnumTraits<T>::propertyName);
114e8fc5751SKrzysztof Grobelny     }
115e8fc5751SKrzysztof Grobelny     return it->first;
116e8fc5751SKrzysztof Grobelny }
117e8fc5751SKrzysztof Grobelny 
118d960e1f3SWludzik, Jozef } // namespace utils
119