diff --git a/src/internal/mana_c_api.h b/src/internal/mana_c_api.h index e4ce71e..83bd088 100644 --- a/src/internal/mana_c_api.h +++ b/src/internal/mana_c_api.h @@ -15,18 +15,31 @@ typedef enum mana_uint8, mana_sint8, mana_uint16, + mana_sint16, mana_uint32, + mana_sint32, mana_uint64, + mana_sint64, mana_float, mana_double, } mana_data_type_t; +// Offset based pointer. Allows to memcpy() structures with these pointers +// inside as long as the range covered by the pointers is also copied. +// +// Raw pointer value is '&ptr + offset'. nullptr is defined as offset=1. +// => Cannot point to the first byte of the struct itself but that's fine. +// Do not create temporaries of these. The offset will then be relative to the +// temporary on the stack! Do not copy these unless you copy the full memory +// range so that the offset_ptr_t in the new location stays valid. typedef struct { mana_data_type_t data_type; ptrdiff_t offset; } mana_offset_ptr_t; +// Typed offset pointer based array. Stores the array size in bytes instead of +// elements to allow storing any type using mana_custom. typedef struct { mana_offset_ptr_t ptr; diff --git a/src/internal/mana_lib.hpp b/src/internal/mana_lib.hpp index 6392d36..f377f5d 100644 --- a/src/internal/mana_lib.hpp +++ b/src/internal/mana_lib.hpp @@ -16,8 +16,11 @@ namespace mesytec::mnode::mana { +inline bool is_null(const mana_offset_ptr_t &ptr) { return ptr.offset == 1; } + namespace detail { + inline void set(mana_offset_ptr_t &ptr, void *p) { assert(p != reinterpret_cast(&ptr) + 1); @@ -33,31 +36,6 @@ inline void set(mana_offset_ptr_t &ptr, void *p) ptr.offset = 1; } } -} // namespace detail - -inline bool is_null(const mana_offset_ptr_t &ptr) { return ptr.offset == 1; } - -inline void *get(mana_offset_ptr_t &ptr) -{ - return is_null(ptr) ? nullptr : reinterpret_cast(&ptr) + ptr.offset; -} - -template T *get(mana_offset_ptr_t &ptr); // to catch unsupported types - -template T *get_(mana_offset_ptr_t &ptr, mana_data_type_t expected) -{ - if (ptr.data_type != expected) - return nullptr; - - return reinterpret_cast(get(ptr)); -} - -template <> u32 *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_uint32); } -template <> u64 *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_uint64); } -template <> s8 *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_sint8); } -template <> char *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_sint8); } -template <> float *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_float); } -template <> double *get(mana_offset_ptr_t &ptr) { return get_(ptr, mana_double); } inline void set(mana_offset_ptr_t &ptr, mana_data_type_t data_type, void *p) { @@ -65,13 +43,47 @@ inline void set(mana_offset_ptr_t &ptr, mana_data_type_t data_type, void *p) detail::set(ptr, p); } -inline void set(mana_offset_ptr_t &ptr, std::nullptr_t) { set(ptr, mana_uint32, nullptr); } -inline void set(mana_offset_ptr_t &ptr, u32 *p) { set(ptr, mana_uint32, p); } -inline void set(mana_offset_ptr_t &ptr, u64 *p) { set(ptr, mana_uint64, p); } -inline void set(mana_offset_ptr_t &ptr, s8 *p) { set(ptr, mana_sint8, p); } -inline void set(mana_offset_ptr_t &ptr, char *p) { set(ptr, mana_sint8, p); } -inline void set(mana_offset_ptr_t &ptr, float *p) { set(ptr, mana_float, p); } -inline void set(mana_offset_ptr_t &ptr, double *p) { set(ptr, mana_double, p); } +inline void *get(mana_offset_ptr_t &ptr) +{ + return is_null(ptr) ? nullptr : reinterpret_cast(&ptr) + ptr.offset; +} + +template T *get(mana_offset_ptr_t &ptr, mana_data_type_t expected) +{ + if (ptr.data_type != expected) + return nullptr; + + return reinterpret_cast(get(ptr)); +} + +} // namespace detail + +template T *get(mana_offset_ptr_t &ptr); // to catch unsupported types + +template <> u32 *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_uint32); } +template <> u64 *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_uint64); } +template <> s8 *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_sint8); } +template <> char *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_sint8); } +template <> float *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_float); } +template <> double *get(mana_offset_ptr_t &ptr) { return detail::get(ptr, mana_double); } + +// To make 'set(ptr, nullptr)' work. +inline void set(mana_offset_ptr_t &ptr, std::nullptr_t) +{ + detail::set(ptr, ptr.data_type, nullptr); +} + +inline void set(mana_offset_ptr_t &ptr, u8 *p) { detail::set(ptr, mana_uint8, p); } +inline void set(mana_offset_ptr_t &ptr, s8 *p) { detail::set(ptr, mana_sint8, p); } +inline void set(mana_offset_ptr_t &ptr, char *p) { detail::set(ptr, mana_sint8, p); } +inline void set(mana_offset_ptr_t &ptr, u16 *p) { detail::set(ptr, mana_uint16, p); } +inline void set(mana_offset_ptr_t &ptr, s16 *p) { detail::set(ptr, mana_sint16, p); } +inline void set(mana_offset_ptr_t &ptr, u32 *p) { detail::set(ptr, mana_uint32, p); } +inline void set(mana_offset_ptr_t &ptr, s32 *p) { detail::set(ptr, mana_sint32, p); } +inline void set(mana_offset_ptr_t &ptr, u64 *p) { detail::set(ptr, mana_uint64, p); } +inline void set(mana_offset_ptr_t &ptr, s64 *p) { detail::set(ptr, mana_sint64, p); } +inline void set(mana_offset_ptr_t &ptr, float *p) { detail::set(ptr, mana_float, p); } +inline void set(mana_offset_ptr_t &ptr, double *p) { detail::set(ptr, mana_double, p); } template T *push_offset_array(mana::Arena &arena, mana_offset_array_t &dest, size_t size) @@ -86,7 +98,7 @@ template T *push_typed_offset_array(mana::Arena &arena, mana_offset_array_t &dest, size_t size) { T *ptr = arena.push_t(size); - mana::set(dest.ptr, ptr); + set(dest.ptr, ptr); dest.size_bytes = size * sizeof(T); return ptr; } @@ -98,7 +110,7 @@ template size_t element_count(mana_offset_array_t &array) template mvlc::util::span get_span(mana_offset_array_t &array) { - auto ptr = reinterpret_cast(get(array.ptr)); + auto ptr = get(array.ptr); auto size = element_count(array); return {ptr, size}; }