Compare commits

...

98 Commits

Author SHA1 Message Date
1b32bdfcad [nostalgia/studio] Bump version to d2024.12.3
All checks were successful
Build / build (push) Successful in 3m14s
2025-01-17 21:45:37 -06:00
3544392fa8 [nostalgia/core/studio] Cleanup, fix possible TileSheet fill tool failure
All checks were successful
Build / build (push) Successful in 3m21s
2025-01-17 21:43:46 -06:00
144d234d09 [nostalgia/studio] Change version to release-d2024.12
All checks were successful
Build / build (push) Successful in 3m20s
2025-01-12 21:03:34 -06:00
465fb06f76 [nostalgia/core] Fix TileSheet validation/repair to ensure pixels gets cleared if there are subsheets
Some checks failed
Build / build (push) Has been cancelled
2025-01-12 20:58:19 -06:00
db953dd0d1 [studio] Fix new project menu to return an appropriately sized string for name 2025-01-12 20:58:19 -06:00
daab4dc4f5 [nostalgia/core/studio] Fix SubSheet editor to return an appropriately sized string 2025-01-12 20:58:19 -06:00
83cbac5cca [nostalgia/studio] Update version to d2024.12.1
All checks were successful
Build / build (push) Successful in 3m19s
2025-01-11 17:22:02 -06:00
74e518fee0 [nostalgia/core/studio/tilesheeteditor] Fix select all not to go beyond end 2025-01-11 17:07:50 -06:00
6b0ce40c02 [nostalgia/core/studio] Fix crash that occurs when a non-leaf node subsheet is selected 2025-01-11 17:07:50 -06:00
4f55964dd9 [nostalgia/core/studio] Fix tile insert to correct input when inserting past the last tile 2025-01-11 17:07:50 -06:00
cb597cf92e [nostalgia/core/studio] Fix tile insert to work on last tile 2025-01-11 17:07:50 -06:00
6906c66ba7 [keel] Fix reloadAsset 2025-01-11 17:07:50 -06:00
ba00d10dfc [nostalgia] Update liccor file 2025-01-11 17:07:50 -06:00
cdfbfe48b7 [ox] Update liccor file 2025-01-11 17:07:50 -06:00
21ae2a14e9 [ox] Run liccor 2025-01-11 17:07:50 -06:00
81b120b1ce [nostalgia,olympic] Run liccor 2025-01-11 17:07:50 -06:00
40938958de [turbine/glfw] Ensure window opens with a standard mandatory refresh period 2025-01-11 17:07:50 -06:00
df190c05a0 [studio] Make first tab not draw before selected tab when window opens 2025-01-11 17:07:50 -06:00
3fe3b08eca [ox/std] Add hash.hpp to install 2025-01-11 17:07:50 -06:00
ecc5ae6b2f [studio] Make selection tracker not go below 0 2025-01-11 17:07:50 -06:00
a863bfc181 [nostalgia/studio] Update version to d2024.12.0
All checks were successful
Build / build (push) Successful in 3m20s
2024-12-21 19:27:00 -06:00
a75c4a11d3 [nfde] Address CMake warning, remove unwanted logging
All checks were successful
Build / build (push) Successful in 2m45s
2024-12-21 17:07:23 -06:00
347a165762 [sample_project] Update type descriptors
All checks were successful
Build / build (push) Successful in 2m55s
2024-12-21 02:45:24 -06:00
fd64bfae13 [keel] Fix a use after free, cleanup
Some checks are pending
Build / build (push) Waiting to run
2024-12-21 02:42:19 -06:00
aaeec20ac9 [nostalgia/player] Fix build 2024-12-21 02:42:05 -06:00
37030f9c11 [keel] Cleanup pack tool 2024-12-21 02:41:56 -06:00
462f2bca4c [nostalgia,olympic] Change macro names to comply with broader conventions 2024-12-21 02:41:19 -06:00
dc72500b98 [glutils] Change macro names to comply with broader conventions 2024-12-18 22:04:39 -06:00
962fe8bc22 [ox] Change macro names to comply with broader conventions 2024-12-18 22:04:25 -06:00
305eb62647 [studio] Fix build
Some checks are pending
Build / build (push) Waiting to run
2024-12-18 21:41:15 -06:00
4754359a21 [ox/std] Cleanup Vec2
Some checks failed
Build / build (push) Has been cancelled
2024-12-15 01:26:41 -06:00
dc07f3d58b [studio] Change FilePicker consturctor to take StringParams 2024-12-15 01:20:29 -06:00
fcdcfd10d1 [ox/std] Run liccor
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-14 14:33:43 -06:00
b74f6a7ace [studio,turbine] Run liccor 2024-12-14 14:33:06 -06:00
ac7e5be187 [ox] Remove OxException
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-14 00:40:05 -06:00
ed910c0beb [nostalgia/core/studio/tilesheeteditor] Fix access overflow on out of bounds Fill command
All checks were successful
Build / build (push) Successful in 2m51s
2024-12-13 22:24:58 -06:00
345fb03857 [ox] Remove OxError 2024-12-13 22:06:47 -06:00
9881253f2a [glutils] Cleanup OxError 2024-12-13 22:06:26 -06:00
96d27eecd1 [nostalgia,olympic] Cleanup 2024-12-13 22:00:03 -06:00
28ebe93b77 [ox/std] Make source_location::current only init if valid
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-12 23:13:39 -06:00
e849e7a3dd [ox/std] Add source_location
Some checks failed
Build / build (push) Has been cancelled
2024-12-12 23:09:01 -06:00
e6777b0ad7 [cityhash] Add install rule 2024-12-12 22:36:09 -06:00
c488c336de [turbine/glfw] Fix mandatoryRefreshPeriodEnd tracking
All checks were successful
Build / build (push) Successful in 2m54s
2024-12-11 22:13:28 -06:00
003f97201f [turbine/glfw] Move MandatoryRefreshPeriod to config.hpp
All checks were successful
Build / build (push) Successful in 2m45s
2024-12-10 23:29:50 -06:00
d85a10af84 [nostalgia/core/studio] Cleanup 2024-12-10 23:29:21 -06:00
ff05d860c4 [turbine/glfw] Replace uninterruptedRefreshes with mandatoryRefreshPeriodEnd
Some checks failed
Build / build (push) Has been cancelled
2024-12-10 01:49:20 -06:00
7679403742 [turbine] Add init wrapper that takes FS path 2024-12-06 23:20:30 -06:00
c51a45e1ba [olympic] Cleanup 2024-12-06 00:22:33 -06:00
a6e24ff2b6 [ox/std] Add CString type alias 2024-12-06 00:20:03 -06:00
e0ec9e0c5f [nostalgia,olympic] Move olympic::run to global namespace
All checks were successful
Build / build (push) Successful in 2m34s
2024-12-06 00:13:10 -06:00
9a42a9b9d9 [nfde] Fix Windows warnings 2024-12-06 00:12:38 -06:00
03a05c511e Merge commit '4ccdfc3a6e5bd501968903a01f7d8141b6f88375'
All checks were successful
Build / build (push) Successful in 2m31s
2024-12-04 19:55:17 -06:00
bd91137d27 [nostalgia,olympic] Fix pack tool build for Windows 2024-12-02 21:10:52 -06:00
161640fa11 [nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 2m46s
2024-12-02 19:58:05 -06:00
2b7d12945e [nostalgia/core/studio] Fix MSVC build 2024-12-01 19:42:29 -06:00
e42126c956 [nostalgia/core] Improve TileSheet validation, add repair
All checks were successful
Build / build (push) Successful in 2m40s
2024-12-01 15:47:49 -06:00
36942cca18 [nostalgia,olympic] Replace SpanView with Span<const T>
All checks were successful
Build / build (push) Successful in 2m36s
2024-12-01 08:41:20 -06:00
b14f1d5000 [ox] Replace SpanView with Span<const T> 2024-12-01 08:41:08 -06:00
1bf4f246c2 [applib] Make run take args as a SpanView 2024-11-28 00:51:42 -06:00
edda8e010e [ox/clargs] Add constructor that takes a SpanView 2024-11-28 00:51:02 -06:00
3308b4dd72 [ox/std] Add missing + and += operators to Span
All checks were successful
Build / build (push) Successful in 2m38s
2024-11-27 00:17:37 -06:00
27f4703a9a [teagba] Suppress warnings for unsafe buffers 2024-11-27 00:15:59 -06:00
6af00d9a2e [nostalgia] Enable warnings for unsafe buffers 2024-11-27 00:14:57 -06:00
86b9f9316e [olympic] Enable warnings for unsafe buffers 2024-11-26 23:58:11 -06:00
a0ed1b3f62 [ox/std] Fix Span raw array constructor 2024-11-26 23:57:41 -06:00
8dad624b21 [studio/applib] Cleanup 2024-11-26 23:32:32 -06:00
dc6605fd48 [keel] Add missing error checking to pack 2024-11-26 23:32:15 -06:00
c78d3cf638 [ox] Add more unsafe buffer exceptions 2024-11-26 23:31:34 -06:00
cee4f65d4a [ox/std] Replace an unsafe buffer
All checks were successful
Build / build (push) Successful in 2m38s
2024-11-26 22:31:20 -06:00
cd3eeeef14 [ox/fs] Suppress unsafe buffer warnings 2024-11-26 22:30:57 -06:00
287d42f2b9 [ox/clargs] Cleanup
All checks were successful
Build / build (push) Successful in 2m41s
2024-11-26 22:08:36 -06:00
dbbaaa46b9 [ox/clargs] Enable unsafe buffer warnings
Some checks failed
Build / build (push) Has been cancelled
2024-11-26 22:06:50 -06:00
9b8a8c4e46 [ox/std] Enable unsafe buffer warnings 2024-11-26 21:59:26 -06:00
e44fa288fd [cityhash] Add pragmas to ignore unsafe buffer warnings 2024-11-26 21:58:39 -06:00
e13c6e812b [ox/std] Remove raw char* CharBufferWriter constructor 2024-11-26 20:48:13 -06:00
cb55b31afa [ox/std] Cleanup 2024-11-26 20:43:43 -06:00
ab3f9e1627 [ox/std] Make Span access check message consistent with other messages 2024-11-26 20:43:20 -06:00
8f25ef96ff [ox/std] Make CharBufferWriter constructor take a Span 2024-11-26 20:42:33 -06:00
e13eebaf0b [ox/std] Cleanup an unsafe buffer 2024-11-26 20:38:00 -06:00
114f5c6685 [ox/std] Add overflow checking to SpanIterator
All checks were successful
Build / build (push) Successful in 2m36s
2024-11-19 01:09:48 -06:00
df44fe235b [keel] Cleanup
All checks were successful
Build / build (push) Successful in 2m42s
2024-11-15 19:59:42 -06:00
72f4db3d5e [nostalgia/core/studio] Fix paste command to never paste beyond target dimensions
All checks were successful
Build / build (push) Successful in 2m40s
2024-11-15 01:39:57 -06:00
8a9ff971a1 [nostalgia/core] Fix resizeSubsheet to work for both growing and shrinking 2024-11-15 01:09:48 -06:00
5a8da59df1 [keel] Fix readAsset to actually return asset 2024-11-15 01:01:31 -06:00
afa3a13d41 [keel] Cleanup 2024-11-14 21:23:42 -06:00
6522cf8a43 [keel] Add ensureValid call to readAsset 2024-11-14 21:17:41 -06:00
f772e48b36 [ox] Add Vector/Array/Span overflow checking 2024-11-14 21:08:38 -06:00
13bfe88195 [nostalgia/core] Fix resizeSubsheet array overflow 2024-11-14 19:59:58 -06:00
5025475414 Merge commit '9e11019b87ba27d1dac9e097dc212a126e404218' 2024-11-01 22:23:08 -05:00
3c7652efc2 [nostalgia/core/studio] Fix PaletteEditor to handle Palettes with 0 pages
All checks were successful
Build / build (push) Successful in 2m55s
2024-10-28 20:57:34 -05:00
941bc71348 [studio] Fix NewMenu name input 2024-10-28 20:57:34 -05:00
bfe890ae00 [ox] Fix typo in docs 2024-10-08 23:04:49 -05:00
ab5bc1adb6 [ox/std] Remove oxRequireT and oxRequireMT 2024-10-06 06:16:14 -05:00
abf7548ab5 [nostalgia/core] Add missing include 2024-10-04 21:36:26 -05:00
e2682b5ef7 [studio/modlib] Add missing include 2024-10-04 21:35:08 -05:00
792ad41499 [nostalgia] Remove .vs dir 2024-10-04 18:51:36 -05:00
e4ae23e114 [olympic/developer-handbook] Remove Ox submodules from project structure
All checks were successful
Build / build (push) Successful in 2m31s
2024-10-04 01:22:21 -05:00
67187d5ec5 [olympic/developer-handbook] Elaborate more on exception usage 2024-10-04 01:18:25 -05:00
403 changed files with 3736 additions and 3286 deletions

View File

@ -2,4 +2,4 @@
source: source:
- src - src
copyright_notice: |- copyright_notice: |-
Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.

View File

@ -1,44 +0,0 @@
{
"version": "0.2.1",
"defaults": {},
"configurations": [
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia.exe (Install)",
"name": "nostalgia.exe (Install)",
"args": [
"${projectDir}/sample_project"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia.exe",
"name": "nostalgia.exe",
"args": [
"${projectDir}/sample_project"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia-studio.exe (Install)",
"name": "nostalgia-studio.exe (Install)",
"args": [
"-profile",
"${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia-studio.exe",
"name": "nostalgia-studio.exe",
"args": [
"-profile",
"${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json"
]
}
]
}

View File

@ -83,13 +83,13 @@ static ox::Result<GLShader> buildShader(
ox::Vector<char> errMsg(ox::units::KB); ox::Vector<char> errMsg(ox::units::KB);
glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data()); glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data());
oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data()); oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data());
return OxError(1, "shader compile error"); return ox::Error(1, "shader compile error");
} }
return shader; return shader;
} }
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
oxRequireM(program, buildShaderProgram( OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader, src.vertShader,
src.fragShader, src.fragShader,
src.geomShader)); src.geomShader));
@ -127,13 +127,13 @@ ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&frag, ox::CStringView const&frag,
ox::CStringView const&geo) noexcept { ox::CStringView const&geo) noexcept {
GLProgram prgm(glCreateProgram()); GLProgram prgm(glCreateProgram());
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs); glAttachShader(prgm, vs);
if (geo.c_str() && geo.bytes() != 0) { if (geo.c_str() && geo.bytes() != 0) {
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad")); OX_REQUIRE(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
glAttachShader(prgm, gs); glAttachShader(prgm, gs);
} }
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad")); OX_REQUIRE(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
glAttachShader(prgm, fs); glAttachShader(prgm, fs);
glLinkProgram(prgm); glLinkProgram(prgm);
return prgm; return prgm;

View File

@ -10,7 +10,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF) option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF)
endif() endif()
option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT}) option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT})
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT}) # DrinkingTea: begin
if(NOT DEFINED NFD_INSTALL)
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT})
endif()
# DrinkingTea: end
set(nfd_PLATFORM Undefined) set(nfd_PLATFORM Undefined)
if(WIN32) if(WIN32)
@ -21,7 +25,9 @@ elseif(UNIX AND NOT APPLE)
set(nfd_PLATFORM PLATFORM_UNIX) set(nfd_PLATFORM PLATFORM_UNIX)
endif() endif()
message("nfd Platform: ${nfd_PLATFORM}") # DrinkingTea: begin
#message("nfd Platform: ${nfd_PLATFORM}")
# DrinkingTea: end
set(nfd_COMPILER Undefined) set(nfd_COMPILER Undefined)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
@ -33,7 +39,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C
set(nfd_COMPILER COMPILER_GNU) set(nfd_COMPILER COMPILER_GNU)
endif() endif()
message("nfd Compiler: ${nfd_COMPILER}") # DrinkingTea: begin
#message("nfd Compiler: ${nfd_COMPILER}")
# DrinkingTea: end
# Use latest C++ by default (should be the best one), but let user override it # Use latest C++ by default (should be the best one), but let user override it
if(NOT DEFINED CMAKE_CXX_STANDARD) if(NOT DEFINED CMAKE_CXX_STANDARD)

View File

