diff --git a/libtransmission/bitfield.cc b/libtransmission/bitfield.cc index 56310988d..fdd82ea1d 100644 --- a/libtransmission/bitfield.cc +++ b/libtransmission/bitfield.cc @@ -485,3 +485,26 @@ tr_bitfield& tr_bitfield::operator&=(tr_bitfield const& that) noexcept rebuildTrueCount(); return *this; } + +bool tr_bitfield::intersects(tr_bitfield const& that) const noexcept +{ + if (hasNone() || that.hasNone()) + { + return false; + } + + if (hasAll() || that.hasAll()) + { + return true; + } + + for (size_t i = 0, n = std::min(std::size(flags_), std::size(that.flags_)); i < n; ++i) + { + if ((flags_[i] & that.flags_[i]) != 0U) + { + return true; + } + } + + return false; +} diff --git a/libtransmission/bitfield.h b/libtransmission/bitfield.h index a06f97c7e..9d1f60bdc 100644 --- a/libtransmission/bitfield.h +++ b/libtransmission/bitfield.h @@ -114,6 +114,7 @@ public: tr_bitfield& operator|=(tr_bitfield const& that) noexcept; tr_bitfield& operator&=(tr_bitfield const& that) noexcept; + [[nodiscard]] bool intersects(tr_bitfield const& that) const noexcept; private: [[nodiscard]] size_t countFlags() const noexcept; diff --git a/tests/libtransmission/bitfield-test.cc b/tests/libtransmission/bitfield-test.cc index b7547ffff..e8bdc702b 100644 --- a/tests/libtransmission/bitfield-test.cc +++ b/tests/libtransmission/bitfield-test.cc @@ -445,3 +445,63 @@ TEST(Bitfield, bitwiseAnd) b &= a; EXPECT_NEAR(0.1F, a.percent(), 0.01); } + +TEST(Bitfield, intersects) +{ + auto a = tr_bitfield{ 100 }; + auto b = tr_bitfield{ 100 }; + + a.setHasAll(); + b.setHasNone(); + EXPECT_FALSE(a.intersects(b)); + EXPECT_FALSE(b.intersects(a)); + + a.setHasAll(); + b.setHasAll(); + EXPECT_TRUE(a.intersects(b)); + EXPECT_TRUE(b.intersects(a)); + + a.setHasNone(); + b.setHasNone(); + EXPECT_FALSE(a.intersects(b)); + EXPECT_FALSE(b.intersects(a)); + + a.setHasNone(); + b.setHasNone(); + a.setSpan(0, std::size(a) / 2U); + b.setSpan(std::size(a) / 2U, std::size(a)); + EXPECT_EQ(0.5, a.percent()); + EXPECT_EQ(0.5, b.percent()); + EXPECT_FALSE(a.intersects(b)); + EXPECT_FALSE(b.intersects(a)); + + a.setHasNone(); + b.setHasNone(); + for (size_t i = 0; i < std::size(a); ++i) + { + if ((i % 2U) != 0U) + { + a.set(i); + } + else + { + b.set(i); + } + } + EXPECT_FALSE(a.intersects(b)); + EXPECT_FALSE(b.intersects(a)); + + a.setHasNone(); + a.setSpan(0U, std::size(a) / 10U); + b.setHasNone(); + b.setSpan(0U, std::size(a) / 20U); + EXPECT_TRUE(a.intersects(b)); + EXPECT_TRUE(b.intersects(a)); + + a.setHasNone(); + a.setSpan(0U, std::size(a) / 10U); + b.setHasNone(); + b.setSpan(0U, std::size(a) / 20U); + EXPECT_TRUE(a.intersects(b)); + EXPECT_TRUE(b.intersects(a)); +}