nostalgia/deps/ox/src/ox/preloader/sizecatcher.hpp

110 lines
2.8 KiB
C++

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