Compare commits

...

137 Commits

Author SHA1 Message Date
fd2fb6e0c1 [nostalgia/studio] Bump version to 2024.12.4
All checks were successful
Build / build (push) Successful in 3m24s
2025-01-26 21:08:52 -06:00
449022f9ae [ox/std] Fix HashMap collision handling
Some checks failed
Build / build (push) Has been cancelled
2025-01-26 21:01:35 -06:00
6898f8eda1 [ox/std] Fix UPtr compare with nullptr 2025-01-26 21:01:35 -06:00
1f5c5a72ef [ox/model] Fix possible infinite recursion 2025-01-23 23:46:42 -06:00
a18c5d9294 [ox/std] Fix string append issues
All checks were successful
Build / build (push) Successful in 3m21s
2025-01-19 17:12:22 -06:00
c753881747 [ox/std] Fix possible error that occurs with appending on boundary of small string size 2025-01-19 09:27:44 -06:00
ba1bf950a8 [nostalgia/core/studio/paletteeditor] Fix adding page if there is no existing page
All checks were successful
Build / build (push) Successful in 3m19s
2025-01-18 21:31:22 -06:00
95950441d1 [nostalgia/core/studio/tilesheeteditor] Fix subsheet and palette scrolling 2025-01-18 21:31:22 -06:00
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
3271a37115 [ox] Add Project Structure section to docs
All checks were successful
Build / build (push) Successful in 2m36s
2024-10-04 01:15:17 -05:00
ea9f50de8d [olympic] Add error handling back to developer-handbook.md 2024-10-04 01:13:45 -05:00
ea3c5e03fb [olympic] Remove Ox from developer-handbook.md 2024-10-04 01:00:02 -05:00
c8c4177d60 [ox] Add ox-docs.md 2024-10-04 00:59:23 -05:00
76b540e3b8 [nostalgia/core] Cleanup, add missing FileAddress wrapper function
All checks were successful
Build / build (push) Successful in 2m32s
2024-10-03 22:48:26 -05:00
2062748676 [keel] Cleanup 2024-10-03 22:39:48 -05:00
135f0e4ce8 [nostalgia/core/studio/paletteeditor] Fix Alt shortcuts to respect keyboard focus
All checks were successful
Build / build (push) Successful in 2m30s
2024-10-02 22:50:55 -05:00
cb16687641 [studio] Add variant of InputText that returns an IString 2024-10-02 20:55:12 -05:00
cb3ef0e79d [keel] Cleanup 2024-10-02 20:54:40 -05:00
0a62d90065 [studio] Remove Editor::setRequiresConstantRefresh 2024-10-02 01:18:37 -05:00
ba7e3929e9 [nostalgia/core/studio] Make TileSheetEditor palette keys behave like PaletteEditor 2024-10-01 22:37:36 -05:00
36c4022b56 [nostalgia/core/studio] Fix PaletteEditor shortcuts to differentiate based on Alt key 2024-10-01 22:37:05 -05:00
e22b25e54c [studio] Remove Editor::requiresConstantRefresh 2024-10-01 22:35:29 -05:00
c6efabaa1d [studio,nostalgia] Fix PaletteEditor color update command merging, add setObsolete 2024-09-30 23:07:14 -05:00
1f6fefdb68 [nostalgia/core/studio] Disable PaletteEditor num key shorts when page rename is open
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-29 23:17:47 -05:00
1e34f91ebd Merge commit '34b7779397bd4712603b4c5a39ffc57b74da0abd'
All checks were successful
Build / build (push) Successful in 2m29s
2024-09-29 22:03:41 -05:00
35cb2ece9f [nostalgia/core/studio] Fix PaletteEditor color name edit 2024-09-29 16:14:26 -05:00
66cd5c4a7e [ox/std] Add CStringViewCR
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-28 23:56:14 -05:00
0daf938f76 [nostalgia/core/studio] Cleanup, make all number keys after num colors jump to last
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-28 23:44:12 -05:00
b90ab27a65 [nostalgia/core/studio] Fix Palette Color Name input to properly take focus
All checks were successful
Build / build (push) Successful in 2m34s
2024-09-28 21:51:28 -05:00
c711f4358e [nostalgia/core/studio] Fix PaletteEditor 0 key shortcut
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-28 21:42:11 -05:00
84cb03d807 [nostalgia/core/studio] Cleanup
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-28 21:37:29 -05:00
945a55f94a [studio] Fix Project to cut off correct end of OC data
All checks were successful
Build / build (push) Successful in 2m31s
2024-09-28 21:10:13 -05:00
2173b12c67 [nostalgia/core/studio] Give PaletteEditor keyboard shortcuts 2024-09-28 21:09:24 -05:00
aa970b1fc0 [keel,studio] Cleanup 2024-09-28 18:45:09 -05:00
6ad79b305c [ox] Cleanup 2024-09-28 18:44:50 -05:00
a7cf267385 [studio] Remove null terminator from OC output
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-28 18:20:01 -05:00
1a9f0d49e7 [ox] Rename CRString to StringCR
All checks were successful
Build / build (push) Successful in 2m30s
2024-09-28 17:46:45 -05:00
a1b5b56553 [olympic,nostalgia] Rename CRStringView to StringViewCR 2024-09-28 16:10:44 -05:00
256be6dae0 [glutils] Rename CRStringView to StringViewCR 2024-09-28 16:10:16 -05:00
cc10631b55 [ox] Rename CRStringView to StringViewCR 2024-09-28 16:09:43 -05:00
406 changed files with 4805 additions and 4192 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

