Blender  V3.3
BLI_generic_array.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
16 #include "BLI_allocator.hh"
17 #include "BLI_cpp_type.hh"
18 #include "BLI_generic_span.hh"
19 
20 namespace blender {
21 
22 template<
27  typename Allocator = GuardedAllocator>
28 class GArray {
29  protected:
32  const CPPType *type_ = nullptr;
33  void *data_ = nullptr;
35 
37 
38  public:
44  GArray(Allocator allocator = {}) noexcept : allocator_(allocator)
45  {
46  }
47 
48  GArray(NoExceptConstructor, Allocator allocator = {}) noexcept : GArray(allocator)
49  {
50  }
51 
56  GArray(const CPPType &type, int64_t size, Allocator allocator = {}) : GArray(type, allocator)
57  {
58  BLI_assert(size >= 0);
59  size_ = size;
60  data_ = this->allocate(size_);
62  }
63 
67  GArray(const CPPType &type, Allocator allocator = {}) : GArray(allocator)
68  {
69  type_ = &type;
70  }
71 
76  GArray(const CPPType &type, void *buffer, int64_t size, Allocator allocator = {})
78  {
79  BLI_assert(size >= 0);
80  BLI_assert(buffer != nullptr || size == 0);
82 
83  data_ = buffer;
84  size_ = size;
85  }
86 
90  GArray(const GSpan span, Allocator allocator = {}) : GArray(span.type(), span.size(), allocator)
91  {
92  if (span.data() != nullptr) {
93  BLI_assert(span.size() != 0);
94  /* Use copy assign rather than construct since the memory is already initialized. */
95  type_->copy_assign_n(span.data(), data_, size_);
96  }
97  }
98 
102  GArray(const GArray &other) : GArray(other.as_span(), other.allocator())
103  {
104  }
105 
109  GArray(GArray &&other) : GArray(other.type(), other.data(), other.size(), other.allocator())
110  {
111  other.data_ = nullptr;
112  other.size_ = 0;
113  }
114 
116  {
117  if (data_ != nullptr) {
119  this->deallocate(data_);
120  }
121  }
122 
123  GArray &operator=(const GArray &other)
124  {
125  return copy_assign_container(*this, other);
126  }
127 
129  {
130  return move_assign_container(*this, std::move(other));
131  }
132 
133  const CPPType &type() const
134  {
135  BLI_assert(type_ != nullptr);
136  return *type_;
137  }
138 
139  bool is_empty() const
140  {
141  return size_ == 0;
142  }
143 
147  int64_t size() const
148  {
149  return size_;
150  }
151 
155  const void *data() const
156  {
157  return data_;
158  }
159  void *data()
160  {
161  return data_;
162  }
163 
164  const void *operator[](int64_t index) const
165  {
166  BLI_assert(index < size_);
167  return POINTER_OFFSET(data_, type_->size() * index);
168  }
169 
170  void *operator[](int64_t index)
171  {
172  BLI_assert(index < size_);
173  return POINTER_OFFSET(data_, type_->size() * index);
174  }
175 
176  operator GSpan() const
177  {
178  BLI_assert(type_ != nullptr);
179  return GSpan(*type_, data_, size_);
180  }
181 
182  operator GMutableSpan()
183  {
184  BLI_assert(type_ != nullptr);
185  return GMutableSpan(*type_, data_, size_);
186  }
187 
188  GSpan as_span() const
189  {
190  return *this;
191  }
192 
194  {
195  return *this;
196  }
197 
201  Allocator &allocator()
202  {
203  return allocator_;
204  }
205  const Allocator &allocator() const
206  {
207  return allocator_;
208  }
209 
214  void reinitialize(const int64_t new_size)
215  {
216  BLI_assert(new_size >= 0);
217  int64_t old_size = size_;
218 
220  size_ = 0;
221 
222  if (new_size <= old_size) {
223  type_->default_construct_n(data_, new_size);
224  }
225  else {
226  void *new_data = this->allocate(new_size);
227  try {
228  type_->default_construct_n(new_data, new_size);
229  }
230  catch (...) {
231  this->deallocate(new_data);
232  throw;
233  }
234  this->deallocate(data_);
235  data_ = new_data;
236  }
237 
238  size_ = new_size;
239  }
240 
241  private:
242  void *allocate(int64_t size)
243  {
244  const int64_t item_size = type_->size();
245  const int64_t alignment = type_->alignment();
246  return allocator_.allocate(static_cast<size_t>(size) * item_size, alignment, AT);
247  }
248 
249  void deallocate(void *ptr)
250  {
251  allocator_.deallocate(ptr);
252  }
253 };
254 
255 } // namespace blender
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define POINTER_OFFSET(v, ofs)
#define AT
#define BLI_NO_UNIQUE_ADDRESS
void default_construct_n(void *ptr, int64_t n) const
void destruct_n(void *ptr, int64_t n) const
void copy_assign_n(const void *src, void *dst, int64_t n) const
bool pointer_has_valid_alignment(const void *ptr) const
int64_t size() const
int64_t alignment() const
bool is_empty() const
GMutableSpan as_mutable_span()
GArray & operator=(const GArray &other)
GArray & operator=(GArray &&other)
BLI_NO_UNIQUE_ADDRESS Allocator allocator_
Allocator & allocator()
int64_t size() const
GArray(NoExceptConstructor, Allocator allocator={}) noexcept
void reinitialize(const int64_t new_size)
GArray(const GArray &other)
GArray(Allocator allocator={}) noexcept
GSpan as_span() const
GArray(GArray &&other)
GArray(const CPPType &type, int64_t size, Allocator allocator={})
GArray(const GSpan span, Allocator allocator={})
GArray(const CPPType &type, void *buffer, int64_t size, Allocator allocator={})
const Allocator & allocator() const
const void * data() const
const CPPType * type_
void * operator[](int64_t index)
const void * operator[](int64_t index) const
const CPPType & type() const
GArray(const CPPType &type, Allocator allocator={})
const void * data() const
const CPPType & type() const
int64_t size() const
ccl_global float * buffer
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
Container & copy_assign_container(Container &dst, const Container &src)
__int64 int64_t
Definition: stdint.h:89
PointerRNA * ptr
Definition: wm_files.c:3480