Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenlib/BLI_span.hh80
-rw-r--r--source/blender/blenlib/BLI_string_ref.hh24
-rw-r--r--source/blender/blenlib/tests/BLI_span_test.cc42
-rw-r--r--source/blender/blenlib/tests/BLI_string_ref_test.cc22
4 files changed, 119 insertions, 49 deletions
diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh
index 8011b2f9abc..5f55efe3f63 100644
--- a/source/blender/blenlib/BLI_span.hh
+++ b/source/blender/blenlib/BLI_span.hh
@@ -142,15 +142,15 @@ template<typename T> class Span {
}
/**
- * Returns a contiguous part of the array. This invokes undefined behavior when the slice does
- * not stay within the bounds of the array.
+ * Returns a contiguous part of the array. This invokes undefined behavior when the start or size
+ * is negative.
*/
constexpr Span slice(int64_t start, int64_t size) const
{
BLI_assert(start >= 0);
BLI_assert(size >= 0);
- BLI_assert(start + size <= this->size() || size == 0);
- return Span(data_ + start, size);
+ const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
+ return Span(data_ + start, new_size);
}
constexpr Span slice(IndexRange range) const
@@ -160,46 +160,46 @@ template<typename T> class Span {
/**
* Returns a new Span with n elements removed from the beginning. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr Span drop_front(int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= this->size());
- return this->slice(n, this->size() - n);
+ const int64_t new_size = std::max<int64_t>(0, size_ - n);
+ return Span(data_ + n, new_size);
}
/**
* Returns a new Span with n elements removed from the beginning. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr Span drop_back(int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= this->size());
- return this->slice(0, this->size() - n);
+ const int64_t new_size = std::max<int64_t>(0, size_ - n);
+ return Span(data_, new_size);
}
/**
* Returns a new Span that only contains the first n elements. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr Span take_front(int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= this->size());
- return this->slice(0, n);
+ const int64_t new_size = std::min<int64_t>(size_, n);
+ return Span(data_, new_size);
}
/**
* Returns a new Span that only contains the last n elements. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr Span take_back(int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= this->size());
- return this->slice(this->size() - n, n);
+ const int64_t new_size = std::min<int64_t>(size_, n);
+ return Span(data_ + size_ - new_size, new_size);
}
/**
@@ -481,6 +481,14 @@ template<typename T> class MutableSpan {
}
/**
+ * Returns true if the size is zero.
+ */
+ constexpr bool is_empty() const
+ {
+ return size_ == 0;
+ }
+
+ /**
* Replace all elements in the referenced array with the given value.
*/
constexpr void fill(const T &value)
@@ -534,53 +542,59 @@ template<typename T> class MutableSpan {
}
/**
- * Returns a contiguous part of the array. This invokes undefined behavior when the slice would
- * go out of bounds.
+ * Returns a contiguous part of the array. This invokes undefined behavior when the start or size
+ * is negative.
*/
- constexpr MutableSpan slice(const int64_t start, const int64_t length) const
+ constexpr MutableSpan slice(const int64_t start, const int64_t size) const
{
- BLI_assert(start + length <= this->size());
- return MutableSpan(data_ + start, length);
+ BLI_assert(start >= 0);
+ BLI_assert(size >= 0);
+ const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
+ return MutableSpan(data_ + start, new_size);
}
/**
* Returns a new MutableSpan with n elements removed from the beginning. This invokes
- * undefined behavior when the array is too small.
+ * undefined behavior when n is negative.
*/
constexpr MutableSpan drop_front(const int64_t n) const
{
- BLI_assert(n <= this->size());
- return this->slice(n, this->size() - n);
+ BLI_assert(n >= 0);
+ const int64_t new_size = std::max<int64_t>(0, size_ - n);
+ return MutableSpan(data_ + n, new_size);
}
/**
* Returns a new MutableSpan with n elements removed from the end. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr MutableSpan drop_back(const int64_t n) const
{
- BLI_assert(n <= this->size());
- return this->slice(0, this->size() - n);
+ BLI_assert(n >= 0);
+ const int64_t new_size = std::max<int64_t>(0, size_ - n);
+ return MutableSpan(data_, new_size);
}
/**
* Returns a new MutableSpan that only contains the first n elements. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr MutableSpan take_front(const int64_t n) const
{
- BLI_assert(n <= this->size());
- return this->slice(0, n);
+ BLI_assert(n >= 0);
+ const int64_t new_size = std::min<int64_t>(size_, n);
+ return MutableSpan(data_, new_size);
}
/**
* Return a new MutableSpan that only contains the last n elements. This invokes undefined
- * behavior when the array is too small.
+ * behavior when n is negative.
*/
constexpr MutableSpan take_back(const int64_t n) const
{
- BLI_assert(n <= this->size());
- return this->slice(this->size() - n, n);
+ BLI_assert(n >= 0);
+ const int64_t new_size = std::min<int64_t>(size_, n);
+ return MutableSpan(data_ + size_ - new_size, new_size);
}
/**
diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh
index a2562c6100a..0cff8fa7fb4 100644
--- a/source/blender/blenlib/BLI_string_ref.hh
+++ b/source/blender/blenlib/BLI_string_ref.hh
@@ -321,37 +321,36 @@ class StringRef : public StringRefBase {
}
/**
- * Returns a new StringRef that does not contain the first n chars.
- *
- * This is similar to std::string_view::remove_prefix.
+ * Returns a new StringRef that does not contain the first n chars. This invokes undefined
+ * behavior when n is negative.
*/
constexpr StringRef drop_prefix(const int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= size_);
- return StringRef(data_ + n, size_ - n);
+ const int64_t clamped_n = std::min(n, size_);
+ const int64_t new_size = size_ - clamped_n;
+ return StringRef(data_ + clamped_n, new_size);
}
/**
* Return a new StringRef with the given prefix being skipped. This invokes undefined behavior if
* the string does not begin with the given prefix.
*/
- constexpr StringRef drop_prefix(StringRef prefix) const
+ constexpr StringRef drop_known_prefix(StringRef prefix) const
{
BLI_assert(this->startswith(prefix));
return this->drop_prefix(prefix.size());
}
/**
- * Return a new StringRef that does not contain the last n chars.
- *
- * This is similar to std::string_view::remove_suffix.
+ * Return a new StringRef that does not contain the last n chars. This invokes undefined behavior
+ * when n is negative.
*/
constexpr StringRef drop_suffix(const int64_t n) const
{
BLI_assert(n >= 0);
- BLI_assert(n <= size_);
- return StringRef(data_, size_ - n);
+ const int64_t new_size = std::max<int64_t>(0, size_ - n);
+ return StringRef(data_, new_size);
}
/**
@@ -460,7 +459,8 @@ constexpr inline bool StringRefBase::endswith(StringRef suffix) const
}
/**
- * Return a new #StringRef containing only a sub-string of the original string.
+ * Return a new #StringRef containing only a sub-string of the original string. This invokes
+ * undefined if the start or max_size is negative.
*/
constexpr inline StringRef StringRefBase::substr(const int64_t start,
const int64_t max_size = INT64_MAX) const
diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc
index d1c9f312b97..002c97b0c7d 100644
--- a/source/blender/blenlib/tests/BLI_span_test.cc
+++ b/source/blender/blenlib/tests/BLI_span_test.cc
@@ -62,6 +62,15 @@ TEST(span, DropFront)
EXPECT_EQ(slice[2], 7);
}
+TEST(span, DropFrontLargeN)
+{
+ Vector<int> a = {1, 2, 3, 4, 5};
+ Span<int> slice1 = Span<int>(a).drop_front(100);
+ MutableSpan<int> slice2 = MutableSpan<int>(a).drop_front(100);
+ EXPECT_TRUE(slice1.is_empty());
+ EXPECT_TRUE(slice2.is_empty());
+}
+
TEST(span, DropFrontAll)
{
Vector<int> a = {4, 5, 6, 7};
@@ -78,6 +87,15 @@ TEST(span, TakeFront)
EXPECT_EQ(slice[1], 5);
}
+TEST(span, TakeFrontLargeN)
+{
+ Vector<int> a = {4, 5, 6, 7};
+ Span<int> slice1 = Span<int>(a).take_front(100);
+ MutableSpan<int> slice2 = MutableSpan<int>(a).take_front(100);
+ EXPECT_EQ(slice1.size(), 4);
+ EXPECT_EQ(slice2.size(), 4);
+}
+
TEST(span, TakeBack)
{
Vector<int> a = {5, 6, 7, 8};
@@ -87,6 +105,15 @@ TEST(span, TakeBack)
EXPECT_EQ(slice[1], 8);
}
+TEST(span, TakeBackLargeN)
+{
+ Vector<int> a = {3, 4, 5, 6};
+ Span<int> slice1 = Span<int>(a).take_back(100);
+ MutableSpan<int> slice2 = MutableSpan<int>(a).take_back(100);
+ EXPECT_EQ(slice1.size(), 4);
+ EXPECT_EQ(slice2.size(), 4);
+}
+
TEST(span, Slice)
{
Vector<int> a = {4, 5, 6, 7};
@@ -112,6 +139,19 @@ TEST(span, SliceRange)
EXPECT_EQ(slice[1], 4);
}
+TEST(span, SliceLargeN)
+{
+ Vector<int> a = {1, 2, 3, 4, 5};
+ Span<int> slice1 = Span<int>(a).slice(3, 100);
+ MutableSpan<int> slice2 = MutableSpan<int>(a).slice(3, 100);
+ EXPECT_EQ(slice1.size(), 2);
+ EXPECT_EQ(slice2.size(), 2);
+ EXPECT_EQ(slice1[0], 4);
+ EXPECT_EQ(slice2[0], 4);
+ EXPECT_EQ(slice1[1], 5);
+ EXPECT_EQ(slice2[1], 5);
+}
+
TEST(span, Contains)
{
Vector<int> a = {4, 5, 6, 7};
@@ -337,7 +377,7 @@ TEST(span, MutableReverseIterator)
EXPECT_EQ_ARRAY(src.data(), Span({14, 15, 16, 17}).data(), 4);
}
-TEST(span, constexpr_)
+TEST(span, Constexpr)
{
static constexpr std::array<int, 3> src = {3, 2, 1};
constexpr Span<int> span(src);
diff --git a/source/blender/blenlib/tests/BLI_string_ref_test.cc b/source/blender/blenlib/tests/BLI_string_ref_test.cc
index 401a7bc1118..fb8b894bfd5 100644
--- a/source/blender/blenlib/tests/BLI_string_ref_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_ref_test.cc
@@ -246,10 +246,18 @@ TEST(string_ref, DropPrefixN)
EXPECT_EQ(ref3, "");
}
-TEST(string_ref, DropPrefix)
+TEST(string_ref, DropPrefixLargeN)
{
StringRef ref("test");
- StringRef ref2 = ref.drop_prefix("tes");
+ StringRef ref2 = ref.drop_prefix(100);
+ EXPECT_EQ(ref2.size(), 0);
+ EXPECT_EQ(ref2, "");
+}
+
+TEST(string_ref, DropKnownPrefix)
+{
+ StringRef ref("test");
+ StringRef ref2 = ref.drop_known_prefix("tes");
EXPECT_EQ(ref2.size(), 1);
EXPECT_EQ(ref2, "t");
}
@@ -262,6 +270,14 @@ TEST(string_ref, DropSuffix)
EXPECT_EQ(ref2, "tes");
}
+TEST(string_ref, DropSuffixLargeN)
+{
+ StringRef ref("test");
+ StringRef ref2 = ref.drop_suffix(100);
+ EXPECT_EQ(ref2.size(), 0);
+ EXPECT_EQ(ref2, "");
+}
+
TEST(string_ref, Substr)
{
StringRef ref("hello world");
@@ -298,7 +314,7 @@ TEST(string_ref, ToStringView)
EXPECT_EQ(view, "hello");
}
-TEST(string_ref, constexpr_)
+TEST(string_ref, Constexpr)
{
constexpr StringRef sref("World");
BLI_STATIC_ASSERT(sref[2] == 'r', "");