Compare commits

...

7 Commits

31 changed files with 294 additions and 335 deletions

View File

@@ -139,7 +139,7 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
TestStruct ts;
oxReturnError(ox::writeClaw(&ts, ox::ClawFormat::Metal));
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal));
return OxError(0);
}
},
@@ -158,12 +158,10 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [buff, err] = ox::writeClaw(&testIn, ox::ClawFormat::Metal);
oxAssert(err, "writeMC failed");
oxAssert(ox::readClaw(buff.data(), buff.size(), &testOut), "readMC failed");
const auto [buff, err] = ox::writeMC(&testIn);
oxAssert(err, "writeClaw failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readClaw failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");

View File

@@ -14,6 +14,7 @@
#endif
#include <ox/std/buffer.hpp>
#include <ox/std/string.hpp>
#include <ox/std/stringview.hpp>
#include "format.hpp"
@@ -27,7 +28,11 @@ struct TypeInfoCatcher {
int version = 0;
template<typename T = void>
constexpr void setTypeInfo(const char *name = T::TypeName, int v = T::TypeVersion, const Vector<String>& = {}, std::size_t = 0) noexcept {
constexpr void setTypeInfo(
const char *name = T::TypeName,
int v = T::TypeVersion,
const Vector<String>& = {},
std::size_t = 0) noexcept {
this->name = name;
this->version = v;
}
@@ -53,57 +58,64 @@ struct type_version<T, decltype((void) T::TypeVersion, -1)> {
};
template<typename T>
constexpr const char *getTypeName(T *t) noexcept {
constexpr const char *getTypeName(const T *t) noexcept {
TypeInfoCatcher tnc;
oxIgnoreError(model(&tnc, t));
return tnc.name;
}
template<typename T>
constexpr int getTypeVersion(T *t) noexcept {
constexpr int getTypeVersion(const T *t) noexcept {
TypeInfoCatcher tnc;
oxIgnoreError(model(&tnc, t));
return tnc.version;
}
template<typename T>
Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
String out;
ox::Error writeClawHeader(Writer_c auto &writer, T *t, ClawFormat fmt) noexcept {
switch (fmt) {
case ClawFormat::Metal:
out += "M2;";
oxReturnError(write(&writer, "M2;"));
break;
case ClawFormat::Organic:
out += "O1;";
oxReturnError(write(&writer, "O1;"));
break;
default:
return OxError(1);
}
out += detail::getTypeName(t);
out += ";";
oxReturnError(write(&writer, detail::getTypeName(t)));
oxReturnError(writer.put(';'));
const auto tn = detail::getTypeVersion(t);
if (tn > -1) {
out += tn;
oxReturnError(ox::itoa(tn, writer));
}
out += ";";
return out;
oxReturnError(writer.put(';'));
return {};
}
}
Result<Buffer> writeClaw(auto *t, ClawFormat fmt = ClawFormat::Metal) {
oxRequire(header, detail::writeClawHeader(t, fmt));
Result<Buffer> writeClaw(
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
oxRequire(data, fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t));
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");
}
oxRequire(data, writeMC(t));
oxReturnError(writeMC(bw, t));
#endif
Buffer out(header.len() + data.size());
memcpy(out.data(), header.data(), header.len());
memcpy(out.data() + header.len(), data.data(), data.size());
out.resize(bw.tellp());
return out;
}

View File

@@ -24,6 +24,8 @@ class FieldBitmapReader {
public:
constexpr FieldBitmapReader(T map, std::size_t maxLen) noexcept;
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept;
constexpr void setFields(int) noexcept;
@@ -41,6 +43,12 @@ constexpr FieldBitmapReader<T>::FieldBitmapReader(T map, std::size_t maxLen) noe
m_mapLen = maxLen;
}
template<typename T>
constexpr auto FieldBitmapReader<T>::setBuffer(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T>
constexpr Result<bool> FieldBitmapReader<T>::get(std::size_t i) const noexcept {
if (i / 8 < m_mapLen) {

View File

@@ -122,8 +122,6 @@ std::map<ox::String, ox::Error(*)()> tests = {
"MetalClawReader",
[] {
// setup for tests
static constexpr size_t buffLen = 1024;
char buff[buffLen];
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
@@ -140,8 +138,9 @@ std::map<ox::String, ox::Error(*)()> tests = {
testIn.Struct.Int = 300;
testIn.Struct.BString = "Test String 2";
// run tests
oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed");
oxAssert(ox::readMC(buff, buffLen, &testOut), "readMC failed");
const auto [buff, err] = ox::writeMC(&testIn);
oxAssert(err, "writeMC failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");

View File

@@ -15,6 +15,7 @@
namespace ox {
template class ModelHandlerInterface<MetalClawWriter>;
template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
}

View File

@@ -27,19 +27,19 @@
namespace ox {
template<Writer_c Writer>
class MetalClawWriter {
private:
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
FieldBitmap m_fieldPresence;
int m_fields = 0;
int m_field = 0;
int m_unionIdx = -1;
std::size_t m_buffIt = 0;
std::size_t m_buffLen = 0;
uint8_t *m_buff = nullptr;
std::size_t m_writerBeginP{};
Writer &m_writer;
public:
constexpr MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx = -1) noexcept;
constexpr explicit MetalClawWriter(Writer &writer, int unionIdx = -1) noexcept;
constexpr ~MetalClawWriter() noexcept = default;
@@ -122,77 +122,81 @@ class MetalClawWriter {
return 0;
}
[[nodiscard]]
constexpr std::size_t size() const noexcept;
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Write;
}
ox::Error finalize() noexcept;
private:
constexpr Error appendInteger(Integer_c auto val) noexcept {
bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val);
if (mi.length < m_buffLen) {
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
fieldSet = true;
ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length);
m_buffIt += mi.length;
} else {
return OxError(MC_BUFFENDED);
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++;
++m_field;
return OxError(0);
}
};
extern template class ModelHandlerInterface<MetalClawWriter>;
extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
constexpr MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
m_fieldPresence(buff, buffLen),
template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx),
m_buffLen(buffLen),
m_buff(buff) {
m_writerBeginP(writer.tellp()),
m_writer(writer) {
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
return appendInteger(*val);
}
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
}
@@ -200,179 +204,155 @@ constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<bool> auto *va
return OxError(0);
}
template<Writer_c Writer>
template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
bool fieldSet = false;
if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto strLen = mc::encodeInteger(val->len());
if (m_buffIt + strLen.length + static_cast<std::size_t>(val->len()) < m_buffLen) {
memcpy(&m_buff[m_buffIt], strLen.data, strLen.length);
m_buffIt += strLen.length;
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length));
// write the string
memcpy(&m_buff[m_buffIt], val->c_str(), static_cast<std::size_t>(val->len()));
m_buffIt += static_cast<std::size_t>(val->len());
oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
}
template<Writer_c Writer>
template<std::size_t L>
constexpr Error MetalClawWriter::field(const char *name, const BString<L> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap());
}
template<Writer_c Writer>
template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
}
template<Writer_c Writer>
template<std::size_t L>
constexpr Error MetalClawWriter::field(const char *name, BString<L> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char *name, BString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap());
}
constexpr Error MetalClawWriter::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
bool fieldSet = false;
if (m_unionIdx == -1 || m_unionIdx == m_field) {
const auto strLen = *val ? ox_strlen(*val) : 0;
// write the length
const auto strLenBuff = mc::encodeInteger(strLen);
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
m_buffIt += strLenBuff.length;
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
// write the string
ox_memcpy(&m_buff[m_buffIt], *val, static_cast<std::size_t>(strLen));
m_buffIt += static_cast<std::size_t>(strLen);
oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen)));
fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
}
constexpr Error MetalClawWriter::fieldCString(const char *name, const char **val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept {
return fieldCString(name, val, {});
}
constexpr Error MetalClawWriter::fieldCString(const char *name, const char *const*val) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept {
return fieldCString(name, val, {});
}
constexpr Error MetalClawWriter::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
bool fieldSet = false;
if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto strLenBuff = mc::encodeInteger(strLen);
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
m_buffIt += strLenBuff.length;
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
// write the string
ox_memcpy(&m_buff[m_buffIt], val, static_cast<std::size_t>(strLen));
m_buffIt += static_cast<std::size_t>(strLen);
oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen)));
fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter::field(const char*, T *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) {
return field(nullptr, val->data(), val->size());
} else {
bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
ModelHandlerInterface<MetalClawWriter> handler{&writer};
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
m_buffIt += writer.m_buffIt;
oxReturnError(writer.finalize());
fieldSet = true;
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return OxError(0);
}
}
template<Writer_c Writer>
template<typename U, bool force>
constexpr Error MetalClawWriter::field(const char*, UnionView<U, force> val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
bool fieldSet = false;
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt, val.idx());
MetalClawWriter<Writer> writer(m_writer, val.idx());
ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get()));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
m_buffIt += writer.m_buffIt;
oxReturnError(writer.finalize());
fieldSet = true;
}
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++;
++m_field;
return OxError(0);
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val, std::size_t len) noexcept {
bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length);
m_buffIt += arrLen.length;
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
handler.setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len));
handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len));
// write the array
for (std::size_t i = 0; i < len; i++) {
oxReturnError(handler.field("", &val[i]));
}
m_buffIt += writer.m_buffIt;
oxReturnError(writer.finalize());
fieldSet = true;
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++;
++m_field;
return OxError(0);
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept {
const auto &keys = val->keys();
const auto len = keys.size();
bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length);
m_buffIt += arrLen.length;
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
// write map
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
// double len for both key and value
handler.setTypeInfo("Map", 0, {}, len * 2);
@@ -386,48 +366,69 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *va
oxRequireM(value, val->at(key));
oxReturnError(handler.field("", value));
}
m_buffIt += writer.m_buffIt;
oxReturnError(writer.finalize());
fieldSet = true;
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++;
++m_field;
return OxError(0);
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter::field(const char *name, HashMap<String, T> *val) noexcept {
constexpr Error MetalClawWriter<Writer>::field(const char *name, HashMap<String, T> *val) noexcept {
return field(name, const_cast<const HashMap<String, T>*>(val));
}
template<Writer_c Writer>
template<typename T>
constexpr void MetalClawWriter::setTypeInfo(const char*, int, const Vector<String>&, std::size_t fields) noexcept {
m_fields = static_cast<int>(fields);
constexpr void MetalClawWriter<Writer>::setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t fields) noexcept {
// TODO: change all setTypeInfo signatures to return Errors
const auto fieldPresenceLen = (fields - 1) / 8 + 1;
oxIgnoreError(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields));
m_buffIt = static_cast<std::size_t>(m_fieldPresence.getMaxLen());
ox_memset(m_buff, 0, m_buffIt);
}
constexpr std::size_t MetalClawWriter::size() const noexcept {
return m_buffIt;
template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end));
return {};
}
Result<Buffer> writeMC(auto *val) noexcept {
Buffer buff(10 * units::MB);
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff.data()), buff.size());
ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val));
buff.resize(writer.size());
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter};
oxReturnError(model(&handler, &val));
oxReturnError(mcWriter.finalize());
return {};
}
Result<Buffer> writeMC(const auto *val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, *val));
buff.resize(bw.tellp());
return buff;
}
Error writeMC(char *buff, std::size_t buffLen, auto *val, std::size_t *sizeOut = nullptr) noexcept {
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff), buffLen);
ModelHandlerInterface handler(&writer);
auto err = model(&handler, val);
Error writeMC(char *buff, std::size_t buffLen, const auto *val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw(buff, buffLen);
oxReturnError(writeMC(bw, *val));
if (sizeOut) {
*sizeOut = writer.size();
*sizeOut = bw.tellp();
}
return err;
return {};
}
}

