From 4ccdfc3a6e5bd501968903a01f7d8141b6f88375 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 4 Dec 2024 19:55:17 -0600 Subject: [PATCH] Squashed 'deps/nostalgia/' changes from 3c7652ef..161640fa 161640fa [nostalgia] Cleanup e42126c9 [nostalgia/core] Improve TileSheet validation, add repair 36942cca [nostalgia,olympic] Replace SpanView with Span b14f1d50 [ox] Replace SpanView with Span 1bf4f246 [applib] Make run take args as a SpanView edda8e01 [ox/clargs] Add constructor that takes a SpanView 3308b4dd [ox/std] Add missing + and += operators to Span 27f4703a [teagba] Suppress warnings for unsafe buffers 6af00d9a [nostalgia] Enable warnings for unsafe buffers 86b9f931 [olympic] Enable warnings for unsafe buffers a0ed1b3f [ox/std] Fix Span raw array constructor 8dad624b [studio/applib] Cleanup dc6605fd [keel] Add missing error checking to pack c78d3cf6 [ox] Add more unsafe buffer exceptions cee4f65d [ox/std] Replace an unsafe buffer cd3eeeef [ox/fs] Suppress unsafe buffer warnings 287d42f2 [ox/clargs] Cleanup dbbaaa46 [ox/clargs] Enable unsafe buffer warnings 9b8a8c4e [ox/std] Enable unsafe buffer warnings e44fa288 [cityhash] Add pragmas to ignore unsafe buffer warnings e13c6e81 [ox/std] Remove raw char* CharBufferWriter constructor cb55b31a [ox/std] Cleanup ab3f9e16 [ox/std] Make Span access check message consistent with other messages 8f25ef96 [ox/std] Make CharBufferWriter constructor take a Span e13eebaf [ox/std] Cleanup an unsafe buffer 114f5c66 [ox/std] Add overflow checking to SpanIterator df44fe23 [keel] Cleanup 72f4db3d [nostalgia/core/studio] Fix paste command to never paste beyond target dimensions 8a9ff971 [nostalgia/core] Fix resizeSubsheet to work for both growing and shrinking 5a8da59d [keel] Fix readAsset to actually return asset afa3a13d [keel] Cleanup 6522cf8a [keel] Add ensureValid call to readAsset f772e48b [ox] Add Vector/Array/Span overflow checking 13bfe881 [nostalgia/core] Fix resizeSubsheet array overflow 50254754 Merge commit '9e11019b87ba27d1dac9e097dc212a126e404218' bfe890ae [ox] Fix typo in docs ab5bc1ad [ox/std] Remove oxRequireT and oxRequireMT abf7548a [nostalgia/core] Add missing include e2682b5e [studio/modlib] Add missing include 792ad414 [nostalgia] Remove .vs dir git-subtree-dir: deps/nostalgia git-subtree-split: 161640fa11986677dc2e1da6ffd4575e38ab31ad --- .vs/launch.vs.json | 44 ---- deps/ox/deps/cityhash/include/cityhash/city.h | 9 + deps/ox/ox-docs.md | 10 +- deps/ox/src/ox/clargs/CMakeLists.txt | 7 +- deps/ox/src/ox/clargs/clargs.cpp | 12 +- deps/ox/src/ox/clargs/clargs.hpp | 3 + deps/ox/src/ox/fs/CMakeLists.txt | 4 + .../src/ox/fs/filestore/filestoretemplate.hpp | 4 + deps/ox/src/ox/fs/filesystem/directory.hpp | 4 + deps/ox/src/ox/fs/filesystem/filelocation.cpp | 2 + deps/ox/src/ox/fs/filesystem/filelocation.hpp | 4 + deps/ox/src/ox/fs/filesystem/pathiterator.cpp | 6 +- deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp | 4 + deps/ox/src/ox/fs/ptrarith/ptr.hpp | 4 + deps/ox/src/ox/fs/test/tests.cpp | 5 +- deps/ox/src/ox/fs/tool.cpp | 23 +- deps/ox/src/ox/logconn/circularbuff.hpp | 4 + deps/ox/src/ox/logconn/logconn.cpp | 28 ++- deps/ox/src/ox/mc/intops.hpp | 10 +- deps/ox/src/ox/mc/presenceindicator.hpp | 2 + deps/ox/src/ox/mc/read.hpp | 10 +- deps/ox/src/ox/mc/write.hpp | 16 +- deps/ox/src/ox/model/desctypes.hpp | 7 +- deps/ox/src/ox/model/descwrite.hpp | 27 ++- deps/ox/src/ox/model/modelvalue.hpp | 35 ++-- deps/ox/src/ox/oc/read.hpp | 4 + deps/ox/src/ox/oc/write.hpp | 2 + deps/ox/src/ox/std/CMakeLists.txt | 6 + deps/ox/src/ox/std/algorithm.hpp | 8 +- deps/ox/src/ox/std/array.hpp | 11 + deps/ox/src/ox/std/assert.cpp | 39 +++- deps/ox/src/ox/std/assert.hpp | 31 +-- deps/ox/src/ox/std/basestringview.hpp | 7 +- deps/ox/src/ox/std/buffer.hpp | 12 +- deps/ox/src/ox/std/cstrops.hpp | 5 + deps/ox/src/ox/std/def.hpp | 19 +- deps/ox/src/ox/std/error.hpp | 9 + deps/ox/src/ox/std/fmt.hpp | 12 +- deps/ox/src/ox/std/heapmgr.cpp | 5 + deps/ox/src/ox/std/istring.hpp | 5 +- deps/ox/src/ox/std/iterator.hpp | 9 + deps/ox/src/ox/std/memops.cpp | 4 + deps/ox/src/ox/std/memops.hpp | 5 + deps/ox/src/ox/std/optional.hpp | 4 - deps/ox/src/ox/std/random.hpp | 5 + deps/ox/src/ox/std/span.hpp | 157 ++++---------- deps/ox/src/ox/std/stacktrace.cpp | 5 + deps/ox/src/ox/std/string.hpp | 9 +- deps/ox/src/ox/std/stringview.hpp | 3 + deps/ox/src/ox/std/strops.cpp | 3 + deps/ox/src/ox/std/strops.hpp | 9 +- deps/ox/src/ox/std/test/tests.cpp | 6 +- deps/ox/src/ox/std/trace.cpp | 24 +-- deps/ox/src/ox/std/trace.hpp | 6 +- deps/ox/src/ox/std/typetraits.hpp | 35 ++++ deps/ox/src/ox/std/uuid.hpp | 11 +- deps/ox/src/ox/std/vec.cpp | 2 +- deps/ox/src/ox/std/vec.hpp | 196 +----------------- deps/ox/src/ox/std/vector.hpp | 6 + deps/teagba/include/teagba/registers.hpp | 4 + src/nostalgia/CMakeLists.txt | 5 + .../core/include/nostalgia/core/gfx.hpp | 28 +++ .../include/nostalgia/core/initparams.hpp | 4 +- .../core/include/nostalgia/core/tilesheet.hpp | 90 +++++++- src/nostalgia/modules/core/src/gba/gfx.cpp | 4 + src/nostalgia/modules/core/src/gba/panic.cpp | 2 + src/nostalgia/modules/core/src/gfx.cpp | 46 +++- src/nostalgia/modules/core/src/opengl/gfx.cpp | 13 +- .../commands/cutpastecommand.cpp | 20 +- .../commands/cutpastecommand.hpp | 4 +- .../commands/deletetilescommand.cpp | 24 +-- .../commands/inserttilescommand.cpp | 21 +- .../tilesheeteditor/tilesheeteditormodel.cpp | 6 +- .../tilesheeteditor/tilesheeteditormodel.hpp | 2 +- src/nostalgia/modules/core/src/tilesheet.cpp | 4 +- src/nostalgia/modules/core/test/tests.cpp | 3 +- src/nostalgia/player/CMakeLists.txt | 3 +- src/nostalgia/player/app.cpp | 35 +++- src/nostalgia/player/main.cpp | 43 ---- src/olympic/CMakeLists.txt | 5 + src/olympic/applib/applib.cpp | 9 +- src/olympic/keel/include/keel/asset.hpp | 7 +- .../keel/include/keel/assetmanager.hpp | 5 +- src/olympic/keel/include/keel/media.hpp | 12 +- src/olympic/keel/include/keel/typeconv.hpp | 3 - src/olympic/keel/src/asset.cpp | 2 +- src/olympic/keel/src/module.cpp | 4 +- src/olympic/keel/src/pack-applib.cpp | 9 +- src/olympic/keel/src/pack.cpp | 30 +-- src/olympic/keel/src/typeconv.cpp | 2 - src/olympic/keel/test/tests.cpp | 3 +- src/olympic/studio/applib/src/main.cpp | 8 +- src/olympic/studio/applib/src/newmenu.cpp | 11 +- src/olympic/studio/applib/src/studioapp.cpp | 12 +- src/olympic/studio/applib/src/studioapp.hpp | 2 +- .../modlib/include/studio/filedialog.hpp | 3 +- .../modlib/include/studio/imguiutil.hpp | 4 +- .../studio/modlib/src/filedialog_nfd.cpp | 8 +- src/olympic/studio/modlib/src/imguiutil.cpp | 4 +- src/olympic/turbine/src/gba/turbine.cpp | 2 + src/olympic/turbine/src/glfw/gfx.cpp | 109 +++++----- 101 files changed, 842 insertions(+), 731 deletions(-) delete mode 100644 .vs/launch.vs.json delete mode 100644 src/nostalgia/player/main.cpp diff --git a/.vs/launch.vs.json b/.vs/launch.vs.json deleted file mode 100644 index 77394c0..0000000 --- a/.vs/launch.vs.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": "0.2.1", - "defaults": {}, - "configurations": [ - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "nostalgia.exe (Install)", - "name": "nostalgia.exe (Install)", - "args": [ - "${projectDir}/sample_project" - ] - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "nostalgia.exe", - "name": "nostalgia.exe", - "args": [ - "${projectDir}/sample_project" - ] - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "nostalgia-studio.exe (Install)", - "name": "nostalgia-studio.exe (Install)", - "args": [ - "-profile", - "${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json" - ] - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "nostalgia-studio.exe", - "name": "nostalgia-studio.exe", - "args": [ - "-profile", - "${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json" - ] - } - ] -} \ No newline at end of file diff --git a/deps/ox/deps/cityhash/include/cityhash/city.h b/deps/ox/deps/cityhash/include/cityhash/city.h index c99bc7c..9c9a2a8 100644 --- a/deps/ox/deps/cityhash/include/cityhash/city.h +++ b/deps/ox/deps/cityhash/include/cityhash/city.h @@ -104,6 +104,11 @@ using size_t = decltype(alignof(int)); #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + namespace cityhash::detail { template @@ -671,4 +676,8 @@ constexpr uint128 CityHash128(const char *s, size_t len) noexcept { } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + #endif // CITY_HASH_H_ diff --git a/deps/ox/ox-docs.md b/deps/ox/ox-docs.md index 3762c29..2cdbfa3 100644 --- a/deps/ox/ox-docs.md +++ b/deps/ox/ox-docs.md @@ -176,14 +176,10 @@ ox::Result f2() noexcept { ``` ```oxRequire``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code. -```oxRequire``` also has variants for throwing the error and for making to value non-const: +```oxRequire``` by default creates a const, but there is also an ```oxRequireM``` (oxRequire Mutable) +variant for creating a non-const value. * ```oxRequireM``` - oxRequire Mutable -* ```oxRequireT``` - oxRequire Throw -* ```oxRequireMT``` - oxRequire Mutable Throw - -The throw variants of ```oxRequire``` are generally legacy code. -```ox::Result::unwrapThrow``` is generally preferred now. ### Logging and Output @@ -207,7 +203,7 @@ never be checked in. ```oxError``` always prints. It includes file and line, and is prefixed with a red "ERROR:". It should generally be used conservatively. -It shuld be used only when there is an error that is not technically fatal, but +It should be used only when there is an error that is not technically fatal, but the user almost certainly wants to know about it. ```oxTrace``` and ```oxTracef```: diff --git a/deps/ox/src/ox/clargs/CMakeLists.txt b/deps/ox/src/ox/clargs/CMakeLists.txt index e2899f9..06c399e 100644 --- a/deps/ox/src/ox/clargs/CMakeLists.txt +++ b/deps/ox/src/ox/clargs/CMakeLists.txt @@ -1,4 +1,9 @@ -cmake_minimum_required(VERSION 3.10) + +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # enable warnings + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") +endif() + add_library( OxClArgs diff --git a/deps/ox/src/ox/clargs/clargs.cpp b/deps/ox/src/ox/clargs/clargs.cpp index 7cb8033..941d25f 100644 --- a/deps/ox/src/ox/clargs/clargs.cpp +++ b/deps/ox/src/ox/clargs/clargs.cpp @@ -11,16 +11,18 @@ namespace ox { -ClArgs::ClArgs(int argc, const char **args) noexcept { - for (auto i = 0u; i < static_cast(argc); ++i) { - auto arg = String(args[i]); +ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast(argc)}) {} + +ClArgs::ClArgs(ox::SpanView args) noexcept { + for (auto i = 0u; i < args.size(); ++i) { + auto arg = StringView(args[i]); if (arg[0] == '-') { while (arg[0] == '-' && arg.len()) { - arg = arg.substr(1); + arg = substr(arg, 1); } m_bools[arg] = true; // parse additional arguments - if (i < static_cast(argc) && args[i + 1]) { + if (i < args.size() && args[i + 1]) { auto val = String(args[i + 1]); if (val.len() && val[i] != '-') { if (val == "false") { diff --git a/deps/ox/src/ox/clargs/clargs.hpp b/deps/ox/src/ox/clargs/clargs.hpp index 610d625..ee54b4a 100644 --- a/deps/ox/src/ox/clargs/clargs.hpp +++ b/deps/ox/src/ox/clargs/clargs.hpp @@ -9,6 +9,7 @@ #pragma once #include +#include #include namespace ox { @@ -22,6 +23,8 @@ class ClArgs { public: ClArgs(int argc, const char **args) noexcept; + ClArgs(ox::SpanView args) noexcept; + [[nodiscard]] bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept; diff --git a/deps/ox/src/ox/fs/CMakeLists.txt b/deps/ox/src/ox/fs/CMakeLists.txt index 543cae8..960f7c6 100644 --- a/deps/ox/src/ox/fs/CMakeLists.txt +++ b/deps/ox/src/ox/fs/CMakeLists.txt @@ -1,3 +1,7 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # enable warnings + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") +endif() add_library( OxFS diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index 8d0505b..12367e4 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -10,6 +10,8 @@ #include +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { using InodeId_t = uint64_t; @@ -771,3 +773,5 @@ using FileStore16 = FileStoreTemplate; using FileStore32 = FileStoreTemplate; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/filesystem/directory.hpp b/deps/ox/src/ox/fs/filesystem/directory.hpp index 5adff26..2dde560 100644 --- a/deps/ox/src/ox/fs/filesystem/directory.hpp +++ b/deps/ox/src/ox/fs/filesystem/directory.hpp @@ -15,6 +15,8 @@ #include "types.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -333,3 +335,5 @@ using Directory16 = Directory; using Directory32 = Directory; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/filesystem/filelocation.cpp b/deps/ox/src/ox/fs/filesystem/filelocation.cpp index 51b9f2d..a808892 100644 --- a/deps/ox/src/ox/fs/filesystem/filelocation.cpp +++ b/deps/ox/src/ox/fs/filesystem/filelocation.cpp @@ -32,7 +32,9 @@ FileAddress::FileAddress(ox::StringViewCR path) noexcept { auto pathSize = path.bytes(); m_data.path = new char[pathSize + 1]; memcpy(m_data.path, path.data(), pathSize); +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) m_data.path[pathSize] = 0; +OX_CLANG_NOWARN_END m_type = FileAddressType::Path; } diff --git a/deps/ox/src/ox/fs/filesystem/filelocation.hpp b/deps/ox/src/ox/fs/filesystem/filelocation.hpp index c8f6cfa..99944ad 100644 --- a/deps/ox/src/ox/fs/filesystem/filelocation.hpp +++ b/deps/ox/src/ox/fs/filesystem/filelocation.hpp @@ -13,6 +13,8 @@ #include #include +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { enum class FileAddressType: int8_t { @@ -180,3 +182,5 @@ constexpr Error model(T *h, CommonPtrWith auto *fa) noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp index 6f5af20..77d4050 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp @@ -11,6 +11,8 @@ #include #include "pathiterator.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) { @@ -30,7 +32,7 @@ PathIterator::PathIterator(StringViewCR path): PathIterator(path.data(), path.by */ Error PathIterator::dirPath(char *out, std::size_t outSize) { const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize); - const auto size = static_cast(idx + 1); + const auto size = static_cast(idx) + 1; if (idx >= 0 && size < outSize) { ox::memcpy(out, m_path, size); out[size] = 0; @@ -183,3 +185,5 @@ const char *PathIterator::fullPath() const { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp b/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp index e09f837..358a798 100644 --- a/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp +++ b/deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp @@ -13,6 +13,8 @@ #include "ptr.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox::ptrarith { template @@ -449,3 +451,5 @@ struct OX_PACKED Item { }; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/ptrarith/ptr.hpp b/deps/ox/src/ox/fs/ptrarith/ptr.hpp index 9994005..5e0efac 100644 --- a/deps/ox/src/ox/fs/ptrarith/ptr.hpp +++ b/deps/ox/src/ox/fs/ptrarith/ptr.hpp @@ -10,6 +10,8 @@ #include +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox::ptrarith { template @@ -256,3 +258,5 @@ constexpr Result> Ptr::validate( } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index 68199ea..f5b6db9 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -226,13 +226,14 @@ const std::map> tests = }, }; -int main(int argc, const char **args) { +int main(int argc, const char **argv) { if (argc < 2) { oxError("Must specify test to run"); return -1; } + auto const args = ox::Span{argv, static_cast(argc)}; ox::StringView const testName = args[1]; - ox::StringView const testArg = args[2] ? args[2] : nullptr; + ox::StringView const testArg = argc >= 3 ? args[2] : nullptr; auto const func = tests.find(testName); if (func != tests.end()) { oxAssert(func->second(testArg), "Test returned Error"); diff --git a/deps/ox/src/ox/fs/tool.cpp b/deps/ox/src/ox/fs/tool.cpp index 3d52f34..c65819f 100644 --- a/deps/ox/src/ox/fs/tool.cpp +++ b/deps/ox/src/ox/fs/tool.cpp @@ -39,25 +39,25 @@ static ox::Result> loadFs(const char *path) noexce return {ox::make_unique(buff.data, buff.size)}; } -static ox::Error runLs(ox::FileSystem *fs, int argc, const char **argv) noexcept { - if (argc < 2) { +static ox::Error runLs(ox::FileSystem *fs, ox::Span args) noexcept { + if (args.size() < 2) { oxErr("Must provide a directory to ls\n"); return OxError(1); } - oxRequire(files, fs->ls(argv[1])); + oxRequire(files, fs->ls(args[1])); for (const auto &file : files) { oxOutf("{}\n", file); } return OxError(0); } -static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexcept { - if (argc < 2) { +static ox::Error runRead(ox::FileSystem *fs, ox::Span args) noexcept { + if (args.size() < 2) { oxErr("Must provide a path to a file to read\n"); return OxError(1); } - oxRequire(buff, fs->read(ox::StringView(argv[1]))); - fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); + oxRequire(buff, fs->read(ox::StringView(args[1]))); + std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); return OxError(0); } @@ -66,13 +66,14 @@ static ox::Error run(int argc, const char **argv) noexcept { oxErr("OxFS file and subcommand arguments are required\n"); return OxError(1); } - const auto fsPath = argv[1]; - ox::String subCmd(argv[2]); + auto const args = ox::Span{argv, static_cast(argc)}; + auto const fsPath = args[1]; + ox::String subCmd(args[2]); oxRequire(fs, loadFs(fsPath)); if (subCmd == "ls") { - return runLs(fs.get(), argc - 2, argv + 2); + return runLs(fs.get(), args + 2); } else if (subCmd == "read") { - return runRead(fs.get(), argc - 2, argv + 2); + return runRead(fs.get(), args + 2); } return OxError(1); } diff --git a/deps/ox/src/ox/logconn/circularbuff.hpp b/deps/ox/src/ox/logconn/circularbuff.hpp index 96e5fb8..1100c10 100644 --- a/deps/ox/src/ox/logconn/circularbuff.hpp +++ b/deps/ox/src/ox/logconn/circularbuff.hpp @@ -45,6 +45,7 @@ class CirculerBuffer { if (sz > avail()) { return OxError(1, "Insufficient space in buffer"); } +OX_ALLOW_UNSAFE_BUFFERS_BEGIN // write seg 1 const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt); ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz); @@ -56,6 +57,7 @@ class CirculerBuffer { ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz); oxAssert(m_buff[0] == buff[seg1Sz], "break"); } +OX_ALLOW_UNSAFE_BUFFERS_END return {}; } @@ -90,7 +92,9 @@ class CirculerBuffer { m_readPt -= m_buff.size(); // read seg 2 const auto seg2Sz = bytesRead - seg1Sz; +OX_ALLOW_UNSAFE_BUFFERS_BEGIN ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz); +OX_ALLOW_UNSAFE_BUFFERS_END } return bytesRead; } diff --git a/deps/ox/src/ox/logconn/logconn.cpp b/deps/ox/src/ox/logconn/logconn.cpp index f5a398f..dfe91a4 100644 --- a/deps/ox/src/ox/logconn/logconn.cpp +++ b/deps/ox/src/ox/logconn/logconn.cpp @@ -9,8 +9,8 @@ #ifdef OX_USE_STDLIB #include -#include #ifndef _WIN32 +#include #include #include #include @@ -25,15 +25,22 @@ #include "logconn.hpp" -#include namespace ox { +#ifdef _WIN32 +using Socket = SOCKET; +using LenType = int; +#else +using Socket = int; +using LenType = size_t; +#endif + using namespace trace; -void closeSock(auto s) noexcept { +static void closeSock(auto s) noexcept { #ifdef _WIN32 - closesocket(s); + closesocket(static_cast(s)); #else close(s); #endif @@ -56,8 +63,8 @@ ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept { addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(5590); - m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - oxReturnError(OxError(static_cast(connect(m_socket, reinterpret_cast(&addr), sizeof(addr))))); + m_socket = static_cast(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); + oxReturnError(OxError(static_cast(connect(static_cast(m_socket), reinterpret_cast(&addr), sizeof(addr))))); return sendInit({.appName = ox::BasicString<128>(appName)}); } @@ -65,9 +72,9 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept { std::size_t totalSent = 0; while (totalSent < len) { //std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket); - const auto sent = ::send(m_socket, buff, len, 0); + const auto sent = ::send(static_cast(m_socket), buff, static_cast(len), 0); if (sent < 0) { - std::fprintf(stderr, "Could not send msg\n"); + std::ignore = std::fprintf(stderr, "Could not send msg\n"); return OxError(1, "Could not send msg"); } totalSent += static_cast(sent); @@ -90,13 +97,14 @@ void LoggerConn::msgSend() noexcept { if (!m_running) { break; } - std::lock_guard buffLk(m_buffMut); + std::lock_guard const buffLk(m_buffMut); while (true) { - ox::Array tmp; + Array tmp; const auto read = m_buff.read(tmp.data(), tmp.size()); if (!read) { break; } + oxAssert(read <= tmp.size(), "logger trying to read too much data"); //std::printf("LoggerConn: sending %lu bytes\n", read); std::ignore = send(tmp.data(), read); } diff --git a/deps/ox/src/ox/mc/intops.hpp b/deps/ox/src/ox/mc/intops.hpp index 501cda8..567af5c 100644 --- a/deps/ox/src/ox/mc/intops.hpp +++ b/deps/ox/src/ox/mc/intops.hpp @@ -57,7 +57,7 @@ static_assert(highestBit(uint64_t(1) << 31) == 31); static_assert(highestBit(uint64_t(1) << 63) == 63); struct McInt { - uint8_t data[9] = {}; + ox::Array data{}; // length of integer in bytes std::size_t length = 0; }; @@ -104,7 +104,7 @@ constexpr McInt encodeInteger(I pInput) noexcept { auto intermediate = static_cast(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast(bytesIndicator); - ox::memcpy(out.data, &intermediate, sizeof(intermediate)); + ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate)); } out.length = bytes; } @@ -160,7 +160,7 @@ constexpr Result decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe ox::Array d = {}; //d[0] = decoded & 0xffff'ffff; //d[1] = decoded >> 32; - ox::memcpy(d.data(), &decoded, sizeof(decoded)); + ox::memcpy(&d[0], &decoded, sizeof(decoded)); auto bit = negBit; for (; bit < ox::min(Bits, 32); ++bit) { d[0] |= 1 << bit; @@ -175,7 +175,7 @@ constexpr Result decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe d[0] = d[1]; d[1] = d0Tmp; } - ox::memcpy(&out, d.data(), sizeof(out)); + ox::memcpy(&out, &d[0], sizeof(out)); return out; } } @@ -185,7 +185,7 @@ constexpr Result decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe template Result decodeInteger(McInt m) noexcept { std::size_t bytesRead{}; - BufferReader br({reinterpret_cast(m.data), 9}); + BufferReader br({reinterpret_cast(m.data.data()), 9}); return decodeInteger(br, &bytesRead); } diff --git a/deps/ox/src/ox/mc/presenceindicator.hpp b/deps/ox/src/ox/mc/presenceindicator.hpp index 8a5b312..f9f02c9 100644 --- a/deps/ox/src/ox/mc/presenceindicator.hpp +++ b/deps/ox/src/ox/mc/presenceindicator.hpp @@ -147,11 +147,13 @@ constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept: constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept { if (i / 8 < m_mapLen) { +OX_ALLOW_UNSAFE_BUFFERS_BEGIN if (on) { m_map[i / 8] |= 1 << (i % 8); } else { m_map[i / 8] &= ~static_cast(1 << (i % 8)); } +OX_ALLOW_UNSAFE_BUFFERS_END return {}; } else { return OxError(McPresenceMapOverflow); diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index cbb472a..e0534d0 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -214,7 +214,9 @@ constexpr Error MetalClawReaderTemplate::field(const char *name, auto *v auto &handler = *reader.interface(); oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast(len))); for (std::size_t i = 0; i < len; ++i) { +OX_ALLOW_UNSAFE_BUFFERS_BEGIN oxReturnError(handler.field({}, &val[i])); +OX_ALLOW_UNSAFE_BUFFERS_END } } else { oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen); @@ -380,9 +382,9 @@ constexpr Error MetalClawReaderTemplate::fieldCString(const char*, char // re-allocate in case too small safeDelete(*val); *val = new char[size + 1]; - auto data = *val; + auto data = ox::Span{*val, size + 1}; // read the string - oxReturnError(m_reader.read(data, size)); + oxReturnError(m_reader.read(data.data(), size)); data[size] = 0; } ++m_field; @@ -402,9 +404,9 @@ constexpr Error MetalClawReaderTemplate::fieldCString(const char*, char *val = new char[size + 1]; buffLen = size + 1; } - auto data = *val; + auto data = ox::Span{*val, size + 1}; // read the string - oxReturnError(m_reader.read(data, size)); + oxReturnError(m_reader.read(data.data(), size)); data[size] = 0; } else { auto data = *val; diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index 49de676..b63480e 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -117,7 +117,7 @@ class MetalClawWriter { bool fieldSet = false; if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { auto mi = mc::encodeInteger(val); - oxReturnError(m_writer.write(reinterpret_cast(mi.data), mi.length)); + oxReturnError(m_writer.write(reinterpret_cast(mi.data.data()), mi.length)); fieldSet = true; } oxReturnError(m_fieldPresence.set(static_cast(m_field), fieldSet)); @@ -194,7 +194,7 @@ constexpr Error MetalClawWriter::field(const char*, const BasicStringlen() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { // write the length const auto strLen = mc::encodeInteger(val->len()); - oxReturnError(m_writer.write(reinterpret_cast(strLen.data), strLen.length)); + oxReturnError(m_writer.write(reinterpret_cast(strLen.data.data()), strLen.length)); // write the string oxReturnError(m_writer.write(val->c_str(), static_cast(val->len()))); fieldSet = true; @@ -217,7 +217,7 @@ constexpr Error MetalClawWriter::fieldCString(const char*, const char *c const auto strLen = *val ? ox::strlen(*val) : 0; // write the length const auto strLenBuff = mc::encodeInteger(strLen); - oxReturnError(m_writer.write(reinterpret_cast(strLenBuff.data), strLenBuff.length)); + oxReturnError(m_writer.write(reinterpret_cast(strLenBuff.data.data()), strLenBuff.length)); // write the string oxReturnError(m_writer.write(*val, static_cast(strLen))); fieldSet = true; @@ -243,7 +243,7 @@ constexpr Error MetalClawWriter::fieldCString(const char*, const char *v if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { // write the length const auto strLenBuff = mc::encodeInteger(strLen); - oxReturnError(m_writer.write(reinterpret_cast(strLenBuff.data), strLenBuff.length)); + oxReturnError(m_writer.write(reinterpret_cast(strLenBuff.data.data()), strLenBuff.length)); // write the string oxReturnError(m_writer.write(val, static_cast(strLen))); fieldSet = true; @@ -298,14 +298,16 @@ constexpr Error MetalClawWriter::field(const char*, const T *val, std::s if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { // write the length const auto arrLen = mc::encodeInteger(len); - oxReturnError(m_writer.write(reinterpret_cast(arrLen.data), arrLen.length)); + oxReturnError(m_writer.write(reinterpret_cast(arrLen.data.data()), arrLen.length)); auto const writeIdx = m_writer.tellp(); MetalClawWriter writer(m_writer); ModelHandlerInterface handler{&writer}; oxReturnError(handler.template setTypeInfo("List", 0, {}, static_cast(len))); // write the array for (std::size_t i = 0; i < len; ++i) { +OX_ALLOW_UNSAFE_BUFFERS_BEGIN oxReturnError(handler.field("", &val[i])); +OX_ALLOW_UNSAFE_BUFFERS_END } oxReturnError(writer.finalize()); fieldSet = writeIdx != m_writer.tellp(); @@ -324,7 +326,7 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap(arrLen.data), arrLen.length)); + oxReturnError(m_writer.write(reinterpret_cast(arrLen.data.data()), arrLen.length)); // write map MetalClawWriter writer(m_writer); ModelHandlerInterface handler{&writer}; @@ -395,7 +397,7 @@ Result writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB } Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { - CharBuffWriter bw(buff, buffLen); + CharBuffWriter bw{{buff, buffLen}}; oxReturnError(writeMC(bw, val)); if (sizeOut) { *sizeOut = bw.tellp(); diff --git a/deps/ox/src/ox/model/desctypes.hpp b/deps/ox/src/ox/model/desctypes.hpp index 6a1bcc4..045cc86 100644 --- a/deps/ox/src/ox/model/desctypes.hpp +++ b/deps/ox/src/ox/model/desctypes.hpp @@ -90,7 +90,7 @@ constexpr Error model(T *io, CommonPtrWith auto *type) noexcept { } oxReturnError(io->field("length", &type->length)); oxReturnError(io->field("smallSzLen", &type->smallSzLen)); - return OxError(0); + return {}; } using SubscriptStack = Vector; @@ -119,6 +119,7 @@ struct DescriptorField { subscriptLevels(pSubscriptLevels), subscriptStack(std::move(pSubscriptType)), typeId(std::move(pTypeId)) { + oxAssert(subscriptLevels <= static_cast(subscriptStack.size()), "Subscript level mismatch"); } constexpr DescriptorField(const DescriptorField &other) noexcept: @@ -202,7 +203,7 @@ constexpr Error model(T *io, CommonPtrWith auto *type) noexcept oxReturnError(io->field("fieldList", &type->fieldList)); oxReturnError(io->field("length", &type->length)); oxReturnError(io->field("preloadable", &type->preloadable)); - return OxError(0); + return {}; } template @@ -215,7 +216,7 @@ constexpr Error model(T *io, CommonPtrWith auto *field) noexcep // defaultValue is unused now, but leave placeholder for backwards compatibility int defaultValue = 0; oxReturnError(io->field("defaultValue", &defaultValue)); - return OxError(0); + return {}; } template diff --git a/deps/ox/src/ox/model/descwrite.hpp b/deps/ox/src/ox/model/descwrite.hpp index 817bfc1..8e50f50 100644 --- a/deps/ox/src/ox/model/descwrite.hpp +++ b/deps/ox/src/ox/model/descwrite.hpp @@ -97,8 +97,14 @@ class TypeDescWriter { std::size_t fields = ModelFieldCount_v) noexcept; template - constexpr Error field(StringViewCR name, const T *val, std::size_t valLen, - const SubscriptStack &subscriptStack = {}) noexcept; + constexpr Error field( + StringViewCR name, + T const*val, + std::size_t valLen, + SubscriptStack const&subscriptStack) noexcept; + + template + constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept; template constexpr Error field(StringViewCR name, UnionView val) noexcept; @@ -193,7 +199,7 @@ constexpr ox::Error TypeDescWriter::setTypeInfo( // array handler template -constexpr Error TypeDescWriter::field(StringViewCR name, const T*, std::size_t, const SubscriptStack &subscriptStack) noexcept { +constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t, SubscriptStack const&subscriptStack) noexcept { if (m_type) { constexpr typename remove_pointer::type *p = nullptr; const auto t = type(p); @@ -204,6 +210,21 @@ constexpr Error TypeDescWriter::field(StringViewCR name, const T*, std::size_t, return OxError(1); } +// array handler +template +constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t) noexcept { + if (m_type) { + constexpr typename remove_pointer::type *p = nullptr; + const auto t = type(p); + oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); + auto const lvls = detail::indirectionLevels_v + 1; + SubscriptStack subscriptStack{lvls}; + m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t)); + return OxError(0); + } + return OxError(1); +} + template constexpr Error TypeDescWriter::field(StringViewCR name, UnionView val) noexcept { if (m_type) { diff --git a/deps/ox/src/ox/model/modelvalue.hpp b/deps/ox/src/ox/model/modelvalue.hpp index 7a62060..84dc58b 100644 --- a/deps/ox/src/ox/model/modelvalue.hpp +++ b/deps/ox/src/ox/model/modelvalue.hpp @@ -188,8 +188,8 @@ class ModelValue { constexpr Error setType( DescriptorType const*type, - int subscriptLevels = 0, - SubscriptStack const& = {}) noexcept; + SubscriptStack const& = {}, + int subscriptLevels = 0) noexcept; template constexpr Error setType() noexcept; @@ -242,7 +242,7 @@ class ModelValueArray { m_vec.resize(sz); if (sz > oldSz) { for (auto i = oldSz; i < sz; ++i) { - oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels)); + oxReturnError(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); } } return {}; @@ -276,8 +276,9 @@ class ModelValueArray { constexpr Error setType( DescriptorType const*type, - int subscriptLevels, - SubscriptStack subscriptStack) noexcept { + SubscriptStack subscriptStack, + int subscriptLevels) noexcept { + oxAssert(subscriptLevels <= static_cast(subscriptStack.size()), "subscript level mismatch"); m_type = type; m_typeSubscriptLevels = subscriptLevels; m_subscriptStack = std::move(subscriptStack); @@ -400,7 +401,7 @@ class ModelValueVector { m_vec.resize(sz); if (sz > oldSz) { for (auto i = oldSz; i < sz; ++i) { - oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack)); + oxReturnError(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); } } return {}; @@ -418,8 +419,9 @@ class ModelValueVector { constexpr Error setType( DescriptorType const*type, - int subscriptLevels, - SubscriptStack subscriptStack) noexcept { + SubscriptStack subscriptStack, + int subscriptLevels) noexcept { + oxAssert(subscriptLevels <= static_cast(subscriptStack.size()), "subscript level mismatch"); m_type = type; m_typeSubscriptLevels = subscriptLevels; m_subscriptStack = std::move(subscriptStack); @@ -674,11 +676,11 @@ class ModelObject { for (const auto &f : type->fieldList) { auto field = make_unique(); field->name = f.fieldName; - oxReturnError(field->value.setType(f.type, f.subscriptLevels, f.subscriptStack)); + oxReturnError(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels)); m_fields[field->name] = &field->value; m_fieldsOrder.emplace_back(std::move(field)); } - return OxError(0); + return {}; } }; @@ -797,12 +799,12 @@ class ModelUnion { auto field = make_unique(); field->name = f.fieldName; field->idx = i; - oxReturnError(field->value.setType(f.type, f.subscriptLevels)); + oxReturnError(field->value.setType(f.type, SubscriptStack{static_cast(f.subscriptLevels)}, f.subscriptLevels)); m_fields[field->name] = field.get(); m_fieldsOrder.emplace_back(std::move(field)); ++i; } - return OxError(0); + return {}; } [[nodiscard]] @@ -1076,20 +1078,21 @@ constexpr ModelValue::Type ModelValue::type() const noexcept { constexpr Error ModelValue::setType( const DescriptorType *type, - int subscriptLevels, - SubscriptStack const&subscriptStack) noexcept { + SubscriptStack const&subscriptStack, + int subscriptLevels) noexcept { freeResources(); + oxAssert(subscriptLevels <= static_cast(subscriptStack.size()), "subscript level mismatch"); if (subscriptLevels) { auto const&subscript = subscriptStack[subscriptStack.size() - static_cast(subscriptLevels)]; if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) { m_type = Type::InlineArray; m_data.array = new ModelValueArray; - oxReturnError(m_data.array->setType(type, subscriptLevels - 1, subscriptStack)); + oxReturnError(m_data.array->setType(type, subscriptStack, subscriptLevels - 1)); oxReturnError(m_data.array->setSize(static_cast(subscript.length))); } else { m_type = Type::Vector; m_data.vec = new ModelValueVector; - oxReturnError(m_data.vec->setType(type, subscriptLevels - 1, subscriptStack)); + oxReturnError(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1)); } return {}; } else if (type->typeName == types::Bool) { diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index 2db945a..9f220c3 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -244,7 +244,9 @@ Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noex OrganicClawReader r(srcVal); ModelHandlerInterface handler{&r}; for (decltype(srcSize) i = 0; i < srcSize; ++i) { +OX_ALLOW_UNSAFE_BUFFERS_BEGIN oxReturnError(handler.field("", &val[i])); +OX_ALLOW_UNSAFE_BUFFERS_END } return OxError(0); } @@ -272,7 +274,9 @@ Error readOC(BufferView buff, auto &val) noexcept { Json::Value doc; Json::CharReaderBuilder parserBuilder; auto parser = UniquePtr(parserBuilder.newCharReader()); +OX_ALLOW_UNSAFE_BUFFERS_BEGIN if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) { +OX_ALLOW_UNSAFE_BUFFERS_END return OxError(1, "Could not parse JSON"); } OrganicClawReader reader(buff.data(), buff.size()); diff --git a/deps/ox/src/ox/oc/write.hpp b/deps/ox/src/ox/oc/write.hpp index 006bfd6..d87b0f7 100644 --- a/deps/ox/src/ox/oc/write.hpp +++ b/deps/ox/src/ox/oc/write.hpp @@ -200,7 +200,9 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n OrganicClawWriter w((Json::Value(Json::arrayValue))); ModelHandlerInterface handler{&w}; for (std::size_t i = 0; i < len; ++i) { +OX_ALLOW_UNSAFE_BUFFERS_BEGIN oxReturnError(handler.field({}, &val[i])); +OX_ALLOW_UNSAFE_BUFFERS_END } value(key) = w.m_json; } diff --git a/deps/ox/src/ox/std/CMakeLists.txt b/deps/ox/src/ox/std/CMakeLists.txt index 890868a..ae2b941 100644 --- a/deps/ox/src/ox/std/CMakeLists.txt +++ b/deps/ox/src/ox/std/CMakeLists.txt @@ -1,3 +1,9 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # enable warnings + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") +endif() + + if(OX_USE_STDLIB AND OX_ENABLE_TRACEHOOK) add_library( OxTraceHook SHARED diff --git a/deps/ox/src/ox/std/algorithm.hpp b/deps/ox/src/ox/std/algorithm.hpp index bc3d96e..c6c9bd6 100644 --- a/deps/ox/src/ox/std/algorithm.hpp +++ b/deps/ox/src/ox/std/algorithm.hpp @@ -8,6 +8,10 @@ #pragma once +#include "def.hpp" + +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -40,4 +44,6 @@ constexpr OutIt copy_n(It in, Size cnt, OutIt out) { return out; } -} \ No newline at end of file +} + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/array.hpp b/deps/ox/src/ox/std/array.hpp index 18926ec..996fe5a 100644 --- a/deps/ox/src/ox/std/array.hpp +++ b/deps/ox/src/ox/std/array.hpp @@ -9,6 +9,7 @@ #pragma once #include "bit.hpp" +#include "def.hpp" #include "error.hpp" #include "initializerlist.hpp" #include "iterator.hpp" @@ -17,6 +18,8 @@ #include "types.hpp" #include "utility.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -35,6 +38,10 @@ class Array { public: constexpr Array() noexcept = default; + template + constexpr Array(Args ...list) noexcept: m_items{std::move(list)...} { + } + constexpr Array(std::initializer_list list) noexcept; constexpr Array(const Array &other); @@ -174,11 +181,13 @@ constexpr Array &Array::operator=(Array &&other) noe template constexpr T &Array::operator[](std::size_t i) noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow"); return m_items[i]; } template constexpr const T &Array::operator[](std::size_t i) const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow"); return m_items[i]; } @@ -198,3 +207,5 @@ constexpr bool Array::contains(const T &v) const { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/assert.cpp b/deps/ox/src/ox/std/assert.cpp index 3f5f68c..0a8b7f7 100644 --- a/deps/ox/src/ox/std/assert.cpp +++ b/deps/ox/src/ox/std/assert.cpp @@ -6,6 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "fmt.hpp" #include "stacktrace.hpp" #include "trace.hpp" @@ -13,7 +14,7 @@ namespace ox { -void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept { +void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept { oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); if (err.msg) { oxErrf("\tError Message:\t{}\n", err.msg); @@ -31,4 +32,40 @@ void panic(const char *file, int line, const char *panicMsg, const Error &err) n #endif } +void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept { + panic(StringView{file}, line, StringView{panicMsg}, err); +} + +void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept { +#ifdef OX_USE_STDLIB + auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); + output += genStackTrace(2); + oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); + std::abort(); +#else + oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); + oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); + constexprPanic(file, line, msg); +#endif +} + +void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept { +#if defined(OX_USE_STDLIB) + auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg); + if (err.msg) { + msg += sfmt("\tError Message:\t{}\n", err.msg); + } + msg += sfmt("\tError Code:\t{}\n", static_cast(err)); + if (err.file != nullptr) { + msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line); + } + msg += genStackTrace(2); + oxErr(msg); + oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line); + std::abort(); +#else + constexprPanic(file, line, assertMsg); +#endif +} + } diff --git a/deps/ox/src/ox/std/assert.hpp b/deps/ox/src/ox/std/assert.hpp index 4ea28bf..b9873b9 100644 --- a/deps/ox/src/ox/std/assert.hpp +++ b/deps/ox/src/ox/std/assert.hpp @@ -32,19 +32,13 @@ constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg } } +void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept; +void assertFailFuncRuntime(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept; + constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept { if (!pass) { if (!std::is_constant_evaluated()) { -#ifdef OX_USE_STDLIB - auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); - output += genStackTrace(2); - oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); - std::abort(); -#else - oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); - oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); - constexprPanic(file, line, msg); -#endif + assertFailFuncRuntime(file, line, assertTxt, msg); } else { while (true); } @@ -54,22 +48,7 @@ constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept { if (err) { if (!std::is_constant_evaluated()) { -#if defined(OX_USE_STDLIB) - auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg); - if (err.msg) { - msg += sfmt("\tError Message:\t{}\n", err.msg); - } - msg += sfmt("\tError Code:\t{}\n", static_cast(err)); - if (err.file != nullptr) { - msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line); - } - msg += genStackTrace(2); - oxErr(msg); - oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line); - std::abort(); -#else - constexprPanic(file, line, assertMsg); -#endif + assertFailFuncRuntime(file, line, err, {}, assertMsg); } else { while (true); } diff --git a/deps/ox/src/ox/std/basestringview.hpp b/deps/ox/src/ox/std/basestringview.hpp index 45ff062..5532a53 100644 --- a/deps/ox/src/ox/std/basestringview.hpp +++ b/deps/ox/src/ox/std/basestringview.hpp @@ -9,9 +9,12 @@ #pragma once #include "bit.hpp" +#include "def.hpp" #include "cstrops.hpp" #include "iterator.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox::detail { class BaseStringView { @@ -202,7 +205,7 @@ class BaseStringView { } [[nodiscard]] - constexpr auto operator[](std::size_t i) const noexcept { + constexpr auto &operator[](std::size_t i) const noexcept { return m_str[i]; } @@ -215,3 +218,5 @@ class BaseStringView { }; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/buffer.hpp b/deps/ox/src/ox/std/buffer.hpp index b49d9eb..b33b7be 100644 --- a/deps/ox/src/ox/std/buffer.hpp +++ b/deps/ox/src/ox/std/buffer.hpp @@ -14,12 +14,14 @@ #include "vector.hpp" #include "writer.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { extern template class Vector; using Buffer = Vector; -using BufferView = SpanView; +using BufferView = Span; class BufferWriter { private: @@ -100,15 +102,11 @@ class CharBuffWriter { char *m_buff = nullptr; public: - template - explicit constexpr CharBuffWriter(ox::Array &buff) noexcept: + explicit constexpr CharBuffWriter(ox::Span buff) noexcept: m_cap(buff.size()), m_buff(buff.data()) { } - explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) { - } - constexpr ox::Error seekp(std::size_t p) noexcept { m_it = p; return {}; @@ -237,3 +235,5 @@ extern template class WriterT; extern template class WriterT; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/cstrops.hpp b/deps/ox/src/ox/std/cstrops.hpp index c86cacb..6b7820d 100644 --- a/deps/ox/src/ox/std/cstrops.hpp +++ b/deps/ox/src/ox/std/cstrops.hpp @@ -8,9 +8,12 @@ #pragma once +#include "def.hpp" #include "types.hpp" #include "typetraits.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -113,3 +116,5 @@ constexpr int lastIndexOf(const auto &str, int character, std::size_t maxLen = 0 } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/def.hpp b/deps/ox/src/ox/std/def.hpp index 790b005..ab848ca 100644 --- a/deps/ox/src/ox/std/def.hpp +++ b/deps/ox/src/ox/std/def.hpp @@ -44,10 +44,6 @@ // oxRequire Mutable #define oxRequireM(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxReturnError(oxConcat(oxRequire_err_, __LINE__)) #define oxRequire(out, x) const oxRequireM(out, x) -// oxRequire Mutable Throw -#define oxRequireMT(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxThrowError(oxConcat(oxRequire_err_, __LINE__)) -// oxRequire Throw -#define oxRequireT(out, x) const oxRequireMT(out, x) // Asserts @@ -75,6 +71,21 @@ constexpr void oxAssert(const ox::Error&, const char*) noexcept {} #define ox_alloca(size) __builtin_alloca(size) #endif +#define OX_PRAGMA(x) _Pragma(#x) +#ifdef __clang__ +#define OX_CLANG_NOWARN_BEGIN(warnoption) \ + OX_PRAGMA(clang diagnostic push) \ + OX_PRAGMA(clang diagnostic ignored #warnoption) +#define OX_CLANG_NOWARN_END OX_PRAGMA(clang diagnostic pop) +#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) +#define OX_ALLOW_UNSAFE_BUFFERS_END OX_CLANG_NOWARN_END +#else +#define OX_CLANG_NOWARN_BEGIN(warnoption) +#define OX_CLANG_NOWARN_END +#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN +#define OX_ALLOW_UNSAFE_BUFFERS_END +#endif + /** * @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation */ diff --git a/deps/ox/src/ox/std/error.hpp b/deps/ox/src/ox/std/error.hpp index 45d217e..49e2917 100644 --- a/deps/ox/src/ox/std/error.hpp +++ b/deps/ox/src/ox/std/error.hpp @@ -24,6 +24,7 @@ class exception { } #endif +#include "defines.hpp" #include "def.hpp" #include "typetraits.hpp" #include "utility.hpp" @@ -332,4 +333,12 @@ constexpr Error toError(const Result &r) noexcept { } +constexpr void primitiveAssert(const char *file, int line, bool pass, const char *msg) noexcept { + if constexpr(ox::defines::Debug) { + if (!pass) [[unlikely]] { + panic(file, line, msg, OxError(1)); + } + } +} + } diff --git a/deps/ox/src/ox/std/fmt.hpp b/deps/ox/src/ox/std/fmt.hpp index bc8d9a4..4694d02 100644 --- a/deps/ox/src/ox/std/fmt.hpp +++ b/deps/ox/src/ox/std/fmt.hpp @@ -25,6 +25,8 @@ #include "types.hpp" #include "typetraits.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { namespace detail { @@ -81,16 +83,16 @@ class FmtArg { private: static constexpr auto DataSz = 23; - char dataStr[DataSz] = {}; + ox::Array dataStr{}; template - constexpr StringView sv(const T &v, char *dataStr) noexcept { + constexpr StringView sv(const T &v, ox::Span dataStr) noexcept { if constexpr(is_bool_v) { return v ? "true" : "false"; } else if constexpr(is_integer_v) { - ox::CharBuffWriter w(dataStr, DataSz); + ox::CharBuffWriter w{dataStr}; std::ignore = ox::writeItoa(v, w); - return dataStr; + return dataStr.data(); } else { return toStringView(v); } @@ -225,3 +227,5 @@ constexpr Result join(auto const&d, auto const&list) { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/heapmgr.cpp b/deps/ox/src/ox/std/heapmgr.cpp index e7ef055..9cdc358 100644 --- a/deps/ox/src/ox/std/heapmgr.cpp +++ b/deps/ox/src/ox/std/heapmgr.cpp @@ -8,8 +8,11 @@ #include "assert.hpp" #include "bit.hpp" +#include "def.hpp" #include "heapmgr.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox::heapmgr { static struct HeapSegment *volatile g_heapBegin = nullptr; @@ -142,3 +145,5 @@ void operator delete[](void *ptr, unsigned long int) noexcept { } #endif + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/istring.hpp b/deps/ox/src/ox/std/istring.hpp index 118e6bd..6df2caa 100644 --- a/deps/ox/src/ox/std/istring.hpp +++ b/deps/ox/src/ox/std/istring.hpp @@ -10,6 +10,7 @@ #include "array.hpp" #include "concepts.hpp" +#include "def.hpp" #include "cstrops.hpp" #include "memops.hpp" #include "error.hpp" @@ -175,7 +176,9 @@ constexpr Error IString::append(const char *str, std::size_t strLen) noe strLen = cap() - currentLen; err = OxError(1, "Insufficient space for full string"); } +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) ox::strncpy(m_buff.data() + currentLen, str, strLen); +OX_CLANG_NOWARN_END // make sure last element is a null terminator m_buff[currentLen + strLen] = 0; m_size += strLen; @@ -263,7 +266,7 @@ constexpr auto itoa(Integer v) noexcept { }(); ox::IString out; std::ignore = out.resize(out.cap()); - ox::CharBuffWriter w(out.data(), out.cap()); + ox::CharBuffWriter w{{out.data(), out.cap()}}; std::ignore = writeItoa(v, w); std::ignore = out.resize(w.tellp()); return out; diff --git a/deps/ox/src/ox/std/iterator.hpp b/deps/ox/src/ox/std/iterator.hpp index b831060..d82e13f 100644 --- a/deps/ox/src/ox/std/iterator.hpp +++ b/deps/ox/src/ox/std/iterator.hpp @@ -8,6 +8,8 @@ #pragma once +#include "def.hpp" +#include "error.hpp" #include "math.hpp" #if !__has_include() @@ -38,6 +40,8 @@ struct contiguous_iterator_tag: public random_access_iterator_tag { #include #endif +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template() const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow"); return &m_t[m_offset]; } constexpr RefType operator*() const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow"); return m_t[m_offset]; } constexpr RefType operator[](std::size_t s) const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, s < m_max, "SpanIterator access overflow"); return m_t[s]; } @@ -167,3 +174,5 @@ struct SpanIterator { }; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/memops.cpp b/deps/ox/src/ox/std/memops.cpp index 86789ea..312b571 100644 --- a/deps/ox/src/ox/std/memops.cpp +++ b/deps/ox/src/ox/std/memops.cpp @@ -10,6 +10,8 @@ #include "types.hpp" #include "memops.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + #ifndef OX_USE_STDLIB #define ox_inhibit_loop_to_libcall __attribute__((__optimize__("-fno-tree-loop-distribute-patterns"))) @@ -96,3 +98,5 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/memops.hpp b/deps/ox/src/ox/std/memops.hpp index 202f3a6..6aa4b58 100644 --- a/deps/ox/src/ox/std/memops.hpp +++ b/deps/ox/src/ox/std/memops.hpp @@ -8,6 +8,7 @@ #pragma once +#include "def.hpp" #include "types.hpp" #include "typetraits.hpp" @@ -27,6 +28,8 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept; } #endif +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -56,3 +59,5 @@ void *memsetElements(T *ptr, T val, std::size_t elements) noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/optional.hpp b/deps/ox/src/ox/std/optional.hpp index f1c0022..db8d2d0 100644 --- a/deps/ox/src/ox/std/optional.hpp +++ b/deps/ox/src/ox/std/optional.hpp @@ -8,11 +8,7 @@ #pragma once -#include "bit.hpp" -#include "initializerlist.hpp" -#include "iterator.hpp" #include "memory.hpp" -#include "new.hpp" #include "types.hpp" #include "utility.hpp" diff --git a/deps/ox/src/ox/std/random.hpp b/deps/ox/src/ox/std/random.hpp index ac6bbf6..5f4ae4d 100644 --- a/deps/ox/src/ox/std/random.hpp +++ b/deps/ox/src/ox/std/random.hpp @@ -9,9 +9,12 @@ #pragma once #include "bit.hpp" +#include "def.hpp" #include "stddef.hpp" #include "types.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { using RandomSeed = uint64_t[2]; @@ -51,3 +54,5 @@ constexpr uint64_t Random::gen() noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/span.hpp b/deps/ox/src/ox/std/span.hpp index 9c8bb2a..c4ad680 100644 --- a/deps/ox/src/ox/std/span.hpp +++ b/deps/ox/src/ox/std/span.hpp @@ -10,135 +10,21 @@ #include "array.hpp" #include "bit.hpp" +#include "def.hpp" #include "iterator.hpp" #include "vector.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { -template -class SpanView { - - private: - T const*m_items{}; - std::size_t m_size{}; - - public: - using value_type = T; - using size_type = std::size_t; - - template - using iterator = SpanIterator; - - constexpr SpanView() noexcept {} - - template - constexpr SpanView(ox::Array const&a) noexcept: - m_items(a.data()), - m_size(a.size()) { - } - - template - constexpr SpanView(ox::Vector const&v) noexcept: - m_items(v.data()), - m_size(v.size()) { - } - - template - constexpr SpanView(const T a[sz]) noexcept: - m_items(a), - m_size(sz) { - } - - constexpr SpanView(const T *a, std::size_t sz) noexcept: - m_items(a), - m_size(sz) { - } - - constexpr iterator<> begin() noexcept { - return iterator<>(m_items, 0, m_size); - } - - constexpr iterator<> end() noexcept { - return iterator<>(m_items, m_size, m_size); - } - - [[nodiscard]] - constexpr iterator begin() const noexcept { - return iterator(m_items, 0, m_size); - } - - [[nodiscard]] - constexpr iterator end() const noexcept { - return iterator(m_items, m_size, m_size); - } - - [[nodiscard]] - constexpr iterator cbegin() const noexcept { - return iterator(m_items, 0, m_size); - } - - [[nodiscard]] - constexpr iterator cend() const noexcept { - return iterator(m_items, m_size, m_size); - } - - [[nodiscard]] - constexpr iterator crbegin() const noexcept { - return iterator(m_items, m_size - 1, m_size); - } - - [[nodiscard]] - constexpr iterator crend() const noexcept { - return iterator(m_items, MaxValue, m_size); - } - - [[nodiscard]] - constexpr iterator rbegin() const noexcept { - return iterator(m_items, m_size - 1, m_size); - } - - [[nodiscard]] - constexpr iterator rend() const noexcept { - return iterator(m_items, MaxValue, m_size); - } - - constexpr const T &operator[](std::size_t i) const noexcept { - return m_items[i]; - } - - constexpr SpanView operator+(size_t i) const noexcept { - return {m_items + i, m_size - i}; - } - - constexpr SpanView operator+=(size_t i) noexcept { - m_items += i; - m_size -= i; - return *this; - } - - [[nodiscard]] - constexpr T const*data() const noexcept { - return m_items; - } - - [[nodiscard]] - constexpr std::size_t size() const noexcept { - return m_size; - } - - [[nodiscard]] - constexpr bool empty() const noexcept { - return m_size == 0; - } - -}; template class Span { private: T *m_items{}; - const std::size_t m_size{}; + std::size_t m_size{}; public: using value_type = T; @@ -147,20 +33,34 @@ class Span { template using iterator = SpanIterator; + constexpr Span() noexcept = default; + template constexpr Span(ox::Array &a) noexcept: m_items(a.data()), m_size(a.size()) { } + template + constexpr Span(ox::Array, sz> const&a) noexcept: + m_items(a.data()), + m_size(a.size()) { + } + template constexpr Span(ox::Vector &v) noexcept: m_items(v.data()), m_size(v.size()) { } + template + constexpr Span(ox::Vector, sz, Allocator> const&v) noexcept: + m_items(v.data()), + m_size(v.size()) { + } + template - constexpr Span(T a[sz]) noexcept: + constexpr Span(T (&a)[sz]) noexcept: m_items(a), m_size(sz) { } @@ -229,13 +129,27 @@ class Span { } constexpr T &operator[](std::size_t i) noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow"); return m_items[i]; } constexpr const T &operator[](std::size_t i) const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow"); return m_items[i]; } + constexpr Span operator+(size_t i) const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow"); + return {m_items + i, m_size - i}; + } + + constexpr Span operator+=(size_t i) noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow"); + m_items += i; + m_size -= i; + return *this; + } + [[nodiscard]] constexpr auto data() const noexcept { return m_items; @@ -253,4 +167,9 @@ class Span { }; +template +using SpanView = Span; + } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/stacktrace.cpp b/deps/ox/src/ox/std/stacktrace.cpp index b4da271..5d3271a 100644 --- a/deps/ox/src/ox/std/stacktrace.cpp +++ b/deps/ox/src/ox/std/stacktrace.cpp @@ -18,11 +18,14 @@ #endif #endif +#include "def.hpp" #include "defines.hpp" #include "string.hpp" #include "trace.hpp" #include "vector.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { #if defined(OX_USE_STDLIB) && __has_include() @@ -100,3 +103,5 @@ void printStackTrace([[maybe_unused]]unsigned shave) noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/string.hpp b/deps/ox/src/ox/std/string.hpp index 7d6a7ba..93daefd 100644 --- a/deps/ox/src/ox/std/string.hpp +++ b/deps/ox/src/ox/std/string.hpp @@ -13,6 +13,7 @@ #endif #include "algorithm.hpp" +#include "def.hpp" #include "ignore.hpp" #include "memops.hpp" #include "serialize.hpp" @@ -22,6 +23,8 @@ #include "strops.hpp" #include "vector.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -496,12 +499,12 @@ constexpr char &BasicString::operator[](std::size_t i) noexce template constexpr BasicString BasicString::substr(std::size_t pos) const noexcept { - return BasicString(m_buff.data() + pos, m_buff.size() - pos - 1); + return BasicString(&m_buff[pos], m_buff.size() - pos - 1); } template constexpr BasicString BasicString::substr(std::size_t begin, std::size_t end) const noexcept { - const auto src = m_buff.data() + begin; + const auto src = &m_buff[begin]; const auto size = end - begin; BasicString out(size); const auto buff = out.data(); @@ -568,3 +571,5 @@ struct MaybeView> { }; } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/stringview.hpp b/deps/ox/src/ox/std/stringview.hpp index c9c6af7..b2c4294 100644 --- a/deps/ox/src/ox/std/stringview.hpp +++ b/deps/ox/src/ox/std/stringview.hpp @@ -17,6 +17,8 @@ #include "maybeview.hpp" #include "writer.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { template @@ -116,3 +118,4 @@ constexpr ox::Result atoi(ox::StringViewCR str) noexcept { } +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/strops.cpp b/deps/ox/src/ox/std/strops.cpp index 2bab557..add1742 100644 --- a/deps/ox/src/ox/std/strops.cpp +++ b/deps/ox/src/ox/std/strops.cpp @@ -6,6 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "def.hpp" #include "strops.hpp" static_assert(ox::strcmp("asdf", "hijk") < 0, "asdf < hijk"); @@ -17,7 +18,9 @@ static_assert(ox::strcmp("", "") == 0, "\"\" == \"\""); static_assert([] { auto testStr = "asdf"; +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) return ox::strchr(testStr, 0, 4) == &testStr[4]; +OX_CLANG_NOWARN_END }(), "ox::strchr 0"); static_assert([] { diff --git a/deps/ox/src/ox/std/strops.hpp b/deps/ox/src/ox/std/strops.hpp index 260ec83..65e8900 100644 --- a/deps/ox/src/ox/std/strops.hpp +++ b/deps/ox/src/ox/std/strops.hpp @@ -9,18 +9,21 @@ #pragma once #include "cstrops.hpp" +#include "def.hpp" #include "error.hpp" #include "math.hpp" #include "stringview.hpp" #include "types.hpp" #include "vector.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { [[nodiscard]] constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexcept { if (str.len() >= pos) { - return {str.data() + pos, str.len() - pos}; + return {&str[pos], str.len() - pos}; } return {}; } @@ -28,7 +31,7 @@ constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexc [[nodiscard]] constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std::size_t end) noexcept { if (str.len() >= start && end >= start) { - return {str.data() + start, end - start}; + return {&str[start], end - start}; } return {}; } @@ -113,3 +116,5 @@ constexpr ox::Result lastIndexOf(ox::StringViewCR str, int characte } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/test/tests.cpp b/deps/ox/src/ox/std/test/tests.cpp index 1a470b2..4aecb7c 100644 --- a/deps/ox/src/ox/std/test/tests.cpp +++ b/deps/ox/src/ox/std/test/tests.cpp @@ -121,7 +121,9 @@ static std::map tests = { auto a1 = static_cast(ox::heapmgr::malloc(5)); auto a2 = static_cast(ox::heapmgr::malloc(5)); oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken"); +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken"); +OX_CLANG_NOWARN_END ox::heapmgr::free(a1); ox::heapmgr::free(a2); return OxError(0); @@ -470,10 +472,12 @@ static std::map tests = { }, }; -int main(int argc, const char **args) { +int main(int argc, const char **argv) { if (argc < 2) { oxError("Must specify test to run"); + return -1; } + auto const args = ox::Span{argv, static_cast(argc)}; auto const testName = args[1]; auto const func = tests.find(testName); if (func != tests.end()) { diff --git a/deps/ox/src/ox/std/trace.cpp b/deps/ox/src/ox/std/trace.cpp index 472c594..0267c5d 100644 --- a/deps/ox/src/ox/std/trace.cpp +++ b/deps/ox/src/ox/std/trace.cpp @@ -10,6 +10,17 @@ namespace ox::trace { +static class: public Logger { + public: + ox::Error send(const TraceMsg&) noexcept final { + return {}; + } + ox::Error sendInit(const InitTraceMsg&) noexcept final { + return {}; + } +} defaultLogger; +static Logger *logger = &defaultLogger; + void init() { oxTraceInitHook(); } @@ -19,19 +30,6 @@ void init(Logger *logger) { setLogger(logger); } -class NullLogger: public Logger { - public: - ox::Error send(const TraceMsg&) noexcept final { - return {}; - } - ox::Error sendInit(const InitTraceMsg&) noexcept final { - return {}; - } -}; - -static NullLogger defaultLogger; -static Logger *logger = &defaultLogger; - void setLogger(Logger *logger) noexcept { trace::logger = logger; } diff --git a/deps/ox/src/ox/std/trace.hpp b/deps/ox/src/ox/std/trace.hpp index de7c536..b156957 100644 --- a/deps/ox/src/ox/std/trace.hpp +++ b/deps/ox/src/ox/std/trace.hpp @@ -173,7 +173,7 @@ class OutStream { return *this; } - constexpr OutStream &operator<<(const char *v) noexcept { + constexpr OutStream &operator<<(StringViewCR v) noexcept { if (m_msg.msg.len()) { m_msg.msg += m_delimiter; } @@ -181,6 +181,10 @@ class OutStream { return *this; } + constexpr OutStream &operator<<(const char *v) noexcept { + return operator<<(StringView{v}); + } + template constexpr OutStream &operator<<(const IString &v) noexcept { return operator<<(v.c_str()); diff --git a/deps/ox/src/ox/std/typetraits.hpp b/deps/ox/src/ox/std/typetraits.hpp index 9207bab..6202efb 100644 --- a/deps/ox/src/ox/std/typetraits.hpp +++ b/deps/ox/src/ox/std/typetraits.hpp @@ -269,6 +269,41 @@ template constexpr bool is_move_constructible_v = detail::is_move_constructible(0); +template +struct remove_cv { + using type = T; +}; + +template +struct remove_cv { + using type = T; +}; + +template +struct remove_cv { + using type = T; +}; + +template +struct remove_cv { + using type = T; +}; + + +template +struct remove_const { + using type = T; +}; + +template +struct remove_const { + using type = T; +}; + +template +using remove_const_t = typename remove_const::type; + + // is String? template diff --git a/deps/ox/src/ox/std/uuid.hpp b/deps/ox/src/ox/std/uuid.hpp index 5e55925..444a856 100644 --- a/deps/ox/src/ox/std/uuid.hpp +++ b/deps/ox/src/ox/std/uuid.hpp @@ -9,6 +9,7 @@ #pragma once #include "bit.hpp" +#include "def.hpp" #include "ignore.hpp" #include "istring.hpp" #include "buffer.hpp" @@ -18,6 +19,8 @@ #include "stringview.hpp" #include "strops.hpp" +OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) + namespace ox { using UUIDStr = ox::IString<36>; @@ -107,12 +110,12 @@ class UUID { static ox::Result generate() noexcept; [[nodiscard]] - constexpr auto const&value() const noexcept { + constexpr ox::Array const&value() const noexcept { return m_value; } [[nodiscard]] - constexpr auto isNull() const noexcept { + constexpr bool isNull() const noexcept { if (std::is_constant_evaluated()) { if (ox::all_of(m_value.begin(), m_value.end(), [](auto v) { return v == 0; })) { return true; @@ -187,7 +190,7 @@ class UUID { constexpr UUIDStr toString() const noexcept { UUIDStr out; std::ignore = out.resize(UUIDStr::cap()); - ox::CharBuffWriter bw(out.data(), UUIDStr::cap()); + ox::CharBuffWriter bw{{out.data(), UUIDStr::cap()}}; std::ignore = toString(bw); out[UUIDStr::cap()] = 0; return out; @@ -220,3 +223,5 @@ constexpr Error model(T *io, ox::CommonPtrWith auto *obj) noexcept { } } + +OX_CLANG_NOWARN_END diff --git a/deps/ox/src/ox/std/vec.cpp b/deps/ox/src/ox/std/vec.cpp index 6da9c75..8220cec 100644 --- a/deps/ox/src/ox/std/vec.cpp +++ b/deps/ox/src/ox/std/vec.cpp @@ -14,7 +14,7 @@ namespace ox { static_assert([] { Vec2 v(1, 2); - return v.x == 1 && v.y == 2 && v[0] == 1 && v[1] == 2 && v.size() == 2; + return v.x == 1 && v.y == 2 && v.size() == 2; }()); } diff --git a/deps/ox/src/ox/std/vec.hpp b/deps/ox/src/ox/std/vec.hpp index 3c443d4..8b44ce0 100644 --- a/deps/ox/src/ox/std/vec.hpp +++ b/deps/ox/src/ox/std/vec.hpp @@ -34,112 +34,6 @@ class Vec2 { float x = 0; float y = 0; - template - struct iterator: public ox::Iterator { - private: - PtrType m_t = nullptr; - size_type m_offset = 0; - size_type m_max = 0; - - public: - constexpr iterator() noexcept = default; - - constexpr iterator(PtrType t, size_type offset, size_type max) noexcept { - m_t = t; - m_offset = offset; - m_max = max; - } - - [[nodiscard]] - constexpr auto offset() const noexcept { - return m_offset; - } - - constexpr iterator operator+(size_type s) const noexcept { - if constexpr(reverse) { - return iterator(m_t, ox::max(m_offset - s, 0), m_max); - } else { - return iterator(m_t, ox::min(m_offset + s, m_max), m_max); - } - } - - constexpr typename ox::Iterator::difference_type - 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-(size_type s) const noexcept { - if constexpr(reverse) { - return iterator(m_t, ox::min(m_offset + s, m_max), m_max); - } else { - return iterator(m_t, ox::max(m_offset - s, 0), m_max); - } - } - - constexpr iterator &operator+=(size_type s) noexcept { - if constexpr(reverse) { - m_offset = ox::max(m_offset - s, 0); - } else { - m_offset = ox::min(m_offset + s, m_max); - } - return *this; - } - - constexpr iterator &operator-=(size_type s) noexcept { - if constexpr(reverse) { - m_offset = ox::min(m_offset + s, m_max); - } else { - m_offset = ox::max(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[](size_type 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; - } - - }; - constexpr Vec2() noexcept = default; explicit constexpr Vec2(class Point const&pt) noexcept; @@ -159,85 +53,8 @@ class Vec2 { } #endif - [[nodiscard]] - constexpr iterator<> begin() noexcept { - return {start(), 0, size()}; - } - - [[nodiscard]] - constexpr iterator<> end() noexcept { - return {start(), size(), size()}; - } - - [[nodiscard]] - constexpr iterator begin() const noexcept { - return {start(), 0, size()}; - } - - [[nodiscard]] - constexpr iterator end() const noexcept { - return {start(), size(), size()}; - } - - [[nodiscard]] - constexpr iterator rbegin() noexcept { - return {start(), size() - 1, size()}; - } - - [[nodiscard]] - constexpr iterator rend() noexcept { - return {start(), ox::MaxValue, size()}; - } - - [[nodiscard]] - constexpr iterator rbegin() const noexcept { - return {start(), size() - 1, size()}; - } - - [[nodiscard]] - constexpr iterator rend() const noexcept { - return {start(), ox::MaxValue, size()}; - } - - constexpr auto &operator[](std::size_t i) noexcept { - if (std::is_constant_evaluated()) { - switch (i) { - case 0: - return x; - case 1: - return y; - default: - oxAssert(false, "Read past end of Vec2"); - return y; - } - } else { - return start()[i]; - } - } - - constexpr const auto &operator[](std::size_t i) const noexcept { - if (std::is_constant_evaluated()) { - switch (i) { - case 0: - return x; - case 1: - return y; - default: - oxAssert(false, "Read past end of Vec2"); - return y; - } - } else { - return start()[i]; - } - } - constexpr auto operator==(const Vec2 &v) const noexcept { - for (auto i = 0u; i < v.size(); ++i) { - if ((*this)[i] != v[i]) { - return false; - } - } - return true; + return x == v.x && y == v.y; } constexpr auto operator!=(const Vec2 &v) const noexcept { @@ -292,17 +109,6 @@ class Vec2 { y /= i; return *this; } - - protected: - [[nodiscard]] - constexpr float *start() noexcept { - return&x; - } - - [[nodiscard]] - constexpr const float *start() const noexcept { - return &x; - } }; template diff --git a/deps/ox/src/ox/std/vector.hpp b/deps/ox/src/ox/std/vector.hpp index 8035dfb..7bdaf52 100644 --- a/deps/ox/src/ox/std/vector.hpp +++ b/deps/ox/src/ox/std/vector.hpp @@ -20,6 +20,8 @@ #include "types.hpp" #include "utility.hpp" +OX_ALLOW_UNSAFE_BUFFERS_BEGIN + namespace ox { namespace detail { @@ -422,11 +424,13 @@ constexpr Vector &Vector constexpr T &Vector::operator[](std::size_t i) noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Vector access overflow"); return m_items[i]; } template constexpr const T &Vector::operator[](std::size_t i) const noexcept { + ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Vector access overflow"); return m_items[i]; } @@ -707,3 +711,5 @@ constexpr auto alignOf(const Vector&) noexcept { } } + +OX_ALLOW_UNSAFE_BUFFERS_END diff --git a/deps/teagba/include/teagba/registers.hpp b/deps/teagba/include/teagba/registers.hpp index efe3691..2311a72 100644 --- a/deps/teagba/include/teagba/registers.hpp +++ b/deps/teagba/include/teagba/registers.hpp @@ -6,6 +6,8 @@ #include "addresses.hpp" +OX_ALLOW_UNSAFE_BUFFERS_BEGIN + namespace teagba { inline auto bgSetSbb(volatile BgCtl &bgCtl, unsigned sbb) noexcept { @@ -53,3 +55,5 @@ constexpr void iterateBgCtl(auto cb) noexcept { } } + +OX_ALLOW_UNSAFE_BUFFERS_END diff --git a/src/nostalgia/CMakeLists.txt b/src/nostalgia/CMakeLists.txt index 4600ff5..986c3f1 100644 --- a/src/nostalgia/CMakeLists.txt +++ b/src/nostalgia/CMakeLists.txt @@ -1,4 +1,9 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # enable warnings + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") +endif() + project(nostalgia CXX) #project packages diff --git a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp index 8092345..88b0f98 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp @@ -121,11 +121,20 @@ ox::Error loadSpritePalette( CompactPalette const&palette, size_t page = 0) noexcept; +ox::Error loadBgPalette( + Context &ctx, + size_t palBank, + ox::StringViewCR palettePath) noexcept; + ox::Error loadBgPalette( Context &ctx, size_t palBank, ox::FileAddress const&paletteAddr) noexcept; +ox::Error loadSpritePalette( + Context &ctx, + ox::StringViewCR palettePath) noexcept; + ox::Error loadSpritePalette( Context &ctx, ox::FileAddress const&paletteAddr) noexcept; @@ -143,6 +152,14 @@ ox::Error loadBgTileSheet( size_t srcTileIdx, size_t tileCnt) noexcept; +ox::Error loadBgTileSheet( + Context &ctx, + unsigned cbb, + ox::StringViewCR tsPath, + size_t dstTileIdx, + size_t srcTileIdx, + size_t tileCnt) noexcept; + ox::Error loadBgTileSheet( Context &ctx, unsigned cbb, @@ -157,6 +174,12 @@ ox::Error loadBgTileSheet( CompactTileSheet const&ts, ox::Optional const&paletteBank = {}) noexcept; +ox::Error loadBgTileSheet( + Context &ctx, + unsigned cbb, + ox::StringViewCR tilesheetPath, + ox::Optional const&paletteBank) noexcept; + ox::Error loadBgTileSheet( Context &ctx, unsigned cbb, @@ -168,6 +191,11 @@ ox::Error loadSpriteTileSheet( CompactTileSheet const&ts, bool loadDefaultPalette) noexcept; +ox::Error loadSpriteTileSheet( + Context &ctx, + ox::StringViewCR tilesheetPath, + bool loadDefaultPalette = false) noexcept; + ox::Error loadSpriteTileSheet( Context &ctx, ox::FileAddress const&tilesheetAddr, diff --git a/src/nostalgia/modules/core/include/nostalgia/core/initparams.hpp b/src/nostalgia/modules/core/include/nostalgia/core/initparams.hpp index c4770c7..701a19c 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/initparams.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/initparams.hpp @@ -4,6 +4,8 @@ #pragma once +#include + namespace nostalgia::core { struct InitParams { @@ -12,4 +14,4 @@ struct InitParams { uint_t glBlocksPerSprite = 64; }; -} \ No newline at end of file +} diff --git a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp index dfbe030..9821cc4 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/tilesheet.hpp @@ -33,7 +33,14 @@ struct TileSheetV1 { [[nodiscard]] constexpr bool valid(TileSheetV1 const&ts) noexcept { - return ts.bpp == 4 || ts.bpp == 8; + auto const bytes = static_cast(ts.columns * ts.rows * PixelsPerTile) / (ts.bpp == 4 ? 2 : 1); + return (ts.bpp == 4 || ts.bpp == 8) && ts.pixels.size() == bytes; +} + +constexpr ox::Error repair(TileSheetV1 &ts, int bpp) noexcept { + auto const bytes = static_cast(ts.columns * ts.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + ts.pixels.resize(bytes); + return {}; } @@ -65,9 +72,34 @@ struct TileSheetV2 { }; +[[nodiscard]] +constexpr bool valid(TileSheetV2::SubSheet const&ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(), + [bpp, bytes](TileSheetV2::SubSheet const&s) { + return bytes == s.pixels.size() && valid(s, bpp); + }); +} + [[nodiscard]] constexpr bool valid(TileSheetV2 const&ts) noexcept { - return ts.bpp == 4 || ts.bpp == 8; + return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp); +} + +constexpr void repair(TileSheetV2::SubSheet &ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + ss.pixels.resize(bytes); + for (auto &s : ss.subsheets) { + repair(s, bpp); + } +} + +constexpr ox::Error repair(TileSheetV2 &ts) noexcept { + if (ts.bpp != 4 && ts.bpp != 8) { + return OxError(1, "Unable to repair TileSheet"); + } + repair(ts.subsheet, ts.bpp); + return {}; } @@ -110,9 +142,34 @@ struct TileSheetV3 { }; +[[nodiscard]] +constexpr bool valid(TileSheetV3::SubSheet const&ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(), + [bpp, bytes](TileSheetV3::SubSheet const&s) { + return bytes == s.pixels.size() && valid(s, bpp); + }); +} + [[nodiscard]] constexpr bool valid(TileSheetV3 const&ts) noexcept { - return ts.bpp == 4 || ts.bpp == 8; + return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp); +} + +constexpr void repair(TileSheetV3::SubSheet &ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + ss.pixels.resize(bytes); + for (auto &s : ss.subsheets) { + repair(s, bpp); + } +} + +constexpr ox::Error repair(TileSheetV3 &ts) noexcept { + if (ts.bpp != 4 && ts.bpp != 8) { + return OxError(1, "Unable to repair TileSheet"); + } + repair(ts.subsheet, ts.bpp); + return {}; } @@ -173,9 +230,34 @@ struct TileSheetV4 { }; +[[nodiscard]] +constexpr bool valid(TileSheetV4::SubSheet const&ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(), + [bpp, bytes](TileSheetV4::SubSheet const&s) { + return bytes == s.pixels.size() && valid(s, bpp); + }); +} + [[nodiscard]] constexpr bool valid(TileSheetV4 const&ts) noexcept { - return ts.bpp == 4 || ts.bpp == 8; + return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp); +} + +constexpr void repair(TileSheetV4::SubSheet &ss, int bpp) noexcept { + auto const bytes = static_cast(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1); + ss.pixels.resize(bytes); + for (auto &s : ss.subsheets) { + repair(s, bpp); + } +} + +constexpr ox::Error repair(TileSheetV4 &ts) noexcept { + if (ts.bpp != 4 && ts.bpp != 8) { + return OxError(1, "Unable to repair TileSheet"); + } + repair(ts.subsheet, ts.bpp); + return {}; } diff --git a/src/nostalgia/modules/core/src/gba/gfx.cpp b/src/nostalgia/modules/core/src/gba/gfx.cpp index c2dffd5..db0256b 100644 --- a/src/nostalgia/modules/core/src/gba/gfx.cpp +++ b/src/nostalgia/modules/core/src/gba/gfx.cpp @@ -17,6 +17,8 @@ #include "context.hpp" +OX_ALLOW_UNSAFE_BUFFERS_BEGIN + namespace nostalgia::core { static constexpr auto SpriteCount = 128; @@ -283,3 +285,5 @@ uint_t spriteCount(Context&) noexcept { } } + +OX_ALLOW_UNSAFE_BUFFERS_END diff --git a/src/nostalgia/modules/core/src/gba/panic.cpp b/src/nostalgia/modules/core/src/gba/panic.cpp index 728e3b0..bc6169d 100644 --- a/src/nostalgia/modules/core/src/gba/panic.cpp +++ b/src/nostalgia/modules/core/src/gba/panic.cpp @@ -25,7 +25,9 @@ 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_ALLOW_UNSAFE_BUFFERS_BEGIN ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END); +OX_ALLOW_UNSAFE_BUFFERS_END auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap(); auto ctx = init(*tctx).unwrap(); std::ignore = initGfx(*ctx, {}); diff --git a/src/nostalgia/modules/core/src/gfx.cpp b/src/nostalgia/modules/core/src/gfx.cpp index 4610225..c0ecf50 100644 --- a/src/nostalgia/modules/core/src/gfx.cpp +++ b/src/nostalgia/modules/core/src/gfx.cpp @@ -18,6 +18,14 @@ int tileRows(Context&) noexcept { return GbaTileRows; } +ox::Error loadBgPalette( + Context &ctx, + size_t palBank, + ox::StringViewCR palettePath) noexcept { + oxRequire(pal, keel::readObj(keelCtx(ctx), palettePath)); + return loadBgPalette(ctx, palBank, *pal, 0); +} + ox::Error loadBgPalette( Context &ctx, size_t palBank, @@ -26,6 +34,13 @@ ox::Error loadBgPalette( return loadBgPalette(ctx, palBank, *pal, 0); } +ox::Error loadSpritePalette( + Context &ctx, + ox::StringViewCR palettePath) noexcept { + oxRequire(pal, keel::readObj(keelCtx(ctx), palettePath)); + return loadSpritePalette(ctx, *pal, 0); +} + ox::Error loadSpritePalette( Context &ctx, ox::FileAddress const&paletteAddr) noexcept { @@ -44,6 +59,26 @@ ox::Error loadBgTileSheet( return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt); } +ox::Error loadBgTileSheet( + Context &ctx, + unsigned cbb, + ox::StringViewCR tsPath, + size_t dstTileIdx, + size_t srcTileIdx, + size_t tileCnt) noexcept { + oxRequire(ts, keel::readObj(keelCtx(ctx), tsPath)); + return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt); +} + +ox::Error loadBgTileSheet( + Context &ctx, + unsigned cbb, + ox::StringViewCR tilesheetPath, + ox::Optional const&paletteBank) noexcept { + oxRequire(ts, keel::readObj(keelCtx(ctx), tilesheetPath)); + return loadBgTileSheet(ctx, cbb, *ts, paletteBank); +} + ox::Error loadBgTileSheet( Context &ctx, unsigned cbb, @@ -53,6 +88,14 @@ ox::Error loadBgTileSheet( return loadBgTileSheet(ctx, cbb, *ts, paletteBank); } +ox::Error loadSpriteTileSheet( + Context &ctx, + ox::StringViewCR tilesheetPath, + bool loadDefaultPalette) noexcept { + oxRequire(ts, readObj(keelCtx(ctx), tilesheetPath)); + return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette); +} + ox::Error loadSpriteTileSheet( Context &ctx, ox::FileAddress const&tilesheetAddr, @@ -213,12 +256,11 @@ void puts( int const column, int const row, ox::StringViewCR str) noexcept { - auto const col = static_cast(column); for (auto i = 0u; i < str.bytes(); ++i) { setBgTile( ctx, 0, - static_cast(col + i), + column + static_cast(i), row, static_cast(charMap[static_cast(str[i])])); } diff --git a/src/nostalgia/modules/core/src/opengl/gfx.cpp b/src/nostalgia/modules/core/src/opengl/gfx.cpp index dc10de0..efe06de 100644 --- a/src/nostalgia/modules/core/src/opengl/gfx.cpp +++ b/src/nostalgia/modules/core/src/opengl/gfx.cpp @@ -554,20 +554,21 @@ static ox::Result buildSetTsd( static void copyPixels( CompactTileSheet const&ts, - uint32_t *dst, + ox::Span dst, size_t const srcPxIdx, size_t pxlCnt) noexcept { + size_t idx{}; if (ts.bpp == 4) { for (size_t i = 0; i < pxlCnt; i += 2) { auto const [a, b] = get2Pixels4Bpp(ts, i + srcPxIdx); - *(dst++) = a; - *(dst++) = b; + dst[idx++] = a; + dst[idx++] = b; } } else if (ts.bpp == 8) { for (size_t i = 0; i < pxlCnt; i += 2) { auto const [a, b] = get2Pixels8Bpp(ts, i + srcPxIdx); - *(dst++) = a; - *(dst++) = b; + dst[idx++] = a; + dst[idx++] = b; } } } @@ -587,7 +588,7 @@ ox::Error loadBgTileSheet( if (dstPxIdx + pxlCnt >= cbbPxls.size()) { return OxError(1, "video mem dst overflow"); } - auto const dst = &cbbPxls[dstPxIdx]; + auto const dst = ox::Span{cbbPxls} + dstPxIdx; copyPixels(ts, dst, srcPxIdx, pxlCnt); auto const cbbTiles = cbbPxls.size() / bytesPerTile; int constexpr cbbWidth = 8; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.cpp index 5f01df7..0ab608f 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.cpp @@ -12,7 +12,7 @@ TileSheetClipboard::Pixel::Pixel(uint16_t pColorIdx, ox::Point pPt) noexcept { } -void TileSheetClipboard::addPixel(const ox::Point &pt, uint16_t colorIdx) noexcept { +void TileSheetClipboard::addPixel(ox::Point const&pt, uint16_t colorIdx) noexcept { m_pixels.emplace_back(colorIdx, pt); } @@ -25,18 +25,20 @@ CutPasteCommand::CutPasteCommand( CommandId commandId, TileSheet &img, TileSheet::SubSheetIdx subSheetIdx, - const ox::Point &dstStart, - const ox::Point &dstEnd, - const TileSheetClipboard &cb) noexcept: + ox::Point const&dstStart, + ox::Point dstEnd, + TileSheetClipboard const&cb) noexcept: m_commandId(commandId), m_img(img), m_subSheetIdx(std::move(subSheetIdx)) { - const auto &subsheet = getSubSheet(m_img, m_subSheetIdx); - for (const auto &p : cb.pixels()) { - const auto dstPt = p.pt + dstStart; + auto const&ss = getSubSheet(m_img, m_subSheetIdx); + dstEnd.x = std::min(ss.columns * TileWidth - 1, dstEnd.x); + dstEnd.y = std::min(ss.rows * TileHeight - 1, dstEnd.y); + for (auto const&p : cb.pixels()) { + auto const dstPt = p.pt + dstStart; if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) { - const auto idx = core::idx(subsheet, dstPt); - m_changes.emplace_back(static_cast(idx), p.colorIdx, getPixel(subsheet, m_img.bpp, idx)); + auto const idx = core::idx(ss, dstPt); + m_changes.emplace_back(static_cast(idx), p.colorIdx, getPixel(ss, m_img.bpp, idx)); } } } diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp index 5dece14..6df4464 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp @@ -68,7 +68,7 @@ class CutPasteCommand: public TileSheetCommand { TileSheet &img, TileSheet::SubSheetIdx subSheetIdx, ox::Point const&dstStart, - ox::Point const&dstEnd, + ox::Point dstEnd, TileSheetClipboard const&cb) noexcept; ox::Error redo() noexcept final; @@ -83,4 +83,4 @@ class CutPasteCommand: public TileSheetCommand { }; -} \ No newline at end of file +} diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/deletetilescommand.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/deletetilescommand.cpp index 09e5749..ab2bc2e 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/deletetilescommand.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/deletetilescommand.cpp @@ -2,6 +2,8 @@ * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include + #include "deletetilescommand.hpp" namespace nostalgia::core { @@ -20,11 +22,9 @@ core::DeleteTilesCommand::DeleteTilesCommand( // copy pixels to be erased { auto &s = getSubSheet(m_img, m_idx); - auto &p = s.pixels; - auto dst = m_deletedPixels.data(); - auto src = p.data() + m_deletePos; - const auto sz = m_deleteSz * sizeof(decltype(p[0])); - ox::memcpy(dst, src, sz); + auto dst = m_deletedPixels.begin(); + auto src = s.pixels.begin() + m_deletePos; + ox::copy_n(src, m_deleteSz, dst); } } @@ -32,9 +32,9 @@ ox::Error core::DeleteTilesCommand::redo() noexcept { auto &s = getSubSheet(m_img, m_idx); auto &p = s.pixels; auto srcPos = m_deletePos + m_deleteSz; - const auto src = p.data() + srcPos; - const auto dst1 = p.data() + m_deletePos; - const auto dst2 = p.data() + (p.size() - m_deleteSz); + auto const src = &p[srcPos]; + auto const dst1 = &p[m_deletePos]; + auto const dst2 = &p[(p.size() - m_deleteSz)]; ox::memmove(dst1, src, p.size() - srcPos); ox::memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0]))); return {}; @@ -43,10 +43,10 @@ ox::Error core::DeleteTilesCommand::redo() noexcept { ox::Error DeleteTilesCommand::undo() noexcept { auto &s = getSubSheet(m_img, m_idx); auto &p = s.pixels; - const auto src = p.data() + m_deletePos; - const auto dst1 = p.data() + m_deletePos + m_deleteSz; - const auto dst2 = src; - const auto sz = p.size() - m_deletePos - m_deleteSz; + auto const src = &p[m_deletePos]; + auto const dst1 = &p[m_deletePos + m_deleteSz]; + auto const dst2 = src; + auto const sz = p.size() - m_deletePos - m_deleteSz; ox::memmove(dst1, src, sz); ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size()); return {}; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/inserttilescommand.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/inserttilescommand.cpp index d4a2437..99d0d52 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/inserttilescommand.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/inserttilescommand.cpp @@ -21,10 +21,9 @@ core::InsertTilesCommand::InsertTilesCommand( { auto &s = getSubSheet(m_img, m_idx); auto &p = s.pixels; - auto dst = m_deletedPixels.data(); - auto src = p.data() + p.size() - m_insertCnt; - const auto sz = m_insertCnt * sizeof(decltype(p[0])); - ox::memcpy(dst, src, sz); + auto dst = m_deletedPixels.begin(); + auto src = p.begin() + p.size() - m_insertCnt; + ox::copy_n(src, m_insertCnt, dst); } } @@ -32,8 +31,8 @@ ox::Error InsertTilesCommand::redo() noexcept { auto &s = getSubSheet(m_img, m_idx); auto &p = s.pixels; auto dstPos = m_insertPos + m_insertCnt; - const auto dst = p.data() + dstPos; - const auto src = p.data() + m_insertPos; + auto const dst = &p[dstPos]; + auto const src = &p[m_insertPos]; ox::memmove(dst, src, p.size() - dstPos); ox::memset(src, 0, m_insertCnt * sizeof(decltype(p[0]))); return {}; @@ -42,11 +41,11 @@ ox::Error InsertTilesCommand::redo() noexcept { ox::Error InsertTilesCommand::undo() noexcept { auto &s = getSubSheet(m_img, m_idx); auto &p = s.pixels; - const auto srcIdx = m_insertPos + m_insertCnt; - const auto src = p.data() + srcIdx; - const auto dst1 = p.data() + m_insertPos; - const auto dst2 = p.data() + p.size() - m_insertCnt; - const auto sz = p.size() - srcIdx; + auto const srcIdx = m_insertPos + m_insertCnt; + auto const src = &p[srcIdx]; + auto const dst1 = &p[m_insertPos]; + auto const dst2 = &p[p.size() - m_insertCnt]; + auto const sz = p.size() - srcIdx; ox::memmove(dst1, src, sz); ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size()); return {}; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index 740ea19..15811e7 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -120,7 +120,7 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept { } constexpr ox::StringView uuidPrefix = "uuid://"; if (ox::beginsWith(path, uuidPrefix)) { - auto uuid = ox::StringView(path.data() + uuidPrefix.bytes(), path.bytes() - uuidPrefix.bytes()); + auto uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes()); auto out = keelCtx(m_tctx).uuidToPath.at(uuid); if (out.error) { return {}; @@ -197,7 +197,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept { if (pt.x >= s.columns * TileWidth || pt.y >= s.rows * TileHeight) { return; } - getFillPixels(updateMap.data(), pt, oldColor); + getFillPixels(updateMap, pt, oldColor); ox::Vector idxList; auto i = core::idx(s, pt) / PixelsPerTile * PixelsPerTile; for (auto u : updateMap) { @@ -281,7 +281,7 @@ bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept { return m_selection && m_selection->contains(pt); } -void TileSheetEditorModel::getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept { +void TileSheetEditorModel::getFillPixels(ox::Span pixels, ox::Point const&pt, int oldColor) const noexcept { const auto &activeSubSheet = this->activeSubSheet(); const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept { return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp index b3b508c..fcceb58 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp @@ -128,7 +128,7 @@ class TileSheetEditorModel: public ox::SignalHandler { bool pixelSelected(std::size_t idx) const noexcept; private: - void getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept; + void getFillPixels(ox::Span pixels, ox::Point const&pt, int oldColor) const noexcept; void pushCommand(studio::UndoCommand *cmd) noexcept; diff --git a/src/nostalgia/modules/core/src/tilesheet.cpp b/src/nostalgia/modules/core/src/tilesheet.cpp index 99428aa..29ca442 100644 --- a/src/nostalgia/modules/core/src/tilesheet.cpp +++ b/src/nostalgia/modules/core/src/tilesheet.cpp @@ -163,8 +163,8 @@ unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept { ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept { ox::Vector out; oxReturnError(setPixelCount(out, pBpp, static_cast(sz.width * sz.height) * PixelsPerTile)); - auto const w = ss.columns * TileWidth; - auto const h = ss.rows * TileHeight; + auto const w = ox::min(ss.columns, sz.width) * TileWidth; + auto const h = ox::min(ss.rows, sz.height) * TileHeight; for (auto x = 0; x < w; ++x) { for (auto y = 0; y < h; ++y) { auto const palIdx = getPixel(ss, pBpp, {x, y}); diff --git a/src/nostalgia/modules/core/test/tests.cpp b/src/nostalgia/modules/core/test/tests.cpp index 0a8bbd5..48b2825 100644 --- a/src/nostalgia/modules/core/test/tests.cpp +++ b/src/nostalgia/modules/core/test/tests.cpp @@ -24,9 +24,10 @@ static std::map tests = { }, }; -int main(int argc, const char **args) { +int main(int argc, const char **argv) { int retval = -1; if (argc > 0) { + auto const args = ox::Span{argv, static_cast(argc)}; auto const testName = ox::StringView(args[1]); if (tests.find(testName) != tests.end()) { retval = static_cast(tests[testName]()); diff --git a/src/nostalgia/player/CMakeLists.txt b/src/nostalgia/player/CMakeLists.txt index 45412f4..d260957 100644 --- a/src/nostalgia/player/CMakeLists.txt +++ b/src/nostalgia/player/CMakeLists.txt @@ -1,7 +1,6 @@ add_executable( nostalgia WIN32 app.cpp - main.cpp ) # enable LTO @@ -23,6 +22,8 @@ endif() target_link_libraries( nostalgia NostalgiaKeelModules + NostalgiaProfile + OlympicApplib OxLogConn ) diff --git a/src/nostalgia/player/app.cpp b/src/nostalgia/player/app.cpp index 8c73f7f..4191b0a 100644 --- a/src/nostalgia/player/app.cpp +++ b/src/nostalgia/player/app.cpp @@ -65,8 +65,8 @@ static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool d [[maybe_unused]] static ox::Error runTest(turbine::Context &tctx) { - constexpr ox::FileAddress TileSheetAddr = ox::StringLiteral("/TileSheets/Charset.ng"); - constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Chester.npal"); + constexpr ox::StringView TileSheetAddr{"/TileSheets/Charset.ng"}; + constexpr ox::StringView PaletteAddr{"/Palettes/Chester.npal"}; oxRequireM(cctx, core::init(tctx)); turbine::setApplicationData(tctx, cctx.get()); oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); @@ -84,24 +84,24 @@ static ox::Error runTest(turbine::Context &tctx) { static ox::Error runTileSheetSetTest(turbine::Context &tctx) { // this should make the screen display 'ABCDB', with the A being upside down // and the first B being backwards - constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal"); + constexpr ox::StringView PaletteAddr{"/Palettes/Charset.npal"}; oxRequireM(cctx, core::init(tctx)); turbine::setApplicationData(tctx, cctx.get()); oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); core::TileSheetSet const set{ .bpp = 4, .entries = { - { .tilesheet = ox::StringLiteral("/TileSheets/Chester.ng"), .sections{{.begin = 0, .tiles = 1}} }, - { .tilesheet = ox::StringLiteral("/TileSheets/AB.ng"), .sections{{.begin = 0, .tiles = 2}} }, - { .tilesheet = ox::StringLiteral("/TileSheets/CD.ng"), .sections{{.begin = 0, .tiles = 2}} }, - { .tilesheet = ox::StringLiteral("/TileSheets/AB.ng"), .sections{{.begin = 1, .tiles = 1}} }, + { .tilesheet = ox::StringLiteral{"/TileSheets/Chester.ng"}, .sections{{.begin = 0, .tiles = 1}} }, + { .tilesheet = ox::StringLiteral{"/TileSheets/AB.ng"}, .sections{{.begin = 0, .tiles = 2}} }, + { .tilesheet = ox::StringLiteral{"/TileSheets/CD.ng"}, .sections{{.begin = 0, .tiles = 2}} }, + { .tilesheet = ox::StringLiteral{"/TileSheets/AB.ng"}, .sections{{.begin = 1, .tiles = 1}} }, }, }; constexpr auto bgPalBank = 1; oxReturnError(core::loadBgTileSheet(*cctx, 0, set)); oxReturnError(core::loadSpriteTileSheet(*cctx, set)); oxReturnError(core::loadBgPalette(*cctx, bgPalBank, PaletteAddr)); - oxReturnError(core::loadBgPalette(*cctx, 0, ox::StringLiteral("/Palettes/Chester.npal"))); + oxReturnError(core::loadBgPalette(*cctx, 0, PaletteAddr)); oxReturnError(core::loadSpritePalette(*cctx, PaletteAddr)); core::setBgStatus(*cctx, 0, true); core::setBgTile(*cctx, 0, 10, 9, { .tileIdx = 1, .palBank = bgPalBank, .flipX = 0, .flipY = 1 }); @@ -147,7 +147,7 @@ static void sceneKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool [[maybe_unused]] static ox::Error runScene(turbine::Context &tctx) { - constexpr ox::FileAddress SceneAddr = ox::StringLiteral("/Scenes/Chester.nscn"); + constexpr ox::StringView SceneAddr{"/Scenes/Chester.nscn"}; oxRequireM(cctx, core::init(tctx)); oxRequire(scn, keel::readObj(keelCtx(tctx), SceneAddr)); turbine::setUpdateHandler(tctx, sceneUpdateHandler); @@ -157,7 +157,20 @@ static ox::Error runScene(turbine::Context &tctx) { return turbine::run(tctx); } -ox::Error run(ox::UniquePtr &&fs) noexcept { - oxRequireM(tctx, turbine::init(std::move(fs), "Nostalgia")); +namespace olympic { + +ox::Error run( + [[maybe_unused]] ox::StringView project, + [[maybe_unused]] ox::StringView appName, + [[maybe_unused]] ox::StringView projectDataDir, + ox::SpanView args) noexcept { + if (args.size() < 2) { + return OxError(1, "Please provide path to project directory or OxFS file."); + } + auto const path = args[1]; + oxRequireM(fs, keel::loadRomFs(path)); + oxRequireM(tctx, turbine::init(std::move(fs), project)); return runTileSheetSetTest(*tctx); } + +} \ No newline at end of file diff --git a/src/nostalgia/player/main.cpp b/src/nostalgia/player/main.cpp deleted file mode 100644 index 8cba068..0000000 --- a/src/nostalgia/player/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. - */ - -#include -#include - -#include - -#include "../modules/keelmodules.hpp" - -#include "app.hpp" - -static ox::Error run(int argc, const char **argv) noexcept { -#ifndef OX_BARE_METAL - // GBA doesn't need the modules and calling this doubles the size of the - // binary. - nostalgia::registerKeelModules(); -#endif - if (argc < 2) { - return OxError(1, "Please provide path to project directory or OxFS file."); - } - const auto path = argv[1]; - oxRequireM(fs, keel::loadRomFs(path)); - return run(std::move(fs)); -} - -#ifdef _WIN32 -int WinMain() { - auto const argc = __argc; - auto const argv = const_cast(__argv); -#else -int main(int argc, const char **argv) { -#endif - OX_INIT_DEBUG_LOGGER(loggerConn, "Nostalgia Player") - ox::Error err; - err = run(argc, argv); - oxAssert(err, "Something went wrong..."); - if (err) { - oxErrf("Failure: {}\n", toStr(err)); - } - return static_cast(err); -} diff --git a/src/olympic/CMakeLists.txt b/src/olympic/CMakeLists.txt index 186fcd6..f054cda 100644 --- a/src/olympic/CMakeLists.txt +++ b/src/olympic/CMakeLists.txt @@ -1,3 +1,8 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # enable warnings + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") +endif() + if(BUILDCORE_TARGET STREQUAL "gba") project(Olympic ASM CXX) else() diff --git a/src/olympic/applib/applib.cpp b/src/olympic/applib/applib.cpp index ee6057e..28211d8 100644 --- a/src/olympic/applib/applib.cpp +++ b/src/olympic/applib/applib.cpp @@ -41,8 +41,7 @@ ox::Error run( ox::StringView project, ox::StringView appName, ox::StringView projectDataDir, - int argc, - char const**argv) noexcept; + ox::SpanView argv) noexcept; } @@ -65,7 +64,11 @@ int main(int argc, char const**argv) { #if OLYMPIC_LOAD_STUDIO_MODULES OLYMPIC_PROJECT_NAMESPACE::registerStudioModules(); #endif - auto const err = olympic::run(OLYMPIC_PROJECT_NAME, OLYMPIC_APP_NAME, OLYMPIC_PROJECT_DATADIR, argc, argv); + auto const err = olympic::run( + OLYMPIC_PROJECT_NAME, + OLYMPIC_APP_NAME, + OLYMPIC_PROJECT_DATADIR, + {argv, static_cast(argc)}); oxAssert(err, "Something went wrong..."); if (err) { oxErrf("Failure: {}\n", toStr(err)); diff --git a/src/olympic/keel/include/keel/asset.hpp b/src/olympic/keel/include/keel/asset.hpp index 6fbd558..7639a37 100644 --- a/src/olympic/keel/include/keel/asset.hpp +++ b/src/olympic/keel/include/keel/asset.hpp @@ -7,6 +7,8 @@ #include #include +#include "validation.hpp" + namespace keel { constexpr auto K1HdrSz = 40; @@ -26,7 +28,10 @@ ox::Result readAsset(ox::BufferView buff) noexcept { if (!err) { offset = K1HdrSz; // the size of K1 headers } - return ox::readClaw(buff + offset); + auto out = ox::readClaw(buff + offset); + oxReturnError(out); + oxReturnError(ensureValid(out.value)); + return out; } ox::Result readAsset(ox::TypeStore &ts, ox::BufferView buff) noexcept; diff --git a/src/olympic/keel/include/keel/assetmanager.hpp b/src/olympic/keel/include/keel/assetmanager.hpp index ca6e6cf..7180740 100644 --- a/src/olympic/keel/include/keel/assetmanager.hpp +++ b/src/olympic/keel/include/keel/assetmanager.hpp @@ -14,8 +14,6 @@ #include #include -#include "validation.hpp" - namespace keel { class AssetManager; @@ -190,7 +188,7 @@ class AssetManager { private: class AssetTypeManagerBase: public ox::SignalHandler { public: - virtual ~AssetTypeManagerBase() = default; + ~AssetTypeManagerBase() override = default; virtual void gc() noexcept = 0; }; @@ -217,7 +215,6 @@ class AssetManager { ox::Result> loadAsset(ox::StringView const assetId) noexcept { auto &p = m_cache[assetId]; oxRequireM(obj, m_loader(assetId)); - oxReturnError(ensureValid(obj)); if (!p) { p = ox::make_unique>(std::move(obj)); } else { diff --git a/src/olympic/keel/include/keel/media.hpp b/src/olympic/keel/include/keel/media.hpp index 728ee97..11a672f 100644 --- a/src/olympic/keel/include/keel/media.hpp +++ b/src/olympic/keel/include/keel/media.hpp @@ -63,10 +63,8 @@ namespace detail { template constexpr auto makeLoader(Context &ctx) { return [&ctx](ox::StringView assetId) -> ox::Result { - ox::StringView path; oxRequire(p, ctx.uuidToPath.at(assetId)); - path = *p; - oxRequire(buff, ctx.rom->read(path)); + oxRequire(buff, ctx.rom->read(*p)); auto [obj, err] = readAsset(buff); if (err) { if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) { @@ -84,21 +82,17 @@ ox::Result> readObjFile( keel::Context &ctx, ox::StringView assetId, bool forceLoad) noexcept { - ox::UUIDStr uuidStr; if (beginsWith(assetId, "uuid://")) { assetId = substr(assetId, 7); - oxRequire(p, keel::uuidToPath(ctx, assetId)); } else { auto const [uuid, uuidErr] = getUuid(ctx, assetId); if (!uuidErr) { - uuidStr = uuid.toString(); - assetId = uuidStr; + assetId = uuid.toString(); } } if (forceLoad) { ctx.assetManager.initTypeManager(detail::makeLoader, ctx); - oxRequire(cached, ctx.assetManager.loadAsset(assetId)); - return cached; + return ctx.assetManager.loadAsset(assetId); } else { auto [cached, err] = ctx.assetManager.getAsset(assetId); if (err) { diff --git a/src/olympic/keel/include/keel/typeconv.hpp b/src/olympic/keel/include/keel/typeconv.hpp index 94ac91e..5d72f35 100644 --- a/src/olympic/keel/include/keel/typeconv.hpp +++ b/src/olympic/keel/include/keel/typeconv.hpp @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include "asset.hpp" #include "context.hpp" @@ -119,7 +117,6 @@ class Converter: public BaseConverter { ox::Result> convertBuffToPtr( keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept final { oxRequireM(src, readAsset(srcBuff)); - oxReturnError(ensureValid(src)); auto dst = makeWrap(); oxReturnError(convert(ctx, src, wrapCast(*dst))); return {std::move(dst)}; diff --git a/src/olympic/keel/src/asset.cpp b/src/olympic/keel/src/asset.cpp index 338ce25..9817491 100644 --- a/src/olympic/keel/src/asset.cpp +++ b/src/olympic/keel/src/asset.cpp @@ -14,7 +14,7 @@ ox::Result readUuidHeader(ox::BufferView buff) noexcept { if (k1Hdr != ox::StringView(buff.data(), k1Hdr.bytes())) [[unlikely]] { return OxError(2, "No Keel asset header data"); } - return ox::UUID::fromString(ox::StringView(buff.data() + k1Hdr.bytes(), 36)); + return ox::UUID::fromString(ox::StringView(&buff[k1Hdr.bytes()], 36)); } ox::Result readAsset(ox::TypeStore &ts, ox::BufferView buff) noexcept { diff --git a/src/olympic/keel/src/module.cpp b/src/olympic/keel/src/module.cpp index 54462a8..5fd0012 100644 --- a/src/olympic/keel/src/module.cpp +++ b/src/olympic/keel/src/module.cpp @@ -9,7 +9,9 @@ namespace keel { static ox::Vector mods; void registerModule(Module const*mod) noexcept { - mods.emplace_back(mod); + if (mod) { + mods.emplace_back(mod); + } } [[nodiscard]] diff --git a/src/olympic/keel/src/pack-applib.cpp b/src/olympic/keel/src/pack-applib.cpp index 820a2a4..3f480f0 100644 --- a/src/olympic/keel/src/pack-applib.cpp +++ b/src/olympic/keel/src/pack-applib.cpp @@ -81,8 +81,8 @@ static ox::Error pack( return {}; } -static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir) noexcept { - ox::ClArgs const args(argc, argv); +static ox::Error run(ox::SpanView argv, ox::StringView projectDataDir) noexcept { + ox::ClArgs const args(argv); auto const argSrc = args.getString("src", ""); auto const argRomBin = args.getString("rom-bin", ""); auto const argManifest = args.getString("manifest", ""); @@ -103,9 +103,8 @@ ox::Error run( [[maybe_unused]] ox::StringView project, [[maybe_unused]] ox::StringView appName, ox::StringView projectDataDir, - int argc, - char const**argv) noexcept { - return ::run(argc, argv, projectDataDir); + ox::SpanView argv) noexcept { + return ::run(argv, projectDataDir); } } diff --git a/src/olympic/keel/src/pack.cpp b/src/olympic/keel/src/pack.cpp index 1f18eb6..3810f16 100644 --- a/src/olympic/keel/src/pack.cpp +++ b/src/olympic/keel/src/pack.cpp @@ -15,16 +15,22 @@ static ox::Error pathToInode( ox::FileSystem &dest, ox::ModelObject &obj) noexcept { auto &o = obj; - auto type = static_cast(o.at("type").unwrap()->get()); - auto &data = o.at("data").unwrap()->get(); + oxRequire(typeVal, o.at("type")); + auto const type = static_cast(typeVal->get()); + oxRequire(dataVal, o.at("data")); + auto &data = dataVal->get(); ox::String path; switch (type) { - case ox::FileAddressType::Path: - path = data.at("path").unwrap()->get(); + case ox::FileAddressType::Path: { + oxRequire(pathVal, data.at("path")); + path = pathVal->get(); break; - case ox::FileAddressType::ConstPath: - path = data.at("constPath").unwrap()->get(); + } + case ox::FileAddressType::ConstPath: { + oxRequire(pathVal, data.at("constPath")); + path = pathVal->get(); break; + } case ox::FileAddressType::Inode: case ox::FileAddressType::None: return {}; @@ -34,7 +40,7 @@ static ox::Error pathToInode( oxReturnError(keel::uuidToPath(ctx, uuid).to().moveTo(path)); } oxRequire(s, dest.stat(path)); - oxReturnError(o.at("type").unwrap()->set(static_cast(ox::FileAddressType::Inode))); + oxReturnError(typeVal->set(static_cast(ox::FileAddressType::Inode))); oxOutf("\tpath to inode: {} => {}\n", path, s.inode); return data.set(2, s.inode); } @@ -162,12 +168,12 @@ static ox::Error copy( // copy oxRequire(fileList, src.ls(path)); for (auto const&name : fileList) { - auto currentFile = ox::sfmt("{}{}", path, name); + auto const currentFile = ox::sfmt("{}{}", path, name); if (beginsWith(name, ".")) { continue; } - oxRequire(stat, src.stat(currentFile)); - if (stat.fileType == ox::FileType::Directory) { + oxRequire(srcStat, src.stat(currentFile)); + if (srcStat.fileType == ox::FileType::Directory) { oxReturnError(dest.mkdir(currentFile, true)); oxReturnError(copy(manifest, src, dest, currentFile + '/', childLogPrefix)); } else { @@ -181,9 +187,9 @@ static ox::Error copy( // write file to dest oxReturnError(dest.write(currentFile, buff)); status = "OK"; - oxRequire(stat, dest.stat(currentFile)); + oxRequire(dstStat, dest.stat(currentFile)); manifest.files[currentFile] = { - .inode = stat.inode, + .inode = dstStat.inode, .type = ox::String{keel::readAssetTypeId(buff).or_value({})}, }; } diff --git a/src/olympic/keel/src/typeconv.cpp b/src/olympic/keel/src/typeconv.cpp index 909ac10..c09bf89 100644 --- a/src/olympic/keel/src/typeconv.cpp +++ b/src/olympic/keel/src/typeconv.cpp @@ -2,8 +2,6 @@ * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. */ -#include - #include #include diff --git a/src/olympic/keel/test/tests.cpp b/src/olympic/keel/test/tests.cpp index 9dac6da..f6768a3 100644 --- a/src/olympic/keel/test/tests.cpp +++ b/src/olympic/keel/test/tests.cpp @@ -25,9 +25,10 @@ static std::map tests = { }, }; -int main(int argc, const char **args) { +int main(int argc, const char **argv) { int retval = -1; if (argc > 0) { + auto const args = ox::Span{argv, static_cast(argc)}; auto testName = args[1]; if (tests.find(testName) != tests.end()) { retval = static_cast(tests[testName]()); diff --git a/src/olympic/studio/applib/src/main.cpp b/src/olympic/studio/applib/src/main.cpp index e1cf5cf..b257450 100644 --- a/src/olympic/studio/applib/src/main.cpp +++ b/src/olympic/studio/applib/src/main.cpp @@ -52,8 +52,7 @@ static ox::Error runApp( static ox::Error run( ox::StringViewCR appName, ox::StringViewCR projectDataDir, - int, - char const**) { + ox::SpanView) { // seed UUID generator auto const time = std::time(nullptr); ox::UUID::seedGenerator({ @@ -74,9 +73,8 @@ ox::Error run( ox::StringView project, ox::StringView appName, ox::StringView projectDataDir, - int argc, - char const**argv) noexcept { - return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, argc, argv); + ox::SpanView args) noexcept { + return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, args); } } diff --git a/src/olympic/studio/applib/src/newmenu.cpp b/src/olympic/studio/applib/src/newmenu.cpp index 9148055..2b297f6 100644 --- a/src/olympic/studio/applib/src/newmenu.cpp +++ b/src/olympic/studio/applib/src/newmenu.cpp @@ -63,12 +63,14 @@ void NewMenu::addItemMaker(ox::UniquePtr &&im) noexcept { void NewMenu::drawNewItemType(studio::StudioContext &sctx) noexcept { drawWindow(sctx.tctx, &m_open, [this] { - auto items = ox_malloca(m_types.size() * sizeof(char const*), char const*, nullptr); + auto const allocSz = m_types.size() * sizeof(char const*); + auto mem = ox_malloca(allocSz, char const*, nullptr); + auto items = ox::Span{mem.get(), allocSz}; for (auto i = 0u; auto const&im : m_types) { - items.get()[i] = im->typeName.c_str(); + items[i] = im->typeName.c_str(); ++i; } - ImGui::ListBox("Item Type", &m_selectedType, items.get(), static_cast(m_types.size())); + ImGui::ListBox("Item Type", &m_selectedType, items.data(), static_cast(m_types.size())); drawFirstPageButtons(); }); } @@ -116,11 +118,12 @@ void NewMenu::drawLastPageButtons(studio::StudioContext &sctx) noexcept { void NewMenu::finish(studio::StudioContext &sctx) noexcept { if (m_itemName.len() == 0) { + oxLogError(OxError(1, "New file error: no file name")); return; } auto const&typeMaker = *m_types[static_cast(m_selectedType)]; if (sctx.project->exists(typeMaker.itemPath(m_itemName))) { - oxLogError(OxError(1, "New file error: File already exists")); + oxLogError(OxError(1, "New file error: file already exists")); return; } auto const [path, err] = typeMaker.write(sctx, m_itemName); diff --git a/src/olympic/studio/applib/src/studioapp.cpp b/src/olympic/studio/applib/src/studioapp.cpp index 2dfada0..001d054 100644 --- a/src/olympic/studio/applib/src/studioapp.cpp +++ b/src/olympic/studio/applib/src/studioapp.cpp @@ -21,7 +21,9 @@ namespace studio { static ox::Vector modules; void registerModule(studio::Module const*mod) noexcept { - modules.emplace_back(mod); + if (mod) { + modules.emplace_back(mod); + } } @@ -238,18 +240,18 @@ void StudioUI::loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept { } } -void StudioUI::loadModule(studio::Module const*mod) noexcept { - for (auto const&editorMaker : mod->editors(m_sctx)) { +void StudioUI::loadModule(studio::Module const&mod) noexcept { + for (auto const&editorMaker : mod.editors(m_sctx)) { loadEditorMaker(editorMaker); } - for (auto &im : mod->itemMakers(m_sctx)) { + for (auto &im : mod.itemMakers(m_sctx)) { m_newMenu.addItemMaker(std::move(im)); } } void StudioUI::loadModules() noexcept { for (auto const mod : modules) { - loadModule(mod); + loadModule(*mod); } } diff --git a/src/olympic/studio/applib/src/studioapp.hpp b/src/olympic/studio/applib/src/studioapp.hpp index efd374c..b0534d7 100644 --- a/src/olympic/studio/applib/src/studioapp.hpp +++ b/src/olympic/studio/applib/src/studioapp.hpp @@ -69,7 +69,7 @@ class StudioUI: public ox::SignalHandler { void loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept; - void loadModule(studio::Module const*mod) noexcept; + void loadModule(studio::Module const&mod) noexcept; void loadModules() noexcept; diff --git a/src/olympic/studio/modlib/include/studio/filedialog.hpp b/src/olympic/studio/modlib/include/studio/filedialog.hpp index e8415f0..f79b568 100644 --- a/src/olympic/studio/modlib/include/studio/filedialog.hpp +++ b/src/olympic/studio/modlib/include/studio/filedialog.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include namespace studio { @@ -24,4 +25,4 @@ ox::Result saveFile(ox::Vector const&exts) noexcept; ox::Result chooseDirectory() noexcept; -} \ No newline at end of file +} diff --git a/src/olympic/studio/modlib/include/studio/imguiutil.hpp b/src/olympic/studio/modlib/include/studio/imguiutil.hpp index cc343bf..0577269 100644 --- a/src/olympic/studio/modlib/include/studio/imguiutil.hpp +++ b/src/olympic/studio/modlib/include/studio/imguiutil.hpp @@ -189,7 +189,7 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im * @param selectedIdx * @return true if new value selected, false otherwise */ -bool ComboBox(ox::CStringView lbl, ox::SpanView list, size_t &selectedIdx) noexcept; +bool ComboBox(ox::CStringView lbl, ox::Span list, size_t &selectedIdx) noexcept; /** * @@ -223,7 +223,7 @@ bool ListBox( * @param selIdx * @return true if new value selected, false otherwise */ -bool ListBox(ox::CStringView name, ox::SpanView const&list, size_t &selIdx) noexcept; +bool ListBox(ox::CStringView name, ox::Span const&list, size_t &selIdx) noexcept; class FilePicker { private: diff --git a/src/olympic/studio/modlib/src/filedialog_nfd.cpp b/src/olympic/studio/modlib/src/filedialog_nfd.cpp index 9420f31..4bf1163 100644 --- a/src/olympic/studio/modlib/src/filedialog_nfd.cpp +++ b/src/olympic/studio/modlib/src/filedialog_nfd.cpp @@ -22,10 +22,12 @@ static ox::Result toResult(nfdresult_t r, NFD::UniquePathN const&pat switch (r) { case NFD_OKAY: { ox::String out; +OX_ALLOW_UNSAFE_BUFFERS_BEGIN for (auto i = 0u; path.get()[i]; ++i) { auto const c = static_cast(path.get()[i]); std::ignore = out.append(&c, 1); } +OX_ALLOW_UNSAFE_BUFFERS_END return out; } case NFD_CANCEL: @@ -35,11 +37,11 @@ static ox::Result toResult(nfdresult_t r, NFD::UniquePathN const&pat } } -ox::Result saveFile(ox::Vector const&filters) noexcept { +ox::Result saveFile(ox::Vector const&exts) noexcept { NFD::Guard const guard; NFD::UniquePathN path; - ox::Vector filterItems(filters.size()); - for (auto i = 0u; auto const&f : filters) { + ox::Vector filterItems(exts.size()); + for (auto i = 0u; auto const&f : exts) { filterItems[i].name = f.name.data(); filterItems[i].spec = f.spec.data(); ++i; diff --git a/src/olympic/studio/modlib/src/imguiutil.cpp b/src/olympic/studio/modlib/src/imguiutil.cpp index 72c9898..7650550 100644 --- a/src/olympic/studio/modlib/src/imguiutil.cpp +++ b/src/olympic/studio/modlib/src/imguiutil.cpp @@ -87,7 +87,7 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im bool ComboBox( ox::CStringView lbl, - ox::SpanView list, + ox::Span list, size_t &selectedIdx) noexcept { bool out{}; auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : ""; @@ -155,7 +155,7 @@ bool ListBox( return out; } -bool ListBox(ox::CStringView name, ox::SpanView const&list, size_t &selIdx) noexcept { +bool ListBox(ox::CStringView name, ox::Span const&list, size_t &selIdx) noexcept { return ListBox(name, [list](size_t i) -> ox::CStringView { return list[i]; }, list.size(), selIdx); diff --git a/src/olympic/turbine/src/gba/turbine.cpp b/src/olympic/turbine/src/gba/turbine.cpp index 9840912..873ecc7 100644 --- a/src/olympic/turbine/src/gba/turbine.cpp +++ b/src/olympic/turbine/src/gba/turbine.cpp @@ -47,12 +47,14 @@ static ox::Result findPreloadSection() noexcept { constexpr auto headerP1Len = ox::strlen(headerP2); constexpr auto headerP2Len = ox::strlen(headerP1); constexpr auto headerLen = headerP1Len + headerP2Len; +OX_ALLOW_UNSAFE_BUFFERS_BEGIN for (auto current = MEM_ROM; current < reinterpret_cast(0x0a000000); current += headerLen) { if (memcmp(current, headerP1, headerP1Len) == 0 && memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) { return reinterpret_cast(current + headerLen); } } +OX_ALLOW_UNSAFE_BUFFERS_END return OxError(1); } diff --git a/src/olympic/turbine/src/glfw/gfx.cpp b/src/olympic/turbine/src/glfw/gfx.cpp index 7507b5e..0b34516 100644 --- a/src/olympic/turbine/src/glfw/gfx.cpp +++ b/src/olympic/turbine/src/glfw/gfx.cpp @@ -9,6 +9,8 @@ #include #endif +#include + #include "context.hpp" namespace turbine { @@ -128,60 +130,61 @@ static void themeImgui() noexcept { static_cast(b), static_cast(a)); }; - style.Colors[ImGuiCol_Text] = imVec4(0.9490196108818054, 0.95686274766922, 0.9764705896377563, 1.0); - style.Colors[ImGuiCol_TextDisabled] = imVec4(0.3568627536296844, 0.4196078479290009, 0.4666666686534882, 1.0); - style.Colors[ImGuiCol_WindowBg] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - style.Colors[ImGuiCol_ChildBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); - style.Colors[ImGuiCol_PopupBg] = imVec4(0.0784313753247261, 0.0784313753247261, 0.0784313753247261, 0.9399999976158142); - style.Colors[ImGuiCol_Border] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); - style.Colors[ImGuiCol_BorderShadow] = imVec4(0.0, 0.0, 0.0, 0.0); - style.Colors[ImGuiCol_FrameBg] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - style.Colors[ImGuiCol_FrameBgHovered] = imVec4(0.1176470592617989, 0.2000000029802322, 0.2784313857555389, 1.0); - style.Colors[ImGuiCol_FrameBgActive] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 1.0); - style.Colors[ImGuiCol_TitleBg] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 0.6499999761581421); - style.Colors[ImGuiCol_TitleBgActive] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); - style.Colors[ImGuiCol_TitleBgCollapsed] = imVec4(0.0, 0.0, 0.0, 0.5099999904632568); - style.Colors[ImGuiCol_MenuBarBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); - style.Colors[ImGuiCol_ScrollbarBg] = imVec4(0.01960784383118153, 0.01960784383118153, 0.01960784383118153, 0.3899999856948853); - style.Colors[ImGuiCol_ScrollbarGrab] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - style.Colors[ImGuiCol_ScrollbarGrabHovered] = imVec4(0.1764705926179886, 0.2196078449487686, 0.2470588237047195, 1.0); - style.Colors[ImGuiCol_ScrollbarGrabActive] = imVec4(0.08627451211214066, 0.2078431397676468, 0.3098039329051971, 1.0); - style.Colors[ImGuiCol_CheckMark] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - style.Colors[ImGuiCol_SliderGrab] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - style.Colors[ImGuiCol_SliderGrabActive] = imVec4(0.3686274588108063, 0.6078431606292725, 1.0, 1.0); - style.Colors[ImGuiCol_Button] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - style.Colors[ImGuiCol_ButtonHovered] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); - style.Colors[ImGuiCol_ButtonActive] = imVec4(0.05882352963089943, 0.529411792755127, 0.9764705896377563, 1.0); + auto colors = ox::Span(style.Colors); + colors[ImGuiCol_Text] = imVec4(0.9490196108818054, 0.95686274766922, 0.9764705896377563, 1.0); + colors[ImGuiCol_TextDisabled] = imVec4(0.3568627536296844, 0.4196078479290009, 0.4666666686534882, 1.0); + colors[ImGuiCol_WindowBg] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_ChildBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); + colors[ImGuiCol_PopupBg] = imVec4(0.0784313753247261, 0.0784313753247261, 0.0784313753247261, 0.9399999976158142); + colors[ImGuiCol_Border] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); + colors[ImGuiCol_BorderShadow] = imVec4(0.0, 0.0, 0.0, 0.0); + colors[ImGuiCol_FrameBg] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_FrameBgHovered] = imVec4(0.1176470592617989, 0.2000000029802322, 0.2784313857555389, 1.0); + colors[ImGuiCol_FrameBgActive] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 1.0); + colors[ImGuiCol_TitleBg] = imVec4(0.08627451211214066, 0.1176470592617989, 0.1372549086809158, 0.6499999761581421); + colors[ImGuiCol_TitleBgActive] = imVec4(0.0784313753247261, 0.09803921729326248, 0.1176470592617989, 1.0); + colors[ImGuiCol_TitleBgCollapsed] = imVec4(0.0, 0.0, 0.0, 0.5099999904632568); + colors[ImGuiCol_MenuBarBg] = imVec4(0.1490196138620377, 0.1764705926179886, 0.2196078449487686, 1.0); + colors[ImGuiCol_ScrollbarBg] = imVec4(0.01960784383118153, 0.01960784383118153, 0.01960784383118153, 0.3899999856948853); + colors[ImGuiCol_ScrollbarGrab] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_ScrollbarGrabHovered] = imVec4(0.1764705926179886, 0.2196078449487686, 0.2470588237047195, 1.0); + colors[ImGuiCol_ScrollbarGrabActive] = imVec4(0.08627451211214066, 0.2078431397676468, 0.3098039329051971, 1.0); + colors[ImGuiCol_CheckMark] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_SliderGrab] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_SliderGrabActive] = imVec4(0.3686274588108063, 0.6078431606292725, 1.0, 1.0); + colors[ImGuiCol_Button] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_ButtonHovered] = imVec4(0.2784313857555389, 0.5568627715110779, 1.0, 1.0); + colors[ImGuiCol_ButtonActive] = imVec4(0.05882352963089943, 0.529411792755127, 0.9764705896377563, 1.0); // custom value - style.Colors[ImGuiCol_Header] = imVec4(0.4000000029802322, 0.4470588237047195, 0.4862745225429535, 0.550000011920929); - style.Colors[ImGuiCol_HeaderHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); - style.Colors[ImGuiCol_HeaderActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); - style.Colors[ImGuiCol_Separator] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - style.Colors[ImGuiCol_SeparatorHovered] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 0.7799999713897705); - style.Colors[ImGuiCol_SeparatorActive] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 1.0); - style.Colors[ImGuiCol_ResizeGrip] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.25); - style.Colors[ImGuiCol_ResizeGripHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.6700000166893005); - style.Colors[ImGuiCol_ResizeGripActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.949999988079071); - style.Colors[ImGuiCol_Tab] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - style.Colors[ImGuiCol_TabHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); - style.Colors[ImGuiCol_TabActive] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); - style.Colors[ImGuiCol_TabUnfocused] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - style.Colors[ImGuiCol_TabUnfocusedActive] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); - style.Colors[ImGuiCol_PlotLines] = imVec4(0.6078431606292725, 0.6078431606292725, 0.6078431606292725, 1.0); - style.Colors[ImGuiCol_PlotLinesHovered] = imVec4(1.0, 0.4274509847164154, 0.3490196168422699, 1.0); - style.Colors[ImGuiCol_PlotHistogram] = imVec4(0.8980392217636108, 0.6980392336845398, 0.0, 1.0); - style.Colors[ImGuiCol_PlotHistogramHovered] = imVec4(1.0, 0.6000000238418579, 0.0, 1.0); - style.Colors[ImGuiCol_TableHeaderBg] = imVec4(0.1882352977991104, 0.1882352977991104, 0.2000000029802322, 1.0); - style.Colors[ImGuiCol_TableBorderStrong] = imVec4(0.3098039329051971, 0.3098039329051971, 0.3490196168422699, 1.0); - style.Colors[ImGuiCol_TableBorderLight] = imVec4(0.2274509817361832, 0.2274509817361832, 0.2470588237047195, 1.0); - style.Colors[ImGuiCol_TableRowBg] = imVec4(0.0, 0.0, 0.0, 0.0); - style.Colors[ImGuiCol_TableRowBgAlt] = imVec4(1.0, 1.0, 1.0, 0.05999999865889549); - style.Colors[ImGuiCol_TextSelectedBg] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.3499999940395355); - style.Colors[ImGuiCol_DragDropTarget] = imVec4(1.0, 1.0, 0.0, 0.8999999761581421); - style.Colors[ImGuiCol_NavHighlight] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); - style.Colors[ImGuiCol_NavWindowingHighlight] = imVec4(1.0, 1.0, 1.0, 0.699999988079071); - style.Colors[ImGuiCol_NavWindowingDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.2000000029802322); - style.Colors[ImGuiCol_ModalWindowDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.3499999940395355); + colors[ImGuiCol_Header] = imVec4(0.4000000029802322, 0.4470588237047195, 0.4862745225429535, 0.550000011920929); + colors[ImGuiCol_HeaderHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); + colors[ImGuiCol_HeaderActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); + colors[ImGuiCol_Separator] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_SeparatorHovered] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 0.7799999713897705); + colors[ImGuiCol_SeparatorActive] = imVec4(0.09803921729326248, 0.4000000059604645, 0.7490196228027344, 1.0); + colors[ImGuiCol_ResizeGrip] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.25); + colors[ImGuiCol_ResizeGripHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.6700000166893005); + colors[ImGuiCol_ResizeGripActive] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.949999988079071); + colors[ImGuiCol_Tab] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_TabHovered] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.800000011920929); + colors[ImGuiCol_TabActive] = imVec4(0.2000000029802322, 0.2470588237047195, 0.2862745225429535, 1.0); + colors[ImGuiCol_TabUnfocused] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_TabUnfocusedActive] = imVec4(0.1098039224743843, 0.1490196138620377, 0.168627455830574, 1.0); + colors[ImGuiCol_PlotLines] = imVec4(0.6078431606292725, 0.6078431606292725, 0.6078431606292725, 1.0); + colors[ImGuiCol_PlotLinesHovered] = imVec4(1.0, 0.4274509847164154, 0.3490196168422699, 1.0); + colors[ImGuiCol_PlotHistogram] = imVec4(0.8980392217636108, 0.6980392336845398, 0.0, 1.0); + colors[ImGuiCol_PlotHistogramHovered] = imVec4(1.0, 0.6000000238418579, 0.0, 1.0); + colors[ImGuiCol_TableHeaderBg] = imVec4(0.1882352977991104, 0.1882352977991104, 0.2000000029802322, 1.0); + colors[ImGuiCol_TableBorderStrong] = imVec4(0.3098039329051971, 0.3098039329051971, 0.3490196168422699, 1.0); + colors[ImGuiCol_TableBorderLight] = imVec4(0.2274509817361832, 0.2274509817361832, 0.2470588237047195, 1.0); + colors[ImGuiCol_TableRowBg] = imVec4(0.0, 0.0, 0.0, 0.0); + colors[ImGuiCol_TableRowBgAlt] = imVec4(1.0, 1.0, 1.0, 0.05999999865889549); + colors[ImGuiCol_TextSelectedBg] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 0.3499999940395355); + colors[ImGuiCol_DragDropTarget] = imVec4(1.0, 1.0, 0.0, 0.8999999761581421); + colors[ImGuiCol_NavHighlight] = imVec4(0.2588235437870026, 0.5882353186607361, 0.9764705896377563, 1.0); + colors[ImGuiCol_NavWindowingHighlight] = imVec4(1.0, 1.0, 1.0, 0.699999988079071); + colors[ImGuiCol_NavWindowingDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.2000000029802322); + colors[ImGuiCol_ModalWindowDimBg] = imVec4(0.800000011920929, 0.800000011920929, 0.800000011920929, 0.3499999940395355); } #endif