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