summaryrefslogtreecommitdiff
path: root/include/ncurses/utils/multiflags.hpp
blob: caed9afb3ef1e8b9e472eff8c9e5285f13cfec59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#ifndef INCLUDE_UTILS_MULTIFLAGS_HPP_
#define INCLUDE_UTILS_MULTIFLAGS_HPP_

#include <type_traits>

#include "ncurses/utils/macros.hpp"
#include <ncurses/utils/flags.hpp>

namespace NCURSES_CPP_NAMESPACE {

template <typename FlagBitType, typename PrimaryType>
struct is_applyable : public std::false_type {};

template <typename BitType, typename SecondBitType>
using is_combosable_types =
    typename std::enable_if<is_bitmask<BitType>::value &&
                                is_applyable<SecondBitType, BitType>::value,
                            bool>::type;

template <typename BitType, typename SecondBitType,
          is_combosable_types<BitType, SecondBitType> = true>
class multiflags {
public:
  using value_type = typename std::underlying_type<BitType>::type;
  using second_value_type = typename SecondBitType::value_type;

  // constructors
  NCURSES_CPP_CONSTEXPR multiflags() NCURSES_CPP_NOEXCEPT : value_(0) {}

  NCURSES_CPP_CONSTEXPR multiflags(BitType bit) NCURSES_CPP_NOEXCEPT
      : value_(static_cast<value_type>(bit)) {}

  NCURSES_CPP_CONSTEXPR multiflags(SecondBitType bit) NCURSES_CPP_NOEXCEPT
      : value_(static_cast<value_type>(bit)) {}

  NCURSES_CPP_CONSTEXPR multiflags(flags<BitType> flag) NCURSES_CPP_NOEXCEPT
      : value_(static_cast<value_type>(flag)) {}

  NCURSES_CPP_CONSTEXPR
  multiflags(multiflags<BitType, SecondBitType> const &rhs) NCURSES_CPP_NOEXCEPT
      : value_(rhs.value_) {}

  NCURSES_CPP_CONSTEXPR explicit multiflags(value_type multiflags)
      : value_(multiflags) {}

  // relational operators

#define NCURSES_CPP_RELATIONAL(op)                                             \
  NCURSES_CPP_CONSTEXPR bool operator op(                                      \
      multiflags<BitType, SecondBitType> const &rhs)                           \
      const NCURSES_CPP_NOEXCEPT {                                             \
    return value_ op rhs.value_;                                               \
  }

  NCURSES_CPP_RELATIONAL(==)
  NCURSES_CPP_RELATIONAL(!=)

  // logical operator

  NCURSES_CPP_CONSTEXPR bool operator!() const NCURSES_CPP_NOEXCEPT {
    return !value_;
  }

  // bitwise operators

#define NCURSES_CPP_BITWISE(op)                                                \
  NCURSES_CPP_CONSTEXPR multiflags<BitType, SecondBitType> operator op(        \
      multiflags<BitType, SecondBitType> const &rhs)                           \
      const NCURSES_CPP_NOEXCEPT {                                             \
    return multiflags<BitType, SecondBitType>(value_ op rhs.value_);           \
  }

  NCURSES_CPP_BITWISE(&)
  NCURSES_CPP_BITWISE(|)
  NCURSES_CPP_BITWISE(^)

  /*NCURSES_CPP_CONSTEXPR multiflags<BitType> operator~() const {*/
  /*  return multiflags<BitType>(m_mask ^
   * is_bitmask<BitType>::allmultiflags.m_mask);*/
  /*}*/

  // assignment operators

#define NCURSES_CPP_ASSIGNMENT(op)                                             \
  NCURSES_CPP_CONSTEXPR_14 multiflags<BitType, SecondBitType> &operator op##=( \
      multiflags<BitType, SecondBitType> const &rhs) NCURSES_CPP_NOEXCEPT {    \
    value_ op## = rhs.value_;                                                  \
    return *this;                                                              \
  }

  NCURSES_CPP_CONSTEXPR_14 multiflags<BitType, SecondBitType> &operator=(
      multiflags<BitType, SecondBitType> const &rhs) NCURSES_CPP_NOEXCEPT {
    value_ = rhs.value_;
    return *this;
  }

  NCURSES_CPP_ASSIGNMENT(&)
  NCURSES_CPP_ASSIGNMENT(|)
  NCURSES_CPP_ASSIGNMENT(^)

  // cast operators
  explicit NCURSES_CPP_CONSTEXPR operator bool() const NCURSES_CPP_NOEXCEPT {
    return !!value_;
  }