View File

@@ -79,6 +79,9 @@ constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept {
if constexpr(T::opType() == OpType::Reflect) {
uint32_t st = 0;
oxReturnError(io->field("subscriptType", &st));
} else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt));
} else {
auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt));
@@ -186,6 +189,9 @@ constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept
if constexpr(T::opType() == OpType::Reflect) {
uint8_t pt = 0;
oxReturnError(io->field("primitiveType", &pt));
} else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt));
} else {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt));

View File

@@ -143,9 +143,6 @@ class TypeDescWriter {
[[nodiscard]]
constexpr const DescriptorType *type(const char *val) const noexcept;
[[nodiscard]]
constexpr const DescriptorType *type(SerStr val) const noexcept;
template<std::size_t SmallStrSz>
[[nodiscard]]
constexpr const DescriptorType *type(const BasicString<SmallStrSz>*) const noexcept {
@@ -332,11 +329,6 @@ constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept
return getType(types::String, 0, PT, 0);
}
constexpr const DescriptorType *TypeDescWriter::type(SerStr) const noexcept {
constexpr auto PT = PrimitiveType::String;
return getType(types::String, 0, PT, 0);
}
template<std::size_t sz>
constexpr const DescriptorType *TypeDescWriter::type(const BString<sz>*) const noexcept {
constexpr auto PT = PrimitiveType::String;

View File

@@ -71,10 +71,6 @@ class MemberList {
return OxError(0);
}
constexpr Error field(const char *name, SerStr s) noexcept {
return field(name, s.target());
}
template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = ModelTypeVersion_v<T>,
const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
@@ -131,10 +127,6 @@ class Copier {
return OxError(0);
}
constexpr Error field(const char *name, SerStr s) {
return field(name, s.target());
}
template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
}
@@ -192,10 +184,6 @@ class Mover {
return OxError(0);
}
constexpr Error field(const char *name, SerStr s) noexcept {
return field(name, s.target());
}
template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
}
@@ -260,18 +248,6 @@ class Equals {
}
}
constexpr Error field(const char*, SerStr s) noexcept {
const auto a = s.c_str();
const auto b = *cbit_cast<const char**>(m_other->vars[m_i]);
++m_i;
if (a && b && ox_strcmp(a, b) == 0) {
return OxError(0);
} else {
this->value = false;
return OxError(1);
}
}
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Read;

