Browse Source

sparse_set: ::contains uses the right version mask

Michele Caini 2 years ago
parent
commit
9e62e1dab6
2 changed files with 33 additions and 2 deletions
  1. 2 1
      src/entt/entity/sparse_set.hpp
  2. 31 1
      test/entt/entity/sparse_set.cpp

+ 2 - 1
src/entt/entity/sparse_set.hpp

@@ -724,8 +724,9 @@ public:
     [[nodiscard]] bool contains(const entity_type entt) const noexcept {
         const auto elem = sparse_ptr(entt);
         constexpr auto cap = traits_type::entity_mask;
+        constexpr auto mask = traits_type::to_integral(null) & ~cap;
         // testing versions permits to avoid accessing the packed array
-        return elem && (((~cap & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
+        return elem && (((mask & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
     }
 
     /**

+ 31 - 1
test/entt/entity/sparse_set.cpp

@@ -21,7 +21,7 @@ struct custom_entity_traits {
     using entity_type = std::uint32_t;
     using version_type = std::uint16_t;
     static constexpr entity_type entity_mask = 0x3FFFF; // 18b
-    static constexpr entity_type version_mask = 0x3FFF; // 14b
+    static constexpr entity_type version_mask = 0x0FFF; // 12b
 };
 
 template<>
@@ -765,6 +765,36 @@ TYPED_TEST(SparseSet, Contains) {
 
         ASSERT_FALSE(set.contains(entity));
         ASSERT_FALSE(set.contains(other));
+
+        if constexpr(traits_type::to_integral(entt::tombstone) != ~traits_type::entity_type{}) {
+            // test reserved bits, if any
+            constexpr entity_type reserved{traits_type::to_integral(entity) | (traits_type::to_integral(entt::tombstone) + 1u)};
+
+            ASSERT_NE(entity, reserved);
+
+            set.push(reserved);
+
+            ASSERT_TRUE(set.contains(entity));
+            ASSERT_TRUE(set.contains(reserved));
+
+            ASSERT_NE(*set.find(entity), entity);
+            ASSERT_EQ(*set.find(entity), reserved);
+
+            set.bump(entity);
+
+            ASSERT_TRUE(set.contains(entity));
+            ASSERT_TRUE(set.contains(reserved));
+
+            ASSERT_NE(*set.find(reserved), reserved);
+            ASSERT_EQ(*set.find(reserved), entity);
+
+            set.erase(reserved);
+
+            ASSERT_FALSE(set.contains(entity));
+            ASSERT_FALSE(set.contains(reserved));
+
+            ASSERT_EQ(set.find(reserved), set.end());
+        }
     }
 }