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