This commit is contained in:
Vendored
+4
-7
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.19)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||||
|
|
||||||
if(BUILDCORE_TARGET STREQUAL "gba")
|
if(BUILDCORE_TARGET STREQUAL "gba")
|
||||||
@@ -9,7 +9,7 @@ else()
|
|||||||
project(nostalgia C CXX)
|
project(nostalgia C CXX)
|
||||||
endif()
|
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")
|
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)
|
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(deps/ox)
|
add_subdirectory(deps/oxlib)
|
||||||
include_directories(
|
|
||||||
deps/ox/src
|
|
||||||
)
|
|
||||||
add_subdirectory(deps/teagba)
|
add_subdirectory(deps/teagba)
|
||||||
|
|
||||||
if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
||||||
@@ -55,7 +52,7 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
|||||||
set(GLFW_BUILD_TESTS OFF)
|
set(GLFW_BUILD_TESTS OFF)
|
||||||
set(GLFW_BUILD_DOCS OFF)
|
set(GLFW_BUILD_DOCS OFF)
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(GLFW_BUILD_WAYLAND OFF)
|
set(GLFW_BUILD_WAYLAND ON)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(deps/glfw)
|
add_subdirectory(deps/glfw)
|
||||||
add_subdirectory(deps/glutils)
|
add_subdirectory(deps/glutils)
|
||||||
|
|||||||
Vendored
+14
-1
@@ -1,7 +1,7 @@
|
|||||||
BC_VAR_PROJECT_NAME=nostalgia
|
BC_VAR_PROJECT_NAME=nostalgia
|
||||||
BC_VAR_PROJECT_NAME_CAP=Nostalgia
|
BC_VAR_PROJECT_NAME_CAP=Nostalgia
|
||||||
BC_VAR_DEVENV_ROOT=util
|
BC_VAR_DEVENV_ROOT=util
|
||||||
BUILDCORE_PATH=deps/buildcore
|
BUILDCORE_PATH=deps/oxlib/deps/buildcore
|
||||||
include ${BUILDCORE_PATH}/base.mk
|
include ${BUILDCORE_PATH}/base.mk
|
||||||
|
|
||||||
ifeq ($(BC_VAR_OS),darwin)
|
ifeq ($(BC_VAR_OS),darwin)
|
||||||
@@ -13,6 +13,19 @@ else
|
|||||||
endif
|
endif
|
||||||
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
|
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
|
.PHONY: pkg-gba
|
||||||
pkg-gba: build-pack build-gba-player
|
pkg-gba: build-pack build-gba-player
|
||||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
|
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
|
||||||
|
|||||||
-12
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Vendored
-11
@@ -1,11 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
sudo: false
|
|
||||||
dist: trusty
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
- gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- cmake
|
|
||||||
script: ./scripts/cibuild
|
|
||||||
Vendored
-68
@@ -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
@@ -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)
|
|
||||||
@@ -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)
|
|
||||||
@@ -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
@@ -1,8 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
make -j release
|
|
||||||
make -j debug
|
|
||||||
make -j
|
|
||||||
make -j test
|
|
||||||
-8
@@ -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
@@ -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
@@ -1 +0,0 @@
|
|||||||
add_subdirectory(ox)
|
|
||||||
@@ -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()
|
|
||||||
@@ -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
@@ -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 {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
@@ -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/*-asan
|
||||||
build/*-debug
|
build/*-debug
|
||||||
build/*-release
|
build/*-release
|
||||||
|
dist
|
||||||
|
.current_build
|
||||||
tags
|
tags
|
||||||
|
compile_commands.json
|
||||||
conanbuildinfo.cmake
|
conanbuildinfo.cmake
|
||||||
conanbuildinfo.txt
|
conanbuildinfo.txt
|
||||||
conaninfo.txt
|
conaninfo.txt
|
||||||
+3
-3
@@ -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
|
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||||
|
|
||||||
project(Ox CXX)
|
project(Ox CXX)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
|
include(deps/buildcore/base.cmake)
|
||||||
include(address_sanitizer)
|
|
||||||
|
|
||||||
if(NOT DEFINED OX_RUN_TESTS)
|
if(NOT DEFINED OX_RUN_TESTS)
|
||||||
set(OX_RUN_TESTS ON)
|
set(OX_RUN_TESTS ON)
|
||||||
Vendored
+18
@@ -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
|
||||||
Vendored
Vendored
Vendored
Vendored
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user