@ -73,7 +73,7 @@ void bind(const FrameBuffer &fb) noexcept {
static ox::Result<GLShader> buildShader( static ox::Result<GLShader> buildShader(
GLuint shaderType, GLuint shaderType,
const GLchar *src, const GLchar *src,
ox::CRStringView shaderName) noexcept { ox::StringViewCR shaderName) noexcept {
GLShader shader(glCreateShader(shaderType)); GLShader shader(glCreateShader(shaderType));
glShaderSource(shader, 1, &src, nullptr); glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader); glCompileShader(shader);
@ -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_

478
deps/ox/ox-docs.md vendored Normal file
View File

@ -0,0 +1,478 @@
# Ox Docs
## Project Structure
All components have a platform indicator next to them:
(OB) - OS, Bare Metal
(-B) - Bare Metal
(O-) - OS
* Ox - Library of things useful for portable bare metal and userland code. Not really that external...
* clargs - Command Line Args processing (OB)
* claw - Reads and writes Metal or Organic Claw with header to indicate which
* event - Qt-like signal system (OB)
* fs - file system (OB)
* logconn - connects logging to Bullock (O-)
* mc - Metal Claw serialization, builds on model (OB)
* oc - Organic Claw serialization (wrapper around JsonCpp), builds on model (O-)
* model - Data structure modelling (OB)
* preloader - library for handling preloading of data (OB)
* std - Standard-ish Library with a lot missing and some things added (OB)
## Systems
### Error Handling
Ox provides ```ox::Error``` to report errors.
```ox::Error``` is a struct that has overloaded operators to behave like an
integer error code, plus some extra fields to enhance debuggability.
If instantiated through the ```OxError(x)``` macro, it will also include the
file and line of the error.
The ```OxError(x)``` macro should only be used for the initial instantiation of
an ```ox::Error```.
In addition to ```ox::Error``` there is also the template ```ox::Result<T>```.
```ox::Result``` simply wraps the type T value in a struct that also includes
error information, which allows the returning of a value and an error without
resorting to output parameters.
If a function returns an ```ox::Error``` or ```ox::Result``` it should be
declared as ```noexcept``` and all exceptions should be translated to an
```ox::Error```.
```ox::Result``` can be used as follows:
```cpp
ox::Result<int> foo(int i) noexcept {
if (i < 10) {
return i + 1; // implicitly calls ox::Result<T>::Result(T)
}
return OxError(1); // implicitly calls ox::Result<T>::Result(ox::Error)
}
int caller1() {
auto v = foo(argc);
if (v.error) {
return 1;
}
std::cout << v.value << '\n';
return 0;
}
int caller2() {
// it is also possible to capture the value and error in their own variables
auto [val, err] = foo(argc);
if (err) {
return 1;
}
std::cout << val << '\n';
return 0;
}
ox::Error caller3(int &i) {
return foo(i).moveTo(i);
}
ox::Error caller4(int &i) {
return foo(i).copyTo(i);
}
int caller5(int i) {
return foo(i).unwrap(); // unwrap will kill the program if there is an error
}
int caller6(int i) {
return foo(i).unwrapThrow(); // unwrap will throw if there is an error
}
int caller7(int i) {
return foo(i).or_value(0); // will return 0 if foo returned an error
}
ox::Result<uint64_t> caller8(int i) {
return foo(i).to<uint64_t>(); // will convert the result of foo to uint64_t
}
```
Lastly, there are a few macros available to help in passing ```ox::Error```s
back up the call stack, ```OX_RETURN_ERROR```, ```OX_THROW_ERROR```, and
```OX_REQUIRE```.
```OX_RETURN_ERROR``` is by far the more helpful of the two.
```OX_RETURN_ERROR``` will return an ```ox::Error``` if it is not 0 and
```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.
In rare cases, you may not have anything you can do with them or you may know
the code will never fail in that particular instance.
This should be used sparingly.
```cpp
void studioCode() {
auto [val, err] = foo(1);
OX_THROW_ERROR(err);
doStuff(val);
}
ox::Error engineCode() noexcept {
auto [val, err] = foo(1);
OX_RETURN_ERROR(err);
doStuff(val);
return {};
}
void anyCode() {
auto [val, err] = foo(1);
std::ignore = err;
doStuff(val);
}
```
Both macros will also take the ```ox::Result``` directly:
```cpp
void studioCode() {
auto valerr = foo(1);
OX_THROW_ERROR(valerr);
doStuff(valerr.value);
}
ox::Error engineCode() noexcept {
auto valerr = foo(1);
OX_RETURN_ERROR(valerr);
doStuff(valerr.value);
return {};
}
```
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.
Rust ```?``` operator:
```rust
fn f() -> Result<i32, i32> {
// do stuff
}
fn f2() -> Result<i32, i32> {
let i = f()?;
Ok(i + 4)
}
```
```OX_REQUIRE```:
```cpp
ox::Result<int> f() noexcept {
// do stuff
}
ox::Result<int> f2() noexcept {
OX_REQUIRE(i, f()); // const auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__))
return i + 4;
}
```
```OX_REQUIRE``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code.
```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.
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
### Logging and Output
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.
Each of these also provides a format variation.
Ox also provide ```oxOut``` and ```oxErr``` for printing to stdout and stderr.
These are intended for permanent messages and always go to stdout and stderr.
Tracing functions do not go to stdout unless the OXTRACE environment variable is set.
They also print with the channel that they are on, along with file and line.
Debug statements go to stdout and go to the logger on the "debug" channel.
Where trace statements are intended to be written with thoughtfulness,
debug statements are intended to be quick and temporary insertions.
Debug statements trigger compilation failures if OX_NODEBUG is enabled when CMake is run,
as it is on Jenkins builds, so ```oxDebug``` statements should never be checked in.
This makes ```oxDebug``` preferable to other forms of logging, as temporary prints should
never be checked in.
```oxError``` always prints.
It includes file and line, and is prefixed with a red "ERROR:".
It should generally be used conservatively.
It should be used only when there is an error that is not technically fatal, but
the user almost certainly wants to know about it.
```oxTrace``` and ```oxTracef```:
```cpp
void f(int x, int y) { // x = 9, y = 4
oxTrace("nostalgia.core.sdl.gfx") << "f:" << x << y; // Output: "f: 9 4"
oxTracef("nostalgia.core.sdl.gfx", "f: {}, {}", x, y); // Output: "f: 9, 4"
}
```
```oxDebug``` and ```oxDebugf```:
```cpp
void f(int x, int y) { // x = 9, y = 4
oxDebug() << "f:" << x << y; // Output: "f: 9 4"
oxDebugf("f: {}, {}", x, y); // Output: "f: 9, 4"
}
```
```oxError``` and ```oxErrorf```:
```cpp
void f(int x, int y) { // x = 9, y = 4
oxError() << "f:" << x << y; // Output: "ERROR: (<file>:<line>): f: 9 4"
oxErrorf("f: {}, {}", x, y); // Output: "ERROR: (<file>:<line>): f: 9, 4"
}
```
### Model System
Ox has a model system that provides a sort of manual reflection mechanism.
Models require a model function for the type that you want to model.
It is also good to provide a type name and type version number, though that is not required.
The model function takes an instance of the type it is modelling and a template
parameter type.
The template parameter type must implement the API used in the models, but it
can do anything with the data provided to it.
Here is an example from the Nostalgia/Core package:
```cpp
struct NostalgiaPalette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors;
};
struct NostalgiaGraphic {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
static constexpr auto TypeVersion = 1;
int8_t bpp = 0;
// rows and columns are really only used by TileSheetEditor
int rows = 1;
int columns = 1;
ox::FileAddress defaultPalette;
NostalgiaPalette pal;
ox::Vector<uint8_t> pixels;
};
template<typename T>
constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaPalette> auto *pal) noexcept {
h->template setTypeInfo<NostalgiaPalette>();
// it is also possible to provide the type name and type version as function arguments
//h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1);
OX_RETURN_ERROR(h->field("colors", &pal->colors));
return {};
}
template<typename T>
constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept {
h->template setTypeInfo<NostalgiaGraphic>();
OX_RETURN_ERROR(h->field("bpp", &ng->bpp));
OX_RETURN_ERROR(h->field("rows", &ng->rows));
OX_RETURN_ERROR(h->field("columns", &ng->columns));
OX_RETURN_ERROR(h->field("defaultPalette", &ng->defaultPalette));
OX_RETURN_ERROR(h->field("pal", &ng->pal));
OX_RETURN_ERROR(h->field("pixels", &ng->pixels));
return {};
}
```
The model system also provides for unions:
```cpp
#include <ox/model/types.hpp>
class FileAddress {
template<typename T>
friend constexpr Error model(T*, ox::CommonPtrWith<FileAddress> auto*) noexcept;
public:
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
union Data {
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress.Data";
char *path;
const char *constPath;
uint64_t inode;
};
protected:
FileAddressType m_type = FileAddressType::None;
Data m_data;
};
template<typename T>
constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
h->template setTypeInfo<FileAddress::Data>();
OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {};
}
template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept {
io->template setTypeInfo<FileAddress>();
// cannot read from object in Reflect operation
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
int8_t type = 0;
OX_RETURN_ERROR(io->field("type", &type));
OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, 0)));
} else {
auto type = static_cast<int8_t>(fa->m_type);
OX_RETURN_ERROR(io->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type);
OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
}
return {};
}
```
There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models:
```cpp
OX_MODEL_BEGIN(NostalgiaGraphic)
OX_MODEL_FIELD(bpp)
OX_MODEL_FIELD(rows)
OX_MODEL_FIELD(columns)
OX_MODEL_FIELD(defaultPalette)
OX_MODEL_FIELD(pal)
OX_MODEL_FIELD(pixels)
oxModelEnd()
```
### Serialization
Using the model system, Ox provides for serialization.
Ox has MetalClaw and OrganicClaw as its serialization format options.
MetalClaw is a custom binary format designed for minimal size.
OrganicClaw is a wrapper around JsonCpp, chosen because it technically
implements a superset of JSON.
OrganicClaw requires support for 64 bit integers, whereas normal JSON
technically does not.
These formats do not currently support floats.
There is also a wrapper format called Claw that provides a header at the
beginning of the file and can dynamically switch between the two depending on
what the header says is present.
The Claw header also includes information about the type and type version of
the data.
Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;```
That reads:
* Format is Metal Claw, version 1
* Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette
* Type version is 1
#### Metal Claw Example
##### Read
```cpp
#include <ox/mc/read.hpp>
ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
return ox::readMC<NostalgiaPalette>(buff);
}
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal;
OX_RETURN_ERROR(ox::readMC(buff, pal));
return pal;
}
```
##### Write
```cpp
#include <ox/mc/write.hpp>
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB);
std::size_t sz = 0;
OX_RETURN_ERROR(ox::writeMC(buffer.data(), buffer.size(), pal, &sz));
buffer.resize(sz);
return buffer;
}
ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette const&pal) noexcept {
return ox::writeMC(pal);
}
```
#### Organic Claw Example
##### Read
```cpp
#include <ox/oc/read.hpp>
ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
return ox::readOC<NostalgiaPalette>(buff);
}
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal;
OX_RETURN_ERROR(ox::readOC(buff, &pal));
return pal;
}
```
##### Write
```cpp
#include <ox/oc/write.hpp>
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB);
OX_RETURN_ERROR(ox::writeOC(buffer.data(), buffer.size(), pal));
return buffer;
}
ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette const&pal) noexcept {
return ox::writeOC(pal);
}
```
#### Claw Example
##### Read
```cpp
#include <ox/claw/read.hpp>
ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
return ox::readClaw<NostalgiaPalette>(buff);
}
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal;
OX_RETURN_ERROR(ox::readClaw(buff, pal));
return pal;
}
```
##### Write
```cpp
#include <ox/claw/write.hpp>
ox::Result<ox::Buffer> writeSpritePalette(NostalgiaPalette const&pal) noexcept {
return ox::writeClaw(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") {
@ -37,33 +39,33 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
} }
} }
bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept { bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg); auto [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue; return !err ? *value : defaultValue;
} }
String ClArgs::getString(ox::CRStringView arg, ox::StringView defaultValue) const noexcept { String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept {
auto [value, err] = m_strings.at(arg); auto [value, err] = m_strings.at(arg);
return !err ? ox::String(*value) : ox::String(defaultValue); return !err ? ox::String(*value) : ox::String(defaultValue);
} }
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept { int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg); auto [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue; return !err ? *value : defaultValue;
} }
Result<bool> ClArgs::getBool(ox::CRStringView 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::CRStringView 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::CRStringView 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,22 +23,24 @@ class ClArgs {
public: public:
ClArgs(int argc, const char **args) noexcept; ClArgs(int argc, const char **args) noexcept;
[[nodiscard]] ClArgs(ox::SpanView<const char*> args) noexcept;
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
[[nodiscard]] [[nodiscard]]
String getString(ox::CRStringView argName, ox::StringView defaultValue) const noexcept; bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept;
[[nodiscard]] [[nodiscard]]
int getInt(ox::CRStringView arg, int defaultValue) const noexcept; String getString(ox::StringViewCR argName, ox::StringView defaultValue) const noexcept;
[[nodiscard]] [[nodiscard]]
Result<bool> getBool(ox::CRStringView arg) const noexcept; int getInt(ox::StringViewCR arg, int defaultValue) const noexcept;
[[nodiscard]] [[nodiscard]]
Result<String> getString(ox::CRStringView argName) const noexcept; Result<bool> getBool(ox::StringViewCR arg) const noexcept;
Result<int> getInt(ox::CRStringView arg) const noexcept; [[nodiscard]]
Result<String> getString(ox::StringViewCR argName) const noexcept;
Result<int> getInt(ox::StringViewCR arg) 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>
@ -43,7 +45,7 @@ struct OX_PACKED DirectoryEntry {
public: public:
constexpr DirectoryEntry() noexcept = default; constexpr DirectoryEntry() noexcept = default;
Error init(InodeId_t inode, ox::CRStringView name, size_t bufferSize) noexcept { Error init(InodeId_t inode, ox::StringViewCR name, size_t bufferSize) noexcept {
oxTracef("ox.fs.DirectoryEntry.init", "inode: {}, name: {}, bufferSize: {}", inode, name, bufferSize); oxTracef("ox.fs.DirectoryEntry.init", "inode: {}, name: {}, bufferSize: {}", inode, name, bufferSize);
m_bufferSize = static_cast<InodeId_t>(bufferSize); m_bufferSize = static_cast<InodeId_t>(bufferSize);
auto d = data(); auto d = data();
@ -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");
} }
@ -284,12 +286,12 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
} }
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(CRStringView name) const noexcept { Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(StringViewCR name) const noexcept {
oxTrace("ox.fs.Directory.findEntry", name); oxTrace("ox.fs.Directory.findEntry", 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()) {
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
@ -28,11 +28,13 @@ FileAddress::FileAddress(uint64_t inode) noexcept {
m_type = FileAddressType::Inode; m_type = FileAddressType::Inode;
} }
FileAddress::FileAddress(ox::CRStringView path) noexcept { 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;
} }
@ -114,7 +116,7 @@ bool FileAddress::operator==(FileAddress const&other) const noexcept {
return true; return true;
} }
bool FileAddress::operator==(CRStringView path) const noexcept { bool FileAddress::operator==(StringViewCR path) const noexcept {
auto [p, err] = getPath(); auto [p, err] = getPath();
if (err) { if (err) {
return false; return false;

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 {
@ -57,7 +59,7 @@ class FileAddress {
FileAddress(uint64_t inode) noexcept; FileAddress(uint64_t inode) noexcept;
explicit FileAddress(CRStringView path) noexcept; explicit FileAddress(StringViewCR path) noexcept;
constexpr FileAddress(ox::StringLiteral path) noexcept; constexpr FileAddress(ox::StringLiteral path) noexcept;
@ -69,7 +71,7 @@ class FileAddress {
bool operator==(const FileAddress &other) const noexcept; bool operator==(const FileAddress &other) const noexcept;
bool operator==(CRStringView path) const noexcept; bool operator==(StringViewCR path) const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr FileAddressType type() const noexcept { constexpr FileAddressType type() const noexcept {
@ -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(CRStringView 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
@ -30,22 +30,22 @@ class FileSystem {
public: public:
virtual ~FileSystem() noexcept = default; virtual ~FileSystem() noexcept = default;
virtual Error mkdir(CRStringView path, bool recursive) noexcept = 0; virtual Error mkdir(StringViewCR path, bool recursive) noexcept = 0;
/** /**
* Moves an entry from one directory to another. * Moves an entry from one directory to another.
* @param src the path to the file * @param src the path to the file
* @param dest the path of the destination directory * @param dest the path of the destination directory
*/ */
virtual Error move(CRStringView src, CRStringView dest) noexcept = 0; virtual Error move(StringViewCR src, StringViewCR dest) noexcept = 0;
Error read(const FileAddress &addr, void *buffer, std::size_t size) noexcept; Error read(const FileAddress &addr, void *buffer, std::size_t size) noexcept;
Result<Buffer> read(const FileAddress &addr) noexcept; Result<Buffer> read(const FileAddress &addr) noexcept;
Result<Buffer> read(CRStringView path) noexcept; Result<Buffer> read(StringViewCR path) noexcept;
inline Error read(CRStringView path, void *buffer, std::size_t buffSize) noexcept { inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
return readFilePath(path, buffer, buffSize); return readFilePath(path, buffer, buffSize);
} }
@ -55,19 +55,19 @@ class FileSystem {
Error read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept; Error read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept;
virtual Result<Vector<String>> ls(CRStringView dir) const noexcept = 0; virtual Result<Vector<String>> ls(StringViewCR dir) const noexcept = 0;
virtual Error remove(CRStringView path, bool recursive) noexcept = 0; virtual Error remove(StringViewCR path, bool recursive) noexcept = 0;
Error remove(const FileAddress &addr, bool recursive = false) noexcept; Error remove(const FileAddress &addr, bool recursive = false) noexcept;
virtual Error resize(uint64_t size, void *buffer) noexcept = 0; virtual Error resize(uint64_t size, void *buffer) noexcept = 0;
Error write(CRStringView path, const void *buffer, uint64_t size) noexcept { Error write(StringViewCR path, const void *buffer, uint64_t size) noexcept {
return writeFilePath(path, buffer, size, FileType::NormalFile); return writeFilePath(path, buffer, size, FileType::NormalFile);
} }
Error write(CRStringView path, ox::Span<char> const&buff) noexcept { Error write(StringViewCR path, ox::Span<char> const&buff) noexcept {
return write(path, buff.data(), buff.size(), FileType::NormalFile); return write(path, buff.data(), buff.size(), FileType::NormalFile);
} }
@ -81,7 +81,7 @@ class FileSystem {
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept { inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
return writeFilePath(path, buffer, size, fileType); return writeFilePath(path, buffer, size, fileType);
} }
@ -93,7 +93,7 @@ class FileSystem {
return statInode(inode); return statInode(inode);
} }
inline Result<FileStat> stat(CRStringView path) const noexcept { inline Result<FileStat> stat(StringViewCR path) const noexcept {
return statPath(path); return statPath(path);
} }
@ -134,15 +134,15 @@ class FileSystem {
protected: protected:
virtual Result<FileStat> statInode(uint64_t inode) const noexcept = 0; virtual Result<FileStat> statInode(uint64_t inode) const noexcept = 0;
virtual Result<FileStat> statPath(CRStringView path) const noexcept = 0; virtual Result<FileStat> statPath(StringViewCR path) const noexcept = 0;
virtual Error readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept = 0; virtual Error readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept = 0;
virtual Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept = 0; virtual Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept = 0;
virtual Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept = 0; virtual Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept = 0;
virtual Error writeFilePath(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept = 0; virtual Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept = 0;
virtual Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept = 0; virtual Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept = 0;
@ -152,7 +152,7 @@ class MemFS: public FileSystem {
public: public:
Result<const char*> directAccess(const FileAddress &addr) const noexcept; Result<const char*> directAccess(const FileAddress &addr) const noexcept;
inline Result<const char*> directAccess(CRStringView path) const noexcept { inline Result<const char*> directAccess(StringViewCR path) const noexcept {
return directAccessPath(path); return directAccessPath(path);
} }
@ -161,7 +161,7 @@ class MemFS: public FileSystem {
} }
protected: protected:
virtual Result<const char*> directAccessPath(CRStringView path) const noexcept = 0; virtual Result<const char*> directAccessPath(StringViewCR path) const noexcept = 0;
virtual Result<const char*> directAccessInode(uint64_t inode) const noexcept = 0; virtual Result<const char*> directAccessInode(uint64_t inode) const noexcept = 0;
}; };
@ -197,13 +197,13 @@ class FileSystemTemplate: public MemFS {
static Error format(void *buff, uint64_t buffSize) noexcept; static Error format(void *buff, uint64_t buffSize) noexcept;
Error mkdir(CRStringView path, bool recursive) noexcept override; Error mkdir(StringViewCR path, bool recursive) noexcept override;
Error move(CRStringView src, CRStringView dest) noexcept override; Error move(StringViewCR src, StringViewCR dest) noexcept override;
Error readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept override; Error readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept override;
Result<const char*> directAccessPath(CRStringView) const noexcept override; Result<const char*> directAccessPath(StringViewCR) const noexcept override;
Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override; Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override;
@ -211,12 +211,12 @@ class FileSystemTemplate: public MemFS {
Result<const char*> directAccessInode(uint64_t) const noexcept override; Result<const char*> directAccessInode(uint64_t) const noexcept override;
Result<Vector<String>> ls(CRStringView dir) const noexcept override; Result<Vector<String>> ls(StringViewCR dir) const noexcept override;
template<typename F> template<typename F>
Error ls(CRStringView path, F cb) const; Error ls(StringViewCR path, F cb) const;
Error remove(CRStringView path, bool recursive) noexcept override; Error remove(StringViewCR path, bool recursive) noexcept override;
/** /**
* Resizes FileSystem to minimum possible size. * Resizes FileSystem to minimum possible size.
@ -225,13 +225,13 @@ class FileSystemTemplate: public MemFS {
Error resize(uint64_t size, void *buffer) noexcept override; Error resize(uint64_t size, void *buffer) noexcept override;
Error writeFilePath(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept override;
Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override;
Result<FileStat> statInode(uint64_t inode) const noexcept override; Result<FileStat> statInode(uint64_t inode) const noexcept override;
Result<FileStat> statPath(CRStringView path) const noexcept override; Result<FileStat> statPath(StringViewCR path) const noexcept override;
[[nodiscard]] [[nodiscard]]
uint64_t spaceNeeded(uint64_t size) const noexcept override; uint64_t spaceNeeded(uint64_t size) const noexcept override;
@ -253,7 +253,7 @@ class FileSystemTemplate: public MemFS {
/** /**
* Finds the inode ID at the given path. * Finds the inode ID at the given path.
*/ */
Result<uint64_t> find(CRStringView path) const noexcept; Result<uint64_t> find(StringViewCR path) const noexcept;
Result<Directory> rootDir() const noexcept; Result<Directory> rootDir() const noexcept;
@ -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(CRStringView 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(CRStringView src, CRStringView 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(CRStringView 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(CRStringView 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,36 +360,36 @@ 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());
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(CRStringView path) const noexcept { Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept {
Vector<String> out; Vector<String> out;
oxReturnError(ls(path, [&out](CRStringView 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;
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
template<typename F> template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(CRStringView 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(CRStringView 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(CRStringView 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,24 +410,24 @@ 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 {};
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::writeFilePath( Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
CRStringView path, StringViewCR path,
const void *buffer, const void *buffer,
uint64_t size, uint64_t size,
FileType fileType) noexcept { FileType fileType) noexcept {
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;
@ -449,8 +449,8 @@ 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(CRStringView 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(CRStringView 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
@ -17,7 +17,7 @@
namespace ox { namespace ox {
PassThroughFS::PassThroughFS(CRStringView dirPath) { PassThroughFS::PassThroughFS(StringViewCR dirPath) {
m_path = std::string_view(dirPath.data(), dirPath.bytes()); m_path = std::string_view(dirPath.data(), dirPath.bytes());
} }
@ -27,7 +27,7 @@ String PassThroughFS::basePath() const noexcept {
return ox::String(m_path.string().c_str()); return ox::String(m_path.string().c_str());
} }
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept { Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
bool success = false; bool success = false;
const auto p = m_path / stripSlash(path); const auto p = m_path / stripSlash(path);
const auto u8p = p.u8string(); const auto u8p = p.u8string();
@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(CRStringView 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(CRStringView 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(CRStringView src, CRStringView 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(CRStringView 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()));
@ -75,25 +75,25 @@ Result<Vector<String>> PassThroughFS::ls(CRStringView dir) const noexcept {
return out; return out;
} }
Error PassThroughFS::remove(CRStringView 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(CRStringView path) const noexcept { Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
std::error_code ec; std::error_code ec;
const auto p = m_path / stripSlash(path); const auto p = m_path / stripSlash(path);
const FileType type = std::filesystem::is_directory(p, ec) ? const FileType type = std::filesystem::is_directory(p, ec) ?
@ -101,7 +101,7 @@ Result<FileStat> PassThroughFS::statPath(CRStringView 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 {
@ -140,48 +140,48 @@ bool PassThroughFS::valid() const noexcept {
return false; return false;
} }
Error PassThroughFS::readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept { Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
try { try {
std::ifstream file((m_path / stripSlash(path)), std::ios::binary | std::ios::ate); std::ifstream file((m_path / stripSlash(path)), std::ios::binary | std::ios::ate);
const std::size_t size = static_cast<std::size_t>(file.tellg()); const std::size_t size = static_cast<std::size_t>(file.tellg());
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(CRStringView path, const void *buffer, uint64_t size, FileType) noexcept { Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept {
const auto p = (m_path / stripSlash(path)); const auto p = (m_path / stripSlash(path));
try { try {
std::ofstream f(p, std::ios::binary); std::ofstream f(p, std::ios::binary);
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
@ -29,29 +29,29 @@ class PassThroughFS: public FileSystem {
std::filesystem::path m_path; std::filesystem::path m_path;
public: public:
explicit PassThroughFS(CRStringView dirPath); explicit PassThroughFS(StringViewCR dirPath);
~PassThroughFS() noexcept override; ~PassThroughFS() noexcept override;
[[nodiscard]] [[nodiscard]]
String basePath() const noexcept; String basePath() const noexcept;
Error mkdir(CRStringView path, bool recursive) noexcept override; Error mkdir(StringViewCR path, bool recursive) noexcept override;
Error move(CRStringView src, CRStringView dest) noexcept override; Error move(StringViewCR src, StringViewCR dest) noexcept override;
Result<Vector<String>> ls(CRStringView dir) const noexcept override; Result<Vector<String>> ls(StringViewCR dir) const noexcept override;
template<typename F> template<typename F>
Error ls(CRStringView dir, F cb) const noexcept; Error ls(StringViewCR dir, F cb) const noexcept;
Error remove(CRStringView path, bool recursive) noexcept override; Error remove(StringViewCR path, bool recursive) noexcept override;
Error resize(uint64_t size, void *buffer) noexcept override; Error resize(uint64_t size, void *buffer) noexcept override;
Result<FileStat> statInode(uint64_t inode) const noexcept override; Result<FileStat> statInode(uint64_t inode) const noexcept override;
Result<FileStat> statPath(CRStringView path) const noexcept override; Result<FileStat> statPath(StringViewCR path) const noexcept override;
[[nodiscard]] [[nodiscard]]
uint64_t spaceNeeded(uint64_t size) const noexcept override; uint64_t spaceNeeded(uint64_t size) const noexcept override;
@ -69,13 +69,13 @@ class PassThroughFS: public FileSystem {
bool valid() const noexcept override; bool valid() const noexcept override;
protected: protected:
Error readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept override; Error readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept override;
Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override; Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override;
Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override; Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override;
Error writeFilePath(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept override;
Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override;
@ -89,14 +89,14 @@ class PassThroughFS: public FileSystem {
}; };
template<typename F> template<typename F>
Error PassThroughFS::ls(CRStringView 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) {
@ -22,7 +24,7 @@ PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t it
PathIterator::PathIterator(const char *path): PathIterator(path, ox::strlen(path)) { PathIterator::PathIterator(const char *path): PathIterator(path, ox::strlen(path)) {
} }
PathIterator::PathIterator(CRStringView path): PathIterator(path.data(), path.bytes()) { PathIterator::PathIterator(StringViewCR path): PathIterator(path.data(), path.bytes()) {
} }
/** /**
@ -30,13 +32,13 @@ PathIterator::PathIterator(CRStringView 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
@ -25,7 +25,7 @@ class PathIterator {
PathIterator(const char *path); PathIterator(const char *path);
PathIterator(CRStringView path); PathIterator(StringViewCR path);
Error dirPath(char *pathOut, std::size_t pathOutSize); Error dirPath(char *pathOut, std::size_t pathOutSize);

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
@ -51,13 +58,13 @@ LoggerConn::~LoggerConn() noexcept {
} }
} }
ox::Error LoggerConn::initConn(ox::CRStringView appName) noexcept { ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept {
sockaddr_in addr{}; sockaddr_in addr{};
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
@ -38,20 +38,20 @@ class LoggerConn: public trace::Logger {
LoggerConn &operator=(const LoggerConn&) noexcept = delete; LoggerConn &operator=(const LoggerConn&) noexcept = delete;
ox::Error send(const trace::TraceMsg&) noexcept final; ox::Error send(const trace::TraceMsg&) noexcept final;
ox::Error sendInit(const trace::InitTraceMsg&) noexcept final; ox::Error sendInit(const trace::InitTraceMsg&) noexcept final;
ox::Error initConn(ox::CRStringView appName) noexcept; ox::Error initConn(ox::StringViewCR appName) noexcept;
ox::Error send(const char *buff, std::size_t len) const noexcept; ox::Error send(const char *buff, std::size_t len) const noexcept;
private: private:
void msgSend() noexcept; void msgSend() noexcept;
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);
} }
}, },
@ -316,10 +316,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Union.Int = 93; testIn.Union.Int = 93;
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed"); oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed");
ox::TypeStore typeStore; ox::TypeStore typeStore;
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);
} }
}, },
@ -368,10 +368,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Struct.IString = "Test String 2"; testIn.Struct.IString = "Test String 2";
oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed"); oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed");
ox::TypeStore typeStore; ox::TypeStore typeStore;
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
@ -35,7 +35,7 @@ constexpr auto buildTypeId() noexcept {
} }
static constexpr auto buildTypeId( static constexpr auto buildTypeId(
CRStringView name, int version, StringViewCR name, int version,
const TypeParamPack &typeParams = {}) noexcept { const TypeParamPack &typeParams = {}) noexcept {
String tp; String tp;
if (!typeParams.empty()) { if (!typeParams.empty()) {
@ -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
@ -91,23 +91,29 @@ class TypeDescWriter {
constexpr ~TypeDescWriter() noexcept = default; constexpr ~TypeDescWriter() noexcept = default;
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(CRStringView name = T::TypeName, constexpr ox::Error setTypeInfo(StringViewCR name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const TypeParamPack &typeParams = {}, const TypeParamPack &typeParams = {},
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(CRStringView name, const T *val, std::size_t valLen, constexpr Error field(
const SubscriptStack &subscriptStack = {}) noexcept; StringViewCR name,
T const*val,
template<typename T, bool force> std::size_t valLen,
constexpr Error field(CRStringView name, UnionView<T, force> val) noexcept; SubscriptStack const&subscriptStack) noexcept;
template<typename T> template<typename T>
constexpr Error field(CRStringView name, const T *val) noexcept; constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept;
template<typename T, bool force>
constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept;
template<typename T>
constexpr Error field(StringViewCR name, const T *val) noexcept;
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(CRStringView name, Args&&...) noexcept; constexpr Error fieldCString(StringViewCR name, Args&&...) noexcept;
[[nodiscard]] [[nodiscard]]
constexpr DescriptorType *definition() noexcept { constexpr DescriptorType *definition() noexcept {
@ -167,7 +173,7 @@ class TypeDescWriter {
constexpr const DescriptorType *type(UnionView<U> val) const noexcept; constexpr const DescriptorType *type(UnionView<U> val) const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr const DescriptorType *getType(CRStringView tn, int typeVersion, PrimitiveType t, int b, constexpr const DescriptorType *getType(StringViewCR tn, int typeVersion, PrimitiveType t, int b,
const TypeParamPack &typeParams = {}) const noexcept; const TypeParamPack &typeParams = {}) const noexcept;
}; };
@ -176,7 +182,7 @@ constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeS
template<typename T> template<typename T>
constexpr ox::Error TypeDescWriter::setTypeInfo( constexpr ox::Error TypeDescWriter::setTypeInfo(
CRStringView typeName, int typeVersion, StringViewCR typeName, int typeVersion,
const TypeParamPack &typeParams, std::size_t) noexcept { const TypeParamPack &typeParams, std::size_t) noexcept {
PrimitiveType pt; PrimitiveType pt;
if constexpr(is_union_v<T>) { if constexpr(is_union_v<T>) {
@ -193,30 +199,45 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
// array handler // array handler
template<typename T> template<typename T>
constexpr Error TypeDescWriter::field(CRStringView 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>
constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val) noexcept { constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val) noexcept {
if (m_type) { if (m_type) {
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>
constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept { constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept {
if (m_type) { if (m_type) {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
typename T::value_type *data = nullptr; typename T::value_type *data = nullptr;
@ -233,11 +254,11 @@ constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept
return {}; return {};
} }
} }
return OxError(1); return ox::Error(1);
} }
template<typename ...Args> template<typename ...Args>
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept { constexpr Error TypeDescWriter::fieldCString(StringViewCR name, Args&&...) noexcept {
constexpr auto s = ""; constexpr auto s = "";
const auto t = type(s); const auto t = type(s);
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
@ -339,7 +360,7 @@ constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const n
return getType(types::BString, 0, PT, 0); return getType(types::BString, 0, PT, 0);
} }
constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typeVersion, PrimitiveType pt, int b, constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b,
const TypeParamPack &typeParams) const noexcept { const TypeParamPack &typeParams) const noexcept {
auto t = m_typeStore->get(tn, typeVersion, typeParams); auto t = m_typeStore->get(tn, typeVersion, typeParams);
if (!t.error) { if (!t.error) {
@ -357,26 +378,26 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
} }
template<typename T> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
TypeDescWriter writer(typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
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();
} }
template<typename T> 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
@ -24,32 +24,32 @@ class FieldCounter {
std::size_t fields = 0; std::size_t fields = 0;
template<typename U = std::nullptr_t> template<typename U = std::nullptr_t>
constexpr ox::Error setTypeInfo(CRStringView = "", int = 0, const Vector<String>& = {}, std::size_t = 0) { constexpr ox::Error setTypeInfo(StringViewCR = "", int = 0, const Vector<String>& = {}, std::size_t = 0) {
return {}; return {};
} }
template<typename U> template<typename U>
constexpr ox::Error field(CRStringView, 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(CRStringView, 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(CRStringView, 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;
} }
@ -652,7 +654,7 @@ class ModelObject {
} }
[[nodiscard]] [[nodiscard]]
constexpr CRString typeName() const noexcept { constexpr StringCR typeName() const noexcept {
return m_type->typeName; return m_type->typeName;
} }
@ -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,11 +40,11 @@ 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();
} }
constexpr DescriptorType *getInit(CRStringView typeName, int typeVersion, PrimitiveType pt, constexpr DescriptorType *getInit(StringViewCR typeName, int typeVersion, PrimitiveType pt,
const TypeParamPack &typeParams) noexcept { const TypeParamPack &typeParams) noexcept {
const auto typeId = buildTypeId(typeName, typeVersion, typeParams); const auto typeId = buildTypeId(typeName, typeVersion, typeParams);
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
@ -56,15 +56,19 @@ 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)); if (typeId == f.typeId) {
f.type = dt.get();
} else {
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,10 +106,10 @@ 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::CRStringView name, int version, Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version,
const ox::TypeParamPack &typeParams) noexcept { const ox::TypeParamPack &typeParams) noexcept {
const auto typeId = buildTypeId(name, version, typeParams); const auto typeId = buildTypeId(name, version, typeParams);
return loadDescriptor(typeId); return loadDescriptor(typeId);

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);
} }
}, },
@ -207,10 +207,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Union.Int = 93; testIn.Union.Int = 93;
oxAssert(ox::writeOC(testIn).moveTo(dataBuff), "Data generation failed"); oxAssert(ox::writeOC(testIn).moveTo(dataBuff), "Data generation failed");
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");
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);
} }
}, },
@ -257,9 +257,9 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
auto [oc, ocErr] = ox::writeOC(testIn); auto [oc, ocErr] = ox::writeOC(testIn);
oxAssert(ocErr, "Data generation failed"); oxAssert(ocErr, "Data generation failed");
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
@ -46,12 +46,12 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
} }
template<typename T, bool force> template<typename T, bool force>
constexpr ox::Error field(CRStringView name, const UnionView<T, force> val) noexcept { constexpr ox::Error field(StringViewCR name, const UnionView<T, force> val) noexcept {
return field(name, val.get()); return field(name, val.get());
} }
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, const T *val) noexcept { constexpr ox::Error field(StringViewCR, const T *val) noexcept {
if constexpr(ox::is_pointer_v<T> || ox::is_integer_v<T>) { if constexpr(ox::is_pointer_v<T> || ox::is_integer_v<T>) {
biggestAlignment = ox::max(biggestAlignment, PlatSpec::alignOf(*val)); biggestAlignment = ox::max(biggestAlignment, PlatSpec::alignOf(*val));
} else { } else {
@ -61,9 +61,9 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
} }
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, 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
@ -94,19 +94,19 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
} }
template<typename U, bool force> template<typename U, bool force>
constexpr ox::Error field(CRStringView, ox::UnionView<U, force> val) noexcept; constexpr ox::Error field(StringViewCR, ox::UnionView<U, force> val) noexcept;
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, const T *val) noexcept; constexpr ox::Error field(StringViewCR, const T *val) noexcept;
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr ox::Error field(CRStringView, const ox::BasicString<SmallStringSize> *val) noexcept; constexpr ox::Error field(StringViewCR, const ox::BasicString<SmallStringSize> *val) noexcept;
template<typename T, std::size_t sz> template<typename T, std::size_t sz>
constexpr ox::Error field(CRStringView, const ox::Array<T, sz> *valArray) noexcept; constexpr ox::Error field(StringViewCR, const ox::Array<T, sz> *valArray) noexcept;
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, const T **val, std::size_t cnt) noexcept; constexpr ox::Error field(StringViewCR, const T **val, std::size_t cnt) noexcept;
constexpr ox::Result<std::size_t> startAlloc(size_t sz, size_t align) noexcept; constexpr ox::Result<std::size_t> startAlloc(size_t sz, size_t align) noexcept;
@ -125,14 +125,14 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
constexpr ox::Error pad(const T*) noexcept; constexpr ox::Error pad(const T*) noexcept;
private: private:
constexpr ox::Error fieldVector(CRStringView name, const ox::ModelValueVector *val) noexcept; constexpr ox::Error fieldVector(StringViewCR name, const ox::ModelValueVector *val) noexcept;
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr ox::Error fieldVector(CRStringView, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept; constexpr ox::Error fieldVector(StringViewCR, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept;
constexpr ox::Error fieldVector(CRStringView, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept; constexpr ox::Error fieldVector(StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept;
constexpr ox::Error fieldArray(CRStringView name, ox::ModelValueArray const*val) noexcept; constexpr ox::Error fieldArray(StringViewCR name, ox::ModelValueArray const*val) noexcept;
constexpr bool unionCheckAndIt() noexcept; constexpr bool unionCheckAndIt() noexcept;
@ -158,11 +158,11 @@ Preloader<PlatSpec>::make(ox::ios_base::seekdir anchor, std::size_t sz) noexcept
template<typename PlatSpec> template<typename PlatSpec>
template<typename U, bool force> template<typename U, bool force>
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::UnionView<U, force> val) noexcept { constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::UnionView<U, force> val) noexcept {
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();
@ -171,17 +171,17 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::UnionView
template<typename PlatSpec> template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const T *val) noexcept { constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const T *val) noexcept {
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);
@ -200,7 +200,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const T *val)
template<typename PlatSpec> template<typename PlatSpec>
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::BasicString<SmallStringSize> *val) noexcept { constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::BasicString<SmallStringSize> *val) noexcept {
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
@ -211,35 +211,35 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, 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 {};
} }
template<typename PlatSpec> template<typename PlatSpec>
template<typename T, std::size_t sz> template<typename T, std::size_t sz>
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const ox::Array<T, sz> *val) noexcept { constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const ox::Array<T, sz> *val) noexcept {
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();
} }
@ -248,16 +248,16 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const ox::Arra
template<typename PlatSpec> template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const T **val, std::size_t cnt) noexcept { constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept {
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
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(CRStringView, 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 {};
} }
@ -327,7 +327,7 @@ constexpr ox::Error Preloader<PlatSpec>::pad(const T *v) noexcept {
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
CRStringView name, const ox::ModelValueVector *val) noexcept { StringViewCR name, const ox::ModelValueVector *val) noexcept {
// serialize the Vector // serialize the Vector
ox::VectorMemMap<PlatSpec> vecVal{ ox::VectorMemMap<PlatSpec> vecVal{
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())), .size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())),
@ -339,7 +339,7 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
CRStringView name, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept { StringViewCR name, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept {
// serialize the Vector // serialize the Vector
ox::VectorMemMap<PlatSpec> vecVal{ ox::VectorMemMap<PlatSpec> vecVal{
.smallVecSize = SmallVectorSize * sizeOf<PlatSpec>(static_cast<T*>(nullptr)), .smallVecSize = SmallVectorSize * sizeOf<PlatSpec>(static_cast<T*>(nullptr)),
@ -353,40 +353,40 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
CRStringView, 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(CRStringView, 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
@ -41,18 +41,18 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
} }
template<typename T, bool force> template<typename T, bool force>
constexpr ox::Error field(CRStringView, 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 {};
} }
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, const T *val) noexcept; constexpr ox::Error field(StringViewCR, const T *val) noexcept;
template<typename T> template<typename T>
constexpr ox::Error field(CRStringView, const T **val, std::size_t cnt) noexcept; constexpr ox::Error field(StringViewCR, const T **val, std::size_t cnt) noexcept;
[[nodiscard]] [[nodiscard]]
constexpr auto size() const noexcept { constexpr auto size() const noexcept {
@ -61,33 +61,33 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
private: private:
template<typename T, std::size_t SmallVecSize> template<typename T, std::size_t SmallVecSize>
constexpr ox::Error fieldStr(CRStringView, const ox::BasicString<SmallVecSize> *val) noexcept; constexpr ox::Error fieldStr(StringViewCR, const ox::BasicString<SmallVecSize> *val) noexcept;
template<typename T, std::size_t SmallVecSize> template<typename T, std::size_t SmallVecSize>
constexpr ox::Error fieldVector(CRStringView, const ox::Vector<T, SmallVecSize> *val) noexcept; constexpr ox::Error fieldVector(StringViewCR, const ox::Vector<T, SmallVecSize> *val) noexcept;
constexpr void setSize(std::size_t sz) noexcept; constexpr void setSize(std::size_t sz) noexcept;
}; };
template<typename PlatSpec> template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(CRStringView, const T *val) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T *val) noexcept {
setSize(sizeOf<PlatSpec>(val)); setSize(sizeOf<PlatSpec>(val));
return {}; return {};
} }
template<typename PlatSpec> template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(CRStringView, 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 {};
} }
template<typename PlatSpec> template<typename PlatSpec>
template<typename T, std::size_t SmallStrSize> template<typename T, std::size_t SmallStrSize>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldStr(CRStringView, const ox::BasicString<SmallStrSize>*) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldStr(StringViewCR, const ox::BasicString<SmallStrSize>*) noexcept {
ox::VectorMemMap<PlatSpec> v; ox::VectorMemMap<PlatSpec> v;
setSize(sizeOf<PlatSpec>(v)); setSize(sizeOf<PlatSpec>(v));
return {}; return {};
@ -95,7 +95,7 @@ constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldStr(CRStringView, const ox:
template<typename PlatSpec> template<typename PlatSpec>
template<typename T, std::size_t SmallVecSize> template<typename T, std::size_t SmallVecSize>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldVector(CRStringView, const ox::Vector<T, SmallVecSize>*) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldVector(StringViewCR, const ox::Vector<T, SmallVecSize>*) noexcept {
ox::VectorMemMap<PlatSpec> v; ox::VectorMemMap<PlatSpec> v;
setSize(sizeOf<PlatSpec>(v)); setSize(sizeOf<PlatSpec>(v));
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(CRStringView file, int line, CRStringView 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(CRStringView file, int line, CRStringView 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,51 +32,30 @@ constexpr void constexprPanic(CRStringView file, int line, CRStringView panicMsg
} }
} }
constexpr void assertFunc(CRStringView file, int line, bool pass, [[maybe_unused]]CRStringView assertTxt, [[maybe_unused]]CRStringView msg) noexcept { void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept;
void assertFailFuncRuntime(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept;
constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept {
if (!pass) { if (!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);
} }
} }
} }
constexpr void assertFunc(CRStringView file, int line, const Error &err, CRStringView, CRStringView 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);
} }
} }
} }
constexpr void expect(CRStringView file, int line, const auto &actual, const auto &expected) noexcept { constexpr void expect(StringViewCR file, int line, const auto &actual, const auto &expected) noexcept {
if (actual != expected) { if (actual != expected) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB) #if defined(OX_USE_STDLIB)

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