From 62394b2492bf4df77f8277e7b7c1b3605dbb467e Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 1 Dec 2021 16:17:00 +0000 Subject: [PATCH] utils: Add more methods to EnumSet Add assignment operators and methods for adding, removing and operators for performing set arithmatic. Change-Id: I13d30734354f503180f75480866b54034f647c2a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/71320 Commit-Queue: Ben Clayton Reviewed-by: Antonio Maiorano Kokoro: Kokoro --- src/utils/enum_set.h | 84 ++++++++++++++++++++++++++++++----- src/utils/enum_set_test.cc | 90 +++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 12 deletions(-) diff --git a/src/utils/enum_set.h b/src/utils/enum_set.h index 3a71f78852..87da779ef4 100644 --- a/src/utils/enum_set.h +++ b/src/utils/enum_set.h @@ -19,6 +19,7 @@ #include #include #include +#include namespace tint { namespace utils { @@ -40,25 +41,88 @@ struct EnumSet { template explicit constexpr EnumSet(VALUES... values) : set(Union(values...)) {} - /// Adds e to this set + /// Copy assignment operator. + /// @param set the set to assign to this set + /// @return this set so calls can be chained + inline EnumSet& operator=(const EnumSet& set) = default; + + /// Copy assignment operator. /// @param e the enum value /// @return this set so calls can be chained - inline EnumSet& Add(Enum e) { - set |= Bit(e); - return *this; + inline EnumSet& operator=(Enum e) { return *this = EnumSet{e}; } + + /// Adds all the given values to this set + /// @param values the values to add + /// @return this set so calls can be chained + template + inline EnumSet& Add(VALUES... values) { + return Add(EnumSet(std::forward(values)...)); } - /// Removes e from this set - /// @param e the enum value + /// Removes all the given values from this set + /// @param values the values to remove /// @return this set so calls can be chained - inline EnumSet& Remove(Enum e) { - set &= ~Bit(e); - return *this; + template + inline EnumSet& Remove(VALUES... values) { + return Remove(EnumSet(std::forward(values)...)); + } + + /// Adds all of s to this set + /// @param s the enum value + /// @return this set so calls can be chained + inline EnumSet& Add(EnumSet s) { return (*this = *this + s); } + + /// Removes all of s from this set + /// @param s the enum value + /// @return this set so calls can be chained + inline EnumSet& Remove(EnumSet s) { return (*this = *this - s); } + + /// @param e the enum value + /// @returns a copy of this set with e added + inline EnumSet operator+(Enum e) const { + EnumSet out; + out.set = set | Bit(e); + return out; + } + + /// @param e the enum value + /// @returns a copy of this set with e removed + inline EnumSet operator-(Enum e) const { + EnumSet out; + out.set = set & ~Bit(e); + return out; + } + + /// @param s the other set + /// @returns the union of this set with s (this ∪ rhs) + inline EnumSet operator+(EnumSet s) const { + EnumSet out; + out.set = set | s.set; + return out; + } + + /// @param s the other set + /// @returns the set of entries found in this but not in s (this \ s) + inline EnumSet operator-(EnumSet s) const { + EnumSet out; + out.set = set & ~s.set; + return out; + } + + /// @param s the other set + /// @returns the intersection of this set with s (this ∩ rhs) + inline EnumSet operator&(EnumSet s) const { + EnumSet out; + out.set = set & s.set; + return out; } /// @param e the enum value /// @return true if the set contains `e` - inline bool Contains(Enum e) { return (set & Bit(e)) != 0; } + inline bool Contains(Enum e) const { return (set & Bit(e)) != 0; } + + /// @return true if the set is empty + inline bool Empty() const { return set == 0; } /// Equality operator /// @param rhs the other EnumSet to compare this to diff --git a/src/utils/enum_set_test.cc b/src/utils/enum_set_test.cc index 9a5186df1a..b7f5b72221 100644 --- a/src/utils/enum_set_test.cc +++ b/src/utils/enum_set_test.cc @@ -44,6 +44,7 @@ TEST(EnumSetTest, ConstructEmpty) { EXPECT_FALSE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); + EXPECT_TRUE(set.Empty()); } TEST(EnumSetTest, ConstructWithSingle) { @@ -51,6 +52,7 @@ TEST(EnumSetTest, ConstructWithSingle) { EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); + EXPECT_FALSE(set.Empty()); } TEST(EnumSetTest, ConstructWithMultiple) { @@ -58,9 +60,26 @@ TEST(EnumSetTest, ConstructWithMultiple) { EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); + EXPECT_FALSE(set.Empty()); } -TEST(EnumSetTest, Add) { +TEST(EnumSetTest, AssignSet) { + EnumSet set; + set = EnumSet(E::A, E::C); + EXPECT_TRUE(set.Contains(E::A)); + EXPECT_FALSE(set.Contains(E::B)); + EXPECT_TRUE(set.Contains(E::C)); +} + +TEST(EnumSetTest, AssignEnum) { + EnumSet set(E::A); + set = E::B; + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + +TEST(EnumSetTest, AddEnum) { EnumSet set; set.Add(E::B); EXPECT_FALSE(set.Contains(E::A)); @@ -68,7 +87,7 @@ TEST(EnumSetTest, Add) { EXPECT_FALSE(set.Contains(E::C)); } -TEST(EnumSetTest, Remove) { +TEST(EnumSetTest, RemoveEnum) { EnumSet set(E::A, E::B); set.Remove(E::B); EXPECT_TRUE(set.Contains(E::A)); @@ -76,6 +95,73 @@ TEST(EnumSetTest, Remove) { EXPECT_FALSE(set.Contains(E::C)); } +TEST(EnumSetTest, AddEnums) { + EnumSet set; + set.Add(E::B, E::C); + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_TRUE(set.Contains(E::C)); +} + +TEST(EnumSetTest, RemoveEnums) { + EnumSet set(E::A, E::B); + set.Remove(E::C, E::B); + EXPECT_TRUE(set.Contains(E::A)); + EXPECT_FALSE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + +TEST(EnumSetTest, AddEnumSet) { + EnumSet set; + set.Add(EnumSet{E::B, E::C}); + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_TRUE(set.Contains(E::C)); +} + +TEST(EnumSetTest, RemoveEnumSet) { + EnumSet set(E::A, E::B); + set.Remove(EnumSet{E::B, E::C}); + EXPECT_TRUE(set.Contains(E::A)); + EXPECT_FALSE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + +TEST(EnumSetTest, OperatorPlusEnum) { + EnumSet set = EnumSet{E::B} + E::C; + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_TRUE(set.Contains(E::C)); +} + +TEST(EnumSetTest, OperatorMinusEnum) { + EnumSet set = EnumSet{E::A, E::B} - E::B; + EXPECT_TRUE(set.Contains(E::A)); + EXPECT_FALSE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + +TEST(EnumSetTest, OperatorPlusSet) { + EnumSet set = EnumSet{E::B} + EnumSet{E::B, E::C}; + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_TRUE(set.Contains(E::C)); +} + +TEST(EnumSetTest, OperatorMinusSet) { + EnumSet set = EnumSet{E::A, E::B} - EnumSet{E::B, E::C}; + EXPECT_TRUE(set.Contains(E::A)); + EXPECT_FALSE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + +TEST(EnumSetTest, OperatorAnd) { + EnumSet set = EnumSet{E::A, E::B} & EnumSet{E::B, E::C}; + EXPECT_FALSE(set.Contains(E::A)); + EXPECT_TRUE(set.Contains(E::B)); + EXPECT_FALSE(set.Contains(E::C)); +} + TEST(EnumSetTest, EqualitySet) { EXPECT_TRUE(EnumSet(E::A, E::B) == EnumSet(E::A, E::B)); EXPECT_FALSE(EnumSet(E::A, E::B) == EnumSet(E::A, E::C));