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:
authorJacques Lucke <jacques@blender.org>2021-02-21 00:05:27 +0300
committerJacques Lucke <jacques@blender.org>2021-02-21 00:05:50 +0300
commit6c2e1f33983766ee5ee028e14a24e36c28d0a566 (patch)
tree101fc34380934b0ce99af0ce010b2b5c4d3e1e05 /source/blender/blenlib/BLI_span.hh
parentd8b4246b9fde78d6eaab170eb34951d7c46778f3 (diff)
BLI: cleanup StringRef and Span and improve parameter validation
Previously, methods like `Span.drop_front` would crash when more elements would be dropped than are available. While this is most efficient, it is not very practical in some use cases. Also other languages silently clamp the index, so one can easily write wrong code accidentally. Now, `Span.drop_front` and similar methods will only crash when n is negative. Too large values will be clamped down to their maximum possible value. While this is slightly less efficient, I did not have a case where this actually mattered yet. If it does matter in the future, we can add a separate `*_unchecked` method. This should not change the behavior of existing code.
Diffstat (limited to 'source/blender/blenlib/BLI_span.hh')
-rw-r--r--source/blender/blenlib/BLI_span.hh80
1 files changed, 47 insertions, 33 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);
}
/**