Compare commits

...

513 Commits

Author SHA1 Message Date
110d4a2e6a [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2026-02-07 15:29:53 -06:00
e29a50d0dc [ox] Rename UniquePtr to UPtr 2026-02-07 14:17:55 -06:00
93d16cafb2 [ox/std] Add Error::throwException() 2026-02-07 14:15:15 -06:00
54d7c706eb [studio] Make FileInfo free resources on close
All checks were successful
Build / build (push) Successful in 1m15s
2026-02-06 21:36:39 -06:00
c9cb186462 [studio] Cleanup useless complexity
All checks were successful
Build / build (push) Successful in 1m16s
2026-02-06 21:28:46 -06:00
f204d01a3d [studio] FileInfo: reset file info when opening
All checks were successful
Build / build (push) Successful in 1m12s
2026-02-05 22:22:07 -06:00
62337bd29e [studio] FileInfo: Rename ID to Asset ID, allow for no value of fields
All checks were successful
Build / build (push) Successful in 1m12s
2026-02-05 22:15:00 -06:00
7b24b33849 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m11s
2026-02-05 21:40:10 -06:00
86c2c26d8d [studio] Fix warning
All checks were successful
Build / build (push) Successful in 1m11s
2026-02-05 21:35:39 -06:00
f8b2700ea7 [studio] Add Get Info file dialog
Some checks failed
Build / build (push) Failing after 1m9s
2026-02-05 21:32:36 -06:00
7848cbbbff [nostalgia/gfx/keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m9s
2026-02-03 02:22:58 -06:00
96c5223e44 [ox/std] Fix possible false positive in HashMap::operator==
All checks were successful
Build / build (push) Successful in 1m13s
2026-01-30 21:03:58 -06:00
d19b848427 [ox/std] Reduce AnyPtr to 2/3 the size
All checks were successful
Build / build (push) Successful in 1m13s
2026-01-30 20:54:17 -06:00
c812051ec0 [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-30 00:31:19 -06:00
3c07eb2df7 [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m7s
2026-01-29 19:30:32 -06:00
ca851e1059 [ox] Cleanup some expensive headers
All checks were successful
Build / build (push) Successful in 1m7s
2026-01-28 22:55:26 -06:00
11e75cb6ca [ox/std] Add Error::reoriginate
All checks were successful
Build / build (push) Successful in 1m13s
2026-01-28 00:46:55 -06:00
8c4add57e4 [ox/std] Fix build
All checks were successful
Build / build (push) Successful in 1m17s
2026-01-28 00:45:26 -06:00
5e1698a321 [ox/std] Cleanup serialize code
Some checks failed
Build / build (push) Failing after 52s
2026-01-27 23:15:53 -06:00
3e95bc0842 [ox/model] Update style for ModelHandlerAdaptor 2026-01-27 23:09:53 -06:00
58e19fad48 [ox] Cleanup MetalClawWriter and FieldBitmapWriter 2026-01-27 23:05:03 -06:00
a3a56b24e8 [ox/std] Fix is_integer_v 2026-01-27 23:03:07 -06:00
7681830ca6 [ox] Remove some unnecessary const_casts 2026-01-27 23:01:36 -06:00
46a7331754 [ox/mc] Cleanup, fix possible overflow bug
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-26 00:55:55 -06:00
56c19ad2a6 [ox/std] Add remove_pointer_t alias 2026-01-26 00:46:12 -06:00
c6ecadf9a8 [ox/mc] Cleanup
All checks were successful
Build / build (push) Successful in 1m10s
2026-01-26 00:21:16 -06:00
2ed469f2dd [ox] Cleanup
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-25 23:58:46 -06:00
53aea9731d [ox] Cleanup
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-25 23:46:54 -06:00
0e028ff653 [ox] Cleanup
All checks were successful
Build / build (push) Successful in 1m10s
2026-01-25 22:05:49 -06:00
07688a2c29 [ox] Remove oxExpect macro
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-25 21:52:26 -06:00
9ce4d3f8c7 [keel,nostalgia/gfx] Minor cleanup of tests 2026-01-25 21:51:10 -06:00
4aa8255c55 [ox] Update formatting in recently edited files
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-25 21:26:44 -06:00
bfdfc10425 [nostalgia/gfx] Update panic
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-25 21:11:54 -06:00
cdd574d873 [ox] Change panic and assert to use std::source_location 2026-01-25 21:11:22 -06:00
bc05bd12e5 [ox/model] Rename and fix isBString helpers
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-25 02:06:14 -06:00
b754c66cf5 [ox] Remove enable_if
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-23 01:38:53 -06:00
6a42303239 [ox/std] Slight optimization 2026-01-23 01:38:31 -06:00
7477ede222 [ox/std] Cleanup some enable_ifs
All checks were successful
Build / build (push) Successful in 1m7s
2026-01-21 23:35:19 -06:00
65e3153dda [ox/std] Add Union_c concept 2026-01-21 23:35:02 -06:00
53a224cf8f [ox/std] Cleanup 2026-01-21 23:34:36 -06:00
592e641ba9 [ox/std] Fix writeItoa to work with max length 64 bit ints
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-21 23:28:13 -06:00
689da4a019 [ox] Update docs
All checks were successful
Build / build (push) Successful in 1m10s
2026-01-21 21:04:17 -06:00
bdf7755ee2 [nostalgia/developer-handbook] Update developer handbook 2026-01-21 21:03:47 -06:00
63f627377d [ox/std] Remove excess char from intToStr return
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-20 01:29:37 -06:00
ff9002ad9a [nostalgia/developer-handbook] Update error handling section
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 01:22:05 -06:00
4d0da022cf [ox] Update error handling docs
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 00:47:51 -06:00
02332d99b5 [ox] Fix issues in String Types section of docs
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 00:26:38 -06:00
a566ed2a8b [ox/std] Fix writeItoa to work with negatives
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-19 23:00:16 -06:00
815c3d19bf [ox/std] Make StringLiteral constructors non-explicit
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-19 21:00:58 -06:00
522bb14f18 [ox/std] Fix intToStr to have room for negatives 2026-01-19 21:00:12 -06:00
f40d5515f9 [ox] Add strings section to docs
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-18 19:00:24 -06:00
941d1d90dc [ox/std] Add Vector::reserveResize
All checks were successful
Build / build (push) Successful in 1m15s
2026-01-07 21:48:04 -06:00
3e880dcdcc [nostalgia/gfx/studio] Remove unused EBO management
All checks were successful
Build / build (push) Successful in 1m16s
2026-01-07 21:33:16 -06:00
03328ac10f [turbine/glfw] Fix to handle null click handler
All checks were successful
Build / build (push) Successful in 1m9s
2025-12-03 20:44:01 -06:00
63d0abaa3c [nostalgia/gfx/gba] Remove teagba scroll bg function call
All checks were successful
Build / build (push) Successful in 1m15s
2025-11-22 23:53:18 -06:00
ef2a8cda77 [teagba] Remove bg scroll, cleanup 2025-11-22 23:53:04 -06:00
671fa54f6f [ox/std] Make ox::Vector::push_back comply with std::vector::push_back
All checks were successful
Build / build (push) Successful in 1m12s
2025-09-10 23:47:36 -05:00
517432679b [nostalgia/gfx/studio] Cleanup includes
All checks were successful
Build / build (push) Successful in 1m15s
2025-09-04 22:40:58 -05:00
b31c01f724 [keel,studio] Cleanup 2025-09-04 22:37:01 -05:00
f41213f13f [ox/std] Fix channel format for oxLogError
All checks were successful
Build / build (push) Successful in 1m8s
2025-09-04 21:11:52 -05:00
28be7c4650 [ox/fs] Fix write functions to take SpanViews 2025-09-04 21:11:52 -05:00
2f340b13b2 [ox/std] Fix Windows GCC build
All checks were successful
Build / build (push) Successful in 1m15s
2025-09-04 01:21:13 -05:00
312c818866 [nostalgia/gfx/studio] Remove unused variable
All checks were successful
Build / build (push) Successful in 1m10s
2025-08-29 22:18:37 -05:00
0d69d0c4a2 [ox/std] Remove oxDebug line
All checks were successful
Build / build (push) Successful in 1m18s
2025-08-19 21:02:13 -05:00
81a0b8c820 [ox/mc] Remove an oxDebug line
Some checks failed
Build / build (push) Failing after 22s
2025-08-19 20:59:51 -05:00
172b5aee90 [ox/oc] Remove an oxDebug line
Some checks failed
Build / build (push) Failing after 17s
2025-08-19 20:58:32 -05:00
2b5338a9df [nostalgia] Improve Makefile dependency handling
Some checks failed
Build / build (push) Failing after 9s
2025-08-17 14:10:45 -05:00
8a430faf4c [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-08-12 22:57:13 -05:00
e59382dd60 [keel] Address undefined behavior 2025-08-12 22:39:08 -05:00
3006e77ef3 [ox/std] Add and integrate std::launder
All checks were successful
Build / build (push) Successful in 1m30s
2025-08-12 22:37:21 -05:00
59c112a69c [studio] Fix navigate back not to iterate on the first item twice
All checks were successful
Build / build (push) Successful in 1m55s
2025-08-09 15:15:34 -05:00
31b39982c5 [keel] Fix AssetRef to call incRef on initial creation of ref, not just copy
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-31 22:06:52 -05:00
5476417be2 [nostalgia] Add release notes for d2025.07.0
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-31 01:05:29 -05:00
e03be694c2 Merge commit 'b67b95767b7bfcd5f618ebc8e14ddbc83edcbe36'
All checks were successful
Build / build (push) Successful in 1m37s
2025-07-31 00:41:06 -05:00
490c0368bc [nostalgia/gfx] Add lists for file extensions 2025-07-31 00:39:55 -05:00
a24fc407c5 [ox/std] Fix MSVC build 2025-07-31 00:38:26 -05:00
e38b85b4f4 [studio] Eliminate redundant serialization and deserialization
All checks were successful
Build / build (push) Successful in 1m42s
2025-07-30 21:48:44 -05:00
f7c3c02c4c Merge commit '1bfb7f99c215e2c74556bd3281f44962b8faaa96'
All checks were successful
Build / build (push) Successful in 1m35s
2025-07-30 00:42:42 -05:00
8f0f1fea39 [nostalgia/gfx/studio] Make editors use Project::loadObj for their primary assets 2025-07-30 00:37:59 -05:00
2f36a3f6f0 [studio] Add File -> Reload Project menu item 2025-07-30 00:37:23 -05:00
07e5bf9054 [keel] Make keel attempt to delete all existing assets when FS is changed 2025-07-30 00:36:56 -05:00
aacff3daf9 [ox/std] Fix UPtr::reset to conform to unique_ptr::reset 2025-07-30 00:29:34 -05:00
e27eee50f0 [teagba] Add set and scroll background offset functions
All checks were successful
Build / build (push) Successful in 1m15s
2025-07-29 00:34:41 -05:00
fd610454d6 [nostalgia/gfx] Fix compiler warning
Some checks failed
Build / build (push) Failing after 24s
2025-07-29 00:30:17 -05:00
e61d4647b5 [nostalgia/gfx] Fix BG tilesheet loading, add background offset functions
Some checks failed
Build / build (push) Failing after 20s
2025-07-28 21:54:50 -05:00
c275c5f5e6 [hull] Disable building hull for now
All checks were successful
Build / build (push) Successful in 1m22s
2025-07-26 18:33:24 -05:00
fbf49ba511 [ox/std] Add pre- and post-increment operators to Span
Some checks failed
Build / build (push) Failing after 8s
2025-07-26 18:31:55 -05:00
92f74b27d1 [ox/std] Add null check for deallocating in consteval context Vector 2025-07-26 18:31:41 -05:00
934f0c9232 [ox/std] Add beginsWith and endsWith variants that that cingle chars 2025-07-26 18:31:03 -05:00
ee9a3e1152 [ox/std] Cleanup 2025-07-26 18:30:12 -05:00
16886cdf1c [hull] Add start on command interpreter 2025-07-26 18:29:51 -05:00
08b9508d83 [ox/std] Give std::ignore a named type 2025-07-26 15:09:10 -05:00
69bd968f98 [nostalgia/player] Fix build
All checks were successful
Build / build (push) Successful in 1m28s
2025-07-25 22:54:43 -05:00
4e7dc66610 [nostalgia,olympic] Rename string len() functions to size() 2025-07-25 22:48:08 -05:00
bea0cf5a0c [ox/std] Rename string len() functions to size() 2025-07-25 22:47:56 -05:00
c7bc2a954f [nostalgia/gfx] Style update
All checks were successful
Build / build (push) Successful in 1m15s
2025-07-24 21:35:21 -05:00
7372036a0a [nostalgia/gfx] Add function missing from header
All checks were successful
Build / build (push) Successful in 1m14s
2025-07-24 21:25:26 -05:00
7461d832b6 [nostalgia/gfx/studio,studio] Fix CLI tool output to only show usage if no args given
All checks were successful
Build / build (push) Successful in 1m19s
2025-07-24 21:17:58 -05:00
6052798fea Merge commit 'dceeaaa9302b7e9ce85fa773fc187bc593f3c93c'
All checks were successful
Build / build (push) Successful in 1m16s
2025-07-24 01:58:27 -05:00
fae1e73e54 [nostalgia/gfx] Make getSubSheet check root subsheet name
All checks were successful
Build / build (push) Successful in 1m17s
2025-07-24 01:54:06 -05:00
51f2905c9c [nostalgia/gfx/studio] Make TileSheetEditor use export-tilesheet functions for export, fix exporting Root subsheet
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-24 01:45:27 -05:00
0c866d1b96 [studio,nostalgia/gfx] Add system for adding sub-commands in Modules, add export-tilesheet command
All checks were successful
Build / build (push) Successful in 1m16s
2025-07-24 01:29:09 -05:00
fdf39d1a25 [ox/std] Add Result::transformError 2025-07-24 01:24:11 -05:00
a523a75e4b [ox/std] Add missing include to StringParam 2025-07-24 01:23:58 -05:00
cdaa64ed3f [ox/clargs] Fix arg parsing for first '-' 2025-07-24 01:23:31 -05:00
801d35c823 [keel] Make type converters work with functions that take const src arg 2025-07-23 00:41:33 -05:00
37b5fcc0f7 [teagba] Put parentheses around all registers
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-07 23:36:34 -05:00
f5f2c3bee6 [studio/applib] Make Studio remove files unable to be opened from open file list in config 2025-07-07 23:35:28 -05:00
f6ef2b5acb [turbine,nostalgia] Make memory regions cast to bounded ox::Arrays
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-29 23:32:36 -05:00
bf958a4a6e [teagba] Make memory regions cast to bounded ox::Arrays 2025-06-29 23:32:11 -05:00
6a70e478a6 [nostalgia/gfx] Cleanup 2025-06-29 17:46:13 -05:00
671b8edaad [ox/std] Make StringLiteral constructors consteval
All checks were successful
Build / build (push) Successful in 1m29s
2025-06-27 23:05:42 -05:00
952637a1ea Merge commit 'cbf4414fcaf00c00a2abf73b5c04a055180ad980'
All checks were successful
Build / build (push) Successful in 1m37s
2025-06-25 21:33:16 -05:00
7569698e95 [nostalgia,studio] Add FileExts_TileSheet const, and corresponding FilePickerPopup constructor 2025-06-25 21:30:49 -05:00
21713ba945 [ox/std] Fix StringLiteral::operator= to work with DevkitARM 2025-06-25 21:29:41 -05:00
73273b6fa7 [nostalgia/gfx] Add isTileSheet function for checking paths against both file extensions 2025-06-25 21:03:45 -05:00
9f040392c7 [olympic,nostalgia] Cleanup style
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-24 01:59:22 -05:00
f4f7e5d053 Merge commit '9b5f7886cadc5c3dc826d00fa5b2e71696151dfd' 2025-06-23 20:49:01 -05:00
f847289bd4 [glutils] Cleanup
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-23 01:39:47 -05:00
94b0020d15 [nostalgia,olympic] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-23 01:30:33 -05:00
c54c0bad38 [teagba] Cleanup
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-23 01:03:33 -05:00
b9ffae0269 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-23 00:47:46 -05:00
003f3e01c6 [nostalgia] Update release notes 2025-06-22 01:01:09 -05:00
9028e74af0 [nostalgia/gfx/studio/tilesheet] Disable paste when nothing is selected 2025-06-22 01:00:56 -05:00
f5ccab5f2c [studio] Cleanup 2025-06-21 19:19:39 -05:00
c27726a4a9 Merge commit '6bbcae10cc7b21b73171ec0ff196f4baf6304404' 2025-06-21 14:29:47 -05:00
37cfa927d1 [nostalgia/gfx] Address a couple of implicit conversions
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-21 14:16:17 -05:00
0efed70b57 [studio] Fix Studio to clear editor pointers when opening a new project
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-21 14:12:45 -05:00
baf5fa3199 [nostalgia] Move d2025.05.2 release notes to d2025.06.0
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-21 08:54:57 -05:00
bd24a775b2 Merge commit '7371df429534f264c179684412f6197f7968ebfa' 2025-06-21 08:48:13 -05:00
857587c18b [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-21 08:31:27 -05:00
eb3d53c955 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-06-21 08:22:13 -05:00
14d58f3f5b [studio] Fix Navigation shortcuts for non-Mac systems
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-21 08:13:14 -05:00
5f2397903a [studio,nostalgia/gfx/studio/tilesheet] Fix copy/cut/paste enablement when there is no selection
All checks were successful
Build / build (push) Successful in 2m2s
2025-06-21 00:20:06 -05:00
58e0ecb469 [studio] Make FilePickerPopup accept on double click of a file
All checks were successful
Build / build (push) Successful in 1m22s
2025-06-20 23:58:29 -05:00
8838bf420e [studio] Fix to properly copy file that has the same name as deleted file
All checks were successful
Build / build (push) Successful in 1m24s
2025-06-20 23:36:20 -05:00
bddc544d7c [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m33s
2025-06-20 22:48:39 -05:00
a9437191bf [studio,turbine] Add support for mouse back/forward buttons
All checks were successful
Build / build (push) Successful in 1m30s
2025-06-20 22:44:09 -05:00
9d8da7ccda [ox/std] Make strToInt return error for empty string
Some checks failed
Build / build (push) Has been cancelled
2025-06-20 22:43:33 -05:00
394b568e72 [studio] Add Back/Forward navigation
All checks were successful
Build / build (push) Successful in 1m14s
2025-06-20 20:58:42 -05:00
78e9f70db6 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-19 23:58:42 -05:00
12e5623fe6 [ox/logconn] Add exception handling for logger thread
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-19 23:56:26 -05:00
cfdfb0a8c9 [studio] Fix file deletion to close file even if not active 2025-06-19 23:55:47 -05:00
56e665301f [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m29s
2025-06-19 21:37:57 -05:00
7415ce4bd9 [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 2m53s
2025-06-17 20:45:24 -05:00
05f42150a1 [olympic] Add new loc command to Makefile
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-09 21:29:27 -05:00
8ea2bc6934 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-09 00:22:17 -05:00
c780924122 [studio] Add [DEBUG] tag to About in debug builds
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-08 21:33:17 -05:00
8c538560ca [nostalgia/gfx/studio/palette] Make RGB key shortcuts work when color channel inputs are focused
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-08 17:00:52 -05:00
c3e75bdb55 [nostalgia/gfx/studio/tilesheet] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-08 16:26:55 -05:00
4419dff299 Merge commit '7688c05bac8c20bc267cae62ec78d55e5d0c493b' 2025-05-31 02:14:15 -05:00
e78c405046 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-31 01:53:59 -05:00
6b7c5d896e [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-31 01:48:07 -05:00
a33a73d73a [nostalgia/gfx/studio/palette] Add preview to color editor
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-31 01:34:00 -05:00
536999c070 Merge commit '47eee1d56d591e3631d16e95a78ea3629ee312ee' 2025-05-30 23:38:53 -05:00
e1cfcc8b5f [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m13s
2025-05-30 23:37:58 -05:00
514cb97835 [nostalgia/gfx/studio/tilesheet] Fix draw command to work on same pixel after switching subsheets 2025-05-30 23:32:51 -05:00
4b5218c4f1 [nostalgia/gfx] Cleanup 2025-05-30 23:32:27 -05:00
2ca77173d3 [keel] Add isUuidUrl function 2025-05-30 23:29:42 -05:00
cce5f52f96 [nostalgia/gfx/studio/tilesheet] Fix manual redo of draw actions, fix drawing to pixel 0, 0 as first action
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-29 22:12:10 -05:00
b55993294a [studio/modlib] Fix headerizeConfigFile to handle slashes in file name
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-25 01:20:20 -05:00
d8f847d707 [studio/applib] Move popup types into their own directory
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-24 15:01:17 -05:00
a5535ef59a Merge commit '08236fc790e711afe886b6ef545511d35e4e5c6c' 2025-05-24 01:44:07 -05:00
8419b137e5 [turbine,studio] Fix some popup window resize weirdness, cleanup some function names
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-24 01:32:14 -05:00
ed1160ec74 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-24 00:50:22 -05:00
1e21778059 [nostalgia/gfx/studio/tilesheet] Ensure config file has a Claw header 2025-05-24 00:48:54 -05:00
78379f58c8 [studio] Add ability to remember recent projects in config 2025-05-24 00:48:10 -05:00
4322f720ba [keel] Fix ox::Result<DstType> convert(Context &ctx, ox::BufferView const&src) 2025-05-24 00:47:39 -05:00
26f1a6051f [ox/std] Make Vector::remove take a MaybeView_t
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-24 00:46:39 -05:00
c4c1d4777b [keel] Cleanup ox::Error(0) instance 2025-05-23 20:25:08 -05:00
fab012d3e7 [ox] Cleanup all ox::Error(0) instances 2025-05-23 20:24:58 -05:00
a90380f377 Merge commit 'e90dd887477452922f783535edb3d4c55e9a0d2c' 2025-05-23 03:23:17 -05:00
312097a799 [ox/std] Fix implementation of std cmp functions
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-23 03:22:27 -05:00
a40198ab8d [nostalgia] Update release-d2025.05.2 release notes
All checks were successful
Build / build (push) Successful in 1m23s
2025-05-22 20:45:34 -05:00
52d8c0bdc8 [nostalgia/gfx] Replace static_cast compare with std::cmp_equal 2025-05-22 20:43:27 -05:00
c19d7f4ea3 [nostalgia] Add .vs and cmake-build-* to .gitignore 2025-05-22 20:42:09 -05:00
159b7e7ee7 [buildcore] Make pybb cmake_build specify --config debug/release 2025-05-22 20:41:30 -05:00
c93eec4f05 [teagba] Make cstart.cpp only compile if GCC 2025-05-22 20:40:33 -05:00
e7e7a22390 [nostalgia/sample_project] Make sample_project exempt from autocrlf 2025-05-22 20:39:56 -05:00
26d5048e67 [ox/fs] Fix new build error in MSVC (VS 17.14) 2025-05-22 20:05:09 -05:00
3b8f97cc41 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-21 22:15:56 -05:00
f1e68e0a04 [nostalgia/gfx/studio/tilesheet] Fix overrun errors when switching subsheets, clear selection on switch 2025-05-21 22:15:07 -05:00
d6e4ab7a24 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m24s
2025-05-18 14:08:39 -05:00
2000b2deee [nostalgia/gfx/studio] Cleanup 2025-05-17 23:35:10 -05:00
7d92400f6d [nostalgia/gfx/studio] Add type specific navigateTo functions 2025-05-17 23:26:23 -05:00
cb304ecf28 [applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-17 17:46:38 -05:00
ea17377700 [ox/std] Make StringViewCR honest
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-17 17:34:22 -05:00
c424bde06d [nostalgia] Style cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 17:31:47 -05:00
ee7d5c6d51 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 17:22:13 -05:00
99247cee32 [nostalgia/gfx/test] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-17 17:18:51 -05:00
7b8ddc189a [nostalgia/gfx] Consolidate implementations into single files, remove unnecessary function exports
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-17 17:13:13 -05:00
a6814030ee [studio/applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m13s
2025-05-17 16:15:32 -05:00
9937a01042 [turbine] Cleanup 2025-05-17 16:12:16 -05:00
abcf2adc56 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 03:02:59 -05:00
05f9023550 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 02:51:56 -05:00
5ba0bcf963 [turbine] Consolidate some files that didn't have sensible distinctions
Some checks failed
Build / build (push) Has been cancelled
2025-05-17 02:51:23 -05:00
3ccadba2f5 [nostalgia/gfx/studio/tilesheet] Fix dragging cursor on image
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-16 21:22:33 -05:00
00e52b6491 [nostalgia] Make pkg-dmg more versatile
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-15 22:26:35 -05:00
ae40487990 [nostalgia/gfx] Add navigateTo handler to TileSheetEditor
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-15 20:39:50 -05:00
84b612c693 [studio/modlib] Give navigateTo a default argument 2025-05-15 20:39:01 -05:00
3c2a6b047e [studio/applib] Make navigateTo handle UUID paths 2025-05-15 20:38:27 -05:00
626da322d9 [ox/std] Add StringParam(IString const&) constructor 2025-05-15 20:37:44 -05:00
0de428a2e5 [studio/applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-14 22:11:43 -05:00
8a52df4f76 [nostalgia/gfx] More cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-14 01:43:59 -05:00
efec6eb3c8 [nostalgia/gfx/studio/palette] Add RGB key shortcuts for focusing color channels
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-14 01:13:40 -05:00
56eeb24900 [nostalgia/gfx/opengl] More cleanup
All checks were successful
Build / build (push) Successful in 1m56s
2025-05-13 22:06:08 -05:00
ae81f6b3de [ox/std] Make Span::operator[] const
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-13 22:02:23 -05:00
c1108301c0 [nostalgia/gfx] Cleanup 2025-05-13 22:01:59 -05:00
83fbe6ac74 [keel,turbine,studio] Fix some install mistakes
All checks were successful
Build / build (push) Successful in 2m17s
2025-05-13 21:39:37 -05:00
80b452833f [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 2m28s
2025-05-13 21:24:04 -05:00
0fa394333b [nostalgia] Add release note about Mac menubar using Cmd
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 01:01:11 -05:00
cae7535034 [nostalgia] Fix typos in release notes
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 00:57:45 -05:00
df87832324 [studio] Add build date to About
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 00:21:54 -05:00
d585794cbe [nostalgia/gfx/studio/tilesheet] Fix Insert tile command 2025-05-09 20:34:42 -05:00
209658549c [nostalgia/gfx/studio/tilesheet] Cleanup 2025-05-09 20:34:04 -05:00
02383a4aed [ox/std] Cleanup 2025-05-09 01:22:29 -05:00
185a76282a [nostalgia] Make pkg-dmg delete bundle after archive created
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-08 23:29:36 -05:00
b722b4f701 [nostalgia] Update release notes
Some checks failed
Build / build (push) Has been cancelled
2025-05-08 23:28:58 -05:00
459ab5aad9 [studio] Remove ability to re-order Editor tabs 2025-05-08 23:28:51 -05:00
565f621cfc [nostalgia/gfx/studio/tilesheet] Fix Delete Tile functionality
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-08 01:57:59 -05:00
9589ca9148 [keel] Cleanup 2025-05-08 01:37:18 -05:00
164db5007b [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m25s
2025-05-08 00:49:50 -05:00
cbfb167d29 [nostalgia] Remove unused project directory
All checks were successful
Build / build (push) Successful in 1m33s
2025-05-07 20:23:48 -05:00
e7b83be867 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 2m28s
2025-05-07 20:18:08 -05:00
649da5fca8 [nostalgia/sample_project] Delete Scenes directory 2025-05-07 20:16:35 -05:00
aa095f7680 [studio] Make Delete key initiate deletion of selected directory 2025-05-07 20:15:38 -05:00
bb99c99f01 [studio] Make deleting a directory close files in that directory 2025-05-07 20:10:34 -05:00
7f0dcdd280 [nostalgia/gfx/studio/tilesheet] Cleanup
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-07 19:57:27 -05:00
6029ad5d47 [nostalgia/studio] Add command for bundling Mac app 2025-05-07 02:48:14 -05:00
26fe266b09 [ox/mc] Fix break from using strnlen_s inappropriately
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-07 01:18:14 -05:00
091eda7b44 Merge commit 'ce53be92716b0f5201882d6959c398b61c6cc93c'
All checks were successful
Build / build (push) Successful in 1m23s
2025-05-07 00:12:52 -05:00
9676ea5978 [turbine/glfw] Fix programmatic shutdown to invoke shutdownHandler
All checks were successful
Build / build (push) Successful in 1m50s
2025-05-07 00:06:21 -05:00
de8ac10653 [turbine/glfw] Fix closing when no shutdown handler is set
All checks were successful
Build / build (push) Successful in 1m53s
2025-05-07 00:01:49 -05:00
88a6cd59f3 [turbine/glfw] Treat close window event like other events with regard to a mandatory refresh period
Some checks are pending
Build / build (push) Waiting to run
2025-05-06 23:56:49 -05:00
cd43fb7f38 [turbine,studio] Fix confirm app close pop up to work with Ctrl-Q
All checks were successful
Build / build (push) Successful in 2m1s
2025-05-06 23:25:00 -05:00
136f422401 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-06 23:11:06 -05:00
e773d6f0ee [studio] Rename StudioContext to Context
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-06 22:37:21 -05:00
7da2f68d30 [nostalgia/sample_project] Add assets
All checks were successful
Build / build (push) Successful in 1m22s
2025-05-06 22:30:28 -05:00
d20889aef1 [nostalgia/gfx/studio] Update for Ox changes 2025-05-06 22:29:51 -05:00
50c8302f4a [ox] Rename itoa to intToStr 2025-05-06 22:29:31 -05:00
d8195d300d [olympic,nostalgia] Address unsafe buffer warnings 2025-05-06 22:25:36 -05:00
a8c1387d5a [ox] Address unsafe buffer warnings 2025-05-06 22:25:13 -05:00
ff1e8f260b [studio] Add popup to warn about UUID duplication 2025-05-06 22:22:26 -05:00
d4329981e7 [studio,nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-06 01:11:47 -05:00
0003454311 [studio,nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-06 01:00:04 -05:00
8c6b2234ec [olympic/util] Make pkg-gba script check return code of subprocesses
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-05 23:11:37 -05:00
aad4b8a44c [studio] Cleanup 2025-05-05 23:10:18 -05:00
7cab133127 [keel] Add ability to log UUID duplication
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-05 21:54:24 -05:00
640ac85de4 [nostalgia/gfx/studio/palette] Make page rename dialog accept on enter if input focused
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-04 00:15:30 -05:00
b8d7658626 [nostalgia/studio] Update generated icondata.cpp with Clang fix
All checks were successful
Build / build (push) Successful in 1m26s
2025-05-02 21:05:21 -05:00
2503bb3b2c [nostalgia/sample_project] Update type descriptors 2025-05-02 21:04:36 -05:00
e5dd448fe7 [turbine,studio] Make Studio confirm with user before closing app if any unsaved changes
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-01 23:15:06 -05:00
4770bb6a93 [olympic/util] Cleanup
All checks were successful
Build / build (push) Successful in 1m17s
2025-04-20 21:44:36 -05:00
c0bac696dc [nostalgia/gfx/studio/paletteeditor] Fix color number key range
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-19 14:43:07 -05:00
95f7c33419 [studio] Change Studio font
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-19 00:23:36 -05:00
535d8876d3 [keel] Cleanup 2025-04-19 00:22:28 -05:00
845e433221 [turbine] Fix Mac build 2025-04-18 01:38:32 -05:00
5169a607cf [turbine] Disable useless window icon on Mac, it causes GLFW warning
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 21:36:56 -05:00
8f03af99a7 [keel] Style updates 2025-04-17 21:36:24 -05:00
ee63a4a1e4 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m17s
2025-04-17 21:04:43 -05:00
ac29f7a0f2 Merge commit 'ec6cf92c4763be5933ee6debbf97bce25b9fcfc9' 2025-04-17 20:12:48 -05:00
89ae226b1d [keel] Improve correctness
All checks were successful
Build / build (push) Successful in 1m18s
2025-04-17 01:17:40 -05:00
477834ac04 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 01:06:08 -05:00
97b707b61c [keel] Fix MSVC build
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 01:01:22 -05:00
e86180e842 [nostalgia/core/keel] Consistency cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 00:39:34 -05:00
035ba8810f [keel,nostalgia] Fix converter type names 2025-04-17 00:37:05 -05:00
f1c2113dd3 [keel] Fix some completely incomprehensible build break in GCC12...
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 00:32:38 -05:00
56b79f414d [keel,nostalgia] Further simplify writing type converters
Some checks failed
Build / build (push) Failing after 14s
2025-04-17 00:22:47 -05:00
844656d557 [nostalgia/gfx/keel] Update type converter style
All checks were successful
Build / build (push) Successful in 1m14s
2025-04-16 23:12:24 -05:00
849aceb86d [keel] Add cleaner way to write type converters 2025-04-16 23:11:47 -05:00
eef51a6d2b [olympic] Improve error handling in file-to-cpp 2025-04-16 20:11:28 -05:00
c84b85102c [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-04-15 22:05:46 -05:00
3fe62464c3 [nostalgia/sample_project] Add NS_Logo32
All checks were successful
Build / build (push) Successful in 1m18s
2025-04-14 22:20:06 -05:00
db55fc722f [nostalgia/player] Cleanup 2025-04-14 22:05:23 -05:00
2094450898 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m22s
2025-04-14 22:00:05 -05:00
889bec04b1 [nostalgia/gfx/studio/tilesheet] Cleanup 2025-04-13 23:20:49 -05:00
ac1e34d4cd [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m19s
2025-04-13 00:37:32 -05:00
55ed75f44d [nostalgia/gfx/studio/tilesheet] Fix selection clearing to work when clicking outside image
All checks were successful
Build / build (push) Successful in 1m19s
2025-04-13 00:33:06 -05:00
2751872c59 [nostalgia] Cleanup file-to-cpp output
All checks were successful
Build / build (push) Successful in 1m15s
2025-04-12 16:50:09 -05:00
2a3cd35cc4 [nostalgia] Fix release notes version, add d2025.02.1
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 16:45:58 -05:00
b66f459f75 [nostalgia] Cleanup icon rsrc generation
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 16:40:49 -05:00
3910f4e77c [nostalgia] Fix debug and gba-run commands in Makefile
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 14:04:41 -05:00
c0e96216ae [turbine] Make accessor functions take const ref to Context
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 13:49:43 -05:00
f9512d72e8 [turbine/glfw] Fix implicit conversion
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 00:22:49 -05:00
b7f2c169ec [nostalgia/studio/gfx] Fix typo
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:14:57 -05:00
1e5057d6e6 [nostalgia] Add app icon note to release notes
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:12:36 -05:00
c6255e3224 [nostalgia/studio] Add icon 16 src
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:06:42 -05:00
02230ef619 [turbine,studio,nostalgia/studio] Add support for window icon scaling, expand icons sizes for Nostalgia Studio
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 22:45:11 -05:00
9b6b60e4d1 [turbine] Cleanup
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:47:26 -05:00
b9a26ab61e [turbine] Fix GLFWimage member init order
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:44:52 -05:00
a521887ddd [studio,turbine] Add support for window icons
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:41:30 -05:00
5ca7e2f226 [ox/fs] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-04-02 01:30:58 -05:00
125a235dd1 [ox/fs] Cleanup
All checks were successful
Build / build (push) Successful in 1m26s
2025-04-02 01:29:02 -05:00
91a7129f8f [nostalgia/gfx/keel] Cleanup 2025-04-02 01:07:26 -05:00
df48a232ec [nostalgia/studio] Add icon to Windows executable
All checks were successful
Build / build (push) Successful in 1m28s
2025-04-02 00:49:13 -05:00
ab11b885e6 [keel] Add missing new line to log message
All checks were successful
Build / build (push) Successful in 1m25s
2025-03-24 21:02:20 -05:00
36fc25fb7e [studio] Fix closing tab with unsaved changes 2025-03-24 21:02:20 -05:00
4803cca334 [nostalgia/player] Cleanup
All checks were successful
Build / build (push) Successful in 1m29s
2025-03-08 22:28:29 -06:00
6bd74611cd [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m28s
2025-02-25 20:02:52 -06:00
c3f9cf9a64 [studio] Fix New Project opening project, disable New if no project open
Some checks failed
Build / build (push) Has been cancelled
2025-02-25 20:01:33 -06:00
646ab1283f [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m26s
2025-02-24 21:45:45 -06:00
74cf055610 [nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 1m32s
2025-02-24 19:43:10 -06:00
0d8ba1b154 [nostalgia/gfx] Cleanup formatting mistake
All checks were successful
Build / build (push) Successful in 1m26s
2025-02-23 23:21:59 -06:00
20edbb7f38 [buildcore] Map aarch64 to arm64
All checks were successful
Build / build (push) Successful in 1m27s
2025-02-23 01:00:12 -06:00
6febc7cc73 [nostalgia] Fix build
All checks were successful
Build / build (push) Successful in 1m32s
2025-02-23 00:51:30 -06:00
b94d6b5061 [nostalgia] Remove scene package, finish stubbing out sound
Some checks failed
Build / build (push) Failing after 21s
2025-02-23 00:49:58 -06:00
b3952cabbc [nostalgia] Add build upload step to CI
All checks were successful
Build / build (push) Successful in 1m39s
2025-02-22 21:30:35 -06:00
2ffc11b04e Merge commit 'e723ead864edb4bc160e4d69713309174ad9e82e'
All checks were successful
Build / build (push) Successful in 1m34s
2025-02-22 20:55:17 -06:00
96cace2cbb [studio] Cleanup 2025-02-22 19:51:55 -06:00
472f5702bd [nostalgia/gfx/studio/tilesheet] Change max export scale to 135
All checks were successful
Build / build (push) Successful in 1m32s
2025-02-22 15:31:39 -06:00
c0ac4345d3 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m30s
2025-02-22 15:16:26 -06:00
fbebf4ef83 [nostalgia/gfx/studio/tilesheet] Fix export for 4bpp images
All checks were successful
Build / build (push) Successful in 1m27s
2025-02-22 00:58:12 -06:00
20513f7749 [nostalgia/sample_project] Add type descriptors 2025-02-21 00:41:04 -06:00
25a7873ea2 [nostalgia,studio] Fix crash that occurred when navigating to file that is not already open
All checks were successful
Build / build (push) Successful in 1m32s
2025-02-20 23:57:02 -06:00
d0a32e247e [ox/std] Add Vector::remove
All checks were successful
Build / build (push) Successful in 1m42s
2025-02-20 23:34:36 -06:00
03d4a5736e [nostalgia,studio] Add ability to navigate from tile sheet to palette color
All checks were successful
Build / build (push) Successful in 1m52s
2025-02-20 23:30:50 -06:00
a2e41e6527 Merge commit '4e94c925686cdda4b1ac777045dd7a17c7dc0329'
All checks were successful
Build / build (push) Successful in 1m38s
2025-02-20 20:11:03 -06:00
40a7caff90 [ox/std] Make bounds checking its own option enable-able in release builds 2025-02-20 20:05:07 -06:00
26fc5565e8 [nostalgia/gfx] Make dangling reference warning suppressions check for GCC 13
All checks were successful
Build / build (push) Successful in 1m30s
2025-02-20 19:40:08 -06:00
388541ce32 [nostalgia/player] Cleanup
All checks were successful
Build / build (push) Successful in 1m24s
2025-02-20 00:01:29 -06:00
6c194667b9 [nostalgia] Fix NostalgiaGfx lib name, stub out sound package
All checks were successful
Build / build (push) Successful in 1m27s
2025-02-19 22:19:16 -06:00
62d0579f40 [ox/fs] Restructure stat error handling to make easier to debug
All checks were successful
Build / build (push) Successful in 1m25s
2025-02-19 21:47:47 -06:00
202595b2a6 [keel] Fix loading assets by path 2025-02-19 21:47:00 -06:00
cb21ff3f04 Merge commit 'a6b9657268eb3fe139b0c22df27c2cb2efc0013c' 2025-02-19 00:34:26 -06:00
2a8e3c2dc4 [nostalgia/gfx] Remove unnecessary cast
All checks were successful
Build / build (push) Successful in 1m26s
2025-02-18 23:01:15 -06:00
998066d377 [ox/std] Add comparison functions
All checks were successful
Build / build (push) Successful in 1m24s
2025-02-18 21:46:41 -06:00
fefb876fe7 [nostalgia/gfx] Add checks for GCC version for warning suppression
All checks were successful
Build / build (push) Successful in 1m24s
2025-02-18 20:33:29 -06:00
5979e9885e [jsoncpp] Up required CMake version 2025-02-18 20:26:47 -06:00
a17abe4639 [nfde] Up required CMake version 2025-02-18 20:26:47 -06:00
d62f913855 [nostalgia/gfx] Suppress some superfluous warnings
Some checks failed
Build / build (push) Failing after 1m9s
2025-02-18 20:22:56 -06:00
12bb7475fc [nostalgia/gfx/studio/tilesheet] Adjust pixel line size on Windows
All checks were successful
Build / build (push) Successful in 1m25s
2025-02-18 20:19:51 -06:00
df2c7e2b67 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m26s
2025-02-08 18:10:49 -06:00
713aec887b [buildcore] Change mypy invokation
All checks were successful
Build / build (push) Successful in 1m28s
2025-02-07 20:38:44 -06:00
3089cd7afc Change builder type to olympic
Some checks failed
Build / build (push) Has been cancelled
2025-02-07 20:34:22 -06:00
00638bc812 [nostalgia/gfx/studio/tilesheet] Mark DrawCommands as obsolete if no changes
All checks were successful
Build / build (push) Successful in 3m37s
2025-02-05 20:26:47 -06:00
e002109829 [studio] Make undo/redo skip over obsolete commands 2025-02-05 20:26:03 -06:00
b4798fd2ab [nostalgia/gfx/studio/tilesheet] Make rotate only available for square subsheets or selections
All checks were successful
Build / build (push) Successful in 3m39s
2025-02-05 01:54:41 -06:00
3c804bf62a [studio] Give MakeCopy popup an error message for files that already exist
All checks were successful
Build / build (push) Successful in 3m36s
2025-02-03 23:30:07 -06:00
d39d552bd9 [nostalgia/studio] Update icon to higher resolution 2025-02-03 23:29:26 -06:00
b7202a2b0d [nostalgia/player] Disable Keel mods on GBA
All checks were successful
Build / build (push) Successful in 3m34s
2025-02-03 22:48:07 -06:00
4e27a4c1f5 [nostalgia/core/studio/tilesheet] Fix palette path display update
All checks were successful
Build / build (push) Successful in 3m37s
2025-02-03 22:43:20 -06:00
4ef31762d0 [nostalgia/core/studio/tilesheet] Cleanup 2025-02-03 22:43:02 -06:00
8b22a8f339 [keel] Make buildUuidMap only read the first 40 bytes of each file 2025-02-03 20:29:06 -06:00
d45ff05bcd [ox/fs] Add new partial file read functions 2025-02-03 20:28:25 -06:00
671dd86206 [keel,studio] Add Make Copy option to ProjectExplorer
All checks were successful
Build / build (push) Successful in 3m46s
2025-02-03 02:01:40 -06:00
0abadc1850 [studio] Fix QuestionPopup to only emit a response when there is a response
All checks were successful
Build / build (push) Successful in 3m36s
2025-02-03 00:35:37 -06:00
4e068d628c [studio] Fix misrender flash on tab close 2025-02-03 00:19:14 -06:00
4461f99fa4 [studio] Add Ctrl-W shortcut for closing active tab
All checks were successful
Build / build (push) Successful in 3m36s
2025-02-02 23:13:15 -06:00
cd1f4bdaa3 [studio] Add confirmation for closing file with unsaved changes 2025-02-02 23:07:59 -06:00
4728699585 [studio] Add combobox that will take string views
All checks were successful
Build / build (push) Successful in 3m47s
2025-02-02 20:46:08 -06:00
105a1e5559 [nostalgia/core/studio/tilesheet] Rework operation ctrls into a dropbox
Some checks failed
Build / build (push) Failing after 1m1s
2025-02-02 20:43:01 -06:00
1bc18e34a8 [nostalgia/core/studio/tilesheet] Add ability to rotate a selection 2025-02-02 20:22:20 -06:00
fb8d295fcb [nostalgia/core/studio/tilesheet] Add rotate functionality 2025-02-02 14:46:21 -06:00
8459d3baea Merge commit 'c42adc290cd8a27d01bb6d9877032dd2c963a4b7' 2025-02-01 22:55:46 -06:00
804d78e116 [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 3m32s
2025-02-01 15:14:24 -06:00
5351e9aa0a [nostalgia/core/studio/tilesheet] Add line drawing tool
All checks were successful
Build / build (push) Successful in 3m36s
2025-02-01 14:14:09 -06:00
b5954f15c5 [studio] Restore context menu for root dir, but exclude Delete
All checks were successful
Build / build (push) Successful in 3m33s
2025-01-29 18:47:48 -06:00
5dce9dd377 [studio] Suppress context menu for root dir in ProjectExplorer
All checks were successful
Build / build (push) Successful in 3m32s
2025-01-28 01:27:51 -06:00
0570f76236 [ox/fs] Fix PassThroughFS::stripSlash
All checks were successful
Build / build (push) Successful in 3m32s
2025-01-28 01:18:44 -06:00
e22b658a67 [studio] Fix isParentOf check in Project to ensure child dir path ends with /
Some checks failed
Build / build (push) Has been cancelled
2025-01-28 01:04:17 -06:00
56b9cb6ebf [studio] Fix file explorer to treat empty directories as directories
All checks were successful
Build / build (push) Successful in 3m32s
2025-01-27 23:31:58 -06:00
eaa9a2415e [keel] Make reloadAsset check if file is loaded 2025-01-27 21:59:57 -06:00
95256a9a0d [studio] Make rename file give error message if the file already exists
All checks were successful
Build / build (push) Successful in 3m32s
2025-01-27 00:54:58 -06:00
2286238abc [studio] Make rename file accept input upon pressing Enter if text input is focused
All checks were successful
Build / build (push) Successful in 3m36s
2025-01-27 00:33:14 -06:00
13f0bf57e4 [studio] Make deleting a file close tabs associated with it 2025-01-27 00:30:27 -06:00
8eb1ac215b [studio] Fix not to try moving a parent directory to its child
All checks were successful
Build / build (push) Successful in 3m34s
2025-01-27 00:10:25 -06:00
e132f2fd1b [studio] Make file move do nothing if the file already exists 2025-01-26 23:59:13 -06:00
12f6b22c8b [nostalgia/gfx/studio/palette] Cleanup 2025-01-26 23:35:03 -06:00
6c858e0c4e [nostalgia/gfx/studio/tilesheet] UI cleanup
All checks were successful
Build / build (push) Successful in 3m35s
2025-01-26 22:30:39 -06:00
c6b58f7c63 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 3m35s
2025-01-26 22:16:04 -06:00
a22aafaf96 [nostalgia/gfx/studio/palette] Add ability to reorder Palette pages 2025-01-26 22:12:57 -06:00
6298ac3a21 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 3m28s
2025-01-26 20:58:22 -06:00
cd63afacfe [studio] Remove Ctrl-0 tab shortcut 2025-01-26 20:53:47 -06:00
2859183742 [nostalgia/gfx/studio/tilesheet] Add the ability to move subsheets 2025-01-26 20:46:15 -06:00
8d04af691e Merge commit 'ab760b064fd6a302bad13274e0e02b2b2c957b67' 2025-01-26 15:42:50 -06:00
055165974e [nostalgia/sample_project] Update test assets 2025-01-26 15:41:40 -06:00
be51838775 [nostalgia/gfx/studio/tilesheet] Add flip x and flip y functionality
All checks were successful
Build / build (push) Successful in 3m33s
2025-01-26 15:41:13 -06:00
1207dadee8 [studio] Add ability to move directories
All checks were successful
Build / build (push) Successful in 3m29s
2025-01-26 09:38:27 -06:00
109e1898cc [studio] Add ability to drag files between directories
All checks were successful
Build / build (push) Successful in 3m29s
2025-01-26 02:03:54 -06:00
a24bf7ffb9 [studio] Fix config to update when open file name changes 2025-01-26 01:01:48 -06:00
046834c2b9 [studio,nostalgia] Update tab name when corresponding file's name changes
All checks were successful
Build / build (push) Successful in 3m30s
2025-01-26 00:52:11 -06:00
f840240aac [nostalgia/gfx/studio/tilesheeteditor] Rework system for tracking current palette path
All checks were successful
Build / build (push) Successful in 3m29s
2025-01-25 22:59:51 -06:00
cfa91d3d39 [keel,studio] Add ability to rename files 2025-01-25 22:59:01 -06:00
f7a7a66a6a [ox/event] Add Signal::connectionCnt 2025-01-25 22:58:18 -06:00
5145595d57 [ox/std] Fix HashMap collision handling 2025-01-25 22:16:42 -06:00
f01d303381 [ox/std] Fix UPtr compare with nullptr 2025-01-25 20:13:47 -06:00
098c8cb844 [nostalgia/gfx/studio] Make move color commands affect all pages
All checks were successful
Build / build (push) Successful in 3m25s
2025-01-24 23:46:26 -06:00
04ad0f0264 [studio] Add drag/drop functions that use model TypeName for name
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-24 23:26:30 -06:00
695e7a4561 [nostalgia/gfx/studio/paletteeditor] Change move color mechanism to use drag/drop
Some checks failed
Build / build (push) Failing after 54s
2025-01-24 23:19:45 -06:00
7d53028faf [studio] Cleanup 2025-01-24 00:21:28 -06:00
6c34198f58 Merge commit '897a59cdad66e593fd45eece9414d8414fa7f1ae' 2025-01-23 23:51:13 -06:00
7e3e046109 [ox/model] Fix possible infinite recursion
All checks were successful
Build / build (push) Successful in 3m26s
2025-01-23 23:48:40 -06:00
f63c58169f [studio] Add filepickerpopup.hpp to studio.hpp 2025-01-23 22:19:59 -06:00
e40b11246d [nostalgia/gfx/studio/paletteeditor] Fix num key shortcuts to ignore if ctrl is down
All checks were successful
Build / build (push) Successful in 3m25s
2025-01-23 21:56:47 -06:00
161194c8b2 [nostalgia/gfx/studio/tilesheeteditor] Add FilePicker to for choosing a Palette
All checks were successful
Build / build (push) Successful in 3m25s
2025-01-23 21:24:10 -06:00
48603ea2c5 [studio] Make tabs not draw while closing 2025-01-23 21:24:10 -06:00
e2f2a17315 [studio] Add FilePickerPopup 2025-01-23 21:24:10 -06:00
e8a0ce88c5 Merge commit 'dff9f81e073bb994d5ce96a6eaa1bfa547f1fdf4'
Some checks are pending
Build / build (push) Waiting to run
2025-01-23 21:21:58 -06:00
82e2ea747f [studio] Fix NewMenu to track prev stage correctly when going back two stages 2025-01-23 21:13:58 -06:00
ff666eda9b [studio] Make NewMenu default Name field to focus when it appears
All checks were successful
Build / build (push) Successful in 3m30s
2025-01-23 00:55:10 -06:00
0d8b82ba49 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 3m10s
2025-01-23 00:32:03 -06:00
5598dfdd87 [nostalgia/player] Update hardcoded tilesheet refs to new file ext
All checks were successful
Build / build (push) Successful in 3m16s
2025-01-23 00:19:35 -06:00
6ef462adcc [keel] Add clearer Error handling 2025-01-23 00:15:55 -06:00
9511cb5719 [studio] Fix prev tracking
All checks were successful
Build / build (push) Successful in 3m16s
2025-01-22 23:37:44 -06:00
1cc1d561e2 [studio] Add a file explorer to NewMenu to choose where new files go
All checks were successful
Build / build (push) Successful in 4m16s
2025-01-22 23:11:08 -06:00
d15a0df7da [studio] Make reusable FileTreeModel 2025-01-22 01:04:25 -06:00
e1282b6bae [studio] Fix build
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-22 00:58:43 -06:00
5fe7c14ccb [nostalgia/sample_project] Rename TileSheet files using new file ext
Some checks failed
Build / build (push) Failing after 52s
2025-01-21 23:40:19 -06:00
42165ba2d6 [nostalgia/gfx] Change default file extension for TileSheets to nts 2025-01-21 23:35:55 -06:00
1af4da43ad [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 3m22s
2025-01-21 22:56:59 -06:00
4fa879a09e [nostalgia/sample_project] Update NS_Logo.ng to final TileSheetV5 format
Some checks failed
Build / build (push) Has been cancelled
2025-01-21 22:54:27 -06:00
fd8f1a29c6 [nostalgia] Add release notes document
All checks were successful
Build / build (push) Successful in 3m24s
2025-01-21 22:45:55 -06:00
9fda2763ba [nostalgia/gfx] Make TileSheetV5::defaultPalette a string instead of FileAddress 2025-01-21 22:44:55 -06:00
cda23ac4af [ox/std] Change ox::String::operator[](size_t) const return a reference 2025-01-21 22:43:57 -06:00
c36b244dd3 [nostalgia/gfx] Cleanup, add PaletteV5, restore mistakenly removed function 2025-01-21 22:17:13 -06:00
335d278f5e [ox/oc] Fix integer read for signed/unsigned 2025-01-21 22:15:36 -06:00
f987b02c65 [nostalgia/gfx] Move to TileSheetV5
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-21 02:21:01 -06:00
3c056276c1 [turbine,nostalgia] Cleanup 2025-01-20 23:19:07 -06:00
87e2fdefcf [ox/std] Make UAnyPtr uncopyable 2025-01-20 20:42:00 -06:00
672b92b363 [nostalgia/gfx/studio] Remove accidental version tag in default Palette
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-20 03:13:01 -06:00
762a6517b2 [nostalgia] Rename core to gfx 2025-01-20 03:11:35 -06:00
d141154a45 Merge commit '38777cfac8868b3628332090260710d5ac26aba0'
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-20 02:15:45 -06:00
6170647c0c [nostalgia,studio] Proper fix for input filtering 2025-01-20 02:10:48 -06:00
48e45c7dd6 [studio] Cleanup 2025-01-20 01:34:00 -06:00
5d3d9229b7 [nostalgia/core/studio/paletteeditor] Ignore keyboard input when popup is open 2025-01-20 01:33:23 -06:00
d54e93d836 [studio] Cleanup 2025-01-20 00:16:16 -06:00
830f8fe3e4 [studio,nostalgia/core/studio] Give default Palette created studio a default page
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-19 20:53:27 -06:00
7b638538aa Merge commit '8e0b6ffbabb10f8a6e9ad7e9f07e0ba1d039a02e' 2025-01-19 20:18:56 -06:00
2016f6e605 [studio] Fix DeleteConfirmation 'No' option to not delete file
All checks were successful
Build / build (push) Successful in 3m22s
2025-01-19 20:17:35 -06:00
240effd305 Merge commit '7e20f7200963cd0b22f84cc46e10db12b6c13806' 2025-01-19 19:04:24 -06:00
6bc629e02c [nostalgia/core/studio/tilesheeteditor] Replace Palette combobox with a readonly text input
All checks were successful
Build / build (push) Successful in 3m21s
2025-01-19 19:02:44 -06:00
f6f2acd67b [nostalgia/core/studio/tilesheeteditor] Add back file type check for palette drop 2025-01-19 18:21:50 -06:00
0146d38405 [nostalgia/core/studio/tilesheeteditor] Manually merge in changes that were lost in conflict
All checks were successful
Build / build (push) Successful in 3m19s
2025-01-19 18:18:52 -06:00
75d8e7bb89 [nostalgia/core/studio/paletteeditor] Fix crash that occurs when removing last color 2025-01-19 17:56:21 -06:00
6b53eaf6b1 [ox/std] Fix string append issues
All checks were successful
Build / build (push) Successful in 3m22s
2025-01-19 16:51:05 -06:00
16c32273ac [nostalgia/core/studio/tilesheeteditor] Fix palette drop target to only take palettes 2025-01-19 16:49:31 -06:00
1567a6e29d [applib] Fix build 2025-01-19 14:32:08 -06:00
89d543bcbc Merge commit '7b7d59cf63d77cf7ab6daf6ed7122eef97954555' 2025-01-19 13:39:31 -06:00
d68e64931b [nostalgia/core/studio/tilesheeteditor] Add support for dragging palette to palette selector
All checks were successful
Build / build (push) Successful in 3m22s
2025-01-19 11:41:48 -06:00
1cbc576286 [studio] Complete drag/drop support for files 2025-01-19 11:41:08 -06:00
500b93562c [studio] Make new dir window OK on Enter key
All checks were successful
Build / build (push) Successful in 3m17s
2025-01-19 09:33:17 -06:00
800ca85176 [ox/std] Fix possible error that occurs with appending on boundary of small string size
All checks were successful
Build / build (push) Successful in 3m20s
2025-01-19 09:26:06 -06:00
cc466a9f1d [studio] Add support for adding and deleting directories 2025-01-19 09:06:16 -06:00
9d1155843e [nostalgia] Rename player from 'nostalgia' to 'Nostalgia'
All checks were successful
Build / build (push) Successful in 3m24s
2025-01-19 01:48:53 -06:00
a2139c09b2 [studio] Cleanup unused member 2025-01-19 01:44:26 -06:00
a3e5f27ab8 [ox/std] Fix Mac build 2025-01-19 01:43:38 -06:00
643f95ec80 [studio] Add confirmation dialog for file deletion, move deletion to Project
All checks were successful
Build / build (push) Successful in 3m16s
2025-01-19 01:15:33 -06:00
6924147686 [studio] Add ability to add file through dir context menu
All checks were successful
Build / build (push) Successful in 3m15s
Also, fix dir context menu to work when dir is closed, and fix it not to
override last file in the directory.
2025-01-18 23:45:04 -06:00
6e2b4fa7b4 [nostalgia] Cleanup player run in Makefile 2025-01-18 23:33:55 -06:00
4e5c749918 [studio] Add support for deleting files
All checks were successful
Build / build (push) Successful in 3m16s
2025-01-18 22:32:12 -06:00
66229de77f [ox/fs] FileSystem fixes with removing files 2025-01-18 22:31:19 -06:00
7eb37c5318 [nostalgia/core/studio/paletteeditor] Fix adding page if there is no existing page
All checks were successful
Build / build (push) Successful in 3m17s
2025-01-18 21:29:36 -06:00
7a21b20711 [nostalgia/core] Replace ContextDeleter with safeDelete(Context*)
All checks were successful
Build / build (push) Successful in 3m15s
2025-01-18 20:57:15 -06:00
894be237f2 [ox/std] Drop ox:: qualifier from safeDelete function for pointee 2025-01-18 20:56:24 -06:00
92e9d9cbfc [keel,studio] Add support for New Item templates
Some checks failed
Build / build (push) Failing after 1m3s
2025-01-18 20:16:29 -06:00
b29b9a9b3a [ox/std] Add UAnyPtr 2025-01-18 20:11:42 -06:00
721f844214 [nostalgia/core/studio/tilesheeteditor] Fix subsheet and palette scrolling 2025-01-18 20:08:09 -06:00
a3d6a58cc8 [nostalgia/core/studio] Fix library cpp file ownership
All checks were successful
Build / build (push) Successful in 3m10s
2025-01-17 21:50:42 -06:00
e598e7fe27 [nostalgia,keel] Add ability to types Obj to Obj
All checks were successful
Build / build (push) Successful in 3m10s
2025-01-15 23:44:18 -06:00
ba9e720f9f [ox/model] Fix ModelTypeName_v to use requireModelTypeName 2025-01-15 23:34:58 -06:00
8e816a261f [nostalgia/core/studio] Cleanup, fix possible TileSheet fill tool failure
All checks were successful
Build / build (push) Successful in 3m11s
2025-01-14 23:06:12 -06:00
5b9929ab3d [keel] Add detail to preload logging 2025-01-14 21:20:13 -06:00
ceb54b3f1b [nostalgia/core/opengl] Cleanup 2025-01-14 21:18:22 -06:00
8764444758 [nostalgia/core] Add clearCbb functions
All checks were successful
Build / build (push) Successful in 3m12s
2025-01-14 21:13:42 -06:00
ce9a0b1fdb [nostalgia/core/opengl] Cleanup memcpys 2025-01-14 21:13:10 -06:00
f7a468ea1e [ox/std] Add spancpy 2025-01-14 21:10:18 -06:00
861d177a27 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 3m12s
2025-01-13 22:58:39 -06:00
3936756b36 [nostalgia/developer-handbook] Update error handling to reflect the enablement of exceptions for GBA build 2025-01-13 22:53:12 -06:00
3e78ec3fe5 [studio] Cleanup 2025-01-13 22:40:08 -06:00
3c3d53b40c [studio] Ensure Editor tabs do first draw immediately, fix shift key being missed with tab shortcuts
All checks were successful
Build / build (push) Successful in 3m14s
2025-01-13 22:29:48 -06:00
151d7c5736 [nostalgia/core/gba] Fix partial tilesheet loading overrun
All checks were successful
Build / build (push) Successful in 3m11s
2025-01-13 22:03:36 -06:00
4e4d8d2c3f [nostalgia/core/gba] Make panic use standard abort call 2025-01-13 21:37:29 -06:00
03d1fd2857 [ox/std] Add and integrate standard abort call 2025-01-13 20:39:21 -06:00
6701decc91 [gbabuildcore] Enable exceptions 2025-01-13 20:18:28 -06:00
6cff526647 [teagba] Add symbols needed for enabling exceptions 2025-01-13 20:17:10 -06:00
dd50bd0249 [studio] Remap toggle explorer keyboard shortcut, add Ctrl+1-0 mappings for jumping between tabs
All checks were successful
Build / build (push) Successful in 3m17s
2025-01-13 01:14:57 -06:00
55a1660242 [nostalgia/core] Fix TileSheet validation/repair to ensure pixels gets cleared if there are subsheets
All checks were successful
Build / build (push) Successful in 3m10s
2025-01-12 16:06:24 -06:00
ed365dfef5 [studio] Fix new project menu to return an appropriately sized string for name 2025-01-12 15:04:31 -06:00
23a09e4a13 [nostalgia/core/studio] Fix SubSheet editor to return an appropriately sized string 2025-01-12 14:55:50 -06:00
b69e7ebb98 [nostalgia/core/studio/tilesheeteditor] Fix select all not to go beyond end
All checks were successful
Build / build (push) Successful in 3m10s
2025-01-11 16:21:10 -06:00
418d6e3f22 [nostalgia/core/studio] Fix crash that occurs when a non-leaf node subsheet is selected
All checks were successful
Build / build (push) Successful in 3m11s
2025-01-11 16:06:48 -06:00
c44d8678cb [nostalgia/core/studio] Fix tile insert to correct input when inserting past the last tile
All checks were successful
Build / build (push) Successful in 3m11s
2025-01-11 15:38:11 -06:00
eb4cd7106d [nostalgia/core/studio] Fix tile insert to work on last tile
All checks were successful
Build / build (push) Successful in 3m9s
2025-01-11 15:23:57 -06:00
d259770f32 Merge commit '4ea4a61d542777a270c4e2c283e0e986fc9eec9c'
All checks were successful
Build / build (push) Successful in 3m9s
2025-01-11 12:32:00 -06:00
80bad608f7 [keel] Fix reloadAsset 2025-01-11 03:39:38 -06:00
2bce9a2baf [ox/std] Add non-const SmallMap::pairs 2025-01-11 03:37:27 -06:00
791b7746f3 [nostalgia] Update liccor file
All checks were successful
Build / build (push) Successful in 3m18s
2025-01-08 23:13:14 -06:00
842e3587fd [nostalgia] Update .gitignore for new location of scripts dir 2025-01-08 23:13:02 -06:00
318e79004b [ox] Update liccor file 2025-01-08 23:12:28 -06:00
9f338a7429 [ox] Run liccor
All checks were successful
Build / build (push) Successful in 3m18s
2025-01-08 23:03:05 -06:00
645e48af7b [nostalgia,olympic] Run liccor 2025-01-08 23:02:08 -06:00
ef92c8df13 [nostalgia] Make pkg-gba.py force lower case for pack tool
All checks were successful
Build / build (push) Successful in 3m9s
2025-01-08 22:01:27 -06:00
849d50be8e [nostalgia/core] Make getTileIdx return an Optional 2025-01-08 21:34:01 -06:00
845092f114 [turbine] Make common turbine.cpp file private to its target 2025-01-08 21:33:23 -06:00
75819a1797 [ox/std] Add SmallMap::values() 2025-01-08 21:31:46 -06:00
d66da85753 [ox/std] SmallMap fixes, add findIdx function 2025-01-07 20:59:04 -06:00
98ddb08abd [nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 3m18s
2025-01-05 20:55:49 -06:00
8d1701b0bb [turbine/glfw] Ensure window opens with a standard mandatory refresh period
All checks were successful
Build / build (push) Successful in 3m19s
2025-01-04 23:49:04 -06:00
1048e522fd [imgui] Make ImGui not an object lib 2025-01-04 23:42:43 -06:00
ee59da4aa3 [glad] Make glad not an object lib 2025-01-04 23:42:43 -06:00
1ba64cb5d8 Merge commit '07610a5af2aaaac9cfcdcf8359b33f7df40d46cd'
All checks were successful
Build / build (push) Successful in 3m15s
2025-01-04 01:29:09 -06:00
462bebf6dd [nostalgia/core] Cleanup unused function declaration 2025-01-04 01:26:02 -06:00
e3f84c4e75 [studio] Make first tab not draw before selected tab when window opens 2025-01-04 01:12:48 -06:00
6837a0556d [keel] Make AssetManager take StringViewCR for assetId
All checks were successful
Build / build (push) Successful in 3m16s
2025-01-04 01:11:05 -06:00
ede2c8ca37 [keel] Make AssetTypeManager(Loader) move loader
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-04 01:05:04 -06:00
f50367f7d5 [ox/std] Add hash.hpp to install
All checks were successful
Build / build (push) Successful in 3m31s
2025-01-03 00:26:10 -06:00
e758e03d2b [nostalgia,olympic] Update for ox::Error changes
All checks were successful
Build / build (push) Successful in 3m20s
2025-01-01 23:43:32 -06:00
835e3270ce [ox] Make Error use std::source_location 2025-01-01 23:42:46 -06:00
480dd5ece4 [ox/std] Cleanup
All checks were successful
Build / build (push) Successful in 3m25s
2025-01-01 22:57:20 -06:00
dba6bb5800 [ox/std] Make Vector(initializer_list) use list size as capacity
All checks were successful
Build / build (push) Successful in 3m55s
2025-01-01 22:37:28 -06:00
40a456e54a [ox/std] Add Vector::shrink_to_fit 2025-01-01 22:32:57 -06:00
bf5be00c12 Merge commit 'dc96270ca5e882e41f6b657be14a20e8bd2ad501'
All checks were successful
Build / build (push) Successful in 3m14s
2024-12-21 20:13:20 -06:00
dc7c2559d6 [studio] Make selection tracker not go below 0 2024-12-21 20:06:48 -06:00
526 changed files with 38865 additions and 8337 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
sample_project text eol=lf

View File

@@ -4,7 +4,7 @@ on: [push]
jobs: jobs:
build: build:
runs-on: nostalgia runs-on: olympic
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -17,3 +17,10 @@ jobs:
- run: make purge configure-release - run: make purge configure-release
- run: make build - run: make build
- run: make test - run: make test
- run: make install
- run: mv dist/linux-x86_64-release nostalgia-linux-x86_64
- run: tar cf nostalgia-linux-x86_64.tar nostalgia-linux-x86_64
- uses: actions/upload-artifact@v3
with:
name: nostalgia-linux-x86_64
path: nostalgia-linux-x86_64.tar

4
.gitignore vendored
View File

@@ -6,12 +6,14 @@
.mypy_cache .mypy_cache
.stfolder .stfolder
.stignore .stignore
scripts/__pycache__ .vs
util/scripts/__pycache__
pyenv pyenv
CMakeLists.txt.user CMakeLists.txt.user
ROM.oxfs ROM.oxfs
Session.vim Session.vim
build build
cmake-build-*
compile_commands.json compile_commands.json
dist dist
graph_info.json graph_info.json

View File

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

View File

@@ -1,35 +1,68 @@
BC_VAR_PROJECT_NAME=nostalgia BC_VAR_PROJECT_NAME=nostalgia
BC_VAR_PROJECT_NAME_CAP=Nostalgia BC_VAR_PROJECT_NAME_CAP=Nostalgia
BC_VAR_DEVENV_ROOT=util
BUILDCORE_PATH=deps/buildcore BUILDCORE_PATH=deps/buildcore
include ${BUILDCORE_PATH}/base.mk include ${BUILDCORE_PATH}/base.mk
ifeq ($(BC_VAR_OS),darwin) ifeq ($(BC_VAR_OS),darwin)
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio PROJECT_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
else else
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio PROJECT_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio
MGBA=mgba-qt MGBA=mgba-qt
endif endif
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
.PHONY: pkg-gba .PHONY: pkg-gba
pkg-gba: build pkg-gba: build-pack build-gba-player
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME} ${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
.PHONY: pkg-mac
pkg-mac: install
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-dmg.py NostalgiaStudio
.PHONY: generate-studio-rsrc
generate-studio-rsrc:
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/olympic/studio/applib/src/rsrc.json
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json
.PHONY: build-gba-player
build-gba-player:
cmake --build ./build/gba-*
.PHONY: build-player
build-player:
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME_CAP}
.PHONY: build-pack
build-pack:
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME}-pack
.PHONY: run .PHONY: run
run: build run: build-player
./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project ${PROJECT_PLAYER} sample_project
.PHONY: build-studio
build-studio:
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME_CAP}Studio
.PHONY: run-studio .PHONY: run-studio
run-studio: build run-studio: build-studio
${NOSTALGIA_STUDIO} ${PROJECT_STUDIO}
.PHONY: gba-run .PHONY: gba-run
gba-run: pkg-gba gba-run: pkg-gba
${MGBA} ${BC_VAR_PROJECT_NAME}.gba ${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba
.PHONY: debug .PHONY: debug
debug: build debug: build
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project ${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project
.PHONY: debug-studio .PHONY: debug-studio
debug-studio: build debug-studio: build
${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO} ${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}
.PHONY: configure-gba .PHONY: configure-gba
configure-gba: configure-gba:
@@ -38,3 +71,25 @@ configure-gba:
.PHONY: configure-gba-debug .PHONY: configure-gba-debug
configure-gba-debug: configure-gba-debug:
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH} ${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
.PHONY: loc
loc:
${BC_PY3} util/scripts/loc.py \
--search-dirs \
src \
deps/ox/src \
deps/buildcore \
deps/gbabuildcore \
deps/glutils \
deps/teagba \
--include-exts \
.cpp \
.hpp \
.py \
.s \
.cmake \
--exclude-paths \
deps/teagba/src/gba_crt0.s \
src/olympic/studio/applib/src/font.cpp \
src/olympic/studio/applib/src/font.hpp \
src/nostalgia/studio/icondata.cpp

View File

@@ -93,7 +93,7 @@ purge:
${BC_CMD_RM_RF} compile_commands.json ${BC_CMD_RM_RF} compile_commands.json
.PHONY: test .PHONY: test
test: build test: build
${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS} ${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test ${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
.PHONY: test-verbose .PHONY: test-verbose
test-verbose: build test-verbose: build

View File

@@ -11,6 +11,7 @@
# "Python Busy Box" - adds cross-platform equivalents to Unix commands that # "Python Busy Box" - adds cross-platform equivalents to Unix commands that
# don't translate well to that other operating system # don't translate well to that other operating system
import multiprocessing
import os import os
import platform import platform
import shutil import shutil
@@ -57,7 +58,11 @@ def cmake_build(base_path: str, target: Optional[str]) -> int:
path = os.path.join(base_path, d) path = os.path.join(base_path, d)
if not os.path.isdir(path): if not os.path.isdir(path):
continue continue
args = ['cmake', '--build', path] args = ['cmake', '--build', path, f'-j{multiprocessing.cpu_count()}']
if path.endswith('release'):
args.append('--config=release')
elif path.endswith('debug'):
args.append('--config=debug')
if target is not None: if target is not None:
args.extend(['--target', target]) args.extend(['--target', target])
err = subprocess.run(args).returncode err = subprocess.run(args).returncode

View File

@@ -35,4 +35,6 @@ def get_arch() -> str:
arch = platform.machine().lower() arch = platform.machine().lower()
if arch == 'amd64': if arch == 'amd64':
arch = 'x86_64' arch = 'x86_64'
elif arch == 'aarch64':
arch = 'arm64'
return arch return arch

View File

@@ -1,8 +1,8 @@
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork")

View File

@@ -1,2 +1,11 @@
add_library(glad OBJECT src/glad.c) add_library(glad src/glad.c)
target_include_directories(glad PUBLIC include)
target_include_directories(glad PUBLIC include)
install(
TARGETS
glad
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@@ -89,7 +89,7 @@ struct GLObject: public Base {
return id; return id;
} }
constexpr operator const GLuint&() const noexcept { constexpr operator GLuint const&() const noexcept {
return id; return id;
} }
@@ -135,7 +135,7 @@ struct FrameBuffer {
return fbo.id; return fbo.id;
} }
constexpr operator const GLuint&() const noexcept { constexpr operator GLuint const&() const noexcept {
return fbo.id; return fbo.id;
} }
@@ -158,14 +158,14 @@ struct FrameBuffer {
class FrameBufferBind { class FrameBufferBind {
private: private:
static const FrameBuffer *s_activeFb; static FrameBuffer const *s_activeFb;
const FrameBuffer *m_restoreFb = nullptr; FrameBuffer const *m_restoreFb = nullptr;
public: public:
explicit FrameBufferBind(const FrameBuffer &fb) noexcept; explicit FrameBufferBind(FrameBuffer const &fb) noexcept;
~FrameBufferBind() noexcept; ~FrameBufferBind() noexcept;
}; };
void bind(const FrameBuffer &fb) noexcept; void bind(FrameBuffer const &fb) noexcept;
struct ShaderVarSet { struct ShaderVarSet {
GLsizei len{}; GLsizei len{};
@@ -176,7 +176,7 @@ struct ProgramSource {
ox::Vector<glutils::ShaderVarSet> const shaderParams; ox::Vector<glutils::ShaderVarSet> const shaderParams;
GLsizei const rowLen = [this] { GLsizei const rowLen = [this] {
GLsizei len{}; GLsizei len{};
for (auto const&v : shaderParams) { for (auto const &v : shaderParams) {
len += v.len; len += v.len;
} }
return len; return len;
@@ -187,23 +187,23 @@ struct ProgramSource {
ox::String const geomShader{}; ox::String const geomShader{};
}; };
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept; ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept;
ox::Result<GLProgram> buildShaderProgram( ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&vert, ox::CStringView const &vert,
ox::CStringView const&frag, ox::CStringView const &frag,
ox::CStringView const&geo = "") noexcept; ox::CStringView const &geo = "") noexcept;
void setupShaderParams( void setupShaderParams(
GLProgram const&shader, GLProgram const &shader,
ox::Vector<ShaderVarSet> const&vars, ox::Vector<ShaderVarSet> const &vars,
GLsizei vertexRowLen) noexcept; GLsizei vertexRowLen) noexcept;
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept; void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept;
glutils::GLVertexArray generateVertexArrayObject() noexcept; GLVertexArray generateVertexArrayObject() noexcept;
glutils::GLBuffer generateBuffer() noexcept; GLBuffer generateBuffer() noexcept;
[[nodiscard]] [[nodiscard]]
FrameBuffer generateFrameBuffer(int width, int height) noexcept; FrameBuffer generateFrameBuffer(int width, int height) noexcept;
@@ -215,20 +215,20 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
*/ */
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept; void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept; void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept;
struct BufferSet { struct BufferSet {
glutils::GLVertexArray vao; GLVertexArray vao;
glutils::GLBuffer vbo; GLBuffer vbo;
glutils::GLBuffer ebo; GLBuffer ebo;
glutils::GLTexture tex; GLTexture tex;
ox::Vector<float> vertices; ox::Vector<float> vertices;
ox::Vector<GLuint> elements; ox::Vector<GLuint> elements;
}; };
void sendVbo(BufferSet const&bs) noexcept; void sendVbo(BufferSet const &bs) noexcept;
void sendEbo(BufferSet const&bs) noexcept; void sendEbo(BufferSet const &bs) noexcept;
void clearScreen() noexcept; void clearScreen() noexcept;

View File

@@ -46,9 +46,9 @@ template struct GLObject<deleteVertexArray>;
template struct GLObject<deleteProgram>; template struct GLObject<deleteProgram>;
template struct GLObject<deleteShader>; template struct GLObject<deleteShader>;
const FrameBuffer *FrameBufferBind::s_activeFb = nullptr; FrameBuffer const *FrameBufferBind::s_activeFb = nullptr;
FrameBufferBind::FrameBufferBind(const FrameBuffer &fb) noexcept: m_restoreFb(s_activeFb) { FrameBufferBind::FrameBufferBind(FrameBuffer const &fb) noexcept: m_restoreFb(s_activeFb) {
s_activeFb = &fb; s_activeFb = &fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb); glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0, 0, fb.width, fb.height); glViewport(0, 0, fb.width, fb.height);
@@ -64,15 +64,15 @@ FrameBufferBind::~FrameBufferBind() noexcept {
} }
} }
void bind(const FrameBuffer &fb) noexcept { void bind(FrameBuffer const &fb) noexcept {
glBindFramebuffer(GL_FRAMEBUFFER, fb); glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0, 0, fb.width, fb.height); glViewport(0, 0, fb.width, fb.height);
} }
static ox::Result<GLShader> buildShader( static ox::Result<GLShader> buildShader(
GLuint shaderType, GLuint const shaderType,
const GLchar *src, GLchar const *src,
ox::StringViewCR shaderName) noexcept { ox::StringViewCR shaderName) noexcept {
GLShader shader(glCreateShader(shaderType)); GLShader shader(glCreateShader(shaderType));
glShaderSource(shader, 1, &src, nullptr); glShaderSource(shader, 1, &src, nullptr);
@@ -88,7 +88,7 @@ static ox::Result<GLShader> buildShader(
return shader; return shader;
} }
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept {
OX_REQUIRE_M(program, buildShaderProgram( OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader, src.vertShader,
src.fragShader, src.fragShader,
@@ -98,11 +98,11 @@ ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
} }
void setupShaderParams( void setupShaderParams(
GLProgram const&shader, GLProgram const &shader,
ox::Vector<ShaderVarSet> const&vars, ox::Vector<ShaderVarSet> const &vars,
GLsizei vertexRowLen) noexcept { GLsizei vertexRowLen) noexcept {
// setup vars // setup vars
for (size_t lenWritten = 0; auto const&v : vars) { for (size_t lenWritten = 0; auto const &v : vars) {
auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str())); auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str()));
glEnableVertexAttribArray(attr); glEnableVertexAttribArray(attr);
glVertexAttribPointer( glVertexAttribPointer(
@@ -113,19 +113,19 @@ void setupShaderParams(
} }
} }
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept { void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept {
// get row len // get row len
GLsizei vertexRowLen{}; GLsizei vertexRowLen{};
for (auto const&v : vars) { for (auto const &v : vars) {
vertexRowLen += v.len; vertexRowLen += v.len;
} }
setupShaderParams(shader, vars, vertexRowLen); setupShaderParams(shader, vars, vertexRowLen);
} }
ox::Result<GLProgram> buildShaderProgram( ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&vert, ox::CStringView const &vert,
ox::CStringView const&frag, ox::CStringView const &frag,
ox::CStringView const&geo) noexcept { ox::CStringView const &geo) noexcept {
GLProgram prgm(glCreateProgram()); GLProgram prgm(glCreateProgram());
OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs); glAttachShader(prgm, vs);
@@ -162,16 +162,30 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
// color texture // color texture
glGenTextures(1, &fb.color.id); glGenTextures(1, &fb.color.id);
glBindTexture(GL_TEXTURE_2D, fb.color); glBindTexture(GL_TEXTURE_2D, fb.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
nullptr);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0); glFramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
// depth texture // depth texture
glGenRenderbuffers(1, &fb.depth.id); glGenRenderbuffers(1, &fb.depth.id);
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth); glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth); glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
fb.depth);
// verify FBO // verify FBO
oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete"); oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete");
// restore primary FB // restore primary FB
@@ -189,7 +203,16 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
glBindFramebuffer(GL_FRAMEBUFFER, fb); glBindFramebuffer(GL_FRAMEBUFFER, fb);
// color texture // color texture
glBindTexture(GL_TEXTURE_2D, fb.color); glBindTexture(GL_TEXTURE_2D, fb.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// depth texture // depth texture
@@ -201,7 +224,7 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
} }
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept { void resizeInitFrameBuffer(FrameBuffer &fb, int const width, int const height) noexcept {
if (!fb) { if (!fb) {
fb = generateFrameBuffer(width, height); fb = generateFrameBuffer(width, height);
return; return;
@@ -209,18 +232,18 @@ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
resizeFrameBuffer(fb, width, height); resizeFrameBuffer(fb, width, height);
} }
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept { void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept {
resizeInitFrameBuffer(fb, sz.width, sz.height); resizeInitFrameBuffer(fb, sz.width, sz.height);
} }
void sendVbo(BufferSet const&bs) noexcept { void sendVbo(BufferSet const &bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size()); auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo); glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
} }
void sendEbo(BufferSet const&bs) noexcept { void sendEbo(BufferSet const &bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size()); auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
} }

View File

@@ -6,7 +6,7 @@ endif()
# DrinkingTea: end # DrinkingTea: end
add_library( add_library(
imgui OBJECT imgui
imgui.cpp imgui.cpp
imgui_demo.cpp imgui_demo.cpp
imgui_draw.cpp imgui_draw.cpp
@@ -19,4 +19,12 @@ add_library(
target_include_directories( target_include_directories(
imgui SYSTEM PUBLIC imgui SYSTEM PUBLIC
. .
) )
install(
TARGETS
imgui
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.19)
project(nativefiledialog-extended VERSION 1.1.1) project(nativefiledialog-extended VERSION 1.1.1)
set(nfd_ROOT_PROJECT OFF) set(nfd_ROOT_PROJECT OFF)

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

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

View File

@@ -12,7 +12,7 @@
# CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will # CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will
# continue to generate policy warnings "CMake Warning (dev)...Policy CMP0XXX is not set:" # continue to generate policy warnings "CMake Warning (dev)...Policy CMP0XXX is not set:"
# #
set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.8.0") set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.13.2")
set(JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION "3.13.2") set(JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION "3.13.2")
cmake_minimum_required(VERSION ${JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION}) cmake_minimum_required(VERSION ${JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION})
if("${CMAKE_VERSION}" VERSION_LESS "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}") if("${CMAKE_VERSION}" VERSION_LESS "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")

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

@@ -28,10 +28,7 @@ All components have a platform indicator next to them:
Ox provides ```ox::Error``` to report errors. Ox provides ```ox::Error``` to report errors.
```ox::Error``` is a struct that has overloaded operators to behave like an ```ox::Error``` is a struct that has overloaded operators to behave like an
integer error code, plus some extra fields to enhance debuggability. integer error code, plus some extra fields to enhance debuggability.
If instantiated through the ```OxError(x)``` macro, it will also include the ```ox::Error```s will also include the file and line of the error.
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>```. 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 ```ox::Result``` simply wraps the type T value in a struct that also includes
@@ -49,7 +46,7 @@ ox::Result<int> foo(int i) noexcept {
if (i < 10) { if (i < 10) {
return i + 1; // implicitly calls ox::Result<T>::Result(T) return i + 1; // implicitly calls ox::Result<T>::Result(T)
} }
return OxError(1); // implicitly calls ox::Result<T>::Result(ox::Error) return ox::Error(1); // implicitly calls ox::Result<T>::Result(ox::Error)
} }
int caller1() { int caller1() {
@@ -181,6 +178,216 @@ variant for creating a non-const value.
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable * ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
### Ox String Types
Ox has six different major string types.
These types are divided into two categories: store types and view types.
String stores maintain a copy of the string data, whereas view types only
maintain a reference to the data.
Views should be used where you otherwise might use a const reference to a
string store type.
Having all of these different string types may sound like an interoperability
nightmare, but taking string view types extensively where applicable makes the
imagined interoperability issues virtually non-existent.
#### String Store Types
##### String / BasicString
```ox::String```, or really ```ox::BasicString```, is Ox's version of
```std::string```.
Like ```std::string```, ```String``` allocates to store the string data.
Also like ```std::string```, ```String``` allows for small string
optimization for strings under 8 bytes.
Unlike ```std::string```, the template that ```String``` is based on,
```BasicString```, takes a parameter that allows adjusting to different size
small string buffers.
```ox::String``` is an alias to ```ox::BasicString<8>```.
```cpp
// s can hold up to 100 bytes, plus one for a null terminator before allocating
ox::BasicString<100> s;
```
Also unlike ```std::string```, ```ox::String``` has an explicit C-string conversion
constructor.
This prevents accidental instantiations of ```String```.
Consider the following:
```cpp
void fStd(std::string const&);
void fOx(ox::String const&);
int main() {
// implicit and silent instantiation of std::string, which includes an
// allocation
fStd("123456789");
// Will fail to compile:
fOx("123456789");
// But explicit String instantiation will work:
fOx(ox::String{"123456789"});
}
```
##### IString
```IString```, or "inline string", is like ```BasicString```, but it will cut
off strings that exceed that limit.
```cpp
ox::IString<5> s; // s can hold up to 5 characters, plus a null terminator
s = "12345"; // valid
s = "123456"; // will compile and run, but will get cut off at '5'
```
This is useful for certain string categories that have fixed lengths, like UUID
strings or for numbers.
Ox makes use of ```IString``` in the following ways:
```cpp
using UUIDStr = ox::IString<36>;
// and
template<Integer_c Integer>
[[nodiscard]]
constexpr auto intToStr(Integer v) noexcept {
constexpr auto Cap = [] {
auto out = 0;
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()}};
std::ignore = writeItoa(v, w);
std::ignore = out.resize(w.tellp());
return out;
}
```
##### StringParam
```StringParam``` is a weird type.
Because ```String::String(const char*)``` is explicit, it becomes a pain for
functions to take ```String```s.
```cpp
struct Type {
ox::String m_s;
explicit Type(ox::String p): m_s(std::move(p)) {
}
};
void f() {
ox::String s{"asdf"};
Type t1{"asdf"}; // invalid - will not compile
Type t2{s}; // invalid - will not compile
Type t3{std::move(s)}; // valid
Type t4{ox::String{"asdf"}}; // valid
}
```
```StringParam``` has implicit conversion constructors, and will appropriately
move from r-value ```String```s or create a ```String``` if not passed
ownership of an existing ```String```.
Think of ```StringParam``` as a way to opt-in to implicit instantiation with
strings.
```StringParam``` can access the string as a view through the ```view()```
function, and the ```String``` inside can be accessed by moving from the
```StringParam```.
```cpp
struct Type {
ox::String m_s;
explicit Type(ox::StringParam p): m_s(std::move(p)) {
}
};
void f() {
ox::String s{"asdf"};
Type t1{"asdf"}; // valid
Type t2{s}; // valid
Type t3{std::move(s)}; // valid
Type t4{ox::String{"asdf"}}; // valid
}
```
#### String View Types
##### StringView
```ox::StringView``` is Ox's version of ```std::string_view```.
```StringView``` contains a pointer to a string, along with its size.
This should be the normal type taken when a function needs a string that will
exist until it returns.
##### CStringView
```CStringView``` is like ```StringView```, but it comes with the promise that
the string ends with a null terminator.
Accordingly, it has a ```c_str()``` function in addition to the ```data()```
function that ```StringView``` has.
```CStringView``` should be used when wrapping a C API that only takes C
strings.
##### StringLiteral
```StringLiteral``` is a string view type, but it kind of straddles the line
between view and store types.
Creating a ```StringLiteral``` is a promise that you are passing a string
literal into the constructor.
This means you can treat it like a store, that can be safely used as a copy of
the data.
Functions that take ```StringLiteral```s are allowed to assume that the data
will have no lifetime concerns and hold onto it without any need to make a
copy.
It has a consteval constructor to enforce the promise that it is a compile time
string.
```cpp
void f(ox::StringLiteral const&);
int main() {
f("123456789"); // valid
f(ox::String{"123456789"}.c_str()); // invalid - will not compile
}
```
#### Other Variants
There are a few convenience aliases as well.
* StringCR = String const&
* StringViewCR = StringView const&
* CStringViewCR = CStringView const&
* CString = const char*
String views do not generally need const references, but it does make debugging
easier, as we can skip the constructor call if a string view already exists.
These kind of aliases probably should not exist for most types, but strings are
fundamental and ease of use is desirable.
### Logging and Output ### Logging and Output
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros. Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,21 +15,21 @@ ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<
ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept { ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
for (auto i = 0u; i < args.size(); ++i) { for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]); auto arg = StringView{args[i]};
if (arg[0] == '-') { if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) { while (arg[0] == '-' && arg.size()) {
arg = substr(arg, 1); arg = substr(arg, 1);
} }
m_bools[arg] = true; m_bools[arg] = true;
// parse additional arguments // parse additional arguments
if (i < args.size() && args[i + 1]) { if (i < args.size() && args[i + 1]) {
auto val = String(args[i + 1]); auto const val = StringView{args[i + 1]};
if (val.len() && val[i] != '-') { if (val.size() && val[0] != '-') {
if (val == "false") { if (val == "false") {
m_bools[arg] = false; m_bools[arg] = false;
} }
m_strings[arg] = val; m_strings[arg] = val;
if (auto r = ox::atoi(val.c_str()); r.error == 0) { if (auto r = ox::strToInt(val); r.error == 0) {
m_ints[arg] = r.value; m_ints[arg] = r.value;
} }
++i; ++i;
@@ -40,17 +40,17 @@ ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
} }
bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept { bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg); auto const [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue; return !err ? *value : defaultValue;
} }
String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept { String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept {
auto [value, err] = m_strings.at(arg); auto const [value, err] = m_strings.at(arg);
return !err ? ox::String(*value) : ox::String(defaultValue); return !err ? ox::String(*value) : ox::String(defaultValue);
} }
int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept { int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg); auto const [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue; return !err ? *value : defaultValue;
} }

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12,7 +12,7 @@
namespace ox { namespace ox {
ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept { Result<StringView> readClawTypeId(BufferView const buff) noexcept {
auto buffRaw = buff.data(); auto buffRaw = buff.data();
auto buffLen = buff.size(); auto buffLen = buff.size();
size_t outSz{}; size_t outSz{};
@@ -43,7 +43,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
return {{buff.data() + fmtSz, outSz - fmtSz - 1}}; return {{buff.data() + fmtSz, outSz - fmtSz - 1}};
} }
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept { Result<ClawHeader> readClawHeader(BufferView const buff) noexcept {
auto buffRaw = buff.data(); auto buffRaw = buff.data();
auto buffLen = buff.size(); auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
@@ -81,13 +81,13 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
return ox::Error(4, "Claw format does not match any supported format/version combo"); return ox::Error(4, "Claw format does not match any supported format/version combo");
} }
hdr.typeName = typeName; hdr.typeName = typeName;
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion); std::ignore = ox::strToInt(versionStr).copyTo(hdr.typeVersion);
hdr.data = buffRaw; hdr.data = buffRaw;
hdr.dataSize = buffLen; hdr.dataSize = buffLen;
return hdr; return hdr;
} }
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept { Result<BufferView> stripClawHeader(BufferView const buff) noexcept {
OX_REQUIRE(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
return {{header.data, header.dataSize}}; return {{header.data, header.dataSize}};
} }
@@ -106,15 +106,14 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
{ {
ox::BufferReader br({header.data, header.dataSize}); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); OX_RETURN_ERROR(model(reader.interface(), &obj));
OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
} }
case ClawFormat::Organic: case ClawFormat::Organic:
{ {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader({header.data, header.dataSize}); OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(reader);
OX_RETURN_ERROR(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
#else #else

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -52,8 +52,7 @@ Error readClaw(ox::BufferView buff, T &val) {
{ {
ox::BufferReader br({header.data, header.dataSize}); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); return model(reader.interface(), &val);
return model(&handler, &val);
} }
case ClawFormat::Organic: case ClawFormat::Organic:
{ {

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -109,7 +109,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader", "ClawHeaderReader",
[] { [] {
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;"); constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1}); auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
oxAssert(err, "Error parsing header"); oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
@@ -121,7 +121,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader2", "ClawHeaderReader2",
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1}); auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
oxAssert(err, "Error parsing header"); oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
@@ -134,8 +134,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3"); constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1})); OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.size() + 1}));
oxExpect(actual, expected); ox::expect(actual, expected);
return ox::Error{}; return ox::Error{};
} }
}, },

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -39,7 +39,7 @@ struct TypeInfoCatcher {
} }
constexpr Error field(...) noexcept { constexpr Error field(...) noexcept {
return ox::Error(0); return {};
} }
static constexpr auto opType() { static constexpr auto opType() {

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -122,7 +122,7 @@ class Signal {
} }
}; };
mutable Vector<UniquePtr<BaseSlot>> m_slots; mutable Vector<UPtr<BaseSlot>> m_slots;
public: public:
~Signal() noexcept; ~Signal() noexcept;
@@ -143,6 +143,11 @@ class Signal {
Error disconnectObject(const void *receiver) const noexcept; Error disconnectObject(const void *receiver) const noexcept;
[[nodiscard]]
size_t connectionCnt() const noexcept {
return m_slots.size();
}
void emit(Args... args) const; void emit(Args... args) const;
Error emitCheckError(Args... args) const noexcept; Error emitCheckError(Args... args) const noexcept;
@@ -213,9 +218,9 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
f->call(args...); f->call(args...);
} }
return ox::Error(0); return {};
} catch (const ox::Exception &ex) { } catch (const ox::Exception &ex) {
return ox::Error(ex.file, ex.line, ex.errCode, ex.msg); return ox::Error(ex.errCode, ex.msg, ex.src);
} }
} }
@@ -298,7 +303,7 @@ class Signal<Error(Args...)> {
} }
}; };
mutable Vector<UniquePtr<BaseSlot>> m_slots; mutable Vector<UPtr<BaseSlot>> m_slots;
public: public:
~Signal() noexcept; ~Signal() noexcept;
@@ -319,6 +324,11 @@ class Signal<Error(Args...)> {
Error disconnectObject(const void *receiver) const noexcept; Error disconnectObject(const void *receiver) const noexcept;
[[nodiscard]]
size_t connectionCnt() const noexcept {
return m_slots.size();
}
void emit(Args... args) const noexcept; void emit(Args... args) const noexcept;
Error emitCheckError(Args... args) const noexcept; Error emitCheckError(Args... args) const noexcept;
@@ -400,7 +410,7 @@ Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...)); OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
} }
return ox::Error(0); return {};
} }
} }

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -230,7 +230,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) { Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
++item->links; ++item->links;
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -240,7 +240,7 @@ Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
if (item->links == 0) { if (item->links == 0) {
OX_RETURN_ERROR(remove(item)); OX_RETURN_ERROR(remove(item));
} }
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -298,7 +298,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
dest->id.get(), dest.offset(), destData.size()); dest->id.get(), dest.offset(), destData.size());
fsData->rootNode = dest.offset(); fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return ox::Error(0); return {};
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
@@ -427,20 +427,20 @@ Error FileStoreTemplate<size_t>::resize() {
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
OX_RETURN_ERROR(m_buffer->setSize(newSize)); OX_RETURN_ERROR(m_buffer->setSize(newSize));
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) { if (m_buffer->size() > size) {
return ox::Error(1); return ox::Error{1, "new buffer is too small for existing data"};
} }
m_buffSize = static_cast<size_t>(size); m_buffSize = static_cast<size_t>(size);
if (newBuff) { if (newBuff) {
m_buffer = reinterpret_cast<Buffer*>(newBuff); m_buffer = static_cast<Buffer*>(newBuff);
OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size))); OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
} }
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -479,7 +479,7 @@ Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) { for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end())); OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
} }
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -503,7 +503,7 @@ Error FileStoreTemplate<size_t>::compact() {
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
if (isFirstItem) { if (isFirstItem) {
isFirstItem = false; isFirstItem = false;
return ox::Error(0); return {};
} }
if (!item.valid()) { if (!item.valid()) {
return ox::Error(1); return ox::Error(1);
@@ -524,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
parent->right = item; parent->right = item;
} }
} }
return ox::Error(0); return {};
}); });
} }
@@ -552,7 +552,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return ox::Error(0); return {};
} else { } else {
return placeItem(root, item); return placeItem(root, item);
} }
@@ -573,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = right->right; item->right = right->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return ox::Error(0); return {};
} else { } else {
return placeItem(right, item, depth + 1); return placeItem(right, item, depth + 1);
} }
@@ -586,7 +586,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = left->right; item->right = left->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return ox::Error(0); return {};
} else { } else {
return placeItem(left, item, depth + 1); return placeItem(left, item, depth + 1);
} }
@@ -624,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else { } else {
fsData->rootNode = 0; fsData->rootNode = 0;
} }
return ox::Error(0); return {};
} else { } else {
return unplaceItem(root, item); return unplaceItem(root, item);
} }
@@ -661,7 +661,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
if (item->left) { if (item->left) {
OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
} }
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -669,7 +669,7 @@ Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) { if (item.valid()) {
OX_RETURN_ERROR(unplaceItem(item)); OX_RETURN_ERROR(unplaceItem(item));
OX_RETURN_ERROR(m_buffer->free(item)); OX_RETURN_ERROR(m_buffer->free(item));
return ox::Error(0); return {};
} }
return ox::Error(1); return ox::Error(1);
} }

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -52,7 +52,7 @@ struct OX_PACKED DirectoryEntry {
if (d.valid()) { if (d.valid()) {
d->inode = inode; d->inode = inode;
auto const maxStrSz = bufferSize - 1 - sizeof(*this); auto const maxStrSz = bufferSize - 1 - sizeof(*this);
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len())); ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.size()));
return {}; return {};
} }
return ox::Error(1); return ox::Error(1);
@@ -219,7 +219,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
return ox::Error(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.size() + 1;
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize); const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize); const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size); auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31,10 +31,10 @@ FileAddress::FileAddress(uint64_t inode) noexcept {
FileAddress::FileAddress(ox::StringViewCR path) noexcept { FileAddress::FileAddress(ox::StringViewCR path) noexcept {
auto pathSize = path.bytes(); auto pathSize = path.bytes();
m_data.path = new char[pathSize + 1]; m_data.path = new char[pathSize + 1];
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
memcpy(m_data.path, path.data(), pathSize); memcpy(m_data.path, path.data(), pathSize);
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
m_data.path[pathSize] = 0; m_data.path[pathSize] = 0;
OX_CLANG_NOWARN_END OX_ALLOW_UNSAFE_BUFFERS_END
m_type = FileAddressType::Path; m_type = FileAddressType::Path;
} }
@@ -48,9 +48,11 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
case FileAddressType::Path: case FileAddressType::Path:
{ {
if (other.m_data.path) { if (other.m_data.path) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
auto strSize = ox::strlen(other.m_data.path) + 1; auto strSize = ox::strlen(other.m_data.path) + 1;
m_data.path = new char[strSize]; m_data.path = new char[strSize];
ox::memcpy(m_data.path, other.m_data.path, strSize); ox::memcpy(m_data.path, other.m_data.path, strSize);
OX_ALLOW_UNSAFE_BUFFERS_END
} else { } else {
m_data.constPath = ""; m_data.constPath = "";
m_type = FileAddressType::ConstPath; m_type = FileAddressType::ConstPath;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -24,9 +24,6 @@ enum class FileAddressType: int8_t {
Inode, Inode,
}; };
template<typename T>
constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept;
class FileAddress { class FileAddress {
template<typename T> template<typename T>

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -37,6 +37,30 @@ Error FileSystem::read(const FileAddress &addr, void *buffer, std::size_t size)
} }
} }
Result<Buffer> FileSystem::read(FileAddress const &addr, size_t const size) noexcept {
Result<Buffer> out;
out.value.resize(size);
switch (addr.type()) {
case FileAddressType::Inode:
OX_RETURN_ERROR(readFileInode(addr.getInode().value, out.value.data(), size));
break;
case FileAddressType::ConstPath:
case FileAddressType::Path:
OX_RETURN_ERROR(readFilePath(StringView{addr.getPath().value}, out.value.data(), size));
break;
default:
return ox::Error{1};
}
return out;
}
Result<Buffer> FileSystem::read(StringViewCR path, size_t const size) noexcept {
Result<Buffer> out;
out.value.resize(size);
OX_RETURN_ERROR(readFilePath(path, out.value.data(), size));
return out;
}
Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept { Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept {
OX_REQUIRE(s, stat(addr)); OX_REQUIRE(s, stat(addr));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
@@ -51,28 +75,31 @@ Result<Buffer> FileSystem::read(StringViewCR path) noexcept {
return buff; return buff;
} }
Error FileSystem::read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept { Error FileSystem::read(
FileAddress const &addr,
std::size_t const readStart,
std::size_t const readSize,
void *buffer,
std::size_t *size) noexcept {
switch (addr.type()) { switch (addr.type()) {
case FileAddressType::Inode: case FileAddressType::Inode:
return read(addr.getInode().value, readStart, readSize, buffer, size); return readFileInodeRange(addr.getInode().value, readStart, readSize, buffer, size);
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
case FileAddressType::Path: case FileAddressType::Path:
return ox::Error(2, "Unsupported for path lookups"); return readFilePathRange(addr.getPath().value, readStart, readSize, buffer, size);
default: default:
return ox::Error(1); return ox::Error(1);
} }
} }
Error FileSystem::remove(const FileAddress &addr, bool recursive) noexcept { Result<size_t> FileSystem::read(
switch (addr.type()) { StringViewCR path,
case FileAddressType::Inode: std::size_t const readStart,
return remove(addr.getInode().value, recursive); std::size_t const readSize,
case FileAddressType::ConstPath: Span<char> buff) noexcept {
case FileAddressType::Path: size_t szOut{buff.size()};
return remove(StringView(addr.getPath().value), recursive); OX_RETURN_ERROR(readFilePathRange(path, readStart, readSize, buff.data(), &szOut));
default: return szOut;
return ox::Error(1);
}
} }
Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType) noexcept { Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType) noexcept {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20,7 +20,7 @@
namespace ox { namespace ox {
namespace detail { namespace detail {
static inline void fsBuffFree(char *buff) noexcept { inline void fsBuffFree(char *buff) noexcept {
safeDelete(buff); safeDelete(buff);
} }
} }
@@ -41,25 +41,45 @@ class FileSystem {
Error read(const FileAddress &addr, void *buffer, std::size_t size) noexcept; Error read(const FileAddress &addr, void *buffer, std::size_t size) noexcept;
Result<Buffer> read(FileAddress const &addr, size_t size) noexcept;
Result<Buffer> read(StringViewCR path, size_t size) noexcept;
Result<Buffer> read(const FileAddress &addr) noexcept; Result<Buffer> read(const FileAddress &addr) noexcept;
Result<Buffer> read(StringViewCR path) noexcept; Result<Buffer> read(StringViewCR path) noexcept;
inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
return readFilePath(path, buffer, buffSize); return readFilePath(path, buffer, buffSize);
} }
inline Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
return readFileInode(inode, buffer, buffSize); return readFileInode(inode, buffer, buffSize);
} }
Error read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept; Error read(
FileAddress const &addr,
size_t readStart,
size_t readSize,
void *buffer,
size_t *size) noexcept;
/**
*
* @param path
* @param readStart
* @param readSize
* @param buff
* @return error or number of bytes read
*/
Result<size_t> read(
StringViewCR path, size_t readStart, size_t readSize, ox::Span<char> buff) noexcept;
virtual Result<Vector<String>> ls(StringViewCR dir) const noexcept = 0; virtual Result<Vector<String>> ls(StringViewCR dir) const noexcept = 0;
virtual Error remove(StringViewCR path, bool recursive) noexcept = 0; Error remove(StringViewCR path, bool recursive = false) noexcept {
return removePath(path, recursive);
Error remove(const FileAddress &addr, bool recursive = false) noexcept; }
virtual Error resize(uint64_t size, void *buffer) noexcept = 0; virtual Error resize(uint64_t size, void *buffer) noexcept = 0;
@@ -67,7 +87,7 @@ class FileSystem {
return writeFilePath(path, buffer, size, FileType::NormalFile); return writeFilePath(path, buffer, size, FileType::NormalFile);
} }
Error write(StringViewCR path, ox::Span<char> const&buff) noexcept { Error write(StringViewCR path, ox::SpanView<char> const&buff) noexcept {
return write(path, buff.data(), buff.size(), FileType::NormalFile); return write(path, buff.data(), buff.size(), FileType::NormalFile);
} }
@@ -75,42 +95,42 @@ class FileSystem {
return write(inode, buffer, size, FileType::NormalFile); return write(inode, buffer, size, FileType::NormalFile);
} }
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept { Error write(uint64_t inode, ox::SpanView<char> const&buff) noexcept {
return write(inode, buff.data(), buff.size(), FileType::NormalFile); return write(inode, buff.data(), buff.size(), FileType::NormalFile);
} }
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept { Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
return writeFilePath(path, buffer, size, fileType); return writeFilePath(path, buffer, size, fileType);
} }
inline Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
return writeFileInode(inode, buffer, size, fileType); return writeFileInode(inode, buffer, size, fileType);
} }
inline Result<FileStat> stat(uint64_t inode) const noexcept { Result<FileStat> stat(uint64_t inode) const noexcept {
return statInode(inode); return statInode(inode);
} }
inline Result<FileStat> stat(StringViewCR path) const noexcept { Result<FileStat> stat(StringViewCR path) const noexcept {
return statPath(path); return statPath(path);
} }
Result<FileStat> stat(const FileAddress &addr) const noexcept; Result<FileStat> stat(const FileAddress &addr) const noexcept;
[[nodiscard]] [[nodiscard]]
inline bool exists(uint64_t inode) const noexcept { bool exists(uint64_t inode) const noexcept {
return statInode(inode).ok(); return statInode(inode).ok();
} }
[[nodiscard]] [[nodiscard]]
inline bool exists(ox::StringView path) const noexcept { bool exists(ox::StringView path) const noexcept {
return statPath(path).ok(); return statPath(path).ok();
} }
[[nodiscard]] [[nodiscard]]
inline bool exists(FileAddress const&addr) const noexcept { bool exists(FileAddress const&addr) const noexcept {
return stat(addr).ok(); return stat(addr).ok();
} }
@@ -140,7 +160,12 @@ class FileSystem {
virtual Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept = 0; virtual Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept = 0;
virtual Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept = 0; virtual Error readFilePathRange(
StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept = 0;
virtual Error readFileInodeRange(uint64_t inode, size_t readStart, size_t readSize, void *buffer, size_t *size) noexcept = 0;
virtual Error removePath(StringViewCR path, bool recursive) noexcept = 0;
virtual Error writeFilePath(StringViewCR 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;
@@ -152,11 +177,11 @@ class MemFS: public FileSystem {
public: public:
Result<const char*> directAccess(const FileAddress &addr) const noexcept; Result<const char*> directAccess(const FileAddress &addr) const noexcept;
inline Result<const char*> directAccess(StringViewCR path) const noexcept { Result<const char*> directAccess(StringViewCR path) const noexcept {
return directAccessPath(path); return directAccessPath(path);
} }
inline Result<const char*> directAccess(uint64_t inode) const noexcept { Result<const char*> directAccess(uint64_t inode) const noexcept {
return directAccessInode(inode); return directAccessInode(inode);
} }
@@ -209,6 +234,11 @@ class FileSystemTemplate: public MemFS {
Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override; Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override;
Error readFilePathRange(
StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept override;
Error removePath(StringViewCR path, bool recursive) noexcept override;
Result<const char*> directAccessInode(uint64_t) const noexcept override; Result<const char*> directAccessInode(uint64_t) const noexcept override;
Result<Vector<String>> ls(StringViewCR dir) const noexcept override; Result<Vector<String>> ls(StringViewCR dir) const noexcept override;
@@ -216,8 +246,6 @@ class FileSystemTemplate: public MemFS {
template<typename F> template<typename F>
Error ls(StringViewCR path, F cb) const; Error ls(StringViewCR path, F cb) const;
Error remove(StringViewCR path, bool recursive) noexcept override;
/** /**
* Resizes FileSystem to minimum possible size. * Resizes FileSystem to minimum possible size.
*/ */
@@ -301,7 +329,7 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
return ox::Error(1); return ox::Error(1);
} }
return ox::Error(0); return {};
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
@@ -318,7 +346,7 @@ Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringVie
OX_REQUIRE_M(inode, rootDir.find(src)); OX_REQUIRE_M(inode, rootDir.find(src));
OX_RETURN_ERROR(rootDir.write(dest, inode)); OX_RETURN_ERROR(rootDir.write(dest, inode));
OX_RETURN_ERROR(rootDir.remove(src)); OX_RETURN_ERROR(rootDir.remove(src));
return ox::Error(0); return {};
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
@@ -357,35 +385,14 @@ Error FileSystemTemplate<FileStore, Directory>::readFileInodeRange(uint64_t inod
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept { Error FileSystemTemplate<FileStore, Directory>::readFilePathRange(
auto data = m_fs.read(inode); StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept {
if (!data.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(StringViewCR path) const noexcept {
Vector<String> out;
OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name);
return ox::Error(0);
}));
return out;
}
template<typename FileStore, typename Directory>
template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const {
oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
OX_REQUIRE(s, stat(path)); OX_REQUIRE(s, stat(path));
Directory dir(m_fs, s.inode); return readFileInodeRange(s.inode, readStart, readSize, buffer, buffSize);
return dir.ls(cb);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::removePath(StringViewCR path, bool recursive) noexcept {
OX_REQUIRE(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
OX_REQUIRE(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
@@ -400,7 +407,35 @@ Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool r
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
return ox::Error(1); return ox::Error(1);
} }
return ox::Error(0); return {};
}
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 ox::Error(1, "Data not valid");
}
return reinterpret_cast<char*>(data.get());
}
template<typename FileStore, typename Directory>
Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept {
Vector<String> out;
OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name);
return ox::Error{};
}));
return out;
}
template<typename FileStore, typename Directory>
template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const {
oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
OX_REQUIRE(s, stat(path));
Directory dir(m_fs, s.inode);
return dir.ls(cb);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
@@ -433,7 +468,7 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { 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)); oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::intToStr(inode));
return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType)); return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType));
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -60,7 +60,7 @@ Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
if (ec.value()) { if (ec.value()) {
return ox::Error(1); return ox::Error(1);
} }
return ox::Error(0); return {};
} }
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
@@ -75,14 +75,6 @@ Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
return out; return out;
} }
Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept {
if (recursive) {
return ox::Error(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
} else {
return ox::Error(std::filesystem::remove(m_path / stripSlash(path)) != 0);
}
}
Error PassThroughFS::resize(uint64_t, void*) noexcept { Error PassThroughFS::resize(uint64_t, void*) noexcept {
// unsupported // unsupported
return ox::Error(1, "resize is not supported by PassThroughFS"); return ox::Error(1, "resize is not supported by PassThroughFS");
@@ -101,7 +93,9 @@ Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path); oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec); const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size); oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed")); if (auto err = ec.value()) {
return ox::Error{static_cast<ox::ErrorCode>(err), "PassThroughFS: stat failed"};
}
return FileStat{0, 0, size, type}; return FileStat{0, 0, size, type};
} }
@@ -154,7 +148,7 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return ox::Error(2); return ox::Error(2);
} }
return ox::Error(0); return {};
} }
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
@@ -162,11 +156,38 @@ Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
return ox::Error(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::readFilePathRange(
StringViewCR path, size_t const readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept {
try {
std::ifstream file(m_path / stripSlash(path), std::ios::binary | std::ios::ate);
auto const size = static_cast<size_t>(file.tellg());
readSize = ox::min(readSize, size);
file.seekg(static_cast<off_t>(readStart), std::ios::beg);
if (readSize > *buffSize) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
return ox::Error{1};
}
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(readSize));
return {};
} catch (std::fstream::failure const &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return ox::Error{2};
}
}
Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept { Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept {
// unsupported // unsupported
return ox::Error(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::removePath(StringViewCR path, bool const recursive) noexcept {
if (recursive) {
return ox::Error{std::filesystem::remove_all(m_path / stripSlash(path)) == 0};
} else {
return ox::Error{!std::filesystem::remove(m_path / stripSlash(path))};
}
}
Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept { Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept {
const auto p = (m_path / stripSlash(path)); const auto p = (m_path / stripSlash(path));
try { try {
@@ -176,7 +197,7 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return ox::Error(1); return ox::Error(1);
} }
return ox::Error(0); return {};
} }
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
@@ -185,8 +206,7 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
} }
std::string_view PassThroughFS::stripSlash(StringView path) noexcept { std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
const auto pathLen = ox::strlen(path); for (auto i = 0u; i < path.size() && path[0] == '/'; i++) {
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
path = substr(path, 1); path = substr(path, 1);
} }
return {path.data(), path.bytes()}; return {path.data(), path.bytes()};

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -45,8 +45,6 @@ class PassThroughFS: public FileSystem {
template<typename F> template<typename F>
Error ls(StringViewCR dir, F cb) const noexcept; Error ls(StringViewCR dir, F cb) const noexcept;
Error remove(StringViewCR path, bool recursive) noexcept override;
Error resize(uint64_t size, void *buffer) noexcept override; Error resize(uint64_t size, void *buffer) noexcept override;
Result<FileStat> statInode(uint64_t inode) const noexcept override; Result<FileStat> statInode(uint64_t inode) const noexcept override;
@@ -73,8 +71,13 @@ class PassThroughFS: public FileSystem {
Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override; Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override;
Error readFilePathRange(
StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept override;
Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override; Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override;
Error removePath(StringViewCR path, bool recursive) noexcept override;
Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept override;
Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override; Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override;
@@ -96,7 +99,7 @@ Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
for (auto &p : di) { for (auto &p : di) {
OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0)); OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
} }
return ox::Error(0); return {};
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -36,7 +36,7 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) {
if (idx >= 0 && size < outSize) { if (idx >= 0 && size < outSize) {
ox::memcpy(out, m_path, size); ox::memcpy(out, m_path, size);
out[size] = 0; out[size] = 0;
return ox::Error(0); return {};
} else { } else {
return ox::Error(1); return ox::Error(1);
} }
@@ -74,7 +74,7 @@ Error PathIterator::get(StringView &fileName) {
if (size && fileName[size - 1] == '/') { if (size && fileName[size - 1] == '/') {
fileName = ox::substr(m_path, start, start + size - 1); fileName = ox::substr(m_path, start, start + size - 1);
} }
oxAssert(fileName[fileName.len()-1] != '/', "name ends in /"); oxAssert(fileName[fileName.size()-1] != '/', "name ends in /");
return {}; return {};
} }
@@ -85,7 +85,7 @@ Error PathIterator::next(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
auto retval = ox::Error(1); auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = ox::Error(0); retval = {};
if (m_path[m_iterator] == '/') { if (m_path[m_iterator] == '/') {
m_iterator++; m_iterator++;
} }
@@ -104,11 +104,11 @@ Error PathIterator::next(StringView &fileName) {
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
while (fileName.len() && fileName[fileName.len() - 1] == '/') { while (fileName.size() && fileName[fileName.size() - 1] == '/') {
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
} }
m_iterator += size; m_iterator += size;
oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /"); oxAssert(fileName.size() == 0 || fileName[fileName.size()-1] != '/', "name ends in /");
} }
return retval; return retval;
} }
@@ -118,7 +118,7 @@ Result<std::size_t> PathIterator::nextSize() const {
auto retval = ox::Error(1); auto retval = ox::Error(1);
auto it = m_iterator; auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) { if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = ox::Error(0); retval = {};
if (m_path[it] == '/') { if (m_path[it] == '/') {
it++; it++;
} }

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -354,7 +354,7 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} }
} }
m_header.bytesUsed -= item.size(); m_header.bytesUsed -= item.size();
return ox::Error(0); return {};
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@@ -370,7 +370,7 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end; auto data = reinterpret_cast<uint8_t*>(this) + end;
ox::memset(data, 0, size - end); ox::memset(data, 0, size - end);
return ox::Error(0); return {};
} }
} }
@@ -422,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
src = ptr(dest->next); src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize()); dest = uninitializedPtr(dest.offset() + dest->fullSize());
} }
return ox::Error(0); return {};
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -59,7 +59,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next1", "PathIterator::next1",
[](ox::StringView) { [](ox::StringView) {
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
@@ -74,9 +74,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path); ox::PathIterator it(path);
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff), "PathIterator::next returned error"); oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "usr"); ox::expect(buff, "usr");
oxAssert(it.next(buff), "PathIterator::next returned error"); oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "share"); ox::expect(buff, "share");
return ox::Error(0); return ox::Error(0);
} }
}, },
@@ -84,7 +84,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next3", "PathIterator::next3",
[](ox::StringView) { [](ox::StringView) {
auto const path = ox::String("/"); auto const path = ox::String("/");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
return ox::Error(0); return ox::Error(0);
@@ -106,7 +106,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next5", "PathIterator::next5",
[](ox::StringView) { [](ox::StringView) {
auto const path = ox::String("usr/share/"); auto const path = ox::String("usr/share/");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
@@ -117,9 +117,11 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::dirPath", "PathIterator::dirPath",
[] (ox::StringView) { [] (ox::StringView) {
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxAssert(it.dirPath(buff, path.size()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(0); return ox::Error(0);
} }
}, },
@@ -127,7 +129,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::hasNext", "PathIterator::hasNext",
[](ox::StringView) { [](ox::StringView) {
const auto path = "/file1"; const auto path = "/file1";
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::PathIterator it(path, ox::strlen(path)); ox::PathIterator it(path, ox::strlen(path));
OX_ALLOW_UNSAFE_BUFFERS_END
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
return ox::Error(0); return ox::Error(0);
@@ -163,14 +167,16 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) { [](ox::StringView) {
constexpr auto buffLen = 5000; constexpr auto buffLen = 5000;
constexpr auto str1 = "Hello, World!"; constexpr auto str1 = "Hello, World!";
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
constexpr auto str1Len = ox::strlen(str1) + 1; constexpr auto str1Len = ox::strlen(str1) + 1;
constexpr auto str2 = "Hello, Moon!"; constexpr auto str2 = "Hello, Moon!";
constexpr auto str2Len = ox::strlen(str2) + 1; constexpr auto str2Len = ox::strlen(str2) + 1;
OX_ALLOW_UNSAFE_BUFFERS_END
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen); auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed."); oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed.");
ox::FileStore32 fileStore(list, buffLen); ox::FileStore32 fileStore(list, buffLen);
oxAssert(fileStore.write(4, const_cast<char*>(str1), str1Len, 1), "FileStore::write 1 failed."); oxAssert(fileStore.write(4, str1, str1Len, 1), "FileStore::write 1 failed.");
oxAssert(fileStore.write(5, const_cast<char*>(str2), str2Len, 1), "FileStore::write 2 failed."); oxAssert(fileStore.write(5, str2, str2Len, 1), "FileStore::write 2 failed.");
char str1Read[str1Len]; char str1Read[str1Len];
size_t str1ReadSize = 0; size_t str1ReadSize = 0;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34,7 +34,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
} }
} }
static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept { static ox::Result<ox::UPtr<ox::FileSystem>> loadFs(const char *path) noexcept {
OX_REQUIRE(buff, loadFsBuff(path)); OX_REQUIRE(buff, loadFsBuff(path));
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
} }
@@ -48,7 +48,7 @@ static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept
for (const auto &file : files) { for (const auto &file : files) {
oxOutf("{}\n", file); oxOutf("{}\n", file);
} }
return ox::Error(0); return {};
} }
static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept { static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
@@ -57,8 +57,10 @@ static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcep
return ox::Error(1); return ox::Error(1);
} }
OX_REQUIRE(buff, fs->read(ox::StringView(args[1]))); OX_REQUIRE(buff, fs->read(ox::StringView(args[1])));
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
return ox::Error(0); OX_ALLOW_UNSAFE_BUFFERS_END
return {};
} }
static ox::Error run(int argc, const char **argv) noexcept { static ox::Error run(int argc, const char **argv) noexcept {

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -14,7 +14,7 @@
{ \ { \
const auto loggerErr = (loggerName).initConn(appName); \ const auto loggerErr = (loggerName).initConn(appName); \
if (loggerErr) { \ if (loggerErr) { \
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line); \ oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.src.file_name(), loggerErr.src.line()); \
} else { \ } else { \
ox::trace::setLogger(&(loggerName)); \ ox::trace::setLogger(&(loggerName)); \
} \ } \

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -91,23 +91,28 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
} }
void LoggerConn::msgSend() noexcept { void LoggerConn::msgSend() noexcept {
while (true) { try {
std::unique_lock lk(m_waitMut);
m_waitCond.wait(lk);
if (!m_running) {
break;
}
std::lock_guard const buffLk(m_buffMut);
while (true) { while (true) {
Array<char, units::KB> tmp; std::unique_lock lk(m_waitMut);
const auto read = m_buff.read(tmp.data(), tmp.size()); m_waitCond.wait(lk);
if (!read) { if (!m_running) {
break; break;
} }
oxAssert(read <= tmp.size(), "logger trying to read too much data"); std::lock_guard const buffLk(m_buffMut);
//std::printf("LoggerConn: sending %lu bytes\n", read); while (true) {
std::ignore = send(tmp.data(), read); 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);
}
} }
} catch (std::exception const &e) {
oxErrf("Exception in logger thread: {}\n", e.what());
oxAssert(false, "logger thread exception");
} }
} }

View File

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

View File

@@ -1,6 +1,5 @@
add_library( add_library(
OxMetalClaw OxMetalClaw
presenceindicator.cpp
read.cpp read.cpp
write.cpp write.cpp
) )

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -18,25 +18,25 @@
namespace ox::mc { namespace ox::mc {
template<typename T> template<Integer_c T>
static constexpr auto Bits = sizeof(T) << 3; static constexpr auto Bits = sizeof(T) << 3;
/** /**
* Returns highest bit other than possible signed bit. * Returns highest bit other than possible signed bit.
* Bit numbering starts at 0. * Bit numbering starts at 0.
*/ */
template<typename I> template<Integer_c I>
[[nodiscard]] [[nodiscard]]
constexpr std::size_t highestBit(I val) noexcept { constexpr size_t highestBit(I const val) noexcept {
unsigned shiftStart = sizeof(I) * 8 - 1; unsigned shiftStart = sizeof(I) * 8 - 1;
// find most significant non-sign indicator bit // find the most significant non-sign indicator bit
std::size_t highestBit = 0; size_t highestBit = 0;
// start at one bit lower if signed // start at one bit lower if signed
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
--shiftStart; --shiftStart;
} }
for (auto i = shiftStart; i > 0; --i) { for (auto i = shiftStart; i > 0; --i) {
const auto bitValue = (val >> i) & 1; auto const bitValue = (val >> i) & 1;
if (bitValue) { if (bitValue) {
highestBit = i; highestBit = i;
break; break;
@@ -45,7 +45,7 @@ constexpr std::size_t highestBit(I val) noexcept {
return highestBit; return highestBit;
} }
static_assert(highestBit(int8_t(0b10000000)) == 0); static_assert(highestBit(static_cast<int8_t>(0b10000000)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-1)) == 0); static_assert(highestBit(~static_cast<int8_t>(-1)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-2)) == 0); static_assert(highestBit(~static_cast<int8_t>(-2)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-3)) == 1); static_assert(highestBit(~static_cast<int8_t>(-3)) == 1);
@@ -53,40 +53,39 @@ static_assert(highestBit(1) == 0);
static_assert(highestBit(2) == 1); static_assert(highestBit(2) == 1);
static_assert(highestBit(4) == 2); static_assert(highestBit(4) == 2);
static_assert(highestBit(8) == 3); static_assert(highestBit(8) == 3);
static_assert(highestBit(uint64_t(1) << 31) == 31); static_assert(highestBit(static_cast<uint64_t>(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63); static_assert(highestBit(static_cast<uint64_t>(1) << 63) == 63);
struct McInt { struct McInt {
ox::Array<uint8_t, 9> data{}; Array<uint8_t, 9> data{};
// length of integer in bytes // length of integer in bytes
std::size_t length = 0; size_t length = 0;
}; };
template<typename I> template<Integer_c I>
[[nodiscard]] [[nodiscard]]
constexpr McInt encodeInteger(I pInput) noexcept { constexpr McInt encodeInteger(I const pInput) noexcept {
auto const input = ox::ResizedInt_t<I, 64>{pInput}; auto const input = ResizedInt_t<I, 64>{pInput};
McInt out; McInt out;
const auto inputNegative = is_signed_v<I> && input < 0; auto const inputNegative = is_signed_v<I> && input < 0;
// move input to uint64_t to allow consistent bit manipulation, and to avoid // move input to uint64_t to allow consistent bit manipulation and to avoid
// overflow concerns // overflow concerns
uint64_t val = 0; auto const val = std::bit_cast<uint64_t>(input);
ox::memcpy(&val, &input, sizeof(input));
if (val) { if (val) {
// bits needed to represent number factoring in space possibly // bits needed to represent number factoring in space possibly
// needed for signed bit // needed for signed bit
const auto highBit = inputNegative ? highestBit(~val) : highestBit(val); auto const highBit = inputNegative ? highestBit(~val) : highestBit(val);
const auto bits = highBit + 1 + (is_signed_v<I> ? 1 : 0); auto const bits = highBit + 1 + (is_signed_v<I> ? 1 : 0);
// bytes needed to store value // bytes needed to store value
std::size_t bytes = bits / 8 + (bits % 8 != 0); size_t bytes = bits / 8 + (bits % 8 != 0);
const auto bitsAvailable = bytes * 8; // bits available to integer value auto const bitsAvailable = bytes * 8; // bits available to integer value
const auto bitsNeeded = bits + bytes; auto const bitsNeeded = bits + bytes;
// factor in bits needed for bytesIndicator (does not affect bytesIndicator) // factor in bits needed for bytesIndicator (does not affect bytesIndicator)
// bits for integer + bits needed to represent bytes > bits available // bits for integer + bits needed to represent bytes > bits available
if (bitsNeeded > bitsAvailable && bytes != 9) { if (bitsNeeded > bitsAvailable && bytes != 9) {
++bytes; ++bytes;
} }
const auto bytesIndicator = onMask<uint8_t>(bytes - 1); auto const bytesIndicator = onMask<uint8_t>(bytes - 1);
// ensure we are copying from little endian representation // ensure we are copying from little endian representation
LittleEndian<uint64_t> leVal = val; LittleEndian<uint64_t> leVal = val;
if (inputNegative) { if (inputNegative) {
@@ -94,17 +93,21 @@ constexpr McInt encodeInteger(I pInput) noexcept {
} }
if (bytes == 9) { if (bytes == 9) {
out.data[0] = bytesIndicator; out.data[0] = bytesIndicator;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&out.data[1], &leVal, 8); ox::memcpy(&out.data[1], &leVal, 8);
OX_ALLOW_UNSAFE_BUFFERS_END
if (inputNegative) { if (inputNegative) {
out.data[1] |= 0b1000'0000; out.data[1] |= 0b1000'0000;
} }
} else { } else {
const auto valBits = bytes * 8; auto const valBits = bytes * 8;
uint64_t negBit = inputNegative ? 1 : 0; uint64_t const negBit = inputNegative ? 1 : 0;
auto intermediate = auto const intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate)); ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
out.length = bytes; out.length = bytes;
} }
@@ -116,8 +119,8 @@ constexpr McInt encodeInteger(I pInput) noexcept {
* length integer. * length integer.
*/ */
[[nodiscard]] [[nodiscard]]
constexpr std::size_t countBytes(unsigned b) noexcept { constexpr size_t countBytes(unsigned const b) noexcept {
std::size_t i = 0; size_t i = 0;
while ((b >> i) & 1) ++i; while ((b >> i) & 1) ++i;
return i + 1; return i + 1;
} }
@@ -132,61 +135,65 @@ static_assert(countBytes(0b0011'1111) == 7);
static_assert(countBytes(0b0111'1111) == 8); static_assert(countBytes(0b0111'1111) == 8);
static_assert(countBytes(0b1111'1111) == 9); static_assert(countBytes(0b1111'1111) == 9);
template<typename I> template<Integer_c I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept { constexpr Result<I> decodeInteger(Reader_c auto &rdr, size_t &bytesRead) noexcept {
uint8_t firstByte = 0; uint8_t firstByte = 0;
OX_RETURN_ERROR(rdr.read(&firstByte, 1)); OX_RETURN_ERROR(rdr.read(&firstByte, 1));
OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte); auto const bytes = countBytes(firstByte);
if (bytes == 9) { if (bytes == 9) {
*bytesRead = bytes; bytesRead = bytes;
I out = 0; I out = 0;
OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
OX_RETURN_ERROR(rdr.read(&out, sizeof(I))); OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
return fromLittleEndian<I>(out); return fromLittleEndian<I>(out);
} }
*bytesRead = bytes; bytesRead = bytes;
uint64_t decoded = 0; uint64_t decoded = 0;
OX_RETURN_ERROR(rdr.read(&decoded, bytes)); OX_RETURN_ERROR(rdr.read(&decoded, bytes));
decoded >>= bytes; decoded >>= bytes;
// move sign bit // move sign bit
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
const auto negBit = bytes * 8 - bytes - 1; auto const negBit = bytes * 8 - bytes - 1;
// move sign // move sign
const auto negative = (decoded >> negBit) == 1; auto const negative = (decoded >> negBit) == 1;
if (negative) { if (negative) {
// fill in all bits between encoded sign and real sign with 1s // fill in all bits between encoded sign and real sign with 1s
// split it up because the 32-bit ARM can't shift more than 32 bits // split it up because the 32-bit ARM can't shift more than 32 bits
ox::Array<uint32_t, 2> d = {}; Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
ox::memcpy(&d[0], &decoded, sizeof(decoded)); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
auto bit = negBit; ox::memcpy(&d[0], &decoded, sizeof(decoded));
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { OX_ALLOW_UNSAFE_BUFFERS_END
d[0] |= 1 << bit; auto bit = negBit;
} for (; bit < ox::min<size_t>(Bits<I>, 32); ++bit) {
bit -= 32; d[0] |= 1 << bit;
for (; bit < Bits<I>; ++bit) { }
d[1] |= 1 << bit; bit -= 32;
} for (; bit < Bits<I>; ++bit) {
I out = 0; d[1] |= 1 << bit;
if constexpr(ox::defines::BigEndian) { }
const auto d0Tmp = d[0]; I out = 0;
d[0] = d[1]; if constexpr(ox::defines::BigEndian) {
d[1] = d0Tmp; auto const d0Tmp = d[0];
} d[0] = d[1];
ox::memcpy(&out, &d[0], sizeof(out)); d[1] = d0Tmp;
return out; }
} OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&out, &d[0], sizeof(out));
OX_ALLOW_UNSAFE_BUFFERS_END
return out;
}
} }
return static_cast<I>(decoded); return static_cast<I>(decoded);
} }
template<typename I> template<Integer_c I>
Result<I> decodeInteger(McInt m) noexcept { Result<I> decodeInteger(McInt const &m) noexcept {
std::size_t bytesRead{}; size_t bytesRead{};
BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9}); BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9});
return decodeInteger<I>(br, &bytesRead); return decodeInteger<I>(br, bytesRead);
} }
} }

View File

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

View File

@@ -1,17 +0,0 @@
/*
* 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/.
*/
#include "err.hpp"
#include "presenceindicator.hpp"
namespace ox {
template class FieldBitmapWriterBase<uint8_t*>;
template class FieldBitmapWriterBase<const uint8_t*>;
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -11,6 +11,7 @@
#include <ox/std/array.hpp> #include <ox/std/array.hpp>
#include <ox/std/bit.hpp> #include <ox/std/bit.hpp>
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/span.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include <ox/std/reader.hpp> #include <ox/std/reader.hpp>
@@ -21,143 +22,101 @@ namespace ox {
template<Reader_c Reader> template<Reader_c Reader>
class FieldBitmapReader { class FieldBitmapReader {
protected: protected:
mutable std::size_t m_mapBlockIdx = ~std::size_t{0}; mutable size_t m_mapBlockIdx = ~size_t{};
mutable uint64_t m_mapBlock = 0; mutable uint64_t m_mapBlock{};
std::size_t m_mapStart = 0; size_t m_mapStart{};
Reader &m_reader; Reader &m_reader;
public: public:
explicit constexpr FieldBitmapReader(Reader &reader) noexcept; explicit constexpr FieldBitmapReader(Reader &reader) noexcept:
m_mapStart(reader.tellg()),
m_reader(reader) {
}
constexpr Result<bool> get(std::size_t i) const noexcept; constexpr Result<bool> get(size_t idx) const noexcept {
constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
OX_RETURN_ERROR(loadMapBlock(blockIdx));
}
idx %= blockBits;
return (m_mapBlock >> idx) & 1;
}
private: private:
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept; constexpr Error loadMapBlock(size_t const idx) const noexcept {
OX_REQUIRE(g, m_reader.tellg());
}; OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
Array<char, sizeof(m_mapBlock)> mapBlock{};
template<Reader_c Reader> OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept: // Warning: narrow-conv
m_mapStart(reader.tellg()), OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_reader(reader) { m_mapBlock = 0;
} for (uint64_t i{}; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
template<Reader_c Reader> i += 8;
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept { }
constexpr auto blockBits = sizeof(m_mapBlock); m_mapBlockIdx = idx;
auto const blockIdx = idx / blockBits; return {};
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
OX_RETURN_ERROR(loadMapBlock(blockIdx));
}
idx %= blockBits;
return (m_mapBlock >> idx) & 1;
}
template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
OX_REQUIRE(g, m_reader.tellg());
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
i += 8;
}
m_mapBlockIdx = idx;
return {};
}
template<typename T>
class FieldBitmapWriterBase {
protected:
T m_map = nullptr;
std::size_t m_mapLen = 0;
public:
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept;
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept;
constexpr void setFields(int) noexcept;
constexpr void setMaxLen(int) noexcept;
[[nodiscard]]
constexpr int64_t getMaxLen() const noexcept;
};
template<typename T>
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T>
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T>
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept {
if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1;
} else {
return ox::Error(McPresenceMapOverflow);
}
}
template<typename T>
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept {
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
}
template<typename T>
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept {
m_mapLen = static_cast<std::size_t>(maxLen);
}
template<typename T>
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
return static_cast<int64_t>(m_mapLen);
}
extern template class FieldBitmapWriterBase<uint8_t*>;
extern template class FieldBitmapWriterBase<const uint8_t*>;
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> {
public:
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
constexpr Error set(std::size_t i, bool on) noexcept;
};
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
FieldBitmapWriterBase<uint8_t*>(map, maxLen) {
}
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
if (i / 8 < m_mapLen) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (on) {
m_map[i / 8] |= 1 << (i % 8);
} else {
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; };
} else {
return ox::Error(McPresenceMapOverflow);
} class FieldBitmapWriter {
} protected:
Span<char> m_map;
size_t m_mapLen{};
public:
explicit constexpr FieldBitmapWriter(Span<char> const &map) noexcept:
m_map(map),
m_mapLen(m_map.size()) {
}
constexpr auto setBuffer(Span<char> const &map) noexcept {
m_map = map;
m_mapLen = map.size();
}
constexpr Result<bool> get(size_t const i) const noexcept {
if (i / 8 < m_mapLen) {
return (std::bit_cast<uint8_t>(m_map[i / 8]) >> (i % 8)) & 1;
}
return Error{McPresenceMapOverflow};
}
constexpr Error setFields(int const fields) noexcept {
m_mapLen = static_cast<size_t>((fields / 8 + 1) - (fields % 8 == 0));
if (m_mapLen > m_map.size()) [[unlikely]] {
return Error{McPresenceMapOverflow};
}
return {};
}
constexpr void setMaxLen(int const maxLen) noexcept {
m_mapLen = static_cast<size_t>(maxLen);
}
constexpr int64_t getMaxLen() const noexcept {
return static_cast<int64_t>(m_mapLen);
}
constexpr Error set(size_t const i, bool const on) noexcept {
if (i / 8 < m_mapLen) {
char &actual = m_map[i / 8];
uint8_t v = std::bit_cast<uint8_t>(actual);
if (on) {
v |= 1 << (i % 8);
} else {
v &= ~static_cast<uint8_t>(1 << (i % 8));
}
actual = std::bit_cast<char>(v);
return {};
}
return Error{McPresenceMapOverflow};
}
};
} }

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -32,58 +32,58 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
private: private:
FieldBitmapReader<Reader> m_fieldPresence; FieldBitmapReader<Reader> m_fieldPresence;
std::size_t m_fields = 0; size_t m_fields{};
std::size_t m_field = 0; size_t m_field{};
ox::Optional<int> m_unionIdx; Optional<int> const m_unionIdx{};
Reader &m_reader; Reader &m_reader;
public: public:
explicit constexpr MetalClawReaderTemplate( explicit constexpr MetalClawReaderTemplate(
Reader &reader, Reader &reader,
ox::Optional<int> const&unionIdx = {}) noexcept; Optional<int> const &unionIdx = {}) noexcept;
constexpr ~MetalClawReaderTemplate() noexcept; constexpr ~MetalClawReaderTemplate() noexcept;
constexpr Error field(const char*, int8_t *val) noexcept; constexpr Error field(CString, int8_t *val) noexcept;
constexpr Error field(const char*, int16_t *val) noexcept; constexpr Error field(CString, int16_t *val) noexcept;
constexpr Error field(const char*, int32_t *val) noexcept; constexpr Error field(CString, int32_t *val) noexcept;
constexpr Error field(const char*, int64_t *val) noexcept; constexpr Error field(CString, int64_t *val) noexcept;
constexpr Error field(const char*, uint8_t *val) noexcept; constexpr Error field(CString, uint8_t *val) noexcept;
constexpr Error field(const char*, uint16_t *val) noexcept; constexpr Error field(CString, uint16_t *val) noexcept;
constexpr Error field(const char*, uint32_t *val) noexcept; constexpr Error field(CString, uint32_t *val) noexcept;
constexpr Error field(const char*, uint64_t *val) noexcept; constexpr Error field(CString, uint64_t *val) noexcept;
constexpr Error field(const char*, bool *val) noexcept; constexpr Error field(CString, bool *val) noexcept;
// array handler // array handler
constexpr Error field(const char*, auto *val, std::size_t len) noexcept; constexpr Error field(CString, auto *val, size_t valLen) noexcept;
// map handler // map handler
template<typename T> template<typename T>
constexpr Error field(const char*, HashMap<String, T> *val) noexcept; constexpr Error field(CString, HashMap<String, T> *val) noexcept;
// array handler, with callback to allow handling individual elements // array handler, with callback to allow handling individual elements
template<typename T, typename CB> template<typename T, typename CB>
constexpr Error field(const char*, CB cb) noexcept; constexpr Error field(CString, CB cb) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, T *val) noexcept; constexpr Error field(CString, T *val) noexcept;
template<typename U, bool force> template<typename U, bool force>
constexpr Error field(const char*, UnionView<U, force> val) noexcept; constexpr Error field(CString, UnionView<U, force> val) noexcept;
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept; constexpr Error field(CString, BasicString<SmallStringSize> *val) noexcept;
template<std::size_t L> template<size_t L>
constexpr Error field(const char*, IString<L> *val) noexcept; constexpr Error field(CString, IString<L> *val) noexcept;
constexpr Error fieldCString(const char*, char *val, std::size_t buffLen) noexcept; constexpr Error fieldCString(CString, char *val, size_t buffLen) noexcept;
constexpr Error fieldCString(const char*, char **val) noexcept; constexpr Error fieldCString(CString, char **val) noexcept;
constexpr Error fieldCString(const char*, char **val, std::size_t buffLen) noexcept; constexpr Error fieldCString(CString, char **val, size_t buffLen) noexcept;
/** /**
* Reads an array length from the current location in the buffer. * Reads an array length from the current location in the buffer.
@@ -101,13 +101,13 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
const char *name = T::TypeName, const char *name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const Vector<String>& = {}, const Vector<String>& = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept; size_t fields = ModelFieldCount_v<T>) noexcept;
/** /**
* Returns a MetalClawReader to parse a child object. * Returns a MetalClawReader to parse a child object.
*/ */
[[nodiscard]] [[nodiscard]]
constexpr MetalClawReaderTemplate<Reader> child(const char *name, ox::Optional<int> unionIdx = {}) noexcept; constexpr MetalClawReaderTemplate<Reader> child(const char *name, Optional<int> unionIdx = {}) noexcept;
/** /**
* Indicates whether or not the next field to be read is present. * Indicates whether or not the next field to be read is present.
@@ -122,20 +122,20 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
constexpr bool fieldPresent(int fieldNo) const noexcept; constexpr bool fieldPresent(int fieldNo) const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr int whichFieldPresent(const char *name, const ModelUnion&) const noexcept; constexpr int whichFieldPresent(const char *name, ModelUnion const&) const noexcept;
constexpr void nextField() noexcept; constexpr void nextField() noexcept;
private: private:
template<typename I> template<typename I>
constexpr Error readInteger(I *val) noexcept; constexpr Error readInteger(I &val) noexcept;
}; };
template<Reader_c Reader> template<Reader_c Reader>
constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate( constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate(
Reader &reader, Reader &reader,
ox::Optional<int> const&unionIdx) noexcept: Optional<int> const &unionIdx) noexcept:
m_fieldPresence(reader), m_fieldPresence(reader),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_reader(reader) { m_reader(reader) {
@@ -149,71 +149,72 @@ constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept {
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int8_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int8_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int16_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int16_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int32_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int32_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int64_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int64_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint8_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint8_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint16_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint16_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint32_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint32_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint64_t *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint64_t *val) noexcept {
return readInteger(val); return readInteger(*val);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, bool *val) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field)); auto const result = m_fieldPresence.get(static_cast<size_t>(m_field));
*val = result.value; *val = result.value;
OX_RETURN_ERROR(result); OX_RETURN_ERROR(result);
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
// array handler // array handler
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { const char *name, auto *val, size_t const valLen) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
// read the list // read the list
if (valLen >= len) { if (valLen >= len) {
auto reader = child({}); auto reader = child({});
auto &handler = *reader.interface(); auto &handler = *reader.interface();
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i])); OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
@@ -230,18 +231,18 @@ OX_ALLOW_UNSAFE_BUFFERS_END
template<Reader_c Reader> template<Reader_c Reader>
template<typename T> template<typename T>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, HashMap<String, T> *val) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
OX_REQUIRE(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
OX_RETURN_ERROR(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto &val) { constexpr auto loopBody = [](auto &handler, auto &val) {
OX_REQUIRE(keyLen, handler.stringLength(nullptr)); OX_REQUIRE(keyLen, handler.stringLength(nullptr));
@@ -250,22 +251,22 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1)); OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
return handler.field("", &val[wkeyPtr]); return handler.field("", &val[wkeyPtr]);
}; };
for (std::size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
OX_RETURN_ERROR(loopBody(handler, *val)); OX_RETURN_ERROR(loopBody(handler, *val));
} }
} }
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
template<typename T> template<typename T>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept {
if constexpr(isVector_v<T>) { if constexpr(isVector_v<T>) {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
OX_REQUIRE(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
OX_RETURN_ERROR(ox::resizeVector(*val, len)); OX_RETURN_ERROR(ox::resizeVector(*val, len));
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
@@ -275,9 +276,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
++m_field; ++m_field;
return {}; return {};
} else if constexpr(isArray_v<T>) { } else if constexpr(isArray_v<T>) {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
OX_REQUIRE(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
if (len > val->size()) { if (len > val->size()) {
return ox::Error(1, "Input array is too long"); return ox::Error(1, "Input array is too long");
@@ -288,8 +289,8 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
++m_field; ++m_field;
return {}; return {};
} else { } else {
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) { if ((!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) && val) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
auto reader = child(""); auto reader = child("");
OX_RETURN_ERROR(model(reader.interface(), val)); OX_RETURN_ERROR(model(reader.interface(), val));
} }
@@ -301,9 +302,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
template<Reader_c Reader> template<Reader_c Reader>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, UnionView<U, force> val) noexcept {
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) { if ((!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) && val.get()) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx())); auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
OX_RETURN_ERROR(model(reader.interface(), val.get())); OX_RETURN_ERROR(model(reader.interface(), val.get()));
} }
@@ -313,13 +314,13 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U,
} }
template<Reader_c Reader> template<Reader_c Reader>
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, BasicString<SmallStringSize> *val) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
const auto cap = size; const auto cap = size;
*val = BasicString<SmallStringSize>(cap); *val = BasicString<SmallStringSize>(cap);
auto data = val->data(); auto data = val->data();
@@ -330,17 +331,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
} }
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
template<std::size_t L> template<size_t L>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, IString<L> *val) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
*val = IString<L>(); *val = IString<L>();
OX_RETURN_ERROR(val->resize(size)); OX_RETURN_ERROR(val->resize(size));
auto const data = val->data(); auto const data = val->data();
@@ -355,11 +356,12 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { CString, char *val, size_t const buffLen) noexcept {
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
if (size > buffLen) { if (size > buffLen) {
return ox::Error(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
@@ -370,15 +372,15 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(CString, char **val) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
// re-allocate in case too small // re-allocate in case too small
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
@@ -388,16 +390,16 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(CString, char **val, size_t buffLen) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
// re-allocate if too small // re-allocate if too small
if (buffLen < size + 1) { if (buffLen < size + 1) {
safeDelete(*val); safeDelete(*val);
@@ -416,17 +418,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
} }
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept { constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(CString, bool const pass) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
if (!pass) { if (!pass) {
OX_RETURN_ERROR(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
} }
@@ -437,12 +439,12 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept { constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(CString) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead); auto len = mc::decodeInteger<StringLength>(m_reader, bytesRead);
OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur)); OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
return len; return len;
} }
@@ -452,34 +454,34 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
template<Reader_c Reader> template<Reader_c Reader>
template<typename I> template<typename I>
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I &val) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
std::size_t bytesRead = 0; size_t bytesRead = 0;
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead); auto const result = mc::decodeInteger<I>(m_reader, bytesRead);
OX_RETURN_ERROR(result); OX_RETURN_ERROR(result);
*val = result.value; val = result.value;
} else { } else {
*val = 0; val = 0;
} }
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
template<typename T, typename CB> template<typename T, typename CB>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(CString, CB cb) noexcept {
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; size_t bytesRead = 0;
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
T val; T val;
OX_RETURN_ERROR(handler.field("", &val)); OX_RETURN_ERROR(handler.field("", &val));
OX_RETURN_ERROR(cb(i, &val)); OX_RETURN_ERROR(cb(i, &val));
@@ -487,13 +489,13 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc
} }
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
template<typename T> template<typename T>
constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo( constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
const char*, int, const Vector<String>&, std::size_t fields) noexcept { CString, int, const Vector<String>&, size_t const fields) noexcept {
m_fields = fields; m_fields = fields;
// Warning: narrow-conv // Warning: narrow-conv
return m_reader.seekg( return m_reader.seekg(
@@ -503,24 +505,24 @@ constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
template<Reader_c Reader> template<Reader_c Reader>
constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child( constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(
const char*, CString,
ox::Optional<int> unionIdx) noexcept { Optional<int> const unionIdx) noexcept {
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx); return MetalClawReaderTemplate<Reader>(m_reader, unionIdx);
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(const char*) const noexcept { constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(CString) const noexcept {
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value; return m_fieldPresence.get(static_cast<size_t>(m_field)).value;
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int fieldNo) const noexcept { constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int const fieldNo) const noexcept {
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value; return m_fieldPresence.get(static_cast<size_t>(fieldNo)).value;
} }
template<Reader_c Reader> template<Reader_c Reader>
[[nodiscard]] [[nodiscard]]
constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept { constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(CString, ModelUnion const &u) const noexcept {
FieldBitmapReader<Reader> p(m_reader); FieldBitmapReader<Reader> p(m_reader);
for (auto i = 0u; i < u.fieldCount(); ++i) { for (auto i = 0u; i < u.fieldCount(); ++i) {
if (p.get(i)) { if (p.get(i)) {
@@ -538,11 +540,10 @@ constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>; using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
template<typename T> template<typename T>
Error readMC(ox::BufferView buff, T &val) noexcept { Error readMC(ox::BufferView const buff, T &val) noexcept {
BufferReader br(buff); BufferReader br(buff);
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader); return model(reader.interface(), &val);
return model(&handler, &val);
} }
template<typename T> template<typename T>

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -157,8 +157,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch"); oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch"); oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch"); oxAssert(testIn.String == testOut.String, "String value mismatch");
oxDebugf("{}", testOut.IString.len()); ox::expect(testIn.IString, testOut.IString);
oxExpect(testIn.IString, testOut.IString);
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch"); oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch"); oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch"); oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29,71 +29,71 @@
namespace ox { namespace ox {
template<Writer_c Writer> template<Writer_c Writer>
class MetalClawWriter { class MetalClawWriter: public ModelHandlerBase<MetalClawWriter<Writer>, OpType::Write> {
private: private:
ox::Vector<uint8_t, 16> m_presenceMapBuff{}; Vector<char, 16> m_presenceMapBuff{};
FieldBitmap m_fieldPresence; FieldBitmapWriter m_fieldPresence{m_presenceMapBuff};
int m_field = 0; int m_field{};
ox::Optional<int> m_unionIdx; Optional<int> m_unionIdx;
std::size_t m_writerBeginP{}; size_t m_writerBeginP{};
Writer &m_writer; Writer &m_writer;
public: public:
constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept; constexpr explicit MetalClawWriter(Writer &writer, Optional<int> const &unionIdx = {}) noexcept;
constexpr ~MetalClawWriter() noexcept = default; constexpr ~MetalClawWriter() noexcept = default;
constexpr Error field(const char*, const int8_t *val) noexcept; constexpr Error field(CString, int8_t const *val) noexcept;
constexpr Error field(const char*, const int16_t *val) noexcept; constexpr Error field(CString, int16_t const *val) noexcept;
constexpr Error field(const char*, const int32_t *val) noexcept; constexpr Error field(CString, int32_t const *val) noexcept;
constexpr Error field(const char*, const int64_t *val) noexcept; constexpr Error field(CString, int64_t const *val) noexcept;
constexpr Error field(const char*, const uint8_t *val) noexcept; constexpr Error field(CString, uint8_t const *val) noexcept;
constexpr Error field(const char*, const uint16_t *val) noexcept; constexpr Error field(CString, uint16_t const *val) noexcept;
constexpr Error field(const char*, const uint32_t *val) noexcept; constexpr Error field(CString, uint32_t const *val) noexcept;
constexpr Error field(const char*, const uint64_t *val) noexcept; constexpr Error field(CString, uint64_t const *val) noexcept;
constexpr Error field(const char*, const bool *val) noexcept; constexpr Error field(CString, bool const *val) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, const T *val, std::size_t len) noexcept; constexpr Error field(CString, T const *val, size_t len) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept; constexpr Error field(CString name, HashMap<String, T> const *val) noexcept;
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept; constexpr Error field(CString, BasicString<SmallStringSize> const *val) noexcept;
template<std::size_t L> template<size_t L>
constexpr Error field(const char*, const IString<L> *val) noexcept; constexpr Error field(CString, IString<L> const *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept; constexpr Error fieldCString(CString name, CString const*val, size_t buffLen) noexcept;
constexpr Error fieldCString(const char *name, const char **val) noexcept; constexpr Error fieldCString(CString name, CString *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val) noexcept; constexpr Error fieldCString(CString name, CString const*val) noexcept;
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept; constexpr Error fieldCString(CString name, CString val, size_t strLen) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, const T *val) noexcept; constexpr Error field(CString, T const *val) noexcept;
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> val) noexcept; constexpr Error field(CString, UnionView<U, force> val) noexcept;
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo( constexpr Error setTypeInfo(
const char *name = T::TypeName, CString name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const Vector<String>& = {}, Vector<String> const& = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept; size_t fields = ModelFieldCount_v<T>) noexcept;
/** /**
* stringLength is not implemented in MetalClawWriter * stringLength is not implemented in MetalClawWriter
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto stringLength(const char*) noexcept { constexpr auto stringLength(CString) noexcept {
return 0; return 0;
} }
@@ -101,28 +101,23 @@ class MetalClawWriter {
* stringLength is not implemented in MetalClawWriter * stringLength is not implemented in MetalClawWriter
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto arrayLength(const char*, bool = true) noexcept { constexpr auto arrayLength(CString, bool = true) noexcept {
return 0; return 0;
} }
[[nodiscard]] constexpr Error finalize() noexcept;
static constexpr auto opType() noexcept {
return OpType::Write;
}
ox::Error finalize() noexcept;
private: private:
constexpr Error appendInteger(Integer_c auto val) noexcept { constexpr Error appendInteger(Integer_c auto val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(mi.data.data()), mi.length));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
}; };
@@ -131,144 +126,147 @@ extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>; extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
template<Writer_c Writer> template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept: constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_writerBeginP(writer.tellp()), m_writerBeginP(writer.tellp()),
m_writer(writer) { m_writer(writer) {
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int8_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int16_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int32_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int64_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint8_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint16_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint32_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint64_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, bool const *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), *val));
} }
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, BasicString<SmallStringSize> const *val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->len()); auto const strLen = mc::encodeInteger(val->size());
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLen.data.data()), strLen.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len()))); OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<size_t>(val->size())));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t L> template<size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString name, IString<L> const *val) noexcept {
return fieldCString(name, val->data(), val->len()); return fieldCString(name, val->data(), val->size());
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const *val, size_t) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
const auto strLen = *val ? ox::strlen(*val) : 0; OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// this strlen is tolerated because sometimes 0 gets passed to
// the size param, which is a lie
// this code should be cleaned up at some point...
auto const strLen = *val ? ox::strlen(*val) : 0;
OX_ALLOW_UNSAFE_BUFFERS_END
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); auto const strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(*val, static_cast<size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString *val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString const *val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const val, size_t const strLen) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); auto const strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(val, static_cast<size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, T const *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
return field(nullptr, val->data(), val->size()); return field(nullptr, val->data(), val->size());
} else { } else {
bool fieldSet = false; bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer}; OX_RETURN_ERROR(model(writer.interface(), val));
OX_RETURN_ERROR(model(&handler, val));
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@@ -276,65 +274,62 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
template<Writer_c Writer> template<Writer_c Writer>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, UnionView<U, force> val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); MetalClawWriter writer(m_writer, Optional<int>(in_place, val.idx()));
ModelHandlerInterface handler{&writer}; OX_RETURN_ERROR(model(writer.interface(), val.get()));
OX_RETURN_ERROR(model(&handler, val.get()));
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, T const *val, size_t const len) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); auto const arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter writer(m_writer);
ModelHandlerInterface handler{&writer}; OX_RETURN_ERROR(writer.interface()->template setTypeInfo<T>("List", 0, {}, static_cast<size_t>(len)));
OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (size_t i{}; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i])); OX_RETURN_ERROR(writer.interface()->field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, HashMap<String, T> const *val) noexcept {
const auto &keys = val->keys(); auto const &keys = val->keys();
const auto len = keys.size(); auto const len = keys.size();
bool fieldSet = false; bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); auto const arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
// write map // write map
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter writer(m_writer);
ModelHandlerInterface handler{&writer};
// double len for both key and value // double len for both key and value
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2)); OX_RETURN_ERROR(writer.interface()->setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error { constexpr auto loopBody = [](auto &handler, auto const &key, auto const &val) -> Error {
const auto keyLen = key.len(); auto const keyLen = key.size();
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1); memcpy(wkey.get(), key.c_str(), keyLen + 1);
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen)); OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
@@ -342,53 +337,51 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
return handler.field("", value); return handler.field("", value);
}; };
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (size_t i{}; i < len; ++i) {
auto const&key = keys[i]; auto const &key = keys[i];
OX_RETURN_ERROR(loopBody(handler, key, *val)); OX_RETURN_ERROR(loopBody(*writer.interface(), key, *val));
} }
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return ox::Error(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo( constexpr Error MetalClawWriter<Writer>::setTypeInfo(
const char*, CString,
int, int,
const Vector<String>&, Vector<String> const&,
std::size_t fields) noexcept { size_t const fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1; auto const fieldPresenceLen = (fields - 1) / 8 + 1;
OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff);
m_fieldPresence.setFields(static_cast<int>(fields)); return m_fieldPresence.setFields(static_cast<int>(fields));
return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept { constexpr Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp(); auto const end = m_writer.tellp();
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP)); OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
OX_RETURN_ERROR(m_writer.write( OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()), m_presenceMapBuff.data(),
m_presenceMapBuff.size())); m_presenceMapBuff.size()));
OX_RETURN_ERROR(m_writer.seekp(end)); OX_RETURN_ERROR(m_writer.seekp(end));
return {}; return {};
} }
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, auto const &val) noexcept {
MetalClawWriter mcWriter(writer); MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter}; OX_RETURN_ERROR(model(mcWriter.interface(), &val));
OX_RETURN_ERROR(model(&handler, &val));
OX_RETURN_ERROR(mcWriter.finalize()); OX_RETURN_ERROR(mcWriter.finalize());
return {}; return {};
} }
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { Result<Buffer> writeMC(auto const &val, size_t const buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz); Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0); BufferWriter bw(&buff, 0);
OX_RETURN_ERROR(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
@@ -396,7 +389,7 @@ Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, size_t const buffLen, auto const &val, size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw{{buff, buffLen}}; CharBuffWriter bw{{buff, buffLen}};
OX_RETURN_ERROR(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -13,7 +13,7 @@
// oxModelFwdDecl is necessary because Apple-Clang is broken... // 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_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_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_END() return {}; }
#define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName)); #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_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 #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -43,7 +43,7 @@ static constexpr auto buildTypeId(
for (const auto &p : typeParams) { for (const auto &p : typeParams) {
tp += p + ","; tp += p + ",";
} }
tp.resize(tp.len() - 1); tp.resize(tp.size() - 1);
tp += "#"; tp += "#";
} }
return ox::sfmt("{}{};{}", name, tp, version); return ox::sfmt("{}{};{}", name, tp, version);
@@ -244,7 +244,7 @@ constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto
// defaultValue is unused now, but placeholder for backwards compatibility // defaultValue is unused now, but placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); oxReturnError(io->field("defaultValue", &defaultValue));
return ox::Error(0); return {};
} }
#endif #endif

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -51,7 +51,7 @@ constexpr auto buildSubscriptStack(const T**, SubscriptStack *s) noexcept {
} }
template<typename T> template<typename T>
constexpr auto buildSubscriptStack(const UniquePtr<T>*, SubscriptStack *s) noexcept { constexpr auto buildSubscriptStack(const UPtr<T>*, SubscriptStack *s) noexcept {
s->push_back({.subscriptType = Subscript::SubscriptType::Ptr}); s->push_back({.subscriptType = Subscript::SubscriptType::Ptr});
} }
@@ -187,7 +187,7 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
PrimitiveType pt; PrimitiveType pt;
if constexpr(is_union_v<T>) { if constexpr(is_union_v<T>) {
pt = PrimitiveType::Union; pt = PrimitiveType::Union;
} else if constexpr(isBasicString_v<T> || isBString_v<T>) { } else if constexpr(isBasicString_v<T> || isIString_v<T>) {
pt = PrimitiveType::String; pt = PrimitiveType::String;
} else { } else {
pt = PrimitiveType::Struct; pt = PrimitiveType::Struct;
@@ -205,7 +205,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t,
const auto t = type(p); const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t)); m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
return ox::Error(0); return {};
} }
return ox::Error(1); return ox::Error(1);
} }
@@ -220,7 +220,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t)
auto const lvls = detail::indirectionLevels_v<T> + 1; auto const lvls = detail::indirectionLevels_v<T> + 1;
SubscriptStack subscriptStack{lvls}; SubscriptStack subscriptStack{lvls};
m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t)); m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t));
return ox::Error(0); return {};
} }
return ox::Error(1); return ox::Error(1);
} }
@@ -231,7 +231,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return ox::Error(0); return {};
} }
return ox::Error(1); return ox::Error(1);
} }
@@ -357,7 +357,7 @@ constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept
template<std::size_t sz> template<std::size_t sz>
constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept { constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept {
constexpr auto PT = PrimitiveType::String; constexpr auto PT = PrimitiveType::String;
return getType(types::BString, 0, PT, 0); return getType(types::IString, 0, PT, 0);
} }
constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b, constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b,
@@ -380,7 +380,7 @@ constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typ
template<typename T> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
TypeDescWriter writer(&typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(writer);
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
std::allocator<T> a; std::allocator<T> a;
T *t = a.allocate(1); T *t = a.allocate(1);
@@ -396,7 +396,7 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
template<typename T> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(writer);
OX_RETURN_ERROR(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
return writer.definition(); return writer.definition();
} }

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,176 +17,177 @@ namespace ox {
template<typename Handler, OpType opType_v = Handler::opType()> template<typename Handler, OpType opType_v = Handler::opType()>
class ModelHandlerInterface { class ModelHandlerInterface {
private: private:
Handler *m_handler = nullptr; Handler &m_handler;
public: public:
constexpr explicit ModelHandlerInterface(Handler *handler) noexcept: m_handler(handler) { constexpr explicit ModelHandlerInterface(Handler &handler) noexcept: m_handler(handler) {
} }
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* name = T::TypeName, CString name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const Vector<String>& typeParams = {}) noexcept { Vector<String> const &typeParams = {}) noexcept {
return m_handler->template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>); return m_handler.template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>);
} }
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char *name, CString name,
int version, int version,
const Vector<String>& typeParams, Vector<String> const &typeParams,
std::size_t fields) noexcept { size_t fields) noexcept {
return m_handler->template setTypeInfo<T>(name, version, typeParams, fields); return m_handler.template setTypeInfo<T>(name, version, typeParams, fields);
} }
template<std::size_t len> template<size_t len>
constexpr Error fieldCString(const char *name, char val[len]) noexcept { constexpr Error fieldCString(CString name, char val[len]) noexcept {
return m_handler->fieldCString(name, &val[0], len); return m_handler.fieldCString(name, &val[0], len);
} }
template<std::size_t len> template<size_t len>
constexpr Error fieldCString(const char *name, const char val[len]) noexcept requires(opType_v != OpType::Read) { constexpr Error fieldCString(CString name, char const val[len]) noexcept requires(opType_v != OpType::Read) {
if constexpr(opType_v != OpType::Read) { if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, &val[0], len); return m_handler.fieldCString(name, &val[0], len);
} else { } else {
return {}; return {};
} }
} }
constexpr Error fieldCString(const char *name, char **val) noexcept { constexpr Error fieldCString(CString name, char **val) noexcept {
return m_handler->fieldCString(name, val); return m_handler.fieldCString(name, val);
} }
constexpr Error fieldCString(const char *name, const char *const*val) noexcept requires(opType_v != OpType::Read) { constexpr Error fieldCString(CString name, char const *const*val) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) { if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val); return m_handler.fieldCString(name, val);
} else { } else {
return {}; return {};
} }
} }
constexpr Error fieldCString(const char *name, const char **val) noexcept requires(opType_v != OpType::Read) { constexpr Error fieldCString(CString name, char const **val) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) { if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val); return m_handler.fieldCString(name, val);
} else { } else {
return {}; return {};
} }
} }
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept { constexpr Error fieldCString(CString name, char **val, size_t buffLen) noexcept {
return m_handler->fieldCString(name, val, buffLen); return m_handler.fieldCString(name, val, buffLen);
} }
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept requires(opType_v != OpType::Read) { constexpr Error fieldCString(CString name, char const **val, size_t buffLen) noexcept requires(opType_v != OpType::Read) {
// this check looks pointless, but it's to address a Clang bug // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) { if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val, buffLen); return m_handler.fieldCString(name, val, buffLen);
} else { } else {
return {}; return {};
} }
} }
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept { constexpr Error fieldCString(CString name, char *val, size_t buffLen) noexcept {
return m_handler->fieldCString(name, val, buffLen); return m_handler.fieldCString(name, val, buffLen);
} }
constexpr Error fieldModelValue(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept { constexpr Error fieldModelValue(char const *name, CommonPtrWith<ModelValue> auto *v) noexcept {
switch (v->type()) { switch (v->type()) {
case ModelValue::Type::Undefined: case ModelValue::Type::Undefined:
break; break;
case ModelValue::Type::Bool: case ModelValue::Type::Bool:
return m_handler->field(name, &v->template get<bool>()); return m_handler.field(name, &v->template get<bool>());
case ModelValue::Type::UnsignedInteger8: case ModelValue::Type::UnsignedInteger8:
return m_handler->field(name, &v->template get<uint8_t>()); return m_handler.field(name, &v->template get<uint8_t>());
case ModelValue::Type::UnsignedInteger16: case ModelValue::Type::UnsignedInteger16:
return m_handler->field(name, &v->template get<uint16_t>()); return m_handler.field(name, &v->template get<uint16_t>());
case ModelValue::Type::UnsignedInteger32: case ModelValue::Type::UnsignedInteger32:
return m_handler->field(name, &v->template get<uint32_t>()); return m_handler.field(name, &v->template get<uint32_t>());
case ModelValue::Type::UnsignedInteger64: case ModelValue::Type::UnsignedInteger64:
return m_handler->field(name, &v->template get<uint64_t>()); return m_handler.field(name, &v->template get<uint64_t>());
case ModelValue::Type::SignedInteger8: case ModelValue::Type::SignedInteger8:
return m_handler->field(name, &v->template get<int8_t>()); return m_handler.field(name, &v->template get<int8_t>());
case ModelValue::Type::SignedInteger16: case ModelValue::Type::SignedInteger16:
return m_handler->field(name, &v->template get<int16_t>()); return m_handler.field(name, &v->template get<int16_t>());
case ModelValue::Type::SignedInteger32: case ModelValue::Type::SignedInteger32:
return m_handler->field(name, &v->template get<int32_t>()); return m_handler.field(name, &v->template get<int32_t>());
case ModelValue::Type::SignedInteger64: case ModelValue::Type::SignedInteger64:
return m_handler->field(name, &v->template get<int64_t>()); return m_handler.field(name, &v->template get<int64_t>());
case ModelValue::Type::String: case ModelValue::Type::String:
return m_handler->field(name, &v->template get<String>()); return m_handler.field(name, &v->template get<String>());
case ModelValue::Type::Object: case ModelValue::Type::Object:
return m_handler->field(name, &v->template get<ModelObject>()); return m_handler.field(name, &v->template get<ModelObject>());
case ModelValue::Type::Union: case ModelValue::Type::Union:
{ {
auto &u = v->template get<ModelUnion>(); auto &u = v->template get<ModelUnion>();
if constexpr(opType_v == OpType::Read) { if constexpr(opType_v == OpType::Read) {
u.setActiveField(m_handler->whichFieldPresent(name, u)); u.setActiveField(whichFieldPresent(m_handler, name, u));
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx())); return m_handler.field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
} else { } else {
return m_handler->field(name, UnionView<const ModelUnion, true>(&u, u.unionIdx())); return m_handler.field(name, UnionView<ModelUnion const, true>(&u, u.unionIdx()));
} }
} }
case ModelValue::Type::Vector: case ModelValue::Type::Vector:
return m_handler->field(name, &v->template get<ModelValueVector>()); return m_handler.field(name, &v->template get<ModelValueVector>());
case ModelValue::Type::InlineArray: case ModelValue::Type::InlineArray:
return m_handler->field(name, &v->template get<ModelValueArray>()); return m_handler.field(name, &v->template get<ModelValueArray>());
} }
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type())); oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(ox::Error(1), "invalid type"); ox::panic("invalid type");
return ox::Error(1, "invalid type"); return ox::Error(1, "invalid type");
} }
// array handler, with callback to allow handling individual elements // array handler, with callback to allow handling individual elements
template<typename T, typename Callback> template<typename T, typename Callback>
constexpr Error field(const char *name, Callback cb) noexcept { constexpr Error field(CString name, Callback cb) noexcept {
return m_handler->template field<T, Callback>(name, cb); return m_handler.template field<T, Callback>(name, cb);
} }
template<typename T> template<typename T>
constexpr Error field(const char *name, const T *v) noexcept { constexpr Error field(CString name, const T *v) noexcept {
if constexpr(ox::is_same_v<T, ModelValue>) { if constexpr(ox::is_same_v<T, ModelValue>) {
return fieldModelValue(name, v); return fieldModelValue(name, v);
} else { } else {
return m_handler->field(name, v); return m_handler.field(name, v);
} }
} }
template<typename T> template<typename T>
constexpr Error field(const char *name, T *v) noexcept { constexpr Error field(CString name, T *v) noexcept {
if constexpr(ox::is_same_v<T, ModelValue>) { if constexpr(ox::is_same_v<T, ModelValue>) {
return fieldModelValue(name, v); return fieldModelValue(name, v);
} else { } else {
return m_handler->field(name, v); return m_handler.field(name, v);
} }
} }
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char *name, UnionView<U, force> val) noexcept { constexpr Error field(CString name, UnionView<U, force> val) noexcept {
return m_handler->field(name, val); return m_handler.field(name, val);
} }
constexpr Error field(const char *name, auto *val, std::size_t len) noexcept { constexpr Error field(CString name, auto *val, size_t len) noexcept {
return m_handler->field(name, val, len); return m_handler.field(name, val, len);
} }
/** /**
* Reads an array length from the current location in the buffer. * Reads an array length from the current location in the buffer.
* @param name
* @param pass indicates that the parsing should iterate past the array length * @param pass indicates that the parsing should iterate past the array length
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto arrayLength(const char *name, bool pass = true) noexcept { constexpr auto arrayLength(CString name, bool pass = true) noexcept {
return m_handler->arrayLength(name, pass); return m_handler.arrayLength(name, pass);
} }
/** /**
* Reads an string length from the current location in the buffer. * Reads an string length from the current location in the buffer.
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto stringLength(const char *name) noexcept { constexpr auto stringLength(CString name) noexcept {
return m_handler->stringLength(name); return m_handler.stringLength(name);
} }
[[nodiscard]] [[nodiscard]]
@@ -198,22 +199,33 @@ class ModelHandlerInterface {
constexpr auto handler() noexcept { constexpr auto handler() noexcept {
return m_handler; return m_handler;
} }
private:
template<typename H>
static constexpr int whichFieldPresent(H &h, CString name, ModelUnion const &u) noexcept
requires(H::opType() == OpType::Read) {
return h.whichFieldPresent(name, u);
}
template<typename H>
static constexpr int whichFieldPresent(H&, CString, ModelUnion const&) noexcept
requires(H::opType() != OpType::Read) {
return 0;
}
}; };
template<typename Handler, ox::OpType opType_v = Handler::opType()> template<typename Handler, OpType opType_v = Handler::opType()>
class ModelHandlerBase { class ModelHandlerBase {
private: private:
ModelHandlerInterface<Handler, opType_v> m_interface; ModelHandlerInterface<Handler, opType_v> m_interface{*static_cast<Handler*>(this)};
public: public:
constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {}
constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {}
constexpr ModelHandlerBase(ModelHandlerBase&&) noexcept: m_interface(static_cast<Handler*>(this)) {}
[[nodiscard]] [[nodiscard]]
constexpr auto interface() noexcept { constexpr auto interface() noexcept {
return &m_interface; return &m_interface;
} }
[[nodiscard]] [[nodiscard]]
static constexpr ox::OpType opType() noexcept { static constexpr OpType opType() noexcept {
return opType_v; return opType_v;
} }
}; };

View File

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

View File

@@ -1,23 +1,28 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include <ox/std/hashmap.hpp>
#include "modelvalue.hpp" #include "modelvalue.hpp"
namespace ox { namespace ox {
static_assert([]() -> ox::Error { static_assert([]() -> Error {
ox::ModelValue v; ModelValue v;
OX_RETURN_ERROR(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
if (v.type() != ModelValue::Type::SignedInteger32) { if (v.type() != ModelValue::Type::SignedInteger32) {
return ox::Error(1, "type is wrong"); return Error(1, "type is wrong");
} }
//oxReturnError(v.set<int32_t>(5)); //oxReturnError(v.set<int32_t>(5));
return {}; return {};
}() == ox::Error(0)); }() == Error{});
// a dummy function to prevent linker errors in a library that has no other symbols
void modelDummyFunc() noexcept {}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -100,7 +100,7 @@ class ModelValue {
return Type::Union; return Type::Union;
} else if constexpr(is_same_v<U, ModelObject>) { } else if constexpr(is_same_v<U, ModelObject>) {
return Type::Object; return Type::Object;
} else if constexpr(isBasicString_v<U> || isBString_v<U>) { } else if constexpr(isBasicString_v<U> || isIString_v<U>) {
return Type::String; return Type::String;
} else if constexpr(is_same_v<U, ModelValueVector>) { } else if constexpr(is_same_v<U, ModelValueVector>) {
return Type::Vector; return Type::Vector;
@@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept { constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast"); ox::panic("invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept { constexpr auto &get() noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast"); ox::panic("invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@@ -187,7 +187,7 @@ class ModelValue {
constexpr Type type() const noexcept; constexpr Type type() const noexcept;
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const *type,
SubscriptStack const& = {}, SubscriptStack const& = {},
int subscriptLevels = 0) noexcept; int subscriptLevels = 0) noexcept;
@@ -200,8 +200,6 @@ class ModelValue {
template<typename T> template<typename T>
constexpr Error set(T &&v) noexcept; constexpr Error set(T &&v) noexcept;
constexpr ModelValue &operator=(ModelValue &val) noexcept;
constexpr ModelValue &operator=(const ModelValue &val) noexcept; constexpr ModelValue &operator=(const ModelValue &val) noexcept;
constexpr ModelValue &operator=(ModelValue &&val) noexcept; constexpr ModelValue &operator=(ModelValue &&val) noexcept;
@@ -275,7 +273,7 @@ class ModelValueArray {
} }
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const *type,
SubscriptStack subscriptStack, SubscriptStack subscriptStack,
int subscriptLevels) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch"); oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
@@ -418,7 +416,7 @@ class ModelValueVector {
} }
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const *type,
SubscriptStack subscriptStack, SubscriptStack subscriptStack,
int subscriptLevels) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch"); oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
@@ -521,7 +519,7 @@ class ModelObject {
protected: protected:
OX_MODEL_FRIEND(ModelObject); OX_MODEL_FRIEND(ModelObject);
friend ModelValue; friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder; Vector<UPtr<Field>> m_fieldsOrder;
HashMap<String, ModelValue*> m_fields; HashMap<String, ModelValue*> m_fields;
const DescriptorType *m_type = nullptr; const DescriptorType *m_type = nullptr;
@@ -694,7 +692,7 @@ class ModelUnion {
}; };
friend constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept; friend constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept;
friend ModelValue; friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder; Vector<UPtr<Field>> m_fieldsOrder;
HashMap<String, Field*> m_fields; HashMap<String, Field*> m_fields;
const DescriptorType *m_type = nullptr; const DescriptorType *m_type = nullptr;
int m_unionIdx = -1; int m_unionIdx = -1;
@@ -720,14 +718,14 @@ class ModelUnion {
m_unionIdx = other.m_unionIdx; m_unionIdx = other.m_unionIdx;
} }
static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept { static constexpr Result<UPtr<ModelUnion>> make(const DescriptorType *type) noexcept {
UniquePtr<ModelUnion> out(new ModelUnion); UPtr<ModelUnion> out(new ModelUnion);
OX_RETURN_ERROR(out->setType(type)); OX_RETURN_ERROR(out->setType(type));
return out; return out;
} }
static constexpr Result<UniquePtr<ModelUnion>> make(const ModelUnion &other) noexcept { static constexpr Result<UPtr<ModelUnion>> make(const ModelUnion &other) noexcept {
return UniquePtr<ModelUnion>(new ModelUnion(other)); return UPtr<ModelUnion>(new ModelUnion(other));
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
@@ -821,7 +819,7 @@ class ModelUnion {
template<typename PlatSpec> template<typename PlatSpec>
[[nodiscard]] [[nodiscard]]
constexpr std::size_t sizeOf(ModelValueArray const*v) noexcept { constexpr std::size_t sizeOf(ModelValueArray const *v) noexcept {
return sizeOf<PlatSpec>(&(*v)[0]) * v->size(); return sizeOf<PlatSpec>(&(*v)[0]) * v->size();
} }
@@ -972,7 +970,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return ox::Error(0); return {};
} }
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
@@ -981,7 +979,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return ox::Error(0); return {};
} }
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
@@ -997,7 +995,7 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); m_data = other.m_data;
break; break;
case Type::String: case Type::String:
m_data.str = new String(other.get<String>()); m_data.str = new String(other.get<String>());
@@ -1030,8 +1028,8 @@ constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); m_data = other.m_data;
ox::memset(&other.m_data, 0, sizeof(m_data)); other.m_data.ui64 = 0;
break; break;
case Type::String: case Type::String:
m_data.str = other.m_data.str; m_data.str = other.m_data.str;
@@ -1098,7 +1096,7 @@ constexpr Error ModelValue::setType(
} else if (type->typeName == types::Bool) { } else if (type->typeName == types::Bool) {
m_type = Type::Bool; m_type = Type::Bool;
} else if (type->typeName == types::BasicString || } else if (type->typeName == types::BasicString ||
type->typeName == types::BString || type->typeName == types::IString ||
type->typeName == types::String) { type->typeName == types::String) {
m_type = Type::String; m_type = Type::String;
m_data.str = new String; m_data.str = new String;
@@ -1129,7 +1127,7 @@ constexpr Error ModelValue::setType(
OX_RETURN_ERROR(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} }
oxAssert(m_type != Type::Undefined, "No type set"); oxAssert(m_type != Type::Undefined, "No type set");
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
@@ -1176,7 +1174,7 @@ template<typename T>
constexpr Error ModelValue::set(const T &v) noexcept { constexpr Error ModelValue::set(const T &v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return ox::Error(1, "type mismatch"); return Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@@ -1184,7 +1182,7 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = v; value = v;
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
@@ -1199,11 +1197,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = std::move(v); value = std::move(v);
return ox::Error(0); return {};
}
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {
return this->operator=(const_cast<const ModelValue&>(other));
} }
constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept { constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
@@ -1223,7 +1217,7 @@ constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); m_data = other.m_data;
break; break;
case Type::String: case Type::String:
m_data.str = new String(other.get<String>()); m_data.str = new String(other.get<String>());
@@ -1261,8 +1255,8 @@ constexpr ModelValue &ModelValue::operator=(ModelValue &&other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); m_data = other.m_data;
ox::memset(&other.m_data, 0, sizeof(m_data)); other.m_data = {};
break; break;
case Type::String: case Type::String:
m_data.str = other.m_data.str; m_data.str = other.m_data.str;

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return ox::Error(0); return {};
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
return ox::Error(0); return {};
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
@@ -77,17 +77,17 @@ struct TypeInfoCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
constexpr Error fieldCString(const char*, T) noexcept { constexpr Error fieldCString(const char*, T) noexcept {
return ox::Error(0); return {};
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
@@ -140,16 +140,16 @@ constexpr Str getModelTypeName() noexcept {
return out; return out;
} }
template<typename T> template<typename T, typename Str = const char*>
[[nodiscard]] [[nodiscard]]
consteval auto requireModelTypeName() noexcept { consteval auto requireModelTypeName() noexcept {
constexpr auto name = getModelTypeName<T>(); constexpr auto name = getModelTypeName<T, Str>();
static_assert(ox::StringView{name}.len(), "Type lacks required TypeName"); static_assert(ox::StringView{name}.size(), "Type lacks required TypeName");
return name; return name;
} }
template<typename T, typename Str = const char*> template<typename T, typename Str = const char*>
constexpr auto ModelTypeName_v = getModelTypeName<T, Str>(); constexpr auto ModelTypeName_v = requireModelTypeName<T, Str>();
template<typename T, typename Str = const char*> template<typename T, typename Str = const char*>
constexpr auto ModelTypeVersion_v = requireModelTypeVersion<T>(); constexpr auto ModelTypeVersion_v = requireModelTypeVersion<T>();
@@ -159,7 +159,7 @@ constexpr auto ModelTypeId_v = [] {
constexpr auto name = ModelTypeName_v<T, ox::StringView>; constexpr auto name = ModelTypeName_v<T, ox::StringView>;
constexpr auto version = ModelTypeVersion_v<T>; constexpr auto version = ModelTypeVersion_v<T>;
constexpr auto versionStr = ox::sfmt<ox::IString<19>>("{}", version); constexpr auto versionStr = ox::sfmt<ox::IString<19>>("{}", version);
return ox::sfmt<ox::IString<name.len() + versionStr.len() + 1>>("{};{}", name, versionStr); return ox::sfmt<ox::IString<name.size() + versionStr.size() + 1>>("{};{}", name, versionStr);
}(); }();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31,18 +31,18 @@
namespace ox { namespace ox {
namespace types { namespace types {
constexpr StringView BasicString = "net.drinkingtea.ox.BasicString"; constexpr StringLiteral BasicString = "net.drinkingtea.ox.BasicString";
constexpr StringView BString = "net.drinkingtea.ox.BString"; constexpr StringLiteral IString = "net.drinkingtea.ox.IString";
constexpr StringView String = "B.string"; constexpr StringLiteral String = "B.string";
constexpr StringView Bool = "B.bool"; constexpr StringLiteral Bool = "B.bool";
constexpr StringView Uint8 = "B.uint8"; constexpr StringLiteral Uint8 = "B.uint8";
constexpr StringView Uint16 = "B.uint16"; constexpr StringLiteral Uint16 = "B.uint16";
constexpr StringView Uint32 = "B.uint32"; constexpr StringLiteral Uint32 = "B.uint32";
constexpr StringView Uint64 = "B.uint64"; constexpr StringLiteral Uint64 = "B.uint64";
constexpr StringView Int8 = "B.int8"; constexpr StringLiteral Int8 = "B.int8";
constexpr StringView Int16 = "B.int16"; constexpr StringLiteral Int16 = "B.int16";
constexpr StringView Int32 = "B.int32"; constexpr StringLiteral Int32 = "B.int32";
constexpr StringView Int64 = "B.int64"; constexpr StringLiteral Int64 = "B.int64";
} }
template<typename T> template<typename T>
@@ -63,17 +63,17 @@ static_assert(isBasicString_v<ox::BasicString<8ul>>);
static_assert(isBasicString_v<ox::String>); static_assert(isBasicString_v<ox::String>);
template<typename T> template<typename T>
consteval bool isBString(const T*) noexcept { consteval bool isIString(const T*) noexcept {
return false; return false;
} }
template<std::size_t SmallVecSize> template<std::size_t SmallVecSize>
consteval bool isBString(const BasicString<SmallVecSize>*) noexcept { consteval bool isIString(const BasicString<SmallVecSize>*) noexcept {
return true; return true;
} }
template<typename T> template<typename T>
constexpr bool isBString_v = isBasicString(static_cast<const T*>(nullptr)); constexpr bool isIString_v = isIString(static_cast<const T*>(nullptr));
static_assert(isBasicString_v<ox::BasicString<0ul>>); static_assert(isBasicString_v<ox::BasicString<0ul>>);
static_assert(isBasicString_v<ox::BasicString<8ul>>); static_assert(isBasicString_v<ox::BasicString<8ul>>);
@@ -161,7 +161,7 @@ template<typename T>
constexpr bool isSmartPtr_v = false; constexpr bool isSmartPtr_v = false;
template<typename T> template<typename T>
constexpr bool isSmartPtr_v<::ox::UniquePtr<T>> = true; constexpr bool isSmartPtr_v<::ox::UPtr<T>> = true;
#if __has_include(<array>) #if __has_include(<array>)
template<typename T> template<typename T>
@@ -169,12 +169,12 @@ constexpr bool isSmartPtr_v<::std::unique_ptr<T>> = true;
#endif #endif
template<typename Union, bool force = false> template<typename Union, bool force = false> requires(force || is_union_v<Union>)
class UnionView { class UnionView {
protected: protected:
int m_idx = -1; int m_idx = -1;
typename enable_if<is_union_v<Union> || force, Union>::type *m_union = nullptr; Union *m_union = nullptr;
public: public:
constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) { constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21,7 +21,7 @@ namespace ox {
class TypeStore { class TypeStore {
private: private:
HashMap<String, UniquePtr<DescriptorType>> m_cache; HashMap<String, UPtr<DescriptorType>> m_cache;
public: public:
constexpr TypeStore() noexcept = default; constexpr TypeStore() noexcept = default;
@@ -58,7 +58,11 @@ class TypeStore {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
OX_REQUIRE_M(dt, loadDescriptor(typeId)); OX_REQUIRE_M(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) { for (auto &f : dt->fieldList) {
OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type)); if (typeId == f.typeId) {
f.type = dt.get();
} else {
OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type));
}
} }
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
out = std::move(dt); out = std::move(dt);
@@ -82,12 +86,12 @@ class TypeStore {
return getLoad(typeName, typeVersion); return getLoad(typeName, typeVersion);
} }
constexpr void set(const auto &typeId, UniquePtr<DescriptorType> dt) noexcept { constexpr void set(const auto &typeId, UPtr<DescriptorType> dt) noexcept {
m_cache[typeId] = std::move(dt); m_cache[typeId] = std::move(dt);
} }
constexpr void set(const auto &typeId, DescriptorType *dt) noexcept { constexpr void set(const auto &typeId, DescriptorType *dt) noexcept {
m_cache[typeId] = UniquePtr<DescriptorType>(dt); m_cache[typeId] = UPtr<DescriptorType>(dt);
} }
[[nodiscard]] [[nodiscard]]
@@ -101,11 +105,11 @@ class TypeStore {
} }
protected: protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept { virtual Result<UPtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return ox::Error(1); return ox::Error(1);
} }
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version, Result<UPtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version,
const ox::TypeParamPack &typeParams) noexcept { const ox::TypeParamPack &typeParams) noexcept {
const auto typeId = buildTypeId(name, version, typeParams); const auto typeId = buildTypeId(name, version, typeParams);
return loadDescriptor(typeId); return loadDescriptor(typeId);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -127,7 +127,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
} }
} }
walker->popNamePath(); walker->popNamePath();
return ox::Error(0); return {};
} }
template<typename Reader, typename FH> template<typename Reader, typename FH>
@@ -141,7 +141,7 @@ constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
for (const auto &field : fields) { for (const auto &field : fields) {
OX_RETURN_ERROR(parseField(field, rdr, walker)); OX_RETURN_ERROR(parseField(field, rdr, walker));
} }
return ox::Error(0); return {};
} }
template<typename Reader, typename Handler> template<typename Reader, typename Handler>

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -13,31 +13,31 @@
namespace ox { namespace ox {
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { OrganicClawReader::OrganicClawReader(const uint8_t *buff, size_t const buffSize) {
auto json = reinterpret_cast<const char*>(buff); auto json = reinterpret_cast<const char*>(buff);
auto jsonLen = ox::strnlen(json, buffSize); auto jsonLen = ox::strnlen_s(json, buffSize);
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw ox::Exception(1, "Could not parse JSON"); throw Exception(1, "Could not parse JSON");
} }
} }
OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) { OrganicClawReader::OrganicClawReader(CString const json, size_t const jsonLen) {
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw ox::Exception(1, "Could not parse JSON"); throw Exception(1, "Could not parse JSON");
} }
} }
OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept: OrganicClawReader::OrganicClawReader(Json::Value json, int const unionIdx) noexcept:
m_json(std::move(json)), m_json(std::move(json)),
m_unionIdx(unionIdx) { m_unionIdx(unionIdx) {
} }
Error OrganicClawReader::field(const char *key, bool *val) noexcept { Error OrganicClawReader::field(CString const key, bool *val) noexcept {
auto err = ox::Error(0); Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@@ -45,16 +45,16 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} else if (jv.isBool()) { } else if (jv.isBool()) {
*val = jv.asBool(); *val = jv.asBool();
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(CString const key, char *val, size_t const buffLen) noexcept {
auto err = ox::Error(0); Error err{};
const char *begin = nullptr, *end = nullptr; CString begin = nullptr, end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
if (jv.empty()) { if (jv.empty()) {
@@ -64,25 +64,25 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
} }
} else if (jv.isString()) { } else if (jv.isString()) {
jv.getString(&begin, &end); jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<size_t>(end - begin);
auto data = val; auto data = val;
if (strSize >= buffLen) { if (strSize >= buffLen) {
err = ox::Error(2, "String size exceeds capacity of destination"); err = Error(2, "String size exceeds capacity of destination");
} else { } else {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); memcpy(data, begin, static_cast<size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} }
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { Error OrganicClawReader::fieldCString(CString const key, char **val) noexcept {
auto err = ox::Error(0); Error err{};
const char *begin = nullptr, *end = nullptr; CString begin = nullptr, end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
auto &data = *val; auto &data = *val;
if (targetValid()) { if (targetValid()) {
@@ -92,22 +92,22 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
} }
} else if (jv.isString()) { } else if (jv.isString()) {
jv.getString(&begin, &end); jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<size_t>(end - begin);
safeDelete(*val); safeDelete(*val);
*val = new char[strSize + 1]; *val = new char[strSize + 1];
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); memcpy(data, begin, static_cast<size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(CString const key, char **val, size_t const buffLen) noexcept {
auto err = ox::Error(0); Error err{};
const char *begin = nullptr, *end = nullptr; CString begin = nullptr, end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
if (jv.empty()) { if (jv.empty()) {
@@ -117,29 +117,29 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
} }
} else if (jv.isString()) { } else if (jv.isString()) {
jv.getString(&begin, &end); jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<size_t>(end - begin);
auto data = val; auto data = val;
if (strSize >= buffLen) { if (strSize >= buffLen) {
safeDelete(*val); safeDelete(*val);
*val = new char[strSize + 1]; *val = new char[strSize + 1];
} }
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); memcpy(data, begin, static_cast<size_t>(strSize));
data[strSize] = nullptr; data[strSize] = nullptr;
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
Error OrganicClawReader::field(const char *key, UUID *val) noexcept { Error OrganicClawReader::field(CString const key, UUID *val) noexcept {
UUIDStr str; UUIDStr str;
OX_RETURN_ERROR(field(key, &str)); OX_RETURN_ERROR(field(key, &str));
return UUID::fromString(str).moveTo(*val); return UUID::fromString(str).moveTo(*val);
} }
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept { Result<size_t> OrganicClawReader::arrayLength(CString const key, bool) noexcept {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
return 0; return 0;
@@ -147,32 +147,32 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
if (jv.isArray()) { if (jv.isArray()) {
return jv.size(); return jv.size();
} }
return ox::Error(1, "Type mismatch"); return Error(1, "Type mismatch");
} }
[[nodiscard]] [[nodiscard]]
std::size_t OrganicClawReader::stringLength(const char *key) noexcept { size_t OrganicClawReader::stringLength(CString const key) noexcept {
const char *begin = nullptr, *end = nullptr; CString begin = nullptr, end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
return 0; return 0;
} }
if (jv.isString()) { if (jv.isString()) {
jv.getString(&begin, &end); jv.getString(&begin, &end);
return static_cast<std::size_t>(end - begin); return static_cast<size_t>(end - begin);
} }
return ox::Error(1, "Type mismatch"); return Error(1, "Type mismatch");
} }
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept { OrganicClawReader OrganicClawReader::child(CString const key, int const unionIdx) noexcept {
return OrganicClawReader(value(key), unionIdx); return OrganicClawReader(value(key), unionIdx);
} }
bool OrganicClawReader::fieldPresent(const char *key) noexcept { bool OrganicClawReader::fieldPresent(CString const key) noexcept {
return !m_json[key].empty(); return !m_json[key].empty();
} }
int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u) const noexcept { int OrganicClawReader::whichFieldPresent(CString const name, ModelUnion const &u) const noexcept {
const auto &obj = m_json[name]; const auto &obj = m_json[name];
if (!obj.isObject()) { if (!obj.isObject()) {
return -1; return -1;
@@ -184,7 +184,7 @@ int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u)
return u.getKeyIdx(keys.front().c_str()); return u.getKeyIdx(keys.front().c_str());
} }
Json::Value &OrganicClawReader::value(const char *key) noexcept { Json::Value &OrganicClawReader::value(CString const key) noexcept {
if (m_json.isArray()) { if (m_json.isArray()) {
return m_json[m_fieldIt]; return m_json[m_fieldIt];
} else { } else {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,7 +8,11 @@
#pragma once #pragma once
#include <ox/std/def.hpp>
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
#include <json/json.h> #include <json/json.h>
OX_ALLOW_UNSAFE_BUFFERS_END
#include <ox/model/fieldcounter.hpp> #include <ox/model/fieldcounter.hpp>
#include <ox/model/modelhandleradaptor.hpp> #include <ox/model/modelhandleradaptor.hpp>
@@ -30,75 +34,76 @@ class OrganicClawReader {
private: private:
Json::Value m_json; Json::Value m_json;
Json::ArrayIndex m_fieldIt = 0; Json::ArrayIndex m_fieldIt = 0;
int m_unionIdx = -1; int const m_unionIdx = -1;
public: public:
OrganicClawReader() noexcept = default; OrganicClawReader() noexcept = default;
OrganicClawReader(const uint8_t *buff, std::size_t buffSize); OrganicClawReader(uint8_t const *buff, size_t buffSize);
OrganicClawReader(const char *json, std::size_t buffSize); OrganicClawReader(CString json, size_t buffSize);
explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept; explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept;
Error field(const char *key, bool *val) noexcept; Error field(CString key, bool *val) noexcept;
// array handler // array handler
template<typename T> template<typename T>
Error field(const char *key, T *val, std::size_t len) noexcept; Error field(CString key, T *val, size_t len) noexcept;
template<typename T> template<typename T>
Error field(const char*, HashMap<String, T> *val) noexcept; Error field(CString, HashMap<String, T> *val) noexcept;
template<typename T> template<typename T>
Error field(const char *key, T *val) noexcept; Error field(CString key, T *val) noexcept;
template<typename U, bool force = false> template<typename U, bool force = false>
Error field(const char *key, UnionView<U, force> val) noexcept; Error field(CString key, UnionView<U, force> val) noexcept;
template<std::size_t L> template<size_t L>
Error field(const char *key, BasicString<L> *val) noexcept; Error field(CString key, BasicString<L> *val) noexcept;
template<std::size_t L> template<size_t L>
Error field(const char *key, IString<L> *val) noexcept; Error field(CString key, IString<L> *val) noexcept;
Error fieldCString(const char *key, char *val, std::size_t buffLen) noexcept; Error fieldCString(CString key, char *val, size_t buffLen) noexcept;
Error fieldCString(const char *key, char **val) noexcept; Error fieldCString(CString key, char **val) noexcept;
Error fieldCString(const char *key, char **val, std::size_t buffLen) noexcept; Error fieldCString(CString key, char **val, size_t buffLen) noexcept;
Error field(const char *key, UUID *val) noexcept; Error field(CString key, UUID *val) noexcept;
/** /**
* Reads an array length from the current location in the buffer. * Reads an array length from the current location in the buffer.
* @param key
* @param pass indicates that the parsing should iterate past the array length * @param pass indicates that the parsing should iterate past the array length
*/ */
Result<std::size_t> arrayLength(const char *key, bool pass = true) noexcept; Result<size_t> arrayLength(CString key, bool pass = true) noexcept;
/** /**
* Reads an string length from the current location in the buffer. * Reads an string length from the current location in the buffer.
*/ */
[[nodiscard]] [[nodiscard]]
std::size_t stringLength(const char *name) noexcept; size_t stringLength(CString key) noexcept;
template<typename T = void> template<typename T = void>
constexpr ox::Error setTypeInfo() noexcept { constexpr Error setTypeInfo() noexcept {
return {}; return {};
} }
template<typename T = void> template<typename T = void>
constexpr ox::Error setTypeInfo(const char*) noexcept { constexpr Error setTypeInfo(CString) noexcept {
return {}; return {};
} }
template<typename T = void> template<typename T = void>
constexpr ox::Error setTypeInfo(const char*, int, const Vector<String>& = {}) noexcept { constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}) noexcept {
return {}; return {};
} }
template<typename T = void> template<typename T = void>
constexpr ox::Error setTypeInfo(const char*, int, const Vector<String>& = {}, std::size_t = {}) noexcept { constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}, size_t = {}) noexcept {
return {}; return {};
} }
@@ -106,16 +111,16 @@ class OrganicClawReader {
* Returns a OrganicClawReader to parse a child object. * Returns a OrganicClawReader to parse a child object.
*/ */
[[nodiscard]] [[nodiscard]]
OrganicClawReader child(const char *key, int unionIdx = -1) noexcept; OrganicClawReader child(CString key, int unionIdx = -1) noexcept;
// compatibility stub // compatibility stub
constexpr void nextField() noexcept {} constexpr void nextField() noexcept {}
[[nodiscard]] [[nodiscard]]
bool fieldPresent(const char *key) noexcept; bool fieldPresent(CString key) noexcept;
[[nodiscard]] [[nodiscard]]
int whichFieldPresent(const char *name, const ModelUnion &u) const noexcept; int whichFieldPresent(CString name, const ModelUnion &u) const noexcept;
[[nodiscard]] [[nodiscard]]
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
@@ -124,7 +129,7 @@ class OrganicClawReader {
private: private:
[[nodiscard]] [[nodiscard]]
Json::Value &value(const char *key) noexcept; Json::Value &value(CString key) noexcept;
[[nodiscard]] [[nodiscard]]
bool targetValid() const noexcept; bool targetValid() const noexcept;
@@ -132,98 +137,102 @@ class OrganicClawReader {
}; };
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept { Error OrganicClawReader::field(CString key, T *val) noexcept {
auto err = ox::Error(0); Error err{};
try { try {
if constexpr (is_integer_v<T>) { if constexpr (is_integer_v<T>) {
if (targetValid()) { if (targetValid()) {
auto const&jv = value(key); auto const &jv = value(key);
auto const rightType = sizeof(T) == 8 ? auto const rightType = sizeof(T) == 8 ?
(ox::is_signed_v<T> ? jv.isInt64() : jv.isUInt64()) : (is_signed_v<T> ? jv.isInt64() : jv.isUInt64()) :
(ox::is_signed_v<T> ? jv.isInt() : jv.isUInt()); (is_signed_v<T> ? jv.isInt() : jv.isUInt());
if (jv.empty()) { if (jv.empty()) {
*val = 0; *val = 0;
} else if (rightType) { } else if (rightType) {
*val = static_cast<T>(jv.asUInt()); if constexpr(is_signed_v<T>) {
*val = static_cast<T>(jv.asInt64());
} else {
*val = static_cast<T>(jv.asUInt64());
}
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error{1, "Type mismatch"};
} }
} }
} else if constexpr (isVector_v<T>) { } else if constexpr (isVector_v<T>) {
const auto&srcVal = value(key); auto const &srcVal = value(key);
const auto srcSize = srcVal.size(); auto const srcSize = srcVal.size();
OX_RETURN_ERROR(ox::resizeVector(*val, srcSize)); OX_RETURN_ERROR(resizeVector(*val, srcSize));
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) { } else if constexpr (isArray_v<T>) {
const auto&srcVal = value(key); auto const &srcVal = value(key);
const auto srcSize = srcVal.size(); auto const srcSize = srcVal.size();
if (srcSize > val->size()) { if (srcSize > val->size()) {
err = ox::Error(1, "Input array is too long"); err = Error{1, "Input array is too long"};
} else { } else {
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} }
} else if (targetValid()) { } else if (targetValid()) {
const auto&jv = value(key); auto const &jv = value(key);
if (jv.empty() || jv.isObject()) { if (jv.empty() || jv.isObject()) {
auto reader = child(key); auto reader = child(key);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(reader);
err = model(&handler, val); err = model(&handler, val);
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error{1, "Type mismatch"};
} }
} }
} catch (Json::LogicError const&) { } catch (Json::LogicError const &e) {
err = ox::Error(1, "error reading JSON data"); err = Error{1, "error reading JSON data"};
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
template<typename U, bool force> template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawReader::field(CString const key, UnionView<U, force> val) noexcept {
auto err = ox::Error(0); Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); auto const &jv = value(key);
if (jv.empty() || jv.isObject()) { if (jv.empty() || jv.isObject()) {
auto reader = child(key, val.idx()); auto reader = child(key, val.idx());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(reader);
err = model(&handler, val.get()); err = model(&handler, val.get());
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error{1, "Type mismatch"};
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
template<std::size_t L> template<size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { Error OrganicClawReader::field(CString const key, BasicString<L> *val) noexcept {
auto err = ox::Error(0); Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); auto const &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
*val = BasicString<L>{}; *val = BasicString<L>{};
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error{1, "Type mismatch"};
} }
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
} }
template<std::size_t L> template<size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { Error OrganicClawReader::field(CString const key, IString<L> *val) noexcept {
auto err = ox::Error(0); Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); auto const &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
*val = IString<L>{}; *val = IString<L>{};
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = ox::Error(1, "Type mismatch"); err = Error{1, "Type mismatch"};
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -232,60 +241,60 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
// array handler // array handler
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept { Error OrganicClawReader::field(CString const key, T *val, size_t valLen) noexcept {
const auto &srcVal = value(key); auto const &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) { if (!srcVal.isNull() && !srcVal.isArray()) {
return ox::Error(1, "Type mismatch"); return Error{1, "Type mismatch"};
} }
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
if (srcSize > valLen) { if (srcSize > valLen) {
return ox::Error(1); return Error{1};
} }
OrganicClawReader r(srcVal); OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i])); OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept { Error OrganicClawReader::field(CString const key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key); auto const &srcVal = value(key);
if (!srcVal.isObject()) { if (!srcVal.isObject()) {
return ox::Error(1, "Type mismatch"); return Error{1, "Type mismatch"};
} }
auto keys = srcVal.getMemberNames(); auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
OrganicClawReader r(srcVal); OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
const auto k = keys[i].c_str(); auto const k = keys[i].c_str();
OX_RETURN_ERROR(handler.field(k, &val->operator[](k))); OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
} }
return ox::Error(0); return {};
} }
Error readOC(BufferView buff, auto &val) noexcept { Error readOC(BufferView const buff, auto &val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors. // OrganicClawReader constructor can throw, but readOC should return its errors.
try { try {
Json::Value doc; Json::Value doc;
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = UPtr<Json::CharReader>(parserBuilder.newCharReader());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) { if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(1, "Could not parse JSON"); return Error{1, "Could not parse JSON"};
} }
OrganicClawReader reader(buff.data(), buff.size()); OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(reader);
return model(&handler, &val); return model(&handler, &val);
} catch (const Error &err) { } catch (Error const &err) {
return err; return err;
} catch (...) { } catch (...) {
return ox::Error(1, "Unknown Error"); return Error{1, "Unknown Error"};
} }
} }
@@ -297,8 +306,8 @@ Result<T> readOC(BufferView buff) noexcept {
} }
template<typename T> template<typename T>
Result<T> readOC(ox::StringView json) noexcept { Result<T> readOC(StringViewCR json) noexcept {
return readOC<T>(ox::BufferView{json.data(), json.len()}); return readOC<T>(BufferView{json.data(), json.size()});
} }
} }

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,29 +10,29 @@
namespace ox { namespace ox {
OrganicClawWriter::OrganicClawWriter(int unionIdx) noexcept: m_unionIdx(unionIdx) { OrganicClawWriter::OrganicClawWriter(int const unionIdx) noexcept: m_unionIdx(unionIdx) {
} }
OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept: OrganicClawWriter::OrganicClawWriter(Json::Value json, int const unionIdx) noexcept:
m_json(std::move(json)), m_json(std::move(json)),
m_unionIdx(unionIdx) { m_unionIdx(unionIdx) {
} }
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, int len) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const *val, int const len) noexcept {
if (targetValid() && len) { if (targetValid() && len) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const *val) noexcept {
return fieldCString(key, const_cast<const char**>(val), static_cast<int>(ox::strlen(val))); return fieldCString(key, const_cast<const char**>(val), static_cast<int>(ox::strlen(val)));
} }
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept { Error OrganicClawWriter::field(const char *key, UUID const *uuid) noexcept {
const auto uuidStr = uuid->toString(); const auto uuidStr = uuid->toString();
if (targetValid() && uuidStr.len()) { if (targetValid() && uuidStr.size()) {
value(key) = uuidStr.c_str(); value(key) = uuidStr.c_str();
} }
++m_fieldIt; ++m_fieldIt;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,7 +8,11 @@
#pragma once #pragma once
#include <ox/std/def.hpp>
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
#include <json/json.h> #include <json/json.h>
OX_ALLOW_UNSAFE_BUFFERS_END
#include <ox/model/fieldcounter.hpp> #include <ox/model/fieldcounter.hpp>
#include <ox/model/modelhandleradaptor.hpp> #include <ox/model/modelhandleradaptor.hpp>
@@ -24,85 +28,85 @@ namespace ox {
class OrganicClawWriter { class OrganicClawWriter {
friend Result<ox::Buffer> writeOC(const auto &val) noexcept; friend Result<Buffer> writeOC(const auto &val) noexcept;
friend Result<ox::String> writeOCString(const auto &val) noexcept; friend Result<String> writeOCString(const auto &val) noexcept;
protected: protected:
Json::Value m_json{Json::Value(Json::objectValue)}; Json::Value m_json{Json::Value(Json::objectValue)};
Json::ArrayIndex m_fieldIt = 0; Json::ArrayIndex m_fieldIt = 0;
int m_unionIdx = -1; int const m_unionIdx = -1;
public: public:
explicit OrganicClawWriter(int unionIdx = -1) noexcept; explicit OrganicClawWriter(int unionIdx = -1) noexcept;
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept; explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
Error field(const char *key, const int8_t *val) noexcept { Error field(CString const key, int8_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const int16_t *val) noexcept { Error field(CString const key, int16_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const int32_t *val) noexcept { Error field(CString const key, int32_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const int64_t *val) noexcept { Error field(CString const key, int64_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const uint8_t *val) noexcept { Error field(CString const key, uint8_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const uint16_t *val) noexcept { Error field(CString const key, uint16_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const uint32_t *val) noexcept { Error field(CString const key, uint32_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(const char *key, const uint64_t *val) noexcept { Error field(CString const key, uint64_t const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error field(char const*key, bool const*val) noexcept { Error field(char const*key, bool const *val) noexcept {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
@@ -114,12 +118,12 @@ class OrganicClawWriter {
Error field(char const*, UnionView<U, force> val) noexcept; Error field(char const*, UnionView<U, force> val) noexcept;
template<typename T> template<typename T>
Error field(char const*key, HashMap<String, T> const*val) noexcept { Error field(char const*key, HashMap<String, T> const *val) noexcept {
if (targetValid()) { if (targetValid()) {
const auto &keys = val->keys(); const auto &keys = val->keys();
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
for (std::size_t i = 0; i < keys.size(); ++i) { for (size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
if (k) [[likely]] { if (k) [[likely]] {
OX_REQUIRE_M(value, val->at(k)); OX_REQUIRE_M(value, val->at(k));
@@ -132,49 +136,49 @@ class OrganicClawWriter {
return {}; return {};
} }
template<std::size_t L> template<size_t L>
Error field(char const*key, IString<L> const*val) noexcept { Error field(char const*key, IString<L> const *val) noexcept {
if (targetValid() && val->len()) { if (targetValid() && val->size()) {
value(key) = val->c_str(); value(key) = val->c_str();
} }
++m_fieldIt; ++m_fieldIt;
return {}; return {};
} }
template<std::size_t L> template<size_t L>
Error field(char const*key, BasicString<L> const*val) noexcept { Error field(char const*key, BasicString<L> const *val) noexcept {
if (targetValid() && val->len()) { if (targetValid() && val->size()) {
value(key) = val->c_str(); value(key) = val->c_str();
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Error fieldCString(const char*, const char *const*val, int len) noexcept; Error fieldCString(CString, CString const *val, int len) noexcept;
Error fieldCString(const char *name, const char *const*val) noexcept; Error fieldCString(CString name, CString const*val) noexcept;
Error field(const char *key, const UUID *uuid) noexcept; Error field(CString key, UUID const *uuid) noexcept;
template<typename T> template<typename T>
Error field(const char*, const T *val, std::size_t len) noexcept; Error field(CString, T const *val, size_t len) noexcept;
template<typename T> template<typename T>
Error field(const char*, const T *val) noexcept; Error field(CString, T const *val) noexcept;
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion) noexcept { int = T::TypeVersion) noexcept {
return {}; return {};
} }
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr Error setTypeInfo(
const char*, const char*,
int, int,
const Vector<String>&, Vector<String> const&,
std::size_t) noexcept { size_t) noexcept {
return {}; return {};
} }
@@ -190,16 +194,16 @@ class OrganicClawWriter {
} }
[[nodiscard]] [[nodiscard]]
Json::Value &value(const char *key) noexcept; Json::Value &value(CString key) noexcept;
}; };
template<typename T> template<typename T>
Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) noexcept { Error OrganicClawWriter::field(CString key, T const *val, size_t const len) noexcept {
if (targetValid() && len) { if (targetValid() && len) {
OrganicClawWriter w((Json::Value(Json::arrayValue))); OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
for (std::size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i])); OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
@@ -207,70 +211,74 @@ OX_ALLOW_UNSAFE_BUFFERS_END
value(key) = w.m_json; value(key) = w.m_json;
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
template<typename T> template<typename T>
Error OrganicClawWriter::field(const char *key, const T *val) noexcept { Error OrganicClawWriter::field(CString key, T const *val) noexcept {
if constexpr(is_integer_v<T>) { if constexpr(is_integer_v<T>) {
if (targetValid() && (*val || m_json.isArray())) { if (targetValid() && (*val || m_json.isArray())) {
// the int type needs to be normalized because jsoncpp doesn't // the int type needs to be normalized because jsoncpp doesn't
// factor in every permutation unsigned long, etc. // factor in every permutation unsigned long, etc.
if constexpr(ox::is_signed_v<T>) { if constexpr(is_signed_v<T>) {
value(key) = static_cast<ox::Int<8 * sizeof(*val)>>(*val); value(key) = static_cast<Int<8 * sizeof(*val)>>(*val);
} else { } else {
value(key) = static_cast<ox::Uint<8 * sizeof(*val)>>(*val); value(key) = static_cast<Uint<8 * sizeof(*val)>>(*val);
} }
} }
} else if constexpr(isVector_v<T> || isArray_v<T>) { } else if constexpr(isVector_v<T> || isArray_v<T>) {
return field(key, val->data(), val->size()); return field(key, val->data(), val->size());
} else if (val && targetValid()) { } else if (val && targetValid()) {
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
OX_RETURN_ERROR(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
if (!w.m_json.empty() || m_json.isArray()) { if (!w.m_json.empty() || m_json.isArray()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
template<typename U, bool force> template<typename U, bool force>
Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawWriter::field(CString key, UnionView<U, force> val) noexcept {
if (targetValid()) { if (targetValid()) {
OrganicClawWriter w(val.idx()); OrganicClawWriter w(val.idx());
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
OX_RETURN_ERROR(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return ox::Error(0); return {};
} }
Result<ox::Buffer> writeOC(const auto &val) noexcept { Result<Buffer> writeOC(auto const &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
OX_RETURN_ERROR(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); auto const str = Json::writeString(jsonBuilder, writer.m_json);
Result<Buffer> buff; Result<Buffer> buff;
buff.value.resize(str.size() + 1); buff.value.resize(str.size() + 1);
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
memcpy(buff.value.data(), str.data(), str.size() + 1); memcpy(buff.value.data(), str.data(), str.size() + 1);
OX_ALLOW_UNSAFE_BUFFERS_END
return buff; return buff;
} }
Result<ox::String> writeOCString(const auto &val) noexcept { Result<String> writeOCString(auto const &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
OX_RETURN_ERROR(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); auto const str = Json::writeString(jsonBuilder, writer.m_json);
Result<ox::String> buff; Result<String> buff;
buff.value.resize(str.size()); buff.value.resize(str.size());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
memcpy(buff.value.data(), str.data(), str.size() + 1); memcpy(buff.value.data(), str.data(), str.size() + 1);
OX_ALLOW_UNSAFE_BUFFERS_END
return buff; return buff;
} }

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -74,7 +74,7 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
const Preloader &operator=(const Preloader &src) = delete; const Preloader &operator=(const Preloader &src) = delete;
const Preloader &operator=(Preloader &&src) = delete; const Preloader &operator=(Preloader &&src) = delete;
constexpr static ox::Result<ox::UniquePtr<Preloader>> make(ox::ios_base::seekdir anchor = ox::ios_base::cur, constexpr static ox::Result<ox::UPtr<Preloader>> make(ox::ios_base::seekdir anchor = ox::ios_base::cur,
std::size_t sz = 0) noexcept; std::size_t sz = 0) noexcept;
template<typename T> template<typename T>
@@ -141,9 +141,9 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
}; };
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Result<ox::UniquePtr<Preloader<PlatSpec>>> constexpr ox::Result<ox::UPtr<Preloader<PlatSpec>>>
Preloader<PlatSpec>::make(ox::ios_base::seekdir anchor, std::size_t sz) noexcept { Preloader<PlatSpec>::make(ox::ios_base::seekdir anchor, std::size_t sz) noexcept {
auto p = ox::UniquePtr<Preloader>(new Preloader); auto p = ox::UPtr<Preloader>(new Preloader);
if (const auto err = p->m_writer.seekp(0, anchor)) { if (const auto err = p->m_writer.seekp(0, anchor)) {
return {std::move(p), err}; return {std::move(p), err};
} }

View File

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

View File

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

View File

@@ -33,6 +33,7 @@ add_library(
concepts.cpp concepts.cpp
fmt.cpp fmt.cpp
heapmgr.cpp heapmgr.cpp
istreamreader.cpp
math.cpp math.cpp
memops.cpp memops.cpp
random.cpp random.cpp
@@ -109,6 +110,7 @@ install(
error.hpp error.hpp
fmt.hpp fmt.hpp
hardware.hpp hardware.hpp
hash.hpp
hashmap.hpp hashmap.hpp
heapmgr.hpp heapmgr.hpp
ignore.hpp ignore.hpp

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,13 +9,25 @@
#pragma once #pragma once
#include "def.hpp" #include "def.hpp"
#include "error.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename It, typename T> template<typename It, typename T>
constexpr It find(It begin, It end, const T &value) { constexpr ox::Result<size_t> findIdx(It begin, It end, T const&value) {
auto it = begin;
for (; it != end; ++it) {
if (*it == value) {
return it.offset();
}
}
return ox::Error{1, "item not found"};
}
template<typename It, typename T>
constexpr It find(It begin, It end, T const&value) {
for (; begin != end; ++begin) { for (; begin != end; ++begin) {
if (*begin == value) { if (*begin == value) {
return begin; return begin;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,20 +15,24 @@
namespace ox { namespace ox {
class AnyPtr { namespace detail {
template<bool unique>
class AnyPtrT {
private: private:
struct WrapBase { struct WrapBase {
virtual constexpr ~WrapBase() = default; virtual constexpr ~WrapBase() = default;
virtual constexpr WrapBase *copyTo(ox::Span<char> s) noexcept = 0; virtual constexpr WrapBase *copyTo(Span<char> s) const noexcept = 0;
virtual constexpr operator bool() const noexcept = 0; virtual constexpr operator bool() const noexcept = 0;
virtual void free() noexcept = 0;
}; };
template<typename T> template<typename T>
struct Wrap: public WrapBase { struct Wrap final: WrapBase {
T *data{}; T *data{};
constexpr Wrap(T *pData) noexcept: data(pData) { explicit constexpr Wrap(T *pData) noexcept: data(pData) {
} }
constexpr WrapBase *copyTo(ox::Span<char> s) noexcept override { constexpr WrapBase *copyTo(Span<char> s) const noexcept override {
oxAssert(s.size() >= sizeof(Wrap), "too small buffer"); oxAssert(s.size() >= sizeof(Wrap), "too small buffer");
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
return new Wrap(data); return new Wrap(data);
@@ -39,71 +43,160 @@ class AnyPtr {
constexpr operator bool() const noexcept override { constexpr operator bool() const noexcept override {
return data != nullptr; return data != nullptr;
} }
constexpr void free() noexcept override {
safeDelete(data);
data = {};
}
}; };
WrapBase *m_wrapPtr{}; union {
ox::Array<char, sizeof(Wrap<void*>)> m_wrapData; WrapBase *m_wrapPtr{};
AllocAlias<Wrap<void*>> m_wrapData;
} m_data;
public: public:
constexpr AnyPtr() noexcept = default; constexpr AnyPtrT() noexcept = default;
template<typename T> template<typename T>
constexpr AnyPtr(T *ptr) noexcept { constexpr AnyPtrT(T *ptr) noexcept {
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
m_wrapPtr = new Wrap(ptr); setWrapPtr(new Wrap<T>(ptr));
} else { } else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); new(m_data.m_wrapData.data()) Wrap<T>(ptr);
} }
} }
constexpr AnyPtr(AnyPtr const&other) noexcept { constexpr AnyPtrT(AnyPtrT const &other) noexcept requires(!unique) {
if (other) { if (other) {
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData); setWrapPtr(other.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
} }
} }
constexpr ~AnyPtr() noexcept { constexpr AnyPtrT(AnyPtrT &&other) noexcept {
if (other) {
setWrapPtr(other.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
if (std::is_constant_evaluated()) {
ox::safeDelete(m_data.m_wrapPtr);
}
m_data.m_wrapData = {};
}
}
constexpr ~AnyPtrT() noexcept {
if constexpr(unique) {
free();
}
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); ox::safeDelete(m_data.m_wrapPtr);
} }
} }
template<typename T> template<typename T>
constexpr AnyPtr &operator=(T *ptr) noexcept { constexpr AnyPtrT &operator=(T *ptr) noexcept {
if constexpr(unique) {
free();
} else if (std::is_constant_evaluated()) {
ox::safeDelete(m_data.m_wrapPtr);
}
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); setWrapPtr(new Wrap(ptr));
m_wrapPtr = new Wrap(ptr);
} else { } else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); new(m_data.m_wrapData.data()) Wrap(ptr);
} }
return *this; return *this;
} }
constexpr AnyPtr &operator=(AnyPtr const&ptr) noexcept { constexpr AnyPtrT &operator=(AnyPtrT const &ptr) noexcept requires(!unique) {
if (this != &ptr) { if (this != &ptr) {
if (ptr) { if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); ox::safeDelete(m_data.m_wrapPtr);
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData); }
if (std::is_constant_evaluated()) {
if (ptr) {
ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff);
}
} else { } else {
m_wrapPtr = nullptr; if (ptr) {
setWrapPtr(ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
} else {
setWrapPtr(nullptr);
}
}
}
return *this;
}
constexpr AnyPtrT &operator=(AnyPtrT &&ptr) noexcept {
if (this != &ptr) {
if constexpr(unique) {
free();
} else if (std::is_constant_evaluated()) {
ox::safeDelete(m_data.m_wrapPtr);
}
if (ptr) {
setWrapPtr(ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
if (std::is_constant_evaluated()) {
ox::safeDelete(ptr.m_data.m_wrapPtr);
setWrapPtr(nullptr);
}
} else {
m_data = {};
} }
} }
return *this; return *this;
} }
constexpr operator bool() const noexcept { constexpr operator bool() const noexcept {
return m_wrapPtr && *m_wrapPtr; return getWrapPtr() && *getWrapPtr();
}
constexpr void free() noexcept {
if (auto p = getWrapPtr()) {
p->free();
}
if (std::is_constant_evaluated()) {
ox::safeDelete(m_data.m_wrapPtr);
}
m_data.m_wrapData = {};
} }
template<typename T> template<typename T>
[[nodiscard]] [[nodiscard]]
constexpr T *get() const noexcept { constexpr T *get() const noexcept {
#ifdef OX_BARE_METAL if constexpr(defines::HasRTTI) {
return static_cast<Wrap<T>*>(m_wrapPtr)->data; return dynamic_cast<Wrap<T> const*>(getWrapPtr())->data;
#else }
return dynamic_cast<Wrap<T>*>(m_wrapPtr)->data; return static_cast<Wrap<T> const*>(getWrapPtr())->data;
#endif
} }
private:
constexpr void setWrapPtr(WrapBase *ptr) noexcept {
if (std::is_constant_evaluated()) {
m_data.m_wrapPtr = ptr;
}
}
constexpr WrapBase *getWrapPtr() noexcept {
if (std::is_constant_evaluated()) {
return m_data.m_wrapPtr;
} else {
return std::launder(reinterpret_cast<WrapBase*>(m_data.m_wrapData.data()));
}
}
constexpr WrapBase const *getWrapPtr() const noexcept {
if (std::is_constant_evaluated()) {
return m_data.m_wrapPtr;
} else {
return std::launder(reinterpret_cast<WrapBase const*>(m_data.m_wrapData.data()));
}
}
}; };
}
using AnyPtr = detail::AnyPtrT<false>;
using UAnyPtr = detail::AnyPtrT<true>;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -181,13 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept { constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow"); boundsCheck(i, size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept { constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow"); boundsCheck(i, size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }

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