Files
nostalgia/deps/ox/src/ox/claw/write.hpp
Gary Talent 9f338a7429
All checks were successful
Build / build (push) Successful in 3m18s
[ox] Run liccor
2025-01-08 23:03:05 -06:00

124 lines
2.7 KiB
C++

/*
* Copyright 2015 - 2025 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/mc/write.hpp>
#ifdef OX_USE_STDLIB
#include <ox/oc/write.hpp>
#endif
#include <ox/std/buffer.hpp>
#include <ox/std/string.hpp>
#include <ox/std/stringview.hpp>
#include "format.hpp"
namespace ox {
namespace detail {
struct TypeInfoCatcher {
const char *name = nullptr;
int version = 0;
template<typename T>
constexpr ox::Error setTypeInfo(
const char *pName = T::TypeName,
int pVersion = T::TypeVersion,
const Vector<String>& = {},
std::size_t = 0) noexcept {
this->name = pName;
this->version = pVersion;
return {};
}
constexpr Error field(...) noexcept {
return ox::Error(0);
}
static constexpr auto opType() {
return OpType::Write;
}
};
template<typename T, typename = int>
struct type_version {
static constexpr auto value = -1;
};
template<typename T>
struct type_version<T, decltype((void) T::TypeVersion, -1)> {
static constexpr auto value = T::TypeVersion;
};
template<typename T>
constexpr const char *getTypeName(const T *t) noexcept {
TypeInfoCatcher tnc;
std::ignore = model(&tnc, t);
return tnc.name;
}
template<typename T>
constexpr int getTypeVersion(const T *t) noexcept {
TypeInfoCatcher tnc;
std::ignore = model(&tnc, t);
return tnc.version;
}
template<typename T>
ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept {
switch (fmt) {
case ClawFormat::Metal:
OX_RETURN_ERROR(write(writer, "M2;"));
break;
case ClawFormat::Organic:
OX_RETURN_ERROR(write(writer, "O1;"));
break;
default:
return ox::Error(1);
}
OX_RETURN_ERROR(write(writer, detail::getTypeName(t)));
OX_RETURN_ERROR(writer.put(';'));
const auto tn = detail::getTypeVersion(t);
if (tn > -1) {
OX_RETURN_ERROR(ox::writeItoa(tn, writer));
}
OX_RETURN_ERROR(writer.put(';'));
return {};
}
}
Result<Buffer> writeClaw(
const auto &t,
ClawFormat fmt = ClawFormat::Metal,
std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer out(buffReserveSz);
BufferWriter bw(&out, 0);
OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt));
#ifdef OX_USE_STDLIB
if (fmt == ClawFormat::Metal) {
OX_RETURN_ERROR(writeMC(bw, t));
} else if (fmt == ClawFormat::Organic) {
OX_REQUIRE(data, writeOC(t));
OX_RETURN_ERROR(bw.write(data.data(), data.size()));
}
#else
if (fmt != ClawFormat::Metal) {
return ox::Error(1, "OC is not supported in this build");
}
OX_RETURN_ERROR(writeMC(bw, t));
#endif
out.resize(bw.tellp());
return out;
}
}