110 lines
2.8 KiB
C++
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();
|
|
}
|
|
}
|
|
|
|
}
|