BLI: Add functions to IndexRange to mirror Span

Adds functions for special cases of slicing and an `is_empty` method.
This commit is contained in:
Hans Goudey 2022-03-03 11:14:44 -05:00
parent e8dc82311d
commit d793d18413
2 changed files with 125 additions and 0 deletions

View File

@ -148,6 +148,14 @@ class IndexRange {
return size_;
}
/**
* Returns true if the size is zero.
*/
constexpr bool is_empty() const
{
return size_ == 0;
}
/**
* Create a new range starting at the end of the current one.
*/
@ -226,6 +234,50 @@ class IndexRange {
return this->slice(range.start(), range.size());
}
/**
* Returns a new IndexRange with n elements removed from the beginning. This invokes undefined
* behavior when n is negative.
*/
constexpr IndexRange drop_front(int64_t n) const
{
BLI_assert(n >= 0);
const int64_t new_size = std::max<int64_t>(0, size_ - n);
return IndexRange(start_ + n, new_size);
}
/**
* Returns a new IndexRange with n elements removed from the beginning. This invokes undefined
* behavior when n is negative.
*/
constexpr IndexRange drop_back(int64_t n) const
{
BLI_assert(n >= 0);
const int64_t new_size = std::max<int64_t>(0, size_ - n);
return IndexRange(start_, new_size);
}
/**
* Returns a new IndexRange that only contains the first n elements. This invokes undefined
* behavior when n is negative.
*/
constexpr IndexRange take_front(int64_t n) const
{
BLI_assert(n >= 0);
const int64_t new_size = std::min<int64_t>(size_, n);
return IndexRange(start_, new_size);
}
/**
* Returns a new IndexRange that only contains the last n elements. This invokes undefined
* behavior when n is negative.
*/
constexpr IndexRange take_back(int64_t n) const
{
BLI_assert(n >= 0);
const int64_t new_size = std::min<int64_t>(size_, n);
return IndexRange(start_ + size_ - new_size, new_size);
}
/**
* Get read-only access to a memory buffer that contains the range as actual numbers.
*/

View File

@ -129,6 +129,79 @@ TEST(index_range, SliceRange)
EXPECT_EQ(slice.last(), 12);
}
TEST(index_range, DropBack)
{
IndexRange a(4, 4);
auto slice = a.drop_back(2);
EXPECT_EQ(slice.size(), 2);
EXPECT_EQ(slice.start(), 4);
EXPECT_EQ(slice[1], 5);
}
TEST(index_range, DropBackAll)
{
IndexRange a(4, 4);
auto slice = a.drop_back(a.size());
EXPECT_TRUE(slice.is_empty());
}
TEST(index_range, DropFront)
{
IndexRange a(4, 4);
auto slice = a.drop_front(1);
EXPECT_EQ(slice.size(), 3);
EXPECT_EQ(slice[0], 5);
EXPECT_EQ(slice[1], 6);
EXPECT_EQ(slice.last(), 7);
}
TEST(index_range, DropFrontLargeN)
{
IndexRange a(1, 5);
IndexRange slice = a.drop_front(100);
EXPECT_TRUE(slice.is_empty());
}
TEST(index_range, DropFrontAll)
{
IndexRange a(50);
IndexRange slice = a.drop_front(a.size());
EXPECT_TRUE(slice.is_empty());
}
TEST(index_range, TakeFront)
{
IndexRange a(4, 4);
IndexRange slice = a.take_front(2);
EXPECT_EQ(slice.size(), 2);
EXPECT_EQ(slice[0], 4);
EXPECT_EQ(slice[1], 5);
}
TEST(index_range, TakeFrontLargeN)
{
IndexRange a(4, 4);
IndexRange slice = a.take_front(100);
EXPECT_EQ(slice.size(), 4);
}
TEST(index_range, TakeBack)
{
IndexRange a(4, 4);
auto slice = a.take_back(2);
EXPECT_EQ(slice.size(), 2);
EXPECT_EQ(slice[0], 6);
EXPECT_EQ(slice[1], 7);
}
TEST(index_range, TakeBackLargeN)
{
IndexRange a(3, 4);
IndexRange slice = a.take_back(100);
EXPECT_EQ(slice.size(), 4);
EXPECT_EQ(slice.size(), 4);
}
TEST(index_range, AsSpan)
{
IndexRange range = IndexRange(4, 6);