Blender V5.0
BLI_span.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
58
59#include <algorithm>
60#include <array>
61#include <vector>
62
63#include "BLI_hash_fwd.hh"
64#include "BLI_index_range.hh"
65#include "BLI_memory_utils.hh"
66#include "BLI_utildefines.h"
67
68namespace blender {
69
74template<typename T> class Span {
75 public:
76 using value_type = T;
77 using pointer = T *;
78 using const_pointer = const T *;
79 using reference = T &;
80 using const_reference = const T &;
81 using iterator = const T *;
83
84 protected:
85 const T *data_ = nullptr;
87
88 public:
92 constexpr Span() = default;
93
94 constexpr Span(const T *start, int64_t size) : data_(start), size_(size)
95 {
96 BLI_assert(size >= 0);
97 }
98
99 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
100 constexpr Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
101 {
102 BLI_assert(size >= 0);
103 }
104
116 constexpr Span(const std::initializer_list<T> &list) : Span(list.begin(), int64_t(list.size()))
117 {
118 }
119
120 constexpr Span(const std::vector<T> &vector) : Span(vector.data(), int64_t(vector.size())) {}
121
122 template<std::size_t N> constexpr Span(const std::array<T, N> &array) : Span(array.data(), N) {}
123
128 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
129 constexpr Span(Span<U> span) : data_(static_cast<const T *>(span.data())), size_(span.size())
130 {
131 }
132
137 constexpr Span slice(int64_t start, int64_t size) const
138 {
139 BLI_assert(start >= 0);
140 BLI_assert(size >= 0);
141 BLI_assert(start + size <= size_ || size == 0);
142 return Span(data_ + start, size);
143 }
144
145 constexpr Span slice(IndexRange range) const
146 {
147 return this->slice(range.start(), range.size());
148 }
149
154 constexpr Span slice_safe(const int64_t start, const int64_t size) const
155 {
156 BLI_assert(start >= 0);
157 BLI_assert(size >= 0);
158 const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
159 return Span(data_ ? data_ + start : nullptr, new_size);
160 }
161
162 constexpr Span slice_safe(IndexRange range) const
163 {
164 return this->slice_safe(range.start(), range.size());
165 }
166
171 constexpr Span drop_front(int64_t n) const
172 {
173 BLI_assert(n >= 0);
174 const int64_t new_size = std::max<int64_t>(0, size_ - n);
175 return Span(data_ + n, new_size);
176 }
177
182 constexpr Span drop_back(int64_t n) const
183 {
184 BLI_assert(n >= 0);
185 const int64_t new_size = std::max<int64_t>(0, size_ - n);
186 return Span(data_, new_size);
187 }
188
193 constexpr Span take_front(int64_t n) const
194 {
195 BLI_assert(n >= 0);
196 const int64_t new_size = std::min<int64_t>(size_, n);
197 return Span(data_, new_size);
198 }
199
204 constexpr Span take_back(int64_t n) const
205 {
206 BLI_assert(n >= 0);
207 const int64_t new_size = std::min<int64_t>(size_, n);
208 return Span(data_ + size_ - new_size, new_size);
209 }
210
215 constexpr const T *data() const
216 {
217 return data_;
218 }
219
220 constexpr const T *begin() const
221 {
222 return data_;
223 }
224 constexpr const T *end() const
225 {
226 return data_ + size_;
227 }
228
229 constexpr std::reverse_iterator<const T *> rbegin() const
230 {
231 return std::reverse_iterator<const T *>(this->end());
232 }
233 constexpr std::reverse_iterator<const T *> rend() const
234 {
235 return std::reverse_iterator<const T *>(this->begin());
236 }
237
242 constexpr const T &operator[](int64_t index) const
243 {
244 BLI_assert(index >= 0);
245 BLI_assert(index < size_);
246 return data_[index];
247 }
248
252 constexpr int64_t size() const
253 {
254 return size_;
255 }
256
260 constexpr bool is_empty() const
261 {
262 return size_ == 0;
263 }
264
268 constexpr int64_t size_in_bytes() const
269 {
270 return sizeof(T) * size_;
271 }
272
277 constexpr bool contains(const T &value) const
278 {
279 for (const T &element : *this) {
280 if (element == value) {
281 return true;
282 }
283 }
284 return false;
285 }
286
291 constexpr bool contains_ptr(const T *ptr) const
292 {
293 return (this->begin() <= ptr) && (ptr < this->end());
294 }
295
300 constexpr int64_t count(const T &value) const
301 {
302 int64_t counter = 0;
303 for (const T &element : *this) {
304 if (element == value) {
305 counter++;
306 }
307 }
308 return counter;
309 }
310
315 constexpr const T &first() const
316 {
317 BLI_assert(size_ > 0);
318 return data_[0];
319 }
320
325 constexpr const T &last(const int64_t n = 0) const
326 {
327 BLI_assert(n >= 0);
328 BLI_assert(n < size_);
329 return data_[size_ - 1 - n];
330 }
331
336 constexpr bool has_duplicates__linear_search() const
337 {
338 /* The size should really be smaller than that. If it is not, the calling code should be
339 * changed. */
340 BLI_assert(size_ < 1000);
341
342 for (int64_t i = 0; i < size_; i++) {
343 const T &value = data_[i];
344 for (int64_t j = i + 1; j < size_; j++) {
345 if (value == data_[j]) {
346 return true;
347 }
348 }
349 }
350 return false;
351 }
352
358 constexpr bool intersects__linear_search(Span other) const
359 {
360 /* The size should really be smaller than that. If it is not, the calling code should be
361 * changed. */
362 BLI_assert(size_ < 1000);
363
364 for (int64_t i = 0; i < size_; i++) {
365 const T &value = data_[i];
366 if (other.contains(value)) {
367 return true;
368 }
369 }
370 return false;
371 }
372
377 constexpr int64_t first_index(const T &search_value) const
378 {
379 const int64_t index = this->first_index_try(search_value);
380 BLI_assert(index >= 0);
381 return index;
382 }
383
387 constexpr int64_t first_index_try(const T &search_value) const
388 {
389 for (int64_t i = 0; i < size_; i++) {
390 if (data_[i] == search_value) {
391 return i;
392 }
393 }
394 return -1;
395 }
396
401 constexpr IndexRange index_range() const
402 {
403 return IndexRange(size_);
404 }
405
406 constexpr uint64_t hash() const
407 {
408 uint64_t hash = 0;
409 for (const T &value : *this) {
410 hash = hash * 33 ^ get_default_hash(value);
411 }
412 return hash;
413 }
414
418 template<typename NewT> Span<NewT> constexpr cast() const
419 {
420 BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
421 int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
422 return Span<NewT>(reinterpret_cast<const NewT *>(data_), new_size);
423 }
424
425 friend bool operator==(const Span<T> a, const Span<T> b)
426 {
427 if (a.size() != b.size()) {
428 return false;
429 }
430 return std::equal(a.begin(), a.end(), b.begin());
431 }
432
433 friend bool operator!=(const Span<T> a, const Span<T> b)
434 {
435 return !(a == b);
436 }
437};
438
443template<typename T> class MutableSpan {
444 public:
445 using value_type = T;
446 using pointer = T *;
447 using const_pointer = const T *;
448 using reference = T &;
449 using const_reference = const T &;
450 using iterator = T *;
452
453 protected:
454 T *data_ = nullptr;
456
457 public:
458 constexpr MutableSpan() = default;
459
460 constexpr MutableSpan(T *start, const int64_t size) : data_(start), size_(size) {}
461
462 constexpr MutableSpan(std::vector<T> &vector) : MutableSpan(vector.data(), vector.size()) {}
463
464 template<std::size_t N>
465 constexpr MutableSpan(std::array<T, N> &array) : MutableSpan(array.data(), N)
466 {
467 }
468
473 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
475 : data_(static_cast<T *>(span.data())), size_(span.size())
476 {
477 }
478
479 constexpr operator Span<T>() const
480 {
481 return Span<T>(data_, size_);
482 }
483
484 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
485 constexpr operator Span<U>() const
486 {
487 return Span<U>(static_cast<const U *>(data_), size_);
488 }
489
493 constexpr int64_t size() const
494 {
495 return size_;
496 }
497
501 constexpr int64_t size_in_bytes() const
502 {
503 return sizeof(T) * size_;
504 }
505
509 constexpr bool is_empty() const
510 {
511 return size_ == 0;
512 }
513
517 constexpr void fill(const T &value) const
518 {
520 }
521
526 template<typename IndexT> constexpr void fill_indices(Span<IndexT> indices, const T &value) const
527 {
528 static_assert(std::is_integral_v<IndexT>);
529 for (IndexT i : indices) {
530 BLI_assert(i < size_);
531 data_[i] = value;
532 }
533 }
534
539 constexpr T *data() const
540 {
541 return data_;
542 }
543
544 constexpr T *begin() const
545 {
546 return data_;
547 }
548 constexpr T *end() const
549 {
550 return data_ + size_;
551 }
552
553 constexpr std::reverse_iterator<T *> rbegin() const
554 {
555 return std::reverse_iterator<T *>(this->end());
556 }
557 constexpr std::reverse_iterator<T *> rend() const
558 {
559 return std::reverse_iterator<T *>(this->begin());
560 }
561
562 constexpr T &operator[](const int64_t index) const
563 {
564 BLI_assert(index >= 0);
565 BLI_assert(index < size_);
566 return data_[index];
567 }
568
573 constexpr MutableSpan slice(const int64_t start, const int64_t size) const
574 {
575 BLI_assert(start >= 0);
576 BLI_assert(size >= 0);
577 BLI_assert(start + size <= size_ || size == 0);
578 return MutableSpan(data_ + start, size);
579 }
580
581 constexpr MutableSpan slice(IndexRange range) const
582 {
583 return this->slice(range.start(), range.size());
584 }
585
590 constexpr MutableSpan slice_safe(const int64_t start, const int64_t size) const
591 {
592 BLI_assert(start >= 0);
593 BLI_assert(size >= 0);
594 const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
595 return MutableSpan(data_ + start, new_size);
596 }
597
598 constexpr MutableSpan slice_safe(IndexRange range) const
599 {
600 return this->slice_safe(range.start(), range.size());
601 }
602
607 constexpr MutableSpan drop_front(const int64_t n) const
608 {
609 BLI_assert(n >= 0);
610 const int64_t new_size = std::max<int64_t>(0, size_ - n);
611 return MutableSpan(data_ + n, new_size);
612 }
613
618 constexpr MutableSpan drop_back(const int64_t n) const
619 {
620 BLI_assert(n >= 0);
621 const int64_t new_size = std::max<int64_t>(0, size_ - n);
622 return MutableSpan(data_, new_size);
623 }
624
629 constexpr MutableSpan take_front(const int64_t n) const
630 {
631 BLI_assert(n >= 0);
632 const int64_t new_size = std::min<int64_t>(size_, n);
633 return MutableSpan(data_, new_size);
634 }
635
640 constexpr MutableSpan take_back(const int64_t n) const
641 {
642 BLI_assert(n >= 0);
643 const int64_t new_size = std::min<int64_t>(size_, n);
644 return MutableSpan(data_ + size_ - new_size, new_size);
645 }
646
650 constexpr void reverse() const
651 {
652 for (const int i : IndexRange(size_ / 2)) {
653 std::swap(data_[size_ - 1 - i], data_[i]);
654 }
655 }
656
661 constexpr Span<T> as_span() const
662 {
663 return Span<T>(data_, size_);
664 }
665
670 constexpr IndexRange index_range() const
671 {
672 return IndexRange(size_);
673 }
674
679 constexpr T &first() const
680 {
681 BLI_assert(size_ > 0);
682 return data_[0];
683 }
684
689 constexpr T &last(const int64_t n = 0) const
690 {
691 BLI_assert(n >= 0);
692 BLI_assert(n < size_);
693 return data_[size_ - 1 - n];
694 }
695
700 constexpr int64_t count(const T &value) const
701 {
702 int64_t counter = 0;
703 for (const T &element : *this) {
704 if (element == value) {
705 counter++;
706 }
707 }
708 return counter;
709 }
710
715 constexpr bool contains(const T &value) const
716 {
717 for (const T &element : *this) {
718 if (element == value) {
719 return true;
720 }
721 }
722 return false;
723 }
724
729 constexpr bool contains_ptr(const T *ptr) const
730 {
731 return (this->begin() <= ptr) && (ptr < this->end());
732 }
733
739 constexpr void copy_from(Span<T> values) const
740 {
741 BLI_assert(size_ == values.size());
743 }
744
749 template<typename NewT> constexpr MutableSpan<NewT> cast() const
750 {
751 BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
752 int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
753 return MutableSpan<NewT>(reinterpret_cast<NewT *>(data_), new_size);
754 }
755};
756
757} /* namespace blender */
#define BLI_assert(a)
Definition BLI_assert.h:46
#define U
ATTR_WARN_UNUSED_RESULT const void * element
long long int int64_t
unsigned long long int uint64_t
blender::bke::pbvh::pixels::Rows::Pixel * data_
Definition BLI_span.hh:454
constexpr int64_t size() const
constexpr int64_t start() const
constexpr MutableSpan()=default
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr bool contains_ptr(const T *ptr) const
Definition BLI_span.hh:729
constexpr MutableSpan slice(IndexRange range) const
Definition BLI_span.hh:581
const T & const_reference
Definition BLI_span.hh:449
constexpr T & operator[](const int64_t index) const
Definition BLI_span.hh:562
constexpr bool contains(const T &value) const
Definition BLI_span.hh:715
constexpr std::reverse_iterator< T * > rbegin() const
Definition BLI_span.hh:553
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:573
constexpr bool is_empty() const
Definition BLI_span.hh:509
constexpr MutableSpan< NewT > cast() const
Definition BLI_span.hh:749
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:640
constexpr T * data() const
Definition BLI_span.hh:539
constexpr MutableSpan drop_back(const int64_t n) const
Definition BLI_span.hh:618
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr MutableSpan slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:590
constexpr MutableSpan drop_front(const int64_t n) const
Definition BLI_span.hh:607
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:501
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr T * end() const
Definition BLI_span.hh:548
constexpr MutableSpan(std::array< T, N > &array)
Definition BLI_span.hh:465
constexpr void reverse() const
Definition BLI_span.hh:650
constexpr T & first() const
Definition BLI_span.hh:679
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:700
constexpr T * begin() const
Definition BLI_span.hh:544
const T * const_pointer
Definition BLI_span.hh:447
constexpr MutableSpan(std::vector< T > &vector)
Definition BLI_span.hh:462
constexpr MutableSpan slice_safe(IndexRange range) const
Definition BLI_span.hh:598
constexpr std::reverse_iterator< T * > rend() const
Definition BLI_span.hh:557
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr MutableSpan(T *start, const int64_t size)
Definition BLI_span.hh:460
constexpr void fill_indices(Span< IndexT > indices, const T &value) const
Definition BLI_span.hh:526
constexpr MutableSpan(MutableSpan< U > span)
Definition BLI_span.hh:474
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:629
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:689
const T * data_
Definition BLI_span.hh:85
friend bool operator!=(const Span< T > a, const Span< T > b)
Definition BLI_span.hh:433
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:171
Span< NewT > constexpr cast() const
Definition BLI_span.hh:418
const T * const_pointer
Definition BLI_span.hh:78
constexpr Span slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:154
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr Span(Span< U > span)
Definition BLI_span.hh:129
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:268
constexpr std::reverse_iterator< const T * > rend() const
Definition BLI_span.hh:233
constexpr std::reverse_iterator< const T * > rbegin() const
Definition BLI_span.hh:229
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr Span take_back(int64_t n) const
Definition BLI_span.hh:204
constexpr int64_t first_index_try(const T &search_value) const
Definition BLI_span.hh:387
friend bool operator==(const Span< T > a, const Span< T > b)
Definition BLI_span.hh:425
constexpr Span slice(IndexRange range) const
Definition BLI_span.hh:145
const T * iterator
Definition BLI_span.hh:81
constexpr Span()=default
constexpr const T & operator[](int64_t index) const
Definition BLI_span.hh:242
constexpr Span(const std::vector< T > &vector)
Definition BLI_span.hh:120
constexpr Span(const T *start, int64_t size)
Definition BLI_span.hh:94
constexpr Span drop_back(int64_t n) const
Definition BLI_span.hh:182
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:300
constexpr const T & first() const
Definition BLI_span.hh:315
constexpr bool has_duplicates__linear_search() const
Definition BLI_span.hh:336
int64_t size_
Definition BLI_span.hh:86
constexpr int64_t first_index(const T &search_value) const
Definition BLI_span.hh:377
constexpr Span(const U *start, int64_t size)
Definition BLI_span.hh:100
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:325
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr Span(const std::array< T, N > &array)
Definition BLI_span.hh:122
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr const T * begin() const
Definition BLI_span.hh:220
constexpr Span(const std::initializer_list< T > &list)
Definition BLI_span.hh:116
constexpr uint64_t hash() const
Definition BLI_span.hh:406
constexpr Span slice_safe(IndexRange range) const
Definition BLI_span.hh:162
const T & const_reference
Definition BLI_span.hh:80
int64_t size_type
Definition BLI_span.hh:82
constexpr Span take_front(int64_t n) const
Definition BLI_span.hh:193
constexpr bool is_empty() const
Definition BLI_span.hh:260
constexpr bool contains(const T &value) const
Definition BLI_span.hh:277
constexpr bool contains_ptr(const T *ptr) const
Definition BLI_span.hh:291
constexpr bool intersects__linear_search(Span other) const
Definition BLI_span.hh:358
static ushort indices[]
#define N
#define T
void initialized_fill_n(T *dst, int64_t n, const T &value)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
void initialized_copy_n(const T *src, int64_t n, T *dst)
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238