Compare commits
No commits in common. "d056323679056cd1d75b6dc52a3d948e8f7ec18c" and "dd16577b5059beefd9ad14eed3699654d2bef8f1" have entirely different histories.
d056323679
...
dd16577b50
@ -4,9 +4,10 @@ Checks: '-*,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
-cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-default-arguments,
|
||||
google-explicit-constructor,
|
||||
google-runtime-operator,
|
||||
hicpp-exception-baseclass,
|
||||
hicpp-multiway-paths-covered,
|
||||
@ -52,7 +53,6 @@ readability-uniqueptr-delete-release,
|
||||
readability-use-anyofallof,
|
||||
cert-*,
|
||||
misc-*,
|
||||
-misc-include-cleaner
|
||||
-misc-use-anonymous-namespace,
|
||||
readability-duplicate-include,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
|
@ -1,24 +0,0 @@
|
||||
# This file is a template, and might need editing before it works on your project.
|
||||
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
|
||||
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
|
||||
#
|
||||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/C++.gitlab-ci.yml
|
||||
|
||||
# use the official gcc image, based on debian
|
||||
# can use versions as well, like gcc:5.2
|
||||
# see https://hub.docker.com/_/gcc/
|
||||
|
||||
image: gcc
|
||||
|
||||
build:
|
||||
stage: build
|
||||
variables:
|
||||
OX_NODEBUG: 1
|
||||
before_script:
|
||||
- apt update && apt -y install make cmake ninja-build pkg-config xorg-dev libgtk-3-dev python3 python3-mypy
|
||||
script:
|
||||
- make purge configure-release test install
|
||||
- make purge configure-asan test install
|
@ -65,11 +65,7 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
||||
/usr/local/include
|
||||
)
|
||||
add_subdirectory(deps/glad)
|
||||
set(GLFW_BUILD_EXAMPLES OFF)
|
||||
set(GLFW_BUILD_TESTS OFF)
|
||||
set(GLFW_BUILD_DOCS OFF)
|
||||
add_subdirectory(deps/glfw)
|
||||
add_subdirectory(deps/glutils)
|
||||
add_subdirectory(deps/imgui)
|
||||
add_subdirectory(deps/lodepng)
|
||||
add_subdirectory(deps/nfde)
|
||||
|
12
Makefile
12
Makefile
@ -3,29 +3,29 @@ BUILDCORE_PATH=deps/buildcore
|
||||
include ${BUILDCORE_PATH}/base.mk
|
||||
|
||||
ifeq ($(BC_VAR_OS),darwin)
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}-studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME}-studio
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia-studio.app/Contents/MacOS/nostalgia-studio
|
||||
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
|
||||
else
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}-studio
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia-studio
|
||||
MGBA=mgba-qt
|
||||
endif
|
||||
|
||||
.PHONY: pkg-gba
|
||||
pkg-gba: build
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project
|
||||
.PHONY: run-studio
|
||||
run-studio: build
|
||||
${NOSTALGIA_STUDIO}
|
||||
.PHONY: gba-run
|
||||
gba-run: pkg-gba
|
||||
${MGBA} ${BC_VAR_PROJECT_NAME}.gba
|
||||
${MGBA} nostalgia.gba
|
||||
.PHONY: debug
|
||||
debug: build
|
||||
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project
|
||||
.PHONY: debug-studio
|
||||
debug-studio: build
|
||||
${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO}
|
||||
|
@ -14,7 +14,6 @@ For Debian (and probably other Linux distros, but the package names will
|
||||
probably differ), install the following additional packages:
|
||||
* pkg-config
|
||||
* xorg-dev
|
||||
* libgtk-3-dev
|
||||
|
||||
## Build
|
||||
|
||||
|
2
deps/buildcore/base.mk
vendored
2
deps/buildcore/base.mk
vendored
@ -89,7 +89,7 @@ purge:
|
||||
${BC_CMD_RM_RF} compile_commands.json
|
||||
.PHONY: test
|
||||
test: build
|
||||
${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
|
||||
${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS}
|
||||
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
|
||||
.PHONY: test-verbose
|
||||
test-verbose: build
|
||||
|
10
deps/glutils/CMakeLists.txt
vendored
10
deps/glutils/CMakeLists.txt
vendored
@ -1,10 +0,0 @@
|
||||
project(GlUtils CXX)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
install(
|
||||
DIRECTORY
|
||||
include/glutils
|
||||
DESTINATION
|
||||
include
|
||||
)
|
2
deps/nfde/CMakeLists.txt
vendored
2
deps/nfde/CMakeLists.txt
vendored
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(nativefiledialog-extended)
|
||||
|
||||
if(NOT MSVC)
|
||||
|
18
deps/ox/src/ox/clargs/clargs.cpp
vendored
18
deps/ox/src/ox/clargs/clargs.cpp
vendored
@ -13,7 +13,7 @@ namespace ox {
|
||||
|
||||
ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
|
||||
auto arg = String(args[i]);
|
||||
String arg = args[i];
|
||||
if (arg[0] == '-') {
|
||||
while (arg[0] == '-' && arg.len()) {
|
||||
arg = arg.substr(1);
|
||||
@ -21,7 +21,7 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
m_bools[arg] = true;
|
||||
// parse additional arguments
|
||||
if (i < static_cast<unsigned>(argc) && args[i + 1]) {
|
||||
auto val = String(args[i + 1]);
|
||||
String val = args[i + 1];
|
||||
if (val.len() && val[i] != '-') {
|
||||
if (val == "false") {
|
||||
m_bools[arg] = false;
|
||||
@ -37,32 +37,32 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept {
|
||||
bool ClArgs::getBool(ox::CRString arg, bool defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept {
|
||||
String ClArgs::getString(ox::CRString arg, const char *defaultValue) const noexcept {
|
||||
auto [value, err] = m_strings.at(arg);
|
||||
return !err ? ox::String(std::move(*value)) : ox::String(defaultValue);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {
|
||||
int ClArgs::getInt(ox::CRString arg, int defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
Result<bool> ClArgs::getBool(ox::CRStringView arg) const noexcept {
|
||||
Result<bool> ClArgs::getBool(ox::CRString arg) const noexcept {
|
||||
oxRequire(out, m_bools.at(arg));
|
||||
return *out;
|
||||
}
|
||||
|
||||
Result<String> ClArgs::getString(ox::CRStringView argName) const noexcept {
|
||||
Result<String> ClArgs::getString(ox::CRString argName) const noexcept {
|
||||
oxRequire(out, m_strings.at(argName));
|
||||
return *out;
|
||||
}
|
||||
|
||||
Result<int> ClArgs::getInt(ox::CRStringView arg) const noexcept {
|
||||
Result<int> ClArgs::getInt(ox::CRString arg) const noexcept {
|
||||
oxRequire(out, m_ints.at(arg));
|
||||
return *out;
|
||||
}
|
||||
|
12
deps/ox/src/ox/clargs/clargs.hpp
vendored
12
deps/ox/src/ox/clargs/clargs.hpp
vendored
@ -23,21 +23,21 @@ class ClArgs {
|
||||
ClArgs(int argc, const char **args) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
|
||||
bool getBool(ox::CRString arg, bool defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
String getString(ox::CRStringView argName, const char *defaultValue) const noexcept;
|
||||
String getString(ox::CRString argName, const char *defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;
|
||||
int getInt(ox::CRString arg, int defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
Result<bool> getBool(ox::CRStringView arg) const noexcept;
|
||||
Result<bool> getBool(ox::CRString arg) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
Result<String> getString(ox::CRStringView argName) const noexcept;
|
||||
Result<String> getString(ox::CRString argName) const noexcept;
|
||||
|
||||
Result<int> getInt(ox::CRStringView arg) const noexcept;
|
||||
Result<int> getInt(ox::CRString arg) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
|
20
deps/ox/src/ox/claw/CMakeLists.txt
vendored
20
deps/ox/src/ox/claw/CMakeLists.txt
vendored
@ -16,16 +16,16 @@ target_link_libraries(
|
||||
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
||||
)
|
||||
|
||||
#if(OX_USE_STDLIB)
|
||||
# add_executable(
|
||||
# readclaw
|
||||
# readclaw.cpp
|
||||
# )
|
||||
# target_link_libraries(
|
||||
# readclaw PUBLIC
|
||||
# OxClaw
|
||||
# )
|
||||
#endif()
|
||||
if(OX_USE_STDLIB)
|
||||
add_executable(
|
||||
readclaw
|
||||
readclaw.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
readclaw PUBLIC
|
||||
OxClaw
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS OxClaw
|
||||
LIBRARY DESTINATION lib
|
||||
|
28
deps/ox/src/ox/claw/test/tests.cpp
vendored
28
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -8,7 +8,11 @@
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ox/claw/format.hpp>
|
||||
#include <ox/claw/read.hpp>
|
||||
#include <ox/claw/write.hpp>
|
||||
@ -103,12 +107,12 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ClawHeaderReader",
|
||||
[] {
|
||||
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
|
||||
ox::String hdr = "O1;com.drinkingtea.ox.claw.test.Header;2;";
|
||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
|
||||
@ -120,7 +124,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
"ClawHeaderReader2",
|
||||
[] {
|
||||
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
|
||||
ox::String hdr = "M2;com.drinkingtea.ox.claw.test.Header2;3;";
|
||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
|
||||
@ -188,14 +192,14 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
int retval = -1;
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
retval = static_cast<int>(tests[testName]());
|
||||
} else {
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
|
16
deps/ox/src/ox/event/test/tests.cpp
vendored
16
deps/ox/src/ox/event/test/tests.cpp
vendored
@ -21,7 +21,7 @@ struct TestStruct: public ox::SignalHandler {
|
||||
}
|
||||
};
|
||||
|
||||
std::map<ox::StringView, std::function<ox::Error()>> tests = {
|
||||
std::map<std::string, std::function<ox::Error()>> tests = {
|
||||
{
|
||||
"test1",
|
||||
[] {
|
||||
@ -39,14 +39,12 @@ std::map<ox::StringView, std::function<ox::Error()>> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
if (argc > 1) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -36,6 +36,13 @@ FileAddress::FileAddress(ox::CRStringView path) noexcept {
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
FileAddress::FileAddress(char *path) noexcept {
|
||||
auto pathSize = ox_strlen(path) + 1;
|
||||
m_data.path = new char[pathSize];
|
||||
memcpy(m_data.path, path, pathSize);
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
93
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
93
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
@ -25,7 +25,7 @@ enum class FileAddressType: int8_t {
|
||||
class FileAddress {
|
||||
|
||||
template<typename T>
|
||||
friend constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept;
|
||||
friend constexpr Error model(T*, CommonPtrWith<FileAddress> auto*) noexcept;
|
||||
|
||||
public:
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
|
||||
@ -59,7 +59,13 @@ class FileAddress {
|
||||
|
||||
explicit FileAddress(CRStringView path) noexcept;
|
||||
|
||||
constexpr FileAddress(ox::StringLiteral path) noexcept;
|
||||
template<std::size_t SmallStrSz>
|
||||
explicit FileAddress(const ox::BasicString<SmallStrSz> &path) noexcept: FileAddress(StringView(path)) {
|
||||
}
|
||||
|
||||
explicit FileAddress(char *path) noexcept;
|
||||
|
||||
explicit constexpr FileAddress(const char *path) noexcept;
|
||||
|
||||
constexpr ~FileAddress() noexcept;
|
||||
|
||||
@ -80,6 +86,7 @@ class FileAddress {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<uint64_t> getInode() const noexcept {
|
||||
switch (m_type) {
|
||||
case FileAddressType::Inode:
|
||||
@ -117,8 +124,8 @@ class FileAddress {
|
||||
|
||||
};
|
||||
|
||||
constexpr FileAddress::FileAddress(ox::StringLiteral path) noexcept {
|
||||
m_data.constPath = path.c_str();
|
||||
constexpr FileAddress::FileAddress(const char *path) noexcept {
|
||||
m_data.constPath = path;
|
||||
m_type = FileAddressType::ConstPath;
|
||||
}
|
||||
|
||||
@ -126,6 +133,45 @@ constexpr FileAddress::~FileAddress() noexcept {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
||||
return FileAddress::Data::TypeName;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||
return FileAddress::TypeName;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||
oxReturnError(io->template setTypeInfo<FileAddress::Data>());
|
||||
oxReturnError(io->fieldCString("path", &obj->path));
|
||||
oxReturnError(io->fieldCString("constPath", &obj->path));
|
||||
oxReturnError(io->field("inode", &obj->inode));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
oxReturnError(io->template setTypeInfo<FileAddress>());
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
int8_t type = 0;
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, 0)));
|
||||
} else if constexpr(T::opType() == OpType::Read) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
fa->m_type = static_cast<FileAddressType>(type);
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
} else if constexpr(T::opType() == OpType::Write) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr void FileAddress::cleanup() noexcept {
|
||||
if (m_type == FileAddressType::Path) {
|
||||
safeDeleteArray(m_data.path);
|
||||
@ -138,43 +184,4 @@ constexpr void FileAddress::clear() noexcept {
|
||||
m_type = FileAddressType::None;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
||||
return FileAddress::Data::TypeName;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||
return FileAddress::TypeName;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||
oxReturnError(h->template setTypeInfo<FileAddress::Data>());
|
||||
oxReturnError(h->fieldCString("path", &obj->path));
|
||||
oxReturnError(h->fieldCString("constPath", &obj->path));
|
||||
oxReturnError(h->field("inode", &obj->inode));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
oxReturnError(h->template setTypeInfo<FileAddress>());
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
int8_t type = 0;
|
||||
oxReturnError(h->field("type", &type));
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, 0)));
|
||||
} else if constexpr(T::opType() == OpType::Read) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(h->field("type", &type));
|
||||
fa->m_type = static_cast<FileAddressType>(type);
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
} else if constexpr(T::opType() == OpType::Write) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(h->field("type", &type));
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ PassThroughFS::PassThroughFS(CRStringView dirPath) {
|
||||
PassThroughFS::~PassThroughFS() noexcept = default;
|
||||
|
||||
String PassThroughFS::basePath() const noexcept {
|
||||
return ox::String(m_path.string().c_str());
|
||||
return m_path.string().c_str();
|
||||
}
|
||||
|
||||
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
|
||||
|
65
deps/ox/src/ox/fs/test/tests.cpp
vendored
65
deps/ox/src/ox/fs/test/tests.cpp
vendored
@ -26,11 +26,11 @@ struct OX_PACKED NodeType: public ox::ptrarith::Item<T> {
|
||||
}
|
||||
};
|
||||
|
||||
const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = {
|
||||
const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tests = {
|
||||
{
|
||||
{
|
||||
"PtrArith::setSize",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
using BuffPtr_t = uint32_t;
|
||||
ox::Vector<char> buff(5 * ox::units::MB);
|
||||
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
|
||||
@ -57,8 +57,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::next1",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -69,8 +69,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::next2",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/");
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -80,8 +80,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::next3",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/");
|
||||
[](std::string_view) {
|
||||
ox::String path = "/";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
|
||||
@ -90,8 +90,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::next4",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("usr/share/charset.gbag");
|
||||
[](std::string_view) {
|
||||
ox::String path = "usr/share/charset.gbag";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -102,8 +102,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::next5",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("usr/share/");
|
||||
[](std::string_view) {
|
||||
ox::String path = "usr/share/";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -113,8 +113,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::dirPath",
|
||||
[] (ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
[] (std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.dirPath(buff, path.len()) == 0 && ox_strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||
@ -123,8 +123,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::fileName",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.fileName(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
|
||||
@ -133,7 +133,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"PathIterator::hasNext",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
const auto path = "/file1";
|
||||
ox::PathIterator it(path, ox_strlen(path));
|
||||
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
|
||||
@ -143,7 +143,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"Ptr::subPtr",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
constexpr auto buffLen = 5000;
|
||||
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
|
||||
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
|
||||
@ -155,7 +155,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"NodeBuffer::insert",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
constexpr auto buffLen = 5000;
|
||||
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
||||
oxAssert(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed");
|
||||
@ -168,7 +168,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"FileStore::readWrite",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
constexpr auto buffLen = 5000;
|
||||
constexpr auto str1 = "Hello, World!";
|
||||
constexpr auto str1Len = ox_strlen(str1) + 1;
|
||||
@ -189,7 +189,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"Directory",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
ox::Vector<uint8_t> fsBuff(5000);
|
||||
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
|
||||
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
|
||||
@ -216,7 +216,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
},
|
||||
{
|
||||
"FileSystem",
|
||||
[](ox::StringView) {
|
||||
[](std::string_view) {
|
||||
ox::Vector<uint8_t> fsBuff(5000);
|
||||
oxTrace("ox.fs.test.FileSystem") << "format";
|
||||
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
||||
@ -237,15 +237,16 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 3) {
|
||||
oxError("Must specify test to run and test argument");
|
||||
int retval = -1;
|
||||
if (argc > 1) {
|
||||
std::string_view testName = args[1];
|
||||
std::string_view testArg;
|
||||
if (args[2]) {
|
||||
testArg = args[2];
|
||||
}
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
retval = static_cast<int>(tests.at(testName)(testArg));
|
||||
}
|
||||
}
|
||||
ox::StringView const testName = args[1];
|
||||
ox::StringView const testArg = args[2] ? args[2] : nullptr;
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(testArg), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
|
2
deps/ox/src/ox/fs/tool.cpp
vendored
2
deps/ox/src/ox/fs/tool.cpp
vendored
@ -67,7 +67,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
const auto fsPath = argv[1];
|
||||
ox::String subCmd(argv[2]);
|
||||
ox::String subCmd = argv[2];
|
||||
oxRequire(fs, loadFs(fsPath));
|
||||
if (subCmd == "ls") {
|
||||
return runLs(fs.get(), argc - 2, argv + 2);
|
||||
|
2
deps/ox/src/ox/mc/read.hpp
vendored
2
deps/ox/src/ox/mc/read.hpp
vendored
@ -276,8 +276,8 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
|
||||
val->resize(len);
|
||||
return field(name, val->data(), val->size());
|
||||
}
|
||||
val->resize(0);
|
||||
}
|
||||
val->resize(0);
|
||||
++m_field;
|
||||
return {};
|
||||
} else if constexpr(isArray_v<T>) {
|
||||
|
19
deps/ox/src/ox/mc/test/tests.cpp
vendored
19
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -45,7 +45,7 @@ struct TestStruct {
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String;
|
||||
ox::String String = "";
|
||||
ox::BString<32> BString = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
||||
@ -105,7 +105,7 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"MetalClawWriter",
|
||||
@ -460,14 +460,11 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
89
deps/ox/src/ox/mc/write.hpp
vendored
89
deps/ox/src/ox/mc/write.hpp
vendored
@ -43,30 +43,39 @@ class MetalClawWriter {
|
||||
|
||||
constexpr ~MetalClawWriter() noexcept = default;
|
||||
|
||||
constexpr Error field(const char*, const int8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int64_t *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int64_t> auto *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, const uint8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint64_t *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, const bool *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<bool> auto *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
constexpr Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, const BString<L> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept;
|
||||
@ -75,8 +84,20 @@ class MetalClawWriter {
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val), buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val));
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char*>(val), buffLen);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, const T *val) noexcept;
|
||||
constexpr Error field(const char*, T *val) noexcept;
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
@ -138,47 +159,47 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx)
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
|
||||
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));
|
||||
}
|
||||
@ -209,6 +230,18 @@ constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<std::size_t SmallStringSize>
|
||||
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<Writer>::field(const char *name, BString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
|
||||
bool fieldSet = false;
|
||||
@ -254,7 +287,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const 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 {
|
||||
@ -290,7 +323,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const 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
|
||||
@ -328,7 +361,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
||||
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2));
|
||||
// this loop body needs to be in a lambda because of the potential alloca call
|
||||
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
|
||||
const auto keyLen = key.len();
|
||||
const auto keyLen = ox_strlen(key);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
memcpy(wkey.get(), key.c_str(), keyLen + 1);
|
||||
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
|
||||
@ -348,6 +381,12 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
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 ox::Error MetalClawWriter<Writer>::setTypeInfo(
|
||||
@ -382,7 +421,7 @@ Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||
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));
|
||||
@ -390,7 +429,7 @@ Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB
|
||||
return buff;
|
||||
}
|
||||
|
||||
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
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) {
|
||||
|
4
deps/ox/src/ox/model/descwrite.hpp
vendored
4
deps/ox/src/ox/model/descwrite.hpp
vendored
@ -209,7 +209,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val
|
||||
if (m_type) {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, t->typeName);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
@ -238,7 +238,7 @@ template<typename ...Args>
|
||||
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
|
||||
constexpr auto s = "";
|
||||
const auto t = type(s);
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, t->typeName);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
19
deps/ox/src/ox/model/modelvalue.hpp
vendored
19
deps/ox/src/ox/model/modelvalue.hpp
vendored
@ -144,6 +144,8 @@ class ModelValue {
|
||||
|
||||
constexpr ModelValue(const ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &&other) noexcept;
|
||||
|
||||
template<typename T>
|
||||
@ -348,7 +350,7 @@ class ModelObject {
|
||||
|
||||
constexpr ModelObject(const ModelObject &other) noexcept {
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
@ -425,7 +427,7 @@ class ModelObject {
|
||||
return *this;
|
||||
}
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
@ -448,7 +450,7 @@ class ModelObject {
|
||||
f = val;
|
||||
}
|
||||
|
||||
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
if (m_fields.contains(k)) {
|
||||
return *m_fields.at(k).value;
|
||||
}
|
||||
@ -462,7 +464,7 @@ class ModelObject {
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr auto &operator[](StringView const&k) noexcept {
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
@ -526,7 +528,7 @@ class ModelUnion {
|
||||
public:
|
||||
constexpr ModelUnion(const ModelUnion &other) noexcept {
|
||||
for (auto i = 0; const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{i, ox::String(f->name), f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{i, f->name, f->value});
|
||||
m_fields[field->name] = field.get();
|
||||
++i;
|
||||
}
|
||||
@ -551,7 +553,7 @@ class ModelUnion {
|
||||
return UniquePtr<ModelUnion>(new ModelUnion(other));
|
||||
}
|
||||
|
||||
constexpr auto &operator[](StringView const&k) noexcept {
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
const auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
@ -586,7 +588,7 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
return &(*t)->value;
|
||||
}
|
||||
@ -812,6 +814,9 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &other) noexcept: ModelValue(const_cast<const ModelValue&>(other)) {
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
|
19
deps/ox/src/ox/model/test/tests.cpp
vendored
19
deps/ox/src/ox/model/test/tests.cpp
vendored
@ -32,7 +32,7 @@ constexpr auto getModelTypeVersion(TestType2*) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ModelValue",
|
||||
@ -47,7 +47,6 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"getModelTypeName",
|
||||
[] {
|
||||
@ -56,7 +55,6 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"getModelTypeVersion",
|
||||
[] {
|
||||
@ -69,14 +67,11 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
112
deps/ox/src/ox/oc/test/tests.cpp
vendored
112
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -53,7 +53,7 @@ struct TestStruct {
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String{""};
|
||||
ox::String String = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
@ -124,7 +124,7 @@ constexpr TestStruct &TestStruct::operator=(TestStruct &&other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"OrganicClawWriter",
|
||||
@ -189,53 +189,53 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
},
|
||||
|
||||
{
|
||||
"OrganicClawModelValue",
|
||||
[] {
|
||||
ox::Buffer dataBuff;
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
"OrganicClawModelValue",
|
||||
[] {
|
||||
ox::Buffer dataBuff;
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@ -354,11 +354,13 @@ int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
const auto testName = args[1];
|
||||
ox::Error(*test)();
|
||||
try {
|
||||
test = tests.at(testName);
|
||||
} catch (const std::out_of_range&) {
|
||||
oxErrorf("Test {} not found", testName);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
return static_cast<int>(test());
|
||||
}
|
||||
|
8
deps/ox/src/ox/oc/write.cpp
vendored
8
deps/ox/src/ox/oc/write.cpp
vendored
@ -26,10 +26,18 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val, int len) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), len);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept {
|
||||
const auto uuidStr = uuid->toString();
|
||||
if (targetValid() && uuidStr.len()) {
|
||||
|
54
deps/ox/src/ox/oc/write.hpp
vendored
54
deps/ox/src/ox/oc/write.hpp
vendored
@ -36,7 +36,7 @@ class OrganicClawWriter {
|
||||
|
||||
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char *key, const int8_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -44,7 +44,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const int16_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -52,7 +52,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const int32_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -60,7 +60,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const int64_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -69,7 +69,7 @@ class OrganicClawWriter {
|
||||
}
|
||||
|
||||
|
||||
Error field(const char *key, const uint8_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -77,7 +77,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint16_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -85,7 +85,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint32_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -93,7 +93,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint64_t *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -101,7 +101,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, const bool *val) noexcept {
|
||||
Error field(const char *key, CommonPtrWith<bool> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -109,6 +109,9 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename U, bool force = true>
|
||||
Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
|
||||
@ -131,6 +134,11 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
return field(key, const_cast<const HashMap<String, T>*>(val));
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, const BString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
@ -140,6 +148,15 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, const BasicString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
@ -149,17 +166,23 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BasicString<L> *val) noexcept {
|
||||
return field(key, const_cast<const BasicString<L>*>(val));
|
||||
}
|
||||
|
||||
Error fieldCString(const char*, const char *const*val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, const char *const*val) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val) noexcept;
|
||||
|
||||
Error field(const char *key, const UUID *uuid) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, const T *val) noexcept;
|
||||
Error field(const char*, T *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
@ -177,7 +200,6 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Write;
|
||||
}
|
||||
@ -194,7 +216,7 @@ class OrganicClawWriter {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) noexcept {
|
||||
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
OrganicClawWriter w((Json::Value(Json::arrayValue)));
|
||||
ModelHandlerInterface handler{&w};
|
||||
@ -208,7 +230,7 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
|
||||
Error OrganicClawWriter::field(const char *key, T *val) noexcept {
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(key, val->data(), val->size());
|
||||
} else if (val && targetValid()) {
|
||||
|
217
deps/ox/src/ox/std/basestringview.hpp
vendored
217
deps/ox/src/ox/std/basestringview.hpp
vendored
@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bit.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace ox::detail {
|
||||
|
||||
class BaseStringView {
|
||||
public:
|
||||
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
|
||||
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
|
||||
private:
|
||||
PtrType m_t = nullptr;
|
||||
std::size_t m_offset = 0;
|
||||
std::size_t m_max = 0;
|
||||
|
||||
public:
|
||||
constexpr iterator() noexcept = default;
|
||||
|
||||
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
|
||||
m_t = t;
|
||||
m_offset = offset;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto offset() const noexcept {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
constexpr iterator operator+(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
} else {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto operator-(const iterator &other) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return m_offset + other.m_offset;
|
||||
} else {
|
||||
return m_offset - other.m_offset;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator operator-(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
} else {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator &operator+=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
} else {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator-=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
} else {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator++() noexcept {
|
||||
return operator+=(1);
|
||||
}
|
||||
|
||||
constexpr iterator &operator--() noexcept {
|
||||
return operator-=(1);
|
||||
}
|
||||
|
||||
constexpr RefType operator*() const noexcept {
|
||||
return m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator[](std::size_t s) const noexcept {
|
||||
return m_t[s];
|
||||
}
|
||||
|
||||
constexpr bool operator<(const iterator &other) const noexcept {
|
||||
return m_offset < other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>(const iterator &other) const noexcept {
|
||||
return m_offset > other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const iterator &other) const noexcept {
|
||||
return m_offset <= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const iterator &other) const noexcept {
|
||||
return m_offset >= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator &other) const noexcept {
|
||||
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator &other) const noexcept {
|
||||
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
const char *m_str = nullptr;
|
||||
std::size_t m_len = 0;
|
||||
protected:
|
||||
constexpr BaseStringView() noexcept = default;
|
||||
|
||||
constexpr BaseStringView(BaseStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr explicit BaseStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> begin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> end() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cbegin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cend() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto bytes() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto len() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto *data() const noexcept {
|
||||
return &m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &front() const noexcept {
|
||||
return m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &back() const noexcept {
|
||||
return m_str[m_len - 1];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr void set(const char *str, std::size_t len) noexcept {
|
||||
m_str = str;
|
||||
m_len = len;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
53
deps/ox/src/ox/std/cstringview.hpp
vendored
53
deps/ox/src/ox/std/cstringview.hpp
vendored
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "basestringview.hpp"
|
||||
#include "bstring.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
class CStringView: public detail::BaseStringView {
|
||||
public:
|
||||
constexpr CStringView() noexcept = default;
|
||||
|
||||
constexpr CStringView(CStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
constexpr CStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr CStringView(const char *str) noexcept: BaseStringView(str) {}
|
||||
|
||||
constexpr CStringView(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
|
||||
|
||||
constexpr auto &operator=(CStringView const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
145
deps/ox/src/ox/std/cstrops.hpp
vendored
145
deps/ox/src/ox/std/cstrops.hpp
vendored
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T const&str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 const&str1, T2 const&str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) 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) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
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;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
20
deps/ox/src/ox/std/def.hpp
vendored
20
deps/ox/src/ox/std/def.hpp
vendored
@ -17,9 +17,16 @@
|
||||
#define oxOut(...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", __VA_ARGS__)
|
||||
#define oxErr(...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", __VA_ARGS__)
|
||||
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#ifdef OX_USE_STDLIB
|
||||
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#else
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define oxInfo(...) oxTrace("info", __VA_ARGS__)
|
||||
#define oxInfof(...) oxTracef("info", __VA_ARGS__)
|
||||
@ -28,7 +35,12 @@
|
||||
|
||||
#ifndef OX_NODEBUG
|
||||
#define oxDebug(...) ox::trace::OutStream(__FILE__, __LINE__, "debug", __VA_ARGS__)
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#ifdef OX_USE_STDLIB
|
||||
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#else
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define oxDebug(...) static_assert(false, "Debug prints were checked in.");
|
||||
#define oxDebugf(...) static_assert(false, "Debug prints were checked in.");
|
||||
|
41
deps/ox/src/ox/std/error.hpp
vendored
41
deps/ox/src/ox/std/error.hpp
vendored
@ -138,16 +138,16 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
|
||||
constexpr Result(const Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
|
||||
}
|
||||
|
||||
constexpr Result(const Error &error) noexcept: value(), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(value), error(error) {
|
||||
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(const_cast<type&>(value)), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(std::move(value)), error(error) {
|
||||
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(ox::forward<type>(value)), error(error) {
|
||||
}
|
||||
|
||||
constexpr ~Result() noexcept = default;
|
||||
@ -165,12 +165,12 @@ struct [[nodiscard]] Result {
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
constexpr Error copyTo(type *val) const noexcept {
|
||||
constexpr Error get(type *val) const noexcept {
|
||||
*val = value;
|
||||
return error;
|
||||
}
|
||||
|
||||
constexpr Error copyTo(type *val) noexcept {
|
||||
constexpr Error get(type *val) noexcept {
|
||||
*val = value;
|
||||
return error;
|
||||
}
|
||||
@ -182,48 +182,27 @@ struct [[nodiscard]] Result {
|
||||
return error;
|
||||
}
|
||||
|
||||
constexpr T &unwrap() & noexcept {
|
||||
constexpr auto &unwrap() noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr T &&unwrap() && noexcept {
|
||||
constexpr auto &unwrapThrow() {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return std::move(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr T const&unwrap() const & noexcept {
|
||||
constexpr const auto &unwrap() const noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr T &unwrapThrow() & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr T &&unwrapThrow() && {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
constexpr T const&unwrapThrow() const & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
constexpr ox::Result<U> to(const auto &f) noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
|
2
deps/ox/src/ox/std/fmt.hpp
vendored
2
deps/ox/src/ox/std/fmt.hpp
vendored
@ -186,7 +186,7 @@ constexpr Fmt<segementCnt> fmtSegments(StringView fmt) noexcept {
|
||||
|
||||
template<typename StringType = String, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr StringType sfmt(StringView fmt, Args&&... args) noexcept {
|
||||
constexpr StringType sfmt(StringView fmt, Args... args) noexcept {
|
||||
assert(ox::detail::argCount(fmt) == sizeof...(args));
|
||||
StringType out;
|
||||
const auto fmtSegments = ox::detail::fmtSegments<sizeof...(args)+1>(fmt);
|
||||
|
43
deps/ox/src/ox/std/hashmap.hpp
vendored
43
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -18,11 +18,25 @@ namespace ox {
|
||||
template<typename K, typename T>
|
||||
class HashMap {
|
||||
|
||||
public:
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
|
||||
private:
|
||||
// Maybe StringView. If K (or KK for MaybeSV) is a string type,
|
||||
// MaybeSV::type/MaybeSV_t is a StringView.
|
||||
// This avoids creating unnecessary Strings when taking a StringView or C
|
||||
// string in lookups.
|
||||
template<typename KK, bool isStr = isOxString_v<KK>>
|
||||
struct MaybeSV {
|
||||
using type = KK;
|
||||
};
|
||||
template<typename KK>
|
||||
struct MaybeSV<KK, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename KK>
|
||||
using MaybeSV_t = MaybeSV<KK>::type;
|
||||
|
||||
struct Pair {
|
||||
K key = {};
|
||||
T value{};
|
||||
@ -71,9 +85,15 @@ class HashMap {
|
||||
|
||||
constexpr static uint64_t hash(StringView const&) noexcept;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *const&access(Vector<Pair*> const&pairs, KK const&key) const;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *&access(Vector<Pair*> &pairs, KK const&key);
|
||||
|
||||
@ -104,7 +124,7 @@ constexpr bool HashMap<K, T>::operator==(HashMap const&other) const {
|
||||
if (m_keys != other.m_keys) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < m_keys.size(); ++i) {
|
||||
for (int i = 0; i < m_keys.size(); i++) {
|
||||
auto &k = m_keys[i];
|
||||
if (at(k) != other.at(k)) {
|
||||
return false;
|
||||
@ -174,7 +194,7 @@ constexpr void HashMap<K, T>::erase(MaybeSV_t<K> const&k) {
|
||||
auto h = hash(k) % m_pairs.size();
|
||||
while (true) {
|
||||
const auto &p = m_pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
oxIgnoreError(m_pairs.erase(h));
|
||||
break;
|
||||
} else {
|
||||
@ -212,7 +232,7 @@ template<typename K, typename T>
|
||||
constexpr void HashMap<K, T>::expand() {
|
||||
Vector<Pair*> r;
|
||||
for (std::size_t i = 0; i < m_keys.size(); ++i) {
|
||||
K k{m_keys[i]};
|
||||
auto k = m_keys[i];
|
||||
access(r, k) = std::move(access(m_pairs, k));
|
||||
}
|
||||
m_pairs = std::move(r);
|
||||
@ -244,7 +264,7 @@ constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
const auto &p = pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
@ -258,7 +278,14 @@ constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pa
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
auto &p = pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
bool matches = [&] {
|
||||
if constexpr (is_integral_v<KK>) {
|
||||
return p == nullptr || k == p->key;
|
||||
} else {
|
||||
return p == nullptr || ox_strcmp(p->key, k) == 0;
|
||||
}
|
||||
}();
|
||||
if (matches) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
|
24
deps/ox/src/ox/std/memory.hpp
vendored
24
deps/ox/src/ox/std/memory.hpp
vendored
@ -180,7 +180,7 @@ template<typename T, typename Deleter = DefaultDelete>
|
||||
class UniquePtr {
|
||||
|
||||
private:
|
||||
T *m_t = nullptr;
|
||||
T *m_t;
|
||||
|
||||
public:
|
||||
explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) {
|
||||
@ -190,8 +190,8 @@ class UniquePtr {
|
||||
|
||||
constexpr UniquePtr(const UniquePtr&) = delete;
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr(UniquePtr<U, UDeleter> &&other) noexcept {
|
||||
template<typename U>
|
||||
constexpr UniquePtr(UniquePtr<U> &&other) noexcept {
|
||||
m_t = other.release();
|
||||
}
|
||||
|
||||
@ -210,25 +210,25 @@ class UniquePtr {
|
||||
return m_t;
|
||||
}
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
|
||||
template<typename U>
|
||||
constexpr void reset(UniquePtr<U> &&other = UniquePtr()) {
|
||||
auto t = m_t;
|
||||
m_t = other.release();
|
||||
Deleter()(t);
|
||||
}
|
||||
|
||||
constexpr UniquePtr &operator=(UniquePtr const&other) = delete;
|
||||
constexpr UniquePtr &operator=(const UniquePtr<T> &other) = delete;
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> const&other) = delete;
|
||||
template<typename U>
|
||||
constexpr UniquePtr &operator=(const UniquePtr<U> &other) = delete;
|
||||
|
||||
constexpr UniquePtr &operator=(UniquePtr<T> &&other) noexcept {
|
||||
reset(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> &&other) noexcept {
|
||||
template<typename U>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U> &&other) noexcept {
|
||||
reset(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
@ -247,8 +247,8 @@ class UniquePtr {
|
||||
|
||||
};
|
||||
|
||||
template<typename T, typename Deleter = DefaultDelete>
|
||||
using UPtr = UniquePtr<T, Deleter>;
|
||||
template<typename T>
|
||||
using UPtr = UniquePtr<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept {
|
||||
|
7
deps/ox/src/ox/std/span.hpp
vendored
7
deps/ox/src/ox/std/span.hpp
vendored
@ -25,7 +25,7 @@ class SpanView {
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
|
||||
template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
|
||||
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
|
||||
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
|
||||
|
||||
template<std::size_t sz>
|
||||
@ -103,11 +103,6 @@ class SpanView {
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T const*data() const noexcept {
|
||||
return m_items;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return m_size;
|
||||
|
3
deps/ox/src/ox/std/std.hpp
vendored
3
deps/ox/src/ox/std/std.hpp
vendored
@ -15,8 +15,6 @@
|
||||
#include "bstring.hpp"
|
||||
#include "byteswap.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "cstringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "def.hpp"
|
||||
#include "defer.hpp"
|
||||
#include "defines.hpp"
|
||||
@ -39,7 +37,6 @@
|
||||
#include "stacktrace.hpp"
|
||||
#include "stddef.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strongint.hpp"
|
||||
#include "strops.hpp"
|
||||
|
83
deps/ox/src/ox/std/string.hpp
vendored
83
deps/ox/src/ox/std/string.hpp
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include(<string>)
|
||||
#if defined(OX_USE_STDLIB)
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
@ -32,15 +32,15 @@ class BasicString {
|
||||
|
||||
constexpr explicit BasicString(std::size_t cap) noexcept;
|
||||
|
||||
constexpr explicit BasicString(const char *str) noexcept;
|
||||
constexpr BasicString(const char *str) noexcept;
|
||||
|
||||
constexpr explicit BasicString(const char8_t *str) noexcept;
|
||||
constexpr BasicString(const char8_t *str) noexcept;
|
||||
|
||||
constexpr BasicString(const char *str, std::size_t size) noexcept;
|
||||
|
||||
constexpr explicit BasicString(CRStringView str) noexcept;
|
||||
|
||||
constexpr explicit BasicString(BasicString const&) noexcept;
|
||||
constexpr BasicString(const BasicString&) noexcept;
|
||||
|
||||
constexpr BasicString(BasicString&&) noexcept;
|
||||
|
||||
@ -130,7 +130,7 @@ class BasicString {
|
||||
|
||||
constexpr BasicString &operator+=(StringView src) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(BasicString const&src) noexcept;
|
||||
constexpr BasicString &operator+=(const BasicString &src) noexcept;
|
||||
|
||||
constexpr BasicString operator+(const char *str) const noexcept;
|
||||
|
||||
@ -142,23 +142,23 @@ class BasicString {
|
||||
|
||||
constexpr BasicString operator+(CRStringView src) const noexcept;
|
||||
|
||||
constexpr BasicString operator+(BasicString const&src) const noexcept;
|
||||
constexpr BasicString operator+(const BasicString &src) const noexcept;
|
||||
|
||||
constexpr bool operator==(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator==(OxString_c auto const&other) const noexcept;
|
||||
constexpr bool operator==(const OxString_c auto &other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(OxString_c auto const&other) const noexcept;
|
||||
constexpr bool operator!=(const OxString_c auto &other) const noexcept;
|
||||
|
||||
constexpr bool operator<(BasicString const&other) const noexcept;
|
||||
constexpr bool operator<(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr bool operator>(BasicString const&other) const noexcept;
|
||||
constexpr bool operator>(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr bool operator<=(BasicString const&other) const noexcept;
|
||||
constexpr bool operator<=(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr bool operator>=(BasicString const&other) const noexcept;
|
||||
constexpr bool operator>=(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr char operator[](std::size_t i) const noexcept;
|
||||
|
||||
@ -200,7 +200,7 @@ class BasicString {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
#if __has_include(<string>)
|
||||
#ifdef OX_USE_STDLIB
|
||||
[[nodiscard]]
|
||||
inline std::string toStdString() const {
|
||||
return c_str();
|
||||
@ -225,14 +225,19 @@ class BasicString {
|
||||
constexpr std::size_t bytes() const noexcept;
|
||||
|
||||
private:
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void set(const BasicString<OtherSize> &src) noexcept;
|
||||
|
||||
constexpr void set(CRStringView str) noexcept;
|
||||
|
||||
constexpr void set(const char *str) noexcept;
|
||||
|
||||
constexpr void set(const char8_t *str) noexcept;
|
||||
};
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
|
||||
if (!m_buff.empty()) {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -242,14 +247,14 @@ constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
|
||||
// GCC complains if you don't do this pretty unnecessary size check
|
||||
if (!m_buff.empty()) {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept {
|
||||
if (!m_buff.empty()) {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -259,7 +264,7 @@ constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char8_t *str) noexcept {
|
||||
if (!m_buff.empty()) {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -383,7 +388,7 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(BasicString const&src) noexcept {
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(const BasicString &src) noexcept {
|
||||
oxIgnoreError(append(src.c_str(), src.len()));
|
||||
return *this;
|
||||
}
|
||||
@ -431,7 +436,7 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(BasicString const&src) const noexcept {
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const BasicString &src) const noexcept {
|
||||
const std::size_t strLen = src.len();
|
||||
const auto currentLen = len();
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
@ -454,7 +459,7 @@ constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) con
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(OxString_c auto const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(const OxString_c auto &other) const noexcept {
|
||||
return ox::StringView(*this) == ox::StringView(other);
|
||||
}
|
||||
|
||||
@ -464,27 +469,27 @@ constexpr bool BasicString<SmallStringSize_v>::operator!=(const char *other) con
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(OxString_c auto const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(const OxString_c auto &other) const noexcept {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<(BasicString const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>(BasicString const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<=(BasicString const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<=(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 1;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>=(BasicString const&other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>=(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > -1;
|
||||
}
|
||||
|
||||
@ -538,14 +543,31 @@ constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
|
||||
return length;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const BasicString<OtherSize> &src) noexcept {
|
||||
std::size_t strBytes = src.bytes();
|
||||
m_buff.resize(strBytes);
|
||||
copy_n(src.begin(), strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(CRStringView str) noexcept {
|
||||
std::size_t const strBytes = str.bytes();
|
||||
std::size_t strBytes = str.bytes();
|
||||
m_buff.resize(strBytes + 1);
|
||||
copy_n(str.data(), strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
m_buff.resize(strBytes);
|
||||
copy_n(str, strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
@ -559,13 +581,6 @@ extern template class BasicString<8>;
|
||||
using String = BasicString<8>;
|
||||
using CRString = String const&;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::String toString(ox::CRStringView sv) noexcept {
|
||||
return ox::String(sv);
|
||||
}
|
||||
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
|
||||
|
4
deps/ox/src/ox/std/stringliteral.hpp
vendored
4
deps/ox/src/ox/std/stringliteral.hpp
vendored
@ -41,10 +41,6 @@ class StringLiteral: public detail::BaseStringView {
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
89
deps/ox/src/ox/std/stringview.hpp
vendored
89
deps/ox/src/ox/std/stringview.hpp
vendored
@ -12,9 +12,12 @@
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "basestringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "writer.hpp"
|
||||
#include "bit.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -86,6 +89,70 @@ constexpr auto operator<=>(CRStringView s1, CRStringView s2) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, char search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (str[i] == search) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (beginsWith(substr(str, i), search)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, char del) {
|
||||
return substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
|
||||
return substr(current, find(current, del) + del.len());
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr auto write(Writer_c auto &writer, ox::CRStringView sv) noexcept {
|
||||
return writer.write(sv.data(), sv.bytes());
|
||||
}
|
||||
@ -96,22 +163,6 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Maybe StringView. If T is a string type, MaybeType::type/MaybeSV_t is a
|
||||
// StringView. This avoids creating unnecessary Strings when taking a
|
||||
// StringView or C string as a function argument.
|
||||
template<typename T, bool isStr = isOxString_v<T>>
|
||||
struct MaybeSV {
|
||||
using type = T;
|
||||
};
|
||||
template<typename T>
|
||||
struct MaybeSV<T, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename T>
|
||||
using MaybeSV_t = typename MaybeSV<T>::type;
|
||||
|
||||
|
||||
}
|
||||
|
||||
constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept {
|
||||
|
220
deps/ox/src/ox/std/strops.hpp
vendored
220
deps/ox/src/ox/std/strops.hpp
vendored
@ -8,19 +8,130 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cstrops.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "error.hpp"
|
||||
#include "math.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strcpy(T1 dest, T2 src) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 str1, T2 str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<OxString_c Str>
|
||||
[[nodiscard]]
|
||||
constexpr ox::StringView substr(Str const&str, std::size_t pos) noexcept {
|
||||
constexpr Str substr(Str const&str, std::size_t pos) noexcept {
|
||||
if (str.len() >= pos) {
|
||||
return Str(str.data() + pos, str.len() - pos);
|
||||
}
|
||||
@ -29,7 +140,7 @@ constexpr ox::StringView substr(Str const&str, std::size_t pos) noexcept {
|
||||
|
||||
template<OxString_c Str>
|
||||
[[nodiscard]]
|
||||
constexpr ox::StringView substr(Str const&str, std::size_t start, std::size_t end) noexcept {
|
||||
constexpr Str substr(Str const&str, std::size_t start, std::size_t end) noexcept {
|
||||
if (str.len() >= start && end >= start) {
|
||||
return Str(str.data() + start, end - start);
|
||||
}
|
||||
@ -68,79 +179,38 @@ constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, char search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (str[i] == search) {
|
||||
break;
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) 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) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
it++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (beginsWith(substr(str, i), search)) {
|
||||
break;
|
||||
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;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, char del) {
|
||||
return substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
|
||||
return substr(current, find(current, del) + del.len());
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::Result<std::size_t> lastIndexOf(ox::CRStringView str, int character) noexcept {
|
||||
ox::Result<std::size_t> retval = OxError(1, "Character not found");
|
||||
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
|
||||
if (str[static_cast<std::size_t>(i)] == character) {
|
||||
retval = static_cast<std::size_t>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
19
deps/ox/src/ox/std/test/tests.cpp
vendored
19
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -12,7 +12,7 @@
|
||||
#include <ox/std/uuid.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
"malloc",
|
||||
[] {
|
||||
@ -117,7 +117,6 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
[] {
|
||||
ox::Vector<int> v;
|
||||
oxAssert(v.size() == 0, "Initial Vector size not 0");
|
||||
oxAssert(v.empty(), "Vector::empty() is broken");
|
||||
auto insertTest = [&v](int val, [[maybe_unused]] std::size_t size) {
|
||||
v.push_back(val);
|
||||
oxReturnError(OxError(v.size() != size, "Vector size incorrect"));
|
||||
@ -173,7 +172,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
oxAssert(w.write("aoeu", 4), "write failed");
|
||||
oxExpect(b.size(), 8u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu");
|
||||
ox::StringView constexpr qwerty = "qwerty";
|
||||
ox::StringView qwerty = "qwerty";
|
||||
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
|
||||
oxExpect(b.size(), 14u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
|
||||
@ -314,14 +313,12 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
if (argc > 1) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
42
deps/ox/src/ox/std/trace.hpp
vendored
42
deps/ox/src/ox/std/trace.hpp
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -39,10 +39,10 @@ enum class MsgId: char {
|
||||
struct TraceMsgRcv {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.trace.TraceMsg";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
BasicString<50> file{""};
|
||||
BasicString<50> file = "";
|
||||
int line = 0;
|
||||
uint64_t time = 0;
|
||||
BasicString<50> ch{""};
|
||||
BasicString<50> ch = "";
|
||||
BasicString<100> msg;
|
||||
};
|
||||
|
||||
@ -141,22 +141,39 @@ class OutStream {
|
||||
m_msg.msg = msg;
|
||||
}
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args const&...elements) noexcept {
|
||||
static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, std::array<detail::FmtArg, fmtSegmentCnt - 1> elements) noexcept {
|
||||
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
m_msg.file = file;
|
||||
m_msg.line = line;
|
||||
m_msg.ch = ch;
|
||||
const auto &firstSegment = fmtSegments.segments[0];
|
||||
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
|
||||
//const detail::FmtArg elements[sizeof...(args)] = {args...};
|
||||
for (size_t i = 0; auto const&e : std::initializer_list<detail::FmtArg>{elements...}) {
|
||||
m_msg.msg += e.out;
|
||||
for (size_t i = 0; i < fmtSegments.size - 1; ++i) {
|
||||
m_msg.msg += elements[i].out;
|
||||
const auto &s = fmtSegments.segments[i + 1];
|
||||
oxIgnoreError(m_msg.msg.append(s.str, s.length));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#else
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args... args) noexcept {
|
||||
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
m_msg.file = file;
|
||||
m_msg.line = line;
|
||||
m_msg.ch = ch;
|
||||
const auto &firstSegment = fmtSegments.segments[0];
|
||||
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
|
||||
const detail::FmtArg elements[sizeof...(args)] = {args...};
|
||||
for (auto i = 0u; i < fmtSegments.size - 1; ++i) {
|
||||
m_msg.msg += elements[i].out;
|
||||
const auto &s = fmtSegments.segments[i + 1];
|
||||
oxIgnoreError(m_msg.msg.append(s.str, s.length));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline ~OutStream() noexcept {
|
||||
oxTraceHook(m_msg.file, m_msg.line, m_msg.ch, m_msg.msg.c_str());
|
||||
@ -240,10 +257,15 @@ class NullStream {
|
||||
constexpr NullStream(const char*, int, const char*, const char* = "") noexcept {
|
||||
}
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args const&...elements) noexcept {
|
||||
static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, std::array<detail::FmtArg, fmtSegmentCnt - 1>) noexcept {
|
||||
}
|
||||
#else
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args...) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr const NullStream &operator<<(const T&) const noexcept {
|
||||
|
5
deps/ox/src/ox/std/typetraits.hpp
vendored
5
deps/ox/src/ox/std/typetraits.hpp
vendored
@ -273,7 +273,6 @@ template<std::size_t SmallStringSize>
|
||||
class BasicString;
|
||||
template<std::size_t sz>
|
||||
class BString;
|
||||
class CStringView;
|
||||
class StringLiteral;
|
||||
class StringView;
|
||||
|
||||
@ -293,10 +292,6 @@ constexpr auto isOxString(const BString<sz>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr auto isOxString(const CStringView*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr auto isOxString(const StringLiteral*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
29
deps/ox/src/ox/std/vector.hpp
vendored
29
deps/ox/src/ox/std/vector.hpp
vendored
@ -16,7 +16,7 @@
|
||||
#include "iterator.hpp"
|
||||
#include "math.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "new.hpp"
|
||||
#include "types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
@ -254,12 +254,12 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool contains(MaybeSV_t<T> const&) const noexcept(useNoexcept);
|
||||
constexpr bool contains(const T&) const noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(
|
||||
std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept);
|
||||
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept);
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, const T &val) noexcept(useNoexcept);
|
||||
|
||||
template<typename... Args>
|
||||
constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept);
|
||||
@ -267,9 +267,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
template<typename... Args>
|
||||
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(T &&item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept);
|
||||
constexpr void push_back(const T &item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void pop_back() noexcept(useNoexcept);
|
||||
|
||||
@ -486,7 +484,7 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) n
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeSV_t<T> const&v) const noexcept(useNoexcept) {
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const noexcept(useNoexcept) {
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
if (m_items[i] == v) {
|
||||
return true;
|
||||
@ -498,7 +496,7 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeSV_t<T> cons
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
|
||||
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept) {
|
||||
if (m_size + cnt > m_cap) {
|
||||
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
|
||||
if (pos < m_size) {
|
||||
@ -526,7 +524,7 @@ Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
|
||||
if (pos < m_size) {
|
||||
@ -583,16 +581,7 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
std::construct_at(&m_items[m_size], std::move(item));
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept) {
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(const T &item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
|
3
deps/teagba/include/teagba/gfx.hpp
vendored
3
deps/teagba/include/teagba/gfx.hpp
vendored
@ -36,6 +36,9 @@ struct OX_ALIGN8 GbaSpriteAttrUpdate {
|
||||
|
||||
};
|
||||
|
||||
extern volatile uint16_t g_spriteUpdates;
|
||||
extern ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;
|
||||
|
||||
void applySpriteUpdates() noexcept;
|
||||
|
4
deps/teagba/src/gfx.cpp
vendored
4
deps/teagba/src/gfx.cpp
vendored
@ -10,8 +10,8 @@
|
||||
|
||||
namespace teagba {
|
||||
|
||||
static volatile uint16_t g_spriteUpdates = 0;
|
||||
static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
volatile uint16_t g_spriteUpdates = 0;
|
||||
ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
|
||||
// block until g_spriteUpdates is less than buffer len
|
||||
|
@ -485,14 +485,17 @@ implements a superset of JSON.
|
||||
OrganicClaw requires support for 64 bit integers, whereas normal JSON
|
||||
technically does not.
|
||||
|
||||
These formats do not currently support floats.
|
||||
|
||||
There is also a wrapper format called Claw that provides a header at the
|
||||
beginning of the file and can dynamically switch between the two depending on
|
||||
what the header says is present.
|
||||
The Claw header also includes information about the type and type version of
|
||||
the data.
|
||||
|
||||
Except when the data is exported for loading on the GBA, Claw is always used as
|
||||
a wrapper around the bare formats.
|
||||
|
||||
These formats do not currently support ```float```s.
|
||||
|
||||
Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;```
|
||||
|
||||
That reads:
|
||||
@ -501,9 +504,6 @@ That reads:
|
||||
* Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette
|
||||
* Type version is 1
|
||||
|
||||
Except when the data is exported for loading on the GBA, Claw is always used as
|
||||
a wrapper around the bare formats.
|
||||
|
||||
#### Metal Claw Example
|
||||
|
||||
##### Read
|
||||
|
@ -14,6 +14,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
||||
"typeId" : "B.uint64;0"
|
||||
}
|
||||
],
|
||||
"preloadable" : true,
|
||||
"primitiveType" : 6,
|
||||
"typeName" : "net.drinkingtea.ox.FileAddress.Data",
|
||||
"typeVersion" : 1
|
||||
|
@ -10,6 +10,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
||||
"typeId" : "net.drinkingtea.ox.FileAddress.Data"
|
||||
}
|
||||
],
|
||||
"preloadable" : true,
|
||||
"primitiveType" : 5,
|
||||
"typeName" : "net.drinkingtea.ox.FileAddress",
|
||||
"typeVersion" : 1
|
||||
|
Binary file not shown.
@ -21,13 +21,12 @@ host_env = f'{os}-{arch}'
|
||||
with open(".current_build","r") as f:
|
||||
current_build = f.readlines()[0]
|
||||
|
||||
project_dir = sys.argv[1]
|
||||
project_name = sys.argv[2]
|
||||
bin = f'./build/{host_env}-{current_build}/bin/'
|
||||
project_bin = f'build/gba-release/bin/{project_name}.bin'
|
||||
project_gba = f'{project_name}.gba'
|
||||
nostalgia_bin = 'build/gba-release/bin/nostalgia.bin'
|
||||
nostalgia_project = sys.argv[1]
|
||||
nostalgia_gba = 'nostalgia.gba'
|
||||
|
||||
shutil.copyfile(project_bin, project_gba)
|
||||
shutil.copyfile(nostalgia_bin, nostalgia_gba)
|
||||
subprocess.run([
|
||||
f'{bin}/{project_name}-pack', '-src', project_dir, '-rom-bin', project_gba])
|
||||
subprocess.run(['gbafix', project_gba])
|
||||
f'{bin}/nost-pack', '-src', nostalgia_project, '-rom-bin', nostalgia_gba])
|
||||
subprocess.run(['gbafix', nostalgia_gba])
|
||||
|
@ -1,2 +1,9 @@
|
||||
include_directories(".")
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
add_subdirectory(glutils)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
add_subdirectory(keel)
|
||||
add_subdirectory(nostalgia)
|
||||
add_subdirectory(olympic)
|
||||
add_subdirectory(turbine)
|
||||
|
@ -3,21 +3,23 @@ add_library(
|
||||
glutils.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
GlUtils PUBLIC
|
||||
../include
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
GlUtils PUBLIC
|
||||
OxStd
|
||||
glad
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
glutils.hpp
|
||||
DESTINATION
|
||||
include/glutils
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
GlUtils
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
)
|
@ -6,7 +6,7 @@
|
||||
#include <ox/std/bstring.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include "glutils/glutils.hpp"
|
||||
#include "glutils.hpp"
|
||||
|
||||
namespace glutils {
|
||||
|
||||
@ -88,23 +88,27 @@ static ox::Result<GLShader> buildShader(
|
||||
return shader;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
ox::CStringView const&vert,
|
||||
ox::CStringView const&frag,
|
||||
ox::CStringView const&geo) noexcept {
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo) noexcept {
|
||||
GLProgram prgm(glCreateProgram());
|
||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
|
||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad"));
|
||||
glAttachShader(prgm, vs);
|
||||
if (geo.c_str() && geo.bytes() != 0) {
|
||||
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
|
||||
if (geo && ox_strlen(geo) != 0) {
|
||||
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo, "gshad"));
|
||||
glAttachShader(prgm, gs);
|
||||
}
|
||||
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
|
||||
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag, "fshad"));
|
||||
glAttachShader(prgm, fs);
|
||||
glLinkProgram(prgm);
|
||||
return prgm;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
const ox::String &vert,
|
||||
const ox::String &frag,
|
||||
const ox::String &geo) noexcept {
|
||||
return buildShaderProgram(vert.c_str(), frag.c_str(), geo.c_str());
|
||||
}
|
||||
|
||||
GLVertexArray generateVertexArrayObject() noexcept {
|
||||
GLVertexArray vao;
|
||||
glGenVertexArrays(1, &vao.id);
|
||||
@ -129,9 +133,8 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
glGenTextures(1, &fb.color.id);
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
||||
// depth texture
|
||||
glGenRenderbuffers(1, &fb.depth.id);
|
||||
@ -147,23 +150,21 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
return fb;
|
||||
}
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
if (!fb) {
|
||||
fb = generateFrameBuffer(width, height);
|
||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
||||
if (!*fb) {
|
||||
*fb = generateFrameBuffer(width, height);
|
||||
return;
|
||||
}
|
||||
width = ox::max(1, width);
|
||||
height = ox::max(1, height);
|
||||
fb.width = width;
|
||||
fb.height = height;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, *fb);
|
||||
// color texture
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glBindTexture(GL_TEXTURE_2D, fb->color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// depth texture
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
// restore primary FB
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@ -171,17 +172,13 @@ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
|
||||
resizeInitFrameBuffer(fb, sz.width, sz.height);
|
||||
}
|
||||
|
||||
void sendVbo(BufferSet const&bs) noexcept {
|
||||
void sendVbo(const BufferSet &bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
void sendEbo(BufferSet const&bs) noexcept {
|
||||
void sendEbo(const BufferSet &bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
|
@ -9,14 +9,14 @@
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <ox/std/bounds.hpp>
|
||||
#include <ox/std/cstringview.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
namespace glutils {
|
||||
|
||||
constexpr ox::StringView GlslVersion = "#version 330";
|
||||
|
||||
struct Empty {
|
||||
virtual ~Empty() noexcept = default;
|
||||
};
|
||||
@ -151,7 +151,9 @@ class FrameBufferBind {
|
||||
void bind(const FrameBuffer &fb) noexcept;
|
||||
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(ox::CStringView const&vert, ox::CStringView const&frag, ox::CStringView const&geo = "") noexcept;
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo = nullptr) noexcept;
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(const ox::String &vert, const ox::String &frag, const ox::String &geo = "") noexcept;
|
||||
|
||||
glutils::GLVertexArray generateVertexArrayObject() noexcept;
|
||||
|
||||
@ -163,9 +165,7 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept;
|
||||
/**
|
||||
* Resizes a FrameBuffer, and creates if it does not already exist.
|
||||
*/
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept;
|
||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept;
|
||||
|
||||
struct BufferSet {
|
||||
glutils::GLVertexArray vao;
|
||||
@ -176,9 +176,9 @@ struct BufferSet {
|
||||
ox::Vector<GLuint> elements;
|
||||
};
|
||||
|
||||
void sendVbo(BufferSet const&bs) noexcept;
|
||||
|
||||
void sendEbo(BufferSet const&bs) noexcept;
|
||||
void sendVbo(const BufferSet &bs) noexcept;
|
||||
|
||||
void sendEbo(const BufferSet &bs) noexcept;
|
||||
|
||||
void clearScreen() noexcept;
|
||||
|
47
src/keel/CMakeLists.txt
Normal file
47
src/keel/CMakeLists.txt
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
add_library(
|
||||
Keel
|
||||
asset.cpp
|
||||
keel.cpp
|
||||
media.cpp
|
||||
module.cpp
|
||||
pack.cpp
|
||||
typeconv.cpp
|
||||
typestore.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
Keel PUBLIC
|
||||
OxClaw
|
||||
OxEvent
|
||||
OxFS
|
||||
OxModel
|
||||
OxPreloader
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
asset.hpp
|
||||
assetmanager.hpp
|
||||
context.hpp
|
||||
keel.hpp
|
||||
media.hpp
|
||||
module.hpp
|
||||
pack.hpp
|
||||
typeconv.hpp
|
||||
typestore.hpp
|
||||
DESTINATION
|
||||
include/keel
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
Keel
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
add_subdirectory(test)
|
||||
endif()
|
@ -2,11 +2,11 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/asset.hpp>
|
||||
#include "asset.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(ox::Buffer const&buff) noexcept {
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept {
|
||||
return readUuidHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexc
|
||||
return ox::UUID::fromString(ox::StringView(buff + k1Hdr.bytes(), 36));
|
||||
}
|
||||
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, ox::Buffer const&buff) noexcept {
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
if (!readUuidHeader(buff).error) {
|
||||
offset = K1HdrSz;
|
||||
@ -39,7 +39,7 @@ ox::Result<AssetHdr> readAssetHeader(const char *buff, std::size_t buffLen) noex
|
||||
return out;
|
||||
}
|
||||
|
||||
ox::Result<AssetHdr> readAssetHeader(ox::Buffer const&buff) noexcept {
|
||||
ox::Result<AssetHdr> readAssetHeader(const ox::Buffer &buff) noexcept {
|
||||
return readAssetHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
@ -36,10 +36,10 @@ class AssetContainer {
|
||||
explicit constexpr AssetContainer(Args&&... args): m_obj(ox::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
AssetContainer(AssetContainer const&) = delete;
|
||||
AssetContainer(AssetContainer&) = delete;
|
||||
AssetContainer(AssetContainer&&) = delete;
|
||||
AssetContainer &operator=(AssetContainer const&) = delete;
|
||||
AssetContainer &operator=(AssetContainer&&) = delete;
|
||||
AssetContainer& operator=(AssetContainer&) = delete;
|
||||
AssetContainer& operator=(AssetContainer&&) = delete;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T *get() noexcept {
|
||||
@ -55,7 +55,7 @@ class AssetContainer {
|
||||
m_obj = std::move(val);
|
||||
}
|
||||
|
||||
constexpr void set(T const&val) {
|
||||
constexpr void set(const T &val) {
|
||||
m_obj = val;
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class AssetRef: public ox::SignalHandler {
|
||||
|
||||
explicit constexpr AssetRef(const AssetContainer<T> *c = nullptr) noexcept;
|
||||
|
||||
constexpr AssetRef(AssetRef const&h) noexcept;
|
||||
constexpr AssetRef(const AssetRef &h) noexcept;
|
||||
|
||||
constexpr AssetRef(AssetRef &&h) noexcept;
|
||||
|
||||
@ -103,7 +103,11 @@ class AssetRef: public ox::SignalHandler {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
constexpr const T &operator*() const noexcept {
|
||||
constexpr const T &operator*() const & noexcept {
|
||||
return *m_ctr->get();
|
||||
}
|
||||
|
||||
constexpr const T &&operator*() const && noexcept {
|
||||
return *m_ctr->get();
|
||||
}
|
||||
|
||||
@ -111,7 +115,7 @@ class AssetRef: public ox::SignalHandler {
|
||||
return m_ctr->get();
|
||||
}
|
||||
|
||||
AssetRef &operator=(AssetRef const&h) noexcept {
|
||||
AssetRef &operator=(const AssetRef &h) noexcept {
|
||||
if (this == &h) {
|
||||
return *this;
|
||||
}
|
||||
@ -160,7 +164,7 @@ constexpr AssetRef<T>::AssetRef(const AssetContainer<T> *c) noexcept: m_ctr(c) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr AssetRef<T>::AssetRef(AssetRef const&h) noexcept {
|
||||
constexpr AssetRef<T>::AssetRef(const AssetRef &h) noexcept {
|
||||
m_ctr = h.m_ctr;
|
||||
if (m_ctr) {
|
||||
m_ctr->updated.connect(this, &AssetRef::emitUpdated);
|
||||
@ -187,16 +191,16 @@ class AssetManager {
|
||||
template<typename T>
|
||||
class AssetTypeManager: public AssetTypeManagerBase {
|
||||
private:
|
||||
ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache;
|
||||
ox::HashMap<ox::String, ox::UniquePtr<AssetContainer<T>>> m_cache;
|
||||
|
||||
public:
|
||||
ox::Result<AssetRef<T>> getAsset(ox::StringView const&assetId) const noexcept {
|
||||
ox::Result<AssetRef<T>> getAsset(const ox::StringView &assetId) const noexcept {
|
||||
auto out = m_cache.at(assetId);
|
||||
oxReturnError(out);
|
||||
return AssetRef<T>(out.value->get());
|
||||
}
|
||||
|
||||
ox::Result<AssetRef<T>> setAsset(ox::StringView const&assetId, T const&obj) noexcept {
|
||||
ox::Result<AssetRef<T>> setAsset(const ox::StringView &assetId, const T &obj) noexcept {
|
||||
auto &p = m_cache[assetId];
|
||||
if (!p) {
|
||||
p = ox::make_unique<AssetContainer<T>>(obj);
|
||||
@ -207,7 +211,7 @@ class AssetManager {
|
||||
return AssetRef<T>(p.get());
|
||||
}
|
||||
|
||||
ox::Result<AssetRef<T>> setAsset(ox::StringView const&assetId, T &&obj) noexcept {
|
||||
ox::Result<AssetRef<T>> setAsset(const ox::StringView &assetId, T &&obj) noexcept {
|
||||
auto &p = m_cache[assetId];
|
||||
if (!p) {
|
||||
p = ox::make_unique<AssetContainer<T>>(obj);
|
||||
@ -228,12 +232,12 @@ class AssetManager {
|
||||
}
|
||||
};
|
||||
|
||||
ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers;
|
||||
ox::HashMap<ox::String, ox::UniquePtr<AssetTypeManagerBase>> m_assetTypeManagers;
|
||||
|
||||
template<typename T>
|
||||
AssetTypeManager<T> *getTypeManager() noexcept {
|
||||
constexpr auto typeName = ox::requireModelTypeName<T>();
|
||||
static_assert(ox::StringView(typeName) != "", "Types must have TypeName to use AssetManager");
|
||||
static_assert(ox_strcmp(typeName, "") != 0, "Types must have TypeName to use AssetManager");
|
||||
auto &am = m_assetTypeManagers[typeName];
|
||||
if (!am) {
|
||||
am = ox::make_unique<AssetTypeManager<T>>();
|
||||
@ -255,7 +259,7 @@ class AssetManager {
|
||||
}
|
||||
|
||||
void gc() noexcept {
|
||||
for (auto const&amk : m_assetTypeManagers.keys()) {
|
||||
for (const auto &amk : m_assetTypeManagers.keys()) {
|
||||
auto &am = m_assetTypeManagers[amk];
|
||||
am->gc();
|
||||
}
|
||||
@ -265,7 +269,7 @@ class AssetManager {
|
||||
template<typename T>
|
||||
class AssetRef {
|
||||
private:
|
||||
const T *const m_obj = nullptr;
|
||||
const T *m_obj = nullptr;
|
||||
|
||||
public:
|
||||
constexpr AssetRef() noexcept = default;
|
@ -6,18 +6,19 @@
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/stringview.hpp>
|
||||
|
||||
#include "assetmanager.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
class Context;
|
||||
using PackTransform = ox::Error(*)(Context&, ox::Buffer &clawData);
|
||||
using PackTransform = ox::Error(*)(Context*, ox::Buffer *clawData);
|
||||
|
||||
class Context {
|
||||
public:
|
||||
ox::UPtr<ox::FileSystem> rom;
|
||||
ox::BasicString<32> appName{"Keel App"};
|
||||
ox::StringView appName = "Keel App";
|
||||
#ifndef OX_BARE_METAL
|
||||
AssetManager assetManager;
|
||||
ox::HashMap<ox::String, ox::UUID> pathToUuid;
|
||||
@ -29,9 +30,9 @@ class Context {
|
||||
#endif
|
||||
|
||||
constexpr Context() noexcept = default;
|
||||
Context(Context const&) noexcept = delete;
|
||||
Context(const Context&) noexcept = delete;
|
||||
Context(Context&&) noexcept = delete;
|
||||
Context &operator=(Context const&) noexcept = delete;
|
||||
Context &operator=(const Context&) noexcept = delete;
|
||||
Context &operator=(Context&&) noexcept = delete;
|
||||
constexpr virtual ~Context() noexcept = default;
|
||||
};
|
@ -2,35 +2,35 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/keel.hpp>
|
||||
#include "keel.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
ox::Error init(
|
||||
keel::Context &ctx,
|
||||
keel::Context *ctx,
|
||||
ox::UPtr<ox::FileSystem> &&fs,
|
||||
ox::CRStringView appName) noexcept {
|
||||
ctx.appName = appName;
|
||||
ctx->appName = appName;
|
||||
oxIgnoreError(setRomFs(ctx, std::move(fs)));
|
||||
#ifndef OX_BARE_METAL
|
||||
#ifndef OX_BARE_METAL
|
||||
const auto &mods = modules();
|
||||
for (auto &mod : mods) {
|
||||
// register type converters
|
||||
for (auto c : mod->converters()) {
|
||||
ctx.converters.emplace_back(c);
|
||||
ctx->converters.emplace_back(c);
|
||||
}
|
||||
// register pack transforms
|
||||
for (auto c : mod->packTransforms()) {
|
||||
ctx.packTransforms.emplace_back(c);
|
||||
ctx->packTransforms.emplace_back(c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
|
||||
auto ctx = ox::make_unique<Context>();
|
||||
oxReturnError(keel::init(*ctx, std::move(fs), appName));
|
||||
oxReturnError(keel::init(ctx.get(), std::move(fs), appName));
|
||||
return ctx;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace keel {
|
||||
|
||||
ox::Error init(
|
||||
keel::Context &ctx,
|
||||
keel::Context *ctx,
|
||||
ox::UPtr<ox::FileSystem> &&fs,
|
||||
ox::CRStringView appName) noexcept;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/media.hpp>
|
||||
#include "media.hpp"
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
@ -24,10 +24,10 @@ ox::Result<char*> loadRom(ox::CRStringView path) noexcept {
|
||||
auto buff = new char[static_cast<std::size_t>(size)];
|
||||
file.read(buff, size);
|
||||
return buff;
|
||||
} catch (std::ios_base::failure const&e) {
|
||||
} catch (const std::ios_base::failure &e) {
|
||||
oxErrorf("Could not read ROM file due to file IO failure: {}", e.what());
|
||||
return OxError(2, "Could not read ROM file");
|
||||
} catch (std::bad_alloc const&e) {
|
||||
} catch (const std::bad_alloc &e) {
|
||||
oxErrorf("Could not read ROM file due to new failure: {}", e.what());
|
||||
return OxError(2, "Could not allocate memory for ROM file");
|
||||
}
|
||||
@ -37,23 +37,27 @@ void unloadRom(char *rom) noexcept {
|
||||
ox::safeDelete(rom);
|
||||
}
|
||||
|
||||
static void clearUuidMap(Context &ctx) noexcept {
|
||||
ctx.uuidToPath.clear();
|
||||
ctx.pathToUuid.clear();
|
||||
ox::Result<void*> findPreloadSection() noexcept {
|
||||
return OxError(1, "findPreloadSection is unsupported on this platform");
|
||||
}
|
||||
|
||||
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uuid) noexcept {
|
||||
ctx.pathToUuid[filePath] = uuid;
|
||||
ctx.uuidToPath[uuid.toString()] = filePath;
|
||||
static void clearUuidMap(Context *ctx) noexcept {
|
||||
ctx->uuidToPath.clear();
|
||||
ctx->pathToUuid.clear();
|
||||
}
|
||||
|
||||
static ox::Error buildUuidMap(Context &ctx, ox::CRStringView path) noexcept {
|
||||
oxRequire(files, ctx.rom->ls(path));
|
||||
void createUuidMapping(Context *ctx, ox::String filePath, const ox::UUID &uuid) noexcept {
|
||||
ctx->pathToUuid[filePath] = uuid;
|
||||
ctx->uuidToPath[uuid.toString()] = std::move(filePath);
|
||||
}
|
||||
|
||||
static ox::Error buildUuidMap(Context *ctx, ox::CRStringView path) noexcept {
|
||||
oxRequire(files, ctx->rom->ls(path));
|
||||
for (const auto &f : files) {
|
||||
oxRequireM(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f}));
|
||||
oxRequire(stat, ctx.rom->stat(filePath));
|
||||
oxRequire(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f}));
|
||||
oxRequire(stat, ctx->rom->stat(filePath));
|
||||
if (stat.fileType == ox::FileType::NormalFile) {
|
||||
oxRequire(data, ctx.rom->read(filePath));
|
||||
oxRequire(data, ctx->rom->read(filePath));
|
||||
const auto [hdr, err] = readAssetHeader(data);
|
||||
if (!err) {
|
||||
createUuidMapping(ctx, filePath, hdr.uuid);
|
||||
@ -67,8 +71,8 @@ static ox::Error buildUuidMap(Context &ctx, ox::CRStringView path) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error buildUuidMap(Context &ctx) noexcept {
|
||||
if (!ctx.rom) {
|
||||
ox::Error buildUuidMap(Context *ctx) noexcept {
|
||||
if (!ctx->rom) {
|
||||
return OxError(1, "No ROM FS");
|
||||
}
|
||||
return buildUuidMap(ctx, "");
|
||||
@ -76,8 +80,7 @@ ox::Error buildUuidMap(Context &ctx) noexcept {
|
||||
|
||||
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(out, ctx.pathToUuid.at(path));
|
||||
return *out;
|
||||
return ctx.pathToUuid[path];
|
||||
#else
|
||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||
#endif
|
||||
@ -85,8 +88,7 @@ ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
|
||||
|
||||
ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(out, ctx.uuidToPath.at(uuid));
|
||||
return *out;
|
||||
return ctx.uuidToPath[uuid];
|
||||
#else
|
||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||
#endif
|
||||
@ -94,8 +96,7 @@ ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept
|
||||
|
||||
ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(out, ctx.uuidToPath.at(uuid.toString()));
|
||||
return *out;
|
||||
return ctx.uuidToPath[uuid.toString()];
|
||||
#else
|
||||
return OxError(1, "UUID to path conversion not supported on this platform");
|
||||
#endif
|
||||
@ -104,7 +105,7 @@ ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
|
||||
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
for (auto tr : ctx.packTransforms) {
|
||||
oxReturnError(tr(ctx, clawData));
|
||||
oxReturnError(tr(&ctx, &clawData));
|
||||
}
|
||||
return {};
|
||||
#else
|
||||
@ -116,16 +117,16 @@ ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
||||
|
||||
#else
|
||||
|
||||
#include <keel/context.hpp>
|
||||
#include "context.hpp"
|
||||
|
||||
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000)
|
||||
|
||||
namespace keel {
|
||||
|
||||
static void clearUuidMap(Context&) noexcept {
|
||||
static void clearUuidMap(Context*) noexcept {
|
||||
}
|
||||
|
||||
ox::Error buildUuidMap(Context&) noexcept {
|
||||
ox::Error buildUuidMap(Context*) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -149,20 +150,20 @@ ox::Result<char*> loadRom(ox::CRStringView) noexcept {
|
||||
void unloadRom(char*) noexcept {
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView path) noexcept {
|
||||
oxRequire(stat, ctx.rom->stat(path));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(path));
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, ox::CRStringView path) noexcept {
|
||||
oxRequire(stat, ctx->rom->stat(path));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(path));
|
||||
PreloadPtr p;
|
||||
oxReturnError(ox::readMC(buff, static_cast<std::size_t>(stat.size), &p));
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx->preloadSectionOffset;
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, const ox::FileAddress &file) noexcept {
|
||||
oxRequire(stat, ctx.rom->stat(file));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(file));
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept {
|
||||
oxRequire(stat, ctx->rom->stat(file));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(file));
|
||||
PreloadPtr p;
|
||||
oxReturnError(ox::readMC(buff, static_cast<std::size_t>(stat.size), &p));
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx->preloadSectionOffset;
|
||||
}
|
||||
|
||||
}
|
||||
@ -171,15 +172,16 @@ ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, const ox::FileAddress
|
||||
|
||||
namespace keel {
|
||||
|
||||
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept {
|
||||
ctx.rom = std::move(fs);
|
||||
ox::Error setRomFs(Context *ctx, ox::UPtr<ox::FileSystem> fs) noexcept {
|
||||
ctx->rom = std::move(fs);
|
||||
clearUuidMap(ctx);
|
||||
return buildUuidMap(ctx);
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept {
|
||||
auto const lastDot = ox::lastIndexOf(path, '.');
|
||||
if (!lastDot.error && substr(path, lastDot.value) == ".oxfs") {
|
||||
const auto lastDot = ox_lastIndexOf(path, '.');
|
||||
const auto fsExt = lastDot != -1 ? substr(path, static_cast<std::size_t>(lastDot)) : "";
|
||||
if (ox_strcmp(fsExt, ".oxfs") == 0) {
|
||||
oxRequire(rom, loadRom(path));
|
||||
return {ox::make_unique<ox::FileSystem32>(rom, 32 * ox::units::MB, unloadRom)};
|
||||
} else {
|
@ -29,17 +29,17 @@ oxModelBegin(PreloadPtr)
|
||||
oxModelField(preloadAddr)
|
||||
oxModelEnd()
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, ox::CRStringView file) noexcept;
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
template<typename T>
|
||||
ox::Result<keel::AssetRef<T>> readObjFile(
|
||||
keel::Context &ctx,
|
||||
keel::Context *ctx,
|
||||
ox::StringView assetId,
|
||||
bool forceLoad) noexcept {
|
||||
constexpr auto readConvert = [](Context &ctx, const ox::Buffer &buff) -> ox::Result<T> {
|
||||
constexpr auto readConvert = [](Context *ctx, const ox::Buffer &buff) -> ox::Result<T> {
|
||||
auto [obj, err] = readAsset<T>(buff);
|
||||
if (err) {
|
||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||
@ -50,24 +50,26 @@ ox::Result<keel::AssetRef<T>> readObjFile(
|
||||
return std::move(obj);
|
||||
};
|
||||
ox::StringView path;
|
||||
ox::UUIDStr uuidStr;
|
||||
if (beginsWith(assetId, "uuid://")) {
|
||||
assetId = substr(assetId, 7);
|
||||
oxRequire(p, ctx.uuidToPath.at(assetId));
|
||||
path = *p;
|
||||
path = ctx->uuidToPath[assetId];
|
||||
} else {
|
||||
path = assetId;
|
||||
uuidStr = ctx->pathToUuid[path].toString();
|
||||
assetId = uuidStr;
|
||||
}
|
||||
if (forceLoad) {
|
||||
oxRequire(buff, ctx.rom->read(path));
|
||||
oxRequire(buff, ctx->rom->read(path));
|
||||
oxRequire(obj, readConvert(ctx, buff));
|
||||
oxRequire(cached, ctx.assetManager.setAsset(assetId, obj));
|
||||
oxRequire(cached, ctx->assetManager.setAsset(assetId, obj));
|
||||
return cached;
|
||||
} else {
|
||||
auto [cached, err] = ctx.assetManager.getAsset<T>(assetId);
|
||||
auto [cached, err] = ctx->assetManager.getAsset<T>(assetId);
|
||||
if (err) {
|
||||
oxRequire(buff, ctx.rom->read(path));
|
||||
oxRequire(buff, ctx->rom->read(path));
|
||||
oxRequire(obj, readConvert(ctx, buff));
|
||||
oxReturnError(ctx.assetManager.setAsset(assetId, obj).moveTo(&cached));
|
||||
oxReturnError(ctx->assetManager.setAsset(assetId, obj).moveTo(&cached));
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
@ -77,7 +79,7 @@ ox::Result<keel::AssetRef<T>> readObjFile(
|
||||
|
||||
template<typename T>
|
||||
ox::Result<keel::AssetRef<T>> readObjNoCache(
|
||||
keel::Context &ctx,
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView assetId) noexcept {
|
||||
if constexpr(ox::preloadable<T>::value) {
|
||||
oxRequire(addr, getPreloadAddr(ctx, assetId));
|
||||
@ -89,9 +91,9 @@ ox::Result<keel::AssetRef<T>> readObjNoCache(
|
||||
|
||||
#endif
|
||||
|
||||
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&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;
|
||||
|
||||
@ -100,19 +102,19 @@ ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
||||
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
|
||||
|
||||
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
|
||||
if (assetId.len() == 0) {
|
||||
return OxError(1, "Invalid asset ID");
|
||||
}
|
||||
ox::UUIDStr idStr;
|
||||
if (assetId[0] == '/') {
|
||||
const auto [id, err] = ctx.pathToUuid.at(assetId);
|
||||
const auto [id, err] = ctx->pathToUuid.at(assetId);
|
||||
oxReturnError(err);
|
||||
idStr = id->toString();
|
||||
assetId = idStr;
|
||||
}
|
||||
return ctx.assetManager.setAsset(assetId, asset);
|
||||
return ctx->assetManager.setAsset(assetId, asset);
|
||||
#else
|
||||
return OxError(1, "Not supported on this platform");
|
||||
#endif
|
||||
@ -120,7 +122,7 @@ ox::Result<AssetRef<T>> setAsset(keel::Context &ctx, ox::StringView assetId, T c
|
||||
|
||||
template<typename T>
|
||||
ox::Result<keel::AssetRef<T>> readObj(
|
||||
keel::Context &ctx,
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView assetId,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
@ -132,8 +134,8 @@ ox::Result<keel::AssetRef<T>> readObj(
|
||||
|
||||
template<typename T>
|
||||
ox::Result<keel::AssetRef<T>> readObj(
|
||||
keel::Context &ctx,
|
||||
ox::FileAddress const&file,
|
||||
keel::Context *ctx,
|
||||
const ox::FileAddress &file,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(assetId, file.getPath());
|
||||
@ -150,15 +152,15 @@ ox::Result<keel::AssetRef<T>> readObj(
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeObj(
|
||||
keel::Context &ctx,
|
||||
ox::FileAddress const&file,
|
||||
T const&obj,
|
||||
keel::Context *ctx,
|
||||
const ox::FileAddress &file,
|
||||
const T &obj,
|
||||
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||
oxRequire(objBuff, ox::writeClaw(obj, fmt));
|
||||
return ctx.rom->write(file, objBuff.data(), objBuff.size());
|
||||
return ctx->rom->write(file, objBuff.data(), objBuff.size());
|
||||
}
|
||||
|
||||
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept;
|
||||
ox::Error setRomFs(Context *ctx, ox::UPtr<ox::FileSystem> fs) noexcept;
|
||||
|
||||
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/module.hpp>
|
||||
#include "module.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
@ -13,7 +13,7 @@ void registerModule(const Module *mod) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<const Module*> const&modules() noexcept {
|
||||
const ox::Vector<const Module*> &modules() noexcept {
|
||||
return mods;
|
||||
}
|
||||
|
@ -11,19 +11,19 @@
|
||||
|
||||
namespace keel {
|
||||
|
||||
using TypeDescGenerator = ox::Error(*)(ox::TypeStore&);
|
||||
using TypeDescGenerator = ox::Error(*)(ox::TypeStore*);
|
||||
|
||||
template<typename T>
|
||||
ox::Error generateTypeDesc(ox::TypeStore &ts) noexcept {
|
||||
return ox::buildTypeDef<T>(&ts).error;
|
||||
ox::Error generateTypeDesc(ox::TypeStore *ts) noexcept {
|
||||
return ox::buildTypeDef<T>(ts).error;
|
||||
}
|
||||
|
||||
class Module {
|
||||
public:
|
||||
constexpr Module() noexcept = default;
|
||||
Module(Module const&) noexcept = delete;
|
||||
Module(const Module&) noexcept = delete;
|
||||
Module(Module&&) noexcept = delete;
|
||||
Module &operator=(Module const&) noexcept = delete;
|
||||
Module &operator=(const Module&) noexcept = delete;
|
||||
Module &operator=(Module&&) noexcept = delete;
|
||||
constexpr virtual ~Module() noexcept = default;
|
||||
|
||||
@ -40,6 +40,6 @@ class Module {
|
||||
void registerModule(const Module *mod) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<const keel::Module*> const&modules() noexcept;
|
||||
const ox::Vector<const keel::Module*> &modules() noexcept;
|
||||
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include <keel/pack.hpp>
|
||||
#include "pack.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
@ -126,6 +126,15 @@ static ox::Error transformClaw(
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error verifyFile(
|
||||
ox::FileSystem &fs,
|
||||
ox::CRStringView path,
|
||||
const ox::Buffer &expected) noexcept {
|
||||
ox::Buffer buff(expected.size());
|
||||
oxReturnError(fs.read(path, buff.data(), buff.size()));
|
||||
return OxError(buff == expected ? 0 : 1);
|
||||
}
|
||||
|
||||
static ox::Error copy(
|
||||
ox::FileSystem &src,
|
||||
ox::FileSystem &dest,
|
||||
@ -149,6 +158,7 @@ static ox::Error copy(
|
||||
// write file to dest
|
||||
oxOutf("writing {}\n", currentFile);
|
||||
oxReturnError(dest.write(currentFile, buff));
|
||||
oxReturnError(verifyFile(dest, currentFile, buff));
|
||||
}
|
||||
}
|
||||
return {};
|
@ -83,19 +83,19 @@ namespace detail {
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
template<typename PlatSpec>
|
||||
ox::Error preloadObj(
|
||||
ox::TypeStore &ts,
|
||||
ox::FileSystem &romFs,
|
||||
ox::Preloader<PlatSpec> &pl,
|
||||
ox::TypeStore *ts,
|
||||
ox::FileSystem *romFs,
|
||||
ox::Preloader<PlatSpec> *pl,
|
||||
ox::CRStringView path) noexcept {
|
||||
// load file
|
||||
oxRequireM(buff, romFs.read(path));
|
||||
oxRequireM(obj, keel::readAsset(&ts, buff));
|
||||
oxRequireM(buff, romFs->read(path));
|
||||
oxRequireM(obj, keel::readAsset(ts, buff));
|
||||
if (obj.type()->preloadable) {
|
||||
oxOutf("preloading {}\n", path);
|
||||
// preload
|
||||
oxRequire(a, pl.startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(&pl, &obj);
|
||||
oxReturnError(pl.endAlloc());
|
||||
oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||
oxReturnError(pl->endAlloc());
|
||||
oxReturnError(err);
|
||||
const keel::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
||||
oxReturnError(ox::writeMC(p).moveTo(&buff));
|
||||
@ -103,7 +103,7 @@ ox::Error preloadObj(
|
||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||
oxReturnError(ox::writeMC(obj).moveTo(&buff));
|
||||
}
|
||||
oxReturnError(romFs.write(path, buff.data(), buff.size()));
|
||||
oxReturnError(romFs->write(path, buff.data(), buff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -111,16 +111,16 @@ ox::Error preloadObj(
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
template<typename PlatSpec>
|
||||
ox::Error preloadDir(
|
||||
ox::TypeStore &ts,
|
||||
ox::FileSystem &romFs,
|
||||
ox::Preloader<PlatSpec> &pl,
|
||||
ox::TypeStore *ts,
|
||||
ox::FileSystem *romFs,
|
||||
ox::Preloader<PlatSpec> *pl,
|
||||
ox::CRStringView path) noexcept {
|
||||
// copy
|
||||
oxTracef("pack.preload", "path: {}", path);
|
||||
oxRequire(fileList, romFs.ls(path));
|
||||
oxRequire(fileList, romFs->ls(path));
|
||||
for (const auto &name : fileList) {
|
||||
const auto filePath = ox::sfmt("{}{}", path, name);
|
||||
oxRequire(stat, romFs.stat(filePath));
|
||||
oxRequire(stat, romFs->stat(filePath));
|
||||
if (stat.fileType == ox::FileType::Directory) {
|
||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
||||
@ -134,29 +134,29 @@ ox::Error preloadDir(
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
ox::Error appendBinary(ox::Buffer &binBuff, ox::SpanView<char> const&fsBuff, ox::Preloader<PlatSpec> &pl) noexcept {
|
||||
constexpr auto padbin = [](ox::BufferWriter &w, unsigned factor) noexcept -> ox::Error {
|
||||
return w.write(nullptr, factor - w.buff().size() % factor);
|
||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, ox::Preloader<PlatSpec> *pl) noexcept {
|
||||
constexpr auto padbin = [](ox::BufferWriter *w, unsigned factor) noexcept -> ox::Error {
|
||||
return w->write(nullptr, factor - w->buff().size() % factor);
|
||||
};
|
||||
constexpr ox::StringView mediaHdr = "KEEL_MEDIA_HEADER_______________";
|
||||
constexpr ox::StringView preloadHdr = "KEEL_PRELOAD_HEADER_____________";
|
||||
constexpr auto hdrSize = 32u;
|
||||
static_assert(mediaHdr.bytes() == hdrSize);
|
||||
static_assert(preloadHdr.bytes() == hdrSize);
|
||||
ox::BufferWriter w(&binBuff);
|
||||
oxReturnError(padbin(w, hdrSize));
|
||||
ox::BufferWriter w(binBuff);
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(mediaHdr.data(), mediaHdr.bytes()));
|
||||
oxReturnError(w.write(fsBuff.data(), fsBuff.size()));
|
||||
oxReturnError(padbin(w, hdrSize));
|
||||
oxReturnError(w.write(fsBuff->data(), fsBuff->size()));
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(preloadHdr.data(), preloadHdr.bytes()));
|
||||
oxReturnError(pl.offsetPtrs(binBuff.size()));
|
||||
const auto &plBuff = pl.buff();
|
||||
oxReturnError(pl->offsetPtrs(binBuff->size()));
|
||||
const auto &plBuff = pl->buff();
|
||||
oxReturnError(w.write(plBuff.data(), plBuff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
ox::Error preload(ox::TypeStore &ts, ox::FileSystem &src, ox::Preloader<PlatSpec> &pl) noexcept {
|
||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, ox::Preloader<PlatSpec> *pl) noexcept {
|
||||
oxOut("Preloading\n");
|
||||
return detail::preloadDir(ts, src, pl, "/");
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include <keel/keel.hpp>
|
||||
|
||||
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
"writeUuidHeader",
|
||||
[]() -> ox::Error {
|
@ -4,19 +4,20 @@
|
||||
|
||||
#include <ox/claw/read.hpp>
|
||||
|
||||
#include <keel/media.hpp>
|
||||
#include <keel/typeconv.hpp>
|
||||
#include "media.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
[[nodiscard]]
|
||||
static ox::Result<const BaseConverter*> findConverter(
|
||||
ox::Vector<const BaseConverter*> const&converters,
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView srcTypeName,
|
||||
int srcTypeVersion,
|
||||
ox::CRStringView dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
||||
for (auto &c : converters) {
|
||||
for (auto &c : ctx->converters) {
|
||||
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
|
||||
return c;
|
||||
}
|
||||
@ -25,48 +26,41 @@ static ox::Result<const BaseConverter*> findConverter(
|
||||
};
|
||||
|
||||
static ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
[[maybe_unused]] keel::Context &ctx,
|
||||
ox::Vector<const BaseConverter*> const&converters,
|
||||
[[maybe_unused]] keel::Context *ctx,
|
||||
[[maybe_unused]] const ox::Buffer &srcBuffer,
|
||||
[[maybe_unused]] ox::CRStringView srcTypeName,
|
||||
[[maybe_unused]] int srcTypeVersion,
|
||||
[[maybe_unused]] ox::CRStringView dstTypeName,
|
||||
[[maybe_unused]] int dstTypeVersion) noexcept {
|
||||
// look for direct converter
|
||||
auto [c, err] = findConverter(converters, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
|
||||
auto [c, err] = findConverter(ctx, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
|
||||
if (!err) {
|
||||
return c->convertBuffToPtr(ctx, srcBuffer);
|
||||
}
|
||||
// try to chain multiple converters
|
||||
for (const auto &subConverter : converters) {
|
||||
for (const auto &subConverter : ctx->converters) {
|
||||
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
|
||||
continue;
|
||||
}
|
||||
const auto [intermediate, chainErr] =
|
||||
convert(ctx, converters, srcBuffer, srcTypeName, srcTypeVersion,
|
||||
convert(ctx, srcBuffer, srcTypeName, srcTypeVersion,
|
||||
subConverter->srcTypeName(), subConverter->srcTypeVersion());
|
||||
if (!chainErr) {
|
||||
return subConverter->convertPtrToPtr(ctx, *intermediate);
|
||||
return subConverter->convertPtrToPtr(ctx, intermediate.get());
|
||||
}
|
||||
}
|
||||
return OxError(1, "Could not convert between types");
|
||||
}
|
||||
#endif
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
[[maybe_unused]] keel::Context &ctx,
|
||||
[[maybe_unused]] keel::Context *ctx,
|
||||
[[maybe_unused]] const ox::Buffer &srcBuffer,
|
||||
[[maybe_unused]] ox::CRStringView dstTypeName,
|
||||
[[maybe_unused]] int dstTypeVersion) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(hdr, readAssetHeader(srcBuffer));
|
||||
return convert(
|
||||
ctx,
|
||||
ctx.converters,
|
||||
srcBuffer,
|
||||
hdr.clawHdr.typeName,
|
||||
hdr.clawHdr.typeVersion,
|
||||
dstTypeName,
|
||||
dstTypeVersion);
|
||||
return convert(ctx, srcBuffer, hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, dstTypeName, dstTypeVersion);
|
||||
#else
|
||||
return OxError(1, "Operation not supported on this platform");
|
||||
#endif
|
@ -67,8 +67,8 @@ constexpr auto makeWrap(Args &&...args) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T *wrapCast(Wrap &ptr) noexcept {
|
||||
return static_cast<WrapInline<T>&>(ptr).obj();
|
||||
constexpr auto wrapCast(auto ptr) noexcept {
|
||||
return static_cast<WrapInline<T>*>(ptr)->obj();
|
||||
}
|
||||
|
||||
class BaseConverter {
|
||||
@ -87,14 +87,13 @@ class BaseConverter {
|
||||
[[nodiscard]]
|
||||
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
||||
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context *ctx, Wrap *src) const noexcept = 0;
|
||||
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context &ctx, const ox::Buffer &srcBuff) const noexcept = 0;
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context *ctx, const ox::Buffer &srcBuff) const noexcept = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool matches(
|
||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
||||
inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
||||
return srcMatches(srcTypeName, srcTypeVersion)
|
||||
&& dstMatches(dstTypeName, dstTypeVersion);
|
||||
}
|
||||
@ -130,30 +129,29 @@ class Converter: public BaseConverter {
|
||||
&& dstTypeVersion == DstTypeVersion;
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept final {
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context *ctx, Wrap *src) const noexcept final {
|
||||
auto dst = makeWrap<DstType>();
|
||||
oxReturnError(convert(ctx, *wrapCast<SrcType>(src), *wrapCast<DstType>(*dst)));
|
||||
oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(dst.get())));
|
||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept final {
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context *ctx, const ox::Buffer &srcBuff) const noexcept final {
|
||||
oxRequireM(src, readAsset<SrcType>(srcBuff));
|
||||
auto dst = makeWrap<DstType>();
|
||||
oxReturnError(convert(ctx, src, *wrapCast<DstType>(*dst)));
|
||||
oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get())));
|
||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ox::Error convert(keel::Context &ctx, SrcType&, DstType&) const noexcept = 0;
|
||||
virtual ox::Error convert(keel::Context *ctx, SrcType*, DstType*) const noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
keel::Context &ctx, const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(keel::Context *ctx, const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<DstType> convert(keel::Context &ctx, const ox::Buffer &srcBuffer) noexcept {
|
||||
ox::Result<DstType> convert(keel::Context *ctx, const ox::Buffer &srcBuffer) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||
@ -161,29 +159,29 @@ ox::Result<DstType> convert(keel::Context &ctx, const ox::Buffer &srcBuffer) noe
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Error convert(keel::Context &ctx, const ox::Buffer &buff, DstType *outObj) noexcept {
|
||||
ox::Error convert(keel::Context *ctx, const ox::Buffer &buff, DstType *outObj) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
||||
*outObj = std::move(*wrapCast<DstType>(*outPtr));
|
||||
*outObj = std::move(*wrapCast<DstType>(outPtr.get()));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(keel::Context &ctx, const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(keel::Context *ctx, const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||
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), fmt);
|
||||
return ox::writeClaw<DstType>(*wrapCast<DstType>(out.get()), fmt);
|
||||
}
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
auto transformRule(keel::Context &ctx, ox::Buffer &buff) noexcept -> ox::Error {
|
||||
oxRequire(hdr, readAssetHeader(buff));
|
||||
auto transformRule(keel::Context *ctx, ox::Buffer *buff) noexcept -> ox::Error {
|
||||
oxRequire(hdr, readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<From>()) {
|
||||
oxReturnError(keel::convertBuffToBuff<To>(ctx, buff, fmt).moveTo(&buff));
|
||||
oxReturnError(keel::convertBuffToBuff<To>(ctx, *buff, fmt).moveTo(buff));
|
||||
}
|
||||
return {};
|
||||
};
|
@ -2,18 +2,18 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/typestore.hpp>
|
||||
#include "typestore.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
TypeStore::TypeStore(ox::FileSystem &fs, ox::StringView descPath) noexcept:
|
||||
TypeStore::TypeStore(ox::FileSystem *fs, ox::String descPath) noexcept:
|
||||
m_fs(fs),
|
||||
m_descPath(std::move(descPath)) {
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> TypeStore::loadDescriptor(ox::CRStringView typeId) noexcept {
|
||||
auto path = ox::sfmt("{}/{}", m_descPath, typeId);
|
||||
oxRequire(buff, m_fs.read(path));
|
||||
oxRequire(buff, m_fs->read(path));
|
||||
auto dt = ox::make_unique<ox::DescriptorType>();
|
||||
oxReturnError(ox::readClaw<ox::DescriptorType>(buff, dt.get()));
|
||||
return dt;
|
@ -12,11 +12,11 @@ namespace keel {
|
||||
|
||||
class TypeStore: public ox::TypeStore {
|
||||
private:
|
||||
ox::FileSystem &m_fs;
|
||||
ox::FileSystem *m_fs = nullptr;
|
||||
ox::String m_descPath;
|
||||
|
||||
public:
|
||||
explicit TypeStore(ox::FileSystem &fs, ox::StringView descPath) noexcept;
|
||||
explicit TypeStore(ox::FileSystem *fs, ox::String descPath) noexcept;
|
||||
|
||||
protected:
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> loadDescriptor(ox::CRStringView typeId) noexcept override;
|
@ -3,6 +3,7 @@
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(scene)
|
||||
|
||||
|
||||
# module libraries
|
||||
|
||||
# Keel
|
||||
@ -42,11 +43,3 @@ if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
include/nostalgia/modules
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(NostalgiaProfile INTERFACE)
|
||||
target_compile_definitions(
|
||||
NostalgiaProfile INTERFACE
|
||||
OLYMPIC_PROJECT_NAME="Nostalgia"
|
||||
OLYMPIC_PROJECT_NAMESPACE=nostalgia
|
||||
OLYMPIC_PROJECT_DATADIR=".nostalgia"
|
||||
)
|
||||
|
@ -5,6 +5,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/point.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace turbine::config {
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
constexpr bool GlFpsPrint = TURBINE_GL_FPS_PRINT;
|
||||
namespace nostalgia::core::config {
|
||||
|
||||
}
|
@ -15,15 +15,19 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class Context;
|
||||
// User Input Output
|
||||
class Context {
|
||||
|
||||
public:
|
||||
Context() noexcept = default;
|
||||
Context(Context &other) noexcept = delete;
|
||||
Context(const Context &other) noexcept = delete;
|
||||
Context(const Context &&other) noexcept = delete;
|
||||
virtual ~Context() noexcept = default;
|
||||
|
||||
struct ContextDeleter {
|
||||
void operator()(Context *p) noexcept;
|
||||
};
|
||||
|
||||
using ContextUPtr = ox::UPtr<Context, ContextDeleter>;
|
||||
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept;
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, const InitParams& = {}) noexcept;
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,56 +36,48 @@ oxModelBegin(Sprite)
|
||||
oxModelEnd()
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t bgStatus(Context &ctx) noexcept;
|
||||
uint8_t bgStatus(Context *ctx) noexcept;
|
||||
|
||||
void setBgStatus(Context &ctx, uint32_t status) noexcept;
|
||||
void setBgStatus(Context *ctx, uint32_t status) noexcept;
|
||||
|
||||
bool bgStatus(Context &ctx, unsigned bg) noexcept;
|
||||
bool bgStatus(Context *ctx, unsigned bg) noexcept;
|
||||
|
||||
void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept;
|
||||
void setBgStatus(Context *ctx, unsigned bg, bool status) noexcept;
|
||||
|
||||
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept;
|
||||
void setBgCbb(Context *ctx, unsigned bgIdx, unsigned cbb) noexcept;
|
||||
|
||||
/**
|
||||
* @param section describes which section of the selected TileSheetSpace to use (e.g. MEM_PALLETE_BG[section])
|
||||
*/
|
||||
ox::Error loadBgTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr = nullptr) noexcept;
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept;
|
||||
|
||||
ox::Error initConsole(Context &ctx) noexcept;
|
||||
ox::Error initConsole(Context *ctx) noexcept;
|
||||
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept;
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept;
|
||||
|
||||
void setTile(Context &ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
|
||||
void clearTileLayer(Context &ctx, unsigned bgIdx) noexcept;
|
||||
void clearTileLayer(Context *ctx, unsigned bgIdx) noexcept;
|
||||
|
||||
void hideSprite(Context &ctx, unsigned) noexcept;
|
||||
void hideSprite(Context *ctx, unsigned) noexcept;
|
||||
|
||||
void setSprite(Context &ctx, unsigned idx, int x, int y, unsigned tileIdx,
|
||||
void setSprite(Context *ctx, unsigned idx, int x, int y, unsigned tileIdx,
|
||||
unsigned spriteShape = 0, unsigned spriteSize = 0, unsigned flipX = 0) noexcept;
|
||||
|
||||
void setSprite(Context &ctx, Sprite const&s) noexcept;
|
||||
void setSprite(Context *ctx, Sprite const&s) noexcept;
|
||||
|
||||
}
|
||||
|
||||
namespace nostalgia::core::gl {
|
||||
|
||||
constexpr ox::CStringView GlslVersion = "#version 330";
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Size drawSize(int scale = 5) noexcept;
|
||||
|
||||
void draw(core::Context &ctx, ox::Size const&renderSz) noexcept;
|
||||
|
||||
void draw(core::Context&, int scale = 5) noexcept;
|
||||
|
||||
void drawMainView(core::Context&, ox::Size const&) noexcept;
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,12 @@
|
||||
#include <ox/std/point.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
|
||||
#include "color.hpp"
|
||||
#include "context.hpp"
|
||||
#include "ptidxconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/point.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
@ -12,8 +11,10 @@
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
#include <nostalgia/core/ptidxconv.hpp>
|
||||
|
||||
#include "color.hpp"
|
||||
#include "context.hpp"
|
||||
#include "ptidxconv.hpp"
|
||||
#include "palette.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
@ -95,7 +96,7 @@ struct TileSheet {
|
||||
SubSheet &operator=(SubSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t idx(ox::Point const&pt) const noexcept;
|
||||
std::size_t idx(const ox::Point &pt) const noexcept;
|
||||
|
||||
/**
|
||||
* Reads all pixels of this sheet or its children into the given pixel list
|
||||
@ -159,7 +160,7 @@ struct TileSheet {
|
||||
|
||||
void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept;
|
||||
|
||||
void setPixel(int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept;
|
||||
void setPixel(int8_t pBpp, const ox::Point &pt, uint8_t palIdx) noexcept;
|
||||
|
||||
ox::Error setPixelCount(int8_t pBpp, std::size_t cnt) noexcept;
|
||||
|
||||
@ -174,16 +175,19 @@ struct TileSheet {
|
||||
/**
|
||||
* Gets the offset in tiles of the desired subsheet.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
ox::Result<unsigned> getTileOffset(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt = 0,
|
||||
unsigned pCurrentTotal = 0) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<SubSheetId> getIdFor(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
std::size_t pIt = 0) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<ox::StringView> getNameFor(SubSheetId pId) const noexcept;
|
||||
|
||||
};
|
||||
@ -196,7 +200,7 @@ struct TileSheet {
|
||||
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
||||
|
||||
constexpr TileSheet() noexcept = default;
|
||||
TileSheet(TileSheet const&other) noexcept = default;
|
||||
TileSheet(const TileSheet &other) noexcept = default;
|
||||
inline TileSheet(TileSheet &&other) noexcept:
|
||||
bpp(other.bpp),
|
||||
idIt(other.idIt),
|
||||
@ -204,13 +208,13 @@ struct TileSheet {
|
||||
subsheet(std::move(other.subsheet)) {
|
||||
}
|
||||
|
||||
TileSheet &operator=(TileSheet const&other) noexcept;
|
||||
TileSheet &operator=(const TileSheet &other) noexcept;
|
||||
|
||||
TileSheet &operator=(TileSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheetIdx validateSubSheetIdx(
|
||||
SubSheetIdx const&pIdx,
|
||||
const SubSheetIdx &pIdx,
|
||||
std::size_t pIdxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
@ -225,43 +229,43 @@ struct TileSheet {
|
||||
SubSheetIdx validateSubSheetIdx(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static SubSheet const&getSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
static const SubSheet &getSubSheet(
|
||||
const SubSheetIdx &idx,
|
||||
std::size_t idxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static SubSheet &getSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
const SubSheetIdx &idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const SubSheet &getSubSheet(SubSheetIdx const&idx) const noexcept;
|
||||
const SubSheet &getSubSheet(const SubSheetIdx &idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheet &getSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
SubSheet &getSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
ox::Error addSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
ox::Error addSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Error rmSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
const SubSheetIdx &idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Error rmSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
ox::Error rmSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
const ox::Point &pt,
|
||||
const SubSheetIdx &subsheetIdx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
const ox::Point &pt,
|
||||
const SubSheetIdx &subsheetIdx) const noexcept;
|
||||
|
||||
ox::Result<SubSheetId> getIdFor(ox::CRStringView path) const noexcept;
|
||||
|
||||
@ -274,8 +278,6 @@ struct TileSheet {
|
||||
|
||||
};
|
||||
|
||||
using TileSheetV3 = TileSheet;
|
||||
|
||||
struct CompactTileSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
@ -307,7 +309,7 @@ oxModelBegin(TileSheetV2)
|
||||
oxModelField(subsheet)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV3::SubSheet)
|
||||
oxModelBegin(TileSheet::SubSheet)
|
||||
oxModelField(name);
|
||||
oxModelField(rows);
|
||||
oxModelField(columns);
|
||||
@ -315,7 +317,7 @@ oxModelBegin(TileSheetV3::SubSheet)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV3)
|
||||
oxModelBegin(TileSheet)
|
||||
oxModelField(bpp)
|
||||
oxModelField(idIt)
|
||||
oxModelField(defaultPalette)
|
||||
|
@ -12,10 +12,9 @@ target_link_libraries(
|
||||
NostalgiaCore-GBA PUBLIC
|
||||
TeaGBA
|
||||
Keel
|
||||
Turbine
|
||||
)
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "GBA")
|
||||
set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm)
|
||||
target_link_libraries(NostalgiaCore PUBLIC NostalgiaCore-GBA)
|
||||
endif()
|
||||
endif()
|
@ -8,19 +8,15 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
void ContextDeleter::operator()(Context *p) noexcept {
|
||||
ox::safeDelete(p);
|
||||
GbaContext::GbaContext(turbine::Context *tctx) noexcept: turbineCtx(tctx) {
|
||||
}
|
||||
|
||||
Context::Context(turbine::Context &tctx) noexcept: turbineCtx(tctx) {
|
||||
}
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<Context>(tctx);
|
||||
oxReturnError(initGfx(*ctx, params));
|
||||
return ContextUPtr(std::move(ctx));
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<GbaContext>(tctx);
|
||||
oxReturnError(initGfx(ctx.get(), params));
|
||||
return ox::UPtr<Context>(ctx.release());
|
||||
}
|
||||
|
||||
}
|
@ -8,21 +8,16 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class Context {
|
||||
struct GbaContext: public core::Context {
|
||||
|
||||
public:
|
||||
turbine::Context &turbineCtx;
|
||||
turbine::Context const*turbineCtx = nullptr;
|
||||
|
||||
explicit Context(turbine::Context &tctx) noexcept;
|
||||
Context(Context &other) noexcept = delete;
|
||||
Context(Context const&other) noexcept = delete;
|
||||
Context(Context const&&other) noexcept = delete;
|
||||
virtual ~Context() noexcept = default;
|
||||
explicit GbaContext(turbine::Context *tctx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::MemFS const&rom() const noexcept {
|
||||
return static_cast<ox::MemFS const&>(*turbine::rom(turbineCtx));
|
||||
}
|
||||
[[nodiscard]]
|
||||
auto const&rom() const noexcept {
|
||||
return *turbine::rom(*turbineCtx);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -71,45 +71,44 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t)
|
||||
return io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
}
|
||||
|
||||
ox::Error initGfx(Context&, InitParams const&) noexcept {
|
||||
ox::Error initGfx(Context*, InitParams const&) noexcept {
|
||||
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
||||
teagba::bgSetSbb(bgCtl, 28);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context&) noexcept {
|
||||
void shutdownGfx(Context*) noexcept {
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context*) noexcept {
|
||||
return (REG_DISPCTL >> 8u) & 0b1111u;
|
||||
}
|
||||
|
||||
void setBgStatus(Context&, uint32_t status) noexcept {
|
||||
void setBgStatus(Context*, uint32_t status) noexcept {
|
||||
constexpr auto BgStatus = 8;
|
||||
REG_DISPCTL = (REG_DISPCTL & ~0b111100000000u) | status << BgStatus;
|
||||
}
|
||||
|
||||
bool bgStatus(Context&, unsigned bg) noexcept {
|
||||
bool bgStatus(Context*, unsigned bg) noexcept {
|
||||
return (REG_DISPCTL >> (8 + bg)) & 1;
|
||||
}
|
||||
|
||||
void setBgStatus(Context&, unsigned bg, bool status) noexcept {
|
||||
void setBgStatus(Context*, unsigned bg, bool status) noexcept {
|
||||
constexpr auto Bg0Status = 8;
|
||||
const auto mask = static_cast<uint32_t>(status) << (Bg0Status + bg);
|
||||
REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask);
|
||||
}
|
||||
|
||||
static void setBgCbb(Context*, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
void setBgCbb(Context*, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
auto &bgCtl = regBgCtl(bgIdx);
|
||||
const auto &cbbData = g_cbbData[cbb];
|
||||
teagba::bgSetBpp(&bgCtl, cbbData.bpp);
|
||||
teagba::bgSetCbb(&bgCtl, cbb);
|
||||
}
|
||||
|
||||
void setBgCbb(Context&, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
setBgCbb(nullptr, bgIdx, cbb);
|
||||
}
|
||||
|
||||
static ox::Error loadBgTileSheet(
|
||||
ox::MemFS const&rom,
|
||||
const ox::MemFS &rom,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
@ -137,20 +136,22 @@ static ox::Error loadBgTileSheet(
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
return loadBgTileSheet(rom, cbb, tilesheetAddr, paletteAddr);
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
oxRequire(tsStat, ctx.rom().stat(tilesheetAddr));
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
oxRequire(tsStat, gctx.rom().stat(tilesheetAddr));
|
||||
oxRequire(ts, rom.directAccess(tilesheetAddr));
|
||||
GbaTileMapTarget target;
|
||||
target.pal.palette = MEM_SPRITE_PALETTE;
|
||||
@ -158,25 +159,27 @@ ox::Error loadSpriteTileSheet(
|
||||
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
|
||||
// load external palette if available
|
||||
if (paletteAddr) {
|
||||
oxRequire(palStat, ctx.rom().stat(paletteAddr));
|
||||
oxRequire(palStat, gctx.rom().stat(paletteAddr));
|
||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target.pal));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadBgPalette(Context &ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
ox::Error loadBgPalette(Context *ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
GbaPaletteTarget target;
|
||||
target.palette = MEM_BG_PALETTE;
|
||||
oxRequire(palStat, ctx.rom().stat(paletteAddr));
|
||||
oxRequire(palStat, gctx.rom().stat(paletteAddr));
|
||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target));
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadSpritePalette(Context &ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
ox::Error loadSpritePalette(Context *ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
GbaPaletteTarget target;
|
||||
target.palette = &MEM_SPRITE_PALETTE[cbb];
|
||||
oxRequire(palStat, rom.stat(paletteAddr));
|
||||
@ -185,16 +188,25 @@ ox::Error loadSpritePalette(Context &ctx, unsigned cbb, ox::FileAddress const&pa
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error initConsole(Context &ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
|
||||
// Do NOT rely on Context in the GBA version of this function.
|
||||
ox::Error initConsole(Context *ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
|
||||
setBgStatus(ctx, 0b0001);
|
||||
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return {};
|
||||
if (!ctx) {
|
||||
oxRequire(rom, keel::loadRom());
|
||||
const ox::FileSystem32 romFs(ox::FileStore32(rom, 32 * ox::units::MB));
|
||||
oxReturnError(loadBgTileSheet(romFs, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(nullptr, 0, 0);
|
||||
return {};
|
||||
} else {
|
||||
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
const auto col = static_cast<unsigned>(column);
|
||||
for (auto i = 0u; i < str.bytes(); i++) {
|
||||
const auto c = charMap[static_cast<std::size_t>(str[i])];
|
||||
@ -202,18 +214,18 @@ void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void setTile(Context&, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
|
||||
void setTile(Context*, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
|
||||
const auto tileIdx = static_cast<std::size_t>(row * GbaTileColumns + column);
|
||||
MEM_BG_MAP[bgIdx][tileIdx] = tile;
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void clearTileLayer(Context&, unsigned bgIdx) noexcept {
|
||||
void clearTileLayer(Context*, unsigned bgIdx) noexcept {
|
||||
memset(MEM_BG_MAP[bgIdx].data(), 0, GbaTileRows * GbaTileColumns);
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context&, unsigned idx) noexcept {
|
||||
void hideSprite(Context*, unsigned idx) noexcept {
|
||||
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
|
||||
teagba::GbaSpriteAttrUpdate oa;
|
||||
oa.attr0 = 2 << 8;
|
||||
@ -221,7 +233,7 @@ void hideSprite(Context&, unsigned idx) noexcept {
|
||||
teagba::addSpriteUpdate(oa);
|
||||
}
|
||||
|
||||
void setSprite(Context&,
|
||||
void setSprite(Context*,
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -7,5 +7,5 @@
|
||||
#include <nostalgia/core/context.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
}
|
||||
|
@ -3,44 +3,33 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <ox/std/def.hpp>
|
||||
|
||||
#include <keel/media.hpp>
|
||||
#include <turbine/turbine.hpp>
|
||||
#include <nostalgia/core/core.hpp>
|
||||
|
||||
#include <teagba/addresses.hpp>
|
||||
#include <teagba/bios.hpp>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <teagba/gfx.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
|
||||
#define HEAP_BEGIN (reinterpret_cast<char*>(MEM_EWRAM_BEGIN))
|
||||
#define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2)
|
||||
#define HEAP_END (reinterpret_cast<char*>(MEM_EWRAM_BEGIN + HEAP_SIZE))
|
||||
|
||||
namespace ox {
|
||||
|
||||
using namespace nostalgia::core;
|
||||
|
||||
void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept {
|
||||
// reset heap to make sure we have enough memory to allocate context data
|
||||
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
|
||||
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
|
||||
auto ctx = init(*tctx).unwrap();
|
||||
oxIgnoreError(initGfx(*ctx, {}));
|
||||
oxIgnoreError(initConsole(*ctx));
|
||||
setBgStatus(*ctx, 0, true);
|
||||
clearTileLayer(*ctx, 0);
|
||||
oxIgnoreError(initGfx(nullptr, {}));
|
||||
oxIgnoreError(initConsole(nullptr));
|
||||
// enable only BG 0
|
||||
REG_DISPCTL = teagba::DispCtl_Bg0;
|
||||
clearTileLayer(nullptr, 0);
|
||||
ox::BString<23> serr = "Error code: ";
|
||||
serr += static_cast<int64_t>(err);
|
||||
puts(*ctx, 32 + 1, 1, "SADNESS...");
|
||||
puts(*ctx, 32 + 1, 4, "UNEXPECTED STATE:");
|
||||
puts(*ctx, 32 + 2, 6, panicMsg);
|
||||
puts(nullptr, 32 + 1, 1, "SADNESS...");
|
||||
puts(nullptr, 32 + 1, 4, "UNEXPECTED STATE:");
|
||||
puts(nullptr, 32 + 2, 6, panicMsg);
|
||||
if (err) {
|
||||
puts(*ctx, 32 + 2, 8, serr);
|
||||
puts(nullptr, 32 + 2, 8, serr);
|
||||
}
|
||||
puts(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
|
||||
puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
|
||||
// print to terminal if in mGBA
|
||||
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
|
||||
if (err.msg) {
|
||||
|
@ -43,7 +43,7 @@ ox::Array<char, 128> charMap = {
|
||||
0, // space
|
||||
38, // !
|
||||
0, // "
|
||||
49, // #
|
||||
0, // #
|
||||
0, // $
|
||||
0, // %
|
||||
0, // &
|
||||
@ -132,12 +132,12 @@ ox::Array<char, 128> charMap = {
|
||||
25, // y
|
||||
26, // z
|
||||
46, // {
|
||||
51, // |
|
||||
0, // |
|
||||
48, // }
|
||||
50, // ~
|
||||
0, // ~
|
||||
};
|
||||
|
||||
void setSprite(Context &c, Sprite const&s) noexcept {
|
||||
void setSprite(Context *c, const Sprite &s) noexcept {
|
||||
setSprite(c, s.idx, s.x, s.y, s.tileIdx, s.spriteShape, s.spriteSize, s.flipX);
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ namespace nostalgia::core {
|
||||
class KeelModule: public keel::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
|
||||
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetConverter;
|
||||
TileSheetV1ToTileSheetConverter m_tileSheetV1ToTileSheetV2Converter;
|
||||
TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter m_tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
ox::String id() const noexcept override {
|
||||
return ox::String("net.drinkingtea.nostalgia.core");
|
||||
return "net.drinkingtea.nostalgia.core";
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -52,15 +52,15 @@ class KeelModule: public keel::Module {
|
||||
ox::Vector<keel::PackTransform> packTransforms() const noexcept final {
|
||||
return {
|
||||
// convert tilesheets to CompactTileSheets
|
||||
[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
|
||||
oxRequire(hdr, keel::readAssetHeader(buff));
|
||||
[](keel::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, keel::readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<TileSheetV1>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV2>() ||
|
||||
typeId == ox::buildTypeId<TileSheet>()) {
|
||||
oxReturnError(keel::convertBuffToBuff<core::CompactTileSheet>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(&buff));
|
||||
ctx, *buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
@ -7,59 +7,60 @@
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error NostalgiaPaletteToPaletteConverter::convert(
|
||||
keel::Context&,
|
||||
NostalgiaPalette &src,
|
||||
Palette &dst) const noexcept {
|
||||
dst.colors = std::move(src.colors);
|
||||
keel::Context*,
|
||||
NostalgiaPalette *src,
|
||||
Palette *dst) const noexcept {
|
||||
dst->colors = std::move(src->colors);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error TileSheetV1ToTileSheetV2Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV1 &src,
|
||||
TileSheetV2 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
dst.subsheet.name = "Root";
|
||||
dst.subsheet.rows = src.rows;
|
||||
dst.subsheet.columns = src.columns;
|
||||
dst.subsheet.pixels = std::move(src.pixels);
|
||||
return {};
|
||||
}
|
||||
|
||||
void TileSheetV2ToTileSheetV3Converter::convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept {
|
||||
dst.id = idIt;
|
||||
dst.name = std::move(src.name);
|
||||
dst.columns = src.columns;
|
||||
dst.rows = src.rows;
|
||||
dst.pixels = std::move(src.pixels);
|
||||
++idIt;
|
||||
dst.subsheets.resize(src.subsheets.size());
|
||||
for (auto i = 0u; i < src.subsheets.size(); ++i) {
|
||||
convertSubsheet(src.subsheets[i], dst.subsheets[i], idIt);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetV2ToTileSheetV3Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV2 &src,
|
||||
TileSheetV3 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
|
||||
ox::Error TileSheetV1ToTileSheetConverter::convert(
|
||||
keel::Context*,
|
||||
TileSheetV1 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
dst->subsheet.name = "Root";
|
||||
dst->subsheet.rows = src->rows;
|
||||
dst->subsheet.columns = src->columns;
|
||||
dst->subsheet.pixels = std::move(src->pixels);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error TileSheetToCompactTileSheetConverter::convert(
|
||||
keel::Context&,
|
||||
TileSheet &src,
|
||||
CompactTileSheet &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
dst.pixels = src.pixels();
|
||||
keel::Context*,
|
||||
TileSheet *src,
|
||||
CompactTileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
dst->pixels = src->pixels();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void TileSheetV2ToTileSheetConverter::convertSubsheet(
|
||||
TileSheetV2::SubSheet *src,
|
||||
TileSheet::SubSheet *dst,
|
||||
SubSheetId *idIt) noexcept {
|
||||
dst->id = *idIt;
|
||||
dst->name = std::move(src->name);
|
||||
dst->columns = src->columns;
|
||||
dst->rows = src->rows;
|
||||
dst->pixels = std::move(src->pixels);
|
||||
++*idIt;
|
||||
dst->subsheets.resize(src->subsheets.size());
|
||||
for (auto i = 0u; i < src->subsheets.size(); ++i) {
|
||||
convertSubsheet(&src->subsheets[i], &dst->subsheets[i], idIt);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetV2ToTileSheetConverter::convert(
|
||||
keel::Context*,
|
||||
TileSheetV2 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
convertSubsheet(&src->subsheet, &dst->subsheet, &dst->idIt);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -17,23 +17,25 @@ namespace nostalgia::core {
|
||||
// Type converters
|
||||
|
||||
class NostalgiaPaletteToPaletteConverter: public keel::Converter<NostalgiaPalette, Palette> {
|
||||
ox::Error convert(keel::Context&, NostalgiaPalette &src, Palette &dst) const noexcept final;
|
||||
ox::Error convert(keel::Context*, NostalgiaPalette *src, Palette *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> {
|
||||
ox::Error convert(keel::Context&, TileSheetV1 &src, TileSheetV2 &dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV2ToTileSheetV3Converter: public keel::Converter<TileSheetV2, TileSheetV3> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept;
|
||||
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
|
||||
class TileSheetV1ToTileSheetConverter: public keel::Converter<TileSheetV1, TileSheet> {
|
||||
ox::Error convert(keel::Context*, TileSheetV1 *src, TileSheet *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> {
|
||||
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
|
||||
ox::Error convert(keel::Context*, TileSheet *src, CompactTileSheet *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV2ToTileSheetConverter: public keel::Converter<TileSheetV2, TileSheet> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet *src,
|
||||
TileSheet::SubSheet *dst,
|
||||
SubSheetId *idIt) noexcept;
|
||||
|
||||
ox::Error convert(keel::Context*, TileSheetV2 *src, TileSheet *dst) const noexcept final;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -7,23 +7,19 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
void ContextDeleter::operator()(Context *p) noexcept {
|
||||
ox::safeDelete(p);
|
||||
}
|
||||
|
||||
Context::Context(turbine::Context &tctx) noexcept:
|
||||
GlContext::GlContext(turbine::Context &tctx) noexcept:
|
||||
turbineCtx(tctx),
|
||||
drawer(*this) {
|
||||
}
|
||||
|
||||
Context::~Context() noexcept {
|
||||
GlContext::~GlContext() noexcept {
|
||||
shutdownGfx(*this);
|
||||
}
|
||||
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<Context>(tctx);
|
||||
oxReturnError(initGfx(*ctx, params));
|
||||
return ContextUPtr(ctx.release());
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<GlContext>(*tctx);
|
||||
oxReturnError(initGfx(ctx.get(), params));
|
||||
return ox::UPtr<Context>(ctx.release());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,19 +15,18 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class Context {
|
||||
|
||||
public:
|
||||
turbine::Context &turbineCtx;
|
||||
glutils::GLProgram bgShader;
|
||||
glutils::GLProgram spriteShader;
|
||||
ox::Array<renderer::CBB, 4> cbbs;
|
||||
renderer::SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<renderer::Background, 4> backgrounds;
|
||||
renderer::Drawer drawer;
|
||||
explicit Context(turbine::Context &tctx) noexcept;
|
||||
~Context() noexcept;
|
||||
struct GlContext: public core::Context {
|
||||
turbine::Context &turbineCtx;
|
||||
glutils::GLProgram bgShader;
|
||||
glutils::GLProgram spriteShader;
|
||||
ox::Array<renderer::CBB, 4> cbbs;
|
||||
renderer::SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<renderer::Background, 4> backgrounds;
|
||||
ox::Optional<ox::Size> renderSize;
|
||||
renderer::Drawer drawer;
|
||||
explicit GlContext(turbine::Context &tctx) noexcept;
|
||||
~GlContext() noexcept override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -15,25 +15,32 @@
|
||||
#include <nostalgia/core/tilesheet.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "gfx.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
constexpr auto Scale = 1;
|
||||
[[nodiscard]]
|
||||
inline GlContext &glctx(Context &ctx) noexcept {
|
||||
if constexpr(ox::defines::Debug) {
|
||||
return dynamic_cast<GlContext&>(ctx);
|
||||
} else {
|
||||
return static_cast<GlContext&>(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto Scale = 5;
|
||||
|
||||
namespace renderer {
|
||||
|
||||
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
|
||||
|
||||
void Drawer::draw(turbine::Context &tctx) noexcept {
|
||||
core::gl::draw(m_ctx, turbine::getScreenSize(tctx));
|
||||
core::gl::drawMainView(m_ctx, turbine::getScreenSize(tctx));
|
||||
}
|
||||
|
||||
constexpr ox::StringView bgvshadTmpl = R"glsl(
|
||||
constexpr ox::StringView bgvshadTmpl = R"(
|
||||
{}
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
in float vTileIdx;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
@ -42,12 +49,10 @@ constexpr ox::StringView bgvshadTmpl = R"glsl(
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vec2(
|
||||
vTexCoord.x,
|
||||
vTexCoord.y * vTileHeight + vTileIdx * vTileHeight);
|
||||
})glsl";
|
||||
fTexCoord = vTexCoord;
|
||||
})";
|
||||
|
||||
constexpr ox::StringView bgfshadTmpl = R"glsl(
|
||||
constexpr ox::StringView bgfshadTmpl = R"(
|
||||
{}
|
||||
out vec4 outColor;
|
||||
in vec2 fTexCoord;
|
||||
@ -63,11 +68,21 @@ constexpr ox::StringView bgfshadTmpl = R"glsl(
|
||||
void main() {
|
||||
pixelSz = vec2(1, 1) / (fSrcImgSz);
|
||||
vec2 pixelCoord = floor(fTexCoord / pixelSz) * pixelSz;
|
||||
vec4 c0 = getColor(pixelCoord + pixelSz * vec2(0, 0));
|
||||
vec4 c1 = getColor(pixelCoord + pixelSz * vec2(0.75, 0));
|
||||
vec4 c2 = getColor(pixelCoord + pixelSz * vec2(0, 0.75));
|
||||
vec4 c3 = getColor(pixelCoord + pixelSz * vec2(0.75, 0.75));
|
||||
float u = fTexCoord.x - fTexCoord.x / pixelSz.x;
|
||||
float v = fTexCoord.y - fTexCoord.y / pixelSz.y;
|
||||
vec4 b0 = (1.0 - u) * c0 + u * c1;
|
||||
vec4 b1 = (1.0 - u) * c2 + u * c3;
|
||||
outColor = (1.0 - v) * b0 + u * b1;
|
||||
outColor = fPalette[int(texture(image, fTexCoord).rgb.r * 256)];
|
||||
//outColor = fPalette[int(texture(image, pixelCoord).rgb.r * 256)];
|
||||
//outColor = vec4(0.0, 0.7, 1.0, 1.0);
|
||||
})glsl";
|
||||
})";
|
||||
|
||||
constexpr ox::StringView spritevshadTmpl = R"glsl(
|
||||
constexpr ox::StringView spritevshadTmpl = R"(
|
||||
{}
|
||||
in float vEnabled;
|
||||
in vec2 vTexCoord;
|
||||
@ -81,7 +96,7 @@ constexpr ox::StringView spritevshadTmpl = R"glsl(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight) * vec2(vEnabled, vEnabled);
|
||||
})glsl";
|
||||
})";
|
||||
|
||||
constexpr ox::StringView spritefshadTmpl = bgfshadTmpl;
|
||||
|
||||
@ -127,7 +142,8 @@ static void setTileBufferObject(
|
||||
uint_t vi,
|
||||
float x,
|
||||
float y,
|
||||
float textureTileIdx,
|
||||
float textureYOffset,
|
||||
float tileHeight,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
@ -137,14 +153,14 @@ static void setTileBufferObject(
|
||||
y *= -ymod;
|
||||
x -= 1.0f;
|
||||
y += 1.0f - ymod;
|
||||
ox::Array<float, BgVertexVboLength> const vertices {
|
||||
x, y, 0, 1, textureTileIdx, // bottom left
|
||||
x + xmod, y, 1, 1, textureTileIdx, // bottom right
|
||||
x + xmod, y + ymod, 1, 0, textureTileIdx, // top right
|
||||
x, y + ymod, 0, 0, textureTileIdx, // top left
|
||||
const ox::Array<float, BgVertexVboLength> vertices {
|
||||
x, y, 0, tileHeight + textureYOffset, // bottom left
|
||||
x + xmod, y, 1, tileHeight + textureYOffset, // bottom right
|
||||
x + xmod, y + ymod, 1, 0 + textureYOffset, // top right
|
||||
x, y + ymod, 0, 0 + textureYOffset, // top left
|
||||
};
|
||||
memcpy(vbo, vertices.data(), sizeof(vertices));
|
||||
ox::Array<GLuint, BgVertexEboLength> const elms {
|
||||
const ox::Array<GLuint, BgVertexEboLength> elms {
|
||||
vi + 0, vi + 1, vi + 2,
|
||||
vi + 2, vi + 3, vi + 0,
|
||||
};
|
||||
@ -170,6 +186,7 @@ static void initBackgroundBufferObjects(glutils::BufferSet &bg) noexcept {
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
0,
|
||||
0,
|
||||
vbo,
|
||||
ebo);
|
||||
}
|
||||
@ -219,16 +236,11 @@ static void initBackgroundBufferset(
|
||||
auto const texCoordAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTexCoord"));
|
||||
glEnableVertexAttribArray(texCoordAttr);
|
||||
glVertexAttribPointer(
|
||||
texCoordAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||
auto const heightMultAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTileIdx"));
|
||||
glEnableVertexAttribArray(heightMultAttr);
|
||||
glVertexAttribPointer(
|
||||
heightMultAttr, 1, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(4 * sizeof(float)));
|
||||
texCoordAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(bg.vertices[0]),
|
||||
reinterpret_cast<void*>(2 * sizeof(bg.vertices[0])));
|
||||
}
|
||||
|
||||
static glutils::GLTexture createTexture(
|
||||
static glutils::GLTexture loadTexture(
|
||||
GLsizei w,
|
||||
GLsizei h,
|
||||
const void *pixels) noexcept {
|
||||
@ -240,8 +252,8 @@ static glutils::GLTexture createTexture(
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width, tex.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
return tex;
|
||||
@ -258,20 +270,20 @@ static void drawBackground(CBB &cbb) noexcept {
|
||||
}
|
||||
|
||||
static void drawBackgrounds(
|
||||
Context &ctx,
|
||||
GlContext &gctx,
|
||||
ox::Size const&renderSz) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(ctx.bgShader);
|
||||
const auto uniformSrcImgSz = glGetUniformLocation(ctx.bgShader, "fSrcImgSz");
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vTileHeight"));
|
||||
glUseProgram(gctx.bgShader);
|
||||
const auto uniformSrcImgSz = glGetUniformLocation(gctx.bgShader, "fSrcImgSz");
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(gctx.bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(gctx.bgShader, "vTileHeight"));
|
||||
const auto [wi, hi] = renderSz;
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
for (const auto &bg : ctx.backgrounds) {
|
||||
for (const auto &bg : gctx.backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = ctx.cbbs[bg.cbbIdx];
|
||||
auto &cbb = gctx.cbbs[bg.cbbIdx];
|
||||
const auto tileRows = cbb.tex.height / (TileHeight * Scale);
|
||||
glUniform1f(uniformTileHeight, 1.0f / static_cast<float>(tileRows));
|
||||
glUniform2f(
|
||||
@ -283,11 +295,11 @@ static void drawBackgrounds(
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
glUseProgram(ctx.spriteShader);
|
||||
auto &sb = ctx.spriteBlocks;
|
||||
const auto uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale");
|
||||
const auto uniformTileHeight = glGetUniformLocation(ctx.spriteShader, "vTileHeight");
|
||||
static void drawSprites(GlContext &gctx, ox::Size const&renderSz) noexcept {
|
||||
glUseProgram(gctx.spriteShader);
|
||||
auto &sb = gctx.spriteBlocks;
|
||||
const auto uniformXScale = glGetUniformLocation(gctx.bgShader, "vXScale");
|
||||
const auto uniformTileHeight = glGetUniformLocation(gctx.spriteShader, "vTileHeight");
|
||||
const auto [wi, hi] = renderSz;
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
@ -326,59 +338,61 @@ static void loadPalette(
|
||||
glUniform4fv(uniformPalette, ColorCnt, palette.data());
|
||||
}
|
||||
|
||||
static void loadBgPalette(Context &ctx, Palette const&pal) noexcept {
|
||||
loadPalette(ctx.bgShader, pal);
|
||||
static void loadBgPalette(GlContext &gctx, Palette const&pal) noexcept {
|
||||
loadPalette(gctx.bgShader, pal);
|
||||
}
|
||||
|
||||
static void loadSpritePalette(Context &ctx, Palette const&pal) noexcept {
|
||||
loadPalette(ctx.spriteShader, pal, true);
|
||||
static void loadSpritePalette(GlContext &gctx, Palette const&pal) noexcept {
|
||||
loadPalette(gctx.spriteShader, pal, true);
|
||||
}
|
||||
|
||||
static void loadBgTexture(
|
||||
Context &ctx,
|
||||
GlContext &gctx,
|
||||
uint_t cbbIdx,
|
||||
const void *pixels,
|
||||
int w,
|
||||
int h) noexcept {
|
||||
oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbbIdx, w, h);
|
||||
ctx.cbbs[cbbIdx].tex = createTexture(w, h, pixels);
|
||||
gctx.cbbs[cbbIdx].tex = loadTexture(w, h, pixels);
|
||||
}
|
||||
|
||||
static void loadSpriteTexture(
|
||||
Context &ctx,
|
||||
GlContext &gctx,
|
||||
const void *pixels,
|
||||
int w,
|
||||
int h) noexcept {
|
||||
oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", w, h);
|
||||
ctx.spriteBlocks.tex = createTexture(w, h, pixels);
|
||||
gctx.spriteBlocks.tex = loadTexture(w, h, pixels);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ox::Error initGfx(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
InitParams const&initParams) noexcept {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion);
|
||||
const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion);
|
||||
const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, gl::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, gl::GlslVersion);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(&ctx.bgShader));
|
||||
const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, glutils::GlslVersion);
|
||||
const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, glutils::GlslVersion);
|
||||
auto &gctx = glctx(*ctx);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad.c_str(), bgFshad.c_str()).moveTo(&gctx.bgShader));
|
||||
oxReturnError(
|
||||
glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(&ctx.spriteShader));
|
||||
for (auto &bg : ctx.cbbs) {
|
||||
initBackgroundBufferset(ctx.bgShader, bg);
|
||||
glutils::buildShaderProgram(spriteVshad.c_str(), spriteFshad.c_str()).moveTo(&gctx.spriteShader));
|
||||
for (auto &bg : gctx.cbbs) {
|
||||
initBackgroundBufferset(gctx.bgShader, bg);
|
||||
}
|
||||
initSpritesBufferset(ctx.spriteShader, ctx.spriteBlocks);
|
||||
initSpritesBufferset(gctx.spriteShader, gctx.spriteBlocks);
|
||||
if (initParams.glInstallDrawer) {
|
||||
turbine::gl::addDrawer(ctx.turbineCtx, &ctx.drawer);
|
||||
turbine::gl::addDrawer(gctx.turbineCtx, &gctx.drawer);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdownGfx(Context &ctx) noexcept {
|
||||
turbine::gl::removeDrawer(ctx.turbineCtx, &ctx.drawer);
|
||||
auto &gctx = glctx(ctx);
|
||||
turbine::gl::removeDrawer(gctx.turbineCtx, &gctx.drawer);
|
||||
}
|
||||
|
||||
struct TileSheetData {
|
||||
@ -392,8 +406,8 @@ struct TileSheetData {
|
||||
};
|
||||
|
||||
static ox::Result<TileSheetData> loadTileSheet(
|
||||
Context &ctx,
|
||||
CompactTileSheet const&tilesheet) noexcept {
|
||||
Context &ctx, CompactTileSheet const&tilesheet) noexcept {
|
||||
auto &gctx = glctx(ctx);
|
||||
const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
|
||||
const auto tiles = tilesheet.pixels.size() / bytesPerTile;
|
||||
constexpr int width = 8;
|
||||
@ -411,52 +425,54 @@ static ox::Result<TileSheetData> loadTileSheet(
|
||||
pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4;
|
||||
}
|
||||
}
|
||||
renderer::loadSpriteTexture(ctx, pixels.data(), width, height);
|
||||
renderer::loadSpriteTexture(gctx, pixels.data(), width, height);
|
||||
return TileSheetData{std::move(pixels), width, height};
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
uint_t cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &kctx = gctx.turbineCtx.keelCtx;
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(&kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(&kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(*ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData {
|
||||
return {
|
||||
.pixels = resizeTileSheetData(t.pixels, t.size(), Scale),
|
||||
.width = t.width * Scale,
|
||||
.height = t.height * Scale,
|
||||
};
|
||||
}));
|
||||
renderer::loadBgTexture(ctx, cbb, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadBgPalette(ctx, *palette);
|
||||
renderer::loadBgTexture(gctx, cbb, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadBgPalette(gctx, *palette);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(ctx, *tilesheet));
|
||||
renderer::loadSpriteTexture(ctx, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadSpritePalette(ctx, *palette);
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &kctx = gctx.turbineCtx.keelCtx;
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(&kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(&kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(*ctx, *tilesheet));
|
||||
renderer::loadSpriteTexture(gctx, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadSpritePalette(gctx, *palette);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error initConsole(Context &ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
|
||||
ox::Error initConsole(Context *ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
|
||||
setBgStatus(ctx, 0b0001);
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr);
|
||||
}
|
||||
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
const auto col = static_cast<uint_t>(column);
|
||||
for (auto i = 0u; i < str.bytes(); ++i) {
|
||||
setTile(
|
||||
@ -468,50 +484,57 @@ void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
|
||||
auto &bg = ctx.backgrounds[bgIdx];
|
||||
void setBgCbb(Context *ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &bg = gctx.backgrounds[bgIdx];
|
||||
bg.cbbIdx = cbbIdx;
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context &ctx) noexcept {
|
||||
uint8_t bgStatus(Context *ctx) noexcept {
|
||||
const auto &gctx = glctx(*ctx);
|
||||
uint8_t out = 0;
|
||||
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
|
||||
out |= static_cast<uint8_t>(static_cast<uint_t>(ctx.backgrounds[i].enabled) << i);
|
||||
for (uint_t i = 0; i < gctx.cbbs.size(); ++i) {
|
||||
out |= static_cast<uint8_t>(static_cast<uint_t>(gctx.backgrounds[i].enabled) << i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void setBgStatus(Context &ctx, uint32_t status) noexcept {
|
||||
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
|
||||
ctx.backgrounds[i].enabled = (status >> i) & 1;
|
||||
void setBgStatus(Context *ctx, uint32_t status) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
for (uint_t i = 0; i < gctx.cbbs.size(); ++i) {
|
||||
gctx.backgrounds[i].enabled = (status >> i) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool bgStatus(Context &ctx, uint_t bg) noexcept {
|
||||
return ctx.backgrounds[bg].enabled;
|
||||
bool bgStatus(Context *ctx, uint_t bg) noexcept {
|
||||
const auto &gctx = glctx(*ctx);
|
||||
return gctx.backgrounds[bg].enabled;
|
||||
}
|
||||
|
||||
void setBgStatus(Context &ctx, uint_t bg, bool status) noexcept {
|
||||
ctx.backgrounds[bg].enabled = status;
|
||||
void setBgStatus(Context *ctx, uint_t bg, bool status) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
gctx.backgrounds[bg].enabled = status;
|
||||
}
|
||||
|
||||
|
||||
void clearTileLayer(Context &ctx, uint_t bgIdx) noexcept {
|
||||
auto &bg = ctx.cbbs[static_cast<std::size_t>(bgIdx)];
|
||||
void clearTileLayer(Context *ctx, uint_t bgIdx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &bg = gctx.cbbs[static_cast<std::size_t>(bgIdx)];
|
||||
initBackgroundBufferObjects(bg);
|
||||
bg.updated = true;
|
||||
}
|
||||
|
||||
void hideSprite(Context &ctx, uint_t idx) noexcept {
|
||||
auto vbo = &ctx.spriteBlocks.vertices[idx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &ctx.spriteBlocks.elements[idx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(
|
||||
idx * renderer::SpriteVertexVboRows, 0, 0, 0, 0, false, vbo, ebo);
|
||||
ctx.spriteBlocks.updated = true;
|
||||
void hideSprite(Context *ctx, uint_t idx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto vbo = &gctx.spriteBlocks.vertices[idx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &gctx.spriteBlocks.elements[idx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(idx * renderer::SpriteVertexVboRows, 0,
|
||||
0, 0, 0, false, vbo, ebo);
|
||||
gctx.spriteBlocks.updated = true;
|
||||
}
|
||||
|
||||
void setSprite(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
uint_t idx,
|
||||
int x,
|
||||
int y,
|
||||
@ -542,13 +565,14 @@ void setSprite(
|
||||
const auto dim = dimensions[(spriteShape << 2) | spriteSize];
|
||||
const auto uX = static_cast<int>(x) % 255;
|
||||
const auto uY = static_cast<int>(y + 8) % 255 - 8;
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto i = 0u;
|
||||
const auto set = [&](int xIt, int yIt) {
|
||||
const auto fX = static_cast<float>(uX + xIt * 8) / 8;
|
||||
const auto fY = static_cast<float>(uY + yIt * 8) / 8;
|
||||
const auto cidx = idx + i;
|
||||
auto vbo = &ctx.spriteBlocks.vertices[cidx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &ctx.spriteBlocks.elements[cidx * renderer::SpriteVertexEboLength];
|
||||
auto vbo = &gctx.spriteBlocks.vertices[cidx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &gctx.spriteBlocks.elements[cidx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(
|
||||
cidx * renderer::SpriteVertexVboRows,
|
||||
1,
|
||||
@ -573,11 +597,11 @@ void setSprite(
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.spriteBlocks.updated = true;
|
||||
gctx.spriteBlocks.updated = true;
|
||||
}
|
||||
|
||||
void setTile(
|
||||
Context &ctx,
|
||||
Context *ctx,
|
||||
uint_t bgIdx,
|
||||
int column,
|
||||
int row,
|
||||
@ -586,18 +610,22 @@ void setTile(
|
||||
"nostalgia.core.gfx.setTile",
|
||||
"bgIdx: {}, column: {}, row: {}, tile: {}",
|
||||
bgIdx, column, row, tile);
|
||||
auto &gctx = glctx(*ctx);
|
||||
const auto z = static_cast<uint_t>(bgIdx);
|
||||
const auto y = static_cast<uint_t>(row);
|
||||
const auto x = static_cast<uint_t>(column);
|
||||
const auto i = renderer::bgVertexRow(x, y);
|
||||
auto &bg = ctx.cbbs[z];
|
||||
auto &bg = gctx.cbbs[z];
|
||||
const auto vbo = &bg.vertices[i * renderer::BgVertexVboLength];
|
||||
const auto ebo = &bg.elements[i * renderer::BgVertexEboLength];
|
||||
const auto tileHeight = static_cast<float>(TileHeight * Scale) / static_cast<float>(bg.tex.height);
|
||||
const auto tileOffset = tileHeight * static_cast<float>(tile);
|
||||
renderer::setTileBufferObject(
|
||||
static_cast<uint_t>(i * renderer::BgVertexVboRows),
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
static_cast<float>(tile),
|
||||
tileOffset,
|
||||
tileHeight,
|
||||
vbo,
|
||||
ebo);
|
||||
bg.updated = true;
|
||||
@ -605,23 +633,16 @@ void setTile(
|
||||
|
||||
namespace gl {
|
||||
|
||||
ox::Size drawSize(int scale) noexcept {
|
||||
return {240 * scale, 160 * scale};
|
||||
}
|
||||
|
||||
void draw(core::Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
void drawMainView(core::Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
glViewport(0, 0, renderSz.width, renderSz.height);
|
||||
glutils::clearScreen();
|
||||
renderer::drawBackgrounds(ctx, renderSz);
|
||||
if (ctx.spriteBlocks.tex) {
|
||||
renderer::drawSprites(ctx, renderSz);
|
||||
auto &gctx = glctx(ctx);
|
||||
renderer::drawBackgrounds(gctx, renderSz);
|
||||
if (gctx.spriteBlocks.tex) {
|
||||
renderer::drawSprites(gctx, renderSz);
|
||||
}
|
||||
}
|
||||
|
||||
void draw(core::Context &ctx, int scale) noexcept {
|
||||
draw(ctx, drawSize(scale));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ constexpr uint64_t TileColumns = 128;
|
||||
constexpr uint64_t TileCount = TileRows * TileColumns;
|
||||
constexpr uint64_t SpriteCount = 128;
|
||||
constexpr uint64_t BgVertexVboRows = 4;
|
||||
constexpr uint64_t BgVertexVboRowLength = 5;
|
||||
constexpr uint64_t BgVertexVboRowLength = 4;
|
||||
constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength;
|
||||
constexpr uint64_t BgVertexEboLength = 6;
|
||||
constexpr uint64_t SpriteVertexVboRows = 256;
|
||||
@ -63,6 +63,6 @@ class Drawer: public turbine::gl::Drawer {
|
||||
}
|
||||
|
||||
namespace nostalgia::core {
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
void shutdownGfx(Context &ctx) noexcept;
|
||||
}
|
@ -1,9 +1,17 @@
|
||||
add_library(NostalgiaCore-Studio)
|
||||
add_library(
|
||||
NostalgiaCore-Studio
|
||||
paletteeditor.cpp
|
||||
tilesheeteditorview.cpp
|
||||
tilesheeteditormodel.cpp
|
||||
tilesheetpixelgrid.cpp
|
||||
tilesheetpixels.cpp
|
||||
)
|
||||
|
||||
add_library(
|
||||
NostalgiaCore-Studio-ImGui
|
||||
studiomodule.cpp
|
||||
tilesheeteditor/tilesheeteditor-imgui.cpp
|
||||
paletteeditor-imgui.cpp
|
||||
tilesheeteditor-imgui.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@ -16,6 +24,7 @@ target_link_libraries(
|
||||
NostalgiaCore-Studio-ImGui PUBLIC
|
||||
NostalgiaCore-Studio
|
||||
Studio
|
||||
lodepng
|
||||
)
|
||||
|
||||
install(
|
||||
@ -25,6 +34,3 @@ install(
|
||||
LIBRARY DESTINATION
|
||||
${NOSTALGIA_DIST_MODULE}
|
||||
)
|
||||
|
||||
add_subdirectory(paletteeditor)
|
||||
add_subdirectory(tilesheeteditor)
|
||||
|
@ -15,22 +15,22 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
PaletteEditorImGui::PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path):
|
||||
PaletteEditorImGui::PaletteEditorImGui(turbine::Context *ctx, ox::String path):
|
||||
m_ctx(ctx),
|
||||
m_itemPath(path),
|
||||
m_itemPath(std::move(path)),
|
||||
m_itemName(m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1)),
|
||||
m_pal(*keel::readObj<Palette>(keelCtx(m_ctx), ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) {
|
||||
m_pal(*keel::readObj<Palette>(&m_ctx->keelCtx, ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) {
|
||||
}
|
||||
|
||||
ox::CStringView PaletteEditorImGui::itemName() const noexcept {
|
||||
const ox::String &PaletteEditorImGui::itemName() const noexcept {
|
||||
return m_itemPath;
|
||||
}
|
||||
|
||||
ox::CStringView PaletteEditorImGui::itemDisplayName() const noexcept {
|
||||
const ox::String &PaletteEditorImGui::itemDisplayName() const noexcept {
|
||||
return m_itemName;
|
||||
}
|
||||
|
||||
void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
static constexpr auto flags = ImGuiTableFlags_RowBg;
|
||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
||||
ImGui::BeginChild("Colors", ImVec2(paneSize.x - 208, paneSize.y), true);
|
||||
@ -42,14 +42,14 @@ void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
if (ImGui::Button("Add", sz)) {
|
||||
const auto colorSz = static_cast<int>(m_pal.colors.size());
|
||||
constexpr Color16 c = 0;
|
||||
undoStack()->push(ox::make_unique<AddColorCommand>(&m_pal, c, colorSz));
|
||||
undoStack()->push(ox::make<AddColorCommand>(&m_pal, c, colorSz));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size());
|
||||
{
|
||||
if (ImGui::Button("Remove", sz)) {
|
||||
undoStack()->push(
|
||||
ox::make_unique<RemoveColorCommand>(
|
||||
ox::make<RemoveColorCommand>(
|
||||
&m_pal,
|
||||
m_pal.colors[static_cast<std::size_t>(m_selectedRow)],
|
||||
static_cast<int>(m_selectedRow)));
|
||||
@ -59,7 +59,7 @@ void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
ImGui::BeginDisabled(m_selectedRow <= 0);
|
||||
{
|
||||
if (ImGui::Button("Move Up", sz)) {
|
||||
undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_selectedRow, -1));
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, -1));
|
||||
--m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1);
|
||||
{
|
||||
if (ImGui::Button("Move Down", sz)) {
|
||||
undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_selectedRow, 1));
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, 1));
|
||||
++m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -125,13 +125,13 @@ void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
int r = red16(c);
|
||||
int g = green16(c);
|
||||
int b = blue16(c);
|
||||
int const a = alpha16(c);
|
||||
int a = alpha16(c);
|
||||
ImGui::InputInt("Red", &r, 1, 5);
|
||||
ImGui::InputInt("Green", &g, 1, 5);
|
||||
ImGui::InputInt("Blue", &b, 1, 5);
|
||||
const auto newColor = color16(r, g, b, a);
|
||||
if (c != newColor) {
|
||||
undoStack()->push(ox::make_unique<UpdateColorCommand>(&m_pal, static_cast<int>(m_selectedRow), c, newColor));
|
||||
undoStack()->push(ox::make<UpdateColorCommand>(&m_pal, static_cast<int>(m_selectedRow), c, newColor));
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@ -139,7 +139,7 @@ void PaletteEditorImGui::draw(turbine::Context&) 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);
|
||||
}
|
||||
|
@ -14,23 +14,25 @@ namespace nostalgia::core {
|
||||
class PaletteEditorImGui: public studio::Editor {
|
||||
|
||||
private:
|
||||
turbine::Context &m_ctx;
|
||||
turbine::Context *m_ctx = nullptr;
|
||||
ox::String m_itemPath;
|
||||
ox::String m_itemName;
|
||||
Palette m_pal;
|
||||
std::size_t m_selectedRow = 0;
|
||||
|
||||
PaletteEditorImGui() noexcept = default;
|
||||
|
||||
public:
|
||||
PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
||||
PaletteEditorImGui(turbine::Context *ctx, ox::String path);
|
||||
|
||||
/**
|
||||
* Returns the name of item being edited.
|
||||
*/
|
||||
ox::CStringView itemName() const noexcept final;
|
||||
const ox::String &itemName() const noexcept final;
|
||||
|
||||
ox::CStringView itemDisplayName() const noexcept final;
|
||||
const ox::String &itemDisplayName() const noexcept final;
|
||||
|
||||
void draw(turbine::Context&) noexcept final;
|
||||
void draw(turbine::Context*) noexcept final;
|
||||
|
||||
protected:
|
||||
ox::Error saveItem() noexcept final;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user