[nostalgia] Replace C strings with StringViews

This commit is contained in:
Gary Talent 2022-12-31 14:59:17 -06:00
parent ca07dc6152
commit 2c2fce2c5a
17 changed files with 119 additions and 94 deletions

View File

@ -124,8 +124,8 @@ void setBgStatus(Context*, unsigned bg, bool status) noexcept {
// Do NOT rely on Context in the GBA version of this function. // Do NOT rely on Context in the GBA version of this function.
ox::Error initConsole(Context *ctx) noexcept { ox::Error initConsole(Context *ctx) noexcept {
constexpr auto TilesheetAddr = "/TileSheets/Charset.ng"; constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
constexpr auto PaletteAddr = "/Palettes/Charset.npal"; constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
setBgStatus(ctx, 0b0001); setBgStatus(ctx, 0b0001);
if (!ctx) { if (!ctx) {
ctx = new (ox_alloca(sizeof(Context))) Context(); ctx = new (ox_alloca(sizeof(Context))) Context();
@ -174,14 +174,13 @@ ox::Error loadBgTileSheet(Context *ctx,
} }
ox::Error loadSpriteTileSheet(Context *ctx, ox::Error loadSpriteTileSheet(Context *ctx,
unsigned cbb,
const ox::FileAddress &tilesheetAddr, const ox::FileAddress &tilesheetAddr,
const ox::FileAddress &paletteAddr) noexcept { const ox::FileAddress &paletteAddr) noexcept {
oxRequire(tsStat, ctx->rom->stat(tilesheetAddr)); oxRequire(tsStat, ctx->rom->stat(tilesheetAddr));
oxRequire(ts, ctx->rom->directAccess(tilesheetAddr)); oxRequire(ts, ctx->rom->directAccess(tilesheetAddr));
GbaTileMapTarget target; GbaTileMapTarget target;
target.pal.palette = &MEM_SPRITE_PALETTE[cbb]; target.pal.palette = MEM_SPRITE_PALETTE;
target.tileMap = &reinterpret_cast<uint16_t*>(MEM_SPRITE_TILES)[cbb * 512]; target.tileMap = MEM_SPRITE_TILES;
oxReturnError(ox::readMC(ts, tsStat.size, &target)); oxReturnError(ox::readMC(ts, tsStat.size, &target));
// load external palette if available // load external palette if available
if (paletteAddr) { if (paletteAddr) {
@ -261,7 +260,7 @@ void setSprite(Context*,
unsigned flipX) noexcept { unsigned flipX) noexcept {
oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
GbaSpriteAttrUpdate oa; GbaSpriteAttrUpdate oa;
oa.attr0 = static_cast<uint16_t>(y & ox::onMask<uint8_t>(7)) oa.attr0 = static_cast<uint16_t>(y & ox::onMask<uint8_t>(0b111))
| (static_cast<uint16_t>(1) << 10) // enable alpha | (static_cast<uint16_t>(1) << 10) // enable alpha
| (static_cast<uint16_t>(spriteShape) << 14); | (static_cast<uint16_t>(spriteShape) << 14);
oa.attr1 = (static_cast<uint16_t>(x) & ox::onMask<uint8_t>(8)) oa.attr1 = (static_cast<uint16_t>(x) & ox::onMask<uint8_t>(8))

View File

@ -31,6 +31,14 @@ ox::Result<char*> loadRom(const char*) noexcept {
void unloadRom(char*) noexcept { void unloadRom(char*) noexcept {
} }
ox::Result<std::size_t> getPreloadAddr(Context *ctx, ox::CRStringView path) noexcept {
oxRequire(stat, ctx->rom->stat(path));
oxRequire(buff, ctx->rom->directAccess(path));
PreloadPtr p;
oxReturnError(ox::readMC(buff, stat.size, &p));
return p.preloadAddr + ctx->preloadSectionOffset;
}
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept { ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept {
oxRequire(stat, ctx->rom->stat(file)); oxRequire(stat, ctx->rom->stat(file));
oxRequire(buff, ctx->rom->directAccess(file)); oxRequire(buff, ctx->rom->directAccess(file));

View File

@ -515,7 +515,6 @@ ox::Error loadBgTileSheet(Context *ctx, unsigned cbb, const ox::FileAddress &til
const ox::FileAddress &palette = nullptr) noexcept; const ox::FileAddress &palette = nullptr) noexcept;
ox::Error loadSpriteTileSheet(Context *ctx, ox::Error loadSpriteTileSheet(Context *ctx,
unsigned section,
const ox::FileAddress &tilesheetAddr, const ox::FileAddress &tilesheetAddr,
const ox::FileAddress &paletteAddr) noexcept; const ox::FileAddress &paletteAddr) noexcept;

View File

@ -26,9 +26,10 @@ oxModelBegin(PreloadPtr)
oxModelEnd() oxModelEnd()
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept; ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept;
ox::Result<std::size_t> getPreloadAddr(Context *ctx, ox::CRStringView file) noexcept;
template<typename T> template<typename T>
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, ox::Result<AssetRef<T>> readObj([[maybe_unused]] Context *ctx, [[maybe_unused]] ox::CRStringView path,
[[maybe_unused]] bool forceLoad = false) noexcept { [[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
constexpr auto readConvert = [](const ox::Buffer &buff) -> ox::Result<T> { constexpr auto readConvert = [](const ox::Buffer &buff) -> ox::Result<T> {
@ -41,21 +42,36 @@ ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file,
} }
return std::move(obj); return std::move(obj);
}; };
oxRequire(path, file.getPath());
if (forceLoad) { if (forceLoad) {
oxRequire(buff, ctx->rom->read(file)); oxRequire(buff, ctx->rom->read(path));
oxRequire(obj, readConvert(buff)); oxRequire(obj, readConvert(buff));
oxRequire(cached, ctx->assetManager.setAsset(path, obj)); oxRequire(cached, ctx->assetManager.setAsset(path, obj));
return std::move(cached); return std::move(cached);
} else { } else {
auto [cached, err] = ctx->assetManager.getAsset<T>(path); auto [cached, err] = ctx->assetManager.getAsset<T>(path);
if (err) { if (err) {
oxRequire(buff, ctx->rom->read(file)); oxRequire(buff, ctx->rom->read(path));
oxRequire(obj, readConvert(buff)); oxRequire(obj, readConvert(buff));
oxReturnError(ctx->assetManager.setAsset(path, obj).moveTo(&cached)); oxReturnError(ctx->assetManager.setAsset(path, obj).moveTo(&cached));
} }
return std::move(cached); return std::move(cached);
} }
#else
if constexpr(ox::preloadable<T>::value) {
oxRequire(addr, getPreloadAddr(ctx, path));
return AssetRef<T>(reinterpret_cast<const T*>(addr));
} else {
return OxError(1);
}
#endif
}
template<typename T>
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file,
[[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL
oxRequire(path, file.getPath());
return readObj<T>(ctx, ox::StringView(path), forceLoad);
#else #else
if constexpr(ox::preloadable<T>::value) { if constexpr(ox::preloadable<T>::value) {
oxRequire(addr, getPreloadAddr(ctx, file)); oxRequire(addr, getPreloadAddr(ctx, file));

View File

@ -19,7 +19,7 @@ ox::Result<PaletteEditorImGui*> PaletteEditorImGui::make(Context *ctx, const ox:
out->m_itemPath = path; out->m_itemPath = path;
const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset(); const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
out->m_itemName = out->m_itemPath.substr(lastSlash + 1); out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
oxRequire(pal, core::readObj<Palette>(out->m_ctx, out->m_itemPath)); oxRequire(pal, core::readObj<Palette>(out->m_ctx, ox::FileAddress(out->m_itemPath.c_str())));
out->m_pal = *pal; out->m_pal = *pal;
return out.release(); return out.release();
} }

View File

@ -511,7 +511,7 @@ class PaletteChangeCommand: public TileSheetCommand {
m_idx = idx; m_idx = idx;
m_img = img; m_img = img;
m_oldPalette = m_img->defaultPalette; m_oldPalette = m_img->defaultPalette;
m_newPalette = newPalette; m_newPalette = ox::FileAddress(newPalette);
} }
void redo() noexcept final { void redo() noexcept final {
@ -538,7 +538,7 @@ class PaletteChangeCommand: public TileSheetCommand {
TileSheetEditorModel::TileSheetEditorModel(Context *ctx, ox::String path) { TileSheetEditorModel::TileSheetEditorModel(Context *ctx, ox::String path) {
m_ctx = ctx; m_ctx = ctx;
m_path = std::move(path); m_path = std::move(path);
oxRequireT(img, readObj<TileSheet>(ctx, m_path.c_str())); oxRequireT(img, readObj<TileSheet>(ctx, m_path));
m_img = *img; m_img = *img;
if (m_img.defaultPalette) { if (m_img.defaultPalette) {
oxThrowError(readObj<Palette>(ctx, m_img.defaultPalette).moveTo(&m_pal)); oxThrowError(readObj<Palette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
@ -709,7 +709,7 @@ ox::Error TileSheetEditorModel::markUpdatedCmdId(const studio::UndoCommand *cmd)
m_updated = true; m_updated = true;
const auto cmdId = cmd->commandId(); const auto cmdId = cmd->commandId();
if (static_cast<CommandId>(cmdId) == CommandId::PaletteChange) { if (static_cast<CommandId>(cmdId) == CommandId::PaletteChange) {
oxReturnError(readObj<Palette>(m_ctx, m_img.defaultPalette.getPath().value).moveTo(&m_pal)); oxReturnError(readObj<Palette>(m_ctx, ox::StringView(m_img.defaultPalette.getPath().value)).moveTo(&m_pal));
} }
auto tsCmd = dynamic_cast<const TileSheetCommand*>(cmd); auto tsCmd = dynamic_cast<const TileSheetCommand*>(cmd);
auto idx = m_img.validateSubSheetIdx(tsCmd->subsheetIdx()); auto idx = m_img.validateSubSheetIdx(tsCmd->subsheetIdx());

View File

@ -10,20 +10,13 @@
namespace nostalgia::core { namespace nostalgia::core {
ox::Error initConsole(Context *ctx) noexcept { ox::Error initConsole(Context *ctx) noexcept {
constexpr auto TilesheetAddr = "/TileSheets/Charset.ng"; constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
constexpr auto PaletteAddr = "/Palettes/Charset.npal"; constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
setBgStatus(ctx, 0b0001); setBgStatus(ctx, 0b0001);
setBgCbb(ctx, 0, 0); setBgCbb(ctx, 0, 0);
return loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr); return loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr);
} }
ox::Error loadSpriteTileSheet(Context*,
unsigned,
const ox::FileAddress&,
const ox::FileAddress&) noexcept {
return OxError(0);
}
ox::Error loadBgTileSheet(Context *ctx, ox::Error loadBgTileSheet(Context *ctx,
unsigned cbb, unsigned cbb,
const ox::FileAddress &tilesheetPath, const ox::FileAddress &tilesheetPath,
@ -53,6 +46,12 @@ ox::Error loadBgTileSheet(Context *ctx,
return OxError(0); return OxError(0);
} }
ox::Error loadSpriteTileSheet(Context*,
const ox::FileAddress&,
const ox::FileAddress&) noexcept {
return OxError(0);
}
void puts(Context *ctx, int column, int row, const char *str) noexcept { void puts(Context *ctx, int column, int row, const char *str) noexcept {
for (int i = 0; str[i]; ++i) { for (int i = 0; str[i]; ++i) {
setTile(ctx, 0, column + i, row, static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])])); setTile(ctx, 0, column + i, row, static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])]));

View File

@ -42,15 +42,15 @@ static void keyEventHandler(core::Context *ctx, core::Key key, bool down) noexce
} }
ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept { ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
oxTraceInitHook();
oxRequireM(ctx, core::init(std::move(fs))); oxRequireM(ctx, core::init(std::move(fs)));
constexpr auto TileSheetAddr = "/TileSheets/Charset.ng"; constexpr ox::FileAddress TileSheetAddr("/TileSheets/Charset.ng");
constexpr auto PaletteAddr = "/Palettes/Charset.npal"; constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
oxRequire(tsStat, ctx->rom->stat(PaletteAddr)); oxRequire(tsStat, ctx->rom->stat(PaletteAddr));
oxReturnError(core::loadSpriteTileSheet(ctx.get(), 0, TileSheetAddr, PaletteAddr)); oxReturnError(core::loadSpriteTileSheet(ctx.get(), TileSheetAddr, PaletteAddr));
oxReturnError(core::initConsole(ctx.get())); oxReturnError(core::initConsole(ctx.get()));
core::puts(ctx.get(), 10, 9, "DOPENESS!!!"); core::puts(ctx.get(), 10, 9, "DOPENESS!!!");
core::setUpdateHandler(ctx.get(), updateHandler); core::setUpdateHandler(ctx.get(), updateHandler);
core::setKeyEventHandler(ctx.get(), keyEventHandler); core::setKeyEventHandler(ctx.get(), keyEventHandler);
return core::run(ctx.get()); return core::run(ctx.get());
} }

View File

@ -2,6 +2,8 @@
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <algorithm>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "editor.hpp" #include "editor.hpp"
@ -93,6 +95,11 @@ ox::Error BaseEditor::saveItem() noexcept {
return OxError(0); return OxError(0);
} }
ox::StringView BaseEditor::pathToItemName(ox::CRStringView path) noexcept {
const auto lastSlash = std::find(path.rbegin(), path.rend(), '/').offset();
return path.substr(lastSlash + 1);
}
Editor::Editor() noexcept { Editor::Editor() noexcept {
m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges); m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges);
} }

View File

@ -100,10 +100,7 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
return nullptr; return nullptr;
} }
static constexpr auto pathToItemName(ox::CRStringView path) noexcept { static ox::StringView pathToItemName(ox::CRStringView path) noexcept;
const auto lastSlash = std::find(path.rbegin(), path.rend(), '/').offset();
return path.substr(lastSlash + 1);
}
// signals // signals
public: public:

View File

@ -26,21 +26,21 @@ ox::FileSystem *Project::romFs() noexcept {
return m_fs; return m_fs;
} }
ox::Error Project::mkdir(const ox::String &path) const noexcept { ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
oxReturnError(m_fs->mkdir(path.c_str(), true)); oxReturnError(m_fs->mkdir(path, true));
fileUpdated.emit(path); fileUpdated.emit(path);
return OxError(0); return OxError(0);
} }
ox::Result<ox::FileStat> Project::stat(const ox::String &path) const noexcept { ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
return m_fs->stat(path.c_str()); return m_fs->stat(path);
} }
bool Project::exists(const ox::String &path) const noexcept { bool Project::exists(ox::CRStringView path) const noexcept {
return m_fs->stat(path.c_str()).error == 0; return m_fs->stat(path).error == 0;
} }
const ox::Vector<ox::String> &Project::fileList(const char *ext) noexcept { const ox::Vector<ox::String> &Project::fileList(ox::CRStringView ext) noexcept {
return m_fileExtFileMap[ext]; return m_fileExtFileMap[ext];
} }
@ -59,7 +59,7 @@ void Project::buildFileIndex() noexcept {
} }
} }
void Project::indexFile(const ox::String &path) noexcept { void Project::indexFile(ox::CRStringView path) noexcept {
const auto [ext, err] = fileExt(path); const auto [ext, err] = fileExt(path);
if (err) { if (err) {
return; return;
@ -67,9 +67,9 @@ void Project::indexFile(const ox::String &path) noexcept {
m_fileExtFileMap[ext].emplace_back(path); m_fileExtFileMap[ext].emplace_back(path);
} }
ox::Error Project::writeBuff(const ox::String &path, const ox::Buffer &buff) noexcept { ox::Error Project::writeBuff(const ox::StringView &path, const ox::Buffer &buff) noexcept {
const auto newFile = m_fs->stat(path.c_str()).error != 0; const auto newFile = m_fs->stat(path).error != 0;
oxReturnError(m_fs->write(path.c_str(), buff.data(), buff.size())); oxReturnError(m_fs->write(path, buff.data(), buff.size(), ox::FileType::NormalFile));
if (newFile) { if (newFile) {
fileAdded.emit(path); fileAdded.emit(path);
indexFile(path); indexFile(path);
@ -80,17 +80,17 @@ ox::Error Project::writeBuff(const ox::String &path, const ox::Buffer &buff) noe
} }
ox::Result<ox::Buffer> Project::loadBuff(const ox::String &path) const noexcept { ox::Result<ox::Buffer> Project::loadBuff(const ox::String &path) const noexcept {
return m_fs->read(path.c_str()); return m_fs->read(path);
} }
ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, const ox::String &path) const noexcept { ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept {
oxRequire(files, m_fs->ls(path.c_str())); oxRequire(files, m_fs->ls(path));
for (const auto &name : files) { for (const auto &name : files) {
const auto fullPath = path + "/" + name.c_str(); auto fullPath = ox::sfmt("{}/{}", path, name);
oxRequire(stat, m_fs->stat(fullPath.c_str())); oxRequire(stat, m_fs->stat(ox::StringView(fullPath)));
switch (stat.fileType) { switch (stat.fileType) {
case ox::FileType::NormalFile: case ox::FileType::NormalFile:
paths->push_back(fullPath); paths->emplace_back(std::move(fullPath));
break; break;
case ox::FileType::Directory: case ox::FileType::Directory:
oxReturnError(lsProcDir(paths, fullPath)); oxReturnError(lsProcDir(paths, fullPath));
@ -102,7 +102,7 @@ ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, const ox::String &pa
return OxError(0); return OxError(0);
} }
ox::Result<ox::Vector<ox::String>> Project::listFiles(const ox::String &path) const noexcept { ox::Result<ox::Vector<ox::String>> Project::listFiles(ox::CRStringView path) const noexcept {
ox::Vector<ox::String> paths; ox::Vector<ox::String> paths;
oxReturnError(lsProcDir(&paths, path)); oxReturnError(lsProcDir(&paths, path));
return paths; return paths;

View File

@ -29,7 +29,7 @@ enum class ProjectEvent {
}; };
[[nodiscard]] [[nodiscard]]
constexpr ox::Result<ox::String> fileExt(const ox::String &path) noexcept { constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
const auto extStart = ox::find(path.crbegin(), path.crend(), '.').offset(); const auto extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
if (!extStart) { if (!extStart) {
return OxError(1, "Cannot open a file without valid extension."); return OxError(1, "Cannot open a file without valid extension.");
@ -52,7 +52,7 @@ class NOSTALGIASTUDIO_EXPORT Project {
[[nodiscard]] [[nodiscard]]
ox::FileSystem *romFs() noexcept; ox::FileSystem *romFs() noexcept;
ox::Error mkdir(const ox::String &path) const noexcept; ox::Error mkdir(ox::CRStringView path) const noexcept;
/** /**
* Writes a MetalClaw object to the project at the given path. * Writes a MetalClaw object to the project at the given path.
@ -63,40 +63,40 @@ class NOSTALGIASTUDIO_EXPORT Project {
template<typename T> template<typename T>
ox::Result<T> loadObj(const ox::String &path) const noexcept; ox::Result<T> loadObj(const ox::String &path) const noexcept;
ox::Result<ox::FileStat> stat(const ox::String &path) const noexcept; ox::Result<ox::FileStat> stat(ox::CRStringView path) const noexcept;
[[nodiscard]] [[nodiscard]]
bool exists(const ox::String& path) const noexcept; bool exists(ox::CRStringView path) const noexcept;
template<typename Functor> template<typename Functor>
ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept; ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept;
[[nodiscard]] [[nodiscard]]
const ox::Vector<ox::String> &fileList(const char *ng) noexcept; const ox::Vector<ox::String> &fileList(ox::CRStringView ext) noexcept;
private: private:
void buildFileIndex() noexcept; void buildFileIndex() noexcept;
void indexFile(const ox::String &path) noexcept; void indexFile(ox::CRStringView path) noexcept;
ox::Error writeBuff(const ox::String &path, const ox::Buffer &buff) noexcept; 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::String &path) const noexcept;
ox::Error lsProcDir(ox::Vector<ox::String> *paths, const ox::String &path) const noexcept; ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept;
ox::Result<ox::Vector<ox::String>> listFiles(const ox::String &path = "") const noexcept; ox::Result<ox::Vector<ox::String>> listFiles(ox::CRStringView path = "") const noexcept;
// signals // signals
public: public:
ox::Signal<ox::Error(ProjectEvent, const ox::String&)> fileEvent; ox::Signal<ox::Error(ProjectEvent, const ox::String&)> fileEvent;
ox::Signal<ox::Error(const ox::String&)> fileAdded; ox::Signal<ox::Error(ox::CRStringView)> fileAdded;
// FileRecognized is triggered for all matching files upon a new // FileRecognized is triggered for all matching files upon a new
// subscription to a section of the project and upon the addition of a // subscription to a section of the project and upon the addition of a
// file. // file.
ox::Signal<ox::Error(const ox::String&)> fileRecognized; ox::Signal<ox::Error(ox::StringView)> fileRecognized;
ox::Signal<ox::Error(const ox::String&)> fileDeleted; ox::Signal<ox::Error(ox::StringView)> fileDeleted;
ox::Signal<ox::Error(const ox::String&)> fileUpdated; ox::Signal<ox::Error(ox::StringView)> fileUpdated;
}; };

View File

@ -13,9 +13,9 @@
namespace nostalgia { namespace nostalgia {
static ox::Result<ox::UniquePtr<ProjectTreeModel>> static ox::Result<ox::UniquePtr<ProjectTreeModel>>
buildProjectTreeModel(ProjectExplorer *explorer, const ox::String &name, const ox::String &path, ProjectTreeModel *parent) noexcept { buildProjectTreeModel(ProjectExplorer *explorer, ox::CRStringView name, ox::CRStringView path, ProjectTreeModel *parent) noexcept {
const auto fs = explorer->romFs(); const auto fs = explorer->romFs();
oxRequire(stat, fs->stat(path.c_str())); oxRequire(stat, fs->stat(path));
auto out = ox::make_unique<ProjectTreeModel>(explorer, name, parent); auto out = ox::make_unique<ProjectTreeModel>(explorer, name, parent);
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
oxRequireM(children, fs->ls(path)); oxRequireM(children, fs->ls(path));
@ -58,7 +58,7 @@ void ProjectExplorer::setModel(ox::UniquePtr<ProjectTreeModel> model) noexcept {
m_treeModel = std::move(model); m_treeModel = std::move(model);
} }
ox::Error ProjectExplorer::refreshProjectTreeModel(const ox::String&) noexcept { ox::Error ProjectExplorer::refreshProjectTreeModel(ox::CRStringView) noexcept {
oxRequireM(model, buildProjectTreeModel(this, "Project", "/", nullptr)); oxRequireM(model, buildProjectTreeModel(this, "Project", "/", nullptr));
setModel(std::move(model)); setModel(std::move(model));
return OxError(0); return OxError(0);

View File

@ -23,7 +23,7 @@ class ProjectExplorer: public studio::Widget {
void setModel(ox::UniquePtr<ProjectTreeModel> model) noexcept; void setModel(ox::UniquePtr<ProjectTreeModel> model) noexcept;
ox::Error refreshProjectTreeModel(const ox::String& = {}) noexcept; ox::Error refreshProjectTreeModel(ox::CRStringView = {}) noexcept;
[[nodiscard]] [[nodiscard]]
constexpr ox::FileSystem *romFs() noexcept { constexpr ox::FileSystem *romFs() noexcept {

View File

@ -9,10 +9,10 @@
namespace nostalgia { namespace nostalgia {
ProjectTreeModel::ProjectTreeModel(ProjectExplorer *explorer, const ox::String &name, ProjectTreeModel::ProjectTreeModel(ProjectExplorer *explorer, ox::String name,
ProjectTreeModel *parent) noexcept { ProjectTreeModel *parent) noexcept {
m_explorer = explorer; m_explorer = explorer;
m_name = name; m_name = std::move(name);
m_parent = parent; m_parent = parent;
} }
@ -23,7 +23,7 @@ ProjectTreeModel::ProjectTreeModel(ProjectTreeModel &&other) noexcept {
void ProjectTreeModel::draw(core::Context *ctx) noexcept { void ProjectTreeModel::draw(core::Context *ctx) noexcept {
constexpr auto dirFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; constexpr auto dirFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
if (m_children.size()) { if (!m_children.empty()) {
if (ImGui::TreeNodeEx(m_name.c_str(), dirFlags)) { if (ImGui::TreeNodeEx(m_name.c_str(), dirFlags)) {
for (auto &child : m_children) { for (auto &child : m_children) {
child->draw(ctx); child->draw(ctx);

View File

@ -18,7 +18,7 @@ class ProjectTreeModel {
ox::String m_name; ox::String m_name;
ox::Vector<ox::UniquePtr<ProjectTreeModel>> m_children; ox::Vector<ox::UniquePtr<ProjectTreeModel>> m_children;
public: public:
explicit ProjectTreeModel(class ProjectExplorer *explorer, const ox::String &name, explicit ProjectTreeModel(class ProjectExplorer *explorer, ox::String name,
ProjectTreeModel *parent = nullptr) noexcept; ProjectTreeModel *parent = nullptr) noexcept;
ProjectTreeModel(ProjectTreeModel &&other) noexcept; ProjectTreeModel(ProjectTreeModel &&other) noexcept;

View File

@ -32,7 +32,7 @@ static ox::Error pathToInode(ox::FileSystem *dest, ox::ModelObject *obj) noexcep
case ox::FileAddressType::None: case ox::FileAddressType::None:
return {}; return {};
} }
oxRequire(s, dest->stat(path.c_str())); oxRequire(s, dest->stat(ox::StringView(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);
} }
@ -58,12 +58,12 @@ static ox::Error transformObj(ox::FileSystem *dest, ox::ModelObject *obj) noexce
return {}; return {};
} }
static ox::Error doTransformations(core::TypeStore *ts, ox::FileSystem *dest, ox::CRString filePath) noexcept { static ox::Error doTransformations(core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept {
if (filePath.endsWith(".ng") || filePath.endsWith(".npal")) { if (endsWith(filePath, ".ng") || endsWith(filePath, ".npal")) {
// load file // load file
oxRequire(s, dest->stat(filePath.c_str())); oxRequire(s, dest->stat(filePath));
oxRequireM(buff, dest->read(s.inode)); oxRequireM(buff, dest->read(s.inode));
if (filePath.endsWith(".ng")) { if (endsWith(filePath, ".ng")) {
oxReturnError(core::convertBuffToBuff<core::CompactTileSheet>(buff, ox::ClawFormat::Metal).moveTo(&buff)); oxReturnError(core::convertBuffToBuff<core::CompactTileSheet>(buff, ox::ClawFormat::Metal).moveTo(&buff));
} }
oxRequireM(obj, ox::readClaw(ts, buff)); oxRequireM(obj, ox::readClaw(ts, buff));
@ -78,15 +78,15 @@ static ox::Error doTransformations(core::TypeStore *ts, ox::FileSystem *dest, ox
// claw file transformations are broken out because path to inode // claw file transformations are broken out 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(core::TypeStore *ts, ox::FileSystem *dest, ox::CRString path) noexcept { static ox::Error transformClaw(core::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 = path + name; const auto filePath = ox::sfmt("{}{}", path, name);
oxRequire(stat, dest->stat(filePath.c_str())); oxRequire(stat, dest->stat(filePath));
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
const auto dir = path + name + '/'; const auto dir = ox::sfmt("{}{}/", path, name);
oxReturnError(transformClaw(ts, dest, dir)); oxReturnError(transformClaw(ts, dest, dir));
} else { } else {
oxReturnError(doTransformations(ts, dest, filePath)); oxReturnError(doTransformations(ts, dest, filePath));
@ -95,9 +95,9 @@ static ox::Error transformClaw(core::TypeStore *ts, ox::FileSystem *dest, ox::CR
return {}; return {};
} }
static ox::Error verifyFile(ox::FileSystem *fs, ox::CRString 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.c_str(), buff.data(), buff.size())); oxReturnError(fs->read(path, buff.data(), buff.size()));
return OxError(buff == expected ? 0 : 1); return OxError(buff == expected ? 0 : 1);
} }
@ -110,7 +110,7 @@ struct VerificationPair {
} }
}; };
static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRString path) noexcept { static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringView path) noexcept {
oxOutf("copying directory: {}\n", path); oxOutf("copying directory: {}\n", path);
ox::Vector<VerificationPair> verificationPairs; ox::Vector<VerificationPair> verificationPairs;
// copy // copy
@ -121,16 +121,16 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRString pa
continue; continue;
} }
oxOutf("reading {}\n", currentFile); oxOutf("reading {}\n", currentFile);
oxRequire(stat, src->stat(currentFile.c_str())); oxRequire(stat, src->stat(ox::StringView(currentFile)));
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
oxReturnError(dest->mkdir(currentFile.c_str(), true)); oxReturnError(dest->mkdir(currentFile.c_str(), true));
oxReturnError(copy(src, dest, currentFile + '/')); oxReturnError(copy(src, dest, currentFile + '/'));
} else { } else {
// load file // load file
oxRequireM(buff, src->read(currentFile.c_str())); 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.c_str(), buff.data(), buff.size())); oxReturnError(dest->write(currentFile, buff.data(), buff.size()));
oxReturnError(verifyFile(dest, currentFile, buff)); oxReturnError(verifyFile(dest, currentFile, buff));
verificationPairs.emplace_back(std::move(currentFile), std::move(buff)); verificationPairs.emplace_back(std::move(currentFile), std::move(buff));
} }
@ -143,9 +143,9 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRString pa
} }
// 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 preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRString path) noexcept { static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept {
// load file // load file
oxRequireM(buff, romFs->read(path.c_str())); oxRequireM(buff, romFs->read(path));
oxRequireM(obj, ox::readClaw(ts, buff)); oxRequireM(obj, ox::readClaw(ts, buff));
if (obj.type()->preloadable) { if (obj.type()->preloadable) {
// preload // preload
@ -159,21 +159,21 @@ static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPrelo
// strip the Claw header (it is not needed after preloading) and write back out to dest fs // strip the Claw header (it is not needed after preloading) and write back out to dest fs
oxReturnError(ox::writeMC(&obj).moveTo(&buff)); oxReturnError(ox::writeMC(&obj).moveTo(&buff));
} }
oxReturnError(romFs->write(path.c_str(), buff.data(), buff.size())); oxReturnError(romFs->write(path, buff.data(), buff.size()));
return {}; return {};
} }
// claw file transformations are broken out because path to inode // claw file transformations are broken out 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 preloadDir(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRString path) noexcept { static ox::Error preloadDir(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept {
// copy // copy
oxTracef("pack::preload", "path: {}", path); oxTracef("pack::preload", "path: {}", path);
oxRequire(fileList, romFs->ls(path)); oxRequire(fileList, romFs->ls(path));
for (const auto &name : fileList) { for (const auto &name : fileList) {
const auto filePath = path + name; const auto filePath = ox::sfmt("{}{}", path, name);
oxRequire(stat, romFs->stat(filePath.c_str())); oxRequire(stat, romFs->stat(ox::StringView(filePath)));
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
const auto dir = path + name + '/'; const auto dir = ox::sfmt("{}{}/", path, name);
oxReturnError(preloadDir(ts, romFs, pl, dir)); oxReturnError(preloadDir(ts, romFs, pl, dir));
} else { } else {
oxReturnError(preloadObj(ts, romFs, pl, filePath)); oxReturnError(preloadObj(ts, romFs, pl, filePath));