124 lines
2.6 KiB
C++
124 lines
2.6 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/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 OxError(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;
|
|
oxIgnoreError(model(&tnc, t));
|
|
return tnc.name;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr int getTypeVersion(const T *t) noexcept {
|
|
TypeInfoCatcher tnc;
|
|
oxIgnoreError(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:
|
|
oxReturnError(write(writer, "M2;"));
|
|
break;
|
|
case ClawFormat::Organic:
|
|
oxReturnError(write(writer, "O1;"));
|
|
break;
|
|
default:
|
|
return OxError(1);
|
|
}
|
|
oxReturnError(write(writer, detail::getTypeName(t)));
|
|
oxReturnError(writer.put(';'));
|
|
const auto tn = detail::getTypeVersion(t);
|
|
if (tn > -1) {
|
|
oxReturnError(ox::writeItoa(tn, writer));
|
|
}
|
|
oxReturnError(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);
|
|
oxReturnError(detail::writeClawHeader(bw, &t, fmt));
|
|
#ifdef OX_USE_STDLIB
|
|
if (fmt == ClawFormat::Metal) {
|
|
oxReturnError(writeMC(bw, t));
|
|
} else if (fmt == ClawFormat::Organic) {
|
|
oxRequire(data, writeOC(t));
|
|
oxReturnError(bw.write(data.data(), data.size()));
|
|
}
|
|
#else
|
|
if (fmt != ClawFormat::Metal) {
|
|
return OxError(1, "OC is not supported in this build");
|
|
}
|
|
oxReturnError(writeMC(bw, t));
|
|
#endif
|
|
out.resize(bw.tellp());
|
|
return out;
|
|
}
|
|
|
|
}
|