summaryrefslogtreecommitdiffstats
path: root/utils.hpp
blob: 2fd0805d7179b5a2d5b875212423dcf488252ef4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#pragma once

namespace phosphor
{
namespace inventory
{
namespace manager
{
/** @struct MakeVariantVisitor
 *  @brief Return a variant if the visited type is a possible variant type.
 *
 *  @tparam V - The desired variant type.
 */
template <typename V>
struct MakeVariantVisitor
{
    /** @struct Make
     *  @brief Return variant visitor.
     *
     *  @tparam T - The variant type to return.
     *  @tparam Arg - The type being visited in the source variant.
     *  @tparam Enable - Overload resolution removal.
     */
    template <typename T, typename Arg, typename Enable = void>
    struct Make
    {
        static auto make(Arg&& arg)
        {
            throw std::runtime_error(
                "Invalid conversion in MakeVariantVisitor");
            return T();
        }
    };

    /** @struct Make
     *  @brief Return variant visitor.
     *
     *  struct Make specialization if Arg is in T (int -> variant<int, char>).
     */
    template <typename T, typename Arg>
    struct Make<
        T, Arg,
        typename std::enable_if<std::is_convertible<Arg, T>::value>::type>
    {
        static auto make(Arg&& arg)
        {
            return T(std::forward<Arg>(arg));
        }
    };

    /** @brief Make variant visitor.  */
    template <typename Arg>
    auto operator()(Arg&& arg) const
    {
        return Make<V, Arg>::make(arg);
    }
};

/** @brief Convert variants with different contained types.
 *
 *  @tparam V - The desired variant type.
 *  @tparam Arg - The source variant type.
 *
 *  @param[in] v - The source variant.
 *  @returns - The converted variant.
 */
template <typename V, typename Arg>
auto convertVariant(Arg&& v)
{
    return sdbusplus::message::variant_ns::visit(MakeVariantVisitor<V>(), v);
}

/** @struct CompareFirst
 *  @brief std::pair binary comparison adapter.
 *
 *  Adapt a binary comparison function to a comparison of
 *  the first pair element.
 *
 *  @tparam Compare - The function object type being adapted.
 */
template <typename Compare>
struct CompareFirst
{
    /** @brief Construct a CompareFirst adapter.
     *
     *  @param[in] c - The function object being adapted.
     */
    explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c))
    {
    }

    /** @brief Compare two pairs adapter.
     *
     *  @tparam L1 - First pair first_type.
     *  @tparam L2 - First pair second_type.
     *  @tparam R1 - Second pair first_type, convertible to L1.
     *  @tparam R2 - Second pair second_type.
     *
     *  @param[in] l - The first pair.
     *  @param[in] r - The second pair.
     *
     *  @returns - The result of the comparison.
     */
    template <typename L1, typename L2, typename R1, typename R2>
    bool operator()(const std::pair<L1, L2>& l,
                    const std::pair<R1, R2>& r) const
    {
        return compare(l.first, r.first);
    }

    /** @brief Compare one pair adapter.
     *
     *  @tparam L1 - Pair first_type.
     *  @tparam L2 - Pair second_type.
     *  @tparam R - Convertible to L1 for comparison.
     *
     *  @param[in] l - The pair.
     *  @param[in] r - To be compared to l.first.
     *
     *  @returns - The result of the comparison.
     */
    template <typename L1, typename L2, typename R>
    bool operator()(const std::pair<L1, L2>& l, const R& r) const
    {
        return compare(l.first, r);
    }

    /** @brief Compare one pair adapter.
     *
     *  @tparam L - Convertible to R1 for comparison.
     *  @tparam R1 - Pair first_type.
     *  @tparam R2 - Pair second_type.
     *
     *  @param[in] l - To be compared to r.first.
     *  @param[in] r - The pair.
     *
     *  @returns - The result of the comparison.
     */
    template <typename L, typename R1, typename R2>
    bool operator()(const L& l, const std::pair<R1, R2>& r) const
    {
        return compare(l, r.first);
    }

    /* @brief The function being adapted. */
    Compare compare;
};

/* @brief Implicit template instantation wrapper for CompareFirst. */
template <typename Compare>
CompareFirst<Compare> compareFirst(Compare&& c)
{
    return CompareFirst<Compare>(std::forward<Compare>(c));
}

/** @struct RelPathCompare
 *  @brief Compare two strings after removing an optional prefix.
 */
struct RelPathCompare
{
    /** @brief Construct a RelPathCompare comparison functor.
     *
     *  @param[in] p - The prefix to check for and remove.
     */
    explicit RelPathCompare(const char* p) : prefix(p)
    {
    }

    /** @brief Check for the prefix and remove if found.
     *
     *  @param[in] s - The string to check for and remove prefix from.
     */
    auto relPath(const std::string& s) const
    {
        if (s.find(prefix) == 0)
        {
            return s.substr(strlen(prefix));
        }

        return s;
    }

    /** @brief Comparison method.
     *
     *  @param[in] l - The first string.
     *  @param[in] r - The second string.
     *
     *  @returns - The result of the comparison.
     */
    bool operator()(const std::string& l, const std::string& r) const
    {
        return relPath(l) < relPath(r);
    }

    /* The path prefix to remove when comparing two paths. */
    const char* prefix;
};
} // namespace manager
} // namespace inventory
} // namespace phosphor

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
OpenPOWER on IntegriCloud