Compare commits

...

174 Commits

Author SHA1 Message Date
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
829dc0298e [keel] Fix Linux build
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-27 02:46:06 -05:00
e8a1ff0643 [ox/oc] Fix Linux build 2024-09-27 02:44:25 -05:00
bdfb5e972a [nostalgia/core] Cleanup 2024-09-27 02:31:54 -05:00
396fecab5b [ox/oc] Add option for writeOC to return a string 2024-09-27 02:31:08 -05:00
5373b63cca [keel,studio] Removing null terminator from JSON file output 2024-09-27 02:30:28 -05:00
8b655c40b9 [ox/std] Add HashMap::values 2024-09-21 16:12:37 -05:00
92d85d1145 Merge commit '9f5f3e26efed6cd27f2a8ff0746f018d75986934'
All checks were successful
Build / build (push) Successful in 2m35s
2024-09-17 23:56:31 -05:00
118fef617f [buildcore] Remove python -m prefix from mypy command 2024-09-17 23:55:15 -05:00
8769305d12 [nostalgia] Allow disabling of BUILD_SHARED_LIBS 2024-09-17 23:51:37 -05:00
c599905000 [nostalgia] Add support for partial tilesheet loading 2024-09-17 23:50:13 -05:00
da23c9304d [ox/std] Add oxModelFwdDecl macro for broken Apple Clang 2024-09-17 23:49:04 -05:00
3ae1d6c897 [ox/std] Make operator[] in Array and Vector nodiscard 2024-09-14 23:45:33 -05:00
a7af6c6660 [keel] Cleanup 2024-09-14 22:35:42 -05:00
0cc6757c57 [keel] Add manifest to pack output 2024-09-14 20:47:54 -05:00
3b8eaef36b [keel] Move vald and repair funcs to their own file, make conversion to validation 2024-09-14 14:16:16 -05:00
b7990ed25b [keel] Make pack file copy logging nest for dir level 2024-09-14 02:52:38 -05:00
71313ed8f4 [ox/std] Cleanup 2024-09-14 02:30:22 -05:00
10531b6ea9 [keel] Cleanup 2024-09-13 23:55:23 -05:00
dfbc298d39 [keel] Add pack file copy status to logging 2024-09-13 23:53:07 -05:00
76760dafb6 [ox/std] Cleanup Defer 2024-09-13 23:51:58 -05:00
5834b9c98d [ox/std] Cleanup logging output 2024-09-13 23:32:42 -05:00
2a58490521 [ox/fs] More cleanup and bug fix from previous cleanup 2024-09-13 23:32:13 -05:00
702b166b8d [ox/fs] Cleanup 2024-09-13 00:17:07 -05:00
8dd837b359 [nostalgia/core] Add a valid function for CompactTileSheet 2024-09-07 23:20:04 -05:00
1d262597a8 [keel] Make default repair return a no repair error 2024-09-07 23:15:15 -05:00
5f10edd35f [nostalgia] Update developer-handbook oxTrace documentation
All checks were successful
Build / build (push) Successful in 2m31s
2024-09-07 20:50:44 -05:00
712299faf3 [studio] Cleanup 2024-09-07 02:25:09 -05:00
c45efa6019 [ox/std] Make Result copyTo and moveTo able to convert 2024-09-07 02:24:52 -05:00
4d63a65fbd [nostalgia/core/studio] Show Palette page names in TileSheetEditor
All checks were successful
Build / build (push) Successful in 2m31s
2024-09-07 00:12:15 -05:00
686db99d5b [nostalgia/core/studio] Disable Palette page hotkeys when Rename popup is open
All checks were successful
Build / build (push) Successful in 2m30s
2024-09-06 21:56:30 -05:00
52533c8c44 [nostalgia/core/studio] Add Palette page names to editor
All checks were successful
Build / build (push) Successful in 2m33s
2024-09-06 21:42:16 -05:00
ba4540e43f [ox/std] Add IString::unsafeResize 2024-09-06 21:19:59 -05:00
36057bb010 [nostalgia/core/studio] Fix Clang build 2024-09-06 02:07:35 -05:00
1a2b2b8bac [nostalgia/core] Add PaletteV4, with support for page names, make PaletteColor object
All checks were successful
Build / build (push) Successful in 2m30s
2024-09-06 01:33:40 -05:00
6189193ac4 [nostalgia] Add NFDE install
All checks were successful
Build / build (push) Successful in 2m32s
2024-09-02 07:40:49 -05:00
67a10d3507 [nostalgia/sample_project] Update type descriptor
All checks were successful
Build / build (push) Successful in 2m35s
2024-08-31 00:28:03 -05:00
ab025e88da [nostalgia] Change Palette converter color idx to be 0 based
All checks were successful
Build / build (push) Successful in 2m30s
2024-08-30 20:53:48 -05:00
bd2e88cd88 [olympic,nostalgia] Cleanup with StringParam
All checks were successful
Build / build (push) Successful in 2m33s
2024-08-30 20:47:43 -05:00
f4a9872fe0 [ox/std] Add StringParam
All checks were successful
Build / build (push) Successful in 2m32s
2024-08-30 20:34:54 -05:00
f8aa60e4c1 [ox/std] Fix itoa result length calculation 2024-08-30 20:12:12 -05:00
3ead305f51 [nostalgia/core/studio/tilesheeteditor] Fix Fill command to properly end
All checks were successful
Build / build (push) Successful in 2m32s
2024-08-30 00:24:59 -05:00
eb498ca557 [ox/event] Comment out Signal disconnect warning
All checks were successful
Build / build (push) Successful in 3m29s
2024-08-27 19:58:14 -05:00
c501fc048f [nostalgia/core/gba] Fix TileSheetSet loading
All checks were successful
Build / build (push) Successful in 2m47s
2024-07-09 22:18:52 -05:00
531d930985 [ox/event] Comment out error logging for a long ignored error
All checks were successful
Build / build (push) Successful in 2m38s
2024-06-30 00:42:45 -05:00
094d159855 [nostalgia] Replace default make command with build instead of install
All checks were successful
Build / build (push) Successful in 2m37s
2024-06-27 20:03:39 -05:00
0017ac27ef [nostalgia] Add gba-dev to README
All checks were successful
Build / build (push) Successful in 2m36s
2024-06-27 19:46:21 -05:00
be920e4905 [nostalgia] Move to C++23
All checks were successful
Build / build (push) Successful in 2m33s
2024-06-26 23:14:50 -05:00
3c4836497a [ox/std] Fix Windows ARM build
All checks were successful
Build / build (push) Successful in 2m29s
2024-06-22 15:20:29 -05:00
f1ee645a0a [buildcore] Windows fixes 2024-06-22 15:18:25 -05:00
3b874c6e6a [turbine] Fix refresh logic to handle default refresh within value
All checks were successful
Build / build (push) Successful in 2m36s
2024-06-17 22:37:36 -05:00
6cf7bf9628 [ox/std] Hopefully fix MSVC build
All checks were successful
Build / build (push) Successful in 2m41s
2024-06-15 15:25:20 -05:00
e34df255e0 [nostalgia] Update developer-handbook non-error return
All checks were successful
Build / build (push) Successful in 2m37s
2024-06-12 23:41:22 -05:00
7eab2f9278 [studio/modlib] Comment out logging in configio 2024-06-12 23:31:40 -05:00
3824788a1a [ox/std] Add non-const operator[] to Pair
All checks were successful
Build / build (push) Successful in 2m36s
2024-06-12 22:52:20 -05:00
1eac7e1e56 [ox/std] Add Pair 2024-06-12 22:51:57 -05:00
8798d2d718 [nostalgia/core] Fix getTileIdx(TileSheet, SubSheetId) 2024-06-03 23:17:50 -05:00
f82db6905c [nostalgia/core] Make load TileSheet functions take CompactTileSheet, in addition to FileAddresses 2024-06-03 20:00:48 -05:00
0dfa7c30e6 [studio/modlib] Make TaskRunner check that task is not null 2024-06-02 14:08:23 -05:00
2afade2447 Merge commit 'fc2dec64389824a251fb258f6fd0a9074e521cc2' 2024-06-02 11:35:07 -05:00
3635702ede [nostalgia] Cleanup config IO 2024-06-01 20:14:29 -05:00
6cbafc75bf [nostalgia,keel] Make repair return ox::Error 2024-06-01 15:54:11 -05:00
0d7b89a025 [turbine] Add TimeMs alias to uint64_t 2024-06-01 13:58:46 -05:00
e8f5c91172 [studio/applib] Change updateHandler to 10 second interval 2024-06-01 13:58:15 -05:00
3cb3bc122b [nostalgia/core] Add valid and repair functions for PaletteV3 2024-06-01 13:56:15 -05:00
a2cec10cb6 [keel] Add valid and repair functions for AssetManager 2024-06-01 13:54:45 -05:00
281 changed files with 5328 additions and 4245 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ imgui.ini
*.sav
studio_state.json
tags
*-manifest.json

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

@ -23,10 +23,12 @@ set(CMAKE_ARCHIVE_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_CXX_STANDARD 23)
if(APPLE)
set(CMAKE_MACOSX_RPATH OFF)
else()
if(UNIX)
if(UNIX AND NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
@ -59,6 +61,7 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
add_subdirectory(deps/glutils)
add_subdirectory(deps/imgui)
add_subdirectory(deps/lodepng)
set(NFD_INSTALL ON)
add_subdirectory(deps/nfde)
endif()

View File

@ -4,6 +4,7 @@
* Install GCC, Clang, or Visual Studio with C++20 support
* Install [devkitPro](https://devkitpro.org/wiki/Getting_Started) to build for GBA
* Install the gba-dev package
* Install Python 3
* Install Ninja, Make, and CMake
* Consider also installing ccache for faster subsequent build times
@ -21,7 +22,7 @@ probably differ), install the following additional packages:
Build options: release, debug, asan, gba, gba-debug
make purge configure-{gba,release,debug} install
make purge configure-{gba,release,debug} build
## Run

View File

@ -10,21 +10,22 @@ ifeq (${OS},Windows_NT)
SHELL := powershell.exe
.SHELLFLAGS := -NoProfile -Command
BC_VAR_OS=windows
BC_CMD_HOST_PY3=python
else
BC_VAR_OS=$(shell uname | tr [:upper:] [:lower:])
endif
ifneq ($(shell which python3 2> /dev/null),)
BC_CMD_HOST_PY3=python3
else
ifeq ($(shell python -c 'import sys; print(sys.version_info[0])'),3)
BC_CMD_HOST_PY3=python
ifneq ($(shell which python3 2> /dev/null),)
BC_CMD_HOST_PY3=python3
else
echo 'Please install Python3 on host'
exit 1
ifeq ($(shell python -c 'import sys; print(sys.version_info[0])'),3)
BC_CMD_HOST_PY3=python
else
echo 'Please install Python3 on host'
exit 1
endif
endif
endif
ifdef BC_VAR_USE_DOCKER_DEVENV
ifneq ($(shell which docker 2> /dev/null),)
BC_VAR_DEVENV=devenv$(shell pwd | sed 's/\//-/g')
@ -43,6 +44,9 @@ ifdef BC_VAR_USE_DOCKER_DEVENV
exit 1
endif
endif
ifndef BC_VAR_DEVENV_ROOT
BC_VAR_DEVENV_ROOT="."
endif
else
BC_CMD_PY3=${BC_CMD_HOST_PY3}
endif
@ -89,7 +93,7 @@ purge:
${BC_CMD_RM_RF} compile_commands.json
.PHONY: test
test: build
${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS}
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
.PHONY: test-verbose
test-verbose: build
@ -101,7 +105,7 @@ test-rerun-verbose: build
ifdef BC_VAR_USE_DOCKER_DEVENV
.PHONY: devenv-image
devenv-image:
docker build . -t ${BC_VAR_DEVENV_IMAGE}
docker build ${BC_VAR_DEVENV_ROOT} -t ${BC_VAR_DEVENV_IMAGE}
.PHONY: devenv-create
devenv-create:
docker run -d \

View File

@ -96,7 +96,7 @@ def main() -> int:
cmake_cmd.append(build_tool)
if qt_path != '':
cmake_cmd.append(qt_path)
if platform.system() == 'Windows':
if platform.system() == 'Windows' and platform.system() == 'AMD64':
cmake_cmd.append('-A x64')
cmake_err = subprocess.run(cmake_cmd).returncode

View File

@ -32,7 +32,7 @@ def get_os() -> str:
def get_arch() -> str:
arch = platform.machine()
if arch.lower() == 'amd64':
arch = platform.machine().lower()
if arch == 'amd64':
arch = 'x86_64'
return arch

View File

@ -73,7 +73,7 @@ void bind(const FrameBuffer &fb) noexcept {
static ox::Result<GLShader> buildShader(
GLuint shaderType,
const GLchar *src,
ox::CRStringView shaderName) noexcept {
ox::StringViewCR shaderName) noexcept {
GLShader shader(glCreateShader(shaderType));
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
@ -83,13 +83,13 @@ static ox::Result<GLShader> buildShader(
ox::Vector<char> errMsg(ox::units::KB);
glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, 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;
}
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
oxRequireM(program, buildShaderProgram(
OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader,
src.fragShader,
src.geomShader));
@ -127,13 +127,13 @@ ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&frag,
ox::CStringView const&geo) noexcept {
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);
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);
}
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
OX_REQUIRE(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
glAttachShader(prgm, fs);
glLinkProgram(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)
endif()
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)
if(WIN32)
@ -21,7 +25,9 @@ elseif(UNIX AND NOT APPLE)
set(nfd_PLATFORM PLATFORM_UNIX)
endif()
message("nfd Platform: ${nfd_PLATFORM}")
# DrinkingTea: begin
#message("nfd Platform: ${nfd_PLATFORM}")
# DrinkingTea: end
set(nfd_COMPILER Undefined)
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)
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
if(NOT DEFINED CMAKE_CXX_STANDARD)

View File

@ -201,7 +201,7 @@ nfdresult_t SetDefaultExtension(::IFileDialog* fileOpenDialog,
}
if (*p_spec) {
// 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'
nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1));
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);
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) {
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);
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) {
return NFD_ERROR;
}

View File

@ -9,9 +9,6 @@ set(CMAKE_CXX_EXTENSIONS OFF)
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_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@ -28,3 +25,10 @@ endif()
add_library(CityHash INTERFACE)
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
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
namespace cityhash::detail {
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_

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(
OxClArgs

View File

@ -11,16 +11,18 @@
namespace ox {
ClArgs::ClArgs(int argc, const char **args) noexcept {
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
auto arg = String(args[i]);
ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<size_t>(argc)}) {}
ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]);
if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) {
arg = arg.substr(1);
arg = substr(arg, 1);
}
m_bools[arg] = true;
// parse additional arguments
if (i < static_cast<unsigned>(argc) && args[i + 1]) {
if (i < args.size() && args[i + 1]) {
auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') {
if (val == "false") {
@ -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);
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);
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);
return !err ? *value : defaultValue;
}
Result<bool> ClArgs::getBool(ox::CRStringView arg) const noexcept {
oxRequire(out, m_bools.at(arg));
Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept {
OX_REQUIRE(out, m_bools.at(arg));
return *out;
}
Result<String> ClArgs::getString(ox::CRStringView argName) const noexcept {
oxRequire(out, m_strings.at(argName));
Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept {
OX_REQUIRE(out, m_strings.at(argName));
return *out;
}
Result<int> ClArgs::getInt(ox::CRStringView arg) const noexcept {
oxRequire(out, m_ints.at(arg));
Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept {
OX_REQUIRE(out, m_ints.at(arg));
return *out;
}

View File

@ -9,6 +9,7 @@
#pragma once
#include <ox/std/hashmap.hpp>
#include <ox/std/span.hpp>
#include <ox/std/string.hpp>
namespace ox {
@ -22,22 +23,24 @@ class ClArgs {
public:
ClArgs(int argc, const char **args) noexcept;
[[nodiscard]]
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
ClArgs(ox::SpanView<const char*> args) noexcept;
[[nodiscard]]
String getString(ox::CRStringView argName, ox::StringView defaultValue) const noexcept;
bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept;
[[nodiscard]]
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;
String getString(ox::StringViewCR argName, ox::StringView defaultValue) const noexcept;
[[nodiscard]]
Result<bool> getBool(ox::CRStringView arg) const noexcept;
int getInt(ox::StringViewCR arg, int defaultValue) const noexcept;
[[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

@ -18,7 +18,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
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;
buffRaw += fmtSz;
@ -26,7 +26,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
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;
buffRaw += s2Size;
@ -34,7 +34,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
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);
buffRaw += s3Size;
@ -48,7 +48,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
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);
StringView const fmt(buffRaw, s1Size);
@ -57,7 +57,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
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);
StringView const typeName(buffRaw, s2Size);
@ -66,7 +66,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s3End = ox::strchr(buffRaw, ';', buffLen);
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);
StringView const versionStr(buffRaw, s3Size);
@ -78,7 +78,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} else if (fmt == "O1") {
hdr.fmt = ClawFormat::Organic;
} 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;
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 {
oxRequire(header, readClawHeader(buff));
OX_REQUIRE(header, readClawHeader(buff));
return {{header.data, header.dataSize}};
}
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff));
OX_REQUIRE(header, readClawHeader(buff));
auto const [t, tdErr] = ts.getLoad(
header.typeName, header.typeVersion, header.typeParams);
if (tdErr) {
return OxError(3, "Could not load type descriptor");
return ox::Error(3, "Could not load type descriptor");
}
ModelObject obj;
oxReturnError(obj.setType(t));
OX_RETURN_ERROR(obj.setType(t));
switch (header.fmt) {
case ClawFormat::Metal:
{
ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br);
ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj));
OX_RETURN_ERROR(model(&handler, &obj));
return obj;
}
case ClawFormat::Organic:
@ -115,16 +115,16 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
#ifdef OX_USE_STDLIB
OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj));
OX_RETURN_ERROR(model(&handler, &obj));
return obj;
#else
break;
#endif
}
case ClawFormat::None:
return OxError(1);
return ox::Error(1);
}
return OxError(1);
return ox::Error(1);
}
}

View File

