#ifndef __JABYENGINE_LINKED_ELEMENTS_HPP__ #define __JABYENGINE_LINKED_ELEMENTS_HPP__ #include "../../Auxiliary/bits.hpp" namespace JabyEngine { namespace GPU { struct Link { static constexpr auto AdrRange = BitRange::from_to(0, 23); static constexpr auto SizeRange = BitRange::from_to(24, 31); static constexpr uint32_t TerminationValue = 0x00FFFFFF; uint32_t value = TerminationValue; constexpr Link() = default; constexpr Link(size_t size) : value(SizeRange.as_value(size >> 2) | TerminationValue) { } void set_adr(const void* adr) { this->value = bit::value::set_normalized(this->value, AdrRange.with(reinterpret_cast(adr))); } void* get_adr() const { return reinterpret_cast(bit::value::get_normalized(this->value, AdrRange)); } template T& insert_after(T& obj) { const auto adr = Link::get_adr(); Link::set_adr(&obj); obj.set_adr(adr); return obj; } template T& concat(T& obj) { Link::set_adr(&obj); return obj; } template const T& concat(const T& obj) { return concat(const_cast(obj)); } constexpr void terminate() { this->value |= TerminationValue; } }; template struct LinkedElement : public Link { T element; constexpr LinkedElement() : Link(sizeof(T)), element() { } constexpr LinkedElement(const T& element) : Link(sizeof(T)), element(element) { } constexpr const T* operator->() const { return &this->element; } constexpr T* operator->() { return &this->element; } }; namespace internal { template struct LinkedElementCreator { typedef LinkedElement Linked; constexpr LinkedElement linked() { return LinkedElement(*static_cast(this)); } }; } } } #endif // !__JABYENGINE_LINKED_ELEMENTS_HPP__