Blender  V2.93
BLI_span.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
71 #include <algorithm>
72 #include <array>
73 #include <iostream>
74 #include <string>
75 #include <vector>
76 
77 #include "BLI_index_range.hh"
78 #include "BLI_memory_utils.hh"
79 #include "BLI_utildefines.h"
80 
81 namespace blender {
82 
87 template<typename T> class Span {
88  public:
89  using value_type = T;
90  using pointer = T *;
91  using const_pointer = const T *;
92  using reference = T &;
93  using const_reference = const T &;
94  using iterator = const T *;
95  using size_type = int64_t;
96 
97  private:
98  const T *data_ = nullptr;
99  int64_t size_ = 0;
100 
101  public:
105  constexpr Span() = default;
106 
107  constexpr Span(const T *start, int64_t size) : data_(start), size_(size)
108  {
109  BLI_assert(size >= 0);
110  }
111 
112  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
113  constexpr Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
114  {
115  BLI_assert(size >= 0);
116  }
117 
129  constexpr Span(const std::initializer_list<T> &list)
130  : Span(list.begin(), static_cast<int64_t>(list.size()))
131  {
132  }
133 
134  constexpr Span(const std::vector<T> &vector)
135  : Span(vector.data(), static_cast<int64_t>(vector.size()))
136  {
137  }
138 
139  template<std::size_t N> constexpr Span(const std::array<T, N> &array) : Span(array.data(), N)
140  {
141  }
142 
147  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
148  constexpr Span(Span<U> span) : data_(static_cast<const T *>(span.data())), size_(span.size())
149  {
150  }
151 
156  constexpr Span slice(int64_t start, int64_t size) const
157  {
158  BLI_assert(start >= 0);
159  BLI_assert(size >= 0);
160  const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
161  return Span(data_ + start, new_size);
162  }
163 
164  constexpr Span slice(IndexRange range) const
165  {
166  return this->slice(range.start(), range.size());
167  }
168 
173  constexpr Span drop_front(int64_t n) const
174  {
175  BLI_assert(n >= 0);
176  const int64_t new_size = std::max<int64_t>(0, size_ - n);
177  return Span(data_ + n, new_size);
178  }
179 
184  constexpr Span drop_back(int64_t n) const
185  {
186  BLI_assert(n >= 0);
187  const int64_t new_size = std::max<int64_t>(0, size_ - n);
188  return Span(data_, new_size);
189  }
190 
195  constexpr Span take_front(int64_t n) const
196  {
197  BLI_assert(n >= 0);
198  const int64_t new_size = std::min<int64_t>(size_, n);
199  return Span(data_, new_size);
200  }
201 
206  constexpr Span take_back(int64_t n) const
207  {
208  BLI_assert(n >= 0);
209  const int64_t new_size = std::min<int64_t>(size_, n);
210  return Span(data_ + size_ - new_size, new_size);
211  }
212 
217  constexpr const T *data() const
218  {
219  return data_;
220  }
221 
222  constexpr const T *begin() const
223  {
224  return data_;
225  }
226  constexpr const T *end() const
227  {
228  return data_ + size_;
229  }
230 
231  constexpr std::reverse_iterator<const T *> rbegin() const
232  {
233  return std::reverse_iterator<const T *>(this->end());
234  }
235  constexpr std::reverse_iterator<const T *> rend() const
236  {
237  return std::reverse_iterator<const T *>(this->begin());
238  }
239 
244  constexpr const T &operator[](int64_t index) const
245  {
246  BLI_assert(index >= 0);
247  BLI_assert(index < size_);
248  return data_[index];
249  }
250 
254  constexpr int64_t size() const
255  {
256  return size_;
257  }
258 
262  constexpr bool is_empty() const
263  {
264  return size_ == 0;
265  }
266 
270  constexpr int64_t size_in_bytes() const
271  {
272  return sizeof(T) * size_;
273  }
274 
279  constexpr bool contains(const T &value) const
280  {
281  for (const T &element : *this) {
282  if (element == value) {
283  return true;
284  }
285  }
286  return false;
287  }
288 
293  constexpr bool contains_ptr(const T *ptr) const
294  {
295  return (this->begin() <= ptr) && (ptr < this->end());
296  }
297 
302  constexpr int64_t count(const T &value) const
303  {
304  int64_t counter = 0;
305  for (const T &element : *this) {
306  if (element == value) {
307  counter++;
308  }
309  }
310  return counter;
311  }
312 
317  constexpr const T &first() const
318  {
319  BLI_assert(size_ > 0);
320  return data_[0];
321  }
322 
327  constexpr const T &last() const
328  {
329  BLI_assert(size_ > 0);
330  return data_[size_ - 1];
331  }
332 
337  constexpr T get(int64_t index, const T &fallback) const
338  {
339  if (index < size_ && index >= 0) {
340  return data_[index];
341  }
342  return fallback;
343  }
344 
349  constexpr bool has_duplicates__linear_search() const
350  {
351  /* The size should really be smaller than that. If it is not, the calling code should be
352  * changed. */
353  BLI_assert(size_ < 1000);
354 
355  for (int64_t i = 0; i < size_; i++) {
356  const T &value = data_[i];
357  for (int64_t j = i + 1; j < size_; j++) {
358  if (value == data_[j]) {
359  return true;
360  }
361  }
362  }
363  return false;
364  }
365 
371  constexpr bool intersects__linear_search(Span other) const
372  {
373  /* The size should really be smaller than that. If it is not, the calling code should be
374  * changed. */
375  BLI_assert(size_ < 1000);
376 
377  for (int64_t i = 0; i < size_; i++) {
378  const T &value = data_[i];
379  if (other.contains(value)) {
380  return true;
381  }
382  }
383  return false;
384  }
385 
390  constexpr int64_t first_index(const T &search_value) const
391  {
392  const int64_t index = this->first_index_try(search_value);
393  BLI_assert(index >= 0);
394  return index;
395  }
396 
400  constexpr int64_t first_index_try(const T &search_value) const
401  {
402  for (int64_t i = 0; i < size_; i++) {
403  if (data_[i] == search_value) {
404  return i;
405  }
406  }
407  return -1;
408  }
409 
414  constexpr IndexRange index_range() const
415  {
416  return IndexRange(size_);
417  }
418 
422  template<typename NewT> Span<NewT> constexpr cast() const
423  {
424  BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
425  int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
426  return Span<NewT>(reinterpret_cast<const NewT *>(data_), new_size);
427  }
428 
429  friend bool operator==(const Span<T> a, const Span<T> b)
430  {
431  if (a.size() != b.size()) {
432  return false;
433  }
434  return std::equal(a.begin(), a.end(), b.begin());
435  }
436 
437  friend bool operator!=(const Span<T> a, const Span<T> b)
438  {
439  return !(a == b);
440  }
441 
446  template<typename PrintLineF> void print_as_lines(std::string name, PrintLineF print_line) const
447  {
448  std::cout << "Span: " << name << " \tSize:" << size_ << '\n';
449  for (const T &value : *this) {
450  std::cout << " ";
451  print_line(value);
452  std::cout << '\n';
453  }
454  }
455 
460  void print_as_lines(std::string name) const
461  {
462  this->print_as_lines(name, [](const T &value) { std::cout << value; });
463  }
464 };
465 
470 template<typename T> class MutableSpan {
471  public:
472  using value_type = T;
473  using pointer = T *;
474  using const_pointer = const T *;
475  using reference = T &;
476  using const_reference = const T &;
477  using iterator = T *;
479 
480  private:
481  T *data_;
482  int64_t size_;
483 
484  public:
485  constexpr MutableSpan() = default;
486 
487  constexpr MutableSpan(T *start, const int64_t size) : data_(start), size_(size)
488  {
489  }
490 
491  constexpr MutableSpan(std::vector<T> &vector) : MutableSpan(vector.data(), vector.size())
492  {
493  }
494 
495  template<std::size_t N>
496  constexpr MutableSpan(std::array<T, N> &array) : MutableSpan(array.data(), N)
497  {
498  }
499 
504  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
505  constexpr MutableSpan(MutableSpan<U> span)
506  : data_(static_cast<T *>(span.data())), size_(span.size())
507  {
508  }
509 
510  constexpr operator Span<T>() const
511  {
512  return Span<T>(data_, size_);
513  }
514 
515  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
516  constexpr operator Span<U>() const
517  {
518  return Span<U>(static_cast<const U *>(data_), size_);
519  }
520 
524  constexpr int64_t size() const
525  {
526  return size_;
527  }
528 
532  constexpr bool is_empty() const
533  {
534  return size_ == 0;
535  }
536 
540  constexpr void fill(const T &value)
541  {
542  initialized_fill_n(data_, size_, value);
543  }
544 
549  constexpr void fill_indices(Span<int64_t> indices, const T &value)
550  {
551  for (int64_t i : indices) {
552  BLI_assert(i < size_);
553  data_[i] = value;
554  }
555  }
556 
561  constexpr T *data() const
562  {
563  return data_;
564  }
565 
566  constexpr T *begin() const
567  {
568  return data_;
569  }
570  constexpr T *end() const
571  {
572  return data_ + size_;
573  }
574 
575  constexpr std::reverse_iterator<T *> rbegin() const
576  {
577  return std::reverse_iterator<T *>(this->end());
578  }
579  constexpr std::reverse_iterator<T *> rend() const
580  {
581  return std::reverse_iterator<T *>(this->begin());
582  }
583 
584  constexpr T &operator[](const int64_t index) const
585  {
586  BLI_assert(index < this->size());
587  return data_[index];
588  }
589 
594  constexpr MutableSpan slice(const int64_t start, const int64_t size) const
595  {
596  BLI_assert(start >= 0);
597  BLI_assert(size >= 0);
598  const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
599  return MutableSpan(data_ + start, new_size);
600  }
601 
606  constexpr MutableSpan drop_front(const int64_t n) const
607  {
608  BLI_assert(n >= 0);
609  const int64_t new_size = std::max<int64_t>(0, size_ - n);
610  return MutableSpan(data_ + n, new_size);
611  }
612 
617  constexpr MutableSpan drop_back(const int64_t n) const
618  {
619  BLI_assert(n >= 0);
620  const int64_t new_size = std::max<int64_t>(0, size_ - n);
621  return MutableSpan(data_, new_size);
622  }
623 
628  constexpr MutableSpan take_front(const int64_t n) const
629  {
630  BLI_assert(n >= 0);
631  const int64_t new_size = std::min<int64_t>(size_, n);
632  return MutableSpan(data_, new_size);
633  }
634 
639  constexpr MutableSpan take_back(const int64_t n) const
640  {
641  BLI_assert(n >= 0);
642  const int64_t new_size = std::min<int64_t>(size_, n);
643  return MutableSpan(data_ + size_ - new_size, new_size);
644  }
645 
650  constexpr Span<T> as_span() const
651  {
652  return Span<T>(data_, size_);
653  }
654 
659  constexpr IndexRange index_range() const
660  {
661  return IndexRange(size_);
662  }
663 
668  constexpr T &last() const
669  {
670  BLI_assert(size_ > 0);
671  return data_[size_ - 1];
672  }
673 
678  constexpr int64_t count(const T &value) const
679  {
680  int64_t counter = 0;
681  for (const T &element : *this) {
682  if (element == value) {
683  counter++;
684  }
685  }
686  return counter;
687  }
688 
694  constexpr void copy_from(Span<T> values)
695  {
696  BLI_assert(size_ == values.size());
697  initialized_copy_n(values.data(), size_, data_);
698  }
699 
704  template<typename NewT> constexpr MutableSpan<NewT> cast() const
705  {
706  BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
707  int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
708  return MutableSpan<NewT>((NewT *)data_, new_size);
709  }
710 };
711 
715 template<typename T1, typename T2> constexpr void assert_same_size(const T1 &v1, const T2 &v2)
716 {
718 #ifdef DEBUG
719  int64_t size = v1.size();
720  BLI_assert(size == v1.size());
721  BLI_assert(size == v2.size());
722 #endif
723 }
724 
725 template<typename T1, typename T2, typename T3>
726 constexpr void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3)
727 {
728  UNUSED_VARS_NDEBUG(v1, v2, v3);
729 #ifdef DEBUG
730  int64_t size = v1.size();
731  BLI_assert(size == v1.size());
732  BLI_assert(size == v2.size());
733  BLI_assert(size == v3.size());
734 #endif
735 }
736 
737 } /* namespace blender */
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED_VARS_NDEBUG(...)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
constexpr int64_t size() const
constexpr int64_t start() const
constexpr MutableSpan()=default
constexpr int64_t size() const
Definition: BLI_span.hh:524
constexpr T * end() const
Definition: BLI_span.hh:570
constexpr T & operator[](const int64_t index) const
Definition: BLI_span.hh:584
constexpr void fill(const T &value)
Definition: BLI_span.hh:540
const T & const_reference
Definition: BLI_span.hh:476
constexpr MutableSpan< NewT > cast() const
Definition: BLI_span.hh:704
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition: BLI_span.hh:594
constexpr bool is_empty() const
Definition: BLI_span.hh:532
constexpr MutableSpan take_back(const int64_t n) const
Definition: BLI_span.hh:639
constexpr MutableSpan drop_back(const int64_t n) const
Definition: BLI_span.hh:617
constexpr MutableSpan drop_front(const int64_t n) const
Definition: BLI_span.hh:606
constexpr void fill_indices(Span< int64_t > indices, const T &value)
Definition: BLI_span.hh:549
constexpr MutableSpan(std::array< T, N > &array)
Definition: BLI_span.hh:496
constexpr void copy_from(Span< T > values)
Definition: BLI_span.hh:694
constexpr std::reverse_iterator< T * > rend() const
Definition: BLI_span.hh:579
constexpr std::reverse_iterator< T * > rbegin() const
Definition: BLI_span.hh:575
constexpr int64_t count(const T &value) const
Definition: BLI_span.hh:678
constexpr Span< T > as_span() const
Definition: BLI_span.hh:650
const T * const_pointer
Definition: BLI_span.hh:474
constexpr MutableSpan(std::vector< T > &vector)
Definition: BLI_span.hh:491
constexpr T * begin() const
Definition: BLI_span.hh:566
constexpr IndexRange index_range() const
Definition: BLI_span.hh:659
constexpr T * data() const
Definition: BLI_span.hh:561
constexpr MutableSpan(T *start, const int64_t size)
Definition: BLI_span.hh:487
constexpr MutableSpan(MutableSpan< U > span)
Definition: BLI_span.hh:505
constexpr T & last() const
Definition: BLI_span.hh:668
constexpr MutableSpan take_front(const int64_t n) const
Definition: BLI_span.hh:628
friend bool operator!=(const Span< T > a, const Span< T > b)
Definition: BLI_span.hh:437
constexpr std::reverse_iterator< const T * > rend() const
Definition: BLI_span.hh:235
constexpr Span drop_front(int64_t n) const
Definition: BLI_span.hh:173
const T * const_pointer
Definition: BLI_span.hh:91
constexpr std::reverse_iterator< const T * > rbegin() const
Definition: BLI_span.hh:231
constexpr Span slice(int64_t start, int64_t size) const
Definition: BLI_span.hh:156
constexpr Span(Span< U > span)
Definition: BLI_span.hh:148
constexpr int64_t size_in_bytes() const
Definition: BLI_span.hh:270
constexpr const T & operator[](int64_t index) const
Definition: BLI_span.hh:244
void print_as_lines(std::string name) const
Definition: BLI_span.hh:460
constexpr Span take_back(int64_t n) const
Definition: BLI_span.hh:206
constexpr int64_t first_index_try(const T &search_value) const
Definition: BLI_span.hh:400
friend bool operator==(const Span< T > a, const Span< T > b)
Definition: BLI_span.hh:429
void print_as_lines(std::string name, PrintLineF print_line) const
Definition: BLI_span.hh:446
constexpr Span slice(IndexRange range) const
Definition: BLI_span.hh:164
const T * iterator
Definition: BLI_span.hh:94
constexpr const T * data() const
Definition: BLI_span.hh:217
constexpr Span()=default
constexpr const T & last() const
Definition: BLI_span.hh:327
constexpr Span(const std::vector< T > &vector)
Definition: BLI_span.hh:134
constexpr Span(const T *start, int64_t size)
Definition: BLI_span.hh:107
constexpr Span drop_back(int64_t n) const
Definition: BLI_span.hh:184
constexpr T get(int64_t index, const T &fallback) const
Definition: BLI_span.hh:337
constexpr int64_t count(const T &value) const
Definition: BLI_span.hh:302
constexpr bool has_duplicates__linear_search() const
Definition: BLI_span.hh:349
constexpr const T & first() const
Definition: BLI_span.hh:317
constexpr int64_t first_index(const T &search_value) const
Definition: BLI_span.hh:390
constexpr Span(const U *start, int64_t size)
Definition: BLI_span.hh:113
constexpr int64_t size() const
Definition: BLI_span.hh:254
constexpr Span< NewT > cast() const
Definition: BLI_span.hh:422
constexpr Span(const std::array< T, N > &array)
Definition: BLI_span.hh:139
constexpr IndexRange index_range() const
Definition: BLI_span.hh:414
constexpr Span(const std::initializer_list< T > &list)
Definition: BLI_span.hh:129
constexpr const T * end() const
Definition: BLI_span.hh:226
const T & const_reference
Definition: BLI_span.hh:93
int64_t size_type
Definition: BLI_span.hh:95
constexpr Span take_front(int64_t n) const
Definition: BLI_span.hh:195
constexpr const T * begin() const
Definition: BLI_span.hh:222
constexpr bool is_empty() const
Definition: BLI_span.hh:262
constexpr bool contains(const T &value) const
Definition: BLI_span.hh:279
constexpr bool contains_ptr(const T *ptr) const
Definition: BLI_span.hh:293
constexpr bool intersects__linear_search(Span other) const
Definition: BLI_span.hh:371
T * data_
static ushort indices[]
#define T
static unsigned a[3]
Definition: RandGen.cpp:92
constexpr void assert_same_size(const T1 &v1, const T2 &v2)
Definition: BLI_span.hh:715
void initialized_fill_n(T *dst, int64_t n, const T &value)
void initialized_copy_n(const T *src, int64_t n, T *dst)
params N
#define min(a, b)
Definition: sort.c:51
__int64 int64_t
Definition: stdint.h:92
#define T2
Definition: util_md5.cpp:36
#define T3
Definition: util_md5.cpp:37
#define T1
Definition: util_md5.cpp:35
PointerRNA * ptr
Definition: wm_files.c:3157