@ -40,12 +40,12 @@ Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
template<typename T>
Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff));
OX_REQUIRE(header, readClawHeader(buff));
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>()) {
return OxError(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch");
return ox::Error(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch");
}
switch (header.fmt) {
case ClawFormat::Metal:
@ -65,15 +65,15 @@ Error readClaw(ox::BufferView buff, T &val) {
#endif
}
case ClawFormat::None:
return OxError(1);
return ox::Error(1);
}
return OxError(1);
return ox::Error(1);
}
template<typename T>
Result<T> readClaw(ox::BufferView buff) {
Result<T> val;
oxReturnError(readClaw(buff, val.value));
OX_RETURN_ERROR(readClaw(buff, val.value));
return val;
}

View File

@ -62,45 +62,45 @@ struct TestStruct {
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) {
oxReturnError(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String));
return OxError(0);
OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return ox::Error(0);
}
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String));
return OxError(0);
OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->field("String", &obj->String));
return ox::Error(0);
}
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
int unionIdx = 0;
if constexpr(T::opType() != ox::OpType::Reflect) {
unionIdx = obj->unionIdx;
}
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct));
return OxError(0);
OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
OX_RETURN_ERROR(io->field("String", &obj->String));
OX_RETURN_ERROR(io->field("List", obj->List, 4));
OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return ox::Error(0);
}
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.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name 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.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name 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 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);
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
// doesn't segfault
TestStruct ts;
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal));
return OxError(0);
OX_RETURN_ERROR(ox::writeClaw(ts, ox::ClawFormat::Metal));
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.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0);
return ox::Error(0);
}
},
}

View File

@ -39,7 +39,7 @@ struct TypeInfoCatcher {
}
constexpr Error field(...) noexcept {
return OxError(0);
return ox::Error(0);
}
static constexpr auto opType() {
@ -76,21 +76,21 @@ template<typename T>
ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept {
switch (fmt) {
case ClawFormat::Metal:
oxReturnError(write(writer, "M2;"));
OX_RETURN_ERROR(write(writer, "M2;"));
break;
case ClawFormat::Organic:
oxReturnError(write(writer, "O1;"));
OX_RETURN_ERROR(write(writer, "O1;"));
break;
default:
return OxError(1);
return ox::Error(1);
}
oxReturnError(write(writer, detail::getTypeName(t)));
oxReturnError(writer.put(';'));
OX_RETURN_ERROR(write(writer, detail::getTypeName(t)));
OX_RETURN_ERROR(writer.put(';'));
const auto tn = detail::getTypeVersion(t);
if (tn > -1) {
oxReturnError(ox::writeItoa(tn, writer));
OX_RETURN_ERROR(ox::writeItoa(tn, writer));
}
oxReturnError(writer.put(';'));
OX_RETURN_ERROR(writer.put(';'));
return {};
}
@ -102,19 +102,19 @@ Result<Buffer> writeClaw(
std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer out(buffReserveSz);
BufferWriter bw(&out, 0);
oxReturnError(detail::writeClawHeader(bw, &t, fmt));
OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt));
#ifdef OX_USE_STDLIB
if (fmt == ClawFormat::Metal) {
oxReturnError(writeMC(bw, t));
OX_RETURN_ERROR(writeMC(bw, t));
} else if (fmt == ClawFormat::Organic) {
oxRequire(data, writeOC(t));
oxReturnError(bw.write(data.data(), data.size()));
OX_REQUIRE(data, writeOC(t));
OX_RETURN_ERROR(bw.write(data.data(), data.size()));
}
#else
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
out.resize(bw.tellp());
return out;

View File

@ -57,7 +57,7 @@ class Signal {
void call(Args... args) final {
if constexpr(detail::isError<decltype(f(args...))>::value) {
oxThrowError(f(args...));
OX_THROW_ERROR(f(args...));
} else {
f(args...);
}
@ -76,17 +76,17 @@ class Signal {
void call(Args... args) final {
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 {
f(args...);
}
}
void cleanup(Signal *signal) noexcept final {
auto err = m_receiver->destruction.disconnectSignal(signal);
if (err) {
oxErrorf("Signal could not notify receiver that it is being destroyed. Destruction of receiver will cause use-after-free. ({})", toStr(err));
}
std::ignore = m_receiver->destruction.disconnectSignal(signal);
//if (err) {
// oxErrorf("Signal could not notify receiver that it is being destroyed. Destruction of receiver will cause use-after-free. ({})", toStr(err));
//}
}
[[nodiscard]]
@ -107,7 +107,7 @@ class Signal {
void call(Args... args) final {
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 {
(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) {
const auto &slot = m_slots[i];
if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i));
OX_RETURN_ERROR(m_slots.erase(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>
@ -213,7 +213,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) {
f->call(args...);
}
return OxError(0);
return ox::Error(0);
} catch (const ox::Exception &ex) {
return ox::Error(ex.file, ex.line, ex.errCode, ex.msg);
}
@ -264,8 +264,8 @@ class Signal<Error(Args...)> {
}
void cleanup(Signal *signal) noexcept final {
auto err = m_receiver->destruction.disconnectSignal(signal);
oxErrorf("{}", toStr(err));
std::ignore = m_receiver->destruction.disconnectSignal(signal);
//oxErrorf("{}", toStr(err));
//oxAssert(err, "Signal could not notify receiver that it is being destroyed. Destruction of receiver will cause use-after-free.");
}
@ -381,11 +381,11 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i];
if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i));
OX_RETURN_ERROR(m_slots.erase(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>
@ -398,9 +398,9 @@ void Signal<Error(Args...)>::emit(Args... args) const noexcept {
template<class... Args>
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
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

@ -17,7 +17,7 @@ struct TestStruct: public ox::SignalHandler {
int value = 0;
ox::Error method(int i) noexcept {
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;
signal.connect([](int i) -> ox::Error {
return OxError(i != 5);
return ox::Error(i != 5);
});
TestStruct ts;
signal.connect(&ts, &TestStruct::method);
oxReturnError(signal.emitCheckError(5));
oxReturnError(OxError(ts.value != 5));
return OxError(0);
OX_RETURN_ERROR(signal.emitCheckError(5));
OX_RETURN_ERROR(ox::Error(ts.value != 5));
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(
OxFS

View File

@ -10,6 +10,8 @@
#include <ox/fs/ptrarith/nodebuffer.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
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;
if (!fsData.valid()) {
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);
if (!data.valid()) {
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;
return {};
@ -221,24 +223,24 @@ Error FileStoreTemplate<size_t>::setSize(std::size_t size) {
if (m_buffSize >= size) {
return m_buffer->setSize(static_cast<size_t>(size));
}
return OxError(1);
return ox::Error(1);
}
template<typename size_t>
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;
return OxError(0);
return ox::Error(0);
}
template<typename size_t>
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;
if (item->links == 0) {
oxReturnError(remove(item));
OX_RETURN_ERROR(remove(item));
}
return OxError(0);
return ox::Error(0);
}
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);
auto existing = find(id);
if (!canWrite(existing, dataSize)) {
oxReturnError(compact());
OX_RETURN_ERROR(compact());
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 (!dest.valid()) {
oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting");
oxReturnError(compact());
OX_RETURN_ERROR(compact());
dest = m_buffer->malloc(dataSize).value;
}
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());
fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return OxError(0);
return ox::Error(0);
}
} else {
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>
@ -315,12 +317,12 @@ Error FileStoreTemplate<size_t>::remove(uint64_t id) {
template<typename size_t>
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read inode {}", id);
auto src = find(static_cast<size_t>(id));
// error check
if (!src.valid()) {
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);
@ -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",
"Item data section size: {}, Expected size: {}", srcData.size(), outSize);
return OxError(1);
return ox::Error(1, "Invalid inode");
}
ox::memcpy(out, srcData, srcData.size());
@ -341,7 +343,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
*size = src.size();
}
return OxError(0);
return {};
}
template<typename size_t>
@ -351,7 +353,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
// error check
if (!src.valid()) {
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);
@ -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",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1);
return ox::Error(1);
}
ox::memcpy(out, srcData.get() + readStart, readSize);
@ -384,7 +386,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
// error check
if (!src.valid()) {
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);
@ -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",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1);
return ox::Error(1);
}
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>
Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact());
OX_RETURN_ERROR(compact());
const auto newSize = static_cast<std::size_t>(size() - available());
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());
return OxError(0);
return ox::Error(0);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) {
return OxError(1);
return ox::Error(1);
}
m_buffSize = static_cast<size_t>(size);
if (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>
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 {
id,
inode->links,
@ -475,16 +477,16 @@ char *FileStoreTemplate<size_t>::buff() {
template<typename size_t>
Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
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>
Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() {
auto fsData = fileStoreData();
if (!fsData) {
return OxError(1);
return ox::Error(1);
}
for (auto i = 0; i < 100; i++) {
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 OxError(2);
return ox::Error(2);
}
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 {
if (isFirstItem) {
isFirstItem = false;
return OxError(0);
return ox::Error(0);
}
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());
// update rootInode if this is it
@ -522,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
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) {
auto fsData = fileStoreData();
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) {
fsData->rootNode = item;
item->left = root->left;
item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return OxError(0);
return ox::Error(0);
} else {
return placeItem(root, item);
}
@ -560,7 +562,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth > 5000) {
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) {
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;
}
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0);
return ox::Error(0);
} else {
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;
}
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0);
return ox::Error(0);
} else {
return placeItem(left, item, depth + 1);
}
} else {
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) {
auto fsData = fileStoreData();
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) {
item->left = root->left;
item->right = root->right;
@ -622,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else {
fsData->rootNode = 0;
}
return OxError(0);
return ox::Error(0);
} else {
return unplaceItem(root, item);
}
@ -632,7 +634,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth >= 5000) {
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) {
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);
}
} else {
return OxError(1);
return ox::Error(1);
}
if (item->right) {
oxReturnError(placeItem(m_buffer->ptr(item->right)));
OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->right)));
}
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>
Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) {
oxReturnError(unplaceItem(item));
oxReturnError(m_buffer->free(item));
return OxError(0);
OX_RETURN_ERROR(unplaceItem(item));
OX_RETURN_ERROR(m_buffer->free(item));
return ox::Error(0);
}
return OxError(1);
return ox::Error(1);
}
template<typename size_t>
@ -771,3 +773,5 @@ using FileStore16 = FileStoreTemplate<uint16_t>;
using FileStore32 = FileStoreTemplate<uint32_t>;
}
OX_CLANG_NOWARN_END

View File

@ -15,6 +15,8 @@
#include "types.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename InodeId_t>
@ -43,15 +45,17 @@ struct OX_PACKED DirectoryEntry {
public:
constexpr DirectoryEntry() noexcept = default;
Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) noexcept {
m_bufferSize = bufferSize;
Error init(InodeId_t inode, ox::StringViewCR name, size_t bufferSize) noexcept {
oxTracef("ox.fs.DirectoryEntry.init", "inode: {}, name: {}, bufferSize: {}", inode, name, bufferSize);
m_bufferSize = static_cast<InodeId_t>(bufferSize);
auto d = data();
if (d.valid()) {
d->inode = inode;
ox::strncpy(d->name, name, ox::min(bufferSize, static_cast<InodeId_t>(MaxFileNameLength)));
return OxError(0);
auto const maxStrSz = bufferSize - 1 - sizeof(*this);
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
return {};
}
return OxError(1);
return ox::Error(1);
}
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
@ -103,23 +107,23 @@ class Directory {
*/
Error init() noexcept;
Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr);
Error mkdir(PathIterator path, bool parents);
/**
* @param parents indicates the operation should create non-existent directories in the path, like mkdir -p
*/
Error write(PathIterator path, uint64_t inode64, FileName *nameBuff = nullptr) noexcept;
Error write(PathIterator path, uint64_t inode64) noexcept;
Error remove(PathIterator path, FileName *nameBuff = nullptr) noexcept;
Error remove(PathIterator path) noexcept;
template<typename F>
Error ls(F cb) noexcept;
[[nodiscard]]
Result<typename FileStore::InodeId_t> findEntry(const FileName &name) const noexcept;
Result<typename FileStore::InodeId_t> findEntry(const StringView &name) const noexcept;
[[nodiscard]]
Result<typename FileStore::InodeId_t> find(PathIterator name, FileName *nameBuff = nullptr) const noexcept;
Result<typename FileStore::InodeId_t> find(PathIterator path) const noexcept;
};
@ -137,46 +141,39 @@ template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::init() noexcept {
constexpr auto Size = sizeof(Buffer);
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>();
if (!buff.valid()) {
m_size = 0;
return OxError(1);
return ox::Error(1);
}
new (buff) Buffer(Size);
m_size = Size;
return OxError(0);
return {};
}
template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
if (path.valid()) {
oxTrace("ox.fs.Directory.mkdir", path.fullPath());
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
}
// determine if already exists
auto name = nameBuff;
oxReturnError(path.get(*name));
auto childInode = find(PathIterator(*name));
ox::StringView name;
OX_RETURN_ERROR(path.get(name));
auto childInode = find(PathIterator(name));
if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled,
// return an error
if (!parents && path.hasNext()) {
return OxError(1);
return ox::Error(1);
}
childInode = m_fs.generateInodeId();
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
oxLogError(childInode.error);
oxReturnError(childInode.error);
OX_RETURN_ERROR(childInode.error);
// initialize the directory
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
oxReturnError(child.init());
auto err = write(PathIterator(*name), childInode.value);
OX_RETURN_ERROR(child.init());
auto err = write(PathIterator(name), childInode.value);
if (err) {
oxLogError(err);
// could not index the directory, delete it
@ -184,87 +181,68 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, Fi
return err;
}
}
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
if (path.hasNext()) {
oxReturnError(child.mkdir(path.next(), parents, nameBuff));
OX_RETURN_ERROR(child.mkdir(path.next(), parents));
}
}
return OxError(0);
return {};
}
template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64, FileName *nameBuff) noexcept {
Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64) noexcept {
const auto inode = static_cast<InodeId_t>(inode64);
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
}
auto name = nameBuff;
ox::StringView name;
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxReturnError(path.get(*name));
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
*name, path.fullPath());
oxRequire(nextChild, findEntry(*name));
oxTracef("ox.fs.Directory.write", "{}: {}", *name, nextChild);
name, path.fullPath());
OX_RETURN_ERROR(path.get(name));
OX_REQUIRE(nextChild, findEntry(name));
oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild);
if (nextChild) {
// reuse name because it is a rather large variable and will not be used again
// be attentive that this remains true
name = nullptr;
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
return Directory(m_fs, nextChild).write(path.next(), inode);
} else {
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.");
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name);
return ox::Error(1, "File not found and not allowed to create it.");
}
} else {
oxTrace("ox.fs.Directory.write", path.fullPath());
OX_RETURN_ERROR(path.next(name));
// insert the new entry on this directory
// get the name
oxReturnError(path.next(*name));
// find existing version of directory
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);
auto old = m_fs.read(m_inodeId).template to<Buffer>();
if (!old.valid()) {
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 newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
if (cpy == nullptr) {
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;
if (!val.valid()) {
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->data());
oxReturnError(val->init(inode, name->data(), val.size()));
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name);
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));
}
}
template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameBuff) noexcept {
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
}
auto &name = *nameBuff;
oxReturnError(path.get(name));
Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
ox::StringView name;
OX_RETURN_ERROR(path.get(name));
oxTrace("ox.fs.Directory.remove", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (buff.valid()) {
@ -273,7 +251,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
auto data = i->data();
if (data.valid()) {
if (name == data->name) {
oxReturnError(buff->free(i));
OX_RETURN_ERROR(buff->free(i));
}
} else {
oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
@ -281,9 +259,9 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
}
} else {
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 OxError(0);
return {};
}
template<typename FileStore, typename InodeId_t>
@ -293,29 +271,27 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) {
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.");
for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data();
if (data.valid()) {
oxReturnError(cb(data->name, data->inode));
OX_RETURN_ERROR(cb(data->name, data->inode));
} else {
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
}
}
return OxError(0);
return {};
}
template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(StringViewCR name) const noexcept {
oxTrace("ox.fs.Directory.findEntry", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) {
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());
for (auto i = buff->iterator(); i.valid(); i.next()) {
@ -327,30 +303,23 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
return static_cast<InodeId_t>(data->inode);
}
} else {
oxTrace("ox.fs.Directory.findEntry") << "INVALID DIRECTORY ENTRY";
oxTrace("ox.fs.Directory.findEntry", "INVALID DIRECTORY ENTRY");
}
}
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>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path, FileName *nameBuff) const noexcept {
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
}
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept {
// determine if already exists
auto name = nameBuff;
oxReturnError(path.get(*name));
oxRequire(v, findEntry(*name));
ox::StringView name;
OX_RETURN_ERROR(path.get(name));
OX_REQUIRE(v, findEntry(name));
// recurse if not at end of path
if (auto p = path.next(); p.valid()) {
Directory dir(m_fs, v);
name = nullptr;
return dir.find(p, nameBuff);
return dir.find(p);
}
return v;
}
@ -366,3 +335,5 @@ using Directory16 = Directory<FileStore16, uint16_t>;
using Directory32 = Directory<FileStore32, uint32_t>;
}
OX_CLANG_NOWARN_END

View File

@ -28,11 +28,13 @@ FileAddress::FileAddress(uint64_t inode) noexcept {
m_type = FileAddressType::Inode;
}
FileAddress::FileAddress(ox::CRStringView path) noexcept {
FileAddress::FileAddress(ox::StringViewCR path) noexcept {
auto pathSize = path.bytes();
m_data.path = new char[pathSize + 1];
memcpy(m_data.path, path.data(), pathSize);
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
m_data.path[pathSize] = 0;
OX_CLANG_NOWARN_END
m_type = FileAddressType::Path;
}
@ -114,7 +116,7 @@ bool FileAddress::operator==(FileAddress const&other) const noexcept {
return true;
}
bool FileAddress::operator==(CRStringView path) const noexcept {
bool FileAddress::operator==(StringViewCR path) const noexcept {
auto [p, err] = getPath();
if (err) {
return false;

View File

@ -13,6 +13,8 @@
#include <ox/model/typenamecatcher.hpp>
#include <ox/model/types.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
enum class FileAddressType: int8_t {
@ -57,7 +59,7 @@ class FileAddress {
FileAddress(uint64_t inode) noexcept;
explicit FileAddress(CRStringView path) noexcept;
explicit FileAddress(StringViewCR path) noexcept;
constexpr FileAddress(ox::StringLiteral path) noexcept;
@ -69,7 +71,7 @@ class FileAddress {
bool operator==(const FileAddress &other) const noexcept;
bool operator==(CRStringView path) const noexcept;
bool operator==(StringViewCR path) const noexcept;
[[nodiscard]]
constexpr FileAddressType type() const noexcept {
@ -87,7 +89,7 @@ class FileAddress {
case FileAddressType::Inode:
return m_data.inode;
default:
return OxError(1);
return ox::Error(1);
}
}
@ -98,7 +100,7 @@ class FileAddress {
case FileAddressType::ConstPath:
return ox::CStringView(m_data.constPath);
default:
return OxError(1);
return ox::Error(1);
}
}
@ -152,31 +154,33 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept {
template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress::Data>());
oxReturnError(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode));
OX_RETURN_ERROR(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 *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress>());
OX_RETURN_ERROR(h->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) {
int8_t type = -1;
oxReturnError(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, type)));
OX_RETURN_ERROR(h->field("type", &type));
OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, type)));
} else if constexpr(T::opType() == OpType::Read) {
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);
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) {
auto const type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
OX_RETURN_ERROR(h->field("type", &type));
OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
}
return {};
}
}
OX_CLANG_NOWARN_END