View File

@@ -157,76 +157,6 @@ constexpr bool isSmartPtr_v<::std::unique_ptr<T>> = true;
#endif
class SerStr {
protected:
int m_cap = 0;
char *m_str = nullptr;
char **m_tgt = nullptr;
public:
template<std::size_t sz>
explicit constexpr SerStr(BString<sz> *str) noexcept {
m_str = str->data();
m_cap = str->cap();
}
constexpr SerStr(char *str, int cap) noexcept {
m_str = str;
m_cap = cap;
}
explicit constexpr SerStr(char **tgt, int cap = -1) noexcept {
m_tgt = tgt;
m_str = const_cast<char*>(*tgt);
m_cap = cap;
}
explicit constexpr SerStr(char *str, char **tgt, int cap = -1) noexcept {
m_tgt = tgt;
m_str = str;
m_cap = cap;
}
template<std::size_t cap>
explicit constexpr SerStr(char (&str)[cap]) noexcept {
m_str = str;
m_cap = cap;
}
[[nodiscard]]
constexpr const char *c_str() const noexcept {
return m_str;
}
[[nodiscard]]
constexpr auto target() const noexcept {
return m_tgt;
}
constexpr char *data(std::size_t sz = 0) noexcept {
if (m_tgt && sz) {
if (!*m_tgt || sz > static_cast<std::size_t>(m_cap)) {
*m_tgt = new char[sz];
m_str = *m_tgt;
m_cap = static_cast<int>(sz);
}
}
return m_str;
}
[[nodiscard]]
constexpr int len() const noexcept {
return static_cast<int>(m_str ? ox_strlen(m_str) : 0);
}
[[nodiscard]]
constexpr int cap() const noexcept {
return m_cap;
}
};
template<typename Union, bool force = false>
class UnionView {

View File

@@ -181,34 +181,6 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
return err;
}
Error OrganicClawReader::field(const char *key, SerStr val) noexcept {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {
if (jv.empty()) {
auto data = val.data();
if (data) {
data[0] = 0;
}
} else if (jv.isString()) {
jv.getString(&begin, &end);
auto strSize = end - begin;
auto data = val.data(static_cast<std::size_t>(strSize) + 1);
if (strSize >= val.cap()) {
err = OxError(1, "String size exceeds capacity of destination");
} else {
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
}
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;

View File

@@ -72,8 +72,6 @@ class OrganicClawReader {
template<std::size_t L>
Error field(const char *key, BString<L> *val) noexcept;
Error field(const char *key, SerStr val) noexcept;
Error fieldCString(const char *key, char *val, std::size_t buffLen) noexcept;
Error fieldCString(const char *key, char **val) noexcept;
@@ -205,7 +203,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L>
Error OrganicClawReader::field(const char *key, BString<L> *val) noexcept {
return field(key, SerStr(val->data(), static_cast<int>(val->cap())));
return fieldCString(key, val->data(), val->cap());
}
// array handler

View File

@@ -132,7 +132,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
TestStruct ts;
return ox::writeOC(&ts).error;
return ox::writeOC(ts).error;
}
},
{
@@ -153,7 +153,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [oc, writeErr] = ox::writeOC(&testIn);
auto [oc, writeErr] = ox::writeOC(testIn);
oxAssert(writeErr, "writeOC failed");
oxOutf("{}\n", oc.data());
auto [testOut, readErr] = ox::readOC<TestStruct>(oc.data());
@@ -205,7 +205,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Struct.String = "Test String 2";
testIn.unionIdx = 1;
testIn.Union.Int = 93;
oxAssert(ox::writeOC(&testIn).moveTo(&dataBuff), "Data generation failed");
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(type.error, "Descriptor write failed");
@@ -254,7 +254,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [oc, ocErr] = ox::writeOC(&testIn);
auto [oc, ocErr] = ox::writeOC(testIn);
oxAssert(ocErr, "Data generation failed");
ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
@@ -332,7 +332,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
}
case ox::PrimitiveType::String: {
ox::Vector<char> v(rdr->stringLength(fieldName) + 1);
oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), static_cast<int>(v.size()))), "Walking model failed.");
oxAssert(rdr->fieldCString(fieldName, v.data(), v.size()), "Walking model failed.");
oxOutf("{}:\tstring:\t{}\n", fieldName, v.data());
break;
}

