Compare commits

...

87 Commits

Author SHA1 Message Date
gary d10a71f06d [studio] Add missing include
Build / build (push) Failing after 1m6s
2026-05-17 15:36:57 -05:00
gary 9593e7eef9 [ox] Add writeOC Writer_c variant 2026-05-17 15:31:56 -05:00
gary 2f9b9c0842 [studio] Fix change-format to only write data portion once
Build / build (push) Successful in 1m15s
2026-05-17 15:22:11 -05:00
gary dce09b564c [ox/std] Fix Result::originate to return value
Build / build (push) Successful in 1m12s
2026-05-17 15:19:13 -05:00
gary 9f485d9496 [studio] Cleanup
Build / build (push) Successful in 1m9s
2026-05-17 15:07:10 -05:00
gary 2c50ce48ed [ox/std] Add Result::reoriginate functions 2026-05-17 15:02:07 -05:00
gary 72e16cb285 [studio] Change output of Claw OC files to make them recognizable as test files 2026-05-17 14:53:42 -05:00
gary d1e410ac55 [ox/std] Add caseInsensitiveEquals 2026-05-17 14:30:43 -05:00
gary be32d575f5 [ox/claw] Add writeClaw Writer_c variant 2026-05-17 14:29:43 -05:00
gary f24929f421 [studio] Remove extra copyright header
Build / build (push) Successful in 1m16s
2026-05-16 16:44:13 -05:00
gary 2d426d2bb3 [studio] Fix change-format format reading
Build / build (push) Successful in 1m13s
2026-05-16 16:29:19 -05:00
gary f89af6fcb3 [studio] Fix change-format usage message
Build / build (push) Successful in 1m12s
2026-05-16 16:17:00 -05:00
gary 899eaa9dce [studio] Add change-format subcommand
Build / build (push) Successful in 1m13s
2026-05-16 16:12:29 -05:00
gary d32b1033c3 [nostalgia/gfx/studio] Cleanup 2026-05-16 14:11:20 -05:00
gary 1d2814bbd0 Merge commit '2e119b5683574d7243d30a9ba33c05b06bcdb8a4'
Build / build (push) Successful in 1m15s
2026-05-08 22:36:42 -05:00
gary 2e119b5683 Squashed 'deps/oxlib/' changes from 170d6e35a..a787fef61
a787fef61 Uncomment code that from Pico fix
298184d58 Fix build warning
51999199c [ox] Fix build problems on Raspberry Pi Pico
682fc5b85 Merge commit 'c286e3794d9d4cc571671548ad765ce370bcfcb4'
94209fd74 [ox/std] Make is_integral use raw types

git-subtree-dir: deps/oxlib
git-subtree-split: a787fef6147dcd11519c24f992289349f0ec355d
2026-05-08 22:36:42 -05:00
gary 46c6ba2e17 Merge commit 'c286e3794d9d4cc571671548ad765ce370bcfcb4' 2026-05-07 01:18:59 -05:00
gary c286e3794d Squashed 'deps/oxlib/' changes from 85f17c418..170d6e35a
170d6e35a [ox] Add dist to gitignore
83fd814d6 [ox] Bump required CMake version

