| #pragma once |
| |
| #include <sdbusplus/exception.hpp> |
| #include <sdbusplus/utility/type_traits.hpp> |
| |
| #include <algorithm> |
| #include <bitset> |
| #include <optional> |
| #include <stdexcept> |
| #include <string> |
| #include <string_view> |
| #include <variant> |
| #include <vector> |
| |
| namespace sdbusplus |
| { |
| |
| namespace details |
| { |
| |
| template <typename VariantType> |
| inline auto findProperty( |
| const std::vector<std::pair<std::string, VariantType>>& container, |
| const std::string& key) noexcept |
| { |
| return std::find_if( |
| container.begin(), container.end(), |
| [&key](const auto& keyValue) { return keyValue.first == key; }); |
| } |
| |
| template <typename OnErrorCallback, typename VariantType, typename ValueType> |
| inline bool readProperty( |
| const OnErrorCallback& onErrorCallback, |
| const std::vector<std::pair<std::string, VariantType>>& container, |
| const std::string& expectedKey, |
| ValueType& |
| outValue) noexcept(noexcept(onErrorCallback(sdbusplus:: |
| UnpackErrorReason{}, |
| std::string{}))) |
| { |
| auto it = findProperty(container, expectedKey); |
| |
| if (it != container.end()) |
| { |
| if constexpr (std::is_pointer_v<ValueType>) |
| { |
| if (const auto* value = std::get_if< |
| std::remove_cv_t<std::remove_pointer_t<ValueType>>>( |
| &it->second)) |
| { |
| outValue = value; |
| } |
| else |
| { |
| onErrorCallback(UnpackErrorReason::wrongType, expectedKey); |
| return false; |
| } |
| } |
| else if constexpr (utility::is_optional_v<ValueType>) |
| { |
| using InnerType = typename ValueType::value_type; |
| static_assert(!std::is_pointer_v<InnerType>, |
| "std::optional<T*> is not supported"); |
| if (const auto value = std::get_if<InnerType>(&it->second)) |
| |
| { |
| outValue = *value; |
| } |
| else |
| { |
| onErrorCallback(UnpackErrorReason::wrongType, expectedKey); |
| return false; |
| } |
| } |
| else |
| { |
| if (const auto value = std::get_if<ValueType>(&it->second)) |
| { |
| outValue = *value; |
| } |
| else |
| { |
| onErrorCallback(UnpackErrorReason::wrongType, expectedKey); |
| return false; |
| } |
| } |
| } |
| else if constexpr (!utility::is_optional_v<ValueType> && |
| !std::is_pointer_v<ValueType>) |
| { |
| onErrorCallback(UnpackErrorReason::missingProperty, expectedKey); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| template <typename OnErrorCallback, typename VariantType, typename ValueType, |
| typename... Args> |
| inline bool readProperties( |
| OnErrorCallback&& onErrorCallback, |
| const std::vector<std::pair<std::string, VariantType>>& container, |
| const std::string& expectedKey, ValueType& outValue, |
| Args&&... args) noexcept(noexcept(onErrorCallback(sdbusplus:: |
| UnpackErrorReason{}, |
| std::string{}))) |
| { |
| if (!readProperty(onErrorCallback, container, expectedKey, outValue)) |
| { |
| return false; |
| } |
| |
| if constexpr (sizeof...(Args) > 0) |
| { |
| return readProperties(std::forward<OnErrorCallback>(onErrorCallback), |
| container, std::forward<Args>(args)...); |
| } |
| |
| return true; |
| } |
| |
| template <typename OnErrorCallback, typename VariantType, typename... Args> |
| inline auto unpackPropertiesCommon( |
| OnErrorCallback&& onErrorCallback, |
| const std::vector<std::pair<std::string, VariantType>>& input, |
| Args&&... args) noexcept(noexcept(onErrorCallback(sdbusplus:: |
| UnpackErrorReason{}, |
| std::string{}))) |
| { |
| static_assert( |
| sizeof...(Args) % 2 == 0, |
| "Expected number of arguments to be even, but got odd number instead"); |
| |
| return details::readProperties( |
| std::forward<OnErrorCallback>(onErrorCallback), input, |
| std::forward<Args>(args)...); |
| } |
| |
| } // namespace details |
| |
| template <typename VariantType, typename... Args> |
| inline void unpackProperties( |
| const std::vector<std::pair<std::string, VariantType>>& input, |
| Args&&... args) |
| { |
| details::unpackPropertiesCommon( |
| [](const UnpackErrorReason reason, const std::string& property) { |
| throw exception::UnpackPropertyError(property, reason); |
| }, |
| input, std::forward<Args>(args)...); |
| } |
| |
| template <typename OnErrorCallback, typename VariantType, typename... Args> |
| inline bool unpackPropertiesNoThrow( |
| OnErrorCallback&& onErrorCallback, |
| const std::vector<std::pair<std::string, VariantType>>& input, |
| Args&&... args) noexcept |
| { |
| return details::unpackPropertiesCommon( |
| std::forward<OnErrorCallback>(onErrorCallback), input, |
| std::forward<Args>(args)...); |
| } |
| |
| } // namespace sdbusplus |