[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 TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
ox::BString<32> name; ox::BString<32> name;
std::size_t begin = 0; uint64_t begin = 0;
std::size_t size = 0; uint64_t size = 0;
int rows = 1; int rows = 1;
int columns = 1; int columns = 1;
ox::Vector<SubSheet> subsheets; 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) { if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
return err; return err;
} }
oxReturnError(convert(buff, T::TypeName, T::TypeVersion, &obj)); oxReturnError(convert<T>(buff, &obj));
} }
return obj; return obj;
}; };

View File

@ -30,9 +30,8 @@ struct NostalgiaPaletteToPaletteConverter: public Converter<NostalgiaPalette, Pa
} }
}; };
template<typename Src> struct TileSheetToCompactTileSheetConverter: public Converter<TileSheet, CompactTileSheet> {
struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> { ox::Error convert(TileSheet *src, CompactTileSheet *dst) noexcept final {
ox::Error convert(Src *src, CompactTileSheet *dst) noexcept final {
dst->bpp = src->bpp; dst->bpp = src->bpp;
dst->defaultPalette = std::move(src->defaultPalette); dst->defaultPalette = std::move(src->defaultPalette);
dst->pixels = std::move(src->pixels); dst->pixels = std::move(src->pixels);
@ -42,11 +41,10 @@ struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
static const auto converters = [] { 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 NostalgiaGraphicToTileSheetConverter());
converters.emplace_back(new NostalgiaPaletteToPaletteConverter()); converters.emplace_back(new NostalgiaPaletteToPaletteConverter());
converters.emplace_back(new ToCompactTileSheetConverter<NostalgiaGraphic>()); converters.emplace_back(new TileSheetToCompactTileSheetConverter());
converters.emplace_back(new ToCompactTileSheetConverter<TileSheet>());
return converters; return converters;
}(); }();
@ -59,11 +57,25 @@ static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, con
return OxError(1, "Could not find converter"); 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(hdr, ox::readClawHeader(srcBuffer));
oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion)); auto [c, err] = findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
return c->convertRaw(srcBuffer, dstObj); 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 #endif
} }

View File

@ -17,14 +17,42 @@ namespace nostalgia::core {
struct BaseConverter { struct BaseConverter {
virtual ~BaseConverter() noexcept = default; 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 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::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> template<typename SrcType, typename DstType>
struct Converter: public BaseConverter{ 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 return srcTypeName == SrcType::TypeName
&& dstTypeName == DstType::TypeName && dstTypeName == DstType::TypeName
&& srcTypeVersion == SrcType::TypeVersion && srcTypeVersion == SrcType::TypeVersion
@ -40,26 +68,26 @@ struct Converter: public BaseConverter{
auto dst = static_cast<DstType*>(pV2); auto dst = static_cast<DstType*>(pV2);
return convert(&src, dst); 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; 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::Error convert(const ox::Buffer &srcBuffer, T *dstObj) noexcept {
return convert((srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
}
template<typename T> template<typename T>
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
T dstObj; return convert(srcBuffer, T::TypeName, T::TypeVersion, fmt);
oxReturnError(convert(srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
return ox::writeClaw(&dstObj, fmt);
} }
template<typename T> template<typename T>
ox::Error convert(ox::Buffer *buff) noexcept { ox::Error convert(const ox::Buffer &buff, T *outObj) noexcept {
return convert<T>(*buff).moveTo(buff); 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 // load file
oxRequireM(buff, dest->read(filePath.c_str())); oxRequireM(buff, dest->read(filePath.c_str()));
if (filePath.endsWith(".ng")) { if (filePath.endsWith(".ng")) {
oxReturnError(core::convert<core::CompactTileSheet>(&buff)); oxReturnError(core::convert<core::CompactTileSheet>(buff).moveTo(&buff));
} }
// do transformations // do transformations
oxReturnError(pathToInode(buff).moveTo(&buff)); oxReturnError(pathToInode(buff).moveTo(&buff));