Skip to content

Commit c171139

Browse files
committed
Common: Add flag helper class
1 parent d63edfa commit c171139

File tree

1 file changed

+179
-0
lines changed
  • Common/Utils/include/CommonUtils

1 file changed

+179
-0
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
#ifndef O2_FRAMEWORK_ENUM_BIT_OPERATORS_H_
12+
#define O2_FRAMEWORK_ENUM_BIT_OPERATORS_H_
13+
14+
#include <type_traits>
15+
#include <string>
16+
#include <sstream>
17+
#include <limits>
18+
19+
namespace o2::flags
20+
{
21+
22+
template <typename E>
23+
concept EFlag = requires {
24+
requires std::is_enum_v<E>;
25+
requires std::is_unsigned_v<std::underlying_type_t<E>>;
26+
requires std::is_convertible_v<std::underlying_type_t<E>, size_t>;
27+
};
28+
29+
// Promote an enum to a functioning flag class. The underlying type is
30+
// the one behind the enum, when bitset becomes constexpr and we get
31+
// reflection one could changes this.
32+
template <EFlag E>
33+
class Flags
34+
{
35+
using U = std::underlying_type_t<E>;
36+
U mBits{0};
37+
38+
constexpr auto to_underlying(E e) const noexcept
39+
{
40+
return static_cast<U>(e);
41+
}
42+
43+
constexpr auto to_bit(E e) const noexcept
44+
{
45+
return U(1) << to_underlying(e);
46+
}
47+
48+
public:
49+
constexpr explicit Flags() = default;
50+
constexpr explicit Flags(E e) : mBits(to_bit(e)) {}
51+
constexpr explicit Flags(const Flags&) = default;
52+
constexpr explicit Flags(U u) : mBits(u) {}
53+
constexpr explicit Flags(std::initializer_list<E> flags) noexcept
54+
{
55+
for (E flag : flags) {
56+
mBits |= to_bit(flag);
57+
}
58+
}
59+
60+
static constexpr U None{0};
61+
static constexpr U All{std::numeric_limits<U>::max()};
62+
63+
void set(std::string& s, int base = 2)
64+
{
65+
if (base == 2) { // check of only 0 and 1 in string
66+
if (!std::all_of(s.begin(), s.end(), [](char c) { return c == '0' || c == '1'; })) {
67+
throw std::invalid_argument("Invalid binary string.");
68+
}
69+
}
70+
mBits = static_cast<U>(std::stoul(s, nullptr, base));
71+
}
72+
73+
constexpr auto value() const noexcept
74+
{
75+
return mBits;
76+
}
77+
78+
constexpr void reset() noexcept
79+
{
80+
mBits = U(0);
81+
}
82+
83+
template <typename T>
84+
requires std::is_same_v<T, E>
85+
constexpr void reset(T t)
86+
{
87+
mBits &= ~to_bit(t);
88+
}
89+
90+
template <typename T>
91+
requires std::is_same_v<T, E>
92+
constexpr bool test(T t) const noexcept
93+
{
94+
return (mBits & to_bit(t)) != None;
95+
}
96+
97+
constexpr bool any() const noexcept
98+
{
99+
return mBits != None;
100+
}
101+
102+
std::string string() const
103+
{
104+
std::ostringstream oss;
105+
oss << std::bitset<std::numeric_limits<U>::digits>(mBits);
106+
return oss.str();
107+
}
108+
109+
constexpr explicit operator bool() const noexcept
110+
{
111+
return any();
112+
}
113+
114+
constexpr bool operator==(const Flags& o) const noexcept
115+
{
116+
return mBits == o.mBits;
117+
}
118+
119+
constexpr bool operator!=(const Flags& o) const noexcept
120+
{
121+
return mBits != o.mBits;
122+
}
123+
124+
constexpr Flags& operator=(const Flags& o) = default;
125+
126+
template <typename T>
127+
requires std::is_same_v<T, E>
128+
constexpr Flags& operator|=(T t) noexcept
129+
{
130+
mBits |= to_bit(t);
131+
return *this;
132+
}
133+
134+
template <typename T>
135+
requires std::is_same_v<T, E>
136+
constexpr Flags operator&=(T t) noexcept
137+
{
138+
mBits |= to_bit(t);
139+
return *this;
140+
}
141+
142+
template <typename T>
143+
requires std::is_same_v<T, E>
144+
constexpr Flags operator&(T t) const noexcept
145+
{
146+
return Flags(mBits & to_bit(t));
147+
}
148+
constexpr Flags operator~() const noexcept
149+
{
150+
return Flags(~mBits);
151+
}
152+
153+
constexpr Flags operator|(const Flags& o) const noexcept
154+
{
155+
return Flags(mBits | o.mBits);
156+
}
157+
158+
constexpr Flags& operator|=(const Flags& o) noexcept
159+
{
160+
mBits |= o.mBits;
161+
return *this;
162+
}
163+
164+
template <typename... Ts>
165+
constexpr bool all_of(Ts... flags) const noexcept
166+
{
167+
return ((test(flags) && ...));
168+
}
169+
170+
template <typename... Ts>
171+
constexpr bool none_of(Ts... flags) const noexcept
172+
{
173+
return (!(test(flags) || ...));
174+
}
175+
};
176+
177+
} // namespace o2::flags
178+
179+
#endif

0 commit comments

Comments
 (0)