Skip to content

Commit 927ea39

Browse files
authored
Common: EnumFlags modifications (#14131)
* Common: EnumFlags turn set with empty string into reset * Common: EnumFlags fix max rep. * Common: EnumFlags allow ',' as delimiter
1 parent 8e4ed02 commit 927ea39

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

Common/Utils/include/CommonUtils/EnumFlags.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,14 @@ struct FlagsHelper final {
154154
}
155155
return values;
156156
}
157-
static constexpr auto Values{getValues(std::make_index_sequence<MaxScan - MinScan - MarginScan>())}; // Enum Values
158-
static constexpr auto count() noexcept { return Values.size(); } // Number of enum members
159-
static constexpr auto Min_v{Values.front()}; // Enum first entry
160-
static constexpr auto Max_v{Values.back()}; // Enum last entry
161-
static constexpr auto Min_u_v{static_cast<size_t>(Min_v)}; // Enum first entry as size_t
162-
static constexpr auto Max_u_v{static_cast<size_t>(Max_v)}; // Enum last entry as size_t
163-
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
164-
static constexpr uint64_t MaxRep{(Max_u_v >= 64) ? std::numeric_limits<uint64_t>::max() : (1ULL << Max_u_v) - 1}; // largest representable value
157+
static constexpr auto Values{getValues(std::make_index_sequence<MaxScan - MinScan - MarginScan>())}; // Enum Values
158+
static constexpr auto count() noexcept { return Values.size(); } // Number of enum members
159+
static constexpr auto Min_v{Values.front()}; // Enum first entry
160+
static constexpr auto Max_v{Values.back()}; // Enum last entry
161+
static constexpr auto Min_u_v{static_cast<size_t>(Min_v)}; // Enum first entry as size_t
162+
static constexpr auto Max_u_v{static_cast<size_t>(Max_v)}; // Enum last entry as size_t
163+
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
164+
static constexpr auto MaxRep{((1 << (Max_u_v - Min_u_v + 1)) - 1) << Min_u_v}; // largest representable value
165165

166166
template <E e>
167167
static constexpr std::string_view getName()
@@ -398,11 +398,14 @@ class EnumFlags
398398
// Sets flags from a string representation.
399399
// This can be either from a number representation (binary or digits) or
400400
// a concatenation of the enums members name e.g., 'Enum1|Enum2|...'
401-
void set(const std::string& s, int base = 2)
401+
void set(const std::string& s = "", int base = 2)
402402
{
403403
// on throw restore previous state and rethrow
404404
const U prev = mBits;
405405
reset();
406+
if (s.empty()) { // no-op
407+
return;
408+
}
406409
try {
407410
setImpl(s, base);
408411
} catch (const std::exception& e) {
@@ -665,15 +668,16 @@ class EnumFlags
665668
throw std::out_of_range("Values exceeds enum range.");
666669
}
667670
mBits = static_cast<U>(v);
668-
} else if (std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalnum(c) != 0 || c == '|' || c == ' ' || c == ':'; })) {
671+
} else if (std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalnum(c) != 0 || c == '|' || c == ' ' || c == ':' || c == ','; })) {
669672
std::string cs{s};
670673
std::transform(cs.begin(), cs.end(), cs.begin(), [](unsigned char c) { return std::tolower(c); });
671674
if (cs == H::All) {
672675
mBits = All;
673676
} else if (cs == H::None) {
674677
mBits = None;
675678
} else {
676-
for (const auto& tok : Str::tokenize(s, '|')) {
679+
char token = (s.find(',') != std::string::npos) ? ',' : '|';
680+
for (const auto& tok : Str::tokenize(s, token)) {
677681
if (auto e = H::fromString(tok)) {
678682
mBits |= to_bit(*e);
679683
} else {

Common/Utils/test/testEnumFlags.cxx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ BOOST_AUTO_TEST_CASE(Flags_test)
3434

3535
// Test default initialization
3636
EFlags flags;
37+
BOOST_TEST(flags.None == 0);
38+
BOOST_TEST(flags.All == 31);
3739
BOOST_TEST(flags.value() == 0);
3840
BOOST_TEST(!flags.any());
3941

@@ -139,6 +141,20 @@ BOOST_AUTO_TEST_CASE(Flags_test)
139141
BOOST_TEST(flags.test(TestEnum::Bit4));
140142
}
141143

144+
{ // test with different delimiter
145+
std::string str = "Bit4,TestEnum::Bit2 , Bit1 ";
146+
flags.set(str);
147+
BOOST_TEST(flags.test(TestEnum::Bit1));
148+
BOOST_TEST(flags.test(TestEnum::Bit2));
149+
BOOST_TEST(!flags.test(TestEnum::Bit3));
150+
BOOST_TEST(flags.test(TestEnum::Bit4));
151+
}
152+
153+
{ // throw test with mixed delimiter
154+
std::string str = "Bit4|TestEnum::Bit2 , Bit1 ";
155+
BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
156+
}
157+
142158
{ // test throw
143159
std::string str = "Invalid";
144160
BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);

0 commit comments

Comments
 (0)