/* * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #pragma once #include #include #include #include #include #include #include "unionsizecatcher.hpp" namespace ox { template [[nodiscard]] constexpr std::size_t alignOf(const T &t) noexcept; template [[nodiscard]] constexpr std::size_t sizeOf(const T *t) noexcept; template class SizeCatcher: public ModelHandlerBase> { private: std::size_t m_size = 0; public: constexpr explicit SizeCatcher() noexcept = default; template constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, const Vector& = {}, int = ModelFieldCount_v) noexcept {} template constexpr ox::Error field(const char*, UnionView) noexcept; template constexpr ox::Error field(const char*, const T *val) noexcept; template constexpr ox::Error field(const char*, const T **val, std::size_t cnt) noexcept; [[nodiscard]] constexpr auto size() const noexcept { return m_size; } [[nodiscard]] static constexpr auto opType() noexcept { return ox::OpType::Reflect; } private: constexpr void pad(const auto *val) noexcept; }; template template constexpr ox::Error SizeCatcher::field(const char*, const UnionView val) noexcept { pad(val.get()); UnionSizeCatcher sc; oxReturnError(model(sc.interface(), val.get())); m_size += sc.size(); return {}; } template template constexpr ox::Error SizeCatcher::field(const char*, const T *val) noexcept { pad(val); m_size += sizeOf(val); return {}; } template template constexpr ox::Error SizeCatcher::field(const char*, const T **val, std::size_t cnt) noexcept { for (std::size_t i = 0; i < cnt; ++i) { oxReturnError(field("", &val[i])); } return {}; } template constexpr void SizeCatcher::pad(const auto *val) noexcept { const auto padding = m_size - m_size % alignOf(*val); m_size += padding; } template [[nodiscard]] constexpr std::size_t sizeOf(const T *t) noexcept { if constexpr(ox::is_integral_v) { return sizeof(T); } else if constexpr(ox::is_pointer_v) { return sizeof(PlatSpec::PtrType); } else { SizeCatcher sc; const auto err = model(sc.interface(), t); oxAssert(err, "Could not get size of type"); return sc.size(); } } }