@ -201,7 +201,7 @@ nfdresult_t SetDefaultExtension(::IFileDialog* fileOpenDialog,
} }
if (*p_spec) { if (*p_spec) {
// multiple file extensions for this type (need to allocate memory) // multiple file extensions for this type (need to allocate memory)
size_t numChars = p_spec - filterList[0].spec; size_t numChars = static_cast<size_t>(p_spec - filterList[0].spec);
// allocate one more char space for the '\0' // allocate one more char space for the '\0'
nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1)); nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1));
if (!extnBuf) { if (!extnBuf) {
@ -710,7 +710,7 @@ nfdresult_t CopyCharToWChar(const nfdu8char_t* inStr, nfdnchar_t*& outStr) {
int charsNeeded = MultiByteToWideChar(CP_UTF8, 0, inStr, -1, nullptr, 0); int charsNeeded = MultiByteToWideChar(CP_UTF8, 0, inStr, -1, nullptr, 0);
assert(charsNeeded); assert(charsNeeded);
nfdnchar_t* tmp_outStr = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * charsNeeded); nfdnchar_t* tmp_outStr = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * static_cast<size_t>(charsNeeded));
if (!tmp_outStr) { if (!tmp_outStr) {
return NFD_ERROR; return NFD_ERROR;
} }
@ -727,7 +727,7 @@ nfdresult_t CopyWCharToNFDChar(const nfdnchar_t* inStr, nfdu8char_t*& outStr) {
int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, inStr, -1, nullptr, 0, nullptr, nullptr); int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, inStr, -1, nullptr, 0, nullptr, nullptr);
assert(bytesNeeded); assert(bytesNeeded);
nfdu8char_t* tmp_outStr = NFDi_Malloc<nfdu8char_t>(sizeof(nfdu8char_t) * bytesNeeded); nfdu8char_t* tmp_outStr = NFDi_Malloc<nfdu8char_t>(sizeof(nfdu8char_t) * static_cast<size_t>(bytesNeeded));
if (!tmp_outStr) { if (!tmp_outStr) {
return NFD_ERROR; return NFD_ERROR;
} }

2
deps/ox/.liccor.yml vendored
View File

@ -2,7 +2,7 @@
source: source:
- src - src
copyright_notice: |- copyright_notice: |-
Copyright 2015 - 2024 gary@drinkingtea.net Copyright 2015 - 2025 gary@drinkingtea.net
This Source Code Form is subject to the terms of the Mozilla Public 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 License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -9,9 +9,6 @@ set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(NOSTALGIA_BUILD_PLAYER OFF)
set(NOSTALGIA_BUILD_STUDIO_APP OFF)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@ -28,3 +25,10 @@ endif()
add_library(CityHash INTERFACE) add_library(CityHash INTERFACE)
target_include_directories(CityHash INTERFACE include) target_include_directories(CityHash INTERFACE include)
install(
DIRECTORY
include/cityhash
DESTINATION
include
)

View File

@ -104,6 +104,11 @@ using size_t = decltype(alignof(int));
#endif #endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
namespace cityhash::detail { namespace cityhash::detail {
template<typename T> template<typename T>
@ -671,4 +676,8 @@ constexpr uint128 CityHash128(const char *s, size_t len) noexcept {
} }
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif // CITY_HASH_H_ #endif // CITY_HASH_H_

90
deps/ox/ox-docs.md vendored
View File

@ -97,12 +97,12 @@ ox::Result<uint64_t> caller8(int i) {
``` ```
Lastly, there are a few macros available to help in passing ```ox::Error```s Lastly, there are a few macros available to help in passing ```ox::Error```s
back up the call stack, ```oxReturnError```, ```oxThrowError```, and back up the call stack, ```OX_RETURN_ERROR```, ```OX_THROW_ERROR```, and
```oxRequire```. ```OX_REQUIRE```.
```oxReturnError``` is by far the more helpful of the two. ```OX_RETURN_ERROR``` is by far the more helpful of the two.
```oxReturnError``` will return an ```ox::Error``` if it is not 0 and ```OX_RETURN_ERROR``` will return an ```ox::Error``` if it is not 0 and
```oxThrowError``` will throw an ```ox::Error``` if it is not 0. ```OX_THROW_ERROR``` will throw an ```ox::Error``` if it is not 0.
Since ```ox::Error``` is always nodiscard, you must do something with them. Since ```ox::Error``` is always nodiscard, you must do something with them.
In rare cases, you may not have anything you can do with them or you may know In rare cases, you may not have anything you can do with them or you may know
@ -113,13 +113,13 @@ This should be used sparingly.
```cpp ```cpp
void studioCode() { void studioCode() {
auto [val, err] = foo(1); auto [val, err] = foo(1);
oxThrowError(err); OX_THROW_ERROR(err);
doStuff(val); doStuff(val);
} }
ox::Error engineCode() noexcept { ox::Error engineCode() noexcept {
auto [val, err] = foo(1); auto [val, err] = foo(1);
oxReturnError(err); OX_RETURN_ERROR(err);
doStuff(val); doStuff(val);
return {}; return {};
} }
@ -136,19 +136,19 @@ Both macros will also take the ```ox::Result``` directly:
```cpp ```cpp
void studioCode() { void studioCode() {
auto valerr = foo(1); auto valerr = foo(1);
oxThrowError(valerr); OX_THROW_ERROR(valerr);
doStuff(valerr.value); doStuff(valerr.value);
} }
ox::Error engineCode() noexcept { ox::Error engineCode() noexcept {
auto valerr = foo(1); auto valerr = foo(1);
oxReturnError(valerr); OX_RETURN_ERROR(valerr);
doStuff(valerr.value); doStuff(valerr.value);
return {}; return {};
} }
``` ```
Ox also has the ```oxRequire``` macro, which will initialize a value if there is no error, and return if there is. Ox also has the ```OX_REQUIRE``` macro, which will initialize a value if there is no error, and return if there is.
It aims to somewhat emulate the ```?``` operator in Rust and Swift. It aims to somewhat emulate the ```?``` operator in Rust and Swift.
Rust ```?``` operator: Rust ```?``` operator:
@ -163,27 +163,23 @@ fn f2() -> Result<i32, i32> {
} }
``` ```
```oxRequire```: ```OX_REQUIRE```:
```cpp ```cpp
ox::Result<int> f() noexcept { ox::Result<int> f() noexcept {
// do stuff // do stuff
} }
ox::Result<int> f2() noexcept { ox::Result<int> f2() noexcept {
oxRequire(i, f()); // const auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxReturnError(oxConcat(oxRequire_err_, __LINE__)) OX_REQUIRE(i, f()); // const auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__))
return i + 4; return i + 4;
} }
``` ```
```oxRequire``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code. ```OX_REQUIRE``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code.
```oxRequire``` also has variants for throwing the error and for making to value non-const: ```OX_REQUIRE``` by default creates a const, but there is also an ```OX_REQUIRE_M``` (OX_REQUIRE Mutable)
variant for creating a non-const value.
* ```oxRequireM``` - oxRequire Mutable * ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
* ```oxRequireT``` - oxRequire Throw
* ```oxRequireMT``` - oxRequire Mutable Throw
The throw variants of ```oxRequire``` are generally legacy code.
```ox::Result::unwrapThrow``` is generally preferred now.
### Logging and Output ### Logging and Output
@ -207,7 +203,7 @@ never be checked in.
```oxError``` always prints. ```oxError``` always prints.
It includes file and line, and is prefixed with a red "ERROR:". It includes file and line, and is prefixed with a red "ERROR:".
It should generally be used conservatively. It should generally be used conservatively.
It shuld be used only when there is an error that is not technically fatal, but It should be used only when there is an error that is not technically fatal, but
the user almost certainly wants to know about it. the user almost certainly wants to know about it.
```oxTrace``` and ```oxTracef```: ```oxTrace``` and ```oxTracef```:
@ -272,19 +268,19 @@ constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaPalette> auto *pal) n
h->template setTypeInfo<NostalgiaPalette>(); h->template setTypeInfo<NostalgiaPalette>();
// it is also possible to provide the type name and type version as function arguments // it is also possible to provide the type name and type version as function arguments
//h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1); //h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1);
oxReturnError(h->field("colors", &pal->colors)); OX_RETURN_ERROR(h->field("colors", &pal->colors));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept { constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept {
h->template setTypeInfo<NostalgiaGraphic>(); h->template setTypeInfo<NostalgiaGraphic>();
oxReturnError(h->field("bpp", &ng->bpp)); OX_RETURN_ERROR(h->field("bpp", &ng->bpp));
oxReturnError(h->field("rows", &ng->rows)); OX_RETURN_ERROR(h->field("rows", &ng->rows));
oxReturnError(h->field("columns", &ng->columns)); OX_RETURN_ERROR(h->field("columns", &ng->columns));
oxReturnError(h->field("defaultPalette", &ng->defaultPalette)); OX_RETURN_ERROR(h->field("defaultPalette", &ng->defaultPalette));
oxReturnError(h->field("pal", &ng->pal)); OX_RETURN_ERROR(h->field("pal", &ng->pal));
oxReturnError(h->field("pixels", &ng->pixels)); OX_RETURN_ERROR(h->field("pixels", &ng->pixels));
return {}; return {};
} }
``` ```
@ -319,9 +315,9 @@ class FileAddress {
template<typename T> template<typename T>
constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept { constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
h->template setTypeInfo<FileAddress::Data>(); h->template setTypeInfo<FileAddress::Data>();
oxReturnError(h->fieldCString("path", &obj->path)); OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path)); OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode)); OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {}; return {};
} }
@ -331,13 +327,13 @@ constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept {
// cannot read from object in Reflect operation // cannot read from object in Reflect operation
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
int8_t type = 0; int8_t type = 0;
oxReturnError(io->field("type", &type)); OX_RETURN_ERROR(io->field("type", &type));
oxReturnError(io->field("data", UnionView(&fa->m_data, 0))); OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, 0)));
} else { } else {
auto type = static_cast<int8_t>(fa->m_type); auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(io->field("type", &type)); OX_RETURN_ERROR(io->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type); fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} }
return {}; return {};
} }
@ -347,13 +343,13 @@ constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept {
There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models: There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models:
```cpp ```cpp
oxModelBegin(NostalgiaGraphic) OX_MODEL_BEGIN(NostalgiaGraphic)
oxModelField(bpp) OX_MODEL_FIELD(bpp)
oxModelField(rows) OX_MODEL_FIELD(rows)
oxModelField(columns) OX_MODEL_FIELD(columns)
oxModelField(defaultPalette) OX_MODEL_FIELD(defaultPalette)
oxModelField(pal) OX_MODEL_FIELD(pal)
oxModelField(pixels) OX_MODEL_FIELD(pixels)
oxModelEnd() oxModelEnd()
``` ```
@ -396,7 +392,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readMC(buff, pal)); OX_RETURN_ERROR(ox::readMC(buff, pal));
return pal; return pal;
} }
``` ```
@ -409,7 +405,7 @@ ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB); ox::Buffer buffer(ox::units::MB);
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(buffer.data(), buffer.size(), pal, &sz)); OX_RETURN_ERROR(ox::writeMC(buffer.data(), buffer.size(), pal, &sz));
buffer.resize(sz); buffer.resize(sz);
return buffer; return buffer;
} }
@ -432,7 +428,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readOC(buff, &pal)); OX_RETURN_ERROR(ox::readOC(buff, &pal));
return pal; return pal;
} }
``` ```
@ -444,7 +440,7 @@ ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB); ox::Buffer buffer(ox::units::MB);
oxReturnError(ox::writeOC(buffer.data(), buffer.size(), pal)); OX_RETURN_ERROR(ox::writeOC(buffer.data(), buffer.size(), pal));
return buffer; return buffer;
} }
@ -466,7 +462,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readClaw(buff, pal)); OX_RETURN_ERROR(ox::readClaw(buff, pal));
return pal; return pal;
} }
``` ```

View File

@ -1,4 +1,9 @@
cmake_minimum_required(VERSION 3.10)
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# enable warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage")
endif()
add_library( add_library(
OxClArgs OxClArgs

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -11,16 +11,18 @@
namespace ox { namespace ox {
ClArgs::ClArgs(int argc, const char **args) noexcept { ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<size_t>(argc)}) {}
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
auto arg = String(args[i]); ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]);
if (arg[0] == '-') { if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) { while (arg[0] == '-' && arg.len()) {
arg = arg.substr(1); arg = substr(arg, 1);
} }
m_bools[arg] = true; m_bools[arg] = true;
// parse additional arguments // parse additional arguments
if (i < static_cast<unsigned>(argc) && args[i + 1]) { if (i < args.size() && args[i + 1]) {
auto val = String(args[i + 1]); auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') { if (val.len() && val[i] != '-') {
if (val == "false") { if (val == "false") {
@ -53,17 +55,17 @@ int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
} }
Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept { Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_bools.at(arg)); OX_REQUIRE(out, m_bools.at(arg));
return *out; return *out;
} }
Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept { Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept {
oxRequire(out, m_strings.at(argName)); OX_REQUIRE(out, m_strings.at(argName));
return *out; return *out;
} }
Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept { Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_ints.at(arg)); OX_REQUIRE(out, m_ints.at(arg));
return *out; return *out;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,6 +9,7 @@
#pragma once #pragma once
#include <ox/std/hashmap.hpp> #include <ox/std/hashmap.hpp>
#include <ox/std/span.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
namespace ox { namespace ox {
@ -22,6 +23,8 @@ class ClArgs {
public: public:
ClArgs(int argc, const char **args) noexcept; ClArgs(int argc, const char **args) noexcept;
ClArgs(ox::SpanView<const char*> args) noexcept;
[[nodiscard]] [[nodiscard]]
bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept; bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -18,7 +18,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
size_t outSz{}; size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1; auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
buffRaw += fmtSz; buffRaw += fmtSz;
@ -26,7 +26,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += fmtSz; outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1; auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
buffRaw += s2Size; buffRaw += s2Size;
@ -34,7 +34,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += s2Size; outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1; auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
buffRaw += s3Size; buffRaw += s3Size;
@ -48,7 +48,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffLen = buff.size(); auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw); auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
StringView const fmt(buffRaw, s1Size); StringView const fmt(buffRaw, s1Size);
@ -57,7 +57,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw); auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
StringView const typeName(buffRaw, s2Size); StringView const typeName(buffRaw, s2Size);
@ -66,7 +66,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s3End = ox::strchr(buffRaw, ';', buffLen); auto const s3End = ox::strchr(buffRaw, ';', buffLen);
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
StringView const versionStr(buffRaw, s3Size); StringView const versionStr(buffRaw, s3Size);
@ -78,7 +78,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} else if (fmt == "O1") { } else if (fmt == "O1") {
hdr.fmt = ClawFormat::Organic; hdr.fmt = ClawFormat::Organic;
} else { } else {
return OxError(4, "Claw format does not match any supported format/version combo"); return ox::Error(4, "Claw format does not match any supported format/version combo");
} }
hdr.typeName = typeName; hdr.typeName = typeName;
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion); std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
@ -88,26 +88,26 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} }
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept { Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
return {{header.data, header.dataSize}}; return {{header.data, header.dataSize}};
} }
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept { Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
auto const [t, tdErr] = ts.getLoad( auto const [t, tdErr] = ts.getLoad(
header.typeName, header.typeVersion, header.typeParams); header.typeName, header.typeVersion, header.typeParams);
if (tdErr) { if (tdErr) {
return OxError(3, "Could not load type descriptor"); return ox::Error(3, "Could not load type descriptor");
} }
ModelObject obj; ModelObject obj;
oxReturnError(obj.setType(t)); OX_RETURN_ERROR(obj.setType(t));
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
{ {
ox::BufferReader br({header.data, header.dataSize}); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
} }
case ClawFormat::Organic: case ClawFormat::Organic:
@ -115,16 +115,16 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader({header.data, header.dataSize}); OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
#else #else
break; break;
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -40,12 +40,12 @@ Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
template<typename T> template<typename T>
Error readClaw(ox::BufferView buff, T &val) { Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
if (header.typeName != getModelTypeName<T>()) { if (header.typeName != getModelTypeName<T>()) {
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); return ox::Error(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
} }
if (header.typeVersion != getModelTypeVersion<T>()) { if (header.typeVersion != getModelTypeVersion<T>()) {
return OxError(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch"); return ox::Error(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch");
} }
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
@ -65,15 +65,15 @@ Error readClaw(ox::BufferView buff, T &val) {
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
Result<T> readClaw(ox::BufferView buff) { Result<T> readClaw(ox::BufferView buff) {
Result<T> val; Result<T> val;
oxReturnError(readClaw(buff, val.value)); OX_RETURN_ERROR(readClaw(buff, val.value));
return val; return val;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -62,45 +62,45 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
int unionIdx = 0; int unionIdx = 0;
if constexpr(T::opType() != ox::OpType::Reflect) { if constexpr(T::opType() != ox::OpType::Reflect) {
unionIdx = obj->unionIdx; unionIdx = obj->unionIdx;
} }
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
static std::map<ox::StringView, ox::Error(*)()> tests = { static std::map<ox::StringView, ox::Error(*)()> tests = {
@ -114,7 +114,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
oxAssert(ch.typeVersion == 2, "Type version wrong"); oxAssert(ch.typeVersion == 2, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -126,7 +126,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
oxAssert(ch.typeVersion == 3, "Type version wrong"); oxAssert(ch.typeVersion == 3, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -134,7 +134,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3"); constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1})); OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
oxExpect(actual, expected); oxExpect(actual, expected);
return ox::Error{}; return ox::Error{};
} }
@ -145,8 +145,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
// This test doesn't confirm much, but it does show that the writer // This test doesn't confirm much, but it does show that the writer
// doesn't segfault // doesn't segfault
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal)); OX_RETURN_ERROR(ox::writeClaw(ts, ox::ClawFormat::Metal));
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -191,7 +191,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -39,7 +39,7 @@ struct TypeInfoCatcher {
} }
constexpr Error field(...) noexcept { constexpr Error field(...) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() { static constexpr auto opType() {
@ -76,21 +76,21 @@ template<typename T>
ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept { ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept {
switch (fmt) { switch (fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
oxReturnError(write(writer, "M2;")); OX_RETURN_ERROR(write(writer, "M2;"));
break; break;
case ClawFormat::Organic: case ClawFormat::Organic:
oxReturnError(write(writer, "O1;")); OX_RETURN_ERROR(write(writer, "O1;"));
break; break;
default: default:
return OxError(1); return ox::Error(1);
} }
oxReturnError(write(writer, detail::getTypeName(t))); OX_RETURN_ERROR(write(writer, detail::getTypeName(t)));
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
const auto tn = detail::getTypeVersion(t); const auto tn = detail::getTypeVersion(t);
if (tn > -1) { if (tn > -1) {
oxReturnError(ox::writeItoa(tn, writer)); OX_RETURN_ERROR(ox::writeItoa(tn, writer));
} }
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
return {}; return {};
} }
@ -102,19 +102,19 @@ Result<Buffer> writeClaw(
std::size_t buffReserveSz = 2 * units::KB) noexcept { std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer out(buffReserveSz); Buffer out(buffReserveSz);
BufferWriter bw(&out, 0); BufferWriter bw(&out, 0);
oxReturnError(detail::writeClawHeader(bw, &t, fmt)); OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt));
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
if (fmt == ClawFormat::Metal) { if (fmt == ClawFormat::Metal) {
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
} else if (fmt == ClawFormat::Organic) { } else if (fmt == ClawFormat::Organic) {
oxRequire(data, writeOC(t)); OX_REQUIRE(data, writeOC(t));
oxReturnError(bw.write(data.data(), data.size())); OX_RETURN_ERROR(bw.write(data.data(), data.size()));
} }
#else #else
if (fmt != ClawFormat::Metal) { if (fmt != ClawFormat::Metal) {
return OxError(1, "OC is not supported in this build"); return ox::Error(1, "OC is not supported in this build");
} }
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
#endif #endif
out.resize(bw.tellp()); out.resize(bw.tellp());
return out; return out;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -57,7 +57,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype(f(args...))>::value) { if constexpr(detail::isError<decltype(f(args...))>::value) {
oxThrowError(f(args...)); OX_THROW_ERROR(f(args...));
} else { } else {
f(args...); f(args...);
} }
@ -76,7 +76,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
f(args...); f(args...);
} }
@ -107,7 +107,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
(m_receiver->*(m_methodPtr))(args...); (m_receiver->*(m_methodPtr))(args...);
} }
@ -193,11 +193,11 @@ Error Signal<Args...>::disconnectObject(const void *receiver) const noexcept {
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@ -213,7 +213,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
f->call(args...); f->call(args...);
} }
return OxError(0); return ox::Error(0);
} catch (const ox::Exception &ex) { } catch (const ox::Exception &ex) {
return ox::Error(ex.file, ex.line, ex.errCode, ex.msg); return ox::Error(ex.file, ex.line, ex.errCode, ex.msg);
} }
@ -381,11 +381,11 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@ -398,9 +398,9 @@ void Signal<Error(Args...)>::emit(Args... args) const noexcept {
template<class... Args> template<class... Args>
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept { Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
oxReturnError(f->call(ox::forward<Args>(args)...)); OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
} }
return OxError(0); return ox::Error(0);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -17,7 +17,7 @@ struct TestStruct: public ox::SignalHandler {
int value = 0; int value = 0;
ox::Error method(int i) noexcept { ox::Error method(int i) noexcept {
value = i; value = i;
return OxError(0); return ox::Error(0);
} }
}; };
@ -27,13 +27,13 @@ std::map<ox::StringView, std::function<ox::Error()>> tests = {
[] { [] {
ox::Signal<ox::Error(int)> signal; ox::Signal<ox::Error(int)> signal;
signal.connect([](int i) -> ox::Error { signal.connect([](int i) -> ox::Error {
return OxError(i != 5); return ox::Error(i != 5);
}); });
TestStruct ts; TestStruct ts;
signal.connect(&ts, &TestStruct::method); signal.connect(&ts, &TestStruct::method);
oxReturnError(signal.emitCheckError(5)); OX_RETURN_ERROR(signal.emitCheckError(5));
oxReturnError(OxError(ts.value != 5)); OX_RETURN_ERROR(ox::Error(ts.value != 5));
return OxError(0); return ox::Error(0);
} }
}, },
}; };