View File

@ -21,7 +21,7 @@ Result<const char*> MemFS::directAccess(const FileAddress &addr) const noexcept
case FileAddressType::Path:
return directAccess(StringView(addr.getPath().value));
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:
return readFilePath(StringView(addr.getPath().value), buffer, size);
default:
return OxError(1);
return ox::Error(1);
}
}
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));
oxReturnError(read(addr, buff.data(), buff.size()));
OX_RETURN_ERROR(read(addr, buff.data(), buff.size()));
return buff;
}
Result<Buffer> FileSystem::read(CRStringView path) noexcept {
oxRequire(s, statPath(path));
Result<Buffer> FileSystem::read(StringViewCR path) noexcept {
OX_REQUIRE(s, statPath(path));
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;
}
@ -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);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return OxError(2, "Unsupported for path lookups");
return ox::Error(2, "Unsupported for path lookups");
default:
return OxError(1);
return ox::Error(1);
}
}
@ -71,7 +71,7 @@ Error FileSystem::remove(const FileAddress &addr, bool recursive) noexcept {
case FileAddressType::Path:
return remove(StringView(addr.getPath().value), recursive);
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:
return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType);
default:
return OxError(1);
return ox::Error(1);
}
}
@ -95,7 +95,7 @@ Result<FileStat> FileSystem::stat(const FileAddress &addr) const noexcept {
case FileAddressType::Path:
return statPath(StringView(addr.getPath().value));
default:
return OxError(1);
return ox::Error(1);
}
}

View File

@ -30,22 +30,22 @@ class FileSystem {
public:
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.
* @param src the path to the file
* @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;
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);
}
@ -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;
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;
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);
}
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);
}
@ -81,7 +81,7 @@ class FileSystem {
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);
}
@ -93,7 +93,7 @@ class FileSystem {
return statInode(inode);
}
inline Result<FileStat> stat(CRStringView path) const noexcept {
inline Result<FileStat> stat(StringViewCR path) const noexcept {
return statPath(path);
}
@ -134,15 +134,15 @@ class FileSystem {
protected:
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 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;
@ -152,7 +152,7 @@ class MemFS: public FileSystem {
public:
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);
}
@ -161,7 +161,7 @@ class MemFS: public FileSystem {
}
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;
};
@ -197,13 +197,13 @@ class FileSystemTemplate: public MemFS {
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;
@ -211,12 +211,12 @@ class FileSystemTemplate: public MemFS {
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>
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.
@ -225,13 +225,13 @@ class FileSystemTemplate: public MemFS {
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;
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]]
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.
*/
Result<uint64_t> find(CRStringView path) const noexcept;
Result<uint64_t> find(StringViewCR path) const noexcept;
Result<Directory> rootDir() const noexcept;
@ -284,67 +284,69 @@ FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() noexcept {
template<typename FileStore, typename Directory>
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));
constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2;
Directory rootDir(fs, rootDirInode);
oxReturnError(rootDir.init());
OX_RETURN_ERROR(rootDir.init());
FileSystemData fd;
fd.rootDirInode = rootDirInode;
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()) {
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>
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);
oxRequireM(rootDir, this->rootDir());
OX_REQUIRE_M(rootDir, this->rootDir());
return rootDir.mkdir(path, recursive);
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::move(CRStringView src, CRStringView dest) noexcept {
oxRequire(fd, fileSystemData());
Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept {
OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode);
oxRequireM(inode, rootDir.find(src));
oxReturnError(rootDir.write(dest, inode));
oxReturnError(rootDir.remove(src));
return OxError(0);
OX_REQUIRE_M(inode, rootDir.find(src));
OX_RETURN_ERROR(rootDir.write(dest, inode));
OX_RETURN_ERROR(rootDir.remove(src));
return ox::Error(0);
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept {
oxRequire(fd, fileSystemData());
Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
oxTrace("ox.fs.FileSystemTemplate.readFilePath", path);
OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(s, stat(path));
OX_REQUIRE(s, stat(path));
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);
}
template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(CRStringView path) const noexcept {
oxRequire(fd, fileSystemData());
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept {
OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path));
OX_REQUIRE(inode, rootDir.find(path));
return directAccessInode(inode);
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
oxRequire(s, stat(inode));
oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode);
OX_REQUIRE(s, stat(inode));
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);
}
@ -358,36 +360,36 @@ template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept {
auto data = m_fs.read(inode);
if (!data.valid()) {
return OxError(1, "Data not valid");
return ox::Error(1, "Data not valid");
}
return reinterpret_cast<char*>(data.get());
}
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;
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);
return OxError(0);
return ox::Error(0);
}));
return out;
}
template<typename FileStore, typename Directory>
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);
oxRequire(s, stat(path));
OX_REQUIRE(s, stat(path));
Directory dir(m_fs, s.inode);
return dir.ls(cb);
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::remove(CRStringView path, bool recursive) noexcept {
oxRequire(fd, fileSystemData());
Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept {
OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path));
oxRequire(st, statInode(inode));
OX_REQUIRE(inode, rootDir.find(path));
OX_REQUIRE(st, statInode(inode));
if (st.fileType == FileType::NormalFile || recursive) {
if (auto err = rootDir.remove(path)) {
// removal failed, try putting the index back
@ -396,9 +398,9 @@ Error FileSystemTemplate<FileStore, Directory>::remove(CRStringView path, bool r
}
} else {
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>
@ -408,31 +410,36 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept {
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer));
return OxError(0);
OX_RETURN_ERROR(m_fs.resize(static_cast<size_t>(size), buffer));
return {};
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::writeFilePath(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
StringViewCR path,
const void *buffer,
uint64_t size,
FileType fileType) noexcept {
oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path);
auto [inode, err] = find(path);
if (err) {
oxRequire(generatedId, m_fs.generateInodeId());
inode = generatedId;
oxRequireM(rootDir, this->rootDir());
oxReturnError(rootDir.write(path, inode));
OX_RETURN_ERROR(m_fs.generateInodeId().moveTo(inode));
OX_REQUIRE_M(rootDir, this->rootDir());
OX_RETURN_ERROR(rootDir.write(path, inode));
}
oxReturnError(writeFileInode(inode, buffer, size, fileType));
return OxError(0);
OX_RETURN_ERROR(writeFileInode(inode, buffer, size, fileType));
return {};
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::itoa(inode));
return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType));
}
template<typename FileStore, typename Directory>
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;
out.inode = s.inode;
out.links = s.links;
@ -442,8 +449,8 @@ Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t in
}
template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(CRStringView path) const noexcept {
oxRequire(inode, find(path));
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept {
OX_REQUIRE(inode, find(path));
return stat(inode);
}
@ -480,25 +487,25 @@ bool FileSystemTemplate<FileStore, Directory>::valid() const noexcept {
template<typename FileStore, typename Directory>
Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept {
FileSystemData fd;
oxReturnError(m_fs.read(InodeFsData, &fd, sizeof(fd)));
OX_RETURN_ERROR(m_fs.read(InodeFsData, &fd, sizeof(fd)));
return fd;
}
template<typename FileStore, typename Directory>
Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(CRStringView path) const noexcept {
oxRequire(fd, fileSystemData());
Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept {
OX_REQUIRE(fd, fileSystemData());
// return root as a special case
if (path == "/") {
return static_cast<uint64_t>(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);
}
template<typename FileStore, typename Directory>
Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept {
oxRequire(fd, fileSystemData());
OX_REQUIRE(fd, fileSystemData());
return Directory(m_fs, fd.rootDirInode);
}

View File

@ -17,7 +17,7 @@
namespace ox {
PassThroughFS::PassThroughFS(CRStringView dirPath) {
PassThroughFS::PassThroughFS(StringViewCR dirPath) {
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());
}
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
bool success = false;
const auto p = m_path / stripSlash(path);
const auto u8p = p.u8string();
@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
success = true;
} else {
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 {
std::error_code ec;
@ -48,26 +48,26 @@ Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
success = true;
} else {
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::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec);
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;
std::error_code 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) {
const auto u8p = p.path().filename().u8string();
out.emplace_back(reinterpret_cast<const char*>(u8p.c_str()));
@ -75,34 +75,33 @@ Result<Vector<String>> PassThroughFS::ls(CRStringView dir) const noexcept {
return out;
}
Error PassThroughFS::remove(CRStringView path, bool recursive) noexcept {
Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept {
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 {
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 {
// 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 {
// 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;
const auto p = m_path / stripSlash(path);
const FileType type = std::filesystem::is_directory(p, ec) ?
FileType::Directory : FileType::NormalFile;
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
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};
}
@ -113,14 +112,14 @@ uint64_t PassThroughFS::spaceNeeded(uint64_t size) const noexcept {
Result<uint64_t> PassThroughFS::available() const noexcept {
std::error_code 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;
}
Result<uint64_t> PassThroughFS::size() const noexcept {
std::error_code 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;
}
@ -129,7 +128,7 @@ char *PassThroughFS::buff() 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 {
@ -141,48 +140,48 @@ bool PassThroughFS::valid() const noexcept {
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 {
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());
file.seekg(0, std::ios::beg);
if (size > buffSize) {
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));
} catch (const std::fstream::failure &f) {
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 {
// 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 {
// 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));
try {
std::ofstream f(p, std::ios::binary);
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
} catch (const std::fstream::failure &f) {
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 {
// 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 {

View File

@ -29,29 +29,29 @@ class PassThroughFS: public FileSystem {
std::filesystem::path m_path;
public:
explicit PassThroughFS(CRStringView dirPath);
explicit PassThroughFS(StringViewCR dirPath);
~PassThroughFS() noexcept override;
[[nodiscard]]
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>
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;
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]]
uint64_t spaceNeeded(uint64_t size) const noexcept override;
@ -69,13 +69,13 @@ class PassThroughFS: public FileSystem {
bool valid() const noexcept override;
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 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;
@ -89,14 +89,14 @@ class PassThroughFS: public FileSystem {
};
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;
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) {
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

@ -11,6 +11,8 @@
#include <ox/std/trace.hpp>
#include "pathiterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) {
@ -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(CRStringView path): PathIterator(path.data(), path.bytes()) {
PathIterator::PathIterator(StringViewCR path): PathIterator(path.data(), path.bytes()) {
}
/**
@ -30,47 +32,26 @@ PathIterator::PathIterator(CRStringView path): PathIterator(path.data(), path.by
*/
Error PathIterator::dirPath(char *out, std::size_t outSize) {
const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
const auto size = static_cast<std::size_t>(idx + 1);
const auto size = static_cast<std::size_t>(idx) + 1;
if (idx >= 0 && size < outSize) {
ox::memcpy(out, m_path, size);
out[size] = 0;
return OxError(0);
return ox::Error(0);
} else {
return OxError(1);
}
}
/**
* @return 0 if no error
*/
Error PathIterator::fileName(char *out, std::size_t outSize) {
auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
if (idx >= 0) {
idx++; // pass up the preceding /
std::size_t fileNameSize = static_cast<size_t>(ox::strlen(&m_path[idx]));
if (fileNameSize < outSize) {
ox::memcpy(out, &m_path[idx], fileNameSize);
out[fileNameSize] = 0;
return OxError(0);
} else {
return OxError(1);
}
} else {
return OxError(2);
return ox::Error(1);
}
}
// Gets the get item in the path
Error PathIterator::get(IString<MaxFileNameLength> &fileName) {
Error PathIterator::get(StringView &fileName) {
std::size_t size = 0;
std::ignore = fileName.resize(MaxFileNameLength);
if (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])) {
oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])");
return OxError(1);
return ox::Error(1);
}
auto start = m_iterator;
if (m_path[start] == '/') {
@ -86,26 +67,25 @@ Error PathIterator::get(IString<MaxFileNameLength> &fileName) {
size = end - start;
// cannot fit the output in the output parameter
if (size >= MaxFileNameLength || size == 0) {
return OxError(1);
return ox::Error(1);
}
ox::memcpy(fileName.data(), &m_path[start], size);
fileName = ox::substr(m_path, start, start + size);
// truncate trailing /
if (size && fileName[size - 1] == '/') {
size--;
fileName = ox::substr(m_path, start, start + size - 1);
}
oxReturnError(fileName.resize(size));
oxAssert(fileName[fileName.len()-1] != '/', "name ends in /");
return {};
}
/**
* @return 0 if no error
*/
Error PathIterator::next(IString<MaxFileNameLength> &fileName) {
Error PathIterator::next(StringView &fileName) {
std::size_t size = 0;
auto retval = OxError(1);
std::ignore = fileName.resize(MaxFileNameLength);
auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = OxError(0);
retval = ox::Error(0);
if (m_path[m_iterator] == '/') {
m_iterator++;
}
@ -120,26 +100,25 @@ Error PathIterator::next(IString<MaxFileNameLength> &fileName) {
size = end - start;
// cannot fit the output in the output parameter
if (size >= MaxFileNameLength) {
return OxError(1);
return ox::Error(1);
}
ox::memcpy(fileName.data(), &m_path[start], size);
fileName = ox::substr(m_path, start, start + size);
// truncate trailing /
while (fileName.len() && fileName[fileName.len() - 1] == '/') {
fileName = ox::substr(m_path, start, start + size);
}
m_iterator += size;
oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /");
}
// truncate trailing /
if (size && fileName[size - 1] == '/') {
size--;
}
fileName[size] = 0; // end with null terminator
oxReturnError(fileName.resize(size));
m_iterator += size;
return retval;
}
Result<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0;
auto retval = OxError(1);
auto retval = ox::Error(1);
auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = OxError(0);
retval = ox::Error(0);
if (m_path[it] == '/') {
it++;
}
@ -206,3 +185,5 @@ const char *PathIterator::fullPath() const {
}
}
OX_CLANG_NOWARN_END

View File

@ -13,7 +13,6 @@
namespace ox {
constexpr std::size_t MaxFileNameLength = 255;
using FileName = IString<MaxFileNameLength>;
class PathIterator {
private:
@ -26,31 +25,14 @@ class PathIterator {
PathIterator(const char *path);
PathIterator(CRStringView path);
PathIterator(StringViewCR path);
/**
* @return 0 if no error
*/
Error dirPath(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error fileName(char *out, std::size_t outSize);
Error next(StringView &fileName);
/**
* @return 0 if no error
*/
Error next(FileName &fileName);
Error get(StringView &fileName);
/**
* @return 0 if no error
*/
Error get(FileName &fileName);
/**
* @return 0 if no error
*/
Result<std::size_t> nextSize() const;
[[nodiscard]]

View File

@ -13,6 +13,8 @@
#include "ptr.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith {
template<typename size_t, typename Item>
@ -174,7 +176,7 @@ template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
m_header.size = static_cast<size_t>(size);
ox::memset(this + 1, 0, size - sizeof(*this));
oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get());
oxTracef("ox.ptrarith.NodeBuffer.constructor", "{}", m_header.firstItem.get());
}
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;
} else {
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);
auto out = ItemPtr(this, m_header.size, addr, fullSize);
if (!out.valid()) {
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);
new (out) Item;
@ -302,7 +304,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
first->prev = out.offset();
} else {
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()) {
@ -312,7 +314,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
if (out.offset() != first.offset()) {
// 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.");
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();
}
@ -321,7 +323,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
return out;
}
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>
@ -344,15 +346,15 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} else {
if (!prev.valid()) {
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()) {
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();
return OxError(0);
return ox::Error(0);
}
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);
if (end > size) {
// resizing to less than buffer size
return OxError(1);
return ox::Error(1);
} else {
m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + 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));
while (dest.offset() <= src.offset()) {
if (!src.valid()) {
return OxError(1);
return ox::Error(1);
}
if (!dest.valid()) {
return OxError(2);
return ox::Error(2);
}
// move node
ox::memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest));
OX_RETURN_ERROR(cb(src, dest));
// update surrounding nodes
auto prev = ptr(dest->prev);
if (prev.valid()) {
@ -420,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize());
}
return OxError(0);
return ox::Error(0);
}
template<typename size_t, typename Item>
@ -449,3 +451,5 @@ struct OX_PACKED Item {
};
}
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,8 @@
#include <ox/std/std.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith {
template<typename T, typename size_t, size_t minOffset = 1>
@ -224,7 +226,7 @@ constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(s
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
oxTracef("ox.ptrarith.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
return subPtr<SubT>(offset, m_itemSize - offset);
}
@ -237,7 +239,7 @@ constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
oxTracef("ox.ptrarith.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
return subPtr<SubT>(offset, m_itemSize - offset);
}
@ -252,7 +254,9 @@ constexpr Result<Ptr<T, size_t, minOffset>> Ptr<T, size_t, minOffset>::validate(
if (valid()) {
return *this;
}
return OxError(1);
return ox::Error(1);
}
}
OX_CLANG_NOWARN_END

View File

@ -19,7 +19,6 @@ add_test("[ox/fs] PathIterator::next5" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests
add_test("[ox/fs] PathIterator::hasNext" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::hasNext)
add_test("[ox/fs] PathIterator::dirPath" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::dirPath)
add_test("[ox/fs] PathIterator::fileName" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::fileName)
add_test("[ox/fs] NodeBuffer::insert" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "NodeBuffer::insert")
add_test("[ox/fs] FileStore::readWrite" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileStore::readWrite")

View File

@ -52,30 +52,32 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(buffer->free(a1), "Free failed.");
oxAssert(buffer->free(a2), "Free failed.");
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
return OxError(0);
return ox::Error(0);
}
},
{
"PathIterator::next1",
[](ox::StringView) {
auto const path = ox::String("/usr/share/charset.gbag");
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
ox::FileName buff;
ox::StringView buff;
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 == "charset.gbag", "PathIterator shows wrong next");
return OxError(0);
return ox::Error(0);
}
},
{
"PathIterator::next2",
[](ox::StringView) {
auto const path = ox::String("/usr/share/");
ox::PathIterator it(path.c_str(), path.len());
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
return OxError(0);
auto constexpr path = ox::StringView("/usr/share/");
ox::PathIterator it(path);
ox::StringView buff;
oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "usr");
oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "share");
return ox::Error(0);
}
},
{
@ -83,21 +85,21 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("/");
ox::PathIterator it(path.c_str(), path.len());
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
return OxError(0);
ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
return ox::Error(0);
}
},
{
"PathIterator::next4",
[](ox::StringView) {
auto const path = ox::String("usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
return OxError(0);
auto constexpr path = ox::StringLiteral("usr/share/charset.gbag");
ox::PathIterator it(path);
ox::StringView buff;
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 == "charset.gbag", "PathIterator shows wrong next");
return ox::Error(0);
}
},
{
@ -105,30 +107,20 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("usr/share/");
ox::PathIterator it(path.c_str(), path.len());
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
return OxError(0);
ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
return ox::Error(0);
}
},
{
"PathIterator::dirPath",
[] (ox::StringView) {
auto const path = ox::String("/usr/share/charset.gbag");
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
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");
return OxError(0);
}
},
{
"PathIterator::fileName",
[](ox::StringView) {
auto const path = ox::String("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.fileName(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
return OxError(0);
return ox::Error(0);
}
},
{
@ -138,7 +130,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path, ox::strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
return OxError(0);
return ox::Error(0);
}
},
{
@ -150,7 +142,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto subPtr = p.subPtr<uint64_t>(50);
oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid.");
return OxError(0);
return ox::Error(0);
}
},
{
@ -163,7 +155,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto first = list->firstItem();
oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item");
oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid");
return OxError(0);
return ox::Error(0);
}
},
{
@ -184,7 +176,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
size_t str1ReadSize = 0;
oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed.");
return OxError(0);
return ox::Error(0);
}
},
{
@ -211,7 +203,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxTrace("ox.fs.test.Directory") << "write 3";
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
return OxError(0);
return ox::Error(0);
}
},
{
@ -221,7 +213,6 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxTrace("ox.fs.test.FileSystem") << "format";
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
oxTrace("ox.fs.test.FileSystem") << "mkdir";
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
oxAssert(fs.stat("/dir").error, "mkdir failed");
@ -229,20 +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.mkdir("/l1d1/l2d2", true), "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) {
oxError("Must specify test to run");
return -1;
}
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::StringView const testName = args[1];
ox::StringView const testArg = args[2] ? args[2] : nullptr;
ox::StringView const testArg = argc >= 3 ? args[2] : nullptr;
auto const func = tests.find(testName);
if (func != tests.end()) {
oxAssert(func->second(testArg), "Test returned Error");

View File

@ -20,7 +20,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.good()) {
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 {
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};
} catch (const std::ios_base::failure &e) {
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 {
oxRequire(buff, loadFsBuff(path));
OX_REQUIRE(buff, loadFsBuff(path));
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
}
static ox::Error runLs(ox::FileSystem *fs, int argc, const char **argv) noexcept {
if (argc < 2) {
static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (args.size() < 2) {
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) {
oxOutf("{}\n", file);
}
return OxError(0);
return ox::Error(0);
}
static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexcept {
if (argc < 2) {
static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (args.size() < 2) {
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])));
fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
return OxError(0);
OX_REQUIRE(buff, fs->read(ox::StringView(args[1])));
std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
return ox::Error(0);
}
static ox::Error run(int argc, const char **argv) noexcept {
if (argc < 3) {
oxErr("OxFS file and subcommand arguments are required\n");
return OxError(1);
return ox::Error(1);
}
const auto fsPath = argv[1];
ox::String subCmd(argv[2]);
oxRequire(fs, loadFs(fsPath));
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const fsPath = args[1];
ox::String subCmd(args[2]);
OX_REQUIRE(fs, loadFs(fsPath));
if (subCmd == "ls") {
return runLs(fs.get(), argc - 2, argv + 2);
return runLs(fs.get(), args + 2);
} else if (subCmd == "read") {
return runRead(fs.get(), argc - 2, argv + 2);
return runRead(fs.get(), args + 2);
}
return OxError(1);
return ox::Error(1);
}
int main(int argc, const char **argv) {

View File

@ -34,7 +34,7 @@ class CirculerBuffer {
constexpr ox::Error put(char v) noexcept {
return write(&v, 1);
if (1 > avail()) {
return OxError(1, "Insufficient space in buffer");
return ox::Error(1, "Insufficient space in buffer");
}
m_buff[m_writePt] = v;
++m_writePt;
@ -43,8 +43,9 @@ class CirculerBuffer {
constexpr ox::Error write(const char *buff, std::size_t sz) noexcept {
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
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
@ -56,12 +57,13 @@ class CirculerBuffer {
ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
oxAssert(m_buff[0] == buff[seg1Sz], "break");
}
OX_ALLOW_UNSAFE_BUFFERS_END
return {};
}
constexpr ox::Error seekp(std::size_t bytesFwd) noexcept {
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;
if (m_writePt > m_buff.size()) {
@ -71,7 +73,7 @@ class CirculerBuffer {
}
constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
return OxError(1, "Unimplemented");
return ox::Error(1, "Unimplemented");
}
[[nodiscard]]
@ -90,7 +92,9 @@ class CirculerBuffer {
m_readPt -= m_buff.size();
// read seg 2
const auto seg2Sz = bytesRead - seg1Sz;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
OX_ALLOW_UNSAFE_BUFFERS_END
}
return bytesRead;
}

View File

@ -9,8 +9,8 @@
#ifdef OX_USE_STDLIB
#include <cstdio>
#include <sys/types.h>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@ -25,15 +25,22 @@
#include "logconn.hpp"
#include <ox/std/bit.hpp>
namespace ox {
#ifdef _WIN32
using Socket = SOCKET;
using LenType = int;
#else
using Socket = int;
using LenType = size_t;
#endif
using namespace trace;
void closeSock(auto s) noexcept {
static void closeSock(auto s) noexcept {
#ifdef _WIN32
closesocket(s);
closesocket(static_cast<Socket>(s));
#else
close(s);
#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{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(5590);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
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)});
}
@ -65,10 +72,10 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
std::size_t totalSent = 0;
while (totalSent < len) {
//std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket);
const auto sent = ::send(m_socket, buff, len, 0);
const auto sent = ::send(static_cast<Socket>(m_socket), buff, static_cast<LenType>(len), 0);
if (sent < 0) {
std::fprintf(stderr, "Could not send msg\n");
return OxError(1, "Could not send msg");
std::ignore = std::fprintf(stderr, "Could not send msg\n");
return ox::Error(1, "Could not send msg");
}
totalSent += static_cast<std::size_t>(sent);
}
@ -90,13 +97,14 @@ void LoggerConn::msgSend() noexcept {
if (!m_running) {
break;
}
std::lock_guard buffLk(m_buffMut);
std::lock_guard const buffLk(m_buffMut);
while (true) {
ox::Array<char, ox::units::KB> tmp;
Array<char, units::KB> tmp;
const auto read = m_buff.read(tmp.data(), tmp.size());
if (!read) {
break;
}
oxAssert(read <= tmp.size(), "logger trying to read too much data");
//std::printf("LoggerConn: sending %lu bytes\n", read);
std::ignore = send(tmp.data(), read);
}

View File

@ -38,20 +38,20 @@ class LoggerConn: public trace::Logger {
LoggerConn &operator=(const LoggerConn&) noexcept = delete;
ox::Error send(const trace::TraceMsg&) 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;
private:
void msgSend() noexcept;
ox::Error send(trace::MsgId msgId, const auto &msg) noexcept {
ox::Array<char, 10 * ox::units::KB> buff;
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);
oxRequire(szBuff, serialize(static_cast<uint32_t>(sz)));
OX_REQUIRE(szBuff, serialize(static_cast<uint32_t>(sz)));
std::unique_lock buffLk(m_buffMut);
oxReturnError(m_buff.put(static_cast<char>(msgId)));
oxReturnError(m_buff.write(szBuff.data(), szBuff.size()));
oxReturnError(m_buff.write(buff.data(), sz));
OX_RETURN_ERROR(m_buff.put(static_cast<char>(msgId)));
OX_RETURN_ERROR(m_buff.write(szBuff.data(), szBuff.size()));
OX_RETURN_ERROR(m_buff.write(buff.data(), sz));
buffLk.unlock();
m_waitCond.notify_one();
return {};

View File

@ -57,7 +57,7 @@ static_assert(highestBit(uint64_t(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63);
struct McInt {
uint8_t data[9] = {};
ox::Array<uint8_t, 9> data{};
// length of integer in bytes
std::size_t length = 0;
};
@ -104,7 +104,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
auto intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator);
ox::memcpy(out.data, &intermediate, sizeof(intermediate));
ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate));
}
out.length = bytes;
}
@ -135,19 +135,19 @@ static_assert(countBytes(0b1111'1111) == 9);
template<typename I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
uint8_t firstByte = 0;
oxReturnError(rdr.read(&firstByte, 1));
oxReturnError(rdr.seekg(-1, ox::ios_base::cur));
OX_RETURN_ERROR(rdr.read(&firstByte, 1));
OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte);
if (bytes == 9) {
*bytesRead = bytes;
I out = 0;
oxReturnError(rdr.seekg(1, ox::ios_base::cur));
oxReturnError(rdr.read(&out, sizeof(I)));
OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
return fromLittleEndian<I>(out);
}
*bytesRead = bytes;
uint64_t decoded = 0;
oxReturnError(rdr.read(&decoded, bytes));
OX_RETURN_ERROR(rdr.read(&decoded, bytes));
decoded >>= bytes;
// move sign bit
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 = {};
//d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32;
ox::memcpy(d.data(), &decoded, sizeof(decoded));
ox::memcpy(&d[0], &decoded, sizeof(decoded));
auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++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[1] = d0Tmp;
}
ox::memcpy(&out, d.data(), sizeof(out));
ox::memcpy(&out, &d[0], sizeof(out));
return out;
}
}
@ -185,7 +185,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
template<typename I>
Result<I> decodeInteger(McInt m) noexcept {
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);
}

