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_FLAG_H_ 8 #define _FCITX_UTILS_FLAG_H_ 9 10 #include <initializer_list> 11 #include <type_traits> 12 #include "fcitx-utils/macros.h" 13 14 /// \addtogroup FcitxUtils 15 /// \{ 16 /// \file 17 /// \brief Helper template class to make easier to use type safe enum flags. 18 /// 19 /// Commonly, One can not do any arithmetic calculation with enum class type 20 /// without using static_cast. To make enum flags easier, this template class 21 /// Stores the actual flag value with enum. 22 /// 23 /// Example: 24 /// \code{.cpp} 25 /// enum class EnumTypeFlag { /* ... */ }; 26 /// using EnumTypeFlags = Flags<EnumTypeFlag>; 27 /// \endcode 28 29 namespace fcitx { 30 31 /// \brief Class provides bit flag support for Enum. 32 template <typename Enum> 33 class Flags { 34 public: 35 typedef typename std::underlying_type_t<Enum> storage_type; Flags(Enum f)36 constexpr Flags(Enum f) : flags_(static_cast<storage_type>(f)) {} flags_(i)37 explicit Flags(storage_type i = 0) : flags_(i) {} Flags(const std::initializer_list<Enum> & l)38 constexpr Flags(const std::initializer_list<Enum> &l) : flags_(0) { 39 for (Enum e : l) { 40 operator|=(e); 41 } 42 } 43 FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(Flags)44 FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(Flags) 45 46 constexpr inline operator storage_type() const { return flags_; } toInteger()47 constexpr inline storage_type toInteger() const { return flags_; } 48 49 Flags &operator=(Enum f) { 50 flags_ = static_cast<storage_type>(f); 51 return *this; 52 } 53 Flags &operator=(storage_type f) { 54 flags_ = f; 55 return *this; 56 } 57 58 constexpr bool operator!() const { return !flags_; } 59 constexpr Flags &operator&=(Flags flag) { 60 flags_ &= flag.flags_; 61 return *this; 62 } 63 Flags &operator&=(Enum flag) { 64 flags_ &= static_cast<storage_type>(flag); 65 return *this; 66 } 67 Flags &operator|=(Flags flag) { 68 flags_ |= flag.flags_; 69 return *this; 70 } 71 constexpr Flags &operator|=(Enum flag) { 72 flags_ |= static_cast<storage_type>(flag); 73 return *this; 74 } 75 Flags &operator^=(Flags flag) { 76 flags_ ^= flag.flags_; 77 return *this; 78 } 79 Flags &operator^=(Enum flag) { 80 flags_ ^= static_cast<storage_type>(flag); 81 return *this; 82 } 83 constexpr inline Flags operator|(Flags f) const { 84 return Flags(flags_ | f.flags_); 85 } 86 constexpr inline Flags operator|(Enum f) const { 87 return Flags(flags_ | static_cast<storage_type>(f)); 88 } 89 constexpr inline Flags operator^(Flags f) const { 90 return Flags(flags_ ^ f.flags_); 91 } 92 constexpr inline Flags operator^(Enum f) const { 93 return Flags(flags_ ^ static_cast<storage_type>(f)); 94 } 95 constexpr inline Flags operator&(Flags f) const { 96 return Flags(flags_ & f.flags_); 97 } 98 constexpr inline Flags operator&(Enum f) const { 99 return Flags(flags_ & static_cast<storage_type>(f)); 100 } 101 constexpr inline Flags operator~() const { return Flags(~flags_); } 102 unset(Enum f)103 constexpr inline Flags unset(Enum f) const { 104 return Flags(flags_ & (~static_cast<storage_type>(f))); 105 } 106 unset(Flags f)107 constexpr inline Flags unset(Flags f) const { 108 return Flags(flags_ & (~f.flags_)); 109 } 110 111 template <typename T> test(T f)112 constexpr inline bool test(T f) const { 113 return (*this & f) == f; 114 } 115 template <typename T> testAny(T f)116 constexpr inline bool testAny(T f) const { 117 return (*this & f) != 0; 118 } 119 120 constexpr bool operator==(const Flags &f) const { 121 return flags_ == f.flags_; 122 } 123 constexpr bool operator==(Enum f) const { 124 return flags_ == static_cast<storage_type>(f); 125 } 126 constexpr bool operator!=(const Flags &f) const { return !operator==(f); } 127 constexpr bool operator!=(Enum f) const { return !operator==(f); } 128 129 private: 130 storage_type flags_; 131 }; 132 } // namespace fcitx 133 134 #endif // _FCITX_UTILS_FLAG_H_ 135