[nostalgia/core] Add ability to chain converters

This commit is contained in:
Gary Talent 2022-02-18 00:43:13 -06:00
parent 1ceb76ee6d
commit 713f5c4bce
5 changed files with 66 additions and 26 deletions

View File

@ -61,8 +61,8 @@ struct TileSheet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
static constexpr auto TypeVersion = 1;
ox::BString<32> name;
std::size_t begin = 0;
std::size_t size = 0;
uint64_t begin = 0;
uint64_t size = 0;
int rows = 1;
int columns = 1;
ox::Vector<SubSheet> subsheets;

View File

@ -23,7 +23,7 @@ ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
return err;
}
oxReturnError(convert(buff, T::TypeName, T::TypeVersion, &obj));
oxReturnError(convert<T>(buff, &obj));
}
return obj;
};

View File

@ -30,9 +30,8 @@ struct NostalgiaPaletteToPaletteConverter: public Converter<NostalgiaPalette, Pa
}
};
template<typename Src>
struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
ox::Error convert(Src *src, CompactTileSheet *dst) noexcept final {
struct TileSheetToCompactTileSheetConverter: public Converter<TileSheet, CompactTileSheet> {
ox::Error convert(TileSheet *src, CompactTileSheet *dst) noexcept final {
dst->bpp = src->bpp;
dst->defaultPalette = std::move(src->defaultPalette);
dst->pixels = std::move(src->pixels);
@ -42,11 +41,10 @@ struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
#ifndef OX_BARE_METAL
static const auto converters = [] {
ox::Vector<ox::UniquePtr<BaseConverter>, 4> converters;
ox::Vector<ox::UniquePtr<BaseConverter>, 3> converters;
converters.emplace_back(new NostalgiaGraphicToTileSheetConverter());
converters.emplace_back(new NostalgiaPaletteToPaletteConverter());
converters.emplace_back(new ToCompactTileSheetConverter<NostalgiaGraphic>());
converters.emplace_back(new ToCompactTileSheetConverter<TileSheet>());
converters.emplace_back(new TileSheetToCompactTileSheetConverter());
return converters;
}();
@ -59,11 +57,25 @@ static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, con
return OxError(1, "Could not find converter");
};
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept {
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt) noexcept {
oxRequire(hdr, ox::readClawHeader(srcBuffer));
oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion));
return c->convertRaw(srcBuffer, dstObj);
auto [c, err] = findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
if (!err) { // try to chain multiple converters
return c->convertBuffToBuff(srcBuffer);
}
for (const auto &subConverter : converters) {
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
continue;
}
const auto [intermediateBuff, chainErr] =
convert(srcBuffer, subConverter->srcTypeName(), subConverter->srcTypeVersion(), fmt);
if (!chainErr) {
return subConverter->convertBuffToBuff(intermediateBuff, fmt);
}
}
return OxError(1, "Could not convert between types");
}
#endif
}

View File

@ -17,14 +17,42 @@ namespace nostalgia::core {
struct BaseConverter {
virtual ~BaseConverter() noexcept = default;
virtual ox::String srcTypeName() noexcept = 0;
virtual int srcTypeVersion() noexcept = 0;
virtual bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept = 0;
virtual bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0;
virtual bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0;
virtual ox::Error convertRaw(const ox::Buffer &pV1Buff, void *pV2) noexcept = 0;
virtual ox::Result<ox::Buffer> convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt = ox::ClawFormat::Metal) noexcept = 0;
};
template<typename SrcType, typename DstType>
struct Converter: public BaseConverter{
bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept override {
ox::String srcTypeName() noexcept final {
return SrcType::TypeName;
}
int srcTypeVersion() noexcept final {
return SrcType::TypeVersion;
}
bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept final {
return srcTypeName == DstType::TypeName
&& srcTypeVersion == DstType::TypeVersion;
}
bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept final {
return dstTypeName == DstType::TypeName
&& dstTypeVersion == DstType::TypeVersion;
}
bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept final {
return srcTypeName == SrcType::TypeName
&& dstTypeName == DstType::TypeName
&& srcTypeVersion == SrcType::TypeVersion
@ -40,26 +68,26 @@ struct Converter: public BaseConverter{
auto dst = static_cast<DstType*>(pV2);
return convert(&src, dst);
}
ox::Result<ox::Buffer> convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt) noexcept final {
DstType dst;
oxReturnError(convertRaw(srcBuff, &dst));
oxRequireM(out, ox::writeClaw(&dst, dstFmt));
return out;
}
};
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept;
template<typename T>
ox::Error convert(const ox::Buffer &srcBuffer, T *dstObj) noexcept {
return convert((srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
}
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
template<typename T>
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
T dstObj;
oxReturnError(convert(srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
return ox::writeClaw(&dstObj, fmt);
return convert(srcBuffer, T::TypeName, T::TypeVersion, fmt);
}
template<typename T>
ox::Error convert(ox::Buffer *buff) noexcept {
return convert<T>(*buff).moveTo(buff);
ox::Error convert(const ox::Buffer &buff, T *outObj) noexcept {
oxRequireM(outBuff, convert<T>(buff));
return ox::readClaw<T>(outBuff).moveTo(outObj);
}
}

View File

@ -36,7 +36,7 @@ static ox::Error doTransformations(ox::FileSystem *dest, const ox::String &fileP
// load file
oxRequireM(buff, dest->read(filePath.c_str()));
if (filePath.endsWith(".ng")) {
oxReturnError(core::convert<core::CompactTileSheet>(&buff));
oxReturnError(core::convert<core::CompactTileSheet>(buff).moveTo(&buff));
}
// do transformations
oxReturnError(pathToInode(buff).moveTo(&buff));