Loading include/ftl/Flags.h +13 −13 Original line number Original line Diff line number Diff line Loading @@ -19,13 +19,12 @@ #include <ftl/enum.h> #include <ftl/enum.h> #include <ftl/string.h> #include <ftl/string.h> #include <bitset> #include <cstdint> #include <cstdint> #include <iterator> #include <iterator> #include <string> #include <string> #include <type_traits> #include <type_traits> #include "utils/BitSet.h" // TODO(b/185536303): Align with FTL style and namespace. // TODO(b/185536303): Align with FTL style and namespace. namespace android { namespace android { Loading Loading @@ -56,21 +55,22 @@ public: : mFlags(t) {} : mFlags(t) {} class Iterator { class Iterator { // The type can't be larger than 64-bits otherwise it won't fit in BitSet64. using Bits = std::uint64_t; static_assert(sizeof(U) <= sizeof(uint64_t)); static_assert(sizeof(U) <= sizeof(Bits)); public: public: constexpr Iterator() = default; Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; } Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; } Iterator() : mRemainingFlags(0), mCurrFlag(static_cast<F>(0)) {} // Pre-fix ++ // Pre-fix ++ Iterator& operator++() { Iterator& operator++() { if (mRemainingFlags.isEmpty()) { if (mRemainingFlags.none()) { mCurrFlag = static_cast<F>(0); mCurrFlag = 0; } else { } else { uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left // TODO: Replace with std::countr_zero in C++20. const U flag = 1 << (64 - bit - 1); const Bits bit = static_cast<Bits>(__builtin_ctzll(mRemainingFlags.to_ullong())); mCurrFlag = static_cast<F>(flag); mRemainingFlags.reset(static_cast<std::size_t>(bit)); mCurrFlag = static_cast<U>(static_cast<Bits>(1) << bit); } } return *this; return *this; } } Loading @@ -88,7 +88,7 @@ public: bool operator!=(Iterator other) const { return !(*this == other); } bool operator!=(Iterator other) const { return !(*this == other); } F operator*() { return mCurrFlag; } F operator*() const { return F{mCurrFlag}; } // iterator traits // iterator traits Loading @@ -107,8 +107,8 @@ public: using pointer = void; using pointer = void; private: private: BitSet64 mRemainingFlags; std::bitset<sizeof(Bits) * 8> mRemainingFlags; F mCurrFlag; U mCurrFlag = 0; }; }; /* /* Loading include/ftl/enum.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -261,10 +261,10 @@ constexpr std::optional<std::string_view> flag_name(E v) { const auto value = to_underlying(v); const auto value = to_underlying(v); // TODO: Replace with std::popcount and std::countr_zero in C++20. // TODO: Replace with std::popcount and std::countr_zero in C++20. if (__builtin_popcountl(value) != 1) return {}; if (__builtin_popcountll(value) != 1) return {}; constexpr auto kRange = details::EnumRange<E, details::FlagName>{}; constexpr auto kRange = details::EnumRange<E, details::FlagName>{}; return kRange.values[__builtin_ctzl(value)]; return kRange.values[__builtin_ctzll(value)]; } } // Returns a stringified enumerator, or its integral value if not named. // Returns a stringified enumerator, or its integral value if not named. Loading libs/ftl/Android.bp +0 −8 Original line number Original line Diff line number Diff line Loading @@ -32,12 +32,4 @@ cc_test { "-Wpedantic", "-Wpedantic", "-Wthread-safety", "-Wthread-safety", ], ], header_libs: [ "libbase_headers", ], shared_libs: [ "libbase", ], } } libs/ftl/enum_test.cpp +10 −0 Original line number Original line Diff line number Diff line Loading @@ -143,6 +143,16 @@ TEST(Enum, String) { EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0"); EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0"); EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010"); EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010"); EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111"); EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111"); enum class Flags64 : std::uint64_t { kFlag0 = 0b1ull, kFlag63 = 0x8000'0000'0000'0000ull, kMask = kFlag0 | kFlag63 }; EXPECT_EQ(ftl::flag_string(Flags64::kFlag0), "kFlag0"); EXPECT_EQ(ftl::flag_string(Flags64::kFlag63), "kFlag63"); EXPECT_EQ(ftl::flag_string(Flags64::kMask), "0x8000000000000001"); } } { { EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth"); EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth"); Loading Loading
include/ftl/Flags.h +13 −13 Original line number Original line Diff line number Diff line Loading @@ -19,13 +19,12 @@ #include <ftl/enum.h> #include <ftl/enum.h> #include <ftl/string.h> #include <ftl/string.h> #include <bitset> #include <cstdint> #include <cstdint> #include <iterator> #include <iterator> #include <string> #include <string> #include <type_traits> #include <type_traits> #include "utils/BitSet.h" // TODO(b/185536303): Align with FTL style and namespace. // TODO(b/185536303): Align with FTL style and namespace. namespace android { namespace android { Loading Loading @@ -56,21 +55,22 @@ public: : mFlags(t) {} : mFlags(t) {} class Iterator { class Iterator { // The type can't be larger than 64-bits otherwise it won't fit in BitSet64. using Bits = std::uint64_t; static_assert(sizeof(U) <= sizeof(uint64_t)); static_assert(sizeof(U) <= sizeof(Bits)); public: public: constexpr Iterator() = default; Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; } Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; } Iterator() : mRemainingFlags(0), mCurrFlag(static_cast<F>(0)) {} // Pre-fix ++ // Pre-fix ++ Iterator& operator++() { Iterator& operator++() { if (mRemainingFlags.isEmpty()) { if (mRemainingFlags.none()) { mCurrFlag = static_cast<F>(0); mCurrFlag = 0; } else { } else { uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left // TODO: Replace with std::countr_zero in C++20. const U flag = 1 << (64 - bit - 1); const Bits bit = static_cast<Bits>(__builtin_ctzll(mRemainingFlags.to_ullong())); mCurrFlag = static_cast<F>(flag); mRemainingFlags.reset(static_cast<std::size_t>(bit)); mCurrFlag = static_cast<U>(static_cast<Bits>(1) << bit); } } return *this; return *this; } } Loading @@ -88,7 +88,7 @@ public: bool operator!=(Iterator other) const { return !(*this == other); } bool operator!=(Iterator other) const { return !(*this == other); } F operator*() { return mCurrFlag; } F operator*() const { return F{mCurrFlag}; } // iterator traits // iterator traits Loading @@ -107,8 +107,8 @@ public: using pointer = void; using pointer = void; private: private: BitSet64 mRemainingFlags; std::bitset<sizeof(Bits) * 8> mRemainingFlags; F mCurrFlag; U mCurrFlag = 0; }; }; /* /* Loading
include/ftl/enum.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -261,10 +261,10 @@ constexpr std::optional<std::string_view> flag_name(E v) { const auto value = to_underlying(v); const auto value = to_underlying(v); // TODO: Replace with std::popcount and std::countr_zero in C++20. // TODO: Replace with std::popcount and std::countr_zero in C++20. if (__builtin_popcountl(value) != 1) return {}; if (__builtin_popcountll(value) != 1) return {}; constexpr auto kRange = details::EnumRange<E, details::FlagName>{}; constexpr auto kRange = details::EnumRange<E, details::FlagName>{}; return kRange.values[__builtin_ctzl(value)]; return kRange.values[__builtin_ctzll(value)]; } } // Returns a stringified enumerator, or its integral value if not named. // Returns a stringified enumerator, or its integral value if not named. Loading
libs/ftl/Android.bp +0 −8 Original line number Original line Diff line number Diff line Loading @@ -32,12 +32,4 @@ cc_test { "-Wpedantic", "-Wpedantic", "-Wthread-safety", "-Wthread-safety", ], ], header_libs: [ "libbase_headers", ], shared_libs: [ "libbase", ], } }
libs/ftl/enum_test.cpp +10 −0 Original line number Original line Diff line number Diff line Loading @@ -143,6 +143,16 @@ TEST(Enum, String) { EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0"); EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0"); EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010"); EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010"); EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111"); EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111"); enum class Flags64 : std::uint64_t { kFlag0 = 0b1ull, kFlag63 = 0x8000'0000'0000'0000ull, kMask = kFlag0 | kFlag63 }; EXPECT_EQ(ftl::flag_string(Flags64::kFlag0), "kFlag0"); EXPECT_EQ(ftl::flag_string(Flags64::kFlag63), "kFlag63"); EXPECT_EQ(ftl::flag_string(Flags64::kMask), "0x8000000000000001"); } } { { EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth"); EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth"); Loading