1 /** 2 * Copyright © 2018 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 #include <boost/asio/spawn.hpp> 18 #include <boost/callable_traits.hpp> 19 #include <cstdint> 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <tuple> 24 #include <type_traits> 25 #include <vector> 26 27 namespace ipmi 28 { 29 30 struct Context; 31 32 namespace utility 33 { 34 35 /** 36 * @brief a utility template to extract the args after N from a tuple 37 * 38 * Given a tuple of type <T1, ...TN, TN+1, ...>, provide type = tuple<TN+1,...> 39 */ 40 template <std::size_t N, typename FirstArg, typename... Rest> 41 struct StripFirstArgs; 42 43 template <std::size_t N, typename FirstArg, typename... Rest> 44 struct StripFirstArgs<N, std::tuple<FirstArg, Rest...>> 45 : StripFirstArgs<N - 1, std::tuple<Rest...>> 46 { 47 }; 48 49 template <typename FirstArg, typename... Rest> 50 struct StripFirstArgs<0, std::tuple<FirstArg, Rest...>> 51 { 52 using type = std::tuple<FirstArg, Rest...>; 53 }; 54 template <std::size_t N> 55 struct StripFirstArgs<N, std::tuple<>> 56 { 57 using type = std::tuple<>; 58 }; 59 60 /** 61 * @brief a utility template to extract the remaining args from a tuple 62 * 63 * Given a tuple of type <T1, T2,...>, provide type = tuple<T2,...> 64 */ 65 template <typename T> 66 using StripFirstArg = StripFirstArgs<1, T>; 67 68 /** 69 * @brief a utility template to find the number of non-special arguments 70 * 71 * Given a tuple, count the args after the first special args 72 */ 73 template <typename FirstArg, typename... Rest> 74 struct NonIpmiArgsCount; 75 76 template <> 77 struct NonIpmiArgsCount<std::tuple<>> 78 { 79 constexpr static std::size_t size() 80 { 81 return 0; 82 } 83 }; 84 template <typename FirstArg, typename... OtherArgs> 85 struct NonIpmiArgsCount<std::tuple<FirstArg, OtherArgs...>> 86 { 87 constexpr static std::size_t size() 88 { 89 if constexpr (std::is_same<FirstArg, ipmi::Context>::value || 90 std::is_same<FirstArg, boost::asio::yield_context>::value) 91 { 92 return 1 + NonIpmiArgsCount<std::tuple<OtherArgs...>>::size(); 93 } 94 else 95 { 96 return NonIpmiArgsCount<std::tuple<OtherArgs...>>::size(); 97 } 98 } 99 }; 100 101 /** 102 * @brief a utility template to find the type of the first arg 103 * 104 * Given a tuple, provide the type of the first element 105 */ 106 template <typename T> 107 struct GetFirstArg 108 { 109 using type = void; 110 }; 111 112 template <typename FirstArg, typename... Rest> 113 struct GetFirstArg<std::tuple<FirstArg, Rest...>> 114 { 115 using type = FirstArg; 116 }; 117 118 /** 119 * @brief a utility template to remove const and reference from types 120 * 121 * Given a tuple, provide the type of the first element 122 */ 123 template <typename... Args> 124 struct DecayTuple; 125 126 template <typename... Args> 127 struct DecayTuple<std::tuple<Args...>> 128 { 129 using type = std::tuple<typename std::decay<Args>::type...>; 130 }; 131 132 /** @brief Convert T[N] to T* if is_same<Tbase,T> 133 * 134 * @tparam Tbase - The base type expected. 135 * @tparam T - The type to convert. 136 */ 137 template <typename Tbase, typename T> 138 using ArrayToPtr_t = typename std::conditional_t< 139 std::is_array<T>::value, 140 std::conditional_t<std::is_same<Tbase, std::remove_extent_t<T>>::value, 141 std::add_pointer_t<std::remove_extent_t<T>>, T>, 142 T>; 143 144 /** @brief Downcast type submembers. 145 * 146 * This allows std::tuple and std::pair members to be downcast to their 147 * non-const, nonref versions of themselves to limit duplication in template 148 * specializations 149 * 150 * 1. Remove references. 151 * 2. Remove 'const' and 'volatile'. 152 * 3. Convert 'char[N]' to 'char*'. 153 */ 154 template <typename T> 155 struct DowncastMembers 156 { 157 using type = T; 158 }; 159 template <typename... Args> 160 struct DowncastMembers<std::pair<Args...>> 161 { 162 using type = std::pair<utility::ArrayToPtr_t< 163 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>; 164 }; 165 166 template <typename... Args> 167 struct DowncastMembers<std::tuple<Args...>> 168 { 169 using type = std::tuple<utility::ArrayToPtr_t< 170 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>; 171 }; 172 173 template <typename T> 174 using DowncastMembers_t = typename DowncastMembers<T>::type; 175 176 /** @brief Convert some C++ types to others for 'TypeId' conversion purposes. 177 * 178 * Similar C++ types have the same dbus type-id, so 'downcast' those to limit 179 * duplication in TypeId template specializations. 180 * 181 * 1. Remove references. 182 * 2. Remove 'const' and 'volatile'. 183 * 3. Convert 'char[N]' to 'char*'. 184 */ 185 template <typename T> 186 struct TypeIdDowncast 187 { 188 using type = utility::ArrayToPtr_t< 189 char, DowncastMembers_t<std::remove_cv_t<std::remove_reference_t<T>>>>; 190 }; 191 192 template <typename T> 193 using TypeIdDowncast_t = typename TypeIdDowncast<T>::type; 194 195 /** @brief Detect if a type is a tuple 196 * 197 */ 198 template <typename> 199 struct is_tuple : std::false_type 200 { 201 }; 202 203 template <typename... T> 204 struct is_tuple<std::tuple<T...>> : std::true_type 205 { 206 }; 207 208 } // namespace utility 209 210 } // namespace ipmi 211