jabyengine/include/PSX/GPU/Primitives/linked_elements.hpp

79 lines
2.3 KiB
C++

#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<uint32_t>(adr)));
}
void* get_adr() const {
return reinterpret_cast<void*>(bit::value::get_normalized(this->value, AdrRange));
}
template<typename T>
T& insert_after(T& obj) {
const auto adr = Link::get_adr();
Link::set_adr(&obj);
obj.set_adr(adr);
return obj;
}
template<typename T>
const T& concat(const T& obj) {
Link::set_adr(&obj);
return obj;
}
constexpr void terminate() {
this->value |= TerminationValue;
}
};
template<typename T>
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<typename T>
struct LinkedElementCreator {
typedef LinkedElement<T> Linked;
constexpr LinkedElement<T> linked() {
return LinkedElement<T>(*static_cast<T*>(this));
}
};
}
}
}
#endif // !__JABYENGINE_LINKED_ELEMENTS_HPP__