FastLED 3.10.8
Loading...
Searching...
No Matches
basic_vector.h
Go to the documentation of this file.
1#pragma once
2
9
10#include "fl/stl/int.h"
11#include "fl/stl/cstring.h"
14#include "fl/stl/noexcept.h"
15
16namespace fl {
17
22 void (*copy_construct)(void* dst, const void* src);
23 void (*move_construct)(void* dst, void* src);
24 void (*default_construct)(void* ptr);
25 void (*swap_elements)(void* a, void* b);
26
29 void (*destroy_n)(void* first, fl::size count);
30};
31
37 public:
38 // ======= CAPACITY =======
39 fl::size size() const FL_NO_EXCEPT { return mSize; }
40 bool empty() const FL_NO_EXCEPT { return mSize == 0; }
41 fl::size capacity() const FL_NO_EXCEPT { return mCapacity; }
42 bool full() const FL_NO_EXCEPT { return mSize >= mCapacity; }
43 fl::size element_size() const FL_NO_EXCEPT { return mElementSize; }
44
45 // ======= RAW DATA ACCESS =======
46 void* data_raw() FL_NO_EXCEPT { return mArray; }
47 const void* data_raw() const FL_NO_EXCEPT { return mArray; }
48
49 // ======= MEMORY MANAGEMENT =======
50 void reserve_impl(fl::size n) FL_NO_EXCEPT;
52
53 // ======= ELEMENT OPERATIONS =======
54 void push_back_copy_impl(const void* element) FL_NO_EXCEPT;
55 void push_back_move_impl(void* element) FL_NO_EXCEPT;
58
60 void erase_impl(fl::size index) FL_NO_EXCEPT;
61
63 void erase_range_impl(fl::size first_index, fl::size count) FL_NO_EXCEPT;
64
66 void insert_copy_impl(fl::size index, const void* element) FL_NO_EXCEPT;
67
69 void insert_move_impl(fl::size index, void* element) FL_NO_EXCEPT;
70
73
75 void resize_value_impl(fl::size n, const void* value) FL_NO_EXCEPT;
76
79
80 // ======= DESTRUCTOR =======
82
83 protected:
84 // ======= CONSTRUCTION (only callable by vector<T>) =======
85
87 vector_basic(fl::size elementSize, memory_resource* resource,
89 : mElementSize(elementSize)
90 , mResource(resource)
91 , mOps(ops)
92 , mInlineOffset(0)
93 , mInlineCapacity(0) {}
94
96 vector_basic(void* inlineBuffer, fl::size inlineCapacity,
97 fl::size elementSize, memory_resource* resource,
98 const vector_element_ops* ops)
99 FL_NO_EXCEPT : mElementSize(elementSize)
100 , mResource(resource)
101 , mOps(ops)
102 , mInlineOffset(static_cast<fl::size>(
103 static_cast<char*>(inlineBuffer) -
104 static_cast<char*>(static_cast<void*>(this))))
105 , mInlineCapacity(inlineCapacity) {
106 // Start with data in inline buffer
107 mArray = inlineBuffer;
108 mCapacity = inlineCapacity;
109 }
110
111 // Deleted copy/move — vector<T> handles these
114 vector_basic& operator=(const vector_basic&) FL_NO_EXCEPT = delete;
115 vector_basic& operator=(vector_basic&&) FL_NO_EXCEPT = delete;
116
117 // ======= HELPERS FOR DERIVED CLASSES =======
118
120 void copy_from(const vector_basic& other) FL_NO_EXCEPT;
121
124
127
128 // ======= DATA MEMBERS =======
129 void* mArray = nullptr;
134 const vector_element_ops* mOps; // nullptr → trivially copyable
135
136 // Inline buffer support (offset trick from basic_string).
137 // Store offset from `this` to the inline buffer, not a raw pointer.
138 // This survives trivial relocation (bitwise copy by containers) because
139 // the offset is relative to `this` which updates with the object.
141 fl::size mInlineCapacity; // 0 = no inline buffer
142
143 // ======= HELPER METHODS =======
144
147 return static_cast<char*>(static_cast<void*>(this)) + mInlineOffset;
148 }
149 const void* inlineBufferPtr() const FL_NO_EXCEPT {
150 return static_cast<const char*>(static_cast<const void*>(this)) + mInlineOffset;
151 }
152
154 bool isInline() const FL_NO_EXCEPT {
155 return mInlineCapacity > 0 && mArray == inlineBufferPtr();
156 }
157
160 return mInlineCapacity > 0;
161 }
162
164 void* element_ptr(fl::size index) FL_NO_EXCEPT {
165 return static_cast<char*>(mArray) + index * mElementSize;
166 }
167 const void* element_ptr(fl::size index) const FL_NO_EXCEPT {
168 return static_cast<const char*>(mArray) + index * mElementSize;
169 }
170
171 private:
173 void ensure_capacity(fl::size n) FL_NO_EXCEPT;
174
176 void grow_to(fl::size new_capacity) FL_NO_EXCEPT;
177 void uninitialized_move_n_impl(void* dst, void* src, fl::size count) const FL_NO_EXCEPT;
178
179 // ======= TRIVIAL ELEMENT HELPERS (memcpy/memmove) =======
180 void trivial_copy(void* dst, const void* src, fl::size count) const FL_NO_EXCEPT;
181 void trivial_move_left(void* dst, const void* src, fl::size count) const FL_NO_EXCEPT;
182 void trivial_default_construct(void* ptr, fl::size count) const FL_NO_EXCEPT;
183 void trivial_swap(void* a, void* b) const FL_NO_EXCEPT;
184};
185
186// ======= OPS TABLE HELPERS =======
187
188namespace detail {
189
190// SFINAE: detect if T is default-constructible
191template <typename T, typename = void>
193
194template <typename T>
195struct has_default_ctor<T, decltype(void(T()))> : fl::true_type {};
196
197// SFINAE: detect if T is copy-constructible
198template <typename T, typename = void>
200
201template <typename T>
202struct has_copy_ctor<T, decltype(void(T(fl::declval<const T&>())))> : fl::true_type {};
203
204// Default construct: available when T has default ctor
205template <typename T>
208 return [](void* ptr) FL_NO_EXCEPT { new (ptr) T(); };
209}
210
211// Default construct: nullptr when T has no default ctor
212template <typename T>
215 return nullptr;
216}
217
218// Copy construct: available when T has copy ctor
219template <typename T>
220typename fl::enable_if<has_copy_ctor<T>::value, void(*)(void*, const void*)>::type
222 return [](void* dst, const void* src) FL_NO_EXCEPT {
223 new (dst) T(*static_cast<const T*>(src));
224 };
225}
226
227// Copy construct: nullptr when T is not copyable
228template <typename T>
229typename fl::enable_if<!has_copy_ctor<T>::value, void(*)(void*, const void*)>::type
231 return nullptr;
232}
233
234// SFINAE: detect if T is move-constructible
235template <typename T, typename = void>
237
238template <typename T>
239struct has_move_ctor<T, decltype(void(T(fl::declval<T&&>())))> : fl::true_type {};
240
241// SFINAE: detect if T is swappable (needs move-constructible + move-assignable)
242template <typename T, typename = void>
244
245template <typename T>
246struct is_swappable<T, decltype(void(
247 fl::declval<T&>() = fl::declval<T&&>()
248))> : has_move_ctor<T> {};
249
250// Move construct: available
251template <typename T>
252typename fl::enable_if<has_move_ctor<T>::value, void(*)(void*, void*)>::type
254 return [](void* dst, void* src) FL_NO_EXCEPT {
255 new (dst) T(static_cast<T&&>(*static_cast<T*>(src)));
256 };
257}
258
259template <typename T>
260typename fl::enable_if<!has_move_ctor<T>::value, void(*)(void*, void*)>::type
262 return nullptr;
263}
264
265// Swap: available when swappable
266template <typename T>
267typename fl::enable_if<is_swappable<T>::value, void(*)(void*, void*)>::type
269 return [](void* a, void* b) FL_NO_EXCEPT {
270 T& ta = *static_cast<T*>(a);
271 T& tb = *static_cast<T*>(b);
272 T tmp(static_cast<T&&>(ta));
273 ta = static_cast<T&&>(tb);
274 tb = static_cast<T&&>(tmp);
275 };
276}
277
278template <typename T>
279typename fl::enable_if<!is_swappable<T>::value, void(*)(void*, void*)>::type
281 return nullptr;
282}
283
284} // namespace detail
285
286// ======= OPS TABLE GENERATOR =======
287
290template <typename T>
292 // Trivially copyable types use the fast path (mOps == nullptr)
294 return nullptr;
295 }
296
297 static const vector_element_ops ops = {
298 detail::get_copy_construct_fn<T>(), // copy_construct
299 detail::get_move_construct_fn<T>(), // move_construct
300 detail::get_default_construct_fn<T>(), // default_construct
301 detail::get_swap_fn<T>(), // swap_elements
302 // destroy_n
303 [](void* first, fl::size count) FL_NO_EXCEPT {
304 T* p = static_cast<T*>(first);
305 for (fl::size i = 0; i < count; ++i) {
306 p[i].~T();
307 }
308 }
309 };
310 return &ops;
311}
312
313} // namespace fl
Polymorphic memory resource base class (PMR-style).
void move_assign(vector_basic &other) FL_NO_EXCEPT
Move-assign from another vector_basic (clears this first).
fl::size capacity() const FL_NO_EXCEPT
bool hasInlineBuffer() const FL_NO_EXCEPT
Does this vector have an inline buffer at all?
const vector_element_ops * mOps
void trivial_swap(void *a, void *b) const FL_NO_EXCEPT
void trivial_copy(void *dst, const void *src, fl::size count) const FL_NO_EXCEPT
const void * element_ptr(fl::size index) const FL_NO_EXCEPT
void ensure_capacity(fl::size n) FL_NO_EXCEPT
Ensure capacity for at least n elements. Grows if needed.
void * element_ptr(fl::size index) FL_NO_EXCEPT
Pointer to element at index (byte arithmetic).
fl::size size() const FL_NO_EXCEPT
void * inlineBufferPtr() FL_NO_EXCEPT
Compute inline buffer pointer from offset.
void resize_impl(fl::size n) FL_NO_EXCEPT
Resize to n elements. New elements are default-constructed (zeroed for trivial).
void resize_value_impl(fl::size n, const void *value) FL_NO_EXCEPT
Resize to n elements. New elements are copy-constructed from value.
const void * inlineBufferPtr() const FL_NO_EXCEPT
void push_back_move_impl(void *element) FL_NO_EXCEPT
bool isInline() const FL_NO_EXCEPT
Is data currently in the inline buffer?
void shrink_to_fit_impl() FL_NO_EXCEPT
fl::size mElementSize
void push_back_copy_impl(const void *element) FL_NO_EXCEPT
void grow_to(fl::size new_capacity) FL_NO_EXCEPT
Grow to new_capacity. Moves existing elements.
void insert_move_impl(fl::size index, void *element) FL_NO_EXCEPT
Insert element at index by move. Shifts subsequent elements right.
void copy_from(const vector_basic &other) FL_NO_EXCEPT
Copy all elements from another vector_basic.
vector_basic(vector_basic &&) FL_NO_EXCEPT=delete
memory_resource * mResource
void trivial_default_construct(void *ptr, fl::size count) const FL_NO_EXCEPT
vector_basic(const vector_basic &) FL_NO_EXCEPT=delete
const void * data_raw() const FL_NO_EXCEPT
vector_basic(void *inlineBuffer, fl::size inlineCapacity, fl::size elementSize, memory_resource *resource, const vector_element_ops *ops) FL_NO_EXCEPT
Vector with inline buffer (for VectorN).
void uninitialized_move_n_impl(void *dst, void *src, fl::size count) const FL_NO_EXCEPT
void trivial_move_left(void *dst, const void *src, fl::size count) const FL_NO_EXCEPT
fl::size mInlineOffset
vector_basic(fl::size elementSize, memory_resource *resource, const vector_element_ops *ops) FL_NO_EXCEPT
Heap-only vector (no inline buffer).
bool empty() const FL_NO_EXCEPT
void clear_impl() FL_NO_EXCEPT
void reserve_impl(fl::size n) FL_NO_EXCEPT
fl::size mInlineCapacity
void erase_impl(fl::size index) FL_NO_EXCEPT
Erase element at index. Shifts subsequent elements left.
void erase_range_impl(fl::size first_index, fl::size count) FL_NO_EXCEPT
Erase range [first_index, first_index + count).
void move_from(vector_basic &other) FL_NO_EXCEPT
Move-steal contents from another vector_basic.
void pop_back_impl() FL_NO_EXCEPT
bool full() const FL_NO_EXCEPT
fl::size element_size() const FL_NO_EXCEPT
void insert_copy_impl(fl::size index, const void *element) FL_NO_EXCEPT
Insert element at index by copy. Shifts subsequent elements right.
void * data_raw() FL_NO_EXCEPT
Type-erased vector base class.
PMR-style polymorphic memory resource for type-erased allocation.
fl::enable_if< has_default_ctor< T >::value, void(*)(void *)>::type get_default_construct_fn() FL_NO_EXCEPT
fl::enable_if< has_move_ctor< T >::value, void(*)(void *, void *)>::type get_move_construct_fn() FL_NO_EXCEPT
fl::enable_if< is_swappable< T >::value, void(*)(void *, void *)>::type get_swap_fn() FL_NO_EXCEPT
fl::enable_if< has_copy_ctor< T >::value, void(*)(void *, constvoid *)>::type get_copy_construct_fn() FL_NO_EXCEPT
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
constexpr int type_rank< T >::value
add_rvalue_reference< T >::type declval() FL_NO_EXCEPT
integral_constant< bool, false > false_type
Definition type_traits.h:29
const vector_element_ops * vector_element_ops_for() FL_NO_EXCEPT
Generate a static ops table for type T.
integral_constant< bool, true > true_type
Definition type_traits.h:28
Base definition for an LED controller.
Definition crgb.hpp:179
void(* default_construct)(void *ptr)
void(* swap_elements)(void *a, void *b)
void(* copy_construct)(void *dst, const void *src)
void(* move_construct)(void *dst, void *src)
void(* destroy_n)(void *first, fl::size count)
Destroy count elements starting at first (count == 1 for a single element: one destroy thunk per type...
Function pointer table for type-specific element operations.