Skip to content

Commit

Permalink
-fix EnumMap when passed a list of enums that don't all have values s…
Browse files Browse the repository at this point in the history
…pecified (#4506)

-add some EnumMap static_assert tests
  • Loading branch information
geoffthemedio committed Apr 29, 2023
1 parent 269a063 commit 9437df4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 19 deletions.
37 changes: 18 additions & 19 deletions GG/GG/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,21 @@ class EnumMap {
// and inserts into this map
constexpr void Insert(std::string_view entry)
{
auto count_trimmed_name_value_str = SplitApply<2>(entry, Trim, '=');
static_assert(std::is_same_v<decltype(count_trimmed_name_value_str.first), std::size_t>);
static_assert(std::is_same_v<decltype(count_trimmed_name_value_str.second),
std::array<std::string_view, 2>>);
const auto [parts_count, trimmed_strs] = SplitApply<2>(entry, Trim, '='); // separate into parts before and after =
static_assert(std::is_same_v<decltype(parts_count), const std::size_t>);
static_assert(std::is_same_v<decltype(trimmed_strs), const std::array<std::string_view, 2>>);

auto count = count_trimmed_name_value_str.first;
if (count < 2)
return;
auto [name, value_str] = count_trimmed_name_value_str.second;
const auto name = trimmed_strs[0];

EnumType value = ToEnumType(value_str);
//std::cout << "inserting entry: " << entry << " as name: " << name
// << " value string: " << value_str
// << " value: " << static_cast<int>(value) << std::endl;
const auto value = [had_value_specified{parts_count >= 2}, value_str{trimmed_strs[1]}, this]() {
if (had_value_specified)
return EnumType(ToInt(value_str));

// increment last-specified value or default to 0 for the first
using value_num_t = std::underlying_type_t<EnumType>;
const value_num_t next_value_num = (m_size == 0u) ? 0 : (static_cast<value_num_t>(m_values[m_size-1]) + 1);
return EnumType(next_value_num);
}();

const auto place_idx = m_size++;
if (m_size >= CAPACITY)
Expand All @@ -111,7 +112,7 @@ class EnumMap {

static constexpr std::size_t CAPACITY = std::numeric_limits<uint8_t>::max();


public:
[[nodiscard]] static constexpr std::pair<std::string_view, std::string_view> Split(
std::string_view delim_separated_vals, const char delim)
{
Expand All @@ -121,12 +122,14 @@ class EnumMap {
return {delim_separated_vals.substr(0, comma_idx),
delim_separated_vals.substr(comma_idx + 1)};
}
private:

static constexpr std::string_view test_cs_names = "123 = 7 , next_thing = 124, last thing =-1";
static constexpr auto first_and_rest = Split(test_cs_names, ',');
static constexpr auto second_and_rest = Split(first_and_rest.second, ',');
static constexpr auto third_and_rest = Split(second_and_rest.second, ',');
static constexpr auto fourth_and_rest = Split(third_and_rest.second, ',');
static_assert(first_and_rest.first == "123 = 7 ");
static_assert(fourth_and_rest.first.empty());
static constexpr std::string_view third_result_expected = " last thing =-1";
static_assert(third_and_rest.first == third_result_expected);
Expand All @@ -143,7 +146,7 @@ class EnumMap {
static constexpr auto comma_count = Count(test_cs_names, ',');
static_assert(comma_count == 3);


public:
template <std::size_t RETVAL_CAP = CAPACITY, typename F>
[[nodiscard]] static constexpr std::pair<std::size_t, std::array<std::string_view, RETVAL_CAP>>
SplitApply(std::string_view comma_separated_names, F&& fn, char delim)
Expand All @@ -160,14 +163,14 @@ class EnumMap {
return {count, retval};
}


[[nodiscard]] static constexpr std::string_view Trim(std::string_view padded)
{
constexpr std::string_view whitespace = " \b\f\n\r\t\v";
auto start_idx = padded.find_first_not_of(whitespace);
auto end_idx = padded.find_last_not_of(whitespace);
return padded.substr(start_idx, end_idx - start_idx + 1);
}
private:
static constexpr std::string_view test_text = " \n\f something = \t 0x42\b\t ";
static constexpr std::string_view trimmed_text_expected = "something = \t 0x42";
static_assert(Trim(test_text) == trimmed_text_expected);
Expand Down Expand Up @@ -256,10 +259,6 @@ class EnumMap {
static_assert(ToInt(std::string_view{}) == 0);


[[nodiscard]] static constexpr EnumType ToEnumType(std::string_view str)
{ return EnumType(ToInt(str)); }


std::size_t m_size = 0;
std::array<std::string_view, CAPACITY> m_names{};
std::array<EnumType, CAPACITY> m_values{};
Expand Down
24 changes: 24 additions & 0 deletions GG/src/Wnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@
using namespace GG;

namespace {
enum class TestEnum : int8_t { INVALID = -1, VALID = 0, MAX = 1, OUT_OF_RANGE, END, ZERO = 0, ONE, TWO, THREE };
constexpr auto* test_enum_text = "INVALID = -1, VALID = 0, MAX = 1, OUT_OF_RANGE, END";

constexpr auto split_result = GG::EnumMap<TestEnum>::Split(test_enum_text, ',');
static_assert(split_result.first == "INVALID = -1");
static_assert(split_result.second == " VALID = 0, MAX = 1, OUT_OF_RANGE, END");

constexpr auto trimmed_result = GG::EnumMap<TestEnum>::Trim(split_result.first);
static_assert(trimmed_result == "INVALID = -1");

constexpr auto split_apply_result = GG::EnumMap<TestEnum>::SplitApply(
test_enum_text, GG::EnumMap<TestEnum>::Trim, ',');

constexpr GG::EnumMap<TestEnum> cmap(test_enum_text);
static_assert(cmap["MAX"] == TestEnum::MAX);
static_assert(cmap["OUT_OF_RANGE"] == TestEnum::OUT_OF_RANGE);


static constexpr auto em = GG::CGetEnumMap<GG::WndRegion>();
static constexpr auto qq = em[GG::WndRegion::WR_TOPLEFT];
static constexpr auto rr = GG::to_string(GG::WndRegion::WR_TOPLEFT);
static_assert(rr == "WR_TOPLEFT");
static_assert(rr == qq);


namespace mi = boost::multi_index;

Expand Down

0 comments on commit 9437df4

Please sign in to comment.