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