View File

@ -47,7 +47,7 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
oxReturnError(loadMapBlock(blockIdx));
OX_RETURN_ERROR(loadMapBlock(blockIdx));
}
idx %= blockBits;
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>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
oxRequire(g, m_reader.tellg());
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
OX_REQUIRE(g, m_reader.tellg());
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// 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;
for (auto i = 0ull; auto b : mapBlock) {
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) {
return (m_map[i / 8] >> (i % 8)) & 1;
} 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 {
if (i / 8 < m_mapLen) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (on) {
m_map[i / 8] |= 1 << (i % 8);
} else {
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
}
OX_ALLOW_UNSAFE_BUFFERS_END
return {};
} else {
return OxError(McPresenceMapOverflow);
return ox::Error(McPresenceMapOverflow);
}
}

View File

@ -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) {
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
*val = result.value;
oxReturnError(result);
OX_RETURN_ERROR(result);
}
++m_field;
return OxError(0);
return ox::Error(0);
}
// 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))) {
// read the length
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
if (valLen >= len) {
auto reader = child({});
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) {
oxReturnError(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
}
} else {
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_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length
oxRequire(g, m_reader.tellg());
OX_REQUIRE(g, m_reader.tellg());
std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
oxReturnError(m_reader.seekg(g));
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
OX_RETURN_ERROR(m_reader.seekg(g));
// read the list
auto reader = child("");
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
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 wkeyPtr = wkey.get();
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
return handler.field("", &val[wkeyPtr]);
};
for (std::size_t i = 0; i < len; ++i) {
oxReturnError(loopBody(handler, *val));
OX_RETURN_ERROR(loopBody(handler, *val));
}
}
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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) {
// 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))) {
oxRequire(len, arrayLength(name, false));
oxReturnError(ox::resizeVector(*val, len));
OX_REQUIRE(len, arrayLength(name, false));
OX_RETURN_ERROR(ox::resizeVector(*val, len));
return field(name, val->data(), val->size());
}
oxReturnError(ox::resizeVector(*val, 0));
OX_RETURN_ERROR(ox::resizeVector(*val, 0));
}
++m_field;
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) {
// 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))) {
oxRequire(len, arrayLength(name, false));
OX_REQUIRE(len, arrayLength(name, false));
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());
@ -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_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child("");
oxReturnError(model(reader.interface(), val));
OX_RETURN_ERROR(model(reader.interface(), val));
}
}
++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_fieldPresence.get(static_cast<std::size_t>(m_field))) {
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;
@ -317,18 +319,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length
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;
*val = BasicString<SmallStringSize>(cap);
auto data = val->data();
// read the string
oxReturnError(m_reader.read(data, size));
OX_RETURN_ERROR(m_reader.read(data, size));
} else {
*val = "";
}
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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))) {
// read the length
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>();
oxReturnError(val->resize(size));
OX_RETURN_ERROR(val->resize(size));
auto const data = val->data();
// read the string
oxReturnError(m_reader.read(data, size));
OX_RETURN_ERROR(m_reader.read(data, size));
} else {
*val = "";
}
@ -357,18 +359,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length
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) {
return OxError(McOutputBuffEnded);
return ox::Error(McOutputBuffEnded);
}
// re-allocate in case too small
auto data = val;
// read the string
oxReturnError(m_reader.read(data, size));
OX_RETURN_ERROR(m_reader.read(data, size));
data[size] = 0;
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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))) {
// read the length
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
safeDelete(*val);
*val = new char[size + 1];
auto data = *val;
auto data = ox::Span{*val, size + 1};
// read the string
oxReturnError(m_reader.read(data, size));
OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0;
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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))) {
// read the length
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
if (buffLen < size + 1) {
safeDelete(*val);
*val = new char[size + 1];
buffLen = size + 1;
}
auto data = *val;
auto data = ox::Span{*val, size + 1};
// read the string
oxReturnError(m_reader.read(data, size));
OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0;
} else {
auto data = *val;
@ -414,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
}
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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))) {
// read the length
std::size_t bytesRead = 0;
oxRequire(g, m_reader.tellg());
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
OX_REQUIRE(g, m_reader.tellg());
OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
if (!pass) {
oxReturnError(m_reader.seekg(g));
OX_RETURN_ERROR(m_reader.seekg(g));
}
return out;
}
}
return OxError(1);
return ox::Error(1);
}
template<Reader_c Reader>
@ -441,7 +443,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
// read the length
std::size_t bytesRead = 0;
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;
}
}
@ -455,14 +457,14 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
std::size_t bytesRead = 0;
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
oxReturnError(result);
OX_RETURN_ERROR(result);
*val = result.value;
} else {
*val = 0;
}
}
++m_field;
return OxError(0);
return ox::Error(0);
}
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))) {
// read the length
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
auto reader = child("");
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) {
T val;
oxReturnError(handler.field("", &val));
oxReturnError(cb(i, &val));
OX_RETURN_ERROR(handler.field("", &val));
OX_RETURN_ERROR(cb(i, &val));
}
}
}
++m_field;
return OxError(0);
return ox::Error(0);
}
template<Reader_c Reader>
@ -546,7 +548,7 @@ Error readMC(ox::BufferView buff, T &val) noexcept {
template<typename T>
Result<T> readMC(ox::BufferView buff) noexcept {
Result<T> val;
oxReturnError(readMC(buff, val.value));
OX_RETURN_ERROR(readMC(buff, val.value));
return val;
}

View File

@ -62,47 +62,47 @@ struct TestStruct {
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("CString", &obj->CString));
return OxError(0);
OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->fieldCString("CString", &obj->CString));
return ox::Error(0);
}
oxModelBegin(TestStructNest)
oxModelField(Bool)
oxModelField(Int)
oxModelField(IString)
oxModelEnd()
OX_MODEL_BEGIN(TestStructNest)
OX_MODEL_FIELD(Bool)
OX_MODEL_FIELD(Int)
OX_MODEL_FIELD(IString)
OX_MODEL_END()
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx));
OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
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 {
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));
oxReturnError(io->field("IString", &obj->IString));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Vector2", &obj->Vector2));
oxReturnError(io->field("Map", &obj->Map));
oxReturnError(io->field("Struct", &obj->Struct));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
return OxError(0);
OX_RETURN_ERROR(io->field("String", &obj->String));
OX_RETURN_ERROR(io->field("IString", &obj->IString));
OX_RETURN_ERROR(io->field("List", obj->List, 4));
OX_RETURN_ERROR(io->field("Vector", &obj->Vector));
OX_RETURN_ERROR(io->field("Vector2", &obj->Vector2));
OX_RETURN_ERROR(io->field("Map", &obj->Map));
OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
return ox::Error(0);
}
std::map<ox::StringView, ox::Error(*)()> tests = {
@ -114,9 +114,9 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// doesn't segfault
ox::Array<char, 1024> buff;
TestStruct ts;
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts));
oxReturnError(ox::writeMC(ts));
return OxError(0);
OX_RETURN_ERROR(ox::writeMC(buff.data(), buff.size(), ts));
OX_RETURN_ERROR(ox::writeMC(ts));
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.IString == testOut.Struct.IString, "Struct.IString 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) {
if (val.length != expected.size()) {
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++) {
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: " << 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) {
if (val.length != 9) {
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]);
if (expected != decoded) {
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
return OxError(1);
return ox::Error(1);
}
return OxError(0);
return ox::Error(0);
};
// signed positive
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
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");
return OxError(0);
return ox::Error(0);
}
},
@ -260,12 +260,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
using ox::mc::decodeInteger;
static constexpr auto check = [](auto val) {
auto result = decodeInteger<decltype(val)>(encodeInteger(val));
oxReturnError(result.error);
OX_RETURN_ERROR(result.error);
if (result.value != val) {
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(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(0xffffffffffff), "Decode of 0xffffffffffff 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;
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed");
ox::TypeStore typeStore;
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut;
oxReturnError(testOut.setType(type));
OX_RETURN_ERROR(testOut.setType(type));
oxAssert(ox::readMC(dataBuff, testOut), "Data read 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");
@ -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(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");
return OxError(0);
return ox::Error(0);
}
},
@ -368,10 +368,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Struct.IString = "Test String 2";
oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed");
ox::TypeStore typeStore;
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed");
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 {
//std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str();
@ -454,10 +454,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union:
break;
}
return OxError(0);
return ox::Error(0);
}
));
return OxError(0);
return ox::Error(0);
}
},
}

