1 /*
2 metaenum.h
3
4 This file is part of GammaRay, the Qt application inspection and
5 manipulation tool.
6
7 Copyright (C) 2016-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8 Author: Volker Krause <volker.krause@kdab.com>
9
10 Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11 accordance with GammaRay Commercial License Agreement provided with the Software.
12
13 Contact info@kdab.com if any conditions of this licensing are not clear to you.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 */
28
29 #ifndef GAMMARAY_METAENUM_H
30 #define GAMMARAY_METAENUM_H
31
32 #include <QStringList>
33
34 #include <type_traits>
35
36 namespace GammaRay {
37 /** Enum/flag stringification utilities. */
38 namespace MetaEnum {
39 template<typename T>
40 struct Value {
41 T value;
42 const char * const name;
43 };
44
45 template<typename T, std::size_t N>
count(const Value<T> (&)[N])46 std::size_t count(const Value<T>(&)[N])
47 {
48 return N;
49 }
50
51 template<typename T, std::size_t N>
enumToString(T value,const Value<T> (& lookupTable)[N])52 QString enumToString(T value, const Value<T>(&lookupTable)[N])
53 {
54 for (std::size_t i = 0; i < N; ++i) {
55 if (lookupTable[i].value == value)
56 return QString::fromUtf8(lookupTable[i].name);
57 }
58 return QStringLiteral("unknown (") + QString::number(value) + ')';
59 }
60
61 template<typename T, typename F, std::size_t N>
flagsToString(T flags,const Value<F> (& lookupTable)[N])62 QString flagsToString(T flags, const Value<F>(&lookupTable)[N])
63 {
64 QStringList l;
65 T handledFlags = T();
66
67 for (std::size_t i = 0; i < N; ++i) {
68 if (flags & lookupTable[i].value) {
69 l.push_back(QString::fromUtf8(lookupTable[i].name));
70 }
71 handledFlags |= lookupTable[i].value;
72 }
73
74 if (flags & ~handledFlags) {
75 l.push_back(QStringLiteral("flag 0x") +
76 QString::number(qulonglong(flags & ~handledFlags), 16));
77 }
78
79 if (l.isEmpty()) {
80 // check if we have a special 0-value
81 for (std::size_t i = 0; i < N; ++i) {
82 if (lookupTable[i].value == 0)
83 return QString::fromUtf8(lookupTable[i].name);
84 }
85 return QStringLiteral("<none>");
86 }
87 return l.join(QStringLiteral("|"));
88 }
89
90 // functors for easy use with VariantHandler::registerStringConverter
91 namespace detail {
92 template <typename T, std::size_t N>
93 class enum_to_string_functor
94 {
95 public:
enum_to_string_functor(const MetaEnum::Value<T> (& lookupTable)[N])96 explicit enum_to_string_functor(const MetaEnum::Value<T>(&lookupTable)[N])
97 : m_lookupTable(lookupTable)
98 {}
99
operator()100 QString operator()(T value)
101 {
102 return MetaEnum::enumToString(value, m_lookupTable);
103 }
104
105 private:
106 const MetaEnum::Value<T> (&m_lookupTable)[N];
107
108 };
109
110 template <typename T, std::size_t N>
111 class flags_to_string_functor
112 {
113 public:
flags_to_string_functor(const MetaEnum::Value<T> (& lookupTable)[N])114 explicit flags_to_string_functor(const MetaEnum::Value<T>(&lookupTable)[N])
115 : m_lookupTable(lookupTable)
116 {}
117
118 #if !defined(Q_CC_MSVC) || _MSC_VER >= 1900 //krazy:exclude=cpp to deal with older MS compilers
operator()119 QString operator()(typename std::underlying_type<T>::type value)
120 #else
121 QString operator()(unsigned int value)
122 #endif
123 {
124 return MetaEnum::flagsToString(value, m_lookupTable);
125 }
126
127 private:
128 const MetaEnum::Value<T> (&m_lookupTable)[N];
129
130 };
131
132 }
133
134 /** Creates a functor for MetaEnum::enumToString and a specific lookup table. */
135 template <typename T, std::size_t N>
enumToString_fn(const Value<T> (& lookupTable)[N])136 detail::enum_to_string_functor<T, N> enumToString_fn(const Value<T>(&lookupTable)[N])
137 {
138 return detail::enum_to_string_functor<T, N>(lookupTable);
139 }
140
141 /** Creates a functor for MetaEnum::flagsToString and a specific lookup table. */
142 template <typename T, std::size_t N>
flagsToString_fn(const Value<T> (& lookupTable)[N])143 detail::flags_to_string_functor<T, N> flagsToString_fn(const Value<T>(&lookupTable)[N])
144 {
145 return detail::flags_to_string_functor<T, N>(lookupTable);
146 }
147
148 } // MetaEnum
149 } // GammaRay
150
151 #endif
152