View File

@ -1,3 +1,7 @@
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# enable warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage")
endif()
add_library( add_library(
OxFS OxFS

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -10,6 +10,8 @@
#include <ox/fs/ptrarith/nodebuffer.hpp> #include <ox/fs/ptrarith/nodebuffer.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
using InodeId_t = uint64_t; using InodeId_t = uint64_t;
@ -205,12 +207,12 @@ Error FileStoreTemplate<size_t>::format(void *buffer, std::size_t bufferSize) {
auto fsData = nb->malloc(sizeof(FileStoreData)).value; auto fsData = nb->malloc(sizeof(FileStoreData)).value;
if (!fsData.valid()) { if (!fsData.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
auto data = nb->template dataOf<FileStoreData>(fsData); auto data = nb->template dataOf<FileStoreData>(fsData);
if (!data.valid()) { if (!data.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
new (data) FileStoreData; new (data) FileStoreData;
return {}; return {};
@ -221,24 +223,24 @@ Error FileStoreTemplate<size_t>::setSize(std::size_t size) {
if (m_buffSize >= size) { if (m_buffSize >= size) {
return m_buffer->setSize(static_cast<size_t>(size)); return m_buffer->setSize(static_cast<size_t>(size));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) { Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
++item->links; ++item->links;
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::decLinks(uint64_t id) { Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
--item->links; --item->links;
if (item->links == 0) { if (item->links == 0) {
oxReturnError(remove(item)); OX_RETURN_ERROR(remove(item));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
@ -247,7 +249,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id); oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id);
auto existing = find(id); auto existing = find(id);
if (!canWrite(existing, dataSize)) { if (!canWrite(existing, dataSize)) {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
existing = find(id); existing = find(id);
} }
@ -267,7 +269,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
// if first malloc failed, compact and try again // if first malloc failed, compact and try again
if (!dest.valid()) { if (!dest.valid()) {
oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting"); oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting");
oxReturnError(compact()); OX_RETURN_ERROR(compact());
dest = m_buffer->malloc(dataSize).value; dest = m_buffer->malloc(dataSize).value;
} }
if (dest.valid()) { if (dest.valid()) {
@ -296,16 +298,16 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
dest->id.get(), dest.offset(), destData.size()); dest->id.get(), dest.offset(), destData.size());
fsData->rootNode = dest.offset(); fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return OxError(0); return ox::Error(0);
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
} }
} }
} }
oxReturnError(m_buffer->free(dest)); OX_RETURN_ERROR(m_buffer->free(dest));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
@ -320,7 +322,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1, "Could not find requested item"); return ox::Error(1, "Could not find requested item");
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -333,7 +335,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), outSize); "Item data section size: {}, Expected size: {}", srcData.size(), outSize);
return OxError(1, "Invalid inode"); return ox::Error(1, "Invalid inode");
} }
ox::memcpy(out, srcData, srcData.size()); ox::memcpy(out, srcData, srcData.size());
@ -351,7 +353,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -364,7 +366,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@ -384,7 +386,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -397,7 +399,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@ -420,30 +422,30 @@ ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(uint64_t id)
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize() { Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
const auto newSize = static_cast<std::size_t>(size() - available()); const auto newSize = static_cast<std::size_t>(size() - available());
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
oxReturnError(m_buffer->setSize(newSize)); OX_RETURN_ERROR(m_buffer->setSize(newSize));
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) { if (m_buffer->size() > size) {
return OxError(1); return ox::Error(1);
} }
m_buffSize = static_cast<size_t>(size); m_buffSize = static_cast<size_t>(size);
if (newBuff) { if (newBuff) {
m_buffer = reinterpret_cast<Buffer*>(newBuff); m_buffer = reinterpret_cast<Buffer*>(newBuff);
oxReturnError(m_buffer->setSize(static_cast<size_t>(size))); OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const { Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const {
oxRequire(inode, find(static_cast<size_t>(id)).validate()); OX_REQUIRE(inode, find(static_cast<size_t>(id)).validate());
return StatInfo { return StatInfo {
id, id,
inode->links, inode->links,
@ -475,16 +477,16 @@ char *FileStoreTemplate<size_t>::buff() {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) { for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
oxReturnError(cb(i->fileType, i.ptr().offset(), i.ptr().end())); OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() { Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
for (auto i = 0; i < 100; i++) { for (auto i = 0; i < 100; i++) {
auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>); auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>);
@ -492,7 +494,7 @@ Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>:
return inode; return inode;
} }
} }
return OxError(2); return ox::Error(2);
} }
template<typename size_t> template<typename size_t>
@ -501,10 +503,10 @@ Error FileStoreTemplate<size_t>::compact() {
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
if (isFirstItem) { if (isFirstItem) {
isFirstItem = false; isFirstItem = false;
return OxError(0); return ox::Error(0);
} }
if (!item.valid()) { if (!item.valid()) {
return OxError(1); return ox::Error(1);
} }
oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset()); oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset());
// update rootInode if this is it // update rootInode if this is it
@ -522,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
parent->right = item; parent->right = item;
} }
} }
return OxError(0); return ox::Error(0);
}); });
} }
@ -542,15 +544,15 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
fsData->rootNode = item; fsData->rootNode = item;
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(root, item); return placeItem(root, item);
} }
@ -560,7 +562,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth > 5000) { if (depth > 5000) {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(2); return ox::Error(2);
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@ -571,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = right->right; item->right = right->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(right, item, depth + 1); return placeItem(right, item, depth + 1);
} }
@ -584,13 +586,13 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = left->right; item->right = left->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(left, item, depth + 1); return placeItem(left, item, depth + 1);
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself.");
return OxError(1, "Cannot insert an item on itself."); return ox::Error(1, "Cannot insert an item on itself.");
} }
} }
@ -598,9 +600,9 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
@ -622,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else { } else {
fsData->rootNode = 0; fsData->rootNode = 0;
} }
return OxError(0); return ox::Error(0);
} else { } else {
return unplaceItem(root, item); return unplaceItem(root, item);
} }
@ -632,7 +634,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth >= 5000) { if (depth >= 5000) {
oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(1, "Excessive recursion depth, stopping before stack overflow."); return ox::Error(1, "Excessive recursion depth, stopping before stack overflow.");
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@ -651,25 +653,25 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
return unplaceItem(left, item, depth + 1); return unplaceItem(left, item, depth + 1);
} }
} else { } else {
return OxError(1); return ox::Error(1);
} }
if (item->right) { if (item->right) {
oxReturnError(placeItem(m_buffer->ptr(item->right))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->right)));
} }
if (item->left) { if (item->left) {
oxReturnError(placeItem(m_buffer->ptr(item->left))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::remove(ItemPtr item) { Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) { if (item.valid()) {
oxReturnError(unplaceItem(item)); OX_RETURN_ERROR(unplaceItem(item));
oxReturnError(m_buffer->free(item)); OX_RETURN_ERROR(m_buffer->free(item));
return OxError(0); return ox::Error(0);
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
@ -771,3 +773,5 @@ using FileStore16 = FileStoreTemplate<uint16_t>;
using FileStore32 = FileStoreTemplate<uint32_t>; using FileStore32 = FileStoreTemplate<uint32_t>;
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -15,6 +15,8 @@
#include "types.hpp" #include "types.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename InodeId_t> template<typename InodeId_t>
@ -53,7 +55,7 @@ struct OX_PACKED DirectoryEntry {
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len())); ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
return {}; return {};
} }
return OxError(1); return ox::Error(1);
} }
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept { ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
@ -139,11 +141,11 @@ template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::init() noexcept { Error Directory<FileStore, InodeId_t>::init() noexcept {
constexpr auto Size = sizeof(Buffer); constexpr auto Size = sizeof(Buffer);
oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId); oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId);
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory))); OX_RETURN_ERROR(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory)));
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
m_size = 0; m_size = 0;
return OxError(1); return ox::Error(1);
} }
new (buff) Buffer(Size); new (buff) Buffer(Size);
m_size = Size; m_size = Size;
@ -156,21 +158,21 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
oxTrace("ox.fs.Directory.mkdir", path.fullPath()); oxTrace("ox.fs.Directory.mkdir", path.fullPath());
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
auto childInode = find(PathIterator(name)); auto childInode = find(PathIterator(name));
if (!childInode.ok()) { if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled, // if this is not the last item in the path and parents is disabled,
// return an error // return an error
if (!parents && path.hasNext()) { if (!parents && path.hasNext()) {
return OxError(1); return ox::Error(1);
} }
childInode = m_fs.generateInodeId(); childInode = m_fs.generateInodeId();
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value); oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
oxLogError(childInode.error); oxLogError(childInode.error);
oxReturnError(childInode.error); OX_RETURN_ERROR(childInode.error);
// initialize the directory // initialize the directory
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
oxReturnError(child.init()); OX_RETURN_ERROR(child.init());
auto err = write(PathIterator(name), childInode.value); auto err = write(PathIterator(name), childInode.value);
if (err) { if (err) {
oxLogError(err); oxLogError(err);
@ -181,7 +183,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
} }
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
if (path.hasNext()) { if (path.hasNext()) {
oxReturnError(child.mkdir(path.next(), parents)); OX_RETURN_ERROR(child.mkdir(path.next(), parents));
} }
} }
return {}; return {};
@ -194,28 +196,28 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
if (path.next().hasNext()) { // not yet at target directory, recurse to next one if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}", oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
name, path.fullPath()); name, path.fullPath());
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(nextChild, findEntry(name)); OX_REQUIRE(nextChild, findEntry(name));
oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild); oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild);
if (nextChild) { if (nextChild) {
return Directory(m_fs, nextChild).write(path.next(), inode); return Directory(m_fs, nextChild).write(path.next(), inode);
} else { } else {
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name); oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name);
return OxError(1, "File not found and not allowed to create it."); return ox::Error(1, "File not found and not allowed to create it.");
} }
} else { } else {
oxTrace("ox.fs.Directory.write", path.fullPath()); oxTrace("ox.fs.Directory.write", path.fullPath());
oxReturnError(path.next(name)); OX_RETURN_ERROR(path.next(name));
// insert the new entry on this directory // insert the new entry on this directory
// get the name // get the name
// find existing version of directory // find existing version of directory
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId); oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
oxRequire(oldStat, m_fs.stat(m_inodeId)); OX_REQUIRE(oldStat, m_fs.stat(m_inodeId));
oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size); oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size);
auto old = m_fs.read(m_inodeId).template to<Buffer>(); auto old = m_fs.read(m_inodeId).template to<Buffer>();
if (!old.valid()) { if (!old.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
return OxError(1, "Could not read existing version of Directory"); return ox::Error(1, "Could not read existing version of Directory");
} }
const auto pathSize = name.len() + 1; const auto pathSize = name.len() + 1;
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize); const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
@ -223,16 +225,16 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size); auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
if (cpy == nullptr) { if (cpy == nullptr) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
return OxError(1, "Could not allocate memory for copy of Directory"); return ox::Error(1, "Could not allocate memory for copy of Directory");
} }
oxReturnError(cpy->setSize(newSize)); OX_RETURN_ERROR(cpy->setSize(newSize));
auto val = cpy->malloc(entryDataSize).value; auto val = cpy->malloc(entryDataSize).value;
if (!val.valid()) { if (!val.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
return OxError(1, "Could not allocate memory for new directory entry"); return ox::Error(1, "Could not allocate memory for new directory entry");
} }
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name); oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name);
oxReturnError(val->init(inode, name, val.size())); OX_RETURN_ERROR(val->init(inode, name, val.size()));
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory)); return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
} }
} }
@ -240,7 +242,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxTrace("ox.fs.Directory.remove", name); oxTrace("ox.fs.Directory.remove", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (buff.valid()) { if (buff.valid()) {
@ -249,7 +251,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
if (name == data->name) { if (name == data->name) {
oxReturnError(buff->free(i)); OX_RETURN_ERROR(buff->free(i));
} }
} else { } else {
oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
@ -257,7 +259,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
} }
} else { } else {
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer"); oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
return OxError(1, "Could not find directory buffer"); return ox::Error(1, "Could not find directory buffer");
} }
return {}; return {};
} }
@ -269,13 +271,13 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer"); oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
return OxError(1, "Could not directory buffer"); return ox::Error(1, "Could not directory buffer");
} }
oxTrace("ox.fs.Directory.ls", "Found directory buffer."); oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
oxReturnError(cb(data->name, data->inode)); OX_RETURN_ERROR(cb(data->name, data->inode));
} else { } else {
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
} }
@ -289,7 +291,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer"); oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer");
return OxError(2, "Could not findEntry directory buffer"); return ox::Error(2, "Could not findEntry directory buffer");
} }
oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size()); oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size());
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
@ -305,15 +307,15 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
} }
} }
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present"); oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
return OxError(1, "Entry not present"); return ox::Error(1, "Entry not present");
} }
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept { Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept {
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(v, findEntry(name)); OX_REQUIRE(v, findEntry(name));
// recurse if not at end of path // recurse if not at end of path
if (auto p = path.next(); p.valid()) { if (auto p = path.next(); p.valid()) {
Directory dir(m_fs, v); Directory dir(m_fs, v);
@ -333,3 +335,5 @@ using Directory16 = Directory<FileStore16, uint16_t>;
using Directory32 = Directory<FileStore32, uint32_t>; using Directory32 = Directory<FileStore32, uint32_t>;
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -32,7 +32,9 @@ FileAddress::FileAddress(ox::StringViewCR path) noexcept {
auto pathSize = path.bytes(); auto pathSize = path.bytes();
m_data.path = new char[pathSize + 1]; m_data.path = new char[pathSize + 1];
memcpy(m_data.path, path.data(), pathSize); memcpy(m_data.path, path.data(), pathSize);
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
m_data.path[pathSize] = 0; m_data.path[pathSize] = 0;
OX_CLANG_NOWARN_END
m_type = FileAddressType::Path; m_type = FileAddressType::Path;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -13,6 +13,8 @@
#include <ox/model/typenamecatcher.hpp> #include <ox/model/typenamecatcher.hpp>
#include <ox/model/types.hpp> #include <ox/model/types.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
enum class FileAddressType: int8_t { enum class FileAddressType: int8_t {
@ -87,7 +89,7 @@ class FileAddress {
case FileAddressType::Inode: case FileAddressType::Inode:
return m_data.inode; return m_data.inode;
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -98,7 +100,7 @@ class FileAddress {
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
return ox::CStringView(m_data.constPath); return ox::CStringView(m_data.constPath);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -152,31 +154,33 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept {
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress::Data>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress::Data>());
oxReturnError(h->fieldCString("path", &obj->path)); OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path)); OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode)); OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
int8_t type = -1; int8_t type = -1;
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, type))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, type)));
} else if constexpr(T::opType() == OpType::Read) { } else if constexpr(T::opType() == OpType::Read) {
auto type = static_cast<int8_t>(fa->m_type); auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type); fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto const type = static_cast<int8_t>(fa->m_type); auto const type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} }
return {}; return {};
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -21,7 +21,7 @@ Result<const char*> MemFS::directAccess(const FileAddress &addr) const noexcept
case FileAddressType::Path: case FileAddressType::Path:
return directAccess(StringView(addr.getPath().value)); return directAccess(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -33,21 +33,21 @@ Error FileSystem::read(const FileAddress &addr, void *buffer, std::size_t size)
case FileAddressType::Path: case FileAddressType::Path:
return readFilePath(StringView(addr.getPath().value), buffer, size); return readFilePath(StringView(addr.getPath().value), buffer, size);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept { Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept {
oxRequire(s, stat(addr)); OX_REQUIRE(s, stat(addr));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(read(addr, buff.data(), buff.size())); OX_RETURN_ERROR(read(addr, buff.data(), buff.size()));
return buff; return buff;
} }
Result<Buffer> FileSystem::read(StringViewCR path) noexcept { Result<Buffer> FileSystem::read(StringViewCR path) noexcept {
oxRequire(s, statPath(path)); OX_REQUIRE(s, statPath(path));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(readFilePath(path, buff.data(), buff.size())); OX_RETURN_ERROR(readFilePath(path, buff.data(), buff.size()));
return buff; return buff;
} }
@ -57,9 +57,9 @@ Error FileSystem::read(const FileAddress &addr, std::size_t readStart, std::size
return read(addr.getInode().value, readStart, readSize, buffer, size); return read(addr.getInode().value, readStart, readSize, buffer, size);
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
case FileAddressType::Path: case FileAddressType::Path:
return OxError(2, "Unsupported for path lookups"); return ox::Error(2, "Unsupported for path lookups");
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -71,7 +71,7 @@ Error FileSystem::remove(const FileAddress &addr, bool recursive) noexcept {
case FileAddressType::Path: case FileAddressType::Path:
return remove(StringView(addr.getPath().value), recursive); return remove(StringView(addr.getPath().value), recursive);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -83,7 +83,7 @@ Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t si
case FileAddressType::Path: case FileAddressType::Path:
return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType); return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -95,7 +95,7 @@ Result<FileStat> FileSystem::stat(const FileAddress &addr) const noexcept {
case FileAddressType::Path: case FileAddressType::Path:
return statPath(StringView(addr.getPath().value)); return statPath(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -284,69 +284,69 @@ FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept {
oxReturnError(FileStore::format(buff, static_cast<size_t>(buffSize))); OX_RETURN_ERROR(FileStore::format(buff, static_cast<size_t>(buffSize)));
FileStore fs(buff, static_cast<size_t>(buffSize)); FileStore fs(buff, static_cast<size_t>(buffSize));
constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2; constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2;
Directory rootDir(fs, rootDirInode); Directory rootDir(fs, rootDirInode);
oxReturnError(rootDir.init()); OX_RETURN_ERROR(rootDir.init());
FileSystemData fd; FileSystemData fd;
fd.rootDirInode = rootDirInode; fd.rootDirInode = rootDirInode;
oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get()); oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get());
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(fs.write(InodeFsData, &fd, sizeof(fd)));
if (!fs.read(fd.rootDirInode).valid()) { if (!fs.read(fd.rootDirInode).valid()) {
oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory"); oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept {
oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive); oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive);
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
return rootDir.mkdir(path, recursive); return rootDir.mkdir(path, recursive);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept { Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequireM(inode, rootDir.find(src)); OX_REQUIRE_M(inode, rootDir.find(src));
oxReturnError(rootDir.write(dest, inode)); OX_RETURN_ERROR(rootDir.write(dest, inode));
oxReturnError(rootDir.remove(src)); OX_RETURN_ERROR(rootDir.remove(src));
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
oxTrace("ox.fs.FileSystemTemplate.readFilePath", path); oxTrace("ox.fs.FileSystemTemplate.readFilePath", path);
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(s, stat(path)); OX_REQUIRE(s, stat(path));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept { Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
return directAccessInode(inode); return directAccessInode(inode);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode); oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode);
oxRequire(s, stat(inode)); OX_REQUIRE(s, stat(inode));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
@ -360,7 +360,7 @@ template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept { Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept {
auto data = m_fs.read(inode); auto data = m_fs.read(inode);
if (!data.valid()) { if (!data.valid()) {
return OxError(1, "Data not valid"); return ox::Error(1, "Data not valid");
} }
return reinterpret_cast<char*>(data.get()); return reinterpret_cast<char*>(data.get());
} }
@ -368,9 +368,9 @@ Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept { Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept {
Vector<String> out; Vector<String> out;
oxReturnError(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) { OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name); out.emplace_back(name);
return OxError(0); return ox::Error(0);
})); }));
return out; return out;
} }
@ -379,17 +379,17 @@ template<typename FileStore, typename Directory>
template<typename F> template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const { Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const {
oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path); oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
oxRequire(s, stat(path)); OX_REQUIRE(s, stat(path));
Directory dir(m_fs, s.inode); Directory dir(m_fs, s.inode);
return dir.ls(cb); return dir.ls(cb);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
oxRequire(st, statInode(inode)); OX_REQUIRE(st, statInode(inode));
if (st.fileType == FileType::NormalFile || recursive) { if (st.fileType == FileType::NormalFile || recursive) {
if (auto err = rootDir.remove(path)) { if (auto err = rootDir.remove(path)) {
// removal failed, try putting the index back // removal failed, try putting the index back
@ -398,9 +398,9 @@ Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool r
} }
} else { } else {
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
@ -410,7 +410,7 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept { Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer)); OX_RETURN_ERROR(m_fs.resize(static_cast<size_t>(size), buffer));
return {}; return {};
} }
@ -423,11 +423,11 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path); oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path);
auto [inode, err] = find(path); auto [inode, err] = find(path);
if (err) { if (err) {
oxReturnError(m_fs.generateInodeId().moveTo(inode)); OX_RETURN_ERROR(m_fs.generateInodeId().moveTo(inode));
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
oxReturnError(rootDir.write(path, inode)); OX_RETURN_ERROR(rootDir.write(path, inode));
} }
oxReturnError(writeFileInode(inode, buffer, size, fileType)); OX_RETURN_ERROR(writeFileInode(inode, buffer, size, fileType));
return {}; return {};
} }
@ -439,7 +439,7 @@ Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, c
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept {
oxRequire(s, m_fs.stat(inode)); OX_REQUIRE(s, m_fs.stat(inode));
FileStat out; FileStat out;
out.inode = s.inode; out.inode = s.inode;
out.links = s.links; out.links = s.links;
@ -450,7 +450,7 @@ Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t in
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept {
oxRequire(inode, find(path)); OX_REQUIRE(inode, find(path));
return stat(inode); return stat(inode);
} }
@ -487,25 +487,25 @@ bool FileSystemTemplate<FileStore, Directory>::valid() const noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept { Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept {
FileSystemData fd; FileSystemData fd;
oxReturnError(m_fs.read(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(m_fs.read(InodeFsData, &fd, sizeof(fd)));
return fd; return fd;
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept { Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
// return root as a special case // return root as a special case
if (path == "/") { if (path == "/") {
return static_cast<uint64_t>(fd.rootDirInode); return static_cast<uint64_t>(fd.rootDirInode);
} }
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(out, rootDir.find(path)); OX_REQUIRE(out, rootDir.find(path));
return static_cast<uint64_t>(out); return static_cast<uint64_t>(out);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept { Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
return Directory(m_fs, fd.rootDirInode); return Directory(m_fs, fd.rootDirInode);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directories(p, ec); success = std::filesystem::create_directories(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} else { } else {
std::error_code ec; std::error_code ec;
@ -48,26 +48,26 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directory(p, ec); success = std::filesystem::create_directory(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} }
return OxError(success ? 0 : 1); return ox::Error(success ? 0 : 1);
} }
Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept { Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
std::error_code ec; std::error_code ec;
std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec); std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec);
if (ec.value()) { if (ec.value()) {
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
Vector<String> out; Vector<String> out;
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (const auto &p : di) { for (const auto &p : di) {
const auto u8p = p.path().filename().u8string(); const auto u8p = p.path().filename().u8string();
out.emplace_back(reinterpret_cast<const char*>(u8p.c_str())); out.emplace_back(reinterpret_cast<const char*>(u8p.c_str()));
@ -77,20 +77,20 @@ Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept { Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept {
if (recursive) { if (recursive) {
return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0); return ox::Error(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
} else { } else {
return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0); return ox::Error(std::filesystem::remove(m_path / stripSlash(path)) != 0);
} }
} }
Error PassThroughFS::resize(uint64_t, void*) noexcept { Error PassThroughFS::resize(uint64_t, void*) noexcept {
// unsupported // unsupported
return OxError(1, "resize is not supported by PassThroughFS"); return ox::Error(1, "resize is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept { Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept {
// unsupported // unsupported
return OxError(1, "statInode(uint64_t) is not supported by PassThroughFS"); return ox::Error(1, "statInode(uint64_t) is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept { Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
@ -101,7 +101,7 @@ Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path); oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec); const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size); oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
return FileStat{0, 0, size, type}; return FileStat{0, 0, size, type};
} }
@ -112,14 +112,14 @@ uint64_t PassThroughFS::spaceNeeded(uint64_t size) const noexcept {
Result<uint64_t> PassThroughFS::available() const noexcept { Result<uint64_t> PassThroughFS::available() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.available; return s.available;
} }
Result<uint64_t> PassThroughFS::size() const noexcept { Result<uint64_t> PassThroughFS::size() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.capacity; return s.capacity;
} }
@ -128,7 +128,7 @@ char *PassThroughFS::buff() noexcept {
} }
Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept { Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept {
return OxError(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS"); return ox::Error(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS");
} }
bool PassThroughFS::valid() const noexcept { bool PassThroughFS::valid() const noexcept {
@ -147,24 +147,24 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
if (size > buffSize) { if (size > buffSize) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path); oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
return OxError(1); return ox::Error(1);
} }
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize)); file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return OxError(2); return ox::Error(2);
} }
return OxError(0); return ox::Error(0);
} }
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
// unsupported // unsupported
return OxError(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS"); return ox::Error(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS");
} }
Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept { Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept {
// unsupported // unsupported
return OxError(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS"); return ox::Error(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS");
} }
Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept { Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept {
@ -174,14 +174,14 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size)); f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
// unsupported // unsupported
return OxError(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS"); return ox::Error(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS");
} }
std::string_view PassThroughFS::stripSlash(StringView path) noexcept { std::string_view PassThroughFS::stripSlash(StringView path) noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -92,11 +92,11 @@ template<typename F>
Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept { Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (auto &p : di) { for (auto &p : di) {
oxReturnError(cb(p.path().filename().c_str(), 0)); OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
} }
return OxError(0); return ox::Error(0);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -11,6 +11,8 @@
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include "pathiterator.hpp" #include "pathiterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) { PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) {
@ -30,13 +32,13 @@ PathIterator::PathIterator(StringViewCR path): PathIterator(path.data(), path.by
*/ */
Error PathIterator::dirPath(char *out, std::size_t outSize) { Error PathIterator::dirPath(char *out, std::size_t outSize) {
const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize); const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
const auto size = static_cast<std::size_t>(idx + 1); const auto size = static_cast<std::size_t>(idx) + 1;
if (idx >= 0 && size < outSize) { if (idx >= 0 && size < outSize) {
ox::memcpy(out, m_path, size); ox::memcpy(out, m_path, size);
out[size] = 0; out[size] = 0;
return OxError(0); return ox::Error(0);
} else { } else {
return OxError(1); return ox::Error(1);
} }
} }
@ -45,11 +47,11 @@ Error PathIterator::get(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
if (m_iterator >= m_maxSize) { if (m_iterator >= m_maxSize) {
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize); oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
return OxError(1); return ox::Error(1);
} }
if (!ox::strlen(&m_path[m_iterator])) { if (!ox::strlen(&m_path[m_iterator])) {
oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])"); oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])");
return OxError(1); return ox::Error(1);
} }
auto start = m_iterator; auto start = m_iterator;
if (m_path[start] == '/') { if (m_path[start] == '/') {
@ -65,7 +67,7 @@ Error PathIterator::get(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength || size == 0) { if (size >= MaxFileNameLength || size == 0) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
@ -81,9 +83,9 @@ Error PathIterator::get(StringView &fileName) {
*/ */
Error PathIterator::next(StringView &fileName) { Error PathIterator::next(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = OxError(0); retval = ox::Error(0);
if (m_path[m_iterator] == '/') { if (m_path[m_iterator] == '/') {
m_iterator++; m_iterator++;
} }
@ -98,7 +100,7 @@ Error PathIterator::next(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength) { if (size >= MaxFileNameLength) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
@ -113,10 +115,10 @@ Error PathIterator::next(StringView &fileName) {
Result<std::size_t> PathIterator::nextSize() const { Result<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
auto it = m_iterator; auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) { if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = OxError(0); retval = ox::Error(0);
if (m_path[it] == '/') { if (m_path[it] == '/') {
it++; it++;
} }
@ -183,3 +185,5 @@ const char *PathIterator::fullPath() const {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -13,6 +13,8 @@
#include "ptr.hpp" #include "ptr.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith { namespace ox::ptrarith {
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -282,14 +284,14 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
addr = m_header.firstItem; addr = m_header.firstItem;
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state.");
return OxError(1, "NodeBuffer is in invalid state."); return ox::Error(1, "NodeBuffer is in invalid state.");
} }
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize); oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize);
auto out = ItemPtr(this, m_header.size, addr, fullSize); auto out = ItemPtr(this, m_header.size, addr, fullSize);
if (!out.valid()) { if (!out.valid()) {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown"); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown");
return OxError(1, "NodeBuffer::malloc: unknown failure"); return ox::Error(1, "NodeBuffer::malloc: unknown failure");
} }
ox::memset(out, 0, fullSize); ox::memset(out, 0, fullSize);
new (out) Item; new (out) Item;
@ -302,7 +304,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
first->prev = out.offset(); first->prev = out.offset();
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid first element pointer.");
} }
if (oldLast.valid()) { if (oldLast.valid()) {
@ -312,7 +314,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
if (out.offset() != first.offset()) { if (out.offset() != first.offset()) {
// if this is not the first allocation, there should be an oldLast // if this is not the first allocation, there should be an oldLast
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid last element pointer.");
} }
out->prev = out.offset(); out->prev = out.offset();
} }
@ -321,7 +323,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
return out; return out;
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available()); oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available());
return OxError(1); return ox::Error(1);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -344,15 +346,15 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} else { } else {
if (!prev.valid()) { if (!prev.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset());
return OxError(1); return ox::Error(1);
} }
if (!next.valid()) { if (!next.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset());
return OxError(1); return ox::Error(1);
} }
} }
m_header.bytesUsed -= item.size(); m_header.bytesUsed -= item.size();
return OxError(0); return ox::Error(0);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -363,12 +365,12 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end); oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end);
if (end > size) { if (end > size) {
// resizing to less than buffer size // resizing to less than buffer size
return OxError(1); return ox::Error(1);
} else { } else {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end; auto data = reinterpret_cast<uint8_t*>(this) + end;
ox::memset(data, 0, size - end); ox::memset(data, 0, size - end);
return OxError(0); return ox::Error(0);
} }
} }
@ -399,14 +401,14 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
auto dest = ptr(sizeof(*this)); auto dest = ptr(sizeof(*this));
while (dest.offset() <= src.offset()) { while (dest.offset() <= src.offset()) {
if (!src.valid()) { if (!src.valid()) {
return OxError(1); return ox::Error(1);
} }
if (!dest.valid()) { if (!dest.valid()) {
return OxError(2); return ox::Error(2);
} }
// move node // move node
ox::memcpy(dest, src, src->fullSize()); ox::memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest)); OX_RETURN_ERROR(cb(src, dest));
// update surrounding nodes // update surrounding nodes
auto prev = ptr(dest->prev); auto prev = ptr(dest->prev);
if (prev.valid()) { if (prev.valid()) {
@ -420,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
src = ptr(dest->next); src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize()); dest = uninitializedPtr(dest.offset() + dest->fullSize());
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -449,3 +451,5 @@ struct OX_PACKED Item {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -10,6 +10,8 @@
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith { namespace ox::ptrarith {
template<typename T, typename size_t, size_t minOffset = 1> template<typename T, typename size_t, size_t minOffset = 1>
@ -252,7 +254,9 @@ constexpr Result<Ptr<T, size_t, minOffset>> Ptr<T, size_t, minOffset>::validate(
if (valid()) { if (valid()) {
return *this; return *this;
} }
return OxError(1); return ox::Error(1);
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -52,7 +52,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(buffer->free(a1), "Free failed."); oxAssert(buffer->free(a1), "Free failed.");
oxAssert(buffer->free(a2), "Free failed."); oxAssert(buffer->free(a2), "Free failed.");
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed."); oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -64,7 +64,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -77,7 +77,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxExpect(buff, "usr"); oxExpect(buff, "usr");
oxAssert(it.next(buff), "PathIterator::next returned error"); oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "share"); oxExpect(buff, "share");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -87,7 +87,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -99,7 +99,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -110,7 +110,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -120,7 +120,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -130,7 +130,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path, ox::strlen(path)); ox::PathIterator it(path, ox::strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -142,7 +142,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto subPtr = p.subPtr<uint64_t>(50); auto subPtr = p.subPtr<uint64_t>(50);
oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid."); oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -155,7 +155,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto first = list->firstItem(); auto first = list->firstItem();
oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item"); oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item");
oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid"); oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -176,7 +176,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
size_t str1ReadSize = 0; size_t str1ReadSize = 0;
oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed."); oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -203,7 +203,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxTrace("ox.fs.test.Directory") << "write 3"; oxTrace("ox.fs.test.Directory") << "write 3";
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed"); oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -220,19 +220,20 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed"); oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
return OxError(0); return ox::Error(0);
} }
}, },
}, },
}; };
int main(int argc, const char **args) { int main(int argc, const char **argv) {
if (argc < 2) { if (argc < 2) {
oxError("Must specify test to run"); oxError("Must specify test to run");
return -1; return -1;
} }
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::StringView const testName = args[1]; ox::StringView const testName = args[1];
ox::StringView const testArg = args[2] ? args[2] : nullptr; ox::StringView const testArg = argc >= 3 ? args[2] : nullptr;
auto const func = tests.find(testName); auto const func = tests.find(testName);
if (func != tests.end()) { if (func != tests.end()) {
oxAssert(func->second(testArg), "Test returned Error"); oxAssert(func->second(testArg), "Test returned Error");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -20,7 +20,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
std::ifstream file(path, std::ios::binary | std::ios::ate); std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.good()) { if (!file.good()) {
oxErrorf("Could not find OxFS file: {}", path); oxErrorf("Could not find OxFS file: {}", path);
return OxError(1, "Could not find OxFS file"); return ox::Error(1, "Could not find OxFS file");
} }
try { try {
const auto size = static_cast<std::size_t>(file.tellg()); const auto size = static_cast<std::size_t>(file.tellg());
@ -30,51 +30,52 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
return Buff{buff, size}; return Buff{buff, size};
} catch (const std::ios_base::failure &e) { } catch (const std::ios_base::failure &e) {
oxErrorf("Could not read OxFS file: {}", e.what()); oxErrorf("Could not read OxFS file: {}", e.what());
return OxError(2, "Could not read OxFS file"); return ox::Error(2, "Could not read OxFS file");
} }
} }
static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept { static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept {
oxRequire(buff, loadFsBuff(path)); OX_REQUIRE(buff, loadFsBuff(path));
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
} }
static ox::Error runLs(ox::FileSystem *fs, int argc, const char **argv) noexcept { static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (argc < 2) { if (args.size() < 2) {
oxErr("Must provide a directory to ls\n"); oxErr("Must provide a directory to ls\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(files, fs->ls(argv[1])); OX_REQUIRE(files, fs->ls(args[1]));
for (const auto &file : files) { for (const auto &file : files) {
oxOutf("{}\n", file); oxOutf("{}\n", file);
} }
return OxError(0); return ox::Error(0);
} }
static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexcept { static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (argc < 2) { if (args.size() < 2) {
oxErr("Must provide a path to a file to read\n"); oxErr("Must provide a path to a file to read\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(buff, fs->read(ox::StringView(argv[1]))); OX_REQUIRE(buff, fs->read(ox::StringView(args[1])));
fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
return OxError(0); return ox::Error(0);
} }
static ox::Error run(int argc, const char **argv) noexcept { static ox::Error run(int argc, const char **argv) noexcept {
if (argc < 3) { if (argc < 3) {
oxErr("OxFS file and subcommand arguments are required\n"); oxErr("OxFS file and subcommand arguments are required\n");
return OxError(1); return ox::Error(1);
} }
const auto fsPath = argv[1]; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::String subCmd(argv[2]); auto const fsPath = args[1];
oxRequire(fs, loadFs(fsPath)); ox::String subCmd(args[2]);
OX_REQUIRE(fs, loadFs(fsPath));
if (subCmd == "ls") { if (subCmd == "ls") {
return runLs(fs.get(), argc - 2, argv + 2); return runLs(fs.get(), args + 2);
} else if (subCmd == "read") { } else if (subCmd == "read") {
return runRead(fs.get(), argc - 2, argv + 2); return runRead(fs.get(), args + 2);
} }
return OxError(1); return ox::Error(1);
} }
int main(int argc, const char **argv) { int main(int argc, const char **argv) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -34,7 +34,7 @@ class CirculerBuffer {
constexpr ox::Error put(char v) noexcept { constexpr ox::Error put(char v) noexcept {
return write(&v, 1); return write(&v, 1);
if (1 > avail()) { if (1 > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
m_buff[m_writePt] = v; m_buff[m_writePt] = v;
++m_writePt; ++m_writePt;
@ -43,8 +43,9 @@ class CirculerBuffer {
constexpr ox::Error write(const char *buff, std::size_t sz) noexcept { constexpr ox::Error write(const char *buff, std::size_t sz) noexcept {
if (sz > avail()) { if (sz > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// write seg 1 // write seg 1
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt); const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz); ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
@ -56,12 +57,13 @@ class CirculerBuffer {
ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz); ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
oxAssert(m_buff[0] == buff[seg1Sz], "break"); oxAssert(m_buff[0] == buff[seg1Sz], "break");
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} }
constexpr ox::Error seekp(std::size_t bytesFwd) noexcept { constexpr ox::Error seekp(std::size_t bytesFwd) noexcept {
if (bytesFwd > avail()) { if (bytesFwd > avail()) {
return OxError(1, "Insufficient space in buffer to seek that far ahead"); return ox::Error(1, "Insufficient space in buffer to seek that far ahead");
} }
m_writePt += bytesFwd; m_writePt += bytesFwd;
if (m_writePt > m_buff.size()) { if (m_writePt > m_buff.size()) {
@ -71,7 +73,7 @@ class CirculerBuffer {
} }
constexpr ox::Error seekp(int, ios_base::seekdir) noexcept { constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
return OxError(1, "Unimplemented"); return ox::Error(1, "Unimplemented");
} }
[[nodiscard]] [[nodiscard]]
@ -90,7 +92,9 @@ class CirculerBuffer {
m_readPt -= m_buff.size(); m_readPt -= m_buff.size();
// read seg 2 // read seg 2
const auto seg2Sz = bytesRead - seg1Sz; const auto seg2Sz = bytesRead - seg1Sz;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz); ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
OX_ALLOW_UNSAFE_BUFFERS_END
} }
return bytesRead; return bytesRead;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,8 +9,8 @@
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
#include <cstdio> #include <cstdio>
#include <sys/types.h>
#ifndef _WIN32 #ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -25,15 +25,22 @@
#include "logconn.hpp" #include "logconn.hpp"
#include <ox/std/bit.hpp>
namespace ox { namespace ox {
#ifdef _WIN32
using Socket = SOCKET;
using LenType = int;
#else
using Socket = int;
using LenType = size_t;
#endif
using namespace trace; using namespace trace;
void closeSock(auto s) noexcept { static void closeSock(auto s) noexcept {
#ifdef _WIN32 #ifdef _WIN32
closesocket(s); closesocket(static_cast<Socket>(s));
#else #else
close(s); close(s);
#endif #endif
@ -56,8 +63,8 @@ ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept {
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(5590); addr.sin_port = htons(5590);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(connect(static_cast<Socket>(m_socket), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
return sendInit({.appName = ox::BasicString<128>(appName)}); return sendInit({.appName = ox::BasicString<128>(appName)});
} }
@ -65,10 +72,10 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
std::size_t totalSent = 0; std::size_t totalSent = 0;
while (totalSent < len) { while (totalSent < len) {
//std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket); //std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket);
const auto sent = ::send(m_socket, buff, len, 0); const auto sent = ::send(static_cast<Socket>(m_socket), buff, static_cast<LenType>(len), 0);
if (sent < 0) { if (sent < 0) {
std::fprintf(stderr, "Could not send msg\n"); std::ignore = std::fprintf(stderr, "Could not send msg\n");
return OxError(1, "Could not send msg"); return ox::Error(1, "Could not send msg");
} }
totalSent += static_cast<std::size_t>(sent); totalSent += static_cast<std::size_t>(sent);
} }
@ -90,13 +97,14 @@ void LoggerConn::msgSend() noexcept {
if (!m_running) { if (!m_running) {
break; break;
} }
std::lock_guard buffLk(m_buffMut); std::lock_guard const buffLk(m_buffMut);
while (true) { while (true) {
ox::Array<char, ox::units::KB> tmp; Array<char, units::KB> tmp;
const auto read = m_buff.read(tmp.data(), tmp.size()); const auto read = m_buff.read(tmp.data(), tmp.size());
if (!read) { if (!read) {
break; break;
} }
oxAssert(read <= tmp.size(), "logger trying to read too much data");
//std::printf("LoggerConn: sending %lu bytes\n", read); //std::printf("LoggerConn: sending %lu bytes\n", read);
std::ignore = send(tmp.data(), read); std::ignore = send(tmp.data(), read);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -45,13 +45,13 @@ class LoggerConn: public trace::Logger {
ox::Error send(trace::MsgId msgId, const auto &msg) noexcept { ox::Error send(trace::MsgId msgId, const auto &msg) noexcept {
ox::Array<char, 10 * ox::units::KB> buff; ox::Array<char, 10 * ox::units::KB> buff;
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(&buff[0], buff.size(), msg, &sz)); OX_RETURN_ERROR(ox::writeMC(&buff[0], buff.size(), msg, &sz));
//std::printf("sz: %lu\n", sz); //std::printf("sz: %lu\n", sz);
oxRequire(szBuff, serialize(static_cast<uint32_t>(sz))); OX_REQUIRE(szBuff, serialize(static_cast<uint32_t>(sz)));
std::unique_lock buffLk(m_buffMut); std::unique_lock buffLk(m_buffMut);
oxReturnError(m_buff.put(static_cast<char>(msgId))); OX_RETURN_ERROR(m_buff.put(static_cast<char>(msgId)));
oxReturnError(m_buff.write(szBuff.data(), szBuff.size())); OX_RETURN_ERROR(m_buff.write(szBuff.data(), szBuff.size()));
oxReturnError(m_buff.write(buff.data(), sz)); OX_RETURN_ERROR(m_buff.write(buff.data(), sz));
buffLk.unlock(); buffLk.unlock();
m_waitCond.notify_one(); m_waitCond.notify_one();
return {}; return {};

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -57,7 +57,7 @@ static_assert(highestBit(uint64_t(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63); static_assert(highestBit(uint64_t(1) << 63) == 63);
struct McInt { struct McInt {
uint8_t data[9] = {}; ox::Array<uint8_t, 9> data{};
// length of integer in bytes // length of integer in bytes
std::size_t length = 0; std::size_t length = 0;
}; };
@ -104,7 +104,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
auto intermediate = auto intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
ox::memcpy(out.data, &intermediate, sizeof(intermediate)); ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate));
} }
out.length = bytes; out.length = bytes;
} }
@ -135,19 +135,19 @@ static_assert(countBytes(0b1111'1111) == 9);
template<typename I> template<typename I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept { constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
uint8_t firstByte = 0; uint8_t firstByte = 0;
oxReturnError(rdr.read(&firstByte, 1)); OX_RETURN_ERROR(rdr.read(&firstByte, 1));
oxReturnError(rdr.seekg(-1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte); const auto bytes = countBytes(firstByte);
if (bytes == 9) { if (bytes == 9) {
*bytesRead = bytes; *bytesRead = bytes;
I out = 0; I out = 0;
oxReturnError(rdr.seekg(1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
oxReturnError(rdr.read(&out, sizeof(I))); OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
return fromLittleEndian<I>(out); return fromLittleEndian<I>(out);
} }
*bytesRead = bytes; *bytesRead = bytes;
uint64_t decoded = 0; uint64_t decoded = 0;
oxReturnError(rdr.read(&decoded, bytes)); OX_RETURN_ERROR(rdr.read(&decoded, bytes));
decoded >>= bytes; decoded >>= bytes;
// move sign bit // move sign bit
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
@ -160,7 +160,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
ox::Array<uint32_t, 2> d = {}; ox::Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
ox::memcpy(d.data(), &decoded, sizeof(decoded)); ox::memcpy(&d[0], &decoded, sizeof(decoded));
auto bit = negBit; auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
d[0] |= 1 << bit; d[0] |= 1 << bit;
@ -175,7 +175,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
d[0] = d[1]; d[0] = d[1];
d[1] = d0Tmp; d[1] = d0Tmp;
} }
ox::memcpy(&out, d.data(), sizeof(out)); ox::memcpy(&out, &d[0], sizeof(out));
return out; return out;
} }
} }
@ -185,7 +185,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
template<typename I> template<typename I>
Result<I> decodeInteger(McInt m) noexcept { Result<I> decodeInteger(McInt m) noexcept {
std::size_t bytesRead{}; std::size_t bytesRead{};
BufferReader br({reinterpret_cast<const char*>(m.data), 9}); BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9});
return decodeInteger<I>(br, &bytesRead); return decodeInteger<I>(br, &bytesRead);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -47,7 +47,7 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
constexpr auto blockBits = sizeof(m_mapBlock); constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits; auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] { if (m_mapBlockIdx != blockIdx) [[unlikely]] {
oxReturnError(loadMapBlock(blockIdx)); OX_RETURN_ERROR(loadMapBlock(blockIdx));
} }
idx %= blockBits; idx %= blockBits;
return (m_mapBlock >> idx) & 1; return (m_mapBlock >> idx) & 1;
@ -55,12 +55,12 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
template<Reader_c Reader> template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept { constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{}; ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv // Warning: narrow-conv
oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0; m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) { for (auto i = 0ull; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i; m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
@ -110,7 +110,7 @@ constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexce
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1; return (m_map[i / 8] >> (i % 8)) & 1;
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }
@ -147,14 +147,16 @@ constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept { constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (on) { if (on) {
m_map[i / 8] |= 1 << (i % 8); m_map[i / 8] |= 1 << (i % 8);
} else { } else {
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8)); m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -194,10 +194,10 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field)); auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
*val = result.value; *val = result.value;
oxReturnError(result); OX_RETURN_ERROR(result);
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
// array handler // array handler
@ -207,18 +207,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *v
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
if (valLen >= len) { if (valLen >= len) {
auto reader = child({}); auto reader = child({});
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field({}, &val[i])); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
} else { } else {
oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen); oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen);
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
} }
} }
@ -232,29 +234,29 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto &val) { constexpr auto loopBody = [](auto &handler, auto &val) {
oxRequire(keyLen, handler.stringLength(nullptr)); OX_REQUIRE(keyLen, handler.stringLength(nullptr));
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
auto wkeyPtr = wkey.get(); auto wkeyPtr = wkey.get();
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1)); OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
return handler.field("", &val[wkeyPtr]); return handler.field("", &val[wkeyPtr]);
}; };
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(loopBody(handler, *val)); OX_RETURN_ERROR(loopBody(handler, *val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -264,11 +266,11 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
oxReturnError(ox::resizeVector(*val, len)); OX_RETURN_ERROR(ox::resizeVector(*val, len));
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
} }
oxReturnError(ox::resizeVector(*val, 0)); OX_RETURN_ERROR(ox::resizeVector(*val, 0));
} }
++m_field; ++m_field;
return {}; return {};
@ -276,9 +278,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
if (len > val->size()) { if (len > val->size()) {
return OxError(1, "Input array is too long"); return ox::Error(1, "Input array is too long");
} }
} }
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
@ -289,7 +291,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) { if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child(""); auto reader = child("");
oxReturnError(model(reader.interface(), val)); OX_RETURN_ERROR(model(reader.interface(), val));
} }
} }
++m_field; ++m_field;
@ -303,7 +305,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U,
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) { if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx())); auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
oxReturnError(model(reader.interface(), val.get())); OX_RETURN_ERROR(model(reader.interface(), val.get()));
} }
} }
++m_field; ++m_field;
@ -317,18 +319,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
const auto cap = size; const auto cap = size;
*val = BasicString<SmallStringSize>(cap); *val = BasicString<SmallStringSize>(cap);
auto data = val->data(); auto data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -338,12 +340,12 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
*val = IString<L>(); *val = IString<L>();
oxReturnError(val->resize(size)); OX_RETURN_ERROR(val->resize(size));
auto const data = val->data(); auto const data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
@ -357,18 +359,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
if (size > buffLen) { if (size > buffLen) {
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
// re-allocate in case too small // re-allocate in case too small
auto data = val; auto data = val;
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -376,17 +378,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate in case too small // re-allocate in case too small
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
auto data = *val; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -395,16 +397,16 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate if too small // re-allocate if too small
if (buffLen < size + 1) { if (buffLen < size + 1) {
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
buffLen = size + 1; buffLen = size + 1;
} }
auto data = *val; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} else { } else {
auto data = *val; auto data = *val;
@ -414,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -423,15 +425,15 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
if (!pass) { if (!pass) {
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
} }
return out; return out;
} }
} }
return OxError(1); return ox::Error(1);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -441,7 +443,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead); auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
oxReturnError(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur)); OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
return len; return len;
} }
} }
@ -455,14 +457,14 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead); auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
oxReturnError(result); OX_RETURN_ERROR(result);
*val = result.value; *val = result.value;
} else { } else {
*val = 0; *val = 0;
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -472,20 +474,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
T val; T val;
oxReturnError(handler.field("", &val)); OX_RETURN_ERROR(handler.field("", &val));
oxReturnError(cb(i, &val)); OX_RETURN_ERROR(cb(i, &val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -546,7 +548,7 @@ Error readMC(ox::BufferView buff, T &val) noexcept {
template<typename T> template<typename T>
Result<T> readMC(ox::BufferView buff) noexcept { Result<T> readMC(ox::BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readMC(buff, val.value)); OX_RETURN_ERROR(readMC(buff, val.value));
return val; return val;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -62,47 +62,47 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("CString", &obj->CString)); OX_RETURN_ERROR(io->fieldCString("CString", &obj->CString));
return OxError(0); return ox::Error(0);
} }
oxModelBegin(TestStructNest) OX_MODEL_BEGIN(TestStructNest)
oxModelField(Bool) OX_MODEL_FIELD(Bool)
oxModelField(Int) OX_MODEL_FIELD(Int)
oxModelField(IString) OX_MODEL_FIELD(IString)
oxModelEnd() OX_MODEL_END()
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if constexpr(T::opType() == ox::OpType::Reflect) { if constexpr(T::opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("IString", &obj->IString)); OX_RETURN_ERROR(io->field("IString", &obj->IString));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Vector", &obj->Vector)); OX_RETURN_ERROR(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Vector2", &obj->Vector2)); OX_RETURN_ERROR(io->field("Vector2", &obj->Vector2));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
return OxError(0); return ox::Error(0);
} }
std::map<ox::StringView, ox::Error(*)()> tests = { std::map<ox::StringView, ox::Error(*)()> tests = {
@ -114,9 +114,9 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// doesn't segfault // doesn't segfault
ox::Array<char, 1024> buff; ox::Array<char, 1024> buff;
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts)); OX_RETURN_ERROR(ox::writeMC(buff.data(), buff.size(), ts));
oxReturnError(ox::writeMC(ts)); OX_RETURN_ERROR(ox::writeMC(ts));
return OxError(0); return ox::Error(0);
} }
}, },
@ -176,7 +176,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch"); oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch"); oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@ -189,28 +189,28 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) { static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) {
if (val.length != expected.size()) { if (val.length != expected.size()) {
std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n'; std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n';
return OxError(1); return ox::Error(1);
} }
for (std::size_t i = 0; i < expected.size(); i++) { for (std::size_t i = 0; i < expected.size(); i++) {
if (expected[i] != val.data[i]) { if (expected[i] != val.data[i]) {
std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n'; std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n';
std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n'; std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
return OxError(1); return ox::Error(1);
} }
} }
return OxError(0); return ox::Error(0);
}; };
constexpr auto check64 = [](McInt val, auto expected) { constexpr auto check64 = [](McInt val, auto expected) {
if (val.length != 9) { if (val.length != 9) {
std::cout << "val.length: " << val.length << '\n'; std::cout << "val.length: " << val.length << '\n';
return OxError(1); return ox::Error(1);
} }
ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]); ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]);
if (expected != decoded) { if (expected != decoded) {
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n'; std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
// signed positive // signed positive
oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail"); oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail");
@ -247,7 +247,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// code deduplication // code deduplication
oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail");
oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail");
return OxError(0); return ox::Error(0);
} }
}, },
@ -260,12 +260,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
using ox::mc::decodeInteger; using ox::mc::decodeInteger;
static constexpr auto check = [](auto val) { static constexpr auto check = [](auto val) {
auto result = decodeInteger<decltype(val)>(encodeInteger(val)); auto result = decodeInteger<decltype(val)>(encodeInteger(val));
oxReturnError(result.error); OX_RETURN_ERROR(result.error);
if (result.value != val) { if (result.value != val) {
std::cout << "Bad value: " << result.value << ", expected: " << val << '\n'; std::cout << "Bad value: " << result.value << ", expected: " << val << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
oxAssert(check(uint32_t(14)), "Decode of 14 failed."); oxAssert(check(uint32_t(14)), "Decode of 14 failed.");
oxAssert(check(int8_t(-1)), "Decode of -1 failed."); oxAssert(check(int8_t(-1)), "Decode of -1 failed.");
@ -291,7 +291,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(check(0xffffffff), "Decode of 0xffffffff failed."); oxAssert(check(0xffffffff), "Decode of 0xffffffff failed.");
oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed."); oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed.");
oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed."); oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed.");
return OxError(0); return ox::Error(0);
} }
}, },
@ -319,7 +319,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type)); OX_RETURN_ERROR(testOut.setType(type));
oxAssert(ox::readMC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@ -344,7 +344,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed"); oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@ -371,7 +371,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::BufferReader br({dataBuff, dataBuffLen}); ox::BufferReader br({dataBuff, dataBuffLen});
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br, OX_RETURN_ERROR(ox::walkModel<ox::MetalClawReader>(type, br,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n'; //std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@ -454,10 +454,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -117,12 +117,12 @@ class MetalClawWriter {
bool fieldSet = false; bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
}; };
@ -181,10 +181,10 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val)
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -194,14 +194,14 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<Sm
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->len()); const auto strLen = mc::encodeInteger(val->len());
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
// write the string // write the string
oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len()))); OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -217,14 +217,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *c
const auto strLen = *val ? ox::strlen(*val) : 0; const auto strLen = *val ? ox::strlen(*val) : 0;
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -243,14 +243,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -264,11 +264,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer}; ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@ -282,11 +282,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@ -298,21 +298,23 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::s
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field("", &val[i])); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -324,32 +326,32 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
// write map // write map
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
// double len for both key and value // double len for both key and value
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2)); OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call // 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 { constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.len(); const auto keyLen = key.len();
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1); memcpy(wkey.get(), key.c_str(), keyLen + 1);
oxReturnError(handler.fieldCString("", wkey.get(), keyLen)); OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
oxRequireM(value, val.at(key)); OX_REQUIRE_M(value, val.at(key));
return handler.field("", value); return handler.field("", value);
}; };
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i]; auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val)); OX_RETURN_ERROR(loopBody(handler, key, *val));
} }
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -360,7 +362,7 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
const Vector<String>&, const Vector<String>&,
std::size_t fields) noexcept { std::size_t fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1; const auto fieldPresenceLen = (fields - 1) / 8 + 1;
oxReturnError(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields)); m_fieldPresence.setFields(static_cast<int>(fields));
@ -370,33 +372,33 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
template<Writer_c Writer> template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept { ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp(); const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP)); OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write( OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()), reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size())); m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end)); OX_RETURN_ERROR(m_writer.seekp(end));
return {}; return {};
} }
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer); MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter}; ModelHandlerInterface handler{&mcWriter};
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
oxReturnError(mcWriter.finalize()); OX_RETURN_ERROR(mcWriter.finalize());
return {}; return {};
} }
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz); Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0); BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
buff.resize(bw.tellp()); buff.resize(bw.tellp());
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw(buff, buffLen); CharBuffWriter bw{{buff, buffLen}};
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {
*sizeOut = bw.tellp(); *sizeOut = bw.tellp();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -11,9 +11,9 @@
#include <ox/std/concepts.hpp> #include <ox/std/concepts.hpp>
// oxModelFwdDecl is necessary because Apple-Clang is broken... // oxModelFwdDecl is necessary because Apple-Clang is broken...
#define oxModelFwdDecl(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>()); #define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>());
#define oxModelEnd() return OxError(0); } #define OX_MODEL_END() return ox::Error(0); }
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName)); #define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); #define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -76,21 +76,21 @@ struct Subscript {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<Subscript>()); OX_RETURN_ERROR(io->template setTypeInfo<Subscript>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint32_t st = 0; uint32_t st = 0;
oxReturnError(io->field("subscriptType", &st)); OX_RETURN_ERROR(io->field("subscriptType", &st));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
} else { } else {
auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
type->subscriptType = static_cast<Subscript::SubscriptType>(pt); type->subscriptType = static_cast<Subscript::SubscriptType>(pt);
} }
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("smallSzLen", &type->smallSzLen)); OX_RETURN_ERROR(io->field("smallSzLen", &type->smallSzLen));
return OxError(0); return {};
} }
using SubscriptStack = Vector<Subscript, 3>; using SubscriptStack = Vector<Subscript, 3>;
@ -119,6 +119,7 @@ struct DescriptorField {
subscriptLevels(pSubscriptLevels), subscriptLevels(pSubscriptLevels),
subscriptStack(std::move(pSubscriptType)), subscriptStack(std::move(pSubscriptType)),
typeId(std::move(pTypeId)) { typeId(std::move(pTypeId)) {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "Subscript level mismatch");
} }
constexpr DescriptorField(const DescriptorField &other) noexcept: constexpr DescriptorField(const DescriptorField &other) noexcept:
@ -184,38 +185,38 @@ constexpr auto buildTypeId(const DescriptorType &t) noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorType>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorType>());
oxReturnError(io->field("typeName", &type->typeName)); OX_RETURN_ERROR(io->field("typeName", &type->typeName));
oxReturnError(io->field("typeVersion", &type->typeVersion)); OX_RETURN_ERROR(io->field("typeVersion", &type->typeVersion));
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint8_t pt = 0; uint8_t pt = 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else { } else {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
type->primitiveType = static_cast<PrimitiveType>(pt); type->primitiveType = static_cast<PrimitiveType>(pt);
} }
oxReturnError(io->field("typeParams", &type->typeParams)); OX_RETURN_ERROR(io->field("typeParams", &type->typeParams));
oxReturnError(io->field("fieldList", &type->fieldList)); OX_RETURN_ERROR(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable)); OX_RETURN_ERROR(io->field("preloadable", &type->preloadable));
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorField>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorField>());
oxReturnError(io->field("typeId", &field->typeId)); OX_RETURN_ERROR(io->field("typeId", &field->typeId));
oxReturnError(io->field("fieldName", &field->fieldName)); OX_RETURN_ERROR(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels)); OX_RETURN_ERROR(io->field("subscriptLevels", &field->subscriptLevels));
oxReturnError(io->field("subscriptStack", &field->subscriptStack)); OX_RETURN_ERROR(io->field("subscriptStack", &field->subscriptStack));
// defaultValue is unused now, but leave placeholder for backwards compatibility // defaultValue is unused now, but leave placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); OX_RETURN_ERROR(io->field("defaultValue", &defaultValue));
return OxError(0); return {};
} }
template<typename ReaderBase> template<typename ReaderBase>
@ -243,7 +244,7 @@ constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto
// defaultValue is unused now, but placeholder for backwards compatibility // defaultValue is unused now, but placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0); return ox::Error(0);
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -97,8 +97,14 @@ class TypeDescWriter {
std::size_t fields = ModelFieldCount_v<T>) noexcept; std::size_t fields = ModelFieldCount_v<T>) noexcept;
template<typename T> template<typename T>
constexpr Error field(StringViewCR name, const T *val, std::size_t valLen, constexpr Error field(
const SubscriptStack &subscriptStack = {}) noexcept; StringViewCR name,
T const*val,
std::size_t valLen,
SubscriptStack const&subscriptStack) noexcept;
template<typename T>
constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept;
template<typename T, bool force> template<typename T, bool force>
constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept; constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept;
@ -193,15 +199,30 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
// array handler // array handler
template<typename T> template<typename T>
constexpr Error TypeDescWriter::field(StringViewCR name, const T*, std::size_t, const SubscriptStack &subscriptStack) noexcept { constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t, SubscriptStack const&subscriptStack) noexcept {
if (m_type) { if (m_type) {
constexpr typename remove_pointer<T>::type *p = nullptr; constexpr typename remove_pointer<T>::type *p = nullptr;
const auto t = type(p); const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t)); m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
return OxError(0); return ox::Error(0);
} }
return OxError(1); return ox::Error(1);
}
// array handler
template<typename T>
constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t) noexcept {
if (m_type) {
constexpr typename remove_pointer<T>::type *p = nullptr;
const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
auto const lvls = detail::indirectionLevels_v<T> + 1;
SubscriptStack subscriptStack{lvls};
m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t));
return ox::Error(0);
}
return ox::Error(1);
} }
template<typename T, bool force> template<typename T, bool force>
@ -210,9 +231,9 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return OxError(0); return ox::Error(0);
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
@ -233,7 +254,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept
return {}; return {};
} }
} }
return OxError(1); return ox::Error(1);
} }
template<typename ...Args> template<typename ...Args>
@ -363,11 +384,11 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
std::allocator<T> a; std::allocator<T> a;
T *t = a.allocate(1); T *t = a.allocate(1);
oxReturnError(model(&handler, t)); OX_RETURN_ERROR(model(&handler, t));
a.deallocate(t, 1); a.deallocate(t, 1);
} else { } else {
auto t = ox_malloca(sizeof(T), T); auto t = ox_malloca(sizeof(T), T);
oxReturnError(model(&handler, t.get())); OX_RETURN_ERROR(model(&handler, t.get()));
} }
return writer.definition(); return writer.definition();
} }
@ -376,7 +397,7 @@ template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
return writer.definition(); return writer.definition();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -31,25 +31,25 @@ class FieldCounter {
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U) noexcept { constexpr ox::Error field(StringViewCR, U) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept { constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename U, typename Handler> template<typename U, typename Handler>
constexpr Error field(StringViewCR, Handler) { constexpr Error field(StringViewCR, Handler) {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -135,8 +135,8 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>()); return m_handler->field(name, &v->template get<ModelValueArray>());
} }
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type())); oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(OxError(1), "invalid type"); oxPanic(ox::Error(1), "invalid type");
return OxError(1, "invalid type"); return ox::Error(1, "invalid type");
} }
// array handler, with callback to allow handling individual elements // array handler, with callback to allow handling individual elements

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -56,19 +56,19 @@ class MemberList {
template<typename T> template<typename T>
constexpr Error field(const char*, T *v) noexcept { constexpr Error field(const char*, T *v) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T *v, int) noexcept { constexpr Error field(const char*, T *v, int) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> u) noexcept { constexpr Error field(const char*, UnionView<U, force> u) noexcept {
vars[m_i++] = static_cast<void*>(u.get()); vars[m_i++] = static_cast<void*>(u.get());
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -107,7 +107,7 @@ class Copier {
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]); auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
dst = src; dst = src;
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
} }
@ -119,7 +119,7 @@ class Copier {
dst = src; dst = src;
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -128,7 +128,7 @@ class Copier {
auto &src = *u.get(); auto &src = *u.get();
dst = src; dst = src;
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename T = void> template<typename T = void>
@ -168,7 +168,7 @@ class Mover {
dst = std::move(src); dst = std::move(src);
src = FT{}; src = FT{};
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
} }
@ -181,7 +181,7 @@ class Mover {
src = FT{}; src = FT{};
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -190,7 +190,7 @@ class Mover {
auto &src = *u.get(); auto &src = *u.get();
dst = std::move(src); dst = std::move(src);
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename T = void> template<typename T = void>
@ -228,10 +228,10 @@ class Equals {
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]); const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return ox::Error(0);
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
@ -242,11 +242,11 @@ class Equals {
const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i]; const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i];
if (!(dst == src)) { if (!(dst == src)) {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -255,10 +255,10 @@ class Equals {
const auto &src = *u.get(); const auto &src = *u.get();
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return ox::Error(0);
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -12,12 +12,12 @@ namespace ox {
static_assert([]() -> ox::Error { static_assert([]() -> ox::Error {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
if (v.type() != ModelValue::Type::SignedInteger32) { if (v.type() != ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
//oxReturnError(v.set<int32_t>(5)); //oxReturnError(v.set<int32_t>(5));
return {}; return {};
}() == OxError(0)); }() == ox::Error(0));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept { constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept { constexpr auto &get() noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@ -188,8 +188,8 @@ class ModelValue {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels = 0, SubscriptStack const& = {},
SubscriptStack const& = {}) noexcept; int subscriptLevels = 0) noexcept;
template<typename T> template<typename T>
constexpr Error setType() noexcept; constexpr Error setType() noexcept;
@ -242,7 +242,7 @@ class ModelValueArray {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@ -276,8 +276,9 @@ class ModelValueArray {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels, SubscriptStack subscriptStack,
SubscriptStack subscriptStack) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type; m_type = type;
m_typeSubscriptLevels = subscriptLevels; m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack); m_subscriptStack = std::move(subscriptStack);
@ -400,7 +401,7 @@ class ModelValueVector {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@ -418,8 +419,9 @@ class ModelValueVector {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels, SubscriptStack subscriptStack,
SubscriptStack subscriptStack) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type; m_type = type;
m_typeSubscriptLevels = subscriptLevels; m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack); m_subscriptStack = std::move(subscriptStack);
@ -517,7 +519,7 @@ class ModelObject {
ModelValue value; ModelValue value;
}; };
protected: protected:
oxModelFriend(ModelObject); OX_MODEL_FRIEND(ModelObject);
friend ModelValue; friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder; Vector<UniquePtr<Field>> m_fieldsOrder;
HashMap<String, ModelValue*> m_fields; HashMap<String, ModelValue*> m_fields;
@ -632,18 +634,18 @@ class ModelObject {
if (m_fields.contains(k)) { if (m_fields.contains(k)) {
return *m_fields.at(k).value; return *m_fields.at(k).value;
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
constexpr Error set(const String &k, T &&val) noexcept { constexpr Error set(const String &k, T &&val) noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
*t = ox::forward<T>(val); *t = ox::forward<T>(val);
return {}; return {};
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return *v; return *v;
} }
@ -668,17 +670,17 @@ class ModelObject {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelObject"); return ox::Error(1, "Cannot load a non-struct type to ModelObject");
} }
m_type = type; m_type = type;
for (const auto &f : type->fieldList) { for (const auto &f : type->fieldList) {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
oxReturnError(field->value.setType(f.type, f.subscriptLevels, f.subscriptStack)); OX_RETURN_ERROR(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels));
m_fields[field->name] = &field->value; m_fields[field->name] = &field->value;
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
} }
return OxError(0); return {};
} }
}; };
@ -720,7 +722,7 @@ class ModelUnion {
static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept { static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept {
UniquePtr<ModelUnion> out(new ModelUnion); UniquePtr<ModelUnion> out(new ModelUnion);
oxReturnError(out->setType(type)); OX_RETURN_ERROR(out->setType(type));
return out; return out;
} }
@ -729,7 +731,7 @@ class ModelUnion {
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return &(*v)->value; return &(*v)->value;
} }
@ -761,7 +763,7 @@ class ModelUnion {
[[nodiscard]] [[nodiscard]]
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept { constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
return &(*t)->value; return &(*t)->value;
} }
@ -788,7 +790,7 @@ class ModelUnion {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelUnion"); return ox::Error(1, "Cannot load a non-struct type to ModelUnion");
} }
m_fields.clear(); m_fields.clear();
m_fieldsOrder.clear(); m_fieldsOrder.clear();
@ -797,12 +799,12 @@ class ModelUnion {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
field->idx = i; field->idx = i;
oxReturnError(field->value.setType(f.type, f.subscriptLevels)); OX_RETURN_ERROR(field->value.setType(f.type, SubscriptStack{static_cast<size_t>(f.subscriptLevels)}, f.subscriptLevels));
m_fields[field->name] = field.get(); m_fields[field->name] = field.get();
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
++i; ++i;
} }
return OxError(0); return {};
} }
[[nodiscard]] [[nodiscard]]
@ -965,21 +967,21 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept {
} }
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelObject>( OX_RETURN_ERROR(h->template setTypeInfo<ModelObject>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return ox::Error(0);
} }
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelUnion>( OX_RETURN_ERROR(h->template setTypeInfo<ModelUnion>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return ox::Error(0);
} }
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
@ -1076,20 +1078,21 @@ constexpr ModelValue::Type ModelValue::type() const noexcept {
constexpr Error ModelValue::setType( constexpr Error ModelValue::setType(
const DescriptorType *type, const DescriptorType *type,
int subscriptLevels, SubscriptStack const&subscriptStack,
SubscriptStack const&subscriptStack) noexcept { int subscriptLevels) noexcept {
freeResources(); freeResources();
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
if (subscriptLevels) { if (subscriptLevels) {
auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)]; auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)];
if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) { if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) {
m_type = Type::InlineArray; m_type = Type::InlineArray;
m_data.array = new ModelValueArray; m_data.array = new ModelValueArray;
oxReturnError(m_data.array->setType(type, subscriptLevels - 1, subscriptStack)); OX_RETURN_ERROR(m_data.array->setType(type, subscriptStack, subscriptLevels - 1));
oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length))); OX_RETURN_ERROR(m_data.array->setSize(static_cast<size_t>(subscript.length)));
} else { } else {
m_type = Type::Vector; m_type = Type::Vector;
m_data.vec = new ModelValueVector; m_data.vec = new ModelValueVector;
oxReturnError(m_data.vec->setType(type, subscriptLevels - 1, subscriptStack)); OX_RETURN_ERROR(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1));
} }
return {}; return {};
} else if (type->typeName == types::Bool) { } else if (type->typeName == types::Bool) {
@ -1118,15 +1121,15 @@ constexpr Error ModelValue::setType(
} else if (type->primitiveType == PrimitiveType::Struct) { } else if (type->primitiveType == PrimitiveType::Struct) {
m_type = Type::Object; m_type = Type::Object;
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if (type->primitiveType == PrimitiveType::Union) { } else if (type->primitiveType == PrimitiveType::Union) {
m_type = Type::Union; m_type = Type::Union;
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} }
oxAssert(m_type != Type::Undefined, "No type set"); oxAssert(m_type != Type::Undefined, "No type set");
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -1138,11 +1141,11 @@ constexpr Error ModelValue::setType() noexcept {
// rather than using getValue<type>() // rather than using getValue<type>()
if constexpr(type == Type::Object) { if constexpr(type == Type::Object) {
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if constexpr(type == Type::Union) { } else if constexpr(type == Type::Union) {
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} else if constexpr(type == Type::String) { } else if constexpr(type == Type::String) {
m_data.str = new String; m_data.str = new String;
} else if constexpr(type == Type::Vector) { } else if constexpr(type == Type::Vector) {
@ -1173,7 +1176,7 @@ template<typename T>
constexpr Error ModelValue::set(const T &v) noexcept { constexpr Error ModelValue::set(const T &v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@ -1181,14 +1184,14 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = v; value = v;
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error ModelValue::set(T &&v) noexcept { constexpr Error ModelValue::set(T &&v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@ -1196,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = std::move(v); value = std::move(v);
return OxError(0); return ox::Error(0);
} }
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept { constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -17,8 +17,8 @@ struct TestType {
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
}; };
oxModelBegin(TestType) OX_MODEL_BEGIN(TestType)
oxModelEnd() OX_MODEL_END()
struct TestType2 { struct TestType2 {
}; };
@ -38,12 +38,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
"ModelValue", "ModelValue",
[] { [] {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
//v.m_type = ox::ModelValue::getType<int32_t>(); //v.m_type = ox::ModelValue::getType<int32_t>();
if (v.type() != ox::ModelValue::Type::SignedInteger32) { if (v.type() != ox::ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
oxReturnError(v.set<int32_t>(5)); OX_RETURN_ERROR(v.set<int32_t>(5));
return ox::Error{}; return ox::Error{};
} }
}, },

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
@ -77,17 +77,17 @@ struct TypeInfoCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error fieldCString(const char*, T) noexcept { constexpr Error fieldCString(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -31,7 +31,7 @@ class TypeStore {
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion, constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
const TypeParamPack &typeParams) const noexcept { const TypeParamPack &typeParams) const noexcept {
const auto typeId = buildTypeId(name, typeVersion, typeParams); const auto typeId = buildTypeId(name, typeVersion, typeParams);
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@ -40,7 +40,7 @@ class TypeStore {
constexpr auto typeName = ModelTypeName_v<T>; constexpr auto typeName = ModelTypeName_v<T>;
constexpr auto typeVersion = ModelTypeVersion_v<T>; constexpr auto typeVersion = ModelTypeVersion_v<T>;
const auto typeId = buildTypeId(typeName, typeVersion, {}); const auto typeId = buildTypeId(typeName, typeVersion, {});
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@ -56,15 +56,15 @@ class TypeStore {
auto [val, err] = m_cache.at(typeId); auto [val, err] = m_cache.at(typeId);
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeId)); OX_REQUIRE_M(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) { for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeId).moveTo(f.type)); OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type));
} }
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
out = std::move(dt); out = std::move(dt);
return out.get(); return out.get();
} else { } else {
return OxError(1, "Type not available"); return ox::Error(1, "Type not available");
} }
} }
return val->get(); return val->get();
@ -102,7 +102,7 @@ class TypeStore {
protected: protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept { virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return OxError(1); return ox::Error(1);
} }
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version, Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -50,7 +50,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler
template<typename Reader, typename T> template<typename Reader, typename T>
constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept { constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept {
oxRequire(out, m_typeStack.back()); OX_REQUIRE(out, m_typeStack.back());
return *out; return *out;
} }
@ -87,9 +87,9 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
walker->pushNamePath(field.fieldName); walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) { if (field.subscriptLevels) {
// add array handling // add array handling
oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); OX_REQUIRE(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true));
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
oxReturnError(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen)); OX_RETURN_ERROR(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen));
DescriptorField f(field); // create mutable copy DescriptorField f(field); // create mutable copy
--f.subscriptLevels; --f.subscriptLevels;
String subscript; String subscript;
@ -98,7 +98,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
subscript += static_cast<uint64_t>(i); subscript += static_cast<uint64_t>(i);
subscript += "]"; subscript += "]";
walker->pushNamePath(subscript); walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker)); OX_RETURN_ERROR(parseField(f, &child, walker));
walker->popNamePath(); walker->popNamePath();
} }
rdr->nextField(); rdr->nextField();
@ -108,40 +108,40 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
case PrimitiveType::SignedInteger: case PrimitiveType::SignedInteger:
case PrimitiveType::Bool: case PrimitiveType::Bool:
case PrimitiveType::String: case PrimitiveType::String:
oxReturnError(walker->read(field, rdr)); OX_RETURN_ERROR(walker->read(field, rdr));
break; break;
case PrimitiveType::Struct: case PrimitiveType::Struct:
case PrimitiveType::Union: case PrimitiveType::Union:
if (rdr->fieldPresent(field.fieldName.c_str())) { if (rdr->fieldPresent(field.fieldName.c_str())) {
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
walker->pushType(field.type); walker->pushType(field.type);
oxReturnError(model(&child, walker)); OX_RETURN_ERROR(model(&child, walker));
walker->popType(); walker->popType();
rdr->nextField(); rdr->nextField();
} else { } else {
// skip and discard absent field // skip and discard absent field
int discard; int discard;
oxReturnError(rdr->field(field.fieldName.c_str(), &discard)); OX_RETURN_ERROR(rdr->field(field.fieldName.c_str(), &discard));
} }
break; break;
} }
} }
walker->popNamePath(); walker->popNamePath();
return OxError(0); return ox::Error(0);
} }
template<typename Reader, typename FH> template<typename Reader, typename FH>
constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept { constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
oxRequire(type, walker->type()); OX_REQUIRE(type, walker->type());
auto typeName = type->typeName.c_str(); auto typeName = type->typeName.c_str();
auto typeVersion = type->typeVersion; auto typeVersion = type->typeVersion;
auto typeParams = type->typeParams; auto typeParams = type->typeParams;
auto &fields = type->fieldList; auto &fields = type->fieldList;
oxReturnError(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size())); OX_RETURN_ERROR(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size()));
for (const auto &field : fields) { for (const auto &field : fields) {
oxReturnError(parseField(field, rdr, walker)); OX_RETURN_ERROR(parseField(field, rdr, walker));
} }
return OxError(0); return ox::Error(0);
} }
template<typename Reader, typename Handler> template<typename Reader, typename Handler>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -19,7 +19,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize)
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@ -27,7 +27,7 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
} }
Error OrganicClawReader::field(const char *key, bool *val) noexcept { Error OrganicClawReader::field(const char *key, bool *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -45,7 +45,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} else if (jv.isBool()) { } else if (jv.isBool()) {
*val = jv.asBool(); *val = jv.asBool();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@ -67,13 +67,13 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<std::size_t>(end - begin);
auto data = val; auto data = val;
if (strSize >= buffLen) { if (strSize >= buffLen) {
err = OxError(2, "String size exceeds capacity of destination"); err = ox::Error(2, "String size exceeds capacity of destination");
} else { } else {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} }
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
} }
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
auto &data = *val; auto &data = *val;
@ -98,7 +98,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@ -126,7 +126,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = nullptr; data[strSize] = nullptr;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -135,7 +135,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
Error OrganicClawReader::field(const char *key, UUID *val) noexcept { Error OrganicClawReader::field(const char *key, UUID *val) noexcept {
UUIDStr str; UUIDStr str;
oxReturnError(field(key, &str)); OX_RETURN_ERROR(field(key, &str));
return UUID::fromString(str).moveTo(*val); return UUID::fromString(str).moveTo(*val);
} }
@ -147,7 +147,7 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
if (jv.isArray()) { if (jv.isArray()) {
return jv.size(); return jv.size();
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
[[nodiscard]] [[nodiscard]]
@ -161,7 +161,7 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
jv.getString(&begin, &end); jv.getString(&begin, &end);
return static_cast<std::size_t>(end - begin); return static_cast<std::size_t>(end - begin);
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept { OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -133,7 +133,7 @@ class OrganicClawReader {
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept { Error OrganicClawReader::field(const char *key, T *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
try { try {
if constexpr (is_integer_v<T>) { if constexpr (is_integer_v<T>) {
if (targetValid()) { if (targetValid()) {
@ -146,19 +146,19 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
} else if (rightType) { } else if (rightType) {
*val = static_cast<T>(jv.asUInt()); *val = static_cast<T>(jv.asUInt());
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
} else if constexpr (isVector_v<T>) { } else if constexpr (isVector_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
oxReturnError(ox::resizeVector(*val, srcSize)); OX_RETURN_ERROR(ox::resizeVector(*val, srcSize));
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) { } else if constexpr (isArray_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
if (srcSize > val->size()) { if (srcSize > val->size()) {
err = OxError(1, "Input array is too long"); err = ox::Error(1, "Input array is too long");
} else { } else {
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} }
@ -169,11 +169,11 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val); err = model(&handler, val);
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
} catch (Json::LogicError const&) { } catch (Json::LogicError const&) {
err = OxError(1, "error reading JSON data"); err = ox::Error(1, "error reading JSON data");
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
@ -181,7 +181,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
template<typename U, bool force> template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty() || jv.isObject()) { if (jv.empty() || jv.isObject()) {
@ -189,7 +189,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val.get()); err = model(&handler, val.get());
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -198,7 +198,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -206,7 +206,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -215,7 +215,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -223,7 +223,7 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -235,25 +235,27 @@ template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept { Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) { if (!srcVal.isNull() && !srcVal.isArray()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
if (srcSize > valLen) { if (srcSize > valLen) {
return OxError(1); return ox::Error(1);
} }
OrganicClawReader r(srcVal); OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
oxReturnError(handler.field("", &val[i])); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept { Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isObject()) { if (!srcVal.isObject()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto keys = srcVal.getMemberNames(); auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
@ -261,9 +263,9 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
oxReturnError(handler.field(k, &val->operator[](k))); OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
} }
return OxError(0); return ox::Error(0);
} }
Error readOC(BufferView buff, auto &val) noexcept { Error readOC(BufferView buff, auto &val) noexcept {
@ -272,8 +274,10 @@ Error readOC(BufferView buff, auto &val) noexcept {
Json::Value doc; Json::Value doc;
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) { if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
return OxError(1, "Could not parse JSON"); OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(1, "Could not parse JSON");
} }
OrganicClawReader reader(buff.data(), buff.size()); OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
@ -281,14 +285,14 @@ Error readOC(BufferView buff, auto &val) noexcept {
} catch (const Error &err) { } catch (const Error &err) {
return err; return err;
} catch (...) { } catch (...) {
return OxError(1, "Unknown Error"); return ox::Error(1, "Unknown Error");
} }
} }
template<typename T> template<typename T>
Result<T> readOC(BufferView buff) noexcept { Result<T> readOC(BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readOC(buff, val.value)); OX_RETURN_ERROR(readOC(buff, val.value));
return val; return val;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -74,45 +74,45 @@ struct TestStruct {
}; };
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if (io->opType() == ox::OpType::Reflect) { if (io->opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
TestStruct::TestStruct(TestStruct &&other) noexcept { TestStruct::TestStruct(TestStruct &&other) noexcept {
@ -184,7 +184,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@ -210,7 +210,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value)); OX_RETURN_ERROR(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readOC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@ -234,7 +234,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@ -259,7 +259,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
ox::TypeStore typeStore; ox::TypeStore typeStore;
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(), OX_RETURN_ERROR(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(),
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f,
ox::OrganicClawReader *rdr) -> ox::Error { ox::OrganicClawReader *rdr) -> ox::Error {
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@ -341,10 +341,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -42,7 +42,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int16_t *val) noexcept { Error field(const char *key, const int16_t *val) noexcept {
@ -50,7 +50,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int32_t *val) noexcept { Error field(const char *key, const int32_t *val) noexcept {
@ -58,7 +58,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int64_t *val) noexcept { Error field(const char *key, const int64_t *val) noexcept {
@ -66,7 +66,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
@ -75,7 +75,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint16_t *val) noexcept { Error field(const char *key, const uint16_t *val) noexcept {
@ -83,7 +83,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint32_t *val) noexcept { Error field(const char *key, const uint32_t *val) noexcept {
@ -91,7 +91,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint64_t *val) noexcept { Error field(const char *key, const uint64_t *val) noexcept {
@ -99,7 +99,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(char const*key, bool const*val) noexcept { Error field(char const*key, bool const*val) noexcept {
@ -122,8 +122,8 @@ class OrganicClawWriter {
for (std::size_t i = 0; i < keys.size(); ++i) { for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
if (k) [[likely]] { if (k) [[likely]] {
oxRequireM(value, val->at(k)); OX_REQUIRE_M(value, val->at(k));
oxReturnError(handler.field(k, value)); OX_RETURN_ERROR(handler.field(k, value));
} }
} }
value(key) = w.m_json; value(key) = w.m_json;
@ -147,7 +147,7 @@ class OrganicClawWriter {
value(key) = val->c_str(); value(key) = val->c_str();
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error fieldCString(const char*, const char *const*val, int len) noexcept; Error fieldCString(const char*, const char *const*val, int len) noexcept;
@ -200,12 +200,14 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n
OrganicClawWriter w((Json::Value(Json::arrayValue))); OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field({}, &val[i])); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
value(key) = w.m_json; value(key) = w.m_json;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -225,13 +227,13 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
} else if (val && targetValid()) { } else if (val && targetValid()) {
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
if (!w.m_json.empty() || m_json.isArray()) { if (!w.m_json.empty() || m_json.isArray()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force> template<typename U, bool force>
@ -239,19 +241,19 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
if (targetValid()) { if (targetValid()) {
OrganicClawWriter w(val.idx()); OrganicClawWriter w(val.idx());
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Result<ox::Buffer> writeOC(const auto &val) noexcept { Result<ox::Buffer> writeOC(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<Buffer> buff; Result<Buffer> buff;
@ -263,7 +265,7 @@ Result<ox::Buffer> writeOC(const auto &val) noexcept {
Result<ox::String> writeOCString(const auto &val) noexcept { Result<ox::String> writeOCString(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<ox::String> buff; Result<ox::String> buff;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -63,7 +63,7 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
template<typename T> template<typename T>
constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept { constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field(nullptr, &val[i])); OX_RETURN_ERROR(field(nullptr, &val[i]));
} }
return {}; return {};
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -162,7 +162,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::UnionView
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val.get())); OX_RETURN_ERROR(pad(val.get()));
m_unionIdx.emplace_back(val.idx()); m_unionIdx.emplace_back(val.idx());
const auto err = preload<PlatSpec, U>(this, val.get()); const auto err = preload<PlatSpec, U>(this, val.get());
m_unionIdx.pop_back(); m_unionIdx.pop_back();
@ -175,13 +175,13 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const T *val)
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val)); OX_RETURN_ERROR(pad(val));
if constexpr(ox::is_integral_v<T>) { if constexpr(ox::is_integral_v<T>) {
return ox::serialize(m_writer, PlatSpec::correctEndianness(*val)); return ox::serialize(m_writer, PlatSpec::correctEndianness(*val));
} else if constexpr(ox::is_pointer_v<T>) { } else if constexpr(ox::is_pointer_v<T>) {
const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart; const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart;
oxReturnError(field(name, *val)); OX_RETURN_ERROR(field(name, *val));
oxReturnError(endAlloc()); OX_RETURN_ERROR(endAlloc());
return ox::serialize(m_writer, PlatSpec::correctEndianness(a)); return ox::serialize(m_writer, PlatSpec::correctEndianness(a));
} else if constexpr(ox::isVector_v<T>) { } else if constexpr(ox::isVector_v<T>) {
return fieldVector(name, val); return fieldVector(name, val);
@ -211,19 +211,19 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::BasicStri
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
}; };
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto restore = m_writer.tellp(); const auto restore = m_writer.tellp();
std::size_t a = 0; std::size_t a = 0;
if (sz && sz >= SmallStringSize) { if (sz && sz >= SmallStringSize) {
oxReturnError(ox::allocate(m_writer, sz).moveTo(a)); OX_RETURN_ERROR(ox::allocate(m_writer, sz).moveTo(a));
} else { } else {
a = restore; a = restore;
} }
vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart); vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart);
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
oxReturnError(m_writer.write(val->data(), sz)); OX_RETURN_ERROR(m_writer.write(val->data(), sz));
oxReturnError(m_writer.seekp(restore)); OX_RETURN_ERROR(m_writer.seekp(restore));
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items); m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items);
return {}; return {};
} }
@ -234,12 +234,12 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const ox::Arra
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
// serialize the Array elements // serialize the Array elements
if constexpr(sz) { if constexpr(sz) {
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(name, &(*val)[i])); OX_RETURN_ERROR(this->interface()->field(name, &(*val)[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@ -253,11 +253,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
return {}; return {};
} }
if (cnt) { if (cnt) {
oxReturnError(pad(*val)); OX_RETURN_ERROR(pad(*val));
// serialize the array // serialize the array
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(this->interface()->field(nullptr, &val[i])); OX_RETURN_ERROR(this->interface()->field(nullptr, &val[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@ -267,11 +267,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept { constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept {
m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp())); m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp()));
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@ -280,11 +280,11 @@ template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc( constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(
std::size_t sz, size_t align, std::size_t restore) noexcept { std::size_t sz, size_t align, std::size_t restore) noexcept {
m_allocStack.emplace_back(restore, ox::ios_base::beg); m_allocStack.emplace_back(restore, ox::ios_base::beg);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@ -295,7 +295,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
return m_writer.seekp(0, ox::ios_base::end); return m_writer.seekp(0, ox::ios_base::end);
} }
const auto &si = *m_allocStack.back().unwrap(); const auto &si = *m_allocStack.back().unwrap();
oxReturnError(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir)); OX_RETURN_ERROR(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir));
m_allocStack.pop_back(); m_allocStack.pop_back();
m_allocStart.pop_back(); m_allocStart.pop_back();
return {}; return {};
@ -304,12 +304,12 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept { constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept {
for (const auto &p : m_ptrs) { for (const auto &p : m_ptrs) {
oxReturnError(m_writer.seekp(p.loc)); OX_RETURN_ERROR(m_writer.seekp(p.loc));
const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>( const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>(
static_cast<typename PlatSpec::PtrType>(p.value + offset)); static_cast<typename PlatSpec::PtrType>(p.value + offset));
oxReturnError(ox::serialize(m_writer, val)); OX_RETURN_ERROR(ox::serialize(m_writer, val));
} }
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
return {}; return {};
} }
@ -354,39 +354,39 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept { StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto vecValPt = m_writer.tellp(); const auto vecValPt = m_writer.tellp();
// serialize the Vector elements // serialize the Vector elements
if (val->size()) { if (val->size()) {
const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size(); const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size();
const auto align = alignOf<PlatSpec>((*val)[0]); const auto align = alignOf<PlatSpec>((*val)[0]);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(p, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(p, ox::allocate(m_writer, sz + padding));
p += padding; p += padding;
oxReturnError(m_writer.seekp(p)); OX_RETURN_ERROR(m_writer.seekp(p));
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(nullptr, &val->operator[](i))); OX_RETURN_ERROR(this->interface()->field(nullptr, &val->operator[](i)));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
vecVal.items = PlatSpec::correctEndianness( vecVal.items = PlatSpec::correctEndianness(
static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart)); static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart));
oxReturnError(m_writer.seekp(vecValPt)); OX_RETURN_ERROR(m_writer.seekp(vecValPt));
} else { } else {
vecVal.items = 0; vecVal.items = 0;
} }
// serialize the Vector // serialize the Vector
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items); m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items);
return {}; return {};
} }
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept { constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept {
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
for (auto const&v : *val) { for (auto const&v : *val) {
oxReturnError(this->interface()->field({}, &v)); OX_RETURN_ERROR(this->interface()->field({}, &v));
} }
return {}; return {};
} }
@ -405,7 +405,7 @@ constexpr size_t Preloader<PlatSpec>::calcPadding(size_t align) const noexcept {
template<typename PlatSpec, typename T> template<typename PlatSpec, typename T>
constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept { constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept {
oxReturnError(model(pl->interface(), obj)); OX_RETURN_ERROR(model(pl->interface(), obj));
return pl->pad(obj); return pl->pad(obj);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -74,7 +74,7 @@ template<typename T, bool force>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept {
pad(val.get()); pad(val.get());
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@ -91,7 +91,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -43,7 +43,7 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
template<typename T, bool force> template<typename T, bool force>
constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept { constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept {
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@ -80,7 +80,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }

View File

@ -1,3 +1,9 @@
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# enable warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage")
endif()
if(OX_USE_STDLIB AND OX_ENABLE_TRACEHOOK) if(OX_USE_STDLIB AND OX_ENABLE_TRACEHOOK)
add_library( add_library(
OxTraceHook SHARED OxTraceHook SHARED
@ -103,6 +109,7 @@ install(
error.hpp error.hpp
fmt.hpp fmt.hpp
hardware.hpp hardware.hpp
hash.hpp
hashmap.hpp hashmap.hpp
heapmgr.hpp heapmgr.hpp
ignore.hpp ignore.hpp

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -8,6 +8,10 @@
#pragma once #pragma once
#include "def.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename It, typename T> template<typename It, typename T>
@ -41,3 +45,5 @@ constexpr OutIt copy_n(It in, Size cnt, OutIt out) {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,6 +9,7 @@
#pragma once #pragma once
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "error.hpp" #include "error.hpp"
#include "initializerlist.hpp" #include "initializerlist.hpp"
#include "iterator.hpp" #include "iterator.hpp"
@ -17,6 +18,8 @@
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
@ -35,6 +38,10 @@ class Array {
public: public:
constexpr Array() noexcept = default; constexpr Array() noexcept = default;
template<typename ...Args>
constexpr Array(Args ...list) noexcept: m_items{std::move(list)...} {
}
constexpr Array(std::initializer_list<T> list) noexcept; constexpr Array(std::initializer_list<T> list) noexcept;
constexpr Array(const Array &other); constexpr Array(const Array &other);
@ -174,11 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept { constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept { constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
@ -198,3 +207,5 @@ constexpr bool Array<T, ArraySize>::contains(const T &v) const {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,11 +1,12 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * 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/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include "fmt.hpp"
#include "stacktrace.hpp" #include "stacktrace.hpp"
#include "trace.hpp" #include "trace.hpp"
@ -13,7 +14,7 @@
namespace ox { namespace ox {
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept { void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) { if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
@ -31,4 +32,40 @@ void panic(const char *file, int line, const char *panicMsg, const Error &err) n
#endif #endif
} }
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
}
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
output += genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
}
void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
#if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort();
#else
constexprPanic(file, line, assertMsg);
#endif
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -22,9 +22,9 @@
namespace ox { namespace ox {
void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = OxError(0)) noexcept; void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept;
constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = OxError(0)) noexcept { constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err); panic(file, line, panicMsg, err);
} else { } else {
@ -32,19 +32,13 @@ constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg
} }
} }
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept;
void assertFailFuncRuntime(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept;
constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept { constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept {
if (!pass) { if (!pass) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#ifdef OX_USE_STDLIB assertFailFuncRuntime(file, line, assertTxt, msg);
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
output += genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
} else { } else {
while (true); while (true);
} }
@ -54,22 +48,7 @@ constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused
constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept { constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB) assertFailFuncRuntime(file, line, err, {}, assertMsg);
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.file != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort();
#else
constexprPanic(file, line, assertMsg);
#endif
} else { } else {
while (true); while (true);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,9 +9,12 @@
#pragma once #pragma once
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "cstrops.hpp" #include "cstrops.hpp"
#include "iterator.hpp" #include "iterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::detail { namespace ox::detail {
class BaseStringView { class BaseStringView {
@ -202,7 +205,7 @@ class BaseStringView {
} }
[[nodiscard]] [[nodiscard]]
constexpr auto operator[](std::size_t i) const noexcept { constexpr auto &operator[](std::size_t i) const noexcept {
return m_str[i]; return m_str[i];
} }
@ -215,3 +218,5 @@ class BaseStringView {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -126,11 +126,11 @@ constexpr void Bounds::set(const Point &pt1, const Point &pt2) noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Bounds> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<Bounds> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Bounds>()); OX_RETURN_ERROR(io->template setTypeInfo<Bounds>());
oxReturnError(io->field("x", &obj->x)); OX_RETURN_ERROR(io->field("x", &obj->x));
oxReturnError(io->field("y", &obj->y)); OX_RETURN_ERROR(io->field("y", &obj->y));
oxReturnError(io->field("width", &obj->width)); OX_RETURN_ERROR(io->field("width", &obj->width));
oxReturnError(io->field("height", &obj->height)); OX_RETURN_ERROR(io->field("height", &obj->height));
return {}; return {};
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this

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