diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh index dd38416c..65db3b81 100644 --- a/lib/utils/mu-utils.hh +++ b/lib/utils/mu-utils.hh @@ -326,7 +326,7 @@ typename Sequence::const_iterator seq_find_if(const Sequence& seq, UnaryPredicat } /** - * Is at least pred(element) true for at least one element of sequence + * Is pred(element) true for at least one element of sequence? * * @param seq sequence * @param pred a predicate @@ -391,6 +391,49 @@ void seq_for_each(const Sequence& seq, UnaryOp op) { std::for_each(seq.cbegin(), seq.cend(), op); } +/** + * array of associated pair elements -- like an alist + * but based on std::array and thus can be constexpr + */ +template + using AssocPairs = std::array, N>; + +/** + * Get the first value of the pair where the second element is @param s. + * + * @param p AssocPairs + * @param s some second pair value + * + * @return the matching first pair value, or Nothing if not found. + */ +template +constexpr Option +to_first(const P& p, typename P::value_type::second_type s) +{ + for (const auto& item: p) + if (item.second == s) + return item.first; + return Nothing; +} + +/** + * Get the second value of the pair where the first element is @param f. + * + * @param p AssocPairs + * @param f some first pair value + * + * @return the matching second pair value, or Nothing if not found. + */ +template +constexpr Option +to_second(const P& p, typename P::value_type::first_type f) +{ + for (const auto& item: p) + if (item.first == f) + return item.second; + return Nothing; +} + /** * Convert string view in something printable with %*s diff --git a/lib/utils/tests/test-utils.cc b/lib/utils/tests/test-utils.cc index b69c705f..fcd9a333 100644 --- a/lib/utils/tests/test-utils.cc +++ b/lib/utils/tests/test-utils.cc @@ -298,6 +298,33 @@ test_error() g_clear_error(&err); } +enum struct TestEnum { A, B, C }; +constexpr AssocPairs +test_epairs = {{ + {TestEnum::A, "a"}, + {TestEnum::B, "b"}, + {TestEnum::C, "c"}, +}}; + +static constexpr Option +to_name(TestEnum te) +{ + return to_second(test_epairs, te); +} + +static constexpr Option +to_type(std::string_view name) +{ + return to_first(test_epairs, name); + +} + +static void +test_enum_pairs(void) +{ + assert_equal(to_name(TestEnum::A).value(), "a"); + g_assert_true(to_type("c").value() == TestEnum::C); +} int main(int argc, char* argv[]) @@ -317,6 +344,7 @@ main(int argc, char* argv[]) g_test_add_func("/utils/to-from-lexnum", test_to_from_lexnum); g_test_add_func("/utils/locale-workaround", test_locale_workaround); g_test_add_func("/utils/error", test_error); + g_test_add_func("/utils/enum-pairs", test_enum_pairs); return g_test_run(); }