Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions Common/Utils/include/CommonUtils/EnumFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@ struct FlagsHelper final {
}
return values;
}
static constexpr auto Values{getValues(std::make_index_sequence<MaxScan - MinScan - MarginScan>())}; // Enum Values
static constexpr auto count() noexcept { return Values.size(); } // Number of enum members
static constexpr auto Min_v{Values.front()}; // Enum first entry
static constexpr auto Max_v{Values.back()}; // Enum last entry
static constexpr auto Min_u_v{static_cast<size_t>(Min_v)}; // Enum first entry as size_t
static constexpr auto Max_u_v{static_cast<size_t>(Max_v)}; // Enum last entry as size_t
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
static constexpr uint64_t MaxRep{(Max_u_v >= 64) ? std::numeric_limits<uint64_t>::max() : (1ULL << Max_u_v) - 1}; // largest representable value
static constexpr auto Values{getValues(std::make_index_sequence<MaxScan - MinScan - MarginScan>())}; // Enum Values
static constexpr auto count() noexcept { return Values.size(); } // Number of enum members
static constexpr auto Min_v{Values.front()}; // Enum first entry
static constexpr auto Max_v{Values.back()}; // Enum last entry
static constexpr auto Min_u_v{static_cast<size_t>(Min_v)}; // Enum first entry as size_t
static constexpr auto Max_u_v{static_cast<size_t>(Max_v)}; // Enum last entry as size_t
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
static constexpr auto MaxRep{((1 << (Max_u_v - Min_u_v + 1)) - 1) << Min_u_v}; // largest representable value

template <E e>
static constexpr std::string_view getName()
Expand Down Expand Up @@ -398,11 +398,14 @@ class EnumFlags
// Sets flags from a string representation.
// This can be either from a number representation (binary or digits) or
// a concatenation of the enums members name e.g., 'Enum1|Enum2|...'
void set(const std::string& s, int base = 2)
void set(const std::string& s = "", int base = 2)
{
// on throw restore previous state and rethrow
const U prev = mBits;
reset();
if (s.empty()) { // no-op
return;
}
try {
setImpl(s, base);
} catch (const std::exception& e) {
Expand Down Expand Up @@ -665,15 +668,16 @@ class EnumFlags
throw std::out_of_range("Values exceeds enum range.");
}
mBits = static_cast<U>(v);
} else if (std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalnum(c) != 0 || c == '|' || c == ' ' || c == ':'; })) {
} else if (std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalnum(c) != 0 || c == '|' || c == ' ' || c == ':' || c == ','; })) {
std::string cs{s};
std::transform(cs.begin(), cs.end(), cs.begin(), [](unsigned char c) { return std::tolower(c); });
if (cs == H::All) {
mBits = All;
} else if (cs == H::None) {
mBits = None;
} else {
for (const auto& tok : Str::tokenize(s, '|')) {
char token = (s.find(',') != std::string::npos) ? ',' : '|';
for (const auto& tok : Str::tokenize(s, token)) {
if (auto e = H::fromString(tok)) {
mBits |= to_bit(*e);
} else {
Expand Down
16 changes: 16 additions & 0 deletions Common/Utils/test/testEnumFlags.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ BOOST_AUTO_TEST_CASE(Flags_test)

// Test default initialization
EFlags flags;
BOOST_TEST(flags.None == 0);
BOOST_TEST(flags.All == 31);
BOOST_TEST(flags.value() == 0);
BOOST_TEST(!flags.any());

Expand Down Expand Up @@ -139,6 +141,20 @@ BOOST_AUTO_TEST_CASE(Flags_test)
BOOST_TEST(flags.test(TestEnum::Bit4));
}

{ // test with different delimiter
std::string str = "Bit4,TestEnum::Bit2 , Bit1 ";
flags.set(str);
BOOST_TEST(flags.test(TestEnum::Bit1));
BOOST_TEST(flags.test(TestEnum::Bit2));
BOOST_TEST(!flags.test(TestEnum::Bit3));
BOOST_TEST(flags.test(TestEnum::Bit4));
}

{ // throw test with mixed delimiter
std::string str = "Bit4|TestEnum::Bit2 , Bit1 ";
BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
}

{ // test throw
std::string str = "Invalid";
BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
Expand Down