Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,35 @@ BOOST_AUTO_TEST_CASE(test_CRanges)
BOOST_CHECK(ranges.Size() > ((1u << test) / 4));
}
}

// The range containing UINT64_MAX is stored with a wrapped half-open end
// of 0. Membership, sizing, duplicate detection, and removal must all
// treat that representation as "extends through the maximum value".
const uint64_t max{std::numeric_limits<uint64_t>::max()};
CRangesSet max_values;
BOOST_CHECK(max_values.Add(max - 2));
BOOST_CHECK(max_values.Add(max - 1));
BOOST_CHECK(max_values.Add(max));
BOOST_CHECK_EQUAL(max_values.Size(), 3U);
BOOST_CHECK(max_values.Contains(max - 2));
BOOST_CHECK(max_values.Contains(max - 1));
BOOST_CHECK(max_values.Contains(max));
BOOST_CHECK(!max_values.Contains(0));
BOOST_CHECK(!max_values.Add(max));
BOOST_CHECK(max_values.Remove(max));
BOOST_CHECK_EQUAL(max_values.Size(), 2U);
BOOST_CHECK(max_values.Contains(max - 1));
BOOST_CHECK(!max_values.Contains(max));
BOOST_CHECK(max_values.Add(max));
BOOST_CHECK(max_values.Contains(max));

CRangesSet lone_max;
BOOST_CHECK(lone_max.Add(max));
BOOST_CHECK_EQUAL(lone_max.Size(), 1U);
BOOST_CHECK(lone_max.Contains(max));
BOOST_CHECK(!lone_max.Add(max));
BOOST_CHECK(lone_max.Remove(max));
BOOST_CHECK(lone_max.IsEmpty());
}

static std::string SpanToStr(const Span<const char>& span)
Expand Down
8 changes: 6 additions & 2 deletions src/util/ranges_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <util/ranges_set.h>

#include <limits>

CRangesSet::Range::Range() : CRangesSet::Range::Range(0, 0) {}

CRangesSet::Range::Range(uint64_t begin_in, uint64_t end_in) :
Expand Down Expand Up @@ -81,7 +83,9 @@ size_t CRangesSet::Size() const noexcept
{
size_t result{0};
for (auto i : ranges) {
result += i.end - i.begin;
// end == 0 is the half-open representation of a range containing
// UINT64_MAX. Avoid the unsigned subtraction wrap for that range.
result += i.end == 0 ? std::numeric_limits<uint64_t>::max() - i.begin + 1 : i.end - i.begin;
}
return result;
}
Expand All @@ -93,5 +97,5 @@ bool CRangesSet::Contains(uint64_t value) const noexcept
if (it == ranges.begin()) return false;
auto prev = it;
--prev;
return prev->begin <= value && prev->end > value;
return prev->begin <= value && (prev->end == 0 || prev->end > value);
}
Loading