Compare commits
7 Commits
15bc41dd35
...
dd16577b50
Author | SHA1 | Date | |
---|---|---|---|
dd16577b50 | |||
c0aa119155 | |||
3c9ce4436a | |||
2a692fc46e | |||
e543131f0d | |||
c085c50b30 | |||
bb8fb0469a |
@ -96,12 +96,12 @@ class FileAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Result<const char*> getPath() const noexcept {
|
constexpr Result<ox::StringView> getPath() const noexcept {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FileAddressType::Path:
|
case FileAddressType::Path:
|
||||||
return m_data.path;
|
return ox::StringView(m_data.path);
|
||||||
case FileAddressType::ConstPath:
|
case FileAddressType::ConstPath:
|
||||||
return m_data.constPath;
|
return ox::StringView(m_data.constPath);
|
||||||
default:
|
default:
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
9
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
9
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
|
#include <ox/std/span.hpp>
|
||||||
|
|
||||||
#include <ox/fs/filestore/filestoretemplate.hpp>
|
#include <ox/fs/filestore/filestoretemplate.hpp>
|
||||||
#include <ox/fs/filesystem/filelocation.hpp>
|
#include <ox/fs/filesystem/filelocation.hpp>
|
||||||
@ -66,10 +67,18 @@ class FileSystem {
|
|||||||
return writeFilePath(path, buffer, size, FileType::NormalFile);
|
return writeFilePath(path, buffer, size, FileType::NormalFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error write(CRStringView path, ox::Span<char> const&buff) noexcept {
|
||||||
|
return write(path, buff.data(), buff.size(), FileType::NormalFile);
|
||||||
|
}
|
||||||
|
|
||||||
Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept {
|
Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept {
|
||||||
return write(inode, buffer, size, FileType::NormalFile);
|
return write(inode, buffer, size, FileType::NormalFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept {
|
||||||
|
return write(inode, buff.data(), buff.size(), FileType::NormalFile);
|
||||||
|
}
|
||||||
|
|
||||||
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
||||||
|
|
||||||
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
|
@ -188,7 +188,7 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
|
|||||||
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
|
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
|
||||||
const auto pathLen = ox_strlen(path);
|
const auto pathLen = ox_strlen(path);
|
||||||
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
|
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
|
||||||
path = path.substr(1);
|
path = substr(path, 1);
|
||||||
}
|
}
|
||||||
return {path.data(), path.bytes()};
|
return {path.data(), path.bytes()};
|
||||||
}
|
}
|
||||||
|
5
deps/ox/src/ox/std/span.hpp
vendored
5
deps/ox/src/ox/std/span.hpp
vendored
@ -214,6 +214,11 @@ class Span {
|
|||||||
return m_items[i];
|
return m_items[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto data() const noexcept {
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr std::size_t size() const noexcept {
|
constexpr std::size_t size() const noexcept {
|
||||||
return m_size;
|
return m_size;
|
||||||
|
@ -46,9 +46,9 @@ static void clearUuidMap(Context *ctx) noexcept {
|
|||||||
ctx->pathToUuid.clear();
|
ctx->pathToUuid.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void createUuidMapping(Context *ctx, const ox::String &filePath, const ox::UUID &uuid) noexcept {
|
void createUuidMapping(Context *ctx, ox::String filePath, const ox::UUID &uuid) noexcept {
|
||||||
ctx->pathToUuid[filePath] = uuid;
|
ctx->pathToUuid[filePath] = uuid;
|
||||||
ctx->uuidToPath[uuid.toString()] = filePath;
|
ctx->uuidToPath[uuid.toString()] = std::move(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error buildUuidMap(Context *ctx, ox::CRStringView path) noexcept {
|
static ox::Error buildUuidMap(Context *ctx, ox::CRStringView path) noexcept {
|
||||||
@ -78,6 +78,41 @@ ox::Error buildUuidMap(Context *ctx) noexcept {
|
|||||||
return buildUuidMap(ctx, "");
|
return buildUuidMap(ctx, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
|
||||||
|
#ifndef OX_BARE_METAL
|
||||||
|
return ctx.pathToUuid[path];
|
||||||
|
#else
|
||||||
|
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept {
|
||||||
|
#ifndef OX_BARE_METAL
|
||||||
|
return ctx.uuidToPath[uuid];
|
||||||
|
#else
|
||||||
|
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
|
||||||
|
#ifndef OX_BARE_METAL
|
||||||
|
return ctx.uuidToPath[uuid.toString()];
|
||||||
|
#else
|
||||||
|
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
||||||
|
#ifndef OX_BARE_METAL
|
||||||
|
for (auto tr : ctx.packTransforms) {
|
||||||
|
oxReturnError(tr(&ctx, &clawData));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
#else
|
||||||
|
return OxError(1, "Transformations not supported on this platform");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -91,10 +91,16 @@ ox::Result<keel::AssetRef<T>> readObjNoCache(
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void createUuidMapping(Context *ctx, const ox::String &filePath, const ox::UUID &uuid) noexcept;
|
void createUuidMapping(Context *ctx, ox::String filePath, const ox::UUID &uuid) noexcept;
|
||||||
|
|
||||||
ox::Error buildUuidMap(Context *ctx) noexcept;
|
ox::Error buildUuidMap(Context *ctx) noexcept;
|
||||||
|
|
||||||
|
ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<AssetRef<T>> setAsset(keel::Context *ctx, ox::StringView assetId, T const&asset) noexcept {
|
ox::Result<AssetRef<T>> setAsset(keel::Context *ctx, ox::StringView assetId, T const&asset) noexcept {
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/model/modelvalue.hpp>
|
#include <ox/model/modelvalue.hpp>
|
||||||
#include <ox/std/utility.hpp>
|
|
||||||
|
|
||||||
#include <keel/media.hpp>
|
#include <keel/media.hpp>
|
||||||
|
|
||||||
@ -13,8 +12,8 @@
|
|||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
static ox::Error pathToInode(
|
static ox::Error pathToInode(
|
||||||
[[maybe_unused]] keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
keel::Context &ctx, ox::FileSystem &dest, ox::ModelObject &obj) noexcept {
|
||||||
auto &o = *obj;
|
auto &o = obj;
|
||||||
auto type = static_cast<ox::FileAddressType>(o["type"].get<int8_t>());
|
auto type = static_cast<ox::FileAddressType>(o["type"].get<int8_t>());
|
||||||
auto &data = o["data"].get<ox::ModelUnion>();
|
auto &data = o["data"].get<ox::ModelUnion>();
|
||||||
ox::String path;
|
ox::String path;
|
||||||
@ -30,35 +29,39 @@ static ox::Error pathToInode(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (beginsWith(path, "uuid://")) {
|
if (beginsWith(path, "uuid://")) {
|
||||||
#ifndef OX_BARE_METAL
|
const auto uuid = substr<ox::StringView>(path, 7);
|
||||||
const auto uuid = substr(ox::StringView(path), 7);
|
oxReturnError(keel::uuidToPath(ctx, uuid).moveTo(&path));
|
||||||
path = ctx->uuidToPath[uuid];
|
|
||||||
#else
|
|
||||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
oxRequire(s, dest->stat(path));
|
oxRequire(s, dest.stat(path));
|
||||||
oxReturnError(o["type"].set(static_cast<int8_t>(ox::FileAddressType::Inode)));
|
oxReturnError(o["type"].set(static_cast<int8_t>(ox::FileAddressType::Inode)));
|
||||||
return data.set(2, s.inode);
|
return data.set(2, s.inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error transformFileAddressesObj(keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept;
|
static ox::Error transformFileAddressesObj(
|
||||||
static ox::Error transformFileAddressesVec(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept;
|
keel::Context &ctx, ox::FileSystem &dest, ox::ModelObject &obj) noexcept;
|
||||||
|
static ox::Error transformFileAddressesVec(
|
||||||
|
keel::Context &ctx, ox::FileSystem &dest, ox::ModelValueVector &v) noexcept;
|
||||||
|
|
||||||
static ox::Error transformFileAddresses(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValue *v) noexcept {
|
static ox::Error transformFileAddresses(
|
||||||
if (v->type() == ox::ModelValue::Type::Object) {
|
keel::Context &ctx,
|
||||||
auto &obj = v->get<ox::ModelObject>();
|
ox::FileSystem &dest,
|
||||||
return transformFileAddressesObj(ctx, dest, &obj);
|
ox::ModelValue &v) noexcept {
|
||||||
} else if (v->type() == ox::ModelValue::Type::Vector) {
|
if (v.type() == ox::ModelValue::Type::Object) {
|
||||||
auto &vec = v->get<ox::ModelValueVector>();
|
auto &obj = v.get<ox::ModelObject>();
|
||||||
return transformFileAddressesVec(ctx, dest, &vec);
|
return transformFileAddressesObj(ctx, dest, obj);
|
||||||
|
} else if (v.type() == ox::ModelValue::Type::Vector) {
|
||||||
|
auto &vec = v.get<ox::ModelValueVector>();
|
||||||
|
return transformFileAddressesVec(ctx, dest, vec);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error transformFileAddressesVec(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept {
|
static ox::Error transformFileAddressesVec(
|
||||||
for (auto &f : *v) {
|
keel::Context &ctx,
|
||||||
oxReturnError(transformFileAddresses(ctx, dest, &f));
|
ox::FileSystem &dest,
|
||||||
|
ox::ModelValueVector &v) noexcept {
|
||||||
|
for (auto &f : v) {
|
||||||
|
oxReturnError(transformFileAddresses(ctx, dest, f));
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -67,51 +70,52 @@ static ox::Error transformFileAddressesVec(keel::Context *ctx, ox::FileSystem *d
|
|||||||
* Convert path references in Claw data to inodes to save space
|
* Convert path references in Claw data to inodes to save space
|
||||||
* @return error
|
* @return error
|
||||||
*/
|
*/
|
||||||
static ox::Error transformFileAddressesObj(keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
static ox::Error transformFileAddressesObj(
|
||||||
if (obj->typeName() == "net.drinkingtea.ox.FileAddress" && obj->typeVersion() == 1) {
|
keel::Context &ctx,
|
||||||
|
ox::FileSystem &dest,
|
||||||
|
ox::ModelObject &obj) noexcept {
|
||||||
|
if (obj.typeName() == "net.drinkingtea.ox.FileAddress" && obj.typeVersion() == 1) {
|
||||||
return pathToInode(ctx, dest, obj);
|
return pathToInode(ctx, dest, obj);
|
||||||
}
|
}
|
||||||
for (auto &f : *obj) {
|
for (auto &f : obj) {
|
||||||
auto &v = f->value;
|
auto &v = f->value;
|
||||||
oxReturnError(transformFileAddresses(ctx, dest, &v));
|
oxReturnError(transformFileAddresses(ctx, dest, v));
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error doTransformations(
|
static ox::Error doTransformations(
|
||||||
[[maybe_unused]] keel::Context *ctx,
|
keel::Context &ctx,
|
||||||
[[maybe_unused]] ox::TypeStore *ts,
|
ox::TypeStore &ts,
|
||||||
[[maybe_unused]] ox::FileSystem *dest,
|
ox::FileSystem &dest,
|
||||||
[[maybe_unused]] ox::CRStringView filePath) noexcept {
|
ox::CRStringView filePath) noexcept {
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
// load file
|
// load file
|
||||||
oxRequire(s, dest->stat(filePath));
|
oxRequire(s, dest.stat(filePath));
|
||||||
// do transformations
|
// do transformations
|
||||||
oxRequireM(buff, dest->read(s.inode));
|
oxRequireM(buff, dest.read(s.inode));
|
||||||
for (auto tr : ctx->packTransforms) {
|
oxReturnError(keel::performPackTransforms(ctx, buff));
|
||||||
oxReturnError(tr(ctx, &buff));
|
|
||||||
}
|
|
||||||
// transform FileAddresses
|
// transform FileAddresses
|
||||||
oxRequireM(obj, keel::readAsset(ts, buff));
|
oxRequireM(obj, keel::readAsset(&ts, buff));
|
||||||
oxReturnError(transformFileAddressesObj(ctx, dest, &obj));
|
oxReturnError(transformFileAddressesObj(ctx, dest, obj));
|
||||||
oxReturnError(ox::writeClaw(obj).moveTo(&buff));
|
oxReturnError(ox::writeClaw(obj).moveTo(&buff));
|
||||||
// write file to dest
|
// write file to dest
|
||||||
oxReturnError(dest->write(s.inode, buff.data(), buff.size()));
|
oxReturnError(dest.write(s.inode, buff));
|
||||||
return {};
|
return {};
|
||||||
#else
|
|
||||||
return OxError(1, "Transformations not supported on this platform");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// claw file transformations are broken out from copy because path to inode
|
// claw file transformations are broken out from copy because path to inode
|
||||||
// transformations need to be done after the copy to the new FS is complete
|
// transformations need to be done after the copy to the new FS is complete
|
||||||
static ox::Error transformClaw(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept {
|
static ox::Error transformClaw(
|
||||||
|
keel::Context &ctx,
|
||||||
|
ox::TypeStore &ts,
|
||||||
|
ox::FileSystem &dest,
|
||||||
|
ox::CRStringView path) noexcept {
|
||||||
// copy
|
// copy
|
||||||
oxTracef("pack.transformClaw", "path: {}", path);
|
oxTracef("pack.transformClaw", "path: {}", path);
|
||||||
oxRequire(fileList, dest->ls(path));
|
oxRequire(fileList, dest.ls(path));
|
||||||
for (const auto &name : fileList) {
|
for (const auto &name : fileList) {
|
||||||
const auto filePath = ox::sfmt("{}{}", path, name);
|
const auto filePath = ox::sfmt("{}{}", path, name);
|
||||||
oxRequire(stat, dest->stat(filePath));
|
oxRequire(stat, dest.stat(filePath));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||||
oxReturnError(transformClaw(ctx, ts, dest, dir));
|
oxReturnError(transformClaw(ctx, ts, dest, dir));
|
||||||
@ -122,61 +126,51 @@ static ox::Error transformClaw(keel::Context *ctx, ox::TypeStore *ts, ox::FileSy
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error verifyFile(ox::FileSystem *fs, ox::CRStringView path, const ox::Buffer &expected) noexcept {
|
static ox::Error verifyFile(
|
||||||
|
ox::FileSystem &fs,
|
||||||
|
ox::CRStringView path,
|
||||||
|
const ox::Buffer &expected) noexcept {
|
||||||
ox::Buffer buff(expected.size());
|
ox::Buffer buff(expected.size());
|
||||||
oxReturnError(fs->read(path, buff.data(), buff.size()));
|
oxReturnError(fs.read(path, buff.data(), buff.size()));
|
||||||
return OxError(buff == expected ? 0 : 1);
|
return OxError(buff == expected ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VerificationPair {
|
static ox::Error copy(
|
||||||
ox::String path;
|
ox::FileSystem &src,
|
||||||
ox::Buffer buff;
|
ox::FileSystem &dest,
|
||||||
VerificationPair(ox::String &&pPath, ox::Buffer &&pBuff) noexcept:
|
ox::CRStringView path) noexcept {
|
||||||
path(ox::forward<ox::String>(pPath)),
|
|
||||||
buff(ox::forward<ox::Buffer>(pBuff)) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringView path, ox::Vector<VerificationPair> *verificationPairs) noexcept {
|
|
||||||
oxOutf("copying directory: {}\n", path);
|
oxOutf("copying directory: {}\n", path);
|
||||||
// copy
|
// copy
|
||||||
oxRequire(fileList, src->ls(path));
|
oxRequire(fileList, src.ls(path));
|
||||||
for (const auto &name : fileList) {
|
for (const auto &name : fileList) {
|
||||||
auto currentFile = ox::sfmt("{}{}", path, name);
|
auto currentFile = ox::sfmt("{}{}", path, name);
|
||||||
if (beginsWith(name, ".")) {
|
if (beginsWith(name, ".")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
oxOutf("reading {}\n", currentFile);
|
oxOutf("reading {}\n", currentFile);
|
||||||
oxRequire(stat, src->stat(currentFile));
|
oxRequire(stat, src.stat(currentFile));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
oxReturnError(dest->mkdir(currentFile, true));
|
oxReturnError(dest.mkdir(currentFile, true));
|
||||||
oxReturnError(copy(src, dest, currentFile + '/', verificationPairs));
|
oxReturnError(copy(src, dest, currentFile + '/'));
|
||||||
} else {
|
} else {
|
||||||
// load file
|
// load file
|
||||||
oxRequireM(buff, src->read(currentFile));
|
oxRequireM(buff, src.read(currentFile));
|
||||||
// write file to dest
|
// write file to dest
|
||||||
oxOutf("writing {}\n", currentFile);
|
oxOutf("writing {}\n", currentFile);
|
||||||
oxReturnError(dest->write(currentFile, buff.data(), buff.size()));
|
oxReturnError(dest.write(currentFile, buff));
|
||||||
oxReturnError(verifyFile(dest, currentFile, buff));
|
oxReturnError(verifyFile(dest, currentFile, buff));
|
||||||
verificationPairs->emplace_back(std::move(currentFile), std::move(buff));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error copyFS(ox::FileSystem *src, ox::FileSystem *dest) noexcept {
|
static ox::Error copyFS(ox::FileSystem &src, ox::FileSystem &dest) noexcept {
|
||||||
ox::Vector<VerificationPair> verificationPairs;
|
oxReturnError(copy(src, dest, "/"));
|
||||||
oxReturnError(copy(src, dest, "/", &verificationPairs));
|
|
||||||
// verify all at once in addition to right after the files are written
|
|
||||||
oxOut("Verifying completed destination\n");
|
|
||||||
for (const auto &v : verificationPairs) {
|
|
||||||
oxReturnError(verifyFile(dest, v.path, v.buff));
|
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept {
|
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept {
|
||||||
oxReturnError(copyFS(ctx->rom.get(), dest));
|
oxReturnError(copyFS(*ctx.rom, dest));
|
||||||
oxOut("Doing transforms\n");
|
oxOut("Doing transforms\n");
|
||||||
oxReturnError(transformClaw(ctx, ts, dest, "/"));
|
oxReturnError(transformClaw(ctx, ts, dest, "/"));
|
||||||
return {};
|
return {};
|
||||||
|
@ -161,6 +161,6 @@ ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, ox::Preloader<PlatSpec
|
|||||||
return detail::preloadDir(ts, src, pl, "/");
|
return detail::preloadDir(ts, src, pl, "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept;
|
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/stringliteral.hpp>
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
constexpr auto TileWidth = 8;
|
constexpr auto TileWidth = 8;
|
||||||
constexpr auto TileHeight = 8;
|
constexpr auto TileHeight = 8;
|
||||||
constexpr auto PixelsPerTile = TileWidth * TileHeight;
|
constexpr auto PixelsPerTile = TileWidth * TileHeight;
|
||||||
|
|
||||||
constexpr auto FileExt_ng = "ng";
|
constexpr ox::StringLiteral FileExt_ng("ng");
|
||||||
constexpr auto FileExt_npal = "npal";
|
constexpr ox::StringLiteral FileExt_npal("npal");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
|||||||
|
|
||||||
ox::Error PaletteEditorImGui::saveItem() noexcept {
|
ox::Error PaletteEditorImGui::saveItem() noexcept {
|
||||||
const auto sctx = applicationData<studio::StudioContext>(*m_ctx);
|
const auto sctx = applicationData<studio::StudioContext>(*m_ctx);
|
||||||
return sctx->project->writeObj(m_itemPath, &m_pal);
|
return sctx->project->writeObj(m_itemPath, m_pal);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,8 @@ namespace nostalgia::core {
|
|||||||
class StudioModule: public studio::Module {
|
class StudioModule: public studio::Module {
|
||||||
ox::Vector<studio::EditorMaker> editors(turbine::Context *ctx) const noexcept final {
|
ox::Vector<studio::EditorMaker> editors(turbine::Context *ctx) const noexcept final {
|
||||||
return {
|
return {
|
||||||
{
|
studio::editorMaker<TileSheetEditorImGui>(ctx, FileExt_ng),
|
||||||
{FileExt_ng},
|
studio::editorMaker<PaletteEditorImGui>(ctx, FileExt_npal),
|
||||||
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
|
||||||
return ox::makeCatch<TileSheetEditorImGui>(ctx, ox::String(path));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{FileExt_npal},
|
|
||||||
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
|
||||||
return ox::makeCatch<PaletteEditorImGui>(ctx, ox::String(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +773,7 @@ void TileSheetEditorModel::ackUpdate() noexcept {
|
|||||||
|
|
||||||
ox::Error TileSheetEditorModel::saveFile() noexcept {
|
ox::Error TileSheetEditorModel::saveFile() noexcept {
|
||||||
const auto sctx = applicationData<studio::StudioContext>(*m_ctx);
|
const auto sctx = applicationData<studio::StudioContext>(*m_ctx);
|
||||||
return sctx->project->writeObj(m_path, &m_img);
|
return sctx->project->writeObj(m_path, m_img);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
||||||
|
@ -49,7 +49,7 @@ void SceneEditorImGui::onActivated() noexcept {
|
|||||||
|
|
||||||
ox::Error SceneEditorImGui::saveItem() noexcept {
|
ox::Error SceneEditorImGui::saveItem() noexcept {
|
||||||
const auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
const auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||||
oxReturnError(sctx->project->writeObj(m_itemPath, &m_editor.scene()));
|
oxReturnError(sctx->project->writeObj(m_itemPath, m_editor.scene()));
|
||||||
oxReturnError(m_ctx.keelCtx.assetManager.setAsset(m_itemPath, m_editor.scene()));
|
oxReturnError(m_ctx.keelCtx.assetManager.setAsset(m_itemPath, m_editor.scene()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ static ox::Error run(const ox::ClArgs &args) noexcept {
|
|||||||
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "nost-pack"));
|
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "nost-pack"));
|
||||||
keel::TypeStore ts(ctx->rom.get(), "/.nostalgia/type_descriptors");
|
keel::TypeStore ts(ctx->rom.get(), "/.nostalgia/type_descriptors");
|
||||||
oxReturnError(generateTypes(&ts));
|
oxReturnError(generateTypes(&ts));
|
||||||
oxReturnError(keel::pack(ctx.get(), &ts, &dst));
|
oxReturnError(keel::pack(*ctx, ts, dst));
|
||||||
oxRequireM(pl, keel::GbaPreloader::make());
|
oxRequireM(pl, keel::GbaPreloader::make());
|
||||||
oxReturnError(preload(&ts, &dst, pl.get()));
|
oxReturnError(preload(&ts, &dst, pl.get()));
|
||||||
oxReturnError(dst.resize());
|
oxReturnError(dst.resize());
|
||||||
|
@ -18,10 +18,10 @@ class ItemMaker {
|
|||||||
const ox::String name;
|
const ox::String name;
|
||||||
const ox::String parentDir;
|
const ox::String parentDir;
|
||||||
const ox::String fileExt;
|
const ox::String fileExt;
|
||||||
constexpr explicit ItemMaker(ox::String pName, ox::String pParentDir, ox::String pFileExt) noexcept:
|
constexpr explicit ItemMaker(ox::String pName, ox::String pParentDir, ox::CRStringView pFileExt) noexcept:
|
||||||
name(std::move(pName)),
|
name(std::move(pName)),
|
||||||
parentDir(std::move(pParentDir)),
|
parentDir(std::move(pParentDir)),
|
||||||
fileExt(std::move(pFileExt)) {
|
fileExt(pFileExt) {
|
||||||
}
|
}
|
||||||
virtual ~ItemMaker() noexcept = default;
|
virtual ~ItemMaker() noexcept = default;
|
||||||
virtual ox::Error write(turbine::Context *ctx, ox::CRStringView pName) const noexcept = 0;
|
virtual ox::Error write(turbine::Context *ctx, ox::CRStringView pName) const noexcept = 0;
|
||||||
@ -33,25 +33,39 @@ class ItemMakerT: public ItemMaker {
|
|||||||
const T item;
|
const T item;
|
||||||
const ox::ClawFormat fmt;
|
const ox::ClawFormat fmt;
|
||||||
public:
|
public:
|
||||||
constexpr explicit ItemMakerT(ox::String pDisplayName, ox::String pParentDir, ox::String fileExt, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept:
|
constexpr explicit ItemMakerT(
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ox::String pDisplayName,
|
||||||
|
ox::String pParentDir,
|
||||||
|
ox::CRStringView fileExt,
|
||||||
|
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept:
|
||||||
|
ItemMaker(std::move(pDisplayName), std::move(pParentDir), fileExt),
|
||||||
fmt(pFmt) {
|
fmt(pFmt) {
|
||||||
}
|
}
|
||||||
constexpr ItemMakerT(ox::String pDisplayName, ox::String pParentDir, ox::String fileExt, const T &pItem, ox::ClawFormat pFmt) noexcept:
|
constexpr ItemMakerT(
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ox::String pDisplayName,
|
||||||
|
ox::String pParentDir,
|
||||||
|
ox::CRStringView fileExt,
|
||||||
|
T pItem,
|
||||||
|
ox::ClawFormat pFmt) noexcept:
|
||||||
|
ItemMaker(std::move(pDisplayName), std::move(pParentDir), fileExt),
|
||||||
item(pItem),
|
item(pItem),
|
||||||
fmt(pFmt) {
|
fmt(pFmt) {
|
||||||
}
|
}
|
||||||
constexpr ItemMakerT(ox::String pDisplayName, ox::String pParentDir, T &&pItem, ox::ClawFormat pFmt) noexcept:
|
constexpr ItemMakerT(
|
||||||
ItemMaker(std::move(pDisplayName), std::move(pParentDir), std::move(fileExt)),
|
ox::String pDisplayName,
|
||||||
item(std::forward(pItem)),
|
ox::String pParentDir,
|
||||||
|
ox::CRStringView fileExt,
|
||||||
|
T &&pItem,
|
||||||
|
ox::ClawFormat pFmt) noexcept:
|
||||||
|
ItemMaker(std::move(pDisplayName), std::move(pParentDir), fileExt),
|
||||||
|
item(std::move(pItem)),
|
||||||
fmt(pFmt) {
|
fmt(pFmt) {
|
||||||
}
|
}
|
||||||
ox::Error write(turbine::Context *ctx, ox::CRStringView pName) const noexcept override {
|
ox::Error write(turbine::Context *ctx, ox::CRStringView pName) const noexcept override {
|
||||||
const auto path = ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
|
const auto path = ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
|
||||||
auto sctx = turbine::applicationData<studio::StudioContext>(*ctx);
|
auto sctx = turbine::applicationData<studio::StudioContext>(*ctx);
|
||||||
keel::createUuidMapping(&ctx->keelCtx, path, ox::UUID::generate().unwrap());
|
keel::createUuidMapping(&ctx->keelCtx, path, ox::UUID::generate().unwrap());
|
||||||
return sctx->project->writeObj(path, &item, fmt);
|
return sctx->project->writeObj(path, item, fmt);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,4 +33,26 @@ class Module {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Editor>
|
||||||
|
[[nodiscard]]
|
||||||
|
studio::EditorMaker editorMaker(turbine::Context *ctx, ox::CRStringView ext) noexcept {
|
||||||
|
return {
|
||||||
|
{ox::String(ext)},
|
||||||
|
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
||||||
|
return ox::makeCatch<Editor>(ctx, ox::String(path));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Editor>
|
||||||
|
[[nodiscard]]
|
||||||
|
studio::EditorMaker editorMaker(turbine::Context *ctx, ox::Vector<ox::String> exts) noexcept {
|
||||||
|
return {
|
||||||
|
std::move(exts),
|
||||||
|
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
||||||
|
return ox::makeCatch<Editor>(ctx, ox::String(path));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
|
|||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
private:
|
private:
|
||||||
keel::Context *m_ctx = nullptr;
|
keel::Context &m_ctx;
|
||||||
ox::String m_path;
|
ox::String m_path;
|
||||||
ox::String m_projectDataDir;
|
ox::String m_projectDataDir;
|
||||||
mutable keel::TypeStore m_typeStore;
|
mutable keel::TypeStore m_typeStore;
|
||||||
@ -60,12 +60,12 @@ class Project {
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error writeObj(
|
ox::Error writeObj(
|
||||||
const ox::StringView &path,
|
ox::CRStringView path,
|
||||||
const T *obj,
|
T const&obj,
|
||||||
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
|
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> loadObj(const ox::StringView &path) const noexcept;
|
ox::Result<T> loadObj(ox::CRStringView path) const noexcept;
|
||||||
|
|
||||||
ox::Result<ox::FileStat> stat(ox::CRStringView path) const noexcept;
|
ox::Result<ox::FileStat> stat(ox::CRStringView path) const noexcept;
|
||||||
|
|
||||||
@ -83,9 +83,9 @@ class Project {
|
|||||||
|
|
||||||
void indexFile(ox::CRStringView path) noexcept;
|
void indexFile(ox::CRStringView path) noexcept;
|
||||||
|
|
||||||
ox::Error writeBuff(const ox::StringView &path, const ox::Buffer &buff) noexcept;
|
ox::Error writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexcept;
|
||||||
|
|
||||||
ox::Result<ox::Buffer> loadBuff(const ox::StringView &path) const noexcept;
|
ox::Result<ox::Buffer> loadBuff(ox::CRStringView path) const noexcept;
|
||||||
|
|
||||||
ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept;
|
ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept;
|
||||||
|
|
||||||
@ -105,14 +105,14 @@ class Project {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error Project::writeObj(const ox::StringView &path, const T *obj, ox::ClawFormat fmt) noexcept {
|
ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat fmt) noexcept {
|
||||||
// write MetalClaw
|
// write MetalClaw
|
||||||
oxRequireM(buff, ox::writeClaw(*obj, fmt));
|
oxRequireM(buff, ox::writeClaw(obj, fmt));
|
||||||
// write to FS
|
// write to FS
|
||||||
oxReturnError(writeBuff(path, buff));
|
oxReturnError(writeBuff(path, buff));
|
||||||
// write type descriptor
|
// write type descriptor
|
||||||
if (m_typeStore.get<T>().error) {
|
if (m_typeStore.get<T>().error) {
|
||||||
oxReturnError(ox::buildTypeDef(&m_typeStore, obj));
|
oxReturnError(ox::buildTypeDef(&m_typeStore, &obj));
|
||||||
}
|
}
|
||||||
// write out type store
|
// write out type store
|
||||||
const auto descPath = ox::sfmt("/.{}/type_descriptors", m_projectDataDir);
|
const auto descPath = ox::sfmt("/.{}/type_descriptors", m_projectDataDir);
|
||||||
@ -125,13 +125,13 @@ ox::Error Project::writeObj(const ox::StringView &path, const T *obj, ox::ClawFo
|
|||||||
const auto typePath = ox::sfmt("/{}/{}", descPath, buildTypeId(*t));
|
const auto typePath = ox::sfmt("/{}/{}", descPath, buildTypeId(*t));
|
||||||
oxReturnError(writeBuff(typePath, typeOut));
|
oxReturnError(writeBuff(typePath, typeOut));
|
||||||
}
|
}
|
||||||
oxReturnError(keel::setAsset(m_ctx, path, *obj));
|
oxReturnError(keel::setAsset(&m_ctx, path, obj));
|
||||||
fileUpdated.emit(path);
|
fileUpdated.emit(path);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> Project::loadObj(const ox::StringView &path) const noexcept {
|
ox::Result<T> Project::loadObj(ox::CRStringView path) const noexcept {
|
||||||
oxRequire(buff, loadBuff(path));
|
oxRequire(buff, loadBuff(path));
|
||||||
if constexpr (ox::is_same_v<T, ox::ModelObject>) {
|
if constexpr (ox::is_same_v<T, ox::ModelObject>) {
|
||||||
return keel::readAsset(&m_typeStore, buff);
|
return keel::readAsset(&m_typeStore, buff);
|
||||||
@ -151,7 +151,7 @@ ox::Error Project::subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&s
|
|||||||
case ProjectEvent::FileRecognized:
|
case ProjectEvent::FileRecognized:
|
||||||
{
|
{
|
||||||
oxRequire(files, listFiles());
|
oxRequire(files, listFiles());
|
||||||
for (const auto &f : files) {
|
for (auto const&f : files) {
|
||||||
slot(f);
|
slot(f);
|
||||||
}
|
}
|
||||||
connect(this, &Project::fileRecognized, tgt, slot);
|
connect(this, &Project::fileRecognized, tgt, slot);
|
||||||
@ -164,7 +164,7 @@ ox::Error Project::subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&s
|
|||||||
connect(this, &Project::fileUpdated, tgt, slot);
|
connect(this, &Project::fileUpdated, tgt, slot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ static void generateTypes(ox::TypeStore *ts) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Project::Project(keel::Context *ctx, ox::String path, ox::CRStringView projectDataDir) noexcept:
|
Project::Project(keel::Context *ctx, ox::String path, ox::CRStringView projectDataDir) noexcept:
|
||||||
m_ctx(ctx),
|
m_ctx(*ctx),
|
||||||
m_path(std::move(path)),
|
m_path(std::move(path)),
|
||||||
m_projectDataDir(projectDataDir),
|
m_projectDataDir(projectDataDir),
|
||||||
m_typeStore(ctx->rom.get(), ox::sfmt("/.{}/type_descriptors", projectDataDir)),
|
m_typeStore(ctx->rom.get(), ox::sfmt("/.{}/type_descriptors", projectDataDir)),
|
||||||
@ -45,7 +45,7 @@ ox::FileSystem *Project::romFs() noexcept {
|
|||||||
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
|
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
|
||||||
oxReturnError(m_fs->mkdir(path, true));
|
oxReturnError(m_fs->mkdir(path, true));
|
||||||
fileUpdated.emit(path);
|
fileUpdated.emit(path);
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
|
ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
|
||||||
@ -83,12 +83,12 @@ void Project::indexFile(ox::CRStringView path) noexcept {
|
|||||||
m_fileExtFileMap[ext].emplace_back(path);
|
m_fileExtFileMap[ext].emplace_back(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error Project::writeBuff(const ox::StringView &path, const ox::Buffer &buff) noexcept {
|
ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexcept {
|
||||||
constexpr auto HdrSz = 40;
|
constexpr auto HdrSz = 40;
|
||||||
ox::Buffer outBuff;
|
ox::Buffer outBuff;
|
||||||
outBuff.reserve(buff.size() + HdrSz);
|
outBuff.reserve(buff.size() + HdrSz);
|
||||||
ox::BufferWriter writer(&outBuff);
|
ox::BufferWriter writer(&outBuff);
|
||||||
const auto [uuid, err] = m_ctx->pathToUuid.at(path);
|
const auto [uuid, err] = m_ctx.pathToUuid.at(path);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
oxReturnError(keel::writeUuidHeader(writer, *uuid));
|
oxReturnError(keel::writeUuidHeader(writer, *uuid));
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ ox::Error Project::writeBuff(const ox::StringView &path, const ox::Buffer &buff)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::Buffer> Project::loadBuff(const ox::StringView &path) const noexcept {
|
ox::Result<ox::Buffer> Project::loadBuff(ox::CRStringView path) const noexcept {
|
||||||
return m_fs->read(path);
|
return m_fs->read(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView pat
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::Vector<ox::String>> Project::listFiles(ox::CRStringView path) const noexcept {
|
ox::Result<ox::Vector<ox::String>> Project::listFiles(ox::CRStringView path) const noexcept {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user