1#pragma once 2#include <algorithm> 3#include <array> 4#include <optional> 5#include <string> 6#include <string_view> 7#include <tuple> 8 9#include <sdbusplus/exception.hpp> 10#include <sdbusplus/message.hpp> 11#include <sdbusplus/utility/dedup_variant.hpp> 12<% 13 def setOfPropertyTypes(): 14 return set(p.cppTypeParam(interface.name) for p in 15 interface.properties); 16%>\ 17 18namespace sdbusplus::common::${interface.cppNamespace()} 19{ 20 21struct ${interface.classname} 22{ 23 static constexpr auto interface = "${interface.name}"; 24 25 % for e in interface.enums: 26 enum class ${e.name} 27 { 28 % for v in e.values: 29 ${v.name}, 30 % endfor 31 }; 32 % endfor 33 34 % if interface.properties: 35 using PropertiesVariant = sdbusplus::utility::dedup_variant_t< 36 ${",\n ".join(sorted(setOfPropertyTypes()))}>; 37 % endif \ 38 39 % for p in interface.paths: 40 % if p.description: 41 /** ${p.description.strip()} */ 42 % endif 43 % if len(p.segments) == 0: 44 static constexpr auto ${p.snake_case} = "${p.value}"; 45 % else: 46 struct ${p.snake_case} 47 { 48 static constexpr auto value = "${p.value}"; 49 % for s in p.segments: 50 % if s.description: 51 /** ${s.description.strip()} */ 52 % endif 53 static constexpr auto ${s.snake_case} = "${s.value}"; 54 % endfor 55 }; 56 % endif 57 % endfor 58 % for s in interface.service_names: 59 % if s.description: 60 /** ${s.description.strip()} */ 61 % endif 62 static constexpr auto ${s.snake_case} = "${s.value}"; 63 % endfor 64 65 % for e in interface.enums: 66 /** @brief Convert a string to an appropriate enum value. 67 * @param[in] s - The string to convert in the form of 68 * "${interface.name}.<value name>" 69 * @return - The enum value. 70 * 71 * @note Throws if string is not a valid mapping. 72 */ 73 static ${e.name} convert${e.name}FromString(const std::string& s); 74 75 /** @brief Convert a string to an appropriate enum value. 76 * @param[in] s - The string to convert in the form of 77 * "${interface.name}.<value name>" 78 * @return - The enum value or std::nullopt 79 */ 80 static std::optional<${e.name}> 81 convertStringTo${e.name}(const std::string& s) noexcept; 82 83 /** @brief Convert an enum value to a string. 84 * @param[in] e - The enum to convert to a string. 85 * @return - The string conversion in the form of 86 * "${interface.name}.<value name>" 87 */ 88 static std::string convert${e.name}ToString(${e.name} e); 89 % endfor 90}; 91 92% for e in interface.enums: 93/* Specialization of sdbusplus::common::convertForMessage 94 * for enum-type ${interface.classname}::${e.name}. 95 * 96 * This converts from the enum to a constant string representing the enum. 97 * 98 * @param[in] e - Enum value to convert. 99 * @return string representing the name for the enum value. 100 */ 101inline std::string convertForMessage(${interface.classname}::${e.name} e) 102{ 103 return ${interface.classname}::convert${e.name}ToString(e); 104} 105% endfor 106 107 % for e in interface.enums: 108 109namespace details 110{ 111using namespace std::literals::string_view_literals; 112 113/** String to enum mapping for ${interface.classname}::${e.name} */ 114inline constexpr std::array mapping${interface.classname}${e.name} = { 115 % for v in e.values: 116 std::make_tuple("${interface.name}.${e.name}.${v.name}"sv, 117 ${interface.classname}::${e.name}::${v.name} ), 118 % endfor 119}; 120} // namespace details 121 122inline auto ${interface.classname}::convertStringTo${e.name}(const std::string& s) noexcept 123 -> std::optional<${e.name}> 124{ 125 auto i = std::find_if(std::begin(details::mapping${interface.classname}${e.name}), 126 std::end(details::mapping${interface.classname}${e.name}), 127 [&s](auto& e){ return s == std::get<0>(e); } ); 128 129 if (std::end(details::mapping${interface.classname}${e.name}) == i) 130 { 131 return std::nullopt; 132 } 133 else 134 { 135 return std::get<1>(*i); 136 } 137} 138 139inline auto ${interface.classname}::convert${e.name}FromString(const std::string& s) -> ${e.name} 140{ 141 auto r = convertStringTo${e.name}(s); 142 143 if (!r) 144 { 145 throw sdbusplus::exception::InvalidEnumString(); 146 } 147 else 148 { 149 return *r; 150 } 151} 152 153inline std::string ${interface.classname}::convert${e.name}ToString( 154 ${interface.classname}::${e.name} v) 155{ 156 auto i = std::find_if(std::begin(details::mapping${interface.classname}${e.name}), 157 std::end(details::mapping${interface.classname}${e.name}), 158 [v](auto& e){ return v == std::get<1>(e); }); 159 160 if (i == std::end(details::mapping${interface.classname}${e.name})) 161 { 162 throw std::invalid_argument(std::to_string(static_cast<int>(v))); 163 } 164 return std::string(std::get<0>(*i)); 165} 166 % endfor 167 168} // sdbusplus::common::${interface.cppNamespace()} 169 170namespace sdbusplus::message::details 171{ 172 % for e in interface.enums: 173template <> 174struct convert_from_string<common::${interface.cppNamespacedClass()}::${e.name}> 175{ 176 static auto op(const std::string& value) noexcept 177 { 178 return common::${interface.cppNamespacedClass()}:: 179 convertStringTo${e.name}(value); 180 } 181}; 182 183template <> 184struct convert_to_string<common::${interface.cppNamespacedClass()}::${e.name}> 185{ 186 static std::string 187 op(common::${interface.cppNamespacedClass()}::${e.name} value) 188 { 189 return common::${interface.cppNamespacedClass()}:: 190 convert${e.name}ToString(value); 191 } 192}; 193 % endfor 194} // namespace sdbusplus::message::details 195