View File

@ -117,12 +117,12 @@ class MetalClawWriter {
bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
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;
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>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
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;
return OxError(0);
return ox::Error(0);
}
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)) {
// write the length
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
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;
}
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;
return OxError(0);
return ox::Error(0);
}
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;
// write the length
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
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;
}
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;
return OxError(0);
return ox::Error(0);
}
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)) {
// write the length
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
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;
}
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;
return OxError(0);
return ox::Error(0);
}
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();
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val));
oxReturnError(writer.finalize());
OX_RETURN_ERROR(model(&handler, val));
OX_RETURN_ERROR(writer.finalize());
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;
return {};
}
@ -282,11 +282,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get()));
oxReturnError(writer.finalize());
OX_RETURN_ERROR(model(&handler, val.get()));
OX_RETURN_ERROR(writer.finalize());
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;
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)) {
// write the length
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();
MetalClawWriter<Writer> writer(m_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
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();
}
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;
return OxError(0);
return ox::Error(0);
}
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)) {
// write the length
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
MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer};
// 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
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.len();
auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1);
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
oxRequireM(value, val.at(key));
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
OX_REQUIRE_M(value, val.at(key));
return handler.field("", value);
};
// write the array
for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val));
OX_RETURN_ERROR(loopBody(handler, key, *val));
}
oxReturnError(writer.finalize());
OX_RETURN_ERROR(writer.finalize());
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;
return OxError(0);
return ox::Error(0);
}
template<Writer_c Writer>
@ -360,7 +362,7 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
const Vector<String>&,
std::size_t fields) noexcept {
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_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields));
@ -370,33 +372,33 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write(
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end));
OX_RETURN_ERROR(m_writer.seekp(end));
return {};
}
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter};
oxReturnError(model(&handler, &val));
oxReturnError(mcWriter.finalize());
OX_RETURN_ERROR(model(&handler, &val));
OX_RETURN_ERROR(mcWriter.finalize());
return {};
}
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, val));
OX_RETURN_ERROR(writeMC(bw, val));
buff.resize(bw.tellp());
return buff;
}
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw(buff, buffLen);
oxReturnError(writeMC(bw, val));
CharBuffWriter bw{{buff, buffLen}};
OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) {
*sizeOut = bw.tellp();
}

View File

@ -10,8 +10,10 @@
#include <ox/std/concepts.hpp>
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>());
#define oxModelEnd() return OxError(0); }
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith<modelName> auto*) noexcept
// oxModelFwdDecl is necessary because Apple-Clang is broken...
#define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
#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 OX_MODEL_END() return ox::Error(0); }
#define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
#define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
#define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept

View File

@ -35,7 +35,7 @@ constexpr auto buildTypeId() noexcept {
}
static constexpr auto buildTypeId(
CRStringView name, int version,
StringViewCR name, int version,
const TypeParamPack &typeParams = {}) noexcept {
String tp;
if (!typeParams.empty()) {
@ -76,21 +76,21 @@ struct Subscript {
template<typename T>
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) {
uint32_t st = 0;
oxReturnError(io->field("subscriptType", &st));
OX_RETURN_ERROR(io->field("subscriptType", &st));
} else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt));
OX_RETURN_ERROR(io->field("subscriptType", &pt));
} else {
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);
}
oxReturnError(io->field("length", &type->length));
oxReturnError(io->field("smallSzLen", &type->smallSzLen));
return OxError(0);
OX_RETURN_ERROR(io->field("length", &type->length));
OX_RETURN_ERROR(io->field("smallSzLen", &type->smallSzLen));
return {};
}
using SubscriptStack = Vector<Subscript, 3>;
@ -119,6 +119,7 @@ struct DescriptorField {
subscriptLevels(pSubscriptLevels),
subscriptStack(std::move(pSubscriptType)),
typeId(std::move(pTypeId)) {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "Subscript level mismatch");
}
constexpr DescriptorField(const DescriptorField &other) noexcept:
@ -184,38 +185,38 @@ constexpr auto buildTypeId(const DescriptorType &t) noexcept {
template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorType>());
oxReturnError(io->field("typeName", &type->typeName));
oxReturnError(io->field("typeVersion", &type->typeVersion));
OX_RETURN_ERROR(io->template setTypeInfo<DescriptorType>());
OX_RETURN_ERROR(io->field("typeName", &type->typeName));
OX_RETURN_ERROR(io->field("typeVersion", &type->typeVersion));
if constexpr(T::opType() == OpType::Reflect) {
uint8_t pt = 0;
oxReturnError(io->field("primitiveType", &pt));
OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt));
OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else {
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);
}
oxReturnError(io->field("typeParams", &type->typeParams));
oxReturnError(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable));
return OxError(0);
OX_RETURN_ERROR(io->field("typeParams", &type->typeParams));
OX_RETURN_ERROR(io->field("fieldList", &type->fieldList));
OX_RETURN_ERROR(io->field("length", &type->length));
OX_RETURN_ERROR(io->field("preloadable", &type->preloadable));
return {};
}
template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorField>());
oxReturnError(io->field("typeId", &field->typeId));
oxReturnError(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels));
oxReturnError(io->field("subscriptStack", &field->subscriptStack));
OX_RETURN_ERROR(io->template setTypeInfo<DescriptorField>());
OX_RETURN_ERROR(io->field("typeId", &field->typeId));
OX_RETURN_ERROR(io->field("fieldName", &field->fieldName));
OX_RETURN_ERROR(io->field("subscriptLevels", &field->subscriptLevels));
OX_RETURN_ERROR(io->field("subscriptStack", &field->subscriptStack));
// defaultValue is unused now, but leave placeholder for backwards compatibility
int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0);
OX_RETURN_ERROR(io->field("defaultValue", &defaultValue));
return {};
}
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
int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0);
return ox::Error(0);
}
#endif

View File

@ -91,23 +91,29 @@ class TypeDescWriter {
constexpr ~TypeDescWriter() noexcept = default;
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(CRStringView name = T::TypeName,
int version = T::TypeVersion,
const TypeParamPack &typeParams = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept;
constexpr ox::Error setTypeInfo(StringViewCR name = T::TypeName,
int version = T::TypeVersion,
const TypeParamPack &typeParams = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept;
template<typename T>
constexpr Error field(CRStringView name, const T *val, std::size_t valLen,
const SubscriptStack &subscriptStack = {}) noexcept;
constexpr Error field(
StringViewCR name,
T const*val,
std::size_t valLen,
SubscriptStack const&subscriptStack) noexcept;
template<typename T>
constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept;
template<typename T, bool force>
constexpr Error field(CRStringView name, UnionView<T, force> val) noexcept;
constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept;
template<typename T>
constexpr Error field(CRStringView name, const T *val) noexcept;
constexpr Error field(StringViewCR name, const T *val) noexcept;
template<typename ...Args>
constexpr Error fieldCString(CRStringView name, Args&&...) noexcept;
constexpr Error fieldCString(StringViewCR name, Args&&...) noexcept;
[[nodiscard]]
constexpr DescriptorType *definition() noexcept {
@ -167,7 +173,7 @@ class TypeDescWriter {
constexpr const DescriptorType *type(UnionView<U> val) const noexcept;
[[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;
};
@ -176,8 +182,8 @@ constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeS
template<typename T>
constexpr ox::Error TypeDescWriter::setTypeInfo(
CRStringView typeName, int typeVersion,
const TypeParamPack &typeParams, std::size_t) noexcept {
StringViewCR typeName, int typeVersion,
const TypeParamPack &typeParams, std::size_t) noexcept {
PrimitiveType pt;
if constexpr(is_union_v<T>) {
pt = PrimitiveType::Union;
@ -193,30 +199,45 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
// array handler
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) {
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");
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>
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) {
const auto t = type(val);
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));
return OxError(0);
return ox::Error(0);
}
return OxError(1);
return ox::Error(1);
}
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 constexpr(isVector_v<T> || isArray_v<T>) {
typename T::value_type *data = nullptr;
@ -233,11 +254,11 @@ constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept
return {};
}
}
return OxError(1);
return ox::Error(1);
}
template<typename ...Args>
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
constexpr Error TypeDescWriter::fieldCString(StringViewCR name, Args&&...) noexcept {
constexpr auto s = "";
const auto t = type(s);
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);
}
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 {
auto t = m_typeStore->get(tn, typeVersion, typeParams);
if (!t.error) {
@ -357,26 +378,26 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
TypeDescWriter writer(typeStore);
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
if (std::is_constant_evaluated()) {
std::allocator<T> a;
T *t = a.allocate(1);
oxReturnError(model(&handler, t));
OX_RETURN_ERROR(model(&handler, t));
a.deallocate(t, 1);
} else {
auto t = ox_malloca(sizeof(T), T);
oxReturnError(model(&handler, t.get()));
OX_RETURN_ERROR(model(&handler, t.get()));
}
return writer.definition();
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
TypeDescWriter writer(typeStore);
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
oxReturnError(model(&handler, val));
OX_RETURN_ERROR(model(&handler, &val));
return writer.definition();
}

View File

@ -24,32 +24,32 @@ class FieldCounter {
std::size_t fields = 0;
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 {};
}
template<typename U>
constexpr ox::Error field(CRStringView, U) noexcept {
constexpr ox::Error field(StringViewCR, U) noexcept {
++fields;
return OxError(0);
return ox::Error(0);
}
template<typename U>
constexpr ox::Error field(CRStringView, U, std::size_t) noexcept {
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
++fields;
return OxError(0);
return ox::Error(0);
}
template<typename U, typename Handler>
constexpr Error field(CRStringView, Handler) {
constexpr Error field(StringViewCR, Handler) {
++fields;
return OxError(0);
return ox::Error(0);
}
template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept {
++fields;
return OxError(0);
return ox::Error(0);
}
static constexpr auto opType() noexcept {

View File

@ -135,8 +135,8 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>());
}
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(OxError(1), "invalid type");
return OxError(1, "invalid type");
oxPanic(ox::Error(1), "invalid type");
return ox::Error(1, "invalid type");
}
// array handler, with callback to allow handling individual elements

View File

@ -56,19 +56,19 @@ class MemberList {
template<typename T>
constexpr Error field(const char*, T *v) noexcept {
vars[m_i++] = static_cast<void*>(v);
return OxError(0);
return ox::Error(0);
}
template<typename T>
constexpr Error field(const char*, T *v, int) noexcept {
vars[m_i++] = static_cast<void*>(v);
return OxError(0);
return ox::Error(0);
}
template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
vars[m_i++] = static_cast<void*>(u.get());
return OxError(0);
return ox::Error(0);
}
template<typename T>
@ -107,7 +107,7 @@ class Copier {
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
dst = src;
++m_i;
return OxError(0);
return ox::Error(0);
}
}
@ -119,7 +119,7 @@ class Copier {
dst = src;
}
++m_i;
return OxError(0);
return ox::Error(0);
}
template<typename U, bool force = false>
@ -128,7 +128,7 @@ class Copier {
auto &src = *u.get();
dst = src;
++m_i;
return OxError(0);
return ox::Error(0);
}
template<typename T = void>
@ -168,7 +168,7 @@ class Mover {
dst = std::move(src);
src = FT{};
++m_i;
return OxError(0);
return ox::Error(0);
}
}
@ -181,7 +181,7 @@ class Mover {
src = FT{};
}
++m_i;
return OxError(0);
return ox::Error(0);
}
template<typename U, bool force = false>
@ -190,7 +190,7 @@ class Mover {
auto &src = *u.get();
dst = std::move(src);
++m_i;
return OxError(0);
return ox::Error(0);
}
template<typename T = void>
@ -228,10 +228,10 @@ class Equals {
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
++m_i;
if (dst == src) {
return OxError(0);
return ox::Error(0);
} else {
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];
if (!(dst == src)) {
this->value = false;
return OxError(1);
return ox::Error(1);
}
}
++m_i;
return OxError(0);
return ox::Error(0);
}
template<typename U, bool force = false>
@ -255,10 +255,10 @@ class Equals {
const auto &src = *u.get();
++m_i;
if (dst == src) {
return OxError(0);
return ox::Error(0);
} else {
this->value = false;
return OxError(1);
return ox::Error(1);
}
}

View File

@ -12,12 +12,12 @@ namespace ox {
static_assert([]() -> ox::Error {
ox::ModelValue v;
oxReturnError(v.setType<int32_t>());
OX_RETURN_ERROR(v.setType<int32_t>());
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));
return {};
}() == OxError(0));
}() == ox::Error(0));
}

View File

@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast");
oxPanic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}
@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast");
oxPanic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}
@ -188,8 +188,8 @@ class ModelValue {
constexpr Error setType(
DescriptorType const*type,
int subscriptLevels = 0,
SubscriptStack const& = {}) noexcept;
SubscriptStack const& = {},
int subscriptLevels = 0) noexcept;
template<typename T>
constexpr Error setType() noexcept;
@ -242,7 +242,7 @@ class ModelValueArray {
m_vec.resize(sz);
if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels));
OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
}
}
return {};
@ -276,8 +276,9 @@ class ModelValueArray {
constexpr Error setType(
DescriptorType const*type,
int subscriptLevels,
SubscriptStack subscriptStack) noexcept {
SubscriptStack subscriptStack,
int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type;
m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack);
@ -400,7 +401,7 @@ class ModelValueVector {
m_vec.resize(sz);
if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack));
OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
}
}
return {};
@ -418,8 +419,9 @@ class ModelValueVector {
constexpr Error setType(
DescriptorType const*type,
int subscriptLevels,
SubscriptStack subscriptStack) noexcept {
SubscriptStack subscriptStack,
int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type;
m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack);
@ -517,7 +519,7 @@ class ModelObject {
ModelValue value;
};
protected:
oxModelFriend(ModelObject);
OX_MODEL_FRIEND(ModelObject);
friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder;
HashMap<String, ModelValue*> m_fields;
@ -632,18 +634,18 @@ class ModelObject {
if (m_fields.contains(k)) {
return *m_fields.at(k).value;
}
return OxError(1);
return ox::Error(1);
}
template<typename T>
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);
return {};
}
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k));
OX_REQUIRE(v, m_fields.at(k));
return *v;
}
@ -652,7 +654,7 @@ class ModelObject {
}
[[nodiscard]]
constexpr CRString typeName() const noexcept {
constexpr StringCR typeName() const noexcept {
return m_type->typeName;
}
@ -668,17 +670,17 @@ class ModelObject {
constexpr Error setType(const DescriptorType *type) noexcept {
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;
for (const auto &f : type->fieldList) {
auto field = make_unique<Field>();
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_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 {
UniquePtr<ModelUnion> out(new ModelUnion);
oxReturnError(out->setType(type));
OX_RETURN_ERROR(out->setType(type));
return out;
}
@ -729,7 +731,7 @@ class ModelUnion {
}
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;
}
@ -761,7 +763,7 @@ class ModelUnion {
[[nodiscard]]
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;
}
@ -788,7 +790,7 @@ class ModelUnion {
constexpr Error setType(const DescriptorType *type) noexcept {
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_fieldsOrder.clear();
@ -797,12 +799,12 @@ class ModelUnion {
auto field = make_unique<Field>();
field->name = f.fieldName;
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_fieldsOrder.emplace_back(std::move(field));
++i;
}
return OxError(0);
return {};
}
[[nodiscard]]
@ -965,21 +967,21 @@ constexpr std::size_t alignOf(const ModelValue &t) 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()));
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 {
oxReturnError(h->template setTypeInfo<ModelUnion>(
OX_RETURN_ERROR(h->template setTypeInfo<ModelUnion>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
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 {
@ -1076,20 +1078,21 @@ constexpr ModelValue::Type ModelValue::type() const noexcept {
constexpr Error ModelValue::setType(
const DescriptorType *type,
int subscriptLevels,
SubscriptStack const&subscriptStack) noexcept {
SubscriptStack const&subscriptStack,
int subscriptLevels) noexcept {
freeResources();
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
if (subscriptLevels) {
auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)];
if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) {
m_type = Type::InlineArray;
m_data.array = new ModelValueArray;
oxReturnError(m_data.array->setType(type, subscriptLevels - 1, subscriptStack));
oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length)));
OX_RETURN_ERROR(m_data.array->setType(type, subscriptStack, subscriptLevels - 1));
OX_RETURN_ERROR(m_data.array->setSize(static_cast<size_t>(subscript.length)));
} else {
m_type = Type::Vector;
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 {};
} else if (type->typeName == types::Bool) {
@ -1118,15 +1121,15 @@ constexpr Error ModelValue::setType(
} else if (type->primitiveType == PrimitiveType::Struct) {
m_type = Type::Object;
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) {
m_type = Type::Union;
oxRequireM(u, ModelUnion::make(type));
OX_REQUIRE_M(u, ModelUnion::make(type));
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");
return OxError(0);
return ox::Error(0);
}
template<typename T>
@ -1138,11 +1141,11 @@ constexpr Error ModelValue::setType() noexcept {
// rather than using getValue<type>()
if constexpr(type == Type::Object) {
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) {
oxRequireM(u, ModelUnion::make(type));
OX_REQUIRE_M(u, ModelUnion::make(type));
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) {
m_data.str = new String;
} else if constexpr(type == Type::Vector) {
@ -1173,7 +1176,7 @@ template<typename T>
constexpr Error ModelValue::set(const T &v) noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch");
return ox::Error(1, "type mismatch");
}
auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object ||
@ -1181,14 +1184,14 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value);
}
value = v;
return OxError(0);
return ox::Error(0);
}
template<typename T>
constexpr Error ModelValue::set(T &&v) noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch");
return ox::Error(1, "type mismatch");
}
auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object ||
@ -1196,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value);
}
value = std::move(v);
return OxError(0);
return ox::Error(0);
}
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {

View File

@ -17,8 +17,8 @@ struct TestType {
static constexpr auto TypeVersion = 1;
};
oxModelBegin(TestType)
oxModelEnd()
OX_MODEL_BEGIN(TestType)
OX_MODEL_END()
struct TestType2 {
};
@ -38,12 +38,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
"ModelValue",
[] {
ox::ModelValue v;
oxReturnError(v.setType<int32_t>());
OX_RETURN_ERROR(v.setType<int32_t>());
//v.m_type = ox::ModelValue::getType<int32_t>();
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{};
}
},