  explicit NCURSES_CPP_CONSTEXPR
  operator value_type() const NCURSES_CPP_NOEXCEPT {
    return value_;
  }

#undef NCURSES_CPP_RELATIONAL
#undef NCURSES_CPP_BITWISE
#undef NCURSES_CPP_ASSIGNMENT

#if defined(NCURSES_CPP_FLAGS_MASK_TYPE_AS_PUBLIC)
public:
#else
private:
#endif
  value_type value_;
};

// TODO:const BitType& - link may be not as good as copy
#define NPP_DEF_GLOB_OP(type_arg, op, pos)                                     \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE type_arg operator op(                           \
      const pos &bit, multiflags<BitType, SecondBitType> const &flag)          \
      NCURSES_CPP_NOEXCEPT {                                                   \
    return flag.operator op(bit);                                              \
  }

#define NPP_DEF_GLOB_OP_FLAGS(op)                                              \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE multiflags<BitType, SecondBitType> operator op( \
      const flags<BitType> &flag,                                              \
      multiflags<BitType, SecondBitType> const &mflags) NCURSES_CPP_NOEXCEPT { \
    return mflags.operator op(                                                 \
        static_cast<typename flags<BitType>::mask_type>(flag));                \
  }

#define NPP_DEF_GLOB_BITTYPE(op)                                               \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE multiflags<BitType, SecondBitType> operator op( \
      BitType lhs, SecondBitType rhs) NCURSES_CPP_NOEXCEPT {                   \
    return multiflags<BitType, SecondBitType>(                                 \
        static_cast<typename multiflags<BitType, SecondBitType>::value_type>(  \
            lhs)                                                               \
            op static_cast<typename multiflags<                                \
                BitType, SecondBitType>::second_value_type>(rhs));             \
  }                                                                            \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE multiflags<BitType, SecondBitType> operator op( \
      SecondBitType lhs, BitType rhs) NCURSES_CPP_NOEXCEPT {                   \
    return rhs op lhs;                                                         \
  }                                                                            \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE multiflags<BitType, SecondBitType> operator op( \
      flags<BitType> lhs, SecondBitType rhs) NCURSES_CPP_NOEXCEPT {            \
    return multiflags<BitType, SecondBitType>(                                 \
        static_cast<typename flags<BitType>::mask_type>(lhs) op static_cast<   \
            typename multiflags<BitType, SecondBitType>::second_value_type>(   \
            rhs));                                                             \
  }                                                                            \
  template <typename BitType, typename SecondBitType,                          \
            is_combosable_types<BitType, SecondBitType> = true>                \
  NCURSES_CPP_CONSTEXPR_INLINE multiflags<BitType, SecondBitType> operator op( \
      SecondBitType lhs, flags<BitType> rhs) NCURSES_CPP_NOEXCEPT {            \
    return rhs op lhs;                                                         \
  }

#define NPP_DEF_GLOB_OP_BOOL_FIRST(op) NPP_DEF_GLOB_OP(bool, op, BitType)
#define NPP_DEF_GLOB_OP_BOOL_SECOND(op) NPP_DEF_GLOB_OP(bool, op, SecondBitType)

#if !defined(NCURSES_CPP_HAS_SPACESHIP_OPERATOR)
// relational operators only needed for pre C++20
NPP_DEF_GLOB_OP_BOOL_FIRST(==)
NPP_DEF_GLOB_OP_BOOL_FIRST(!=)
NPP_DEF_GLOB_OP_BOOL_SECOND(==)
NPP_DEF_GLOB_OP_BOOL_SECOND(!=)
#endif

NPP_DEF_GLOB_OP_FLAGS(&)
NPP_DEF_GLOB_OP_FLAGS(|)
NPP_DEF_GLOB_OP_FLAGS(^)

// bitwise operators on BitType
NPP_DEF_GLOB_BITTYPE(&)
NPP_DEF_GLOB_BITTYPE(|)
NPP_DEF_GLOB_BITTYPE(^)

#undef NPP_DEF_GLOB_OP
#undef NPP_DEF_GLOB_OP_FLAGS
#undef NPP_DEF_GLOB_BITTYPE
#undef NPP_DEF_GLOB_OP_BOOL_FIRST
#undef NPP_DEF_GLOB_OP_BOOL_SECOND

} // namespace NCURSES_CPP_NAMESPACE

#endif // INCLUDE_UTILS_MULTIFLAGS_HPP_