View File

@@ -18,14 +18,6 @@ OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept:
m_unionIdx(unionIdx) {
}
Error OrganicClawWriter::field(const char *key, SerStr val) noexcept {
if (targetValid() && val.len()) {
value(key) = val.c_str();
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, int len) noexcept {
if (targetValid() && len) {
value(key) = *val;

View File

@@ -24,7 +24,7 @@ namespace ox {
class OrganicClawWriter {
friend Result<Buffer> writeOC(auto *val) noexcept;
friend Result<Buffer> writeOC(auto &val) noexcept;
protected:
Json::Value m_json;
@@ -141,12 +141,20 @@ class OrganicClawWriter {
template<std::size_t L>
Error field(const char *key, const BString<L> *val) noexcept {
return field(key, SerStr(val->data(), val->cap()));
if (targetValid() && val->len()) {
value(key) = val->c_str();
}
++m_fieldIt;
return {};
}
template<std::size_t L>
Error field(const char *key, BString<L> *val) noexcept {
return field(key, SerStr(val->data(), static_cast<int>(val->cap())));
if (targetValid() && val->len()) {
value(key) = val->c_str();
}
++m_fieldIt;
return {};
}
template<std::size_t L>
@@ -163,8 +171,6 @@ class OrganicClawWriter {
return field(key, const_cast<const BasicString<L>*>(val));
}
Error field(const char*, SerStr val) noexcept;
Error fieldCString(const char*, const char *const*val, int len) noexcept;
Error fieldCString(const char *name, char **val, int len) noexcept;
@@ -242,10 +248,10 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
return OxError(0);
}
Result<Buffer> writeOC(auto *val) noexcept {
Result<Buffer> writeOC(auto &val) noexcept {
OrganicClawWriter writer;
ModelHandlerInterface handler(&writer);
oxReturnError(model(&handler, val));
oxReturnError(model(&handler, &val));
Json::StreamWriterBuilder jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json);
Buffer buff(str.size() + 1);

View File

@@ -60,7 +60,7 @@ class BufferWriter {
}
constexpr ox::Error put(char val) noexcept {
if (m_it >= m_buff.size()) [[unlikely]] {
if (m_it >= m_buff.size()) {
m_buff.resize(m_buff.size() + 1);
}
m_buff[m_it] = val;
@@ -98,9 +98,9 @@ class CharBuffWriter {
public:
template<std::size_t sz>
explicit constexpr CharBuffWriter(ox::Array<char, sz> *buff) noexcept:
m_cap(buff->size()),
m_buff(buff->data()) {
explicit constexpr CharBuffWriter(ox::Array<char, sz> &buff) noexcept:
m_cap(buff.size()),
m_buff(buff.data()) {
}
explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) {

View File

@@ -87,7 +87,7 @@ constexpr ox::Error serialize(Writer_c auto *buff, T val) noexcept requires(is_i
template<typename T>
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
ox::Array<char, sizeof(T)> out = {};
CharBuffWriter w(&out);
CharBuffWriter w(out);
oxReturnError(serialize(&w, in));
return out;
};

View File

@@ -280,7 +280,7 @@ using CRStringView = const StringView&;
[[nodiscard]]
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
const auto beginningLen = ox::min(beginning.len(), base.len());
return ox_strncmp(base.data(), beginning, beginningLen) == 0;
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
}
[[nodiscard]]

View File

@@ -12,6 +12,7 @@
#include "math.hpp"
#include "types.hpp"
#include "typetraits.hpp"
#include "writer.hpp"
template<typename T1, typename T2>
constexpr char *ox_strcpy(T1 dest, T2 src) noexcept {
@@ -125,6 +126,42 @@ constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen
return retval;
}
namespace ox {
template<typename Integer>
constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
oxReturnError(writer.put('-'));
++it;
}
while (mod) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
ox::ResizedInt_t<Integer, 64> start = '0';
if (digit >= 10) {
start = 'a';
digit -= 10;
}
oxReturnError(writer.put(static_cast<char>(start + digit)));
++it;
}
}
} else {
// 0 is a special case
oxReturnError(writer.put('0'));
}
return {};
}
}
template<typename Integer, typename T>
constexpr T ox_itoa(Integer v, T str) noexcept {
if (v) {

View File

@@ -11,6 +11,7 @@ add_test("[ox/std] ox_memcmp ABCDEFG != HIJKLMN" StdTest "ABCDEFG != HIJKLMN")
add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" StdTest "HIJKLMN != ABCDEFG")
add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" StdTest "ABCDEFG == ABCDEFG")
add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" StdTest "ABCDEFGHI == ABCDEFG")
add_test("[ox/std] itoa" StdTest "itoa")
add_test("[ox/std] BString" StdTest "BString")
add_test("[ox/std] String" StdTest "String")
add_test("[ox/std] Vector" StdTest "Vector")

View File

@@ -25,6 +25,22 @@ static std::map<ox::String, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"itoa",
[]() {
ox::Array<char, 10> buff;
ox::CharBuffWriter bw(buff);
oxAssert(ox::itoa(5, bw), "ox::itoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("5"));
oxReturnError(bw.seekp(0));
oxAssert(ox::itoa(50, bw), "ox::itoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("50"));
oxReturnError(bw.seekp(0));
oxAssert(ox::itoa(500, bw), "ox::itoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("500"));
return ox::Error{};
}
},
{
"ABCDEFG != HIJKLMN",
[]() {

View File

@@ -66,6 +66,12 @@ class WriterT: public Writer_v {
}
};
/**
* Allocates the specified amount of data at the end of the current write stream.
* @param writer
* @param sz
* @return
*/
constexpr ox::Result<std::size_t> allocate(Writer_c auto *writer, std::size_t sz) noexcept {
const auto p = writer->tellp();
oxReturnError(writer->seekp(0, ios_base::end));

View File

@@ -9,7 +9,7 @@
namespace teagba {
inline auto bgSetSbb(volatile BgCtl *bgCtl, unsigned sbb) noexcept {
*bgCtl = (*bgCtl & ~0b11111'0000'0000u) | (sbb << 8);
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b11111'0000'0000u) | static_cast<BgCtl>(sbb << 8);
}
[[nodiscard]]
@@ -24,7 +24,7 @@ inline auto bgPri(const volatile BgCtl *bgCtl) noexcept {
inline auto bgSetPri(volatile BgCtl *bgCtl, unsigned pri) noexcept {
pri = pri & 0b1;
*bgCtl = (*bgCtl & ~0b1u) | (pri << 0);
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b1u) | static_cast<BgCtl>(pri << 0);
}
[[nodiscard]]
@@ -58,7 +58,7 @@ inline auto bgCbb(const volatile BgCtl *bgCtl) noexcept {
inline auto bgSetCbb(volatile BgCtl *bgCtl, unsigned cbb) noexcept {
cbb = cbb & 0b11;
*bgCtl = (*bgCtl & ~0b1100u) | (cbb << 2);
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b1100u) | static_cast<BgCtl>(cbb << 2);
}
constexpr void iterateBgCtl(auto cb) noexcept {

View File

@@ -10,6 +10,11 @@ add_library(
gfx.cpp
)
if(NOT MSVC)
target_compile_options(TeaGBA PRIVATE -Wsign-conversion)
target_compile_options(TeaGBA PRIVATE -Wconversion)
endif()
target_include_directories(
TeaGBA PUBLIC
../include

View File

@@ -131,7 +131,7 @@ ox::Error writeObj(
const ox::FileAddress &file,
const T &obj,
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
oxRequire(objBuff, ox::writeClaw(&obj, fmt));
oxRequire(objBuff, ox::writeClaw(obj, fmt));
return ctx->rom->write(file, objBuff.data(), objBuff.size());
}

View File

@@ -87,7 +87,7 @@ static ox::Error doTransformations(keel::Context *ctx, ox::TypeStore *ts, ox::Fi
// transform FileAddresses
oxRequireM(obj, keel::readAsset(ts, buff));
oxReturnError(transformFileAddressesObj(ctx, dest, &obj));
oxReturnError(ox::writeClaw(&obj).moveTo(&buff));
oxReturnError(ox::writeClaw(obj).moveTo(&buff));
// write file to dest
oxReturnError(dest->write(s.inode, buff.data(), buff.size()));
return {};

View File

@@ -172,7 +172,7 @@ ox::Result<ox::Buffer> convertBuffToBuff(keel::Context *ctx, const ox::Buffer &s
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
return ox::writeClaw<DstType>(wrapCast<DstType>(out.get()), fmt);
return ox::writeClaw<DstType>(*wrapCast<DstType>(out.get()), fmt);
}
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>

View File

@@ -421,7 +421,7 @@ uint8_t bgStatus(Context *ctx) noexcept {
const auto &gctx = static_cast<GlContext&>(*ctx);
uint8_t out = 0;
for (unsigned i = 0; i < gctx.cbbs.size(); ++i) {
out |= gctx.backgrounds[i].enabled << i;
out |= static_cast<uint8_t>(static_cast<unsigned>(gctx.backgrounds[i].enabled) << i);
}
return out;
}

View File

@@ -48,7 +48,7 @@ ox::Error writeConfig(keel::Context *ctx, ox::CRStringView name, T *data) noexce
oxErrf("Could not create config directory: {}\n", toStr(err));
return err;
}
oxRequireM(buff, ox::writeOC(data));
oxRequireM(buff, ox::writeOC(*data));
buff.back().value = '\n';
if (const auto err = fs.write(path, buff.data(), buff.size())) {
oxErrf("Could not read config file: {}\n", toStr(err));

View File

@@ -59,10 +59,13 @@ class Project {
* Writes a MetalClaw object to the project at the given path.
*/
template<typename T>
ox::Error writeObj(const ox::String &path, const T *obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
ox::Error writeObj(
const ox::StringView &path,
const T *obj,
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
template<typename T>
ox::Result<T> loadObj(const ox::String &path) const noexcept;
ox::Result<T> loadObj(const ox::StringView &path) const noexcept;
ox::Result<ox::FileStat> stat(ox::CRStringView path) const noexcept;
@@ -82,7 +85,7 @@ class Project {
ox::Error writeBuff(const ox::StringView &path, const ox::Buffer &buff) noexcept;
ox::Result<ox::Buffer> loadBuff(const ox::String &path) const noexcept;
ox::Result<ox::Buffer> loadBuff(const ox::StringView &path) const noexcept;
ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept;
@@ -102,9 +105,9 @@ class Project {
};
template<typename T>
ox::Error Project::writeObj(const ox::String &path, const T *obj, ox::ClawFormat fmt) noexcept {
ox::Error Project::writeObj(const ox::StringView &path, const T *obj, ox::ClawFormat fmt) noexcept {
// write MetalClaw
oxRequireM(buff, ox::writeClaw(obj, fmt));
oxRequireM(buff, ox::writeClaw(*obj, fmt));
// write to FS
oxReturnError(writeBuff(path, buff));
// write type descriptor
@@ -115,7 +118,7 @@ ox::Error Project::writeObj(const ox::String &path, const T *obj, ox::ClawFormat
const auto descPath = ox::sfmt("/.{}/type_descriptors", m_projectDataDir);
oxReturnError(mkdir(descPath));
for (const auto &t : m_typeStore.typeList()) {
oxRequireM(typeOut, ox::writeClaw(t, ox::ClawFormat::Organic));
oxRequireM(typeOut, ox::writeClaw(*t, ox::ClawFormat::Organic));
// replace garbage last character with new line
typeOut.back().value = '\n';
// write to FS
@@ -127,7 +130,7 @@ ox::Error Project::writeObj(const ox::String &path, const T *obj, ox::ClawFormat
}
template<typename T>
ox::Result<T> Project::loadObj(const ox::String &path) const noexcept {
ox::Result<T> Project::loadObj(const ox::StringView &path) const noexcept {
oxRequire(buff, loadBuff(path));
if constexpr (ox::is_same_v<T, ox::ModelObject>) {
return keel::readAsset(&m_typeStore, buff);

View File

@@ -104,7 +104,7 @@ ox::Error Project::writeBuff(const ox::StringView &path, const ox::Buffer &buff)
return {};
}
ox::Result<ox::Buffer> Project::loadBuff(const ox::String &path) const noexcept {
ox::Result<ox::Buffer> Project::loadBuff(const ox::StringView &path) const noexcept {
return m_fs->read(path);
}