git-subtree-dir: deps/oxlib
git-subtree-split: 170d6e35a67739b600aa95abfff7269972a45c00
2026-05-07 01:18:59 -05:00
gary 45cbede7e2 [ox/std] Make is_integral use raw types 2026-05-07 01:16:57 -05:00
gary 5aa133a788 [nostalgia] Fix Ox references
Build / build (push) Successful in 1m9s
2026-05-06 02:48:59 -05:00
gary fafe78ba80 [nostalgia] Adjust for new ox path
Build / build (push) Successful in 1m9s
2026-05-06 01:40:34 -05:00
gary 69fcd7ad10 Squashed 'deps/oxlib/' content from commit 85f17c41
git-subtree-dir: deps/oxlib
git-subtree-split: 85f17c4188e266b82ba8858d21f67289c72e7b9a
2026-05-06 01:38:00 -05:00
gary 335a61bd79 Merge commit '69fcd7ad1056940166a5d9524b4f03578f680834' as 'deps/oxlib' 2026-05-06 01:38:00 -05:00
gary 572b8b2c78 [ox] Remove Ox 2026-05-06 01:15:07 -05:00
gary 88e901e214 [keel] Cleanup
Build / build (push) Successful in 1m9s
2026-04-29 01:55:32 -05:00
gary d42e10fcbe [olympic] Cleanup pkg-gba 2026-04-29 01:52:59 -05:00
gary bc88333a59 [studio/modlib] Update ImGui drag/drop, other cleanup 2026-04-29 01:50:39 -05:00
gary 4048753205 [ox/std] Add call and logCatch for safe calling of throwing functions 2026-04-29 01:47:15 -05:00
gary 5c146c6660 [ox/std] Add call and logCatch for safe calling of throwing functions 2026-04-29 01:45:56 -05:00
gary 0885919dbd [ox/std] Cleanup 2026-04-29 01:44:43 -05:00
gary 8c7d8cd08b [ox/model] Cleanup TypeNameCatcher and TypeInfoCatcher 2026-04-29 01:42:53 -05:00
gary 110d4a2e6a [keel] Cleanup
Build / build (push) Successful in 1m16s
2026-02-07 15:29:53 -06:00
gary e29a50d0dc [ox] Rename UniquePtr to UPtr 2026-02-07 14:17:55 -06:00
gary 93d16cafb2 [ox/std] Add Error::throwException() 2026-02-07 14:15:15 -06:00
gary 54d7c706eb [studio] Make FileInfo free resources on close
Build / build (push) Successful in 1m15s
2026-02-06 21:36:39 -06:00
gary c9cb186462 [studio] Cleanup useless complexity
Build / build (push) Successful in 1m16s
2026-02-06 21:28:46 -06:00
gary f204d01a3d [studio] FileInfo: reset file info when opening
Build / build (push) Successful in 1m12s
2026-02-05 22:22:07 -06:00
gary 62337bd29e [studio] FileInfo: Rename ID to Asset ID, allow for no value of fields
Build / build (push) Successful in 1m12s
2026-02-05 22:15:00 -06:00
gary 7b24b33849 [nostalgia] Update release notes
Build / build (push) Successful in 1m11s
2026-02-05 21:40:10 -06:00
gary 86c2c26d8d [studio] Fix warning
Build / build (push) Successful in 1m11s
2026-02-05 21:35:39 -06:00
gary f8b2700ea7 [studio] Add Get Info file dialog
Build / build (push) Failing after 1m9s
2026-02-05 21:32:36 -06:00
gary 7848cbbbff [nostalgia/gfx/keel] Cleanup
Build / build (push) Successful in 1m9s
2026-02-03 02:22:58 -06:00
gary 96c5223e44 [ox/std] Fix possible false positive in HashMap::operator==
Build / build (push) Successful in 1m13s
2026-01-30 21:03:58 -06:00
gary d19b848427 [ox/std] Reduce AnyPtr to 2/3 the size
Build / build (push) Successful in 1m13s
2026-01-30 20:54:17 -06:00
gary c812051ec0 [nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 1m11s
2026-01-30 00:31:19 -06:00
gary 3c07eb2df7 [nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 1m7s
2026-01-29 19:30:32 -06:00
gary ca851e1059 [ox] Cleanup some expensive headers
Build / build (push) Successful in 1m7s
2026-01-28 22:55:26 -06:00
gary 11e75cb6ca [ox/std] Add Error::reoriginate
Build / build (push) Successful in 1m13s
2026-01-28 00:46:55 -06:00
gary 8c4add57e4 [ox/std] Fix build
Build / build (push) Successful in 1m17s
2026-01-28 00:45:26 -06:00
gary 5e1698a321 [ox/std] Cleanup serialize code
Build / build (push) Failing after 52s
2026-01-27 23:15:53 -06:00
gary 3e95bc0842 [ox/model] Update style for ModelHandlerAdaptor 2026-01-27 23:09:53 -06:00
gary 58e19fad48 [ox] Cleanup MetalClawWriter and FieldBitmapWriter 2026-01-27 23:05:03 -06:00
gary a3a56b24e8 [ox/std] Fix is_integer_v 2026-01-27 23:03:07 -06:00
gary 7681830ca6 [ox] Remove some unnecessary const_casts 2026-01-27 23:01:36 -06:00
gary 46a7331754 [ox/mc] Cleanup, fix possible overflow bug
Build / build (push) Successful in 1m8s
2026-01-26 00:55:55 -06:00
gary 56c19ad2a6 [ox/std] Add remove_pointer_t alias 2026-01-26 00:46:12 -06:00
gary c6ecadf9a8 [ox/mc] Cleanup
Build / build (push) Successful in 1m10s
2026-01-26 00:21:16 -06:00
gary 2ed469f2dd [ox] Cleanup
Build / build (push) Successful in 1m11s
2026-01-25 23:58:46 -06:00
gary 53aea9731d [ox] Cleanup
Build / build (push) Successful in 1m9s
2026-01-25 23:46:54 -06:00
gary 0e028ff653 [ox] Cleanup
Build / build (push) Successful in 1m10s
2026-01-25 22:05:49 -06:00
gary 07688a2c29 [ox] Remove oxExpect macro
Build / build (push) Successful in 1m9s
2026-01-25 21:52:26 -06:00
gary 9ce4d3f8c7 [keel,nostalgia/gfx] Minor cleanup of tests 2026-01-25 21:51:10 -06:00
gary 4aa8255c55 [ox] Update formatting in recently edited files
Build / build (push) Successful in 1m11s
2026-01-25 21:26:44 -06:00
gary bfdfc10425 [nostalgia/gfx] Update panic
Build / build (push) Successful in 1m11s
2026-01-25 21:11:54 -06:00
gary cdd574d873 [ox] Change panic and assert to use std::source_location 2026-01-25 21:11:22 -06:00
gary bc05bd12e5 [ox/model] Rename and fix isBString helpers
Build / build (push) Successful in 1m8s
2026-01-25 02:06:14 -06:00
gary b754c66cf5 [ox] Remove enable_if
Build / build (push) Successful in 1m8s
2026-01-23 01:38:53 -06:00
gary 6a42303239 [ox/std] Slight optimization 2026-01-23 01:38:31 -06:00
gary 7477ede222 [ox/std] Cleanup some enable_ifs
Build / build (push) Successful in 1m7s
2026-01-21 23:35:19 -06:00
gary 65e3153dda [ox/std] Add Union_c concept 2026-01-21 23:35:02 -06:00
gary 53a224cf8f [ox/std] Cleanup 2026-01-21 23:34:36 -06:00
gary 592e641ba9 [ox/std] Fix writeItoa to work with max length 64 bit ints
Build / build (push) Successful in 1m8s
2026-01-21 23:28:13 -06:00
gary 689da4a019 [ox] Update docs
Build / build (push) Successful in 1m10s
2026-01-21 21:04:17 -06:00
gary bdf7755ee2 [nostalgia/developer-handbook] Update developer handbook 2026-01-21 21:03:47 -06:00
gary 63f627377d [ox/std] Remove excess char from intToStr return
Build / build (push) Successful in 1m9s
2026-01-20 01:29:37 -06:00
gary ff9002ad9a [nostalgia/developer-handbook] Update error handling section
Build / build (push) Successful in 1m8s
2026-01-20 01:22:05 -06:00
gary 4d0da022cf [ox] Update error handling docs
Build / build (push) Successful in 1m8s
2026-01-20 00:47:51 -06:00
gary 02332d99b5 [ox] Fix issues in String Types section of docs
Build / build (push) Successful in 1m8s
2026-01-20 00:26:38 -06:00
gary a566ed2a8b [ox/std] Fix writeItoa to work with negatives
Build / build (push) Successful in 1m9s
2026-01-19 23:00:16 -06:00
gary 815c3d19bf [ox/std] Make StringLiteral constructors non-explicit
Build / build (push) Successful in 1m8s
2026-01-19 21:00:58 -06:00
gary 522bb14f18 [ox/std] Fix intToStr to have room for negatives 2026-01-19 21:00:12 -06:00
gary f40d5515f9 [ox] Add strings section to docs
Build / build (push) Successful in 1m11s
2026-01-18 19:00:24 -06:00
gary 941d1d90dc [ox/std] Add Vector::reserveResize
Build / build (push) Successful in 1m15s
2026-01-07 21:48:04 -06:00
gary 3e880dcdcc [nostalgia/gfx/studio] Remove unused EBO management
Build / build (push) Successful in 1m16s
2026-01-07 21:33:16 -06:00
gary 03328ac10f [turbine/glfw] Fix to handle null click handler
Build / build (push) Successful in 1m9s
2025-12-03 20:44:01 -06:00
gary 63d0abaa3c [nostalgia/gfx/gba] Remove teagba scroll bg function call
Build / build (push) Successful in 1m15s
2025-11-22 23:53:18 -06:00
gary ef2a8cda77 [teagba] Remove bg scroll, cleanup 2025-11-22 23:53:04 -06:00
517 changed files with 3529 additions and 2993 deletions
+2 -5
View File
@@ -9,7 +9,7 @@ else()
project(nostalgia C CXX)
endif()
include(deps/buildcore/base.cmake)
include(deps/oxlib/deps/buildcore/base.cmake)
set(OX_ENABLE_TRACEHOOK OFF CACHE BOOL "Generate OxTraceHook shared library for uprobes")
@@ -35,10 +35,7 @@ else()
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif()
add_subdirectory(deps/ox)
include_directories(
deps/ox/src
)
add_subdirectory(deps/oxlib)
add_subdirectory(deps/teagba)
if(NOT BUILDCORE_TARGET STREQUAL "gba")
+14 -1
View File
@@ -1,7 +1,7 @@
BC_VAR_PROJECT_NAME=nostalgia
BC_VAR_PROJECT_NAME_CAP=Nostalgia
BC_VAR_DEVENV_ROOT=util
BUILDCORE_PATH=deps/buildcore
BUILDCORE_PATH=deps/oxlib/deps/buildcore
include ${BUILDCORE_PATH}/base.mk
ifeq ($(BC_VAR_OS),darwin)
@@ -13,6 +13,19 @@ else
endif
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
.PHONY: git-setup-ox-remote
git-setup-ox-remote:
git remote add -f ox-master git@git.drinkingtea.net:drinkingtea/ox.git
.PHONY: git-pull-ox
git-pull-ox:
git fetch ox-master master
git subtree pull --prefix deps/oxlib ox-master master --squash
.PHONY: git-push-ox
git-push-ox:
git subtree push --prefix=deps/oxlib ox-master master
.PHONY: pkg-gba
pkg-gba: build-pack build-gba-player
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
-12
View File
@@ -1,12 +0,0 @@
{
"log_functions": [
{
"function": "ox::trace::gdblogger::captureLogFunc",
"ignore_frames": 3,
"file_var": "file",
"line_var": "line",
"channel_var": "ch",
"msg_var": "msg"
}
]
}
-11
View File
@@ -1,11 +0,0 @@
language: cpp
sudo: false
dist: trusty
compiler:
- clang
- gcc
addons:
apt:
packages:
- cmake
script: ./scripts/cibuild
-68
View File
@@ -1,68 +0,0 @@
OS=$(shell uname | tr [:upper:] [:lower:])
HOST_ENV=${OS}-$(shell uname -m)
DEVENV=devenv$(shell pwd | sed 's/\//-/g')
DEVENV_IMAGE=wombatant/devenv
ifneq ($(shell which docker 2>&1),)
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
endif
endif
all:
${ENV_RUN} ./scripts/run-make build
preinstall:
${ENV_RUN} ./scripts/run-make build preinstall
install:
${ENV_RUN} ./scripts/run-make build install
clean:
${ENV_RUN} ./scripts/run-make build clean
purge:
${ENV_RUN} rm -rf build
test:
${ENV_RUN} ./scripts/run-make build test
devenv:
docker pull ${DEVENV_IMAGE}
docker run -d -v $(shell pwd):/usr/src/project \
-e LOCAL_USER_ID=$(shell id -u ${USER}) \
--name ${DEVENV} -t ${DEVENV_IMAGE} bash
devenv-destroy:
docker rm -f ${DEVENV}
devenv-shell:
${ENV_RUN} bash
configure-release:
${ENV_RUN} rm -rf build/${HOST_ENV}-release
${ENV_RUN} ./scripts/setup_build ${HOST_ENV}
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-release build/current
configure-debug:
${ENV_RUN} rm -rf build/${HOST_ENV}-debug
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} debug
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-debug build/current
configure-asan:
${ENV_RUN} rm -rf build/${HOST_ENV}-asan
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} asan
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-asan build/current
configure-windows:
${ENV_RUN} rm -rf build/windows
${ENV_RUN} ./scripts/setup_build windows
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s windows build/current
configure-windows-debug:
${ENV_RUN} rm -rf build/windows
${ENV_RUN} ./scripts/setup_build windows debug
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s windows build/current
configure-gba:
${ENV_RUN} rm -rf build/gba-release
${ENV_RUN} ./scripts/setup_build gba
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s gba-release build/current
-24
View File
@@ -1,24 +0,0 @@
set(CMAKE_SYSTEM_NAME "Generic")
set(DEVKITARM $ENV{DEVKITARM})
if(NOT DEVKITARM)
message(FATAL_ERROR "DEVKITARM environment variable not set")
endif()
set(CMAKE_C_COMPILER ${DEVKITARM}/bin/arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER ${DEVKITARM}/bin/arm-none-eabi-g++)
set(CMAKE_FIND_ROOT_PATH ${DEVKITARM})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_LIBRARY_PREFIXES lib)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
set(LINKER_FLAGS "-specs=gba.specs")
add_definitions (
-DARM7
)
include(FindPackageHandleStandardArgs)
-18
View File
@@ -1,18 +0,0 @@
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
# cross compilers to use for C and C++
set(CMAKE_C_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
# set 1st to dir with the cross compiler's C/C++ headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-52
View File
@@ -1,52 +0,0 @@
# This file belongs Nick Overdijk, and is from https://github.com/NickNick/wubwubcmake
# The MIT License (MIT)
#
# Copyright (c) 2013 Nick Overdijk
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.option(USE_ASAN "Enable Address Sanitizer, if your compiler supports it" ON)
option(USE_ASAN "Enable Address Sanitizer, if your compiler supports it" OFF)
if(USE_ASAN)
include(CheckCXXSourceCompiles)
# If the compiler understands -fsanitize=address, add it to the flags (gcc since 4.8 & clang since version 3.2)
set(CMAKE_REQUIRED_FLAGS_BAK "${CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fsanitize=address")
CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" FLAG_FSANA_SUPPORTED)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_BAK}")
if(FLAG_FSANA_SUPPORTED)
set(asan_flag "-fsanitize=address")
else(FLAG_FSANA_SUPPORTED)
# Alternatively, try if it understands -faddress-sanitizer (clang until version 3.2)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -faddress-sanitizer")
CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" FLAG_FASAN_SUPPORTED)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_BAK}")
if(FLAG_FASAN_SUPPORTED)
set(asan_flag "-faddress-sanitizer")
endif(FLAG_FASAN_SUPPORTED)
endif(FLAG_FSANA_SUPPORTED)
if(FLAG_FSANA_SUPPORTED OR FLAG_FASAN_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${asan_flag}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${asan_flag}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${asan_flag}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${asan_flag}")
endif()
endif(USE_ASAN)
-8
View File
@@ -1,8 +0,0 @@
#! /usr/bin/env bash
set -e
make -j release
make -j debug
make -j
make -j test
-8
View File
@@ -1,8 +0,0 @@
#! /usr/bin/env bash
set -e
for f in $(find $1 -maxdepth 1 -mindepth 1 -type d)
do
cmake --build "$f" --target $2 --
done
-34
View File
@@ -1,34 +0,0 @@
#! /usr/bin/env bash
set -e
project=$(pwd)/
TARGET=$1
BUILD_TYPE=$2
if [[ $TARGET == windows ]]; then
toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/modules/Mingw.cmake"
elif [[ $TARGET == gba ]]; then
toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/modules/GBA.cmake -DOX_USE_STDLIB=OFF -DCMAKE_INSTALL_PREFIX=$DEVKITARM"
fi
if [[ $BUILD_TYPE == asan ]]; then
buildTypeArgs="-DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug"
buildDir="build/${TARGET}-asan"
elif [[ $BUILD_TYPE == debug ]]; then
buildTypeArgs="-DCMAKE_BUILD_TYPE=Debug"
buildDir="build/${TARGET}-debug"
else
buildTypeArgs="-DCMAKE_BUILD_TYPE=Release"
buildDir="build/${TARGET}-release"
fi
mkdir -p $buildDir
pushd $buildDir
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-GNinja \
$buildTypeArgs \
$toolchain \
$project
popd
-1
View File
@@ -1 +0,0 @@
add_subdirectory(ox)
-46
View File
@@ -1,46 +0,0 @@
add_library(
OxEvent
signal.cpp
)
if(NOT MSVC)
target_compile_options(OxEvent PRIVATE -Wsign-conversion)
target_compile_options(OxEvent PRIVATE -Wconversion)
endif()
if(NOT OX_BARE_METAL)
set_property(
TARGET
OxEvent
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
endif()
target_compile_definitions(
OxEvent PUBLIC
$<$<BOOL:${OX_USE_STDLIB}>:OX_USE_STDLIB>
$<$<BOOL:${OX_NODEBUG}>:OX_NODEBUG>
)
target_link_libraries(
OxEvent PUBLIC
OxStd
)
install(
FILES
event.hpp
signal.hpp
DESTINATION
include/ox/event
)
install(TARGETS OxEvent
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
if(OX_RUN_TESTS)
add_subdirectory(test)
endif()
-163
View File
@@ -1,163 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/array.hpp>
#include <ox/std/bit.hpp>
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>
#include <ox/std/reader.hpp>
#include "err.hpp"
namespace ox {
template<Reader_c Reader>
class FieldBitmapReader {
protected:
mutable std::size_t m_mapBlockIdx = ~std::size_t{0};
mutable uint64_t m_mapBlock = 0;
std::size_t m_mapStart = 0;
Reader &m_reader;
public:
explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept;
private:
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept;
};
template<Reader_c Reader>
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
m_mapStart(reader.tellg()),
m_reader(reader) {
}
template<Reader_c Reader>
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept {
constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
OX_RETURN_ERROR(loadMapBlock(blockIdx));
}
idx %= blockBits;
return (m_mapBlock >> idx) & 1;
}
template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
OX_REQUIRE(g, m_reader.tellg());
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
i += 8;
}
m_mapBlockIdx = idx;
return {};
}
template<typename T>
class FieldBitmapWriterBase {
protected:
T m_map = nullptr;
std::size_t m_mapLen = 0;
public:
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept;
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept;
constexpr void setFields(int) noexcept;
constexpr void setMaxLen(int) noexcept;
[[nodiscard]]
constexpr int64_t getMaxLen() const noexcept;
};
template<typename T>
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T>
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T>
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept {
if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1;
} else {
return ox::Error(McPresenceMapOverflow);
}
}
template<typename T>
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept {
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
}
template<typename T>
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept {
m_mapLen = static_cast<std::size_t>(maxLen);
}
template<typename T>
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
return static_cast<int64_t>(m_mapLen);
}
extern template class FieldBitmapWriterBase<uint8_t*>;
extern template class FieldBitmapWriterBase<const uint8_t*>;
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> {
public:
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
constexpr Error set(std::size_t i, bool on) noexcept;
};
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
FieldBitmapWriterBase<uint8_t*>(map, maxLen) {
}
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<uint8_t>(1 << (i % 8));
}
OX_ALLOW_UNSAFE_BUFFERS_END
return {};
} else {
return ox::Error(McPresenceMapOverflow);
}
}
}
-413
View File
@@ -1,413 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/model/fieldcounter.hpp>
#include <ox/model/modelhandleradaptor.hpp>
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/bit.hpp>
#include <ox/std/buffer.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/optional.hpp>
#include <ox/std/string.hpp>
#include <ox/std/types.hpp>
#include <ox/std/units.hpp>
#include "intops.hpp"
#include "err.hpp"
#include "presenceindicator.hpp"
#include "types.hpp"
namespace ox {
template<Writer_c Writer>
class MetalClawWriter {
private:
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
FieldBitmap m_fieldPresence;
int m_field = 0;
ox::Optional<int> m_unionIdx;
std::size_t m_writerBeginP{};
Writer &m_writer;
public:
constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept;
constexpr ~MetalClawWriter() noexcept = default;
constexpr Error field(const char*, const int8_t *val) noexcept;
constexpr Error field(const char*, const int16_t *val) noexcept;
constexpr Error field(const char*, const int32_t *val) noexcept;
constexpr Error field(const char*, const int64_t *val) noexcept;
constexpr Error field(const char*, const uint8_t *val) noexcept;
constexpr Error field(const char*, const uint16_t *val) noexcept;
constexpr Error field(const char*, const uint32_t *val) noexcept;
constexpr Error field(const char*, const uint64_t *val) noexcept;
constexpr Error field(const char*, const bool *val) noexcept;
template<typename T>
constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
template<typename T>
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
template<std::size_t SmallStringSize>
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
template<std::size_t L>
constexpr Error field(const char*, const IString<L> *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
constexpr Error fieldCString(const char *name, const char **val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val) noexcept;
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
template<typename T>
constexpr Error field(const char*, const T *val) noexcept;
template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(
const char *name = T::TypeName,
int version = T::TypeVersion,
const Vector<String>& = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept;
/**
* stringLength is not implemented in MetalClawWriter
*/
[[nodiscard]]
constexpr auto stringLength(const char*) noexcept {
return 0;
}
/**
* stringLength is not implemented in MetalClawWriter
*/
[[nodiscard]]
constexpr auto arrayLength(const char*, bool = true) noexcept {
return 0;
}
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Write;
}
ox::Error finalize() noexcept;
private:
constexpr Error appendInteger(Integer_c auto val) noexcept {
bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
};
extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx),
m_writerBeginP(writer.tellp()),
m_writer(writer) {
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
return appendInteger(*val);
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
}
++m_field;
return {};
}
template<Writer_c Writer>
template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
bool fieldSet = false;
if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length
const auto strLen = mc::encodeInteger(val->size());
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
// write the string
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->size())));
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
template<std::size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept {
return fieldCString(name, val->data(), val->size());
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
bool fieldSet = false;
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// this strlen is tolerated because sometimes 0 gets passed to
// the size param, which is a lie
// this code should be cleaned up at some point...
const auto strLen = *val ? ox::strlen(*val) : 0;
OX_ALLOW_UNSAFE_BUFFERS_END
// write the length
const auto strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string
OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen)));
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept {
return fieldCString(name, val, {});
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept {
return fieldCString(name, val, {});
}
template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
bool fieldSet = false;
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length
const auto strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string
OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen)));
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) {
return field(nullptr, val->data(), val->size());
} else {
bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
OX_RETURN_ERROR(model(&handler, val));
OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp();
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
}
template<Writer_c Writer>
template<typename U, bool force>
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
bool fieldSet = false;
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer};
OX_RETURN_ERROR(model(&handler, val.get()));
OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp();
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept {
bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array
for (std::size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
}
OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp();
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept {
const auto &keys = val->keys();
const auto len = keys.size();
bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
// write map
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
// double len for both key and value
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.size();
auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1);
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
OX_REQUIRE_M(value, val.at(key));
return handler.field("", value);
};
// write the array
for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i];
OX_RETURN_ERROR(loopBody(handler, key, *val));
}
OX_RETURN_ERROR(writer.finalize());
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return {};
}
template<Writer_c Writer>
template<typename T>
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1;
OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields));
return {};
}
template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp();
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size()));
OX_RETURN_ERROR(m_writer.seekp(end));
return {};
}
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter};
OX_RETURN_ERROR(model(&handler, &val));
OX_RETURN_ERROR(mcWriter.finalize());
return {};
}
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0);
OX_RETURN_ERROR(writeMC(bw, val));
buff.resize(bw.tellp());
return buff;
}
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw{{buff, buffLen}};
OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) {
*sizeOut = bw.tellp();
}
return {};
}
}
-54
View File
@@ -1,54 +0,0 @@
add_library(
OxModel
desctypes.cpp
descwrite.cpp
modelvalue.cpp
)
if(NOT MSVC)
target_compile_options(OxModel PRIVATE -Wconversion)
target_compile_options(OxModel PRIVATE -Wsign-conversion)
endif()
target_link_libraries(
OxModel PUBLIC
OxStd
)
if(NOT OX_BARE_METAL)
set_property(
TARGET
OxModel
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
endif()
install(
FILES
def.hpp
descread.hpp
desctypes.hpp
descwrite.hpp
optype.hpp
metadata.hpp
model.hpp
modelhandleradaptor.hpp
modelops.hpp
modelvalue.hpp
typenamecatcher.hpp
types.hpp
typestore.hpp
walk.hpp
DESTINATION
include/ox/model
)
install(TARGETS OxModel
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
if(OX_RUN_TESTS)
add_subdirectory(test)
endif()
-231
View File
@@ -1,231 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/utility.hpp>
#include "modelvalue.hpp"
namespace ox {
template<typename Handler, OpType opType_v = Handler::opType()>
class ModelHandlerInterface {
private:
Handler *m_handler = nullptr;
public:
constexpr explicit ModelHandlerInterface(Handler *handler) noexcept: m_handler(handler) {
}
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(
const char* name = T::TypeName,
int version = T::TypeVersion,
const Vector<String>& typeParams = {}) noexcept {
return m_handler->template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>);
}
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(
const char *name,
int version,
const Vector<String>& typeParams,
std::size_t fields) noexcept {
return m_handler->template setTypeInfo<T>(name, version, typeParams, fields);
}
template<std::size_t len>
constexpr Error fieldCString(const char *name, char val[len]) noexcept {
return m_handler->fieldCString(name, &val[0], len);
}
template<std::size_t len>
constexpr Error fieldCString(const char *name, const char val[len]) noexcept requires(opType_v != OpType::Read) {
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, &val[0], len);
} else {
return {};
}
}
constexpr Error fieldCString(const char *name, char **val) noexcept {
return m_handler->fieldCString(name, val);
}
constexpr Error fieldCString(const char *name, const char *const*val) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val);
} else {
return {};
}
}
constexpr Error fieldCString(const char *name, const char **val) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val);
} else {
return {};
}
}
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
return m_handler->fieldCString(name, val, buffLen);
}
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val, buffLen);
} else {
return {};
}
}
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
return m_handler->fieldCString(name, val, buffLen);
}
constexpr Error fieldModelValue(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept {
switch (v->type()) {
case ModelValue::Type::Undefined:
break;
case ModelValue::Type::Bool:
return m_handler->field(name, &v->template get<bool>());
case ModelValue::Type::UnsignedInteger8:
return m_handler->field(name, &v->template get<uint8_t>());
case ModelValue::Type::UnsignedInteger16:
return m_handler->field(name, &v->template get<uint16_t>());
case ModelValue::Type::UnsignedInteger32:
return m_handler->field(name, &v->template get<uint32_t>());
case ModelValue::Type::UnsignedInteger64:
return m_handler->field(name, &v->template get<uint64_t>());
case ModelValue::Type::SignedInteger8:
return m_handler->field(name, &v->template get<int8_t>());
case ModelValue::Type::SignedInteger16:
return m_handler->field(name, &v->template get<int16_t>());
case ModelValue::Type::SignedInteger32:
return m_handler->field(name, &v->template get<int32_t>());
case ModelValue::Type::SignedInteger64:
return m_handler->field(name, &v->template get<int64_t>());
case ModelValue::Type::String:
return m_handler->field(name, &v->template get<String>());
case ModelValue::Type::Object:
return m_handler->field(name, &v->template get<ModelObject>());
case ModelValue::Type::Union:
{
auto &u = v->template get<ModelUnion>();
if constexpr(opType_v == OpType::Read) {
u.setActiveField(m_handler->whichFieldPresent(name, u));
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
} else {
return m_handler->field(name, UnionView<const ModelUnion, true>(&u, u.unionIdx()));
}
}
case ModelValue::Type::Vector:
return m_handler->field(name, &v->template get<ModelValueVector>());
case ModelValue::Type::InlineArray:
return m_handler->field(name, &v->template get<ModelValueArray>());
}
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(ox::Error(1), "invalid type");
return ox::Error(1, "invalid type");
}
// array handler, with callback to allow handling individual elements
template<typename T, typename Callback>
constexpr Error field(const char *name, Callback cb) noexcept {
return m_handler->template field<T, Callback>(name, cb);
}
template<typename T>
constexpr Error field(const char *name, const T *v) noexcept {
if constexpr(ox::is_same_v<T, ModelValue>) {
return fieldModelValue(name, v);
} else {
return m_handler->field(name, v);
}
}
template<typename T>
constexpr Error field(const char *name, T *v) noexcept {
if constexpr(ox::is_same_v<T, ModelValue>) {
return fieldModelValue(name, v);
} else {
return m_handler->field(name, v);
}
}
template<typename U, bool force = false>
constexpr Error field(const char *name, UnionView<U, force> val) noexcept {
return m_handler->field(name, val);
}
constexpr Error field(const char *name, auto *val, std::size_t len) noexcept {
return m_handler->field(name, val, len);
}
/**
* Reads an array length from the current location in the buffer.
* @param pass indicates that the parsing should iterate past the array length
*/
[[nodiscard]]
constexpr auto arrayLength(const char *name, bool pass = true) noexcept {
return m_handler->arrayLength(name, pass);
}
/**
* Reads an string length from the current location in the buffer.
*/
[[nodiscard]]
constexpr auto stringLength(const char *name) noexcept {
return m_handler->stringLength(name);
}
[[nodiscard]]
static constexpr auto opType() noexcept {
return Handler::opType();
}
[[nodiscard]]
constexpr auto handler() noexcept {
return m_handler;
}
};
template<typename Handler, ox::OpType opType_v = Handler::opType()>
class ModelHandlerBase {
private:
ModelHandlerInterface<Handler, opType_v> m_interface;
public:
constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {}
constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {}
constexpr ModelHandlerBase(ModelHandlerBase&&) noexcept: m_interface(static_cast<Handler*>(this)) {}
[[nodiscard]]
constexpr auto interface() noexcept {
return &m_interface;
}
[[nodiscard]]
static constexpr ox::OpType opType() noexcept {
return opType_v;
}
};
constexpr ox::Error resizeVector(auto &vec, size_t sz) {
if constexpr(ox::is_same_v<decltype(vec.resize(0)), ox::Error>) {
return vec.resize(sz);
} else {
vec.resize(sz);
return {};
}
}
}
-83
View File
@@ -1,83 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "fmt.hpp"
#include "realstd.hpp"
#include "stacktrace.hpp"
#include "trace.hpp"
#include "assert.hpp"
namespace ox {
void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
}
#ifdef OX_USE_STDLIB
printStackTrace(2);
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << file << ":" << line << ")";
std::abort();
#else
while (1);
#endif
}
#if __GNUC__ && !_WIN32
__attribute__((weak))
#endif
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
}
void assertFailFuncRuntime(
StringViewCR file,
int const line,
StringViewCR assertTxt,
StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB
auto const st = genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st);
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 const line,
[[maybe_unused]] Error const&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<ErrorCode>(err));
if (err.src.file_name() != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
abort();
#else
constexprPanic(file, line, assertMsg);
#endif
}
}
-105
View File
@@ -1,105 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#if defined(OX_USE_STDLIB)
#include <iostream>
#endif
#include "def.hpp"
#include "defines.hpp"
#include "error.hpp"
#include "realstd.hpp"
#include "stacktrace.hpp"
#include "trace.hpp"
#include "typetraits.hpp"
namespace ox {
[[noreturn]]
void panic(StringViewCR file, int line, StringViewCR panicMsg, Error const&err = {}) noexcept;
[[noreturn]]
constexpr void constexprPanic(
StringViewCR file,
int const line,
StringViewCR panicMsg,
Error const&err = {}) noexcept {
if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err);
} else {
while (true);
}
}
void assertFailFuncRuntime(
StringViewCR file,
int line,
StringViewCR assertTxt,
StringViewCR msg) noexcept;
void assertFailFuncRuntime(
StringViewCR file,
int line,
Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept;
constexpr void assertFunc(
StringViewCR file,
int const line,
bool const pass,
[[maybe_unused]]StringViewCR assertTxt,
[[maybe_unused]]StringViewCR msg) noexcept {
if (!pass) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, assertTxt, msg);
} else {
while (true);
}
}
}
constexpr void assertFunc(
StringViewCR file,
int const line,
Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept {
if (err) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, err, {}, assertMsg);
} else {
while (true);
}
}
}
constexpr void expect(
StringViewCR file,
int const line,
auto const&actual,
auto const&expected) noexcept {
if (actual != expected) {
if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB)
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
printStackTrace(2);
oxTracef("assert.expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
std::abort();
#else
constexprPanic(file, line, "Comparison failed");
#endif
} else {
while (true);
}
}
}
}
-53
View File
@@ -1,53 +0,0 @@
/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "bit.hpp"
#include "error.hpp"
#include "math.hpp"
#include "types.hpp"
#include "writer.hpp"
namespace ox {
template<Integer_c Integer>
constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
OX_RETURN_ERROR(writer.put('-'));
++it;
}
while (mod) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
ox::ResizedInt_t<Integer, 64> start = '0';
if (digit >= 10) {
start = 'a';
digit -= 10;
}
OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
++it;
}
}
} else {
// 0 is a special case
OX_RETURN_ERROR(writer.put('0'));
}
return {};
}
}
#include "istring.hpp"
+20
View File
@@ -0,0 +1,20 @@
name: Build
run-name: ${{ gitea.actor }} build and test
on: [push]
jobs:
build:
runs-on: olympic
steps:
- name: Check out repository code
uses: actions/checkout@v3
- run: make purge configure-debug
- run: make build
- run: make test
- run: make purge configure-asan
- run: make build
- run: make test
- run: make purge configure-release
- run: make build
- run: make test
- run: make install
@@ -3,7 +3,10 @@ build/gba
build/*-asan
build/*-debug
build/*-release
dist
.current_build
tags
compile_commands.json
conanbuildinfo.cmake
conanbuildinfo.txt
conaninfo.txt
View File
+3 -3
View File
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.25)
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
project(Ox CXX)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
include(address_sanitizer)
include(deps/buildcore/base.cmake)
if(NOT DEFINED OX_RUN_TESTS)
set(OX_RUN_TESTS ON)
View File
+18
View File
@@ -0,0 +1,18 @@
BC_VAR_PROJECT_NAME=ox
BC_VAR_PROJECT_NAME_CAP=Ox
BC_VAR_DEVENV_ROOT=util
BUILDCORE_PATH=deps/buildcore
include ${BUILDCORE_PATH}/base.mk
.PHONY: git-setup-buildcore-remote
git-setup-buildcore-remote:
git remote add -f buildcore-master git@git.drinkingtea.net:drinkingtea/buildcore.git
.PHONY: git-pull-buildcore
git-pull-buildcore:
git fetch buildcore-master master
git subtree pull --prefix deps/buildcore buildcore-master master --squash
.PHONY: git-push-buildcore
git-push-buildcore:
git subtree push --prefix=deps/buildcore buildcore-master master

Some files were not shown because too many files have changed in this diff Show More