From 1ce03f493d0f6c0016abb5514f6d0d33167ce54e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 8 Feb 2019 06:10:52 +0700 Subject: [PATCH] math: check_and_set/check_and_clear bit flags functions --- headers/enduro2d/math/_math.hpp | 52 +++++++++++++++ untests/sources/untests_math/_math.cpp | 88 ++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/headers/enduro2d/math/_math.hpp b/headers/enduro2d/math/_math.hpp index 1114d359..76027560 100644 --- a/headers/enduro2d/math/_math.hpp +++ b/headers/enduro2d/math/_math.hpp @@ -366,6 +366,58 @@ namespace e2d { namespace math return flag_mask == (flags & flag_mask); } + template < typename T, typename U > + std::enable_if_t< + std::is_unsigned::value && + std::is_convertible::value, + bool> + check_and_set_any_flags(T& flags, U flag_mask) noexcept { + if ( flag_mask == (flags & flag_mask) ) { + return false; + } + flags |= flag_mask; + return true; + } + + template < typename T, typename U > + std::enable_if_t< + std::is_unsigned::value && + std::is_convertible::value, + bool> + check_and_set_all_flags(T& flags, U flag_mask) noexcept { + if ( !!(flags & flag_mask) ) { + return false; + } + flags |= flag_mask; + return true; + } + + template < typename T, typename U > + std::enable_if_t< + std::is_unsigned::value && + std::is_convertible::value, + bool> + check_and_clear_any_flags(T& flags, U flag_mask) noexcept { + if ( !(flags & flag_mask) ) { + return false; + } + flags &= ~flag_mask; + return true; + } + + template < typename T, typename U > + std::enable_if_t< + std::is_unsigned::value && + std::is_convertible::value, + bool> + check_and_clear_all_flags(T& flags, U flag_mask) noexcept { + if ( flag_mask != (flags & flag_mask) ) { + return false; + } + flags &= ~flag_mask; + return true; + } + // // power of two // diff --git a/untests/sources/untests_math/_math.cpp b/untests/sources/untests_math/_math.cpp index 503498b3..e2a7bfd9 100644 --- a/untests/sources/untests_math/_math.cpp +++ b/untests/sources/untests_math/_math.cpp @@ -200,6 +200,94 @@ TEST_CASE("math") { REQUIRE_FALSE(math::check_all_flags(0b1101u, fm_flag0 | fm_flag1)); REQUIRE_FALSE(math::check_all_flags(0b1100u, fm_flag0 | fm_flag1)); REQUIRE_FALSE(math::check_all_flags(0b0000u, fm_flag0 | fm_flag1)); + + // + // check_and_set_any_flags + // + + { + u32 f = 0b0000u; + REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + + f = 0b0001u; + REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + + f = 0b0010u; + REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + + f = 0b0011u; + REQUIRE_FALSE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + } + + // + // check_and_set_all_flags + // + + { + u32 f = 0b0000u; + REQUIRE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + + f = 0b0001u; + REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0001u); + + f = 0b0010u; + REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0010u); + + f = 0b0011u; + REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b0011u); + } + + // + // check_and_clear_any_flags + // + + { + u32 f = 0b1100u; + REQUIRE_FALSE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + + f = 0b1101u; + REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + + f = 0b1110u; + REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + + f = 0b1111u; + REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + } + + // + // check_and_clear_all_flags + // + + { + u32 f = 0b1100u; + REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + + f = 0b1101u; + REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1101u); + + f = 0b1110u; + REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1110u); + + f = 0b1111u; + REQUIRE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1)); + REQUIRE(f == 0b1100u); + } } { REQUIRE(math::is_power_of_2(1u));