1 /*
2  * SPDX-FileCopyrightText: 2015-2015 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_UTILS_MACROS_H_
8 #define _FCITX_UTILS_MACROS_H_
9 
10 #include "fcitxutils_export.h"
11 
12 // steal some Qt macro here
13 
14 #define FCITX_DECLARE_PRIVATE(Class)                                           \
15     inline Class##Private *d_func() {                                          \
16         return static_cast<Class##Private *>(d_ptr.get());                     \
17     }                                                                          \
18     inline const Class##Private *d_func() const {                              \
19         return static_cast<Class##Private *>(d_ptr.get());                     \
20     }                                                                          \
21     friend class Class##Private;
22 
23 #define FCITX_D() auto *const d = d_func()
24 #define FCITX_Q() auto *const q = q_func()
25 
26 #define FCITX_TYPED_D(TYPE) auto *const d = static_cast<TYPE *>(d_func())
27 
28 #define FCITX_UNUSED(X) ((void)(X))
29 
30 #ifdef __cplusplus
31 #define FCITX_C_DECL_BEGIN extern "C" {
32 #define FCITX_C_DECL_END }
33 #else
34 #define FCITX_C_DECL_BEGIN
35 #define FCITX_C_DECL_END
36 #endif
37 
38 #define FCITX_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
39 
40 #ifdef __GNUC__
41 #define _FCITX_UNUSED_ __attribute__((__unused__))
42 #else
43 #define _FCITX_UNUSED_
44 #endif
45 
46 #define FCITX_WHITESPACE "\f\n\r\t\v "
47 
48 #define FCITX_EXPAND(x) x
49 
50 #define FCITX_FOR_EACH_0(...)
51 #define FCITX_FOR_EACH_1(what, x, ...) what(x)
52 #define FCITX_FOR_EACH_2(what, x, ...)                                         \
53     what(x) FCITX_EXPAND(FCITX_FOR_EACH_1(what, __VA_ARGS__))
54 #define FCITX_FOR_EACH_3(what, x, ...)                                         \
55     what(x) FCITX_EXPAND(FCITX_FOR_EACH_2(what, __VA_ARGS__))
56 #define FCITX_FOR_EACH_4(what, x, ...)                                         \
57     what(x) FCITX_EXPAND(FCITX_FOR_EACH_3(what, __VA_ARGS__))
58 #define FCITX_FOR_EACH_5(what, x, ...)                                         \
59     what(x) FCITX_EXPAND(FCITX_FOR_EACH_4(what, __VA_ARGS__))
60 #define FCITX_FOR_EACH_6(what, x, ...)                                         \
61     what(x) FCITX_EXPAND(FCITX_FOR_EACH_5(what, __VA_ARGS__))
62 #define FCITX_FOR_EACH_7(what, x, ...)                                         \
63     what(x) FCITX_EXPAND(FCITX_FOR_EACH_6(what, __VA_ARGS__))
64 #define FCITX_FOR_EACH_8(what, x, ...)                                         \
65     what(x) FCITX_EXPAND(FCITX_FOR_EACH_7(what, __VA_ARGS__))
66 #define FCITX_FOR_EACH_9(what, x, ...)                                         \
67     what(x) FCITX_EXPAND(FCITX_FOR_EACH_8(what, __VA_ARGS__))
68 #define FCITX_FOR_EACH_10(what, x, ...)                                        \
69     what(x) FCITX_EXPAND(FCITX_FOR_EACH_9(what, __VA_ARGS__))
70 #define FCITX_FOR_EACH_11(what, x, ...)                                        \
71     what(x) FCITX_EXPAND(FCITX_FOR_EACH_10(what, __VA_ARGS__))
72 #define FCITX_FOR_EACH_12(what, x, ...)                                        \
73     what(x) FCITX_EXPAND(FCITX_FOR_EACH_11(what, __VA_ARGS__))
74 
75 #define FCITX_FOR_EACH_IDX_0(...)
76 #define FCITX_FOR_EACH_IDX_1(what, x, ...) what(1, x)
77 #define FCITX_FOR_EACH_IDX_2(what, x, ...)                                     \
78     what(2, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_1(what, __VA_ARGS__))
79 #define FCITX_FOR_EACH_IDX_3(what, x, ...)                                     \
80     what(3, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_2(what, __VA_ARGS__))
81 #define FCITX_FOR_EACH_IDX_4(what, x, ...)                                     \
82     what(4, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_3(what, __VA_ARGS__))
83 #define FCITX_FOR_EACH_IDX_5(what, x, ...)                                     \
84     what(5, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_4(what, __VA_ARGS__))
85 #define FCITX_FOR_EACH_IDX_6(what, x, ...)                                     \
86     what(6, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_5(what, __VA_ARGS__))
87 #define FCITX_FOR_EACH_IDX_7(what, x, ...)                                     \
88     what(7, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_6(what, __VA_ARGS__))
89 #define FCITX_FOR_EACH_IDX_8(what, x, ...)                                     \
90     what(8, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_7(what, __VA_ARGS__))
91 #define FCITX_FOR_EACH_IDX_9(what, x, ...)                                     \
92     what(9, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_8(what, __VA_ARGS__))
93 #define FCITX_FOR_EACH_IDX_10(what, x, ...)                                    \
94     what(10, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_9(what, __VA_ARGS__))
95 #define FCITX_FOR_EACH_IDX_11(what, x, ...)                                    \
96     what(11, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_10(what, __VA_ARGS__))
97 #define FCITX_FOR_EACH_IDX_12(what, x, ...)                                    \
98     what(12, x) FCITX_EXPAND(FCITX_FOR_EACH_IDX_11(what, __VA_ARGS__))
99 
100 #define FCITX_GET_ARG13(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N,  \
101                         ...)                                                   \
102     N
103 
104 #define FCITX_HAS_COMMA(...)                                                   \
105     FCITX_GET_ARG13(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
106 
107 #define FCITX_TRIGGER_PARENTHESIS_(...) ,
108 
109 #define FCITX_IS_EMPTY(...)                                                    \
110     FCITX_IS_EMPTY_(FCITX_HAS_COMMA(__VA_ARGS__),                              \
111                     FCITX_HAS_COMMA(FCITX_TRIGGER_PARENTHESIS_ __VA_ARGS__),   \
112                     FCITX_HAS_COMMA(__VA_ARGS__()),                            \
113                     FCITX_HAS_COMMA(FCITX_TRIGGER_PARENTHESIS_ __VA_ARGS__()))
114 
115 #define FCITX_PASTE5_(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
116 
117 #define FCITX_IS_EMPTY_(_0, _1, _2, _3)                                        \
118     FCITX_HAS_COMMA(FCITX_PASTE5_(FCITX_IS_EMPTY_CASE_, _0, _1, _2, _3))
119 
120 #define FCITX_IS_EMPTY_CASE_0001 ,
121 
122 #define FCITX_EMPTY_1(X) 0
123 #define FCITX_EMPTY_0(X) X
124 
125 #define FCITX_NARG(...)                                                        \
126     FCITX_NARG_HELPER_(FCITX_IS_EMPTY(__VA_ARGS__), FCITX_NARG_(__VA_ARGS__))
127 #define FCITX_NARG_HELPER_(B, VAL)                                             \
128     FCITX_NARG_HELPER__(FCITX_CONCATENATE(FCITX_EMPTY_, B), VAL)
129 #define FCITX_NARG_HELPER__(B, VAL) B(VAL)
130 
131 #define FCITX_NARG_(...) FCITX_NARG__(__VA_ARGS__, FCITX_RSEQ12())
132 #define FCITX_NARG__(...) FCITX_EXPAND(FCITX_GET_ARG13(__VA_ARGS__))
133 #define FCITX_RSEQ12() 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
134 #define FCITX_CONCATENATE(x, y) x##y
135 #define FCITX_FOR_EACH_(N, what, ...)                                          \
136     FCITX_EXPAND(FCITX_CONCATENATE(FCITX_FOR_EACH_, N)(what, __VA_ARGS__))
137 #define FCITX_FOR_EACH(what, ...)                                              \
138     FCITX_FOR_EACH_(FCITX_NARG(__VA_ARGS__), what, __VA_ARGS__)
139 
140 #define FCITX_FOR_EACH_IDX_(N, what, ...)                                      \
141     FCITX_EXPAND(FCITX_CONCATENATE(FCITX_FOR_EACH_IDX_, N)(what, __VA_ARGS__))
142 #define FCITX_FOR_EACH_IDX(what, ...)                                          \
143     FCITX_FOR_EACH_IDX_(FCITX_NARG(__VA_ARGS__), what, __VA_ARGS__)
144 
145 #define FCITX_XSTRINGIFY(...) #__VA_ARGS__
146 #define FCITX_STRINGIFY(...) FCITX_XSTRINGIFY(__VA_ARGS__)
147 #define FCITX_RETURN_IF(EXPR, VALUE)                                           \
148     if ((EXPR)) {                                                              \
149         return (VALUE);                                                        \
150     }
151 
152 #define FCITX_DECLARE_READ_ONLY_PROPERTY(TYPE, GETTER)                         \
153     std::conditional_t<std::is_class<TYPE>::value, const TYPE &, TYPE>         \
154     GETTER() const;
155 
156 #define FCITX_DECLARE_PROPERTY(TYPE, GETTER, SETTER)                           \
157     FCITX_DECLARE_READ_ONLY_PROPERTY(TYPE, GETTER)                             \
158     void SETTER(TYPE);
159 
160 #define FCITX_DEFINE_READ_ONLY_PROPERTY_PRIVATE(THIS, TYPE, GETTER)            \
161     std::conditional_t<std::is_class<TYPE>::value, const TYPE &, TYPE>         \
162     THIS::GETTER() const {                                                     \
163         FCITX_TYPED_D(const THIS##Private);                                    \
164         return d->GETTER##_;                                                   \
165     }
166 
167 #define FCITX_DEFINE_PROPERTY_PRIVATE(THIS, TYPE, GETTER, SETTER)              \
168     FCITX_DEFINE_READ_ONLY_PROPERTY_PRIVATE(THIS, TYPE, GETTER)                \
169     void THIS::SETTER(TYPE v) {                                                \
170         FCITX_TYPED_D(THIS##Private);                                          \
171         d->GETTER##_ = std::move(v);                                           \
172     }
173 
174 #define FCITX_DECLARE_VIRTUAL_DTOR(TypeName) virtual ~TypeName();
175 
176 #define FCITX_DECLARE_MOVE(TypeName)                                           \
177     TypeName(TypeName &&other) noexcept;                                       \
178     TypeName &operator=(TypeName &&other) noexcept;
179 
180 #define FCITX_DECLARE_COPY(TypeName)                                           \
181     TypeName(const TypeName &other);                                           \
182     TypeName &operator=(const TypeName &other);
183 
184 #define FCITX_DECLARE_COPY_AND_MOVE(TypeName)                                  \
185     FCITX_DECLARE_COPY(TypeName)                                               \
186     FCITX_DECLARE_MOVE(TypeName)
187 
188 #define FCITX_DECLARE_VIRTUAL_DTOR_COPY_AND_MOVE(TypeName)                     \
189     FCITX_DECLARE_VIRTUAL_DTOR(TypeName)                                       \
190     FCITX_DECLARE_COPY_AND_MOVE(TypeName)
191 
192 #define FCITX_DECLARE_VIRTUAL_DTOR_COPY(TypeName)                              \
193     FCITX_DECLARE_VIRTUAL_DTOR(TypeName)                                       \
194     FCITX_DECLARE_COPY(TypeName)
195 
196 #define FCITX_DECLARE_VIRTUAL_DTOR_MOVE(TypeName)                              \
197     FCITX_DECLARE_VIRTUAL_DTOR(TypeName)                                       \
198     FCITX_DECLARE_MOVE(TypeName)
199 
200 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITH_SPEC(TypeName, Spec)    \
201     ~TypeName() = default;                                                     \
202     TypeName(TypeName &&other) Spec = default;                                 \
203     TypeName &operator=(TypeName &&other) Spec = default;
204 
205 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITHOUT_SPEC(TypeName)       \
206     FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITH_SPEC(TypeName, )
207 
208 // try to enforce rule of three-five-zero
209 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE(TypeName)                    \
210     FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITH_SPEC(TypeName, noexcept)
211 
212 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(TypeName)                    \
213     ~TypeName() = default;                                                     \
214     TypeName(const TypeName &other) = default;                                 \
215     TypeName &operator=(const TypeName &other) = default;
216 
217 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITH_SPEC(TypeName,     \
218                                                                  Spec)         \
219     FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITH_SPEC(TypeName, Spec)        \
220     TypeName(const TypeName &other) = default;                                 \
221     TypeName &operator=(const TypeName &other) = default;
222 
223 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITHOUT_SPEC(TypeName)  \
224     FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITH_SPEC(TypeName, )
225 
226 #define FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(TypeName)               \
227     FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITH_SPEC(TypeName, noexcept)
228 
229 #define FCITX_DEFINE_DEFAULT_MOVE(TypeName)                                    \
230     TypeName::TypeName(TypeName &&other) noexcept = default;                   \
231     TypeName &TypeName::operator=(TypeName &&other) noexcept = default;
232 
233 #define FCITX_DEFINE_DEFAULT_COPY(TypeName)                                    \
234     TypeName::TypeName(const TypeName &other) = default;                       \
235     TypeName &TypeName::operator=(const TypeName &other) = default;
236 
237 #define FCITX_DEFINE_DEFAULT_DTOR(TypeName) TypeName::~TypeName() = default;
238 
239 #define FCITX_DEFINE_DPTR_COPY(TypeName)                                       \
240     TypeName::TypeName(const TypeName &other)                                  \
241         : d_ptr(                                                               \
242               std::make_unique<decltype(d_ptr)::element_type>(*other.d_ptr)) { \
243     }                                                                          \
244     TypeName &TypeName::operator=(const TypeName &other) {                     \
245         if (d_ptr) {                                                           \
246             *d_ptr = *other.d_ptr;                                             \
247         } else {                                                               \
248             d_ptr =                                                            \
249                 std::make_unique<decltype(d_ptr)::element_type>(*other.d_ptr); \
250         }                                                                      \
251         return *this;                                                          \
252     }
253 
254 #define FCITX_DEFINE_DPTR_COPY_AND_DEFAULT_MOVE(TypeName)                      \
255     FCITX_DEFINE_DPTR_COPY(TypeName)                                           \
256     FCITX_DEFINE_DEFAULT_MOVE(TypeName)
257 
258 #define FCITX_DEFINE_DEFAULT_DTOR_AND_MOVE(TypeName)                           \
259     FCITX_DEFINE_DEFAULT_DTOR(TypeName)                                        \
260     FCITX_DEFINE_DEFAULT_MOVE(TypeName)
261 
262 #define FCITX_DEFINE_DPTR_COPY_AND_DEFAULT_DTOR_AND_MOVE(TypeName)             \
263     FCITX_DEFINE_DPTR_COPY(TypeName)                                           \
264     FCITX_DEFINE_DEFAULT_MOVE(TypeName)                                        \
265     FCITX_DEFINE_DEFAULT_DTOR(TypeName)
266 
267 #define FCITX_DEFAULT_DTOR_MOVE_AND_COPY(TypeName)                             \
268     FCITX_DEFINE_DEFAULT_COPY(TypeName)                                        \
269     FCITX_DEFINE_DEFAULT_MOVE(TypeName)                                        \
270     FCITX_DEFINE_DEFAULT_DTOR(TypeName)
271 
272 #if defined(__clang__) || __GNUC__ >= 5
273 #define HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
274 #else
275 #define HAS_CPP_ATTRIBUTE(attr) 0
276 #endif
277 
278 // Use [[nodiscard]] specifier if supported by our compiler.
279 #if HAS_CPP_ATTRIBUTE(nodiscard)
280 #define FCITX_NODISCARD [[nodiscard]]
281 #elif HAS_CPP_ATTRIBUTE(gnu::warn_unused_result)
282 #define FCITX_NODISCARD [[gnu::warn_unused_result]]
283 #else
284 #define FCITX_NODISCARD
285 #endif
286 
287 namespace fcitx {
288 template <typename T>
289 class QPtrHolder {
290 public:
291     explicit QPtrHolder(T *q) : q_ptr(q) {}
292     QPtrHolder(const QPtrHolder &) = delete;
293     QPtrHolder(QPtrHolder &&) = delete;
294 
295     QPtrHolder &operator=(const QPtrHolder &) = delete;
296     QPtrHolder &operator=(QPtrHolder &&) = delete;
297 
298     T *q_func() { return q_ptr; }
299     const T *q_func() const { return q_ptr; }
300 
301 protected:
302     T *q_ptr;
303 };
304 } // namespace fcitx
305 #endif // _FCITX_UTILS_MACROS_H_
306