Blender V4.3
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
59#include <algorithm>
60#include <array>
61#include <vector>
62
63#include "BLI_index_range.hh"
64#include "BLI_memory_utils.hh"
65#include "BLI_utildefines.h"
66
67namespace blender {
68
69template<typename T> uint64_t get_default_hash(const T &v);
70
75template<typename T> class Span {
76 public:
77 using value_type = T;
78 using pointer = T *;
79 using const_pointer = const T *;
80 using reference = T &;
81 using const_reference = const T &;
82 using iterator = const T *;
84
85 protected:
86 const T *data_ = nullptr;
88
89 public:
93 constexpr Span() = default;
94
95 constexpr Span(const T *start, int64_t size) : data_(start), size_(size)
96 {
97 BLI_assert(size >= 0);
98 }
99
100 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
101 constexpr Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
102 {
103 BLI_assert(size >= 0);
104 }
105
117 constexpr Span(const std::initializer_list<T> &list) : Span(list.begin(), int64_t(list.size()))
118 {
119 }
120
121 constexpr Span(const std::vector<T> &vector) : Span(vector.data(), int64_t(vector.size())) {}
122
123 template<std::size_t N> constexpr Span(const std::array<T, N> &array) : Span(array.data(), N) {}
124
129 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
130 constexpr Span(Span<U> span) : data_(static_cast<const T *>(span.data())), size_(span.size())
131 {
132 }
133
138 constexpr Span slice(int64_t start, int64_t size) const
139 {
140 BLI_assert(start >= 0);
141 BLI_assert(size >= 0);
142 BLI_assert(start + size <= size_ || size == 0);
143 return Span(data_ + start, size);
144 }
145
146 constexpr Span slice(IndexRange range) const
147 {
148 return this->slice(range.start(), range.size());
149 }
150
155 constexpr Span slice_safe(const int64_t start, const int64_t size) const
156 {
157 BLI_assert(start >= 0);
158 BLI_assert(size >= 0);
159 const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
160 return Span(data_ + start, new_size);
161 }
162
163 constexpr Span slice_safe(IndexRange range) const
164 {
165 return this->slice_safe(range.start(), range.size());
166 }
167
172 constexpr Span drop_front(int64_t n) const
173 {
174 BLI_assert(n >= 0);
175 const int64_t new_size = std::max<int64_t>(0, size_ - n);
176 return Span(data_ + n, new_size);
177 }
178
183 constexpr Span drop_back(int64_t n) const
184 {
185 BLI_assert(n >= 0);
186 const int64_t new_size = std::max<int64_t>(0, size_ - n);
187 return Span(data_, new_size);
188 }
189
194 constexpr Span take_front(int64_t n) const
195 {
196 BLI_assert(n >= 0);
197 const int64_t new_size = std::min<int64_t>(size_, n);
198 return Span(data_, new_size);
199 }
200
205 constexpr Span take_back(int64_t n) const
206 {
207 BLI_assert(n >= 0);
208 const int64_t new_size = std::min<int64_t>(size_, n);
209 return Span(data_ + size_ - new_size, new_size);
210 }
211
216 constexpr const T *data() const
217 {
218 return data_;
219 }
220
221 constexpr const T *begin() const
222 {
223 return data_;
224 }
225 constexpr const T *end() const
226 {
227 return data_ + size_;
228 }
229
230 constexpr std::reverse_iterator<const T *> rbegin() const
231 {
232 return std::reverse_iterator<const T *>(this->end());
233 }
234 constexpr std::reverse_iterator<const T *> rend() const
235 {
236 return std::reverse_iterator<const T *>(this->begin());
237 }
238
243 constexpr const T &operator[](int64_t index) const
244 {
245 BLI_assert(index >= 0);
246 BLI_assert(index < size_);
247 return data_[index];
248 }
249
253 constexpr int64_t size() const
254 {
255 return size_;
256 }
257
261 constexpr bool is_empty() const
262 {
263 return size_ == 0;
264 }
265
269 constexpr int64_t size_in_bytes() const
270 {
271 return sizeof(T) * size_;
272 }
273
278 constexpr bool contains(const T &value) const
279 {
280 for (const T &element : *this) {
281 if (element == value) {
282 return true;
283 }
284 }
285 return false;
286 }
287
292 constexpr bool contains_ptr(const T *ptr) const
293 {
294 return (this->begin() <= ptr) && (ptr < this->end());
295 }
296
301 constexpr int64_t count(const T &value) const
302 {
303 int64_t counter = 0;
304 for (const T &element : *this) {
305 if (element == value) {
306 counter++;
307 }
308 }
309 return counter;
310 }
311
316 constexpr const T &first() const
317 {
318 BLI_assert(size_ > 0);
319 return data_[0];
320 }
321
326 constexpr const T &last(const int64_t n = 0) const
327 {
328 BLI_assert(n >= 0);
329 BLI_assert(n < size_);
330 return data_[size_ - 1 - n];
331 }
332
337 constexpr bool has_duplicates__linear_search() const
338 {
339 /* The size should really be smaller than that. If it is not, the calling code should be
340 * changed. */
341 BLI_assert(size_ < 1000);
342
343 for (int64_t i = 0; i < size_; i++) {
344 const T &value = data_[i];
345 for (int64_t j = i + 1; j < size_; j++) {
346 if (value == data_[j]) {
347 return true;
348 }
349 }
350 }
351 return false;
352 }
353
359 constexpr bool intersects__linear_search(Span other) const
360 {
361 /* The size should really be smaller than that. If it is not, the calling code should be
362 * changed. */
363 BLI_assert(size_ < 1000);
364
365 for (int64_t i = 0; i < size_; i++) {
366 const T &value = data_[i];
367 if (other.contains(value)) {
368 return true;
369 }
370 }
371 return false;
372 }
373
378 constexpr int64_t first_index(const T &search_value) const
379 {
380 const int64_t index = this->first_index_try(search_value);
381 BLI_assert(index >= 0);
382 return index;
383 }
384
388 constexpr int64_t first_index_try(const T &search_value) const
389 {
390 for (int64_t i = 0; i < size_; i++) {
391 if (data_[i] == search_value) {
392 return i;
393 }
394 }
395 return -1;
396 }
397
402 constexpr IndexRange index_range() const
403 {
404 return IndexRange(size_);
405 }
406
407 constexpr uint64_t hash() const
408 {
409 uint64_t hash = 0;
410 for (const T &value : *this) {
411 hash = hash * 33 ^ get_default_hash(value);
412 }
413 return hash;
414 }
415
419 template<typename NewT> Span<NewT> constexpr cast() const
420 {
421 BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
422 int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
423 return Span<NewT>(reinterpret_cast<const NewT *>(data_), new_size);
424 }
425
426 friend bool operator==(const Span<T> a, const Span<T> b)
427 {
428 if (a.size() != b.size()) {
429 return false;
430 }
431 return std::equal(a.begin(), a.end(), b.begin());
432 }
433
434 friend bool operator!=(const Span<T> a, const Span<T> b)
435 {
436 return !(a == b);
437 }
438};
439
444template<typename T> class MutableSpan {
445 public:
446 using value_type = T;
447 using pointer = T *;
448 using const_pointer = const T *;
449 using reference = T &;
450 using const_reference = const T &;
451 using iterator = T *;
453
454 protected:
455 T *data_ = nullptr;
457
458 public:
459 constexpr MutableSpan() = default;
460
461 constexpr MutableSpan(T *start, const int64_t size) : data_(start), size_(size) {}
462
463 constexpr MutableSpan(std::vector<T> &vector) : MutableSpan(vector.data(), vector.size()) {}
464
465 template<std::size_t N>
466 constexpr MutableSpan(std::array<T, N> &array) : MutableSpan(array.data(), N)
467 {
468 }
469
474 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
476 : data_(static_cast<T *>(span.data())), size_(span.size())
477 {
478 }
479
480 constexpr operator Span<T>() const
481 {
482 return Span<T>(data_, size_);
483 }
484
485 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
486 constexpr operator Span<U>() const
487 {
488 return Span<U>(static_cast<const U *>(data_), size_);
489 }
490
494 constexpr int64_t size() const
495 {
496 return size_;
497 }
498
502 constexpr int64_t size_in_bytes() const
503 {
504 return sizeof(T) * size_;
505 }
506
510 constexpr bool is_empty() const
511 {
512 return size_ == 0;
513 }
514
518 constexpr void fill(const T &value) const
519 {
521 }
522
527 template<typename IndexT> constexpr void fill_indices(Span<IndexT> indices, const T &value) const
528 {
529 static_assert(std::is_integral_v<IndexT>);
530 for (IndexT i : indices) {
531 BLI_assert(i < size_);
532 data_[i] = value;
533 }
534 }
535
540 constexpr T *data() const
541 {
542 return data_;
543 }
544
545 constexpr T *begin() const
546 {
547 return data_;
548 }
549 constexpr T *end() const
550 {
551 return data_ + size_;
552 }
553
554 constexpr std::reverse_iterator<T *> rbegin() const
555 {
556 return std::reverse_iterator<T *>(this->end());
557 }
558 constexpr std::reverse_iterator<T *> rend() const
559 {
560 return std::reverse_iterator<T *>(this->begin());
561 }
562
563 constexpr T &operator[](const int64_t index) const
564 {
565 BLI_assert(index >= 0);
566 BLI_assert(index < size_);
567 return data_[index];
568 }
569
574 constexpr MutableSpan slice(const int64_t start, const int64_t size) const
575 {
576 BLI_assert(start >= 0);
577 BLI_assert(size >= 0);
578 BLI_assert(start + size <= size_ || size == 0);
579 return MutableSpan(data_ + start, size);
580 }
581
582 constexpr MutableSpan slice(IndexRange range) const
583 {
584 return this->slice(range.start(), range.size());
585 }
586
591 constexpr MutableSpan slice_safe(const int64_t start, const int64_t size) const
592 {
593 BLI_assert(start >= 0);
594 BLI_assert(size >= 0);
595 const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
596 return MutableSpan(data_ + start, new_size);
597 }
598
599 constexpr MutableSpan slice_safe(IndexRange range) const
600 {
601 return this->slice_safe(range.start(), range.size());
602 }
603
608 constexpr MutableSpan drop_front(const int64_t n) const
609 {
610 BLI_assert(n >= 0);
611 const int64_t new_size = std::max<int64_t>(0, size_ - n);
612 return MutableSpan(data_ + n, new_size);
613 }
614
619 constexpr MutableSpan drop_back(const int64_t n) const
620 {
621 BLI_assert(n >= 0);
622 const int64_t new_size = std::max<int64_t>(0, size_ - n);
623 return MutableSpan(data_, new_size);
624 }
625
630 constexpr MutableSpan take_front(const int64_t n) const
631 {
632 BLI_assert(n >= 0);
633 const int64_t new_size = std::min<int64_t>(size_, n);
634 return MutableSpan(data_, new_size);
635 }
636
641 constexpr MutableSpan take_back(const int64_t n) const
642 {
643 BLI_assert(n >= 0);
644 const int64_t new_size = std::min<int64_t>(size_, n);
645 return MutableSpan(data_ + size_ - new_size, new_size);
646 }
647
651 constexpr void reverse() const
652 {
653 for (const int i : IndexRange(size_ / 2)) {
654 std::swap(data_[size_ - 1 - i], data_[i]);
655 }
656 }
657
662 constexpr Span<T> as_span() const
663 {
664 return Span<T>(data_, size_);
665 }
666
671 constexpr IndexRange index_range() const
672 {
673 return IndexRange(size_);
674 }
675
680 constexpr T &first() const
681 {
682 BLI_assert(size_ > 0);
683 return data_[0];
684 }
685
690 constexpr T &last(const int64_t n = 0) const
691 {
692 BLI_assert(n >= 0);
693 BLI_assert(n < size_);
694 return data_[size_ - 1 - n];
695 }
696
701 constexpr int64_t count(const T &value) const
702 {
703 int64_t counter = 0;
704 for (const T &element : *this) {
705 if (element == value) {
706 counter++;
707 }
708 }
709 return counter;
710 }
711
716 constexpr bool contains_ptr(const T *ptr) const
717 {
718 return (this->begin() <= ptr) && (ptr < this->end());
719 }
720
726 constexpr void copy_from(Span<T> values) const
727 {
728 BLI_assert(size_ == values.size());
729 initialized_copy_n(values.data(), size_, data_);
730 }
731
736 template<typename NewT> constexpr MutableSpan<NewT> cast() const
737 {
738 BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
739 int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
740 return MutableSpan<NewT>(reinterpret_cast<NewT *>(data_), new_size);
741 }
742};
743
744} /* namespace blender */
#define BLI_assert(a)
Definition BLI_assert.h:50
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition btGjkEpa3.h:78
constexpr int64_t start() const
constexpr MutableSpan()=default
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr bool contains_ptr(const T *ptr) const
Definition BLI_span.hh:716
constexpr MutableSpan slice(IndexRange range) const
Definition BLI_span.hh:582
const T & const_reference
Definition BLI_span.hh:450
constexpr T & operator[](const int64_t index) const
Definition BLI_span.hh:563
constexpr std::reverse_iterator< T * > rbegin() const
Definition BLI_span.hh:554
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr bool is_empty() const
Definition BLI_span.hh:510
constexpr MutableSpan< NewT > cast() const
Definition BLI_span.hh:736
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:641
constexpr T * data() const
Definition BLI_span.hh:540
constexpr MutableSpan drop_back(const int64_t n) const
Definition BLI_span.hh:619
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr MutableSpan slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:591
constexpr MutableSpan drop_front(const int64_t n) const
Definition BLI_span.hh:608
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:502
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
constexpr T * end() const
Definition BLI_span.hh:549
constexpr MutableSpan(std::array< T, N > &array)
Definition BLI_span.hh:466
constexpr void reverse() const
Definition BLI_span.hh:651
constexpr T & first() const
Definition BLI_span.hh:680
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:701
constexpr T * begin() const
Definition BLI_span.hh:545
const T * const_pointer
Definition BLI_span.hh:448
constexpr MutableSpan(std::vector< T > &vector)
Definition BLI_span.hh:463
constexpr MutableSpan slice_safe(IndexRange range) const
Definition BLI_span.hh:599
constexpr std::reverse_iterator< T * > rend() const
Definition BLI_span.hh:558
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
constexpr MutableSpan(T *start, const int64_t size)
Definition BLI_span.hh:461
constexpr void fill_indices(Span< IndexT > indices, const T &value) const
Definition BLI_span.hh:527
constexpr MutableSpan(MutableSpan< U > span)
Definition BLI_span.hh:475
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:630
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:690
const T * data_
Definition BLI_span.hh:86
friend bool operator!=(const Span< T > a, const Span< T > b)
Definition BLI_span.hh:434
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:172
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
const T * const_pointer
Definition BLI_span.hh:79
constexpr Span slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:155
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:138
constexpr Span(Span< U > span)
Definition BLI_span.hh:130
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:269
constexpr std::reverse_iterator< const T * > rend() const
Definition BLI_span.hh:234
constexpr std::reverse_iterator< const T * > rbegin() const
Definition BLI_span.hh:230
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr Span take_back(int64_t n) const
Definition BLI_span.hh:205
constexpr int64_t first_index_try(const T &search_value) const
Definition BLI_span.hh:388
friend bool operator==(const Span< T > a, const Span< T > b)
Definition BLI_span.hh:426
constexpr Span slice(IndexRange range) const
Definition BLI_span.hh:146
const T * iterator
Definition BLI_span.hh:82
constexpr Span()=default
constexpr const T & operator[](int64_t index) const
Definition BLI_span.hh:243
constexpr Span(const std::vector< T > &vector)
Definition BLI_span.hh:121
constexpr Span(const T *start, int64_t size)
Definition BLI_span.hh:95
constexpr Span drop_back(int64_t n) const
Definition BLI_span.hh:183
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:301
constexpr const T & first() const
Definition BLI_span.hh:316
constexpr bool has_duplicates__linear_search() const
Definition BLI_span.hh:337
int64_t size_
Definition BLI_span.hh:87
constexpr int64_t first_index(const T &search_value) const
Definition BLI_span.hh:378
constexpr Span(const U *start, int64_t size)
Definition BLI_span.hh:101
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:326
constexpr const T * end() const
Definition BLI_span.hh:225
constexpr Span(const std::array< T, N > &array)
Definition BLI_span.hh:123
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr const T * begin() const
Definition BLI_span.hh:221
constexpr Span(const std::initializer_list< T > &list)
Definition BLI_span.hh:117
constexpr uint64_t hash() const
Definition BLI_span.hh:407
constexpr Span slice_safe(IndexRange range) const
Definition BLI_span.hh:163
const T & const_reference
Definition BLI_span.hh:81
int64_t size_type
Definition BLI_span.hh:83
constexpr Span take_front(int64_t n) const
Definition BLI_span.hh:194
constexpr bool is_empty() const
Definition BLI_span.hh:261
constexpr bool contains(const T &value) const
Definition BLI_span.hh:278
constexpr bool contains_ptr(const T *ptr) const
Definition BLI_span.hh:292
constexpr bool intersects__linear_search(Span other) const
Definition BLI_span.hh:359
local_group_size(16, 16) .push_constant(Type b
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)
Definition BLI_hash.hh:219
void initialized_copy_n(const T *src, int64_t n, T *dst)
__int64 int64_t
Definition stdint.h:89
unsigned __int64 uint64_t
Definition stdint.h:90
PointerRNA * ptr
Definition wm_files.cc:4126