Blender V5.0
BLI_generic_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
10
11#include "BLI_cpp_type.hh"
12#include "BLI_span.hh"
13
14namespace blender {
15
19class GSpan {
20 protected:
21 const CPPType *type_ = nullptr;
22 const void *data_ = nullptr;
24
25 public:
26 GSpan() = default;
27
28 GSpan(const CPPType *type, const void *buffer, int64_t size)
29 : type_(type), data_(buffer), size_(size)
30 {
31 BLI_assert(size >= 0);
32 BLI_assert(buffer != nullptr || size == 0);
33 BLI_assert(size == 0 || type != nullptr);
34 BLI_assert(type == nullptr || type->pointer_has_valid_alignment(buffer));
35 }
36
37 GSpan(const CPPType &type, const void *buffer, int64_t size) : GSpan(&type, buffer, size) {}
38
39 GSpan(const CPPType &type) : type_(&type) {}
40
41 GSpan(const CPPType *type) : type_(type) {}
42
43 template<typename T>
45 : GSpan(CPPType::get<T>(), static_cast<const void *>(array.data()), array.size())
46 {
47 }
48
49 template<typename T>
51 : GSpan(CPPType::get<T>(), static_cast<const void *>(array.data()), array.size())
52 {
53 }
54
55 const CPPType &type() const
56 {
57 BLI_assert(type_ != nullptr);
58 return *type_;
59 }
60
61 const CPPType *type_ptr() const
62 {
63 return type_;
64 }
65
66 bool is_empty() const
67 {
68 return size_ == 0;
69 }
70
71 int64_t size() const
72 {
73 return size_;
74 }
75
77 {
78 return type_->size * size_;
79 }
80
81 const void *data() const
82 {
83 return data_;
84 }
85
86 const void *operator[](int64_t index) const
87 {
88 BLI_assert(index < size_);
89 return POINTER_OFFSET(data_, type_->size * index);
90 }
91
92 template<typename T> Span<T> typed() const
93 {
94 BLI_assert(size_ == 0 || type_ != nullptr);
95 BLI_assert(type_ == nullptr || type_->is<T>());
96 return Span<T>(static_cast<const T *>(data_), size_);
97 }
98
99 GSpan slice(const int64_t start, int64_t size) const
100 {
101 BLI_assert(start >= 0);
102 BLI_assert(size >= 0);
103 BLI_assert(start + size <= size_ || size == 0);
104 return GSpan(type_, POINTER_OFFSET(data_, type_->size * start), size);
105 }
106
107 GSpan slice(const IndexRange range) const
108 {
109 return this->slice(range.start(), range.size());
110 }
111
112 GSpan drop_front(const int64_t n) const
113 {
114 BLI_assert(n >= 0);
115 const int64_t new_size = std::max<int64_t>(0, size_ - n);
116 return GSpan(*type_, POINTER_OFFSET(data_, type_->size * n), new_size);
117 }
118
119 GSpan drop_back(const int64_t n) const
120 {
121 BLI_assert(n >= 0);
122 const int64_t new_size = std::max<int64_t>(0, size_ - n);
123 return GSpan(*type_, data_, new_size);
124 }
125
126 GSpan take_front(const int64_t n) const
127 {
128 BLI_assert(n >= 0);
129 const int64_t new_size = std::min<int64_t>(size_, n);
130 return GSpan(*type_, data_, new_size);
131 }
132
133 GSpan take_back(const int64_t n) const
134 {
135 BLI_assert(n >= 0);
136 const int64_t new_size = std::min<int64_t>(size_, n);
137 return GSpan(*type_, POINTER_OFFSET(data_, type_->size * (size_ - new_size)), new_size);
138 }
139};
140
146 protected:
147 const CPPType *type_ = nullptr;
148 void *data_ = nullptr;
150
151 public:
152 GMutableSpan() = default;
153
154 GMutableSpan(const CPPType *type, void *buffer, int64_t size)
155 : type_(type), data_(buffer), size_(size)
156 {
157 BLI_assert(size >= 0);
158 BLI_assert(buffer != nullptr || size == 0);
159 BLI_assert(size == 0 || type != nullptr);
160 BLI_assert(type == nullptr || type->pointer_has_valid_alignment(buffer));
161 }
162
163 GMutableSpan(const CPPType &type, void *buffer, int64_t size) : GMutableSpan(&type, buffer, size)
164 {
165 }
166
168
170
171 template<typename T>
173 : GMutableSpan(CPPType::get<T>(), static_cast<void *>(array.begin()), array.size())
174 {
175 }
176
177 operator GSpan() const
178 {
179 return GSpan(type_, data_, size_);
180 }
181
182 const CPPType &type() const
183 {
184 BLI_assert(type_ != nullptr);
185 return *type_;
186 }
187
188 const CPPType *type_ptr() const
189 {
190 return type_;
191 }
192
193 bool is_empty() const
194 {
195 return size_ == 0;
196 }
197
198 int64_t size() const
199 {
200 return size_;
201 }
202
204 {
205 return type_->size * size_;
206 }
207
208 void *data() const
209 {
210 return data_;
211 }
212
213 void *operator[](int64_t index) const
214 {
215 BLI_assert(index >= 0);
216 BLI_assert(index < size_);
217 return POINTER_OFFSET(data_, type_->size * index);
218 }
219
220 template<typename T> MutableSpan<T> typed() const
221 {
222 BLI_assert(size_ == 0 || type_ != nullptr);
223 BLI_assert(type_ == nullptr || type_->is<T>());
224 return MutableSpan<T>(static_cast<T *>(data_), size_);
225 }
226
228 {
229 BLI_assert(start >= 0);
230 BLI_assert(size >= 0);
231 BLI_assert(start + size <= size_ || size == 0);
232 return GMutableSpan(type_, POINTER_OFFSET(data_, type_->size * start), size);
233 }
234
236 {
237 return this->slice(range.start(), range.size());
238 }
239
241 {
242 BLI_assert(n >= 0);
243 const int64_t new_size = std::max<int64_t>(0, size_ - n);
244 return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size * n), new_size);
245 }
246
248 {
249 BLI_assert(n >= 0);
250 const int64_t new_size = std::max<int64_t>(0, size_ - n);
251 return GMutableSpan(*type_, data_, new_size);
252 }
253
255 {
256 BLI_assert(n >= 0);
257 const int64_t new_size = std::min<int64_t>(size_, n);
258 return GMutableSpan(*type_, data_, new_size);
259 }
260
262 {
263 BLI_assert(n >= 0);
264 const int64_t new_size = std::min<int64_t>(size_, n);
265 return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size * (size_ - new_size)), new_size);
266 }
267
273 void copy_from(GSpan values)
274 {
275 BLI_assert(type_ == &values.type());
276 BLI_assert(size_ == values.size());
277 type_->copy_assign_n(values.data(), data_, size_);
278 }
279};
280
281} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
#define POINTER_OFFSET(v, ofs)
iter begin(iter)
long long int int64_t
GMutableSpan(const CPPType *type)
void * operator[](int64_t index) const
void copy_from(GSpan values)
GMutableSpan(MutableSpan< T > array)
int64_t size_in_bytes() const
GMutableSpan take_front(const int64_t n) const
GMutableSpan take_back(const int64_t n) const
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType * type_ptr() const
GMutableSpan drop_back(const int64_t n) const
const CPPType & type() const
GMutableSpan(const CPPType &type)
GMutableSpan(const CPPType *type, void *buffer, int64_t size)
MutableSpan< T > typed() const
GMutableSpan(const CPPType &type, void *buffer, int64_t size)
GMutableSpan drop_front(const int64_t n) const
GMutableSpan slice(IndexRange range) const
const CPPType * type_ptr() const
GSpan(MutableSpan< T > array)
Span< T > typed() const
const CPPType & type() const
GSpan(const CPPType *type, const void *buffer, int64_t size)
GSpan drop_back(const int64_t n) const
GSpan drop_front(const int64_t n) const
GSpan slice(const IndexRange range) const
GSpan(Span< T > array)
int64_t size_in_bytes() const
bool is_empty() const
GSpan take_back(const int64_t n) const
GSpan(const CPPType &type, const void *buffer, int64_t size)
GSpan(const CPPType &type)
GSpan slice(const int64_t start, int64_t size) const
const void * data_
GSpan()=default
const void * data() const
GSpan(const CPPType *type)
const CPPType * type_
GSpan take_front(const int64_t n) const
int64_t size() const
const void * operator[](int64_t index) const
constexpr int64_t size() const
constexpr int64_t start() const
#define T