113 using TargetCastType = std::add_pointer_t<ValueType>;
118 GAIA_NODISCARD
static constexpr uint32_t get_min_byte_size(uintptr_t addr,
size_t cnt)
noexcept {
119 const auto offset = detail::get_aligned_byte_offset<ValueType, Alignment>(addr, cnt);
120 return (uint32_t)(offset - addr);
123 template <
typename Allocator>
124 GAIA_NODISCARD
static uint8_t* alloc(
size_t cnt)
noexcept {
125 const auto bytes = get_min_byte_size(0, cnt);
126 auto* pData = (ValueType*)mem::AllocHelper::alloc<uint8_t, Allocator>(bytes);
127 core::call_ctor_raw_n(pData, cnt);
128 return (uint8_t*)pData;
131 template <
typename Allocator>
132 static void free(
void* pData,
size_t cap,
size_t cnt)
noexcept {
133 if (pData ==
nullptr)
135 core::call_dtor_n((ValueType*)pData, cnt);
136 GAIA_MEM_SANI_DEL_BLOCK(
sizeof(ValueType), pData, cap, cnt);
137 return mem::AllocHelper::free<Allocator>(pData);
140 template <
typename Allocator>
141 static void free(
void* pData,
size_t cnt)
noexcept {
142 if (pData ==
nullptr)
144 core::call_dtor_n((ValueType*)pData, cnt);
145 return mem::AllocHelper::free<Allocator>(pData);
244 static_assert(std::is_copy_assignable_v<ValueType>);
246 using TTuple =
decltype(meta::struct_to_tuple(std::declval<ValueType>()));
247 using TargetCastType = uint8_t*;
251 constexpr static size_t TTupleItems = std::tuple_size<TTuple>::value;
252 static_assert(Alignment > 0U,
"SoA data can't be zero-aligned");
254 template <
size_t Item>
255 using value_type =
typename std::tuple_element<Item, TTuple>::type;
256 template <
size_t Item>
257 using const_value_type =
typename std::add_const<value_type<Item>>::type;
259 GAIA_NODISCARD
constexpr static uint32_t get_min_byte_size(uintptr_t addr,
size_t cnt)
noexcept {
260 const auto offset = get_aligned_byte_offset<TTupleItems>(addr, cnt);
261 return (uint32_t)(offset - addr);
264 template <
typename Allocator>
265 GAIA_NODISCARD
static uint8_t* alloc(
size_t cnt)
noexcept {
266 const auto bytes = get_min_byte_size(0, cnt);
267 return mem::AllocHelper::alloc_alig<uint8_t, Allocator>(Alignment, bytes);
270 template <
typename Allocator>
271 static void free(
void* pData,
size_t cap,
size_t cnt)
noexcept {
272 if (pData ==
nullptr)
275 mem_del_block(pData, cap, cnt);
276 return mem::AllocHelper::free_alig<Allocator>(pData);
279 static void mem_add_block(
void* pData,
size_t cap,
size_t count) {
280 meta::each_member(ValueType{}, [&](
auto&&... item) {
281 auto address = mem::align<Alignment>((uintptr_t)pData);
284 GAIA_MEM_SANI_ADD_BLOCK(
sizeof(item), (
void*)address, cap, count),
286 address = mem::align<Alignment>(address + (
sizeof(item) * cap))),
291 static void mem_del_block(
void* pData,
size_t cap,
size_t count) {
292 meta::each_member(ValueType{}, [&](
auto&&... item) {
293 auto address = mem::align<Alignment>((uintptr_t)pData);
296 GAIA_MEM_SANI_DEL_BLOCK(
sizeof(item), (
void*)address, cap, count),
298 address = mem::align<Alignment>(address + (
sizeof(item) * cap))),
303 static void mem_push_block(
void* pData,
size_t cap,
size_t count,
size_t n) {
304 meta::each_member(ValueType{}, [&](
auto&&... item) {
305 auto address = mem::align<Alignment>((uintptr_t)pData);
308 GAIA_MEM_SANI_PUSH_N(
sizeof(item), (
void*)address, cap, count, n),
310 address = mem::align<Alignment>(address + (
sizeof(item) * cap))),
315 static void mem_pop_block(
void* pData,
size_t cap,
size_t count,
size_t n) {
316 meta::each_member(ValueType{}, [&](
auto&&... item) {
317 auto address = mem::align<Alignment>((uintptr_t)pData);
320 GAIA_MEM_SANI_POP_N(
sizeof(item), (
void*)address, cap, count, n),
322 address = mem::align<Alignment>(address + (
sizeof(item) * cap))),
328 return get_inter(meta::struct_to_tuple(ValueType{}), s, idx, std::make_index_sequence<TTupleItems>());
331 template <
size_t Item>
333 const auto offset = get_aligned_byte_offset<Item>((uintptr_t)s.data(), s.size());
334 const auto& ref = get_ref<const value_type<Item>>(
reinterpret_cast<const uint8_t*
>(offset), idx);
345 constexpr void operator=(
const ValueType& val)
noexcept {
346 set_inter(meta::struct_to_tuple(val), m_data, m_idx, std::make_index_sequence<TTupleItems>());
349 constexpr void operator=(ValueType&& val)
noexcept {
350 set_inter(meta::struct_to_tuple(GAIA_MOV(val)), m_data, m_idx, std::make_index_sequence<TTupleItems>());
353 GAIA_NODISCARD
constexpr operator ValueType()
const noexcept {
355 meta::struct_to_tuple(ValueType{}), {(
const uint8_t*)m_data.data(), m_data.size()}, m_idx,
356 std::make_index_sequence<TTupleItems>());
364 template <
size_t Item>
365 GAIA_NODISCARD
constexpr static auto set(
std::span<uint8_t> s,
size_t idx = 0) noexcept {
366 const auto offset = get_aligned_byte_offset<Item>((uintptr_t)s.data(), s.size());
367 auto& ref = get_ref<value_type<Item>>((
const uint8_t*)offset, idx);
372 template <
size_t... Ids>
373 GAIA_NODISCARD
constexpr static size_t
374 get_aligned_byte_offset_seq(uintptr_t address,
size_t cnt, std::index_sequence<Ids...> ) {
376 address = mem::align<Alignment>(address);
378 ((address = mem::align<Alignment>(address + (
sizeof(value_type<Ids>) * cnt))), ...);
382 template <u
int32_t N>
383 GAIA_NODISCARD
constexpr static size_t get_aligned_byte_offset(uintptr_t address,
size_t cnt) {
384 return get_aligned_byte_offset_seq(address, cnt, std::make_index_sequence<N>());
387 template <
typename TMemberType>
388 GAIA_NODISCARD
constexpr static TMemberType& get_ref(
const uint8_t* data,
size_t idx)
noexcept {
391 auto* pCastData = (TMemberType*)data;
392 return pCastData[idx];
395 template <
typename Tup,
size_t... Ids>
396 GAIA_NODISCARD
constexpr static ValueType
398 auto address = mem::align<Alignment>((uintptr_t)s.data());
401 std::get<Ids>(t) = get_ref<value_type<Ids>>((
const uint8_t*)address, idx),
403 address = mem::align<Alignment>(address + (
sizeof(value_type<Ids>) * s.size()))),
405 return meta::tuple_to_struct<ValueType, TTuple>(GAIA_FWD(t));
408 template <
typename Tup,
size_t... Ids>
409 constexpr static void
410 set_inter(Tup&& t,
std::span<uint8_t> s,
size_t idx, std::index_sequence<Ids...> )
noexcept {
411 auto address = mem::align<Alignment>((uintptr_t)s.data());
414 get_ref<value_type<Ids>>((uint8_t*)address, idx) = std::get<Ids>(t),
416 address = mem::align<Alignment>(address + (
sizeof(value_type<Ids>) * s.size()))),