Files
nostalgia/deps/ox/src/ox/preloader/sizecatcher.hpp
Gary Talent e9a6a09629
All checks were successful
Build / build (push) Successful in 2m20s
[ox] Run liccor
2024-04-21 17:01:48 -05:00

124 lines
3.0 KiB
C++

/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#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>, OpType::Reflect> {
private:
std::size_t m_size = 0;
public:
constexpr explicit SizeCatcher() noexcept = default;
template<typename T>
constexpr ox::Error setTypeInfo(
const char* = T::TypeName,
int = T::TypeVersion) noexcept {
return {};
}
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {};
}
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;
}
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 a = alignOf<PlatSpec>(*val);
const auto excess = m_size % a;
if (excess) {
m_size += a - excess;
}
}
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(typename PlatSpec::PtrType);
} else {
SizeCatcher<PlatSpec> sc;
const auto err = model(sc.interface(), t);
oxAssert(err, "Could not get size of type");
return sc.size();
}
}
}