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