View File

@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0);
return ox::Error(0);
}
template<typename T>
constexpr Error field(const char*, T) noexcept {
return OxError(0);
return ox::Error(0);
}
template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept {
return OxError(0);
return ox::Error(0);
}
static constexpr auto opType() noexcept {
@ -77,17 +77,17 @@ struct TypeInfoCatcher {
template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0);
return ox::Error(0);
}
template<typename T>
constexpr Error field(const char*, T) noexcept {
return OxError(0);
return ox::Error(0);
}
template<typename T>
constexpr Error fieldCString(const char*, T) noexcept {
return OxError(0);
return ox::Error(0);
}
static constexpr auto opType() noexcept {

View File

@ -31,7 +31,7 @@ class TypeStore {
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
const TypeParamPack &typeParams) const noexcept {
const auto typeId = buildTypeId(name, typeVersion, typeParams);
oxRequire(out, m_cache.at(typeId));
OX_REQUIRE(out, m_cache.at(typeId));
return out->get();
}
@ -40,11 +40,11 @@ class TypeStore {
constexpr auto typeName = ModelTypeName_v<T>;
constexpr auto typeVersion = ModelTypeVersion_v<T>;
const auto typeId = buildTypeId(typeName, typeVersion, {});
oxRequire(out, m_cache.at(typeId));
OX_REQUIRE(out, m_cache.at(typeId));
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 auto typeId = buildTypeId(typeName, typeVersion, typeParams);
auto &out = m_cache[typeId];
@ -56,15 +56,15 @@ class TypeStore {
auto [val, err] = m_cache.at(typeId);
if (err) {
if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeId));
OX_REQUIRE_M(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeId).moveTo(f.type));
OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type));
}
auto &out = m_cache[typeId];
out = std::move(dt);
return out.get();
} else {
return OxError(1, "Type not available");
return ox::Error(1, "Type not available");
}
}
return val->get();
@ -102,10 +102,10 @@ class TypeStore {
protected:
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 auto typeId = buildTypeId(name, version, typeParams);
return loadDescriptor(typeId);

View File

@ -50,7 +50,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler
template<typename Reader, typename T>
constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept {
oxRequire(out, m_typeStack.back());
OX_REQUIRE(out, m_typeStack.back());
return *out;
}
@ -87,9 +87,9 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) {
// 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());
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
--f.subscriptLevels;
String subscript;
@ -98,7 +98,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
subscript += static_cast<uint64_t>(i);
subscript += "]";
walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker));
OX_RETURN_ERROR(parseField(f, &child, walker));
walker->popNamePath();
}
rdr->nextField();
@ -108,40 +108,40 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
case PrimitiveType::SignedInteger:
case PrimitiveType::Bool:
case PrimitiveType::String:
oxReturnError(walker->read(field, rdr));
OX_RETURN_ERROR(walker->read(field, rdr));
break;
case PrimitiveType::Struct:
case PrimitiveType::Union:
if (rdr->fieldPresent(field.fieldName.c_str())) {
auto child = rdr->child(field.fieldName.c_str());
walker->pushType(field.type);
oxReturnError(model(&child, walker));
OX_RETURN_ERROR(model(&child, walker));
walker->popType();
rdr->nextField();
} else {
// skip and discard absent field
int discard;
oxReturnError(rdr->field(field.fieldName.c_str(), &discard));
OX_RETURN_ERROR(rdr->field(field.fieldName.c_str(), &discard));
}
break;
}
}
walker->popNamePath();
return OxError(0);
return ox::Error(0);
}
template<typename Reader, typename FH>
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 typeVersion = type->typeVersion;
auto typeParams = type->typeParams;
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) {
oxReturnError(parseField(field, rdr, walker));
OX_RETURN_ERROR(parseField(field, rdr, walker));
}
return OxError(0);
return ox::Error(0);
}
template<typename Reader, typename Handler>

View File

@ -19,7 +19,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize)
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
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;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
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 {
auto err = OxError(0);
auto err = ox::Error(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@ -45,7 +45,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} else if (jv.isBool()) {
*val = jv.asBool();
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++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 {
auto err = OxError(0);
auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
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);
auto data = val;
if (strSize >= buffLen) {
err = OxError(2, "String size exceeds capacity of destination");
err = ox::Error(2, "String size exceeds capacity of destination");
} else {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
}
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++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 {
auto err = OxError(0);
auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
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));
data[strSize] = 0;
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++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 {
auto err = OxError(0);
auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
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));
data[strSize] = nullptr;
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++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 {
UUIDStr str;
oxReturnError(field(key, &str));
OX_RETURN_ERROR(field(key, &str));
return UUID::fromString(str).moveTo(*val);
}
@ -147,7 +147,7 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
if (jv.isArray()) {
return jv.size();
}
return OxError(1, "Type mismatch");
return ox::Error(1, "Type mismatch");
}
[[nodiscard]]
@ -161,7 +161,7 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
jv.getString(&begin, &end);
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 {

View File

@ -133,7 +133,7 @@ class OrganicClawReader {
template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept {
auto err = OxError(0);
auto err = ox::Error(0);
try {
if constexpr (is_integer_v<T>) {
if (targetValid()) {
@ -146,19 +146,19 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
} else if (rightType) {
*val = static_cast<T>(jv.asUInt());
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
} else if constexpr (isVector_v<T>) {
const auto&srcVal = value(key);
const auto srcSize = srcVal.size();
oxReturnError(ox::resizeVector(*val, srcSize));
OX_RETURN_ERROR(ox::resizeVector(*val, srcSize));
err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) {
const auto&srcVal = value(key);
const auto srcSize = srcVal.size();
if (srcSize > val->size()) {
err = OxError(1, "Input array is too long");
err = ox::Error(1, "Input array is too long");
} else {
err = field(key, val->data(), val->size());
}
@ -169,11 +169,11 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
ModelHandlerInterface handler(&reader);
err = model(&handler, val);
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
} catch (Json::LogicError const&) {
err = OxError(1, "error reading JSON data");
err = ox::Error(1, "error reading JSON data");
}
++m_fieldIt;
return err;
@ -181,7 +181,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = OxError(0);
auto err = ox::Error(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
@ -189,7 +189,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
ModelHandlerInterface handler(&reader);
err = model(&handler, val.get());
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++m_fieldIt;
@ -198,7 +198,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
template<std::size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
auto err = OxError(0);
auto err = ox::Error(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@ -206,7 +206,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
} else if (jv.isString()) {
*val = jv.asString().c_str();
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++m_fieldIt;
@ -215,7 +215,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
auto err = OxError(0);
auto err = ox::Error(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@ -223,7 +223,7 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
} else if (jv.isString()) {
*val = jv.asString().c_str();
} else {
err = OxError(1, "Type mismatch");
err = ox::Error(1, "Type mismatch");
}
}
++m_fieldIt;
@ -235,25 +235,27 @@ template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
const auto &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) {
return OxError(1, "Type mismatch");
return ox::Error(1, "Type mismatch");
}
auto srcSize = srcVal.size();
if (srcSize > valLen) {
return OxError(1);
return ox::Error(1);
}
OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r};
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>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key);
if (!srcVal.isObject()) {
return OxError(1, "Type mismatch");
return ox::Error(1, "Type mismatch");
}
auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size();
@ -261,9 +263,9 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
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 {
@ -272,8 +274,10 @@ Error readOC(BufferView buff, auto &val) noexcept {
Json::Value doc;
Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
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());
ModelHandlerInterface handler(&reader);
@ -281,14 +285,14 @@ Error readOC(BufferView buff, auto &val) noexcept {
} catch (const Error &err) {
return err;
} catch (...) {
return OxError(1, "Unknown Error");
return ox::Error(1, "Unknown Error");
}
}
template<typename T>
Result<T> readOC(BufferView buff) noexcept {
Result<T> val;
oxReturnError(readOC(buff, val.value));
OX_RETURN_ERROR(readOC(buff, val.value));
return val;
}

View File

@ -74,45 +74,45 @@ struct TestStruct {
};
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String));
return OxError(0);
OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return ox::Error(0);
}
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String));
return OxError(0);
OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->field("String", &obj->String));
return ox::Error(0);
}
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx));
OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
OX_RETURN_ERROR(io->field("Int", &obj->Int));
OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
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 {
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));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct));
return OxError(0);
OX_RETURN_ERROR(io->field("String", &obj->String));
OX_RETURN_ERROR(io->field("List", obj->List, 4));
OX_RETURN_ERROR(io->field("Map", &obj->Map));
OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return ox::Error(0);
}
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.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;
oxAssert(ox::writeOC(testIn).moveTo(dataBuff), "Data generation failed");
ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value));
OX_RETURN_ERROR(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff, testOut), "Data read 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");
@ -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(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");
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);
oxAssert(ocErr, "Data generation failed");
ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
auto type = ox::buildTypeDef(typeStore, testIn);
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,
ox::OrganicClawReader *rdr) -> ox::Error {
auto fieldName = f.fieldName.c_str();
@ -341,10 +341,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union:
break;
}
return OxError(0);
return ox::Error(0);
}
));
return OxError(0);
return ox::Error(0);
}
},
}

View File

@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {

View File

@ -24,7 +24,8 @@ namespace ox {
class OrganicClawWriter {
friend Result<Buffer> writeOC(const auto &val) noexcept;
friend Result<ox::Buffer> writeOC(const auto &val) noexcept;
friend Result<ox::String> writeOCString(const auto &val) noexcept;
protected:
Json::Value m_json{Json::Value(Json::objectValue)};
@ -41,7 +42,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const int16_t *val) noexcept {
@ -49,7 +50,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const int32_t *val) noexcept {
@ -57,7 +58,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const int64_t *val) noexcept {
@ -65,7 +66,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
@ -74,7 +75,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const uint16_t *val) noexcept {
@ -82,7 +83,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const uint32_t *val) noexcept {
@ -90,7 +91,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(const char *key, const uint64_t *val) noexcept {
@ -98,7 +99,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error field(char const*key, bool const*val) noexcept {
@ -121,8 +122,8 @@ class OrganicClawWriter {
for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str();
if (k) [[likely]] {
oxRequireM(value, val->at(k));
oxReturnError(handler.field(k, value));
OX_REQUIRE_M(value, val->at(k));
OX_RETURN_ERROR(handler.field(k, value));
}
}
value(key) = w.m_json;
@ -146,7 +147,7 @@ class OrganicClawWriter {
value(key) = val->c_str();
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Error fieldCString(const char*, const char *const*val, int len) noexcept;
@ -199,12 +200,14 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n
OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
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;
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
template<typename T>
@ -224,13 +227,13 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
} else if (val && targetValid()) {
OrganicClawWriter 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()) {
value(key) = w.m_json;
}
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
template<typename U, bool force>
@ -238,23 +241,36 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
if (targetValid()) {
OrganicClawWriter w(val.idx());
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val.get()));
OX_RETURN_ERROR(model(&handler, val.get()));
if (!w.m_json.isNull()) {
value(key) = w.m_json;
}
}
++m_fieldIt;
return OxError(0);
return ox::Error(0);
}
Result<Buffer> writeOC(const auto &val) noexcept {
Result<ox::Buffer> writeOC(const auto &val) noexcept {
OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val));
Json::StreamWriterBuilder jsonBuilder;
OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json);
Buffer buff(str.size() + 1);
memcpy(buff.data(), str.c_str(), str.size() + 1);
Result<Buffer> buff;
buff.value.resize(str.size() + 1);
memcpy(buff.value.data(), str.data(), str.size() + 1);
return buff;
}
Result<ox::String> writeOCString(const auto &val) noexcept {
OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<ox::String> buff;
buff.value.resize(str.size());
memcpy(buff.value.data(), str.data(), str.size() + 1);
return buff;
}

View File

@ -46,12 +46,12 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
}
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());
}
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>) {
biggestAlignment = ox::max(biggestAlignment, PlatSpec::alignOf(*val));
} else {
@ -61,9 +61,9 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
}
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) {
oxReturnError(field(nullptr, &val[i]));
OX_RETURN_ERROR(field(nullptr, &val[i]));
}
return {};
}

View File

@ -94,19 +94,19 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
}
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>
constexpr ox::Error field(CRStringView, const T *val) noexcept;
constexpr ox::Error field(StringViewCR, const T *val) noexcept;
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>
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>
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;
@ -125,14 +125,14 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
constexpr ox::Error pad(const T*) noexcept;
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>
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;
@ -158,11 +158,11 @@ Preloader<PlatSpec>::make(ox::ios_base::seekdir anchor, std::size_t sz) noexcept
template<typename PlatSpec>
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()) {
return {};
}
oxReturnError(pad(val.get()));
OX_RETURN_ERROR(pad(val.get()));
m_unionIdx.emplace_back(val.idx());
const auto err = preload<PlatSpec, U>(this, val.get());
m_unionIdx.pop_back();
@ -171,17 +171,17 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::UnionView
template<typename PlatSpec>
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()) {
return {};
}
oxReturnError(pad(val));
OX_RETURN_ERROR(pad(val));
if constexpr(ox::is_integral_v<T>) {
return ox::serialize(m_writer, PlatSpec::correctEndianness(*val));
} else if constexpr(ox::is_pointer_v<T>) {
const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart;
oxReturnError(field(name, *val));
oxReturnError(endAlloc());
OX_RETURN_ERROR(field(name, *val));
OX_RETURN_ERROR(endAlloc());
return ox::serialize(m_writer, PlatSpec::correctEndianness(a));
} else if constexpr(ox::isVector_v<T>) {
return fieldVector(name, val);
@ -200,7 +200,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const T *val)
template<typename PlatSpec>
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()) {
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)),
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
};
oxReturnError(pad(&vecVal));
OX_RETURN_ERROR(pad(&vecVal));
const auto restore = m_writer.tellp();
std::size_t a = 0;
if (sz && sz >= SmallStringSize) {
oxReturnError(ox::allocate(m_writer, sz).moveTo(a));
OX_RETURN_ERROR(ox::allocate(m_writer, sz).moveTo(a));
} else {
a = restore;
}
vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart);
oxReturnError(m_writer.seekp(a));
oxReturnError(m_writer.write(val->data(), sz));
oxReturnError(m_writer.seekp(restore));
oxReturnError(serialize(m_writer, vecVal));
OX_RETURN_ERROR(m_writer.seekp(a));
OX_RETURN_ERROR(m_writer.write(val->data(), sz));
OX_RETURN_ERROR(m_writer.seekp(restore));
OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items);
return {};
}
template<typename PlatSpec>
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()) {
return {};
}
oxReturnError(pad(&(*val)[0]));
OX_RETURN_ERROR(pad(&(*val)[0]));
// serialize the Array elements
if constexpr(sz) {
m_unionIdx.emplace_back(-1);
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();
}
@ -248,16 +248,16 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const ox::Arra
template<typename PlatSpec>
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()) {
return {};
}
if (cnt) {
oxReturnError(pad(*val));
OX_RETURN_ERROR(pad(*val));
// serialize the array
m_unionIdx.emplace_back(-1);
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();
}
@ -267,11 +267,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const T **val, std:
template<typename PlatSpec>
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()));
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);
oxRequireM(a, ox::allocate(m_writer, sz + padding));
OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding;
oxReturnError(m_writer.seekp(a));
OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a);
return a;
}
@ -280,11 +280,11 @@ template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(
std::size_t sz, size_t align, std::size_t restore) noexcept {
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);
oxRequireM(a, ox::allocate(m_writer, sz + padding));
OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding;
oxReturnError(m_writer.seekp(a));
OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a);
return a;
}
@ -295,7 +295,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
return m_writer.seekp(0, ox::ios_base::end);
}
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_allocStart.pop_back();
return {};
@ -304,12 +304,12 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept {
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>(
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 {};
}
@ -327,7 +327,7 @@ constexpr ox::Error Preloader<PlatSpec>::pad(const T *v) noexcept {
template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector(
CRStringView name, const ox::ModelValueVector *val) noexcept {
StringViewCR name, const ox::ModelValueVector *val) noexcept {
// serialize the Vector
ox::VectorMemMap<PlatSpec> vecVal{
.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 T, std::size_t SmallVectorSize, typename Allocator>
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
ox::VectorMemMap<PlatSpec> vecVal{
.smallVecSize = SmallVectorSize * sizeOf<PlatSpec>(static_cast<T*>(nullptr)),
@ -353,40 +353,40 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector(
CRStringView, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
oxReturnError(pad(&vecVal));
StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
OX_RETURN_ERROR(pad(&vecVal));
const auto vecValPt = m_writer.tellp();
// serialize the Vector elements
if (val->size()) {
const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size();
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);
oxRequireM(p, ox::allocate(m_writer, sz + padding));
OX_REQUIRE_M(p, ox::allocate(m_writer, sz + padding));
p += padding;
oxReturnError(m_writer.seekp(p));
OX_RETURN_ERROR(m_writer.seekp(p));
m_unionIdx.emplace_back(-1);
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();
vecVal.items = PlatSpec::correctEndianness(
static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart));
oxReturnError(m_writer.seekp(vecValPt));
OX_RETURN_ERROR(m_writer.seekp(vecValPt));
} else {
vecVal.items = 0;
}
// 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);
return {};
}
template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldArray(CRStringView, ox::ModelValueArray const*val) noexcept {
oxReturnError(pad(&(*val)[0]));
constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept {
OX_RETURN_ERROR(pad(&(*val)[0]));
for (auto const&v : *val) {
oxReturnError(this->interface()->field({}, &v));
OX_RETURN_ERROR(this->interface()->field({}, &v));
}
return {};
}
@ -405,7 +405,7 @@ constexpr size_t Preloader<PlatSpec>::calcPadding(size_t align) const noexcept {
template<typename PlatSpec, typename T>
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);
}

View File

@ -74,7 +74,7 @@ template<typename T, bool force>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept {
pad(val.get());
UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get()));
OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size();
return {};
}
@ -91,7 +91,7 @@ template<typename PlatSpec>
template<typename T>
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) {
oxReturnError(field("", &val[i]));
OX_RETURN_ERROR(field("", &val[i]));
}
return {};
}

View File

@ -41,18 +41,18 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
}
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;
oxReturnError(model(sc.interface(), val.get()));
OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size();
return {};
}
template<typename T>
constexpr ox::Error field(CRStringView, const T *val) noexcept;
constexpr ox::Error field(StringViewCR, const T *val) noexcept;
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]]
constexpr auto size() const noexcept {
@ -61,33 +61,33 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
private:
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>
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;
};
template<typename PlatSpec>
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));
return {};
}
template<typename PlatSpec>
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) {
oxReturnError(field("", &val[i]));
OX_RETURN_ERROR(field("", &val[i]));
}
return {};
}
template<typename PlatSpec>
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;
setSize(sizeOf<PlatSpec>(v));
return {};
@ -95,7 +95,7 @@ constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldStr(CRStringView, const ox:
template<typename PlatSpec>
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;
setSize(sizeOf<PlatSpec>(v));
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)
add_library(
OxTraceHook SHARED
@ -113,6 +119,7 @@ install(
memory.hpp
new.hpp
optional.hpp
pair.hpp
point.hpp
random.hpp
ranges.hpp
@ -127,6 +134,7 @@ install(
stringview.hpp
strongint.hpp
strconv.hpp
stringparam.hpp
strops.hpp
trace.hpp
typeinfo.hpp

View File

@ -8,6 +8,10 @@
#pragma once
#include "def.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename It, typename T>
@ -40,4 +44,6 @@ constexpr OutIt copy_n(It in, Size cnt, OutIt out) {
return out;
}
}
}
OX_CLANG_NOWARN_END

View File

@ -9,6 +9,7 @@
#pragma once
#include "bit.hpp"
#include "def.hpp"
#include "error.hpp"
#include "initializerlist.hpp"
#include "iterator.hpp"
@ -17,6 +18,8 @@
#include "types.hpp"
#include "utility.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename T, std::size_t ArraySize>
@ -35,13 +38,17 @@ class Array {
public:
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(const Array &other);
constexpr Array(Array &&other) noexcept;
~Array() = default;
constexpr ~Array() = default;
constexpr iterator<> begin() noexcept {
return iterator<>(&m_items[0], 0, ArraySize);
@ -81,8 +88,10 @@ class Array {
constexpr Array &operator=(Array &&other) noexcept;
[[nodiscard]]
constexpr T &operator[](std::size_t i) noexcept;
[[nodiscard]]
constexpr const T &operator[](std::size_t i) const noexcept;
[[nodiscard]]
@ -172,11 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow");
return m_items[i];
}
template<typename T, std::size_t ArraySize>
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];
}
@ -196,3 +207,5 @@ constexpr bool Array<T, ArraySize>::contains(const T &v) const {
}
}
OX_CLANG_NOWARN_END

View File

@ -6,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "fmt.hpp"
#include "stacktrace.hpp"
#include "trace.hpp"
@ -13,7 +14,7 @@
namespace ox {
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept {
void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
@ -31,4 +32,40 @@ void panic(const char *file, int line, const char *panicMsg, const Error &err) n
#endif
}
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
}
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
output += genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
}
void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
#if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
msg += sfmt("\tError Code:\t{}\n", static_cast<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

@ -22,9 +22,9 @@
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()) {
panic(file, line, panicMsg, err);
} else {
@ -32,50 +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 (!std::is_constant_evaluated()) {
#ifdef OX_USE_STDLIB
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
printStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
assertFailFuncRuntime(file, line, assertTxt, msg);
} else {
while (true);
}
}
}
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 (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB)
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
}
printStackTrace(2);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort();
#else
constexprPanic(file, line, assertMsg);
#endif
assertFailFuncRuntime(file, line, err, {}, assertMsg);
} else {
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 (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB)

View File

@ -9,9 +9,12 @@
#pragma once
#include "bit.hpp"
#include "def.hpp"
#include "cstrops.hpp"
#include "iterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::detail {
class BaseStringView {
@ -202,7 +205,7 @@ class BaseStringView {
}
[[nodiscard]]
constexpr auto operator[](std::size_t i) const noexcept {
constexpr auto &operator[](std::size_t i) const noexcept {
return m_str[i];
}
@ -215,3 +218,5 @@ class BaseStringView {
};
}
OX_CLANG_NOWARN_END

View File

@ -126,11 +126,11 @@ constexpr void Bounds::set(const Point &pt1, const Point &pt2) noexcept {
template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Bounds> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Bounds>());
oxReturnError(io->field("x", &obj->x));
oxReturnError(io->field("y", &obj->y));
oxReturnError(io->field("width", &obj->width));
oxReturnError(io->field("height", &obj->height));
OX_RETURN_ERROR(io->template setTypeInfo<Bounds>());
OX_RETURN_ERROR(io->field("x", &obj->x));
OX_RETURN_ERROR(io->field("y", &obj->y));
OX_RETURN_ERROR(io->field("width", &obj->width));
OX_RETURN_ERROR(io->field("height", &obj->height));
return {};
}

View File

@ -14,12 +14,14 @@
#include "vector.hpp"
#include "writer.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
extern template class Vector<char>;
using Buffer = Vector<char>;
using BufferView = SpanView<char>;
using BufferView = Span<const char>;
class BufferWriter {
private:
@ -51,7 +53,7 @@ class BufferWriter {
base = static_cast<ox::Signed<std::size_t>>(m_it);
break;
default:
return OxError(1, "Invalid seekdir");
return ox::Error(1, "Invalid seekdir");
}
m_it = static_cast<std::size_t>(base + off);
return {};
@ -100,15 +102,11 @@ class CharBuffWriter {
char *m_buff = nullptr;
public:
template<std::size_t sz>
explicit constexpr CharBuffWriter(ox::Array<char, sz> &buff) noexcept:
explicit constexpr CharBuffWriter(ox::Span<char> buff) noexcept:
m_cap(buff.size()),
m_buff(buff.data()) {
}
explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) {
}
constexpr ox::Error seekp(std::size_t p) noexcept {
m_it = p;
return {};
@ -127,7 +125,7 @@ class CharBuffWriter {
base = static_cast<ox::Signed<std::size_t>>(m_it);
break;
default:
return OxError(1, "Invalid seekdir");
return ox::Error(1, "Invalid seekdir");
}
m_it = static_cast<std::size_t>(base + off);
return {};
@ -140,7 +138,7 @@ class CharBuffWriter {
constexpr ox::Error put(char val) noexcept {
if (m_it >= m_cap) [[unlikely]] {
return OxError(1, "Buffer overrun");
return ox::Error(1, "Buffer overrun");
}
m_buff[m_it] = val;
++m_it;
@ -151,7 +149,7 @@ class CharBuffWriter {
constexpr ox::Error write(const char *buff, std::size_t cnt) noexcept {
const auto end = m_it + cnt;
if (end > m_cap) [[unlikely]] {
return OxError(1, "Buffer overrun");
return ox::Error(1, "Buffer overrun");
}
if (buff) {
for (auto i = 0u; i < cnt; ++i) {
@ -181,7 +179,7 @@ class BufferReader {
constexpr ox::Result<char> peek() const noexcept {
if (m_it >= m_size) [[unlikely]] {
return OxError(1, "Peek failed: buffer overrun");
return ox::Error(1, "Peek failed: buffer overrun");
}
return m_buff[m_it];
}
@ -189,7 +187,7 @@ class BufferReader {
constexpr ox::Result<std::size_t> read(void *v, std::size_t sz) noexcept {
sz = ox::min(sz, m_size - m_it);
if (m_it + sz > m_size) [[unlikely]] {
return OxError(1, "Read failed: Buffer overrun");
return ox::Error(1, "Read failed: Buffer overrun");
}
ox::memcpy(v, &m_buff[m_it], sz);
m_it += sz;
@ -198,7 +196,7 @@ class BufferReader {
constexpr ox::Error seekg(std::size_t p) noexcept {
if (p > m_size) [[unlikely]] {
return OxError(1, "Seek failed: Buffer overrun");
return ox::Error(1, "Seek failed: Buffer overrun");
}
m_it = p;
return {};
@ -217,11 +215,11 @@ class BufferReader {
base = static_cast<ox::Signed<std::size_t>>(m_it);
break;
default:
return OxError(1, "Invalid seekdir");
return ox::Error(1, "Invalid seekdir");
}
auto const newIt = static_cast<std::size_t>(base + off);
if (newIt > m_size) [[unlikely]] {
return OxError(1, "Seek failed: Buffer overrun");
return ox::Error(1, "Seek failed: Buffer overrun");
}
m_it = newIt;
return {};
@ -237,3 +235,5 @@ extern template class WriterT<BufferWriter>;
extern template class WriterT<CharBuffWriter>;
}
OX_CLANG_NOWARN_END

View File

@ -14,32 +14,20 @@
namespace ox {
constexpr Vec2::operator Point() const noexcept {
return {
static_cast<int32_t>(x),
static_cast<int32_t>(y),
};
}
constexpr Point::Point(Vec2 const&pt) noexcept:
x(static_cast<int32_t>(pt.x)),
y(static_cast<int32_t>(pt.y)) {}
constexpr Vec2::operator Size() const noexcept {
return {
static_cast<int32_t>(x),
static_cast<int32_t>(y),
};
}
constexpr Size::Size(Vec2 const&pt) noexcept:
width(static_cast<int32_t>(pt.x)),
height(static_cast<int32_t>(pt.y)) {}
constexpr Point::operator Vec2() const noexcept {
return {
static_cast<float>(x),
static_cast<float>(y),
};
}
constexpr Vec2::Vec2(Point const&pt) noexcept:
x(static_cast<float>(pt.x)),
y(static_cast<float>(pt.y)) {}
constexpr Size::operator Vec2() const noexcept {
return {
static_cast<float>(width),
static_cast<float>(height),
};
}
constexpr Vec2::Vec2(Size const&pt) noexcept:
x(static_cast<float>(pt.width)),
y(static_cast<float>(pt.height)) {}
}

View File

@ -49,5 +49,7 @@ class CStringView: public detail::BaseStringView {
};
using CStringViewCR = CStringView const&;
}

View File

@ -8,9 +8,12 @@
#pragma once
#include "def.hpp"
#include "types.hpp"
#include "typetraits.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename T1, typename T2>
@ -113,3 +116,5 @@ constexpr int lastIndexOf(const auto &str, int character, std::size_t maxLen = 0
}
}
OX_CLANG_NOWARN_END

View File

@ -37,17 +37,13 @@
// Error handling
#define oxReturnError(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] return _ox_error; } (void) 0
#define oxThrowError(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] throw ox::Exception(_ox_error); } (void) 0
#define oxConcatImpl(a, b) a##b
#define oxConcat(a, b) oxConcatImpl(a, b)
#define OX_RETURN_ERROR(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] return _ox_error; } (void) 0
#define OX_THROW_ERROR(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] throw ox::Exception(_ox_error); } (void) 0
#define OX_CONCAT_IMPL(a, b) a##b
#define OX_CONCAT(a, b) OX_CONCAT_IMPL(a, b)
// oxRequire Mutable
#define oxRequireM(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxReturnError(oxConcat(oxRequire_err_, __LINE__))
#define oxRequire(out, x) const oxRequireM(out, x)
// oxRequire Mutable Throw
#define oxRequireMT(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxThrowError(oxConcat(oxRequire_err_, __LINE__))
// oxRequire Throw
#define oxRequireT(out, x) const oxRequireMT(out, x)
#define OX_REQUIRE_M(out, x) auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__))
#define OX_REQUIRE(out, x) const OX_REQUIRE_M(out, x)
// Asserts
@ -75,6 +71,21 @@ constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
#define ox_alloca(size) __builtin_alloca(size)
#endif
#define OX_PRAGMA(x) _Pragma(#x)
#ifdef __clang__
#define OX_CLANG_NOWARN_BEGIN(warnoption) \
OX_PRAGMA(clang diagnostic push) \
OX_PRAGMA(clang diagnostic ignored #warnoption)
#define OX_CLANG_NOWARN_END OX_PRAGMA(clang diagnostic pop)
#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
#define OX_ALLOW_UNSAFE_BUFFERS_END OX_CLANG_NOWARN_END
#else
#define OX_CLANG_NOWARN_BEGIN(warnoption)
#define OX_CLANG_NOWARN_END
#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN
#define OX_ALLOW_UNSAFE_BUFFERS_END
#endif
/**
* @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation
*/

View File

@ -8,8 +8,6 @@
#pragma once
#include "error.hpp"
namespace ox {
template<typename T>
@ -18,13 +16,12 @@ class Defer {
T m_deferredFunc;
public:
Defer(T deferredFunc) {
m_deferredFunc = deferredFunc;
constexpr Defer(T deferredFunc) noexcept: m_deferredFunc(deferredFunc) {
}
Defer(const Defer&) = delete;
~Defer() {
constexpr ~Defer() {
m_deferredFunc();
}
@ -34,4 +31,4 @@ class Defer {
}
#define oxDefer ox::Defer oxConcat(oxDefer_, __LINE__) = [&]
#define OX_DEFER ox::Defer const OX_CONCAT(oxDefer_, __LINE__) =

View File

@ -17,57 +17,59 @@ class exception {
virtual ~exception() = default;
[[nodiscard]]
virtual const char *what() const noexcept {
virtual char const*what() const noexcept {
return "";
}
};
}
#endif
#include "defines.hpp"
#include "def.hpp"
#include "source_location.hpp"
#include "typetraits.hpp"
#include "utility.hpp"
#define OxError(...) ox::Error(__FILE__, __LINE__, __VA_ARGS__)
#define OxException(...) ox::Exception(__FILE__, __LINE__, __VA_ARGS__)
namespace ox {
using ErrorCode = uint16_t;
struct [[nodiscard]] Error {
const char *msg = nullptr;
const char *file = nullptr;
ox::CString msg = nullptr;
ox::CString file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0;
constexpr Error() noexcept = default;
explicit constexpr Error(ErrorCode ec) noexcept: errCode(ec) {
}
explicit constexpr Error(
ox::CString file,
uint32_t const line,
ErrorCode const errCode,
ox::CString msg = nullptr) noexcept:
msg{msg},
file{file},
line{static_cast<uint16_t>(line)},
errCode{errCode} {}
explicit constexpr Error(const char *file, uint32_t line, ErrorCode errCode, const char *msg = nullptr) noexcept {
this->file = file;
this->line = static_cast<uint16_t>(line);
this->msg = msg;
this->errCode = errCode;
}
explicit constexpr Error(
ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept:
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode}
{}
constexpr Error(const Error &o) noexcept {
this->msg = o.msg;
this->file = o.file;
this->line = o.line;
this->errCode = o.errCode;
}
constexpr Error &operator=(const Error &o) noexcept {
this->msg = o.msg;
this->file = o.file;
this->line = o.line;
this->errCode = o.errCode;
return *this;
}
explicit constexpr Error(
ErrorCode const errCode,
ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept:
msg{msg},
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode}
{}
constexpr operator uint64_t() const noexcept {
return errCode;
@ -76,51 +78,62 @@ struct [[nodiscard]] Error {
};
[[nodiscard]]
constexpr auto errCode(const Error &err) noexcept {
constexpr auto errCode(Error const&err) noexcept {
return err.errCode;
}
template<typename T=const char*>
template<typename T = char const*>
[[nodiscard]]
constexpr auto toStr(const Error &err) noexcept {
return err.msg ? T(err.msg) : "";
constexpr auto toStr(Error const&err) noexcept {
return err.msg ? T{err.msg} : "";
}
struct Exception: public std::exception {
const char *msg = nullptr;
const char *file = nullptr;
ox::CString msg = nullptr;
ox::CString file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0;
explicit inline Exception(const char *file, uint32_t line, ErrorCode errCode, const char *msg = "") noexcept {
explicit inline Exception(ox::CString file, uint32_t line, ErrorCode errCode, char const*msg = "") noexcept {
this->file = file;
this->line = static_cast<uint16_t>(line);
this->msg = msg;
this->errCode = errCode;
}
explicit inline Exception(const Error &err) {
if (err.msg) {
this->msg = err.msg;
} else {
this->msg = "";
}
this->file = err.file;
this->line = err.line;
this->errCode = err.errCode;
}
explicit inline Exception(
ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept:
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} {}
explicit inline Exception(
ErrorCode const errCode,
ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept:
msg{msg},
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} {}
explicit inline Exception(Error const&err) noexcept:
msg{err.msg ? err.msg : ""},
file{err.file},
line{err.line},
errCode{err.errCode} {}
constexpr Error toError() const noexcept {
return Error(file, line, errCode, msg);
}
[[nodiscard]]
const char *what() const noexcept override {
char const*what() const noexcept override {
return msg;
}
};
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept;
void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
template<typename T>
struct [[nodiscard]] Result {
@ -134,25 +147,25 @@ struct [[nodiscard]] Result {
}
template<typename U>
constexpr Result(const Result<U> &other) noexcept: value(other.value), error(other.error) {
constexpr Result(Result<U> const&other) noexcept: value(other.value), error(other.error) {
}
template<typename U>
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
}
constexpr Result(const Error &error) noexcept: value(), error(error) {
constexpr Result(Error const&error) noexcept: value(), error(error) {
}
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(value), error(error) {
constexpr Result(type const&value, Error const&error = {}) noexcept: value(value), error(error) {
}
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(std::move(value)), error(error) {
constexpr Result(type &&value, Error const&error = {}) noexcept: value(std::move(value)), error(error) {
}
constexpr ~Result() noexcept = default;
explicit constexpr operator const type&() const noexcept {
explicit constexpr operator type const&() const noexcept {
return value;
}
@ -165,21 +178,24 @@ struct [[nodiscard]] Result {
return error == 0;
}
constexpr Error copyTo(type &val) const& noexcept {
template<typename U>
constexpr Error copyTo(U &val) const& noexcept {
if (!error) [[likely]] {
val = value;
}
return error;
}
constexpr Error copyTo(type &val) && noexcept {
template<typename U>
constexpr Error copyTo(U &val) && noexcept {
if (!error) [[likely]] {
val = std::move(value);
}
return error;
}
constexpr Error moveTo(type &val) noexcept {
template<typename U>
constexpr Error moveTo(U &val) noexcept {
if (!error) [[likely]] {
val = std::move(value);
}
@ -318,15 +334,23 @@ struct [[nodiscard]] Result {
namespace detail {
constexpr Error toError(const Error &e) noexcept {
constexpr Error toError(Error const&e) noexcept {
return e;
}
template<typename T>
constexpr Error toError(const Result<T> &r) noexcept {
constexpr Error toError(Result<T> const&r) noexcept {
return r.error;
}
}
constexpr void primitiveAssert(char const*file, int line, bool pass, char const*msg) noexcept {
if constexpr(ox::defines::Debug) {
if (!pass) [[unlikely]] {
panic(file, line, msg, ox::Error(1));
}
}
}
}

View File

@ -25,6 +25,8 @@
#include "types.hpp"
#include "typetraits.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
namespace detail {
@ -81,16 +83,16 @@ class FmtArg {
private:
static constexpr auto DataSz = 23;
char dataStr[DataSz] = {};
ox::Array<char, DataSz> dataStr{};
template<typename T>
constexpr StringView sv(const T &v, char *dataStr) noexcept {
constexpr StringView sv(const T &v, ox::Span<char> dataStr) noexcept {
if constexpr(is_bool_v<T>) {
return v ? "true" : "false";
} else if constexpr(is_integer_v<T>) {
ox::CharBuffWriter w(dataStr, DataSz);
ox::CharBuffWriter w{dataStr};
std::ignore = ox::writeItoa(v, w);
return dataStr;
return dataStr.data();
} else {
return toStringView(v);
}
@ -225,3 +227,5 @@ constexpr Result<T> join(auto const&d, auto const&list) {
}
}
OX_CLANG_NOWARN_END

View File

@ -12,9 +12,9 @@
#define OX_ARCH_x86_64
#elif defined(__i386__) || defined(_M_IX86)
#define OX_ARCH_x86_32
#elif defined(__arm64__) || defined(__aarch64__)
#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
#define OX_ARCH_ARM64
#elif defined(__arm__)
#elif defined(__arm__) || defined(_M_ARM)
#define OX_ARCH_ARM
#endif

View File

@ -64,6 +64,9 @@ class HashMap {
[[nodiscard]]
constexpr Vector<K> const&keys() const noexcept;
[[nodiscard]]
constexpr Vector<T> values() const noexcept;
constexpr void clear();
private:
@ -151,7 +154,7 @@ template<typename K, typename T>
constexpr Result<T*> HashMap<K, T>::at(MaybeView_t<K> const&k) noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
return {nullptr, ox::Error(1, "value not found for given key")};
}
return &p->value;
}
@ -160,7 +163,7 @@ template<typename K, typename T>
constexpr Result<const T*> HashMap<K, T>::at(MaybeView_t<K> const&k) const noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
return {nullptr, ox::Error(1, "value not found for given key")};
}
return &p->value;
}
@ -198,6 +201,16 @@ constexpr Vector<K> const&HashMap<K, T>::keys() const noexcept {
return m_keys;
}
template<typename K, typename T>
constexpr Vector<T> HashMap<K, T>::values() const noexcept {
Vector<T> out;
out.reserve(m_pairs.size());
for (auto const&p : m_pairs) {
out.emplace_back(p->value);
}
return out;
}
template<typename K, typename T>
constexpr void HashMap<K, T>::clear() {
for (std::size_t i = 0; i < m_pairs.size(); i++) {

View File

@ -8,8 +8,11 @@
#include "assert.hpp"
#include "bit.hpp"
#include "def.hpp"
#include "heapmgr.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::heapmgr {
static struct HeapSegment *volatile g_heapBegin = nullptr;
@ -74,7 +77,7 @@ static HeapSegment *findSegmentFor(std::size_t sz) noexcept {
return s;
}
}
oxPanic(OxError(1), "malloc: could not find segment");
oxPanic(ox::Error(1), "malloc: could not find segment");
return nullptr;
}
@ -99,7 +102,7 @@ void free(void *ptr) noexcept {
} else if (p.segment) {
p.segment->inUse = false;
} else {
oxPanic(OxError(1), "Bad heap free");
oxPanic(ox::Error(1), "Bad heap free");
}
}
@ -142,3 +145,5 @@ void operator delete[](void *ptr, unsigned long int) noexcept {
}
#endif
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,7 @@
#include "array.hpp"
#include "concepts.hpp"
#include "def.hpp"
#include "cstrops.hpp"
#include "memops.hpp"
#include "error.hpp"
@ -35,7 +36,7 @@ class IString {
constexpr IString(const char *str) noexcept;
constexpr IString &operator=(CRStringView str) noexcept;
constexpr IString &operator=(StringViewCR str) noexcept;
constexpr IString &operator=(const char *str) noexcept;
@ -81,6 +82,11 @@ class IString {
constexpr ox::Error resize(size_t sz) noexcept;
/**
* Resizes without clearing memory between current end and new end.
*/
constexpr ox::Error unsafeResize(size_t sz) noexcept;
/**
* Returns the capacity of bytes for this string.
*/
@ -114,7 +120,7 @@ constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
}
template<std::size_t size>
constexpr IString<size> &IString<size>::operator=(ox::CRStringView str) noexcept {
constexpr IString<size> &IString<size>::operator=(ox::StringViewCR str) noexcept {
std::size_t strLen = str.len();
if (cap() < strLen) {
strLen = cap();
@ -168,9 +174,11 @@ constexpr Error IString<StrCap>::append(const char *str, std::size_t strLen) noe
auto const currentLen = len();
if (cap() < currentLen + strLen) {
strLen = cap() - currentLen;
err = OxError(1, "Insufficient space for full string");
err = ox::Error(1, "Insufficient space for full string");
}
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
ox::strncpy(m_buff.data() + currentLen, str, strLen);
OX_CLANG_NOWARN_END
// make sure last element is a null terminator
m_buff[currentLen + strLen] = 0;
m_size += strLen;
@ -211,7 +219,7 @@ constexpr std::size_t IString<StrCap>::bytes() const noexcept {
template<std::size_t StrCap>
constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
if (sz > StrCap) [[unlikely]] {
return OxError(1, "Trying to extend IString beyond its cap");
return ox::Error(1, "Trying to extend IString beyond its cap");
}
for (auto i = m_size; i < sz; ++i) {
m_buff[i] = 0;
@ -220,6 +228,15 @@ constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
return {};
}
template<std::size_t StrCap>
constexpr ox::Error IString<StrCap>::unsafeResize(size_t sz) noexcept {
if (sz > StrCap) [[unlikely]] {
return ox::Error(1, "Trying to extend IString beyond its cap");
}
m_size = sz;
return {};
}
template<size_t sz>
struct MaybeView<ox::IString<sz>> {
using type = ox::StringView;
@ -234,18 +251,22 @@ constexpr auto itoa(Integer v) noexcept {
switch (sizeof(Integer)) {
case 1:
out = 3;
break;
case 2:
out = 5;
break;
case 4:
out = 10;
break;
case 8:
out = 21;
break;
}
return out + ox::is_signed_v<Integer>;
}();
ox::IString<Cap> out;
std::ignore = out.resize(out.cap());
ox::CharBuffWriter w(out.data(), out.cap());
ox::CharBuffWriter w{{out.data(), out.cap()}};
std::ignore = writeItoa(v, w);
std::ignore = out.resize(w.tellp());
return out;

View File

@ -8,6 +8,8 @@
#pragma once
#include "def.hpp"
#include "error.hpp"
#include "math.hpp"
#if !__has_include(<iterator>)
@ -38,6 +40,8 @@ struct contiguous_iterator_tag: public random_access_iterator_tag {
#include <iterator>
#endif
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename Category, typename T, typename DiffType = std::ptrdiff_t,
@ -129,14 +133,17 @@ struct SpanIterator {
}
constexpr PtrType operator->() const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
return &m_t[m_offset];
}
constexpr RefType operator*() const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
return m_t[m_offset];
}
constexpr RefType operator[](std::size_t s) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, s < m_max, "SpanIterator access overflow");
return m_t[s];
}
@ -167,3 +174,5 @@ struct SpanIterator {
};
}
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,8 @@
#include "types.hpp"
#include "memops.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
#ifndef OX_USE_STDLIB
#define ox_inhibit_loop_to_libcall __attribute__((__optimize__("-fno-tree-loop-distribute-patterns")))
@ -96,3 +98,5 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
}
}
OX_CLANG_NOWARN_END

View File

@ -8,6 +8,7 @@
#pragma once
#include "def.hpp"
#include "types.hpp"
#include "typetraits.hpp"
@ -27,6 +28,8 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
}
#endif
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename T1, typename T2>
@ -56,3 +59,5 @@ void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {
}
}
OX_CLANG_NOWARN_END

View File

@ -42,10 +42,10 @@ constexpr U *make(Args &&...args) noexcept {
try {
return new T(ox::forward<Args>(args)...);
} catch (std::exception const&ex) {
oxPanic(OxError(1, ex.what()), ex.what());
oxPanic(ox::Error(1, ex.what()), ex.what());
return nullptr;
} catch (...) {
oxPanic(OxError(2, "Allocation or constructor failed"), "Allocation or constructor failed");
oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
return nullptr;
}
#else
@ -62,7 +62,7 @@ constexpr Result<T*> makeCatch(Args &&...args) noexcept {
} catch (const ox::Exception &ex) {
return ex.toError();
} catch (...) {
return OxError(1, "Allocation or constructor failed");
return ox::Error(1, "Allocation or constructor failed");
}
#else
return new T(ox::forward<Args>(args)...);

View File

@ -8,11 +8,7 @@
#pragma once
#include "bit.hpp"
#include "initializerlist.hpp"
#include "iterator.hpp"
#include "memory.hpp"
#include "new.hpp"
#include "types.hpp"
#include "utility.hpp"

19
deps/ox/src/ox/std/pair.hpp vendored Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace ox {
template<typename T, typename U = T>
struct Pair {
T a{};
U b{};
};
}

View File

@ -24,6 +24,8 @@ class Point {
constexpr Point(int x, int y) noexcept;
explicit constexpr Point(class Vec2 const&pt) noexcept;
constexpr Point operator+(const Point &p) const noexcept;
constexpr Point operator-(const Point &p) const noexcept;
@ -187,9 +189,9 @@ constexpr bool Point::operator!=(const Point &p) const noexcept {
template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Point> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Point>());
oxReturnError(io->field("x", &obj->x));
oxReturnError(io->field("y", &obj->y));
OX_RETURN_ERROR(io->template setTypeInfo<Point>());
OX_RETURN_ERROR(io->field("x", &obj->x));
OX_RETURN_ERROR(io->field("y", &obj->y));
return {};
}

View File

@ -9,9 +9,12 @@
#pragma once
#include "bit.hpp"
#include "def.hpp"
#include "stddef.hpp"
#include "types.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
using RandomSeed = uint64_t[2];
@ -51,3 +54,5 @@ constexpr uint64_t Random::gen() noexcept {
}
}
OX_CLANG_NOWARN_END

View File

@ -34,11 +34,11 @@ ox::Result<char> StreamReader::peek() const noexcept {
m_strm.get(c);
auto const ok = c != EOF;
if (ok && m_strm.unget()) [[unlikely]] {
return OxError(1, "Unable to unget character");
return ox::Error(1, "Unable to unget character");
}
return {static_cast<char>(c), OxError(!ok, "File peek failed")};
return {static_cast<char>(c), ox::Error(!ok, "File peek failed")};
} catch (std::exception const&) {
return OxError(1, "peek failed");
return ox::Error(1, "peek failed");
}
}
@ -50,7 +50,7 @@ ox::Error StreamReader::seekg(std::size_t p) noexcept {
try {
m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur);
} catch (std::exception const&) {
return OxError(1, "seekg failed");
return ox::Error(1, "seekg failed");
}
return {};
}
@ -59,14 +59,14 @@ ox::Error StreamReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
try {
m_strm.seekg(p, sdMap(sd));
} catch (std::exception const&) {
return OxError(1, "seekg failed");
return ox::Error(1, "seekg failed");
}
return {};
}
ox::Result<std::size_t> StreamReader::tellg() noexcept {
const auto sz = m_strm.tellg();
return {static_cast<std::size_t>(sz), OxError(sz == -1)};
return {static_cast<std::size_t>(sz), ox::Error(sz == -1)};
}
}

View File

@ -63,10 +63,10 @@ constexpr ox::Error pad(Writer_c auto &w, const T *v) noexcept {
template<typename PlatSpec>
constexpr ox::Error serialize(Writer_c auto &w, const VectorMemMap<PlatSpec> &vm) noexcept {
oxReturnError(w.write(nullptr, vm.smallVecSize));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.size)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.cap)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.items)));
OX_RETURN_ERROR(w.write(nullptr, vm.smallVecSize));
OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.size)));
OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.cap)));
OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.items)));
return {};
}
@ -83,7 +83,7 @@ template<typename T>
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
ox::Array<char, sizeof(T)> out = {};
CharBuffWriter w(out);
oxReturnError(serialize(w, in));
OX_RETURN_ERROR(serialize(w, in));
return out;
};

View File

@ -24,6 +24,8 @@ class Size {
constexpr Size(int width, int height) noexcept;
explicit constexpr Size(class Vec2 const&pt) noexcept;
constexpr Size operator+(Size p) const noexcept;
constexpr Size operator-(Size p) const noexcept;
@ -188,9 +190,9 @@ constexpr bool Size::operator!=(const Size &p) const noexcept {
template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Size> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Size>());
oxReturnError(io->field("width", &obj->width));
oxReturnError(io->field("height", &obj->height));
OX_RETURN_ERROR(io->template setTypeInfo<Size>());
OX_RETURN_ERROR(io->field("width", &obj->width));
OX_RETURN_ERROR(io->field("height", &obj->height));
return {};
}

View File

@ -140,7 +140,7 @@ template<typename K, typename T, size_t SmallSz>
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
return {nullptr, ox::Error(1, "value not found for given key")};
}
return &p->value;
}
@ -149,7 +149,7 @@ template<typename K, typename T, size_t SmallSz>
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
return {nullptr, ox::Error(1, "value not found for given key")};
}
return &p->value;
}
@ -247,8 +247,8 @@ constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::acces
template<typename T, typename K, typename V, size_t SmallSz>
constexpr Error model(T *io, ox::CommonPtrWith<SmallMap<K, V, SmallSz>> auto *obj) noexcept {
using Map = SmallMap<K, V, SmallSz>;
oxReturnError(io->template setTypeInfo<Map>());
oxReturnError(io->field("pairs", &obj->m_pairs));
OX_RETURN_ERROR(io->template setTypeInfo<Map>());
OX_RETURN_ERROR(io->field("pairs", &obj->m_pairs));
return {};
}

68
deps/ox/src/ox/std/source_location.hpp vendored Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#if __has_include(<source_location>)
#include <source_location>
#else
#include "types.hpp"
namespace std {
class source_location {
private:
struct __impl {
char const*_M_file_name{};
char const*_M_function_name{};
uint32_t _M_line{};
uint32_t _M_column{};
};
static constexpr __impl Default{
._M_file_name = "",
._M_function_name = "",
._M_line = {},
._M_column = {},
};
__impl const*m_data{&Default};
using Raw = decltype(__builtin_source_location());
public:
constexpr source_location() noexcept = default;
static consteval source_location current(Raw const pSl = __builtin_source_location()) noexcept {
source_location sl;
if (pSl) {
sl.m_data = static_cast<__impl const*>(pSl);
}
return sl;
}
constexpr uint32_t line() const noexcept {
return m_data->_M_line;
}
constexpr uint32_t column() const noexcept {
return m_data->_M_column;
}
constexpr ox::CString file_name() const noexcept {
return m_data->_M_file_name;
}
constexpr ox::CString function_name() const noexcept {
return m_data->_M_function_name;
}
};
}
#endif

View File

@ -10,135 +10,21 @@
#include "array.hpp"
#include "bit.hpp"
#include "def.hpp"
#include "iterator.hpp"
#include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
template<typename T>
class SpanView {
private:
T const*m_items{};
std::size_t m_size{};
public:
using value_type = T;
using size_type = std::size_t;
template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr SpanView() noexcept {}
template<std::size_t sz>
constexpr SpanView(ox::Array<T, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator>
constexpr SpanView(ox::Vector<T, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz>
constexpr SpanView(const T a[sz]) noexcept:
m_items(a),
m_size(sz) {
}
constexpr SpanView(const T *a, std::size_t sz) noexcept:
m_items(a),
m_size(sz) {
}
constexpr iterator<> begin() noexcept {
return iterator<>(m_items, 0, m_size);
}
constexpr iterator<> end() noexcept {
return iterator<>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> begin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> end() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cbegin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cend() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
constexpr const T &operator[](std::size_t i) const noexcept {
return m_items[i];
}
constexpr SpanView operator+(size_t i) const noexcept {
return {m_items + i, m_size - i};
}
constexpr SpanView operator+=(size_t i) noexcept {
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]]
constexpr T const*data() const noexcept {
return m_items;
}
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return m_size;
}
[[nodiscard]]
constexpr bool empty() const noexcept {
return m_size == 0;
}
};
template<typename T>
class Span {
private:
T *m_items{};
const std::size_t m_size{};
std::size_t m_size{};
public:
using value_type = T;
@ -147,20 +33,34 @@ class Span {
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr Span() noexcept = default;
template<std::size_t sz>
constexpr Span(ox::Array<T, sz> &a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz>
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<T, sz, Allocator> &v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz>
constexpr Span(T a[sz]) noexcept:
constexpr Span(T (&a)[sz]) noexcept:
m_items(a),
m_size(sz) {
}
@ -228,10 +128,28 @@ class Span {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
constexpr const T &operator[](std::size_t i) const noexcept {
constexpr T &operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i];
}
constexpr const T &operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i];
}
constexpr Span operator+(size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return {m_items + i, m_size - i};
}
constexpr Span operator+=(size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]]
constexpr auto data() const noexcept {
return m_items;
@ -249,4 +167,9 @@ class Span {
};
template<typename T>
using SpanView = Span<const T>;
}
OX_CLANG_NOWARN_END

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