1 #pragma once
2 
3 #include <cstddef>
4 #include <optional>
5 #include <tuple>
6 #include <type_traits>
7 
8 namespace sdbusplus
9 {
10 
11 namespace utility
12 {
13 
14 /** @brief Retrieve the first type from a parameter pack
15  *
16  * @tparam Types - the parameter pack
17  */
18 template <typename... Types>
19 using first_type_t = std::tuple_element_t<0, std::tuple<Types...>>;
20 
21 /** @brief Convert T[N] to T* if is_same<Tbase,T>
22  *
23  *  @tparam Tbase - The base type expected.
24  *  @tparam T - The type to convert.
25  */
26 template <typename Tbase, typename T>
27 using array_to_ptr_t = typename std::conditional_t<
28     std::is_array_v<T>,
29     std::conditional_t<std::is_same_v<Tbase, std::remove_extent_t<T>>,
30                        std::add_pointer_t<std::remove_extent_t<T>>, T>,
31     T>;
32 
33 template <std::size_t N, typename FirstArg, typename... Rest>
34 struct strip_first_n_args;
35 
36 template <std::size_t N, typename FirstArg, typename... Rest>
37 struct strip_first_n_args<N, std::tuple<FirstArg, Rest...>> :
38     strip_first_n_args<N - 1, std::tuple<Rest...>>
39 {};
40 
41 template <typename FirstArg, typename... Rest>
42 struct strip_first_n_args<0, std::tuple<FirstArg, Rest...>>
43 {
44     using type = std::tuple<FirstArg, Rest...>;
45 };
46 template <std::size_t N>
47 struct strip_first_n_args<N, std::tuple<>>
48 {
49     using type = std::tuple<>;
50 };
51 
52 template <std::size_t N, typename... Args>
53 using strip_first_n_args_t = typename strip_first_n_args<N, Args...>::type;
54 
55 // Small helper class for stripping off the error code from the function
56 // argument definitions so unpack can be called appropriately
57 template <typename T>
58 using strip_first_arg = strip_first_n_args<1, T>;
59 
60 template <typename T>
61 using strip_first_arg_t = typename strip_first_arg<T>::type;
62 
63 // matching helper class to only return the first type
64 template <typename T>
65 struct get_first_arg
66 {
67     using type = void;
68 };
69 
70 template <typename FirstArg, typename... Rest>
71 struct get_first_arg<std::tuple<FirstArg, Rest...>>
72 {
73     using type = FirstArg;
74 };
75 
76 template <typename... Args>
77 using get_first_arg_t = typename get_first_arg<Args...>::type;
78 
79 // helper class to remove const and reference from types
80 template <typename T>
81 struct decay_tuple
82 {};
83 
84 template <typename... Args>
85 struct decay_tuple<std::tuple<Args...>>
86 {
87     using type = std::tuple<typename std::decay<Args>::type...>;
88 };
89 
90 template <typename... Args>
91 using decay_tuple_t = typename decay_tuple<Args...>::type;
92 
93 // Small helper class for stripping off the first + last character of a char
94 // array
95 template <std::size_t N, std::size_t... Is>
strip_ends(const std::array<char,N> & s,std::index_sequence<Is...>)96 constexpr std::array<char, N - 2> strip_ends(const std::array<char, N>& s,
97                                              std::index_sequence<Is...>)
98 {
99     return {(s[1 + Is])..., static_cast<char>(0)};
100 }
101 
102 template <std::size_t N>
strip_ends(const std::array<char,N> & s)103 constexpr std::array<char, N - 2> strip_ends(const std::array<char, N>& s)
104 {
105     return strip_ends(s, std::make_index_sequence<N - 3>{});
106 }
107 
108 template <typename T>
109 class has_member_find
110 {
111   private:
112     template <typename U>
113     static U& ref();
114 
115     template <typename U>
116     static std::true_type check(decltype(ref<U>().find(
117         ref<std::tuple_element_t<0, typename U::value_type>>()))*);
118     template <typename>
119     static std::false_type check(...);
120 
121   public:
122     static constexpr bool value =
123         decltype(check<std::decay_t<T>>(nullptr))::value;
124 };
125 
126 template <typename T>
127 constexpr bool has_member_find_v = has_member_find<T>::value;
128 
129 template <typename T>
130 class has_member_contains
131 {
132   private:
133     template <typename U>
134     static U& ref();
135 
136     template <typename U>
137     static std::true_type check(decltype(ref<U>().contains(
138         ref<std::tuple_element_t<0, typename U::value_type>>()))*);
139     template <typename>
140     static std::false_type check(...);
141 
142   public:
143     static constexpr bool value =
144         decltype(check<std::decay_t<T>>(nullptr))::value;
145 };
146 
147 template <typename T>
148 constexpr bool has_member_contains_v = has_member_contains<T>::value;
149 
150 template <typename T>
151 struct is_optional : public std::false_type
152 {};
153 
154 template <typename T>
155 struct is_optional<std::optional<T>> : public std::true_type
156 {};
157 
158 template <typename T>
159 struct is_optional<const std::optional<T>> : public std::true_type
160 {};
161 
162 template <typename T>
163 struct is_optional<std::optional<T>&> : public std::true_type
164 {};
165 
166 template <typename T>
167 struct is_optional<const std::optional<T>&> : public std::true_type
168 {};
169 
170 template <typename T>
171 constexpr bool is_optional_v = is_optional<T>::value;
172 
173 } // namespace utility
174 
175 } // namespace sdbusplus
176