blob: 3a364348716cb4c6c1b5e3f77877737140f8d4e3 [file] [log] [blame]
Vernon Mauerye7329c72018-10-08 12:05:16 -07001/**
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
27namespace ipmi
28{
29
30struct Context;
31
32namespace 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 */
40template <std::size_t N, typename FirstArg, typename... Rest>
41struct StripFirstArgs;
42
43template <std::size_t N, typename FirstArg, typename... Rest>
44struct StripFirstArgs<N, std::tuple<FirstArg, Rest...>>
45 : StripFirstArgs<N - 1, std::tuple<Rest...>>
46{
47};
48
49template <typename FirstArg, typename... Rest>
50struct StripFirstArgs<0, std::tuple<FirstArg, Rest...>>
51{
52 using type = std::tuple<FirstArg, Rest...>;
53};
54template <std::size_t N>
55struct 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 */
65template <typename T>
66using 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 */
73template <typename FirstArg, typename... Rest>
74struct NonIpmiArgsCount;
75
76template <>
77struct NonIpmiArgsCount<std::tuple<>>
78{
79 constexpr static std::size_t size()
80 {
81 return 0;
82 }
83};
84template <typename FirstArg, typename... OtherArgs>
85struct 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 */
106template <typename T>
107struct GetFirstArg
108{
109 using type = void;
110};
111
112template <typename FirstArg, typename... Rest>
113struct 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 */
123template <typename... Args>
124struct DecayTuple;
125
126template <typename... Args>
127struct 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 */
137template <typename Tbase, typename T>
138using 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 */
154template <typename T>
155struct DowncastMembers
156{
157 using type = T;
158};
159template <typename... Args>
160struct 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
166template <typename... Args>
167struct 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
173template <typename T>
174using 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 */
185template <typename T>
186struct TypeIdDowncast
187{
188 using type = utility::ArrayToPtr_t<
189 char, DowncastMembers_t<std::remove_cv_t<std::remove_reference_t<T>>>>;
190};
191
192template <typename T>
193using TypeIdDowncast_t = typename TypeIdDowncast<T>::type;
194
195/** @brief Detect if a type is a tuple
196 *
197 */
198template <typename>
199struct is_tuple : std::false_type
200{
201};
202
203template <typename... T>
204struct is_tuple<std::tuple<T...>> : std::true_type
205{
206};
207
208} // namespace utility
209
210} // namespace ipmi