[ox/fs/ptrarith] Make everything in ptrarith noexcept

This commit is contained in:
Gary Talent 2021-04-18 14:33:06 -05:00
parent 5ad7c963b1
commit 9d74c5b464
2 changed files with 110 additions and 99 deletions

View File

@ -34,45 +34,48 @@ class OX_PACKED NodeBuffer {
size_t m_it = 0;
public:
Iterator(NodeBuffer *buffer, ItemPtr current) {
Iterator(NodeBuffer *buffer, ItemPtr current) noexcept {
m_buffer = buffer;
m_current = current;
oxTrace("ox::ptrarith::Iterator::start") << current.offset();
}
operator const Item*() const {
operator const Item*() const noexcept {
return m_current;
}
ItemPtr ptr() {
ItemPtr ptr() noexcept {
return m_current;
}
Item *get() {
[[nodiscard]]
Item *get() noexcept {
return m_current;
}
operator ItemPtr() {
operator ItemPtr() noexcept {
return m_current;
}
operator Item*() {
operator Item*() noexcept {
return m_current;
}
const Item *operator->() const {
const Item *operator->() const noexcept {
return m_current;
}
Item *operator->() {
Item *operator->() noexcept {
return m_current;
}
[[nodiscard]] bool valid() const noexcept {
[[nodiscard]]
bool valid() const noexcept {
return m_current.valid();
}
bool hasNext() {
[[nodiscard]]
bool hasNext() noexcept {
if (m_current.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
auto next = m_buffer->next(m_current);
@ -81,7 +84,7 @@ class OX_PACKED NodeBuffer {
return false;
}
void next() {
void next() noexcept {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++;
if (hasNext()) {
m_current = m_buffer->next(m_current);
@ -94,76 +97,83 @@ class OX_PACKED NodeBuffer {
Header m_header;
public:
NodeBuffer();
NodeBuffer() noexcept;
NodeBuffer(const NodeBuffer &other, size_t size);
NodeBuffer(const NodeBuffer &other, size_t size) noexcept;
explicit NodeBuffer(size_t size);
explicit NodeBuffer(size_t size) noexcept;
const Iterator iterator() const;
[[nodiscard]]
const Iterator iterator() const noexcept;
Iterator iterator();
[[nodiscard]]
Iterator iterator() noexcept;
ItemPtr firstItem();
ItemPtr firstItem() noexcept;
ItemPtr lastItem();
ItemPtr lastItem() noexcept;
/**
* @return the data section of the given item
*/
template<typename T>
Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr);
Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr) noexcept;
[[nodiscard]] ItemPtr prev(Item *item);
ItemPtr prev(Item *item) noexcept;
[[nodiscard]] ItemPtr next(Item *item);
ItemPtr next(Item *item) noexcept;
/**
* Like pointer but omits checks that assume the memory at the offset has
* already been initialed as an Item.
*/
[[nodiscard]] ItemPtr uninitializedPtr(size_t offset);
ItemPtr uninitializedPtr(size_t offset) noexcept;
[[nodiscard]] ItemPtr ptr(size_t offset);
ItemPtr ptr(size_t offset) noexcept;
[[nodiscard]] ItemPtr malloc(size_t size);
ItemPtr malloc(size_t size) noexcept;
Error free(ItemPtr item);
Error free(ItemPtr item) noexcept;
[[nodiscard]] bool valid(size_t maxSize);
[[nodiscard]]
bool valid(size_t maxSize) noexcept;
/**
* Set size, capacity.
*/
Error setSize(size_t size);
Error setSize(size_t size) noexcept;
/**
* Get size, capacity.
* @return capacity
*/
size_t size();
[[nodiscard]]
constexpr size_t size() const noexcept;
/**
* @return the bytes still available in this NodeBuffer
*/
size_t available();
[[nodiscard]]
size_t available() noexcept;
/**
* @return the actual number a bytes need to store the given number of
* bytes
*/
static size_t spaceNeeded(size_t size);
[[nodiscard]]
static size_t spaceNeeded(size_t size) noexcept;
template<typename F>
Error compact(F cb = [](uint64_t, ItemPtr) {});
Error compact(F cb = [](uint64_t, ItemPtr) {}) noexcept;
private:
uint8_t *data();
private:
[[nodiscard]]
uint8_t *data() noexcept;
};
template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(size_t size) {
NodeBuffer<size_t, Item>::NodeBuffer(size_t size) noexcept {
m_header.size = size;
auto data = reinterpret_cast<uint8_t*>(this) + sizeof(*this);
ox_memset(data, 0, size - sizeof(*this));
@ -171,7 +181,7 @@ NodeBuffer<size_t, Item>::NodeBuffer(size_t size) {
}
template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, size_t size) {
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, size_t size) noexcept {
oxTrace("ox::ptrarith::NodeBuffer::copy") << "other.m_header.firstItem:" << other.m_header.firstItem;
auto data = reinterpret_cast<uint8_t*>(this) + sizeof(*this);
ox_memset(data, 0, size - sizeof(*this));
@ -179,24 +189,24 @@ NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, size_t size) {
}
template<typename size_t, typename Item>
const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() const {
const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() const noexcept {
return Iterator(this, firstItem());
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() {
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() noexcept {
oxTrace("ox::ptrarith::NodeBuffer::iterator::size") << m_header.size;
return Iterator(this, firstItem());
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::firstItem() {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::firstItem() noexcept {
//oxTrace("ox::ptrarith::NodeBuffer::firstItem") << m_header.firstItem;
return ptr(m_header.firstItem);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem() {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem() noexcept {
auto first = ptr(m_header.firstItem);
if (first.valid()) {
return prev(first);
@ -206,24 +216,24 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem()
template<typename size_t, typename Item>
template<typename T>
Ptr<T, size_t, sizeof(Item)> NodeBuffer<size_t, Item>::dataOf(ItemPtr ip) {
Ptr<T, size_t, sizeof(Item)> NodeBuffer<size_t, Item>::dataOf(ItemPtr ip) noexcept {
auto out = ip.template subPtr<T>(sizeof(Item));
oxAssert(out.size() == ip.size() - sizeof(Item), "Sub Ptr has invalid size.");
return out;
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::prev(Item *item) {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::prev(Item *item) noexcept {
return ptr(item->prev);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *item) {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *item) noexcept {
return ptr(item->next);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::uninitializedPtr(size_t itemOffset) {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::uninitializedPtr(size_t itemOffset) noexcept {
// make sure this can be read as an Item, and then use Item::size for the size
std::size_t itemSpace = m_header.size - itemOffset;
if (itemOffset >= sizeof(Header) &&
@ -240,7 +250,7 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::uninitializ
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) noexcept {
// make sure this can be read as an Item, and then use Item::size for the size
std::size_t itemSpace = m_header.size - itemOffset;
auto item = reinterpret_cast<Item*>(reinterpret_cast<uint8_t*>(this) + itemOffset);
@ -259,7 +269,7 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size_t size) {
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size_t size) noexcept {
oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Size:" << size;
size_t fullSize = size + sizeof(Item);
if (m_header.size - m_header.bytesUsed >= fullSize) {
@ -318,7 +328,7 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size
}
template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
oxTrace("ox::ptrarith::NodeBuffer::free") << "offset:" << item.offset();
auto prev = this->prev(item);
auto next = this->next(item);
@ -349,7 +359,7 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
}
template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
Error NodeBuffer<size_t, Item>::setSize(size_t size) noexcept {
oxTracef("ox::ptrarith::NodeBuffer::setSize", "{} to {}", m_header.size.get(), size);
auto last = lastItem();
auto end = last.valid() ? last.end() : sizeof(m_header);
@ -366,28 +376,28 @@ Error NodeBuffer<size_t, Item>::setSize(size_t size) {
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::size() {
constexpr size_t NodeBuffer<size_t, Item>::size() const noexcept {
return m_header.size;
}
template<typename size_t, typename Item>
bool NodeBuffer<size_t, Item>::valid(size_t maxSize) {
bool NodeBuffer<size_t, Item>::valid(size_t maxSize) noexcept {
return m_header.size <= maxSize;
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::available() {
size_t NodeBuffer<size_t, Item>::available() noexcept {
return m_header.size - m_header.bytesUsed;
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::spaceNeeded(size_t size) {
size_t NodeBuffer<size_t, Item>::spaceNeeded(size_t size) noexcept {
return sizeof(Item) + size;
}
template<typename size_t, typename Item>
template<typename F>
Error NodeBuffer<size_t, Item>::compact(F cb) {
Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
auto src = firstItem();
auto dest = ptr(sizeof(*this));
while (dest.offset() <= src.offset()) {
@ -417,7 +427,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) {
}
template<typename size_t, typename Item>
uint8_t *NodeBuffer<size_t, Item>::data() {
uint8_t *NodeBuffer<size_t, Item>::data() noexcept {
return reinterpret_cast<uint8_t*>(ptr(sizeof(*this)).get());
}

View File

@ -13,7 +13,7 @@
namespace ox::ptrarith {
template<typename T, typename size_t, size_t minOffset = 1>
class Ptr {
class [[nodiscard]] Ptr {
private:
uint8_t *m_dataStart = nullptr;
@ -25,65 +25,66 @@ class Ptr {
mutable uint8_t m_validated = false;
public:
inline Ptr() = default;
constexpr Ptr() noexcept = default;
inline Ptr(std::nullptr_t);
constexpr Ptr(std::nullptr_t) noexcept;
inline Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize = sizeof(T), size_t itemTypeSize = sizeof(T));
constexpr Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize = sizeof(T), size_t itemTypeSize = sizeof(T)) noexcept;
[[nodiscard]] inline bool valid() const;
[[nodiscard]]
constexpr bool valid() const noexcept;
inline size_t size() const;
constexpr size_t size() const noexcept;
inline size_t offset() const;
constexpr size_t offset() const noexcept;
inline size_t end();
constexpr size_t end() noexcept;
inline const T *get() const;
constexpr const T *get() const noexcept;
inline T *get();
constexpr T *get() noexcept;
inline const T *operator->() const;
constexpr const T *operator->() const noexcept;
inline T *operator->();
constexpr T *operator->() noexcept;
inline operator const T*() const;
constexpr operator const T*() const noexcept;
inline operator T*();
constexpr operator T*() noexcept;
inline const T &operator*() const;
constexpr const T &operator*() const noexcept;
inline T &operator*();
constexpr T &operator*() noexcept;
inline operator size_t() const;
constexpr operator size_t() const noexcept;
inline bool operator==(const Ptr<T, size_t, minOffset> &other) const;
constexpr bool operator==(const Ptr<T, size_t, minOffset> &other) const noexcept;
inline bool operator!=(const Ptr<T, size_t, minOffset> &other) const;
constexpr bool operator!=(const Ptr<T, size_t, minOffset> &other) const noexcept;
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size) const;
constexpr const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size) const noexcept;
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset) const;
constexpr const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset) const noexcept;
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size);
constexpr Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size) noexcept;
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset);
constexpr Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset) noexcept;
template<typename SubT>
inline const Ptr<SubT, size_t, minOffset> to() const;
constexpr const Ptr<SubT, size_t, minOffset> to() const noexcept;
};
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::Ptr(std::nullptr_t) {
constexpr Ptr<T, size_t, minOffset>::Ptr(std::nullptr_t) noexcept {
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize, size_t itemTypeSize) {
constexpr Ptr<T, size_t, minOffset>::Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize, size_t itemTypeSize) noexcept {
// do some sanity checks before assuming this is valid
if (itemSize >= itemTypeSize &&
dataStart &&
@ -97,84 +98,84 @@ inline Ptr<T, size_t, minOffset>::Ptr(void *dataStart, size_t dataSize, size_t i
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::valid() const {
constexpr bool Ptr<T, size_t, minOffset>::valid() const noexcept {
m_validated = m_dataStart != nullptr;
return m_validated;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::size() const {
constexpr size_t Ptr<T, size_t, minOffset>::size() const noexcept {
return m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::offset() const {
constexpr size_t Ptr<T, size_t, minOffset>::offset() const noexcept {
return m_itemOffset;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::end() {
constexpr size_t Ptr<T, size_t, minOffset>::end() noexcept {
return m_itemOffset + m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline const T *Ptr<T, size_t, minOffset>::get() const {
constexpr const T *Ptr<T, size_t, minOffset>::get() const noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::get())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::get())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T *Ptr<T, size_t, minOffset>::get() {
constexpr T *Ptr<T, size_t, minOffset>::get() noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::get())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::get())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline const T *Ptr<T, size_t, minOffset>::operator->() const {
constexpr const T *Ptr<T, size_t, minOffset>::operator->() const noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator->())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T *Ptr<T, size_t, minOffset>::operator->() {
constexpr T *Ptr<T, size_t, minOffset>::operator->() noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator->())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator const T*() const {
constexpr Ptr<T, size_t, minOffset>::operator const T*() const noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator const T*())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator const T*())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator T*() {
constexpr Ptr<T, size_t, minOffset>::operator T*() noexcept {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator T*())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator T*())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline const T &Ptr<T, size_t, minOffset>::operator*() const {
constexpr const T &Ptr<T, size_t, minOffset>::operator*() const noexcept {
oxAssert(m_validated, "Unvalidated pointer dereference. (ox::fs::Ptr::operator*())");
oxAssert(valid(), "Invalid pointer dereference. (ox::fs::Ptr::operator*())");
return *reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T &Ptr<T, size_t, minOffset>::operator*() {
constexpr T &Ptr<T, size_t, minOffset>::operator*() noexcept {
oxAssert(m_validated, "Unvalidated pointer dereference. (ox::fs::Ptr::operator*())");
oxAssert(valid(), "Invalid pointer dereference. (ox::fs::Ptr::operator*())");
return *reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator size_t() const {
constexpr Ptr<T, size_t, minOffset>::operator size_t() const noexcept {
if (m_dataStart && m_itemOffset) {
return m_itemOffset;
}
@ -182,14 +183,14 @@ inline Ptr<T, size_t, minOffset>::operator size_t() const {
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::operator==(const Ptr<T, size_t, minOffset> &other) const {
constexpr bool Ptr<T, size_t, minOffset>::operator==(const Ptr<T, size_t, minOffset> &other) const noexcept {
return m_dataStart == other.m_dataStart &&
m_itemOffset == other.m_itemOffset &&
m_itemSize == other.m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::operator!=(const Ptr<T, size_t, minOffset> &other) const {
constexpr bool Ptr<T, size_t, minOffset>::operator!=(const Ptr<T, size_t, minOffset> &other) const noexcept {
return m_dataStart != other.m_dataStart ||
m_itemOffset != other.m_itemOffset ||
m_itemSize != other.m_itemSize;
@ -197,33 +198,33 @@ inline bool Ptr<T, size_t, minOffset>::operator!=(const Ptr<T, size_t, minOffset
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) const {
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) const noexcept {
return Ptr<SubT, size_t, sizeof(T)>(get(), this->size(), offset, size);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const {
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
oxTrace("ox::fs::Ptr::subPtr") << m_itemOffset << this->size() << offset << m_itemSize << (m_itemSize - offset);
return subPtr<SubT>(offset, m_itemSize - offset);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) {
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) noexcept {
return Ptr<SubT, size_t, sizeof(T)>(get(), this->size(), offset, size);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) {
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
oxTrace("ox::fs::Ptr::subPtr") << m_itemOffset << this->size() << offset << m_itemSize << (m_itemSize - offset);
return subPtr<SubT>(offset, m_itemSize - offset);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, minOffset> Ptr<T, size_t, minOffset>::to() const {
constexpr const Ptr<SubT, size_t, minOffset> Ptr<T, size_t, minOffset>::to() const noexcept {
return Ptr<SubT, size_t, minOffset>(m_dataStart, m_dataSize, m_itemOffset, m_itemSize);
}