Compare commits

..

462 Commits

Author SHA1 Message Date
gary 17c9f673bd [studio] Fix navigate back not to iterate on the first item twice
Build / build (push) Successful in 1m29s
2025-08-09 15:15:54 -05:00
gary 870fb9c6e3 [nostalgia/studio] Set version to d2025.07.0
Build / build (push) Successful in 1m17s
2025-07-31 22:07:22 -05:00
gary 31b39982c5 [keel] Fix AssetRef to call incRef on initial creation of ref, not just copy
Build / build (push) Successful in 1m18s
2025-07-31 22:06:52 -05:00
gary 5476417be2 [nostalgia] Add release notes for d2025.07.0
Build / build (push) Successful in 1m18s
2025-07-31 01:05:29 -05:00
gary e03be694c2 Merge commit 'b67b95767b7bfcd5f618ebc8e14ddbc83edcbe36'
Build / build (push) Successful in 1m37s
2025-07-31 00:41:06 -05:00
gary 490c0368bc [nostalgia/gfx] Add lists for file extensions 2025-07-31 00:39:55 -05:00
gary a24fc407c5 [ox/std] Fix MSVC build 2025-07-31 00:38:26 -05:00
gary e38b85b4f4 [studio] Eliminate redundant serialization and deserialization
Build / build (push) Successful in 1m42s
2025-07-30 21:48:44 -05:00
gary f7c3c02c4c Merge commit '1bfb7f99c215e2c74556bd3281f44962b8faaa96'
Build / build (push) Successful in 1m35s
2025-07-30 00:42:42 -05:00
gary 8f0f1fea39 [nostalgia/gfx/studio] Make editors use Project::loadObj for their primary assets 2025-07-30 00:37:59 -05:00
gary 2f36a3f6f0 [studio] Add File -> Reload Project menu item 2025-07-30 00:37:23 -05:00
gary 07e5bf9054 [keel] Make keel attempt to delete all existing assets when FS is changed 2025-07-30 00:36:56 -05:00
gary aacff3daf9 [ox/std] Fix UPtr::reset to conform to unique_ptr::reset 2025-07-30 00:29:34 -05:00
gary e27eee50f0 [teagba] Add set and scroll background offset functions
Build / build (push) Successful in 1m15s
2025-07-29 00:34:41 -05:00
gary fd610454d6 [nostalgia/gfx] Fix compiler warning
Build / build (push) Failing after 24s
2025-07-29 00:30:17 -05:00
gary e61d4647b5 [nostalgia/gfx] Fix BG tilesheet loading, add background offset functions
Build / build (push) Failing after 20s
2025-07-28 21:54:50 -05:00
gary c275c5f5e6 [hull] Disable building hull for now
Build / build (push) Successful in 1m22s
2025-07-26 18:33:24 -05:00
gary fbf49ba511 [ox/std] Add pre- and post-increment operators to Span
Build / build (push) Failing after 8s
2025-07-26 18:31:55 -05:00
gary 92f74b27d1 [ox/std] Add null check for deallocating in consteval context Vector 2025-07-26 18:31:41 -05:00
gary 934f0c9232 [ox/std] Add beginsWith and endsWith variants that that cingle chars 2025-07-26 18:31:03 -05:00
gary ee9a3e1152 [ox/std] Cleanup 2025-07-26 18:30:12 -05:00
gary 16886cdf1c [hull] Add start on command interpreter 2025-07-26 18:29:51 -05:00
gary 08b9508d83 [ox/std] Give std::ignore a named type 2025-07-26 15:09:10 -05:00
gary 69bd968f98 [nostalgia/player] Fix build
Build / build (push) Successful in 1m28s
2025-07-25 22:54:43 -05:00
gary 4e7dc66610 [nostalgia,olympic] Rename string len() functions to size() 2025-07-25 22:48:08 -05:00
gary bea0cf5a0c [ox/std] Rename string len() functions to size() 2025-07-25 22:47:56 -05:00
gary c7bc2a954f [nostalgia/gfx] Style update
Build / build (push) Successful in 1m15s
2025-07-24 21:35:21 -05:00
gary 7372036a0a [nostalgia/gfx] Add function missing from header
Build / build (push) Successful in 1m14s
2025-07-24 21:25:26 -05:00
gary 7461d832b6 [nostalgia/gfx/studio,studio] Fix CLI tool output to only show usage if no args given
Build / build (push) Successful in 1m19s
2025-07-24 21:17:58 -05:00
gary 6052798fea Merge commit 'dceeaaa9302b7e9ce85fa773fc187bc593f3c93c'
Build / build (push) Successful in 1m16s
2025-07-24 01:58:27 -05:00
gary fae1e73e54 [nostalgia/gfx] Make getSubSheet check root subsheet name
Build / build (push) Successful in 1m17s
2025-07-24 01:54:06 -05:00
gary 51f2905c9c [nostalgia/gfx/studio] Make TileSheetEditor use export-tilesheet functions for export, fix exporting Root subsheet
Build / build (push) Successful in 1m18s
2025-07-24 01:45:27 -05:00
gary 0c866d1b96 [studio,nostalgia/gfx] Add system for adding sub-commands in Modules, add export-tilesheet command
Build / build (push) Successful in 1m16s
2025-07-24 01:29:09 -05:00
gary fdf39d1a25 [ox/std] Add Result::transformError 2025-07-24 01:24:11 -05:00
gary a523a75e4b [ox/std] Add missing include to StringParam 2025-07-24 01:23:58 -05:00
gary cdaa64ed3f [ox/clargs] Fix arg parsing for first '-' 2025-07-24 01:23:31 -05:00
gary 801d35c823 [keel] Make type converters work with functions that take const src arg 2025-07-23 00:41:33 -05:00
gary 37b5fcc0f7 [teagba] Put parentheses around all registers
Build / build (push) Successful in 1m18s
2025-07-07 23:36:34 -05:00
gary 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
gary f6ef2b5acb [turbine,nostalgia] Make memory regions cast to bounded ox::Arrays
Build / build (push) Successful in 1m16s
2025-06-29 23:32:36 -05:00
gary bf958a4a6e [teagba] Make memory regions cast to bounded ox::Arrays 2025-06-29 23:32:11 -05:00
gary 6a70e478a6 [nostalgia/gfx] Cleanup 2025-06-29 17:46:13 -05:00
gary 671b8edaad [ox/std] Make StringLiteral constructors consteval
Build / build (push) Successful in 1m29s
2025-06-27 23:05:42 -05:00
gary 952637a1ea Merge commit 'cbf4414fcaf00c00a2abf73b5c04a055180ad980'
Build / build (push) Successful in 1m37s
2025-06-25 21:33:16 -05:00
gary 7569698e95 [nostalgia,studio] Add FileExts_TileSheet const, and corresponding FilePickerPopup constructor 2025-06-25 21:30:49 -05:00
gary 21713ba945 [ox/std] Fix StringLiteral::operator= to work with DevkitARM 2025-06-25 21:29:41 -05:00
gary 73273b6fa7 [nostalgia/gfx] Add isTileSheet function for checking paths against both file extensions 2025-06-25 21:03:45 -05:00
gary 9f040392c7 [olympic,nostalgia] Cleanup style
Build / build (push) Successful in 1m18s
2025-06-24 01:59:22 -05:00
gary f4f7e5d053 Merge commit '9b5f7886cadc5c3dc826d00fa5b2e71696151dfd' 2025-06-23 20:49:01 -05:00
gary f847289bd4 [glutils] Cleanup
Build / build (push) Successful in 1m20s
2025-06-23 01:39:47 -05:00
gary 94b0020d15 [nostalgia,olympic] Cleanup
Build / build (push) Successful in 1m16s
2025-06-23 01:30:33 -05:00
gary c54c0bad38 [teagba] Cleanup
Build / build (push) Successful in 1m20s
2025-06-23 01:03:33 -05:00
gary b9ffae0269 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m18s
2025-06-23 00:47:46 -05:00
gary 003f3e01c6 [nostalgia] Update release notes 2025-06-22 01:01:09 -05:00
gary 9028e74af0 [nostalgia/gfx/studio/tilesheet] Disable paste when nothing is selected 2025-06-22 01:00:56 -05:00
gary f5ccab5f2c [studio] Cleanup 2025-06-21 19:19:39 -05:00
gary c27726a4a9 Merge commit '6bbcae10cc7b21b73171ec0ff196f4baf6304404' 2025-06-21 14:29:47 -05:00
gary 37cfa927d1 [nostalgia/gfx] Address a couple of implicit conversions
Build / build (push) Successful in 1m19s
2025-06-21 14:16:17 -05:00
gary 0efed70b57 [studio] Fix Studio to clear editor pointers when opening a new project
Build / build (push) Successful in 1m20s
2025-06-21 14:12:45 -05:00
gary baf5fa3199 [nostalgia] Move d2025.05.2 release notes to d2025.06.0
Build / build (push) Successful in 1m19s
2025-06-21 08:54:57 -05:00
gary bd24a775b2 Merge commit '7371df429534f264c179684412f6197f7968ebfa' 2025-06-21 08:48:13 -05:00
gary 857587c18b [studio] Cleanup
Build / build (push) Successful in 1m16s
2025-06-21 08:31:27 -05:00
gary eb3d53c955 [studio] Cleanup
Build / build (push) Successful in 1m15s
2025-06-21 08:22:13 -05:00
gary 14d58f3f5b [studio] Fix Navigation shortcuts for non-Mac systems
Build / build (push) Successful in 1m18s
2025-06-21 08:13:14 -05:00
gary 5f2397903a [studio,nostalgia/gfx/studio/tilesheet] Fix copy/cut/paste enablement when there is no selection
Build / build (push) Successful in 2m2s
2025-06-21 00:20:06 -05:00
gary 58e0ecb469 [studio] Make FilePickerPopup accept on double click of a file
Build / build (push) Successful in 1m22s
2025-06-20 23:58:29 -05:00
gary 8838bf420e [studio] Fix to properly copy file that has the same name as deleted file
Build / build (push) Successful in 1m24s
2025-06-20 23:36:20 -05:00
gary bddc544d7c [nostalgia] Update release notes
Build / build (push) Successful in 1m33s
2025-06-20 22:48:39 -05:00
gary a9437191bf [studio,turbine] Add support for mouse back/forward buttons
Build / build (push) Successful in 1m30s
2025-06-20 22:44:09 -05:00
gary 9d8da7ccda [ox/std] Make strToInt return error for empty string
Build / build (push) Has been cancelled
2025-06-20 22:43:33 -05:00
gary 394b568e72 [studio] Add Back/Forward navigation
Build / build (push) Successful in 1m14s
2025-06-20 20:58:42 -05:00
gary 78e9f70db6 [nostalgia] Update release notes
Build / build (push) Successful in 1m20s
2025-06-19 23:58:42 -05:00
gary 12e5623fe6 [ox/logconn] Add exception handling for logger thread
Build / build (push) Successful in 1m18s
2025-06-19 23:56:26 -05:00
gary cfdfb0a8c9 [studio] Fix file deletion to close file even if not active 2025-06-19 23:55:47 -05:00
gary 56e665301f [studio] Cleanup
Build / build (push) Successful in 1m29s
2025-06-19 21:37:57 -05:00
gary 7415ce4bd9 [nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 2m53s
2025-06-17 20:45:24 -05:00
gary 05f42150a1 [olympic] Add new loc command to Makefile
Build / build (push) Successful in 1m19s
2025-06-09 21:29:27 -05:00
gary 8ea2bc6934 [nostalgia] Update release notes
Build / build (push) Successful in 1m16s
2025-06-09 00:22:17 -05:00
gary c780924122 [studio] Add [DEBUG] tag to About in debug builds
Build / build (push) Successful in 1m18s
2025-06-08 21:33:17 -05:00
gary 8c538560ca [nostalgia/gfx/studio/palette] Make RGB key shortcuts work when color channel inputs are focused
Build / build (push) Successful in 1m16s
2025-06-08 17:00:52 -05:00
gary c3e75bdb55 [nostalgia/gfx/studio/tilesheet] Cleanup
Build / build (push) Successful in 1m16s
2025-06-08 16:26:55 -05:00
gary 4419dff299 Merge commit '7688c05bac8c20bc267cae62ec78d55e5d0c493b' 2025-05-31 02:14:15 -05:00
gary e78c405046 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m19s
2025-05-31 01:53:59 -05:00
gary 6b7c5d896e [nostalgia] Update release notes
Build / build (push) Successful in 1m14s
2025-05-31 01:48:07 -05:00
gary a33a73d73a [nostalgia/gfx/studio/palette] Add preview to color editor
Build / build (push) Successful in 1m16s
2025-05-31 01:34:00 -05:00
gary 536999c070 Merge commit '47eee1d56d591e3631d16e95a78ea3629ee312ee' 2025-05-30 23:38:53 -05:00
gary e1cfcc8b5f [nostalgia] Update release notes
Build / build (push) Successful in 1m13s
2025-05-30 23:37:58 -05:00
gary 514cb97835 [nostalgia/gfx/studio/tilesheet] Fix draw command to work on same pixel after switching subsheets 2025-05-30 23:32:51 -05:00
gary 4b5218c4f1 [nostalgia/gfx] Cleanup 2025-05-30 23:32:27 -05:00
gary 2ca77173d3 [keel] Add isUuidUrl function 2025-05-30 23:29:42 -05:00
gary cce5f52f96 [nostalgia/gfx/studio/tilesheet] Fix manual redo of draw actions, fix drawing to pixel 0, 0 as first action
Build / build (push) Successful in 1m15s
2025-05-29 22:12:10 -05:00
gary b55993294a [studio/modlib] Fix headerizeConfigFile to handle slashes in file name
Build / build (push) Successful in 1m12s
2025-05-25 01:20:20 -05:00
gary d8f847d707 [studio/applib] Move popup types into their own directory
Build / build (push) Successful in 1m20s
2025-05-24 15:01:17 -05:00
gary a5535ef59a Merge commit '08236fc790e711afe886b6ef545511d35e4e5c6c' 2025-05-24 01:44:07 -05:00
gary 8419b137e5 [turbine,studio] Fix some popup window resize weirdness, cleanup some function names
Build / build (push) Successful in 1m17s
2025-05-24 01:32:14 -05:00
gary ed1160ec74 [nostalgia] Update release notes
Build / build (push) Successful in 1m14s
2025-05-24 00:50:22 -05:00
gary 1e21778059 [nostalgia/gfx/studio/tilesheet] Ensure config file has a Claw header 2025-05-24 00:48:54 -05:00
gary 78379f58c8 [studio] Add ability to remember recent projects in config 2025-05-24 00:48:10 -05:00
gary 4322f720ba [keel] Fix ox::Result<DstType> convert(Context &ctx, ox::BufferView const&src) 2025-05-24 00:47:39 -05:00
gary 26f1a6051f [ox/std] Make Vector::remove take a MaybeView_t
Build / build (push) Successful in 1m17s
2025-05-24 00:46:39 -05:00
gary c4c1d4777b [keel] Cleanup ox::Error(0) instance 2025-05-23 20:25:08 -05:00
gary fab012d3e7 [ox] Cleanup all ox::Error(0) instances 2025-05-23 20:24:58 -05:00
gary a90380f377 Merge commit 'e90dd887477452922f783535edb3d4c55e9a0d2c' 2025-05-23 03:23:17 -05:00
gary 312097a799 [ox/std] Fix implementation of std cmp functions
Build / build (push) Successful in 1m12s
2025-05-23 03:22:27 -05:00
gary a40198ab8d [nostalgia] Update release-d2025.05.2 release notes
Build / build (push) Successful in 1m23s
2025-05-22 20:45:34 -05:00
gary 52d8c0bdc8 [nostalgia/gfx] Replace static_cast compare with std::cmp_equal 2025-05-22 20:43:27 -05:00
gary c19d7f4ea3 [nostalgia] Add .vs and cmake-build-* to .gitignore 2025-05-22 20:42:09 -05:00
gary 159b7e7ee7 [buildcore] Make pybb cmake_build specify --config debug/release 2025-05-22 20:41:30 -05:00
gary c93eec4f05 [teagba] Make cstart.cpp only compile if GCC 2025-05-22 20:40:33 -05:00
gary e7e7a22390 [nostalgia/sample_project] Make sample_project exempt from autocrlf 2025-05-22 20:39:56 -05:00
gary 26d5048e67 [ox/fs] Fix new build error in MSVC (VS 17.14) 2025-05-22 20:05:09 -05:00
gary 3b8f97cc41 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m15s
2025-05-21 22:15:56 -05:00
gary f1e68e0a04 [nostalgia/gfx/studio/tilesheet] Fix overrun errors when switching subsheets, clear selection on switch 2025-05-21 22:15:07 -05:00
gary d6e4ab7a24 [keel] Cleanup
Build / build (push) Successful in 1m24s
2025-05-18 14:08:39 -05:00
gary 2000b2deee [nostalgia/gfx/studio] Cleanup 2025-05-17 23:35:10 -05:00
gary 7d92400f6d [nostalgia/gfx/studio] Add type specific navigateTo functions 2025-05-17 23:26:23 -05:00
gary cb304ecf28 [applib] Cleanup
Build / build (push) Successful in 1m12s
2025-05-17 17:46:38 -05:00
gary ea17377700 [ox/std] Make StringViewCR honest
Build / build (push) Successful in 1m17s
2025-05-17 17:34:22 -05:00
gary c424bde06d [nostalgia] Style cleanup
Build / build (push) Successful in 1m14s
2025-05-17 17:31:47 -05:00
gary ee7d5c6d51 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m14s
2025-05-17 17:22:13 -05:00
gary 99247cee32 [nostalgia/gfx/test] Cleanup
Build / build (push) Successful in 1m15s
2025-05-17 17:18:51 -05:00
gary 7b8ddc189a [nostalgia/gfx] Consolidate implementations into single files, remove unnecessary function exports
Build / build (push) Successful in 1m17s
2025-05-17 17:13:13 -05:00
gary a6814030ee [studio/applib] Cleanup
Build / build (push) Successful in 1m13s
2025-05-17 16:15:32 -05:00
gary 9937a01042 [turbine] Cleanup 2025-05-17 16:12:16 -05:00
gary abcf2adc56 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m14s
2025-05-17 03:02:59 -05:00
gary 05f9023550 [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m14s
2025-05-17 02:51:56 -05:00
gary 5ba0bcf963 [turbine] Consolidate some files that didn't have sensible distinctions
Build / build (push) Has been cancelled
2025-05-17 02:51:23 -05:00
gary 3ccadba2f5 [nostalgia/gfx/studio/tilesheet] Fix dragging cursor on image
Build / build (push) Successful in 1m20s
2025-05-16 21:22:33 -05:00
gary 00e52b6491 [nostalgia] Make pkg-dmg more versatile
Build / build (push) Successful in 1m14s
2025-05-15 22:26:35 -05:00
gary ae40487990 [nostalgia/gfx] Add navigateTo handler to TileSheetEditor
Build / build (push) Successful in 1m20s
2025-05-15 20:39:50 -05:00
gary 84b612c693 [studio/modlib] Give navigateTo a default argument 2025-05-15 20:39:01 -05:00
gary 3c2a6b047e [studio/applib] Make navigateTo handle UUID paths 2025-05-15 20:38:27 -05:00
gary 626da322d9 [ox/std] Add StringParam(IString const&) constructor 2025-05-15 20:37:44 -05:00
gary 0de428a2e5 [studio/applib] Cleanup
Build / build (push) Successful in 1m19s
2025-05-14 22:11:43 -05:00
gary 8a52df4f76 [nostalgia/gfx] More cleanup
Build / build (push) Successful in 1m16s
2025-05-14 01:43:59 -05:00
gary efec6eb3c8 [nostalgia/gfx/studio/palette] Add RGB key shortcuts for focusing color channels
Build / build (push) Successful in 1m15s
2025-05-14 01:13:40 -05:00
gary 56eeb24900 [nostalgia/gfx/opengl] More cleanup
Build / build (push) Successful in 1m56s
2025-05-13 22:06:08 -05:00
gary ae81f6b3de [ox/std] Make Span::operator[] const
Build / build (push) Successful in 1m17s
2025-05-13 22:02:23 -05:00
gary c1108301c0 [nostalgia/gfx] Cleanup 2025-05-13 22:01:59 -05:00
gary 83fbe6ac74 [keel,turbine,studio] Fix some install mistakes
Build / build (push) Successful in 2m17s
2025-05-13 21:39:37 -05:00
gary 80b452833f [nostalgia/gfx] Cleanup
Build / build (push) Successful in 2m28s
2025-05-13 21:24:04 -05:00
gary 0fa394333b [nostalgia] Add release note about Mac menubar using Cmd
Build / build (push) Successful in 1m15s
2025-05-10 01:01:11 -05:00
gary cae7535034 [nostalgia] Fix typos in release notes
Build / build (push) Successful in 1m15s
2025-05-10 00:57:45 -05:00
gary df87832324 [studio] Add build date to About
Build / build (push) Successful in 1m15s
2025-05-10 00:21:54 -05:00
gary d585794cbe [nostalgia/gfx/studio/tilesheet] Fix Insert tile command 2025-05-09 20:34:42 -05:00
gary 209658549c [nostalgia/gfx/studio/tilesheet] Cleanup 2025-05-09 20:34:04 -05:00
gary 02383a4aed [ox/std] Cleanup 2025-05-09 01:22:29 -05:00
gary 185a76282a [nostalgia] Make pkg-dmg delete bundle after archive created
Build / build (push) Successful in 1m15s
2025-05-08 23:29:36 -05:00
gary b722b4f701 [nostalgia] Update release notes
Build / build (push) Has been cancelled
2025-05-08 23:28:58 -05:00
gary 459ab5aad9 [studio] Remove ability to re-order Editor tabs 2025-05-08 23:28:51 -05:00
gary 565f621cfc [nostalgia/gfx/studio/tilesheet] Fix Delete Tile functionality
Build / build (push) Successful in 1m15s
2025-05-08 01:57:59 -05:00
gary 9589ca9148 [keel] Cleanup 2025-05-08 01:37:18 -05:00
gary 164db5007b [keel] Cleanup
Build / build (push) Successful in 1m25s
2025-05-08 00:49:50 -05:00
gary cbfb167d29 [nostalgia] Remove unused project directory
Build / build (push) Successful in 1m33s
2025-05-07 20:23:48 -05:00
gary e7b83be867 [nostalgia] Update release notes
Build / build (push) Successful in 2m28s
2025-05-07 20:18:08 -05:00
gary 649da5fca8 [nostalgia/sample_project] Delete Scenes directory 2025-05-07 20:16:35 -05:00
gary aa095f7680 [studio] Make Delete key initiate deletion of selected directory 2025-05-07 20:15:38 -05:00
gary bb99c99f01 [studio] Make deleting a directory close files in that directory 2025-05-07 20:10:34 -05:00
gary 7f0dcdd280 [nostalgia/gfx/studio/tilesheet] Cleanup
Build / build (push) Successful in 1m20s
2025-05-07 19:57:27 -05:00
gary 6029ad5d47 [nostalgia/studio] Add command for bundling Mac app 2025-05-07 02:48:14 -05:00
gary 26fe266b09 [ox/mc] Fix break from using strnlen_s inappropriately
Build / build (push) Successful in 1m16s
2025-05-07 01:18:14 -05:00
gary 091eda7b44 Merge commit 'ce53be92716b0f5201882d6959c398b61c6cc93c'
Build / build (push) Successful in 1m23s
2025-05-07 00:12:52 -05:00
gary 9676ea5978 [turbine/glfw] Fix programmatic shutdown to invoke shutdownHandler
Build / build (push) Successful in 1m50s
2025-05-07 00:06:21 -05:00
gary de8ac10653 [turbine/glfw] Fix closing when no shutdown handler is set
Build / build (push) Successful in 1m53s
2025-05-07 00:01:49 -05:00
gary 88a6cd59f3 [turbine/glfw] Treat close window event like other events with regard to a mandatory refresh period
Build / build (push) Waiting to run
2025-05-06 23:56:49 -05:00
gary cd43fb7f38 [turbine,studio] Fix confirm app close pop up to work with Ctrl-Q
Build / build (push) Successful in 2m1s
2025-05-06 23:25:00 -05:00
gary 136f422401 [nostalgia] Update release notes
Build / build (push) Successful in 1m16s
2025-05-06 23:11:06 -05:00
gary e773d6f0ee [studio] Rename StudioContext to Context
Build / build (push) Successful in 1m16s
2025-05-06 22:37:21 -05:00
gary 7da2f68d30 [nostalgia/sample_project] Add assets
Build / build (push) Successful in 1m22s
2025-05-06 22:30:28 -05:00
gary d20889aef1 [nostalgia/gfx/studio] Update for Ox changes 2025-05-06 22:29:51 -05:00
gary 50c8302f4a [ox] Rename itoa to intToStr 2025-05-06 22:29:31 -05:00
gary d8195d300d [olympic,nostalgia] Address unsafe buffer warnings 2025-05-06 22:25:36 -05:00
gary a8c1387d5a [ox] Address unsafe buffer warnings 2025-05-06 22:25:13 -05:00
gary ff1e8f260b [studio] Add popup to warn about UUID duplication 2025-05-06 22:22:26 -05:00
gary d4329981e7 [studio,nostalgia] Cleanup
Build / build (push) Successful in 1m14s
2025-05-06 01:11:47 -05:00
gary 0003454311 [studio,nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 1m14s
2025-05-06 01:00:04 -05:00
gary 8c6b2234ec [olympic/util] Make pkg-gba script check return code of subprocesses
Build / build (push) Successful in 1m14s
2025-05-05 23:11:37 -05:00
gary aad4b8a44c [studio] Cleanup 2025-05-05 23:10:18 -05:00
gary 7cab133127 [keel] Add ability to log UUID duplication
Build / build (push) Successful in 1m14s
2025-05-05 21:54:24 -05:00
gary 640ac85de4 [nostalgia/gfx/studio/palette] Make page rename dialog accept on enter if input focused
Build / build (push) Successful in 1m19s
2025-05-04 00:15:30 -05:00
gary b8d7658626 [nostalgia/studio] Update generated icondata.cpp with Clang fix
Build / build (push) Successful in 1m26s
2025-05-02 21:05:21 -05:00
gary 2503bb3b2c [nostalgia/sample_project] Update type descriptors 2025-05-02 21:04:36 -05:00
gary e5dd448fe7 [turbine,studio] Make Studio confirm with user before closing app if any unsaved changes
Build / build (push) Successful in 1m15s
2025-05-01 23:15:06 -05:00
gary 4770bb6a93 [olympic/util] Cleanup
Build / build (push) Successful in 1m17s
2025-04-20 21:44:36 -05:00
gary c0bac696dc [nostalgia/gfx/studio/paletteeditor] Fix color number key range
Build / build (push) Successful in 1m16s
2025-04-19 14:43:07 -05:00
gary 95f7c33419 [studio] Change Studio font
Build / build (push) Successful in 1m16s
2025-04-19 00:23:36 -05:00
gary 535d8876d3 [keel] Cleanup 2025-04-19 00:22:28 -05:00
gary 845e433221 [turbine] Fix Mac build 2025-04-18 01:38:32 -05:00
gary 5169a607cf [turbine] Disable useless window icon on Mac, it causes GLFW warning
Build / build (push) Successful in 1m16s
2025-04-17 21:36:56 -05:00
gary 8f03af99a7 [keel] Style updates 2025-04-17 21:36:24 -05:00
gary ee63a4a1e4 [keel] Cleanup
Build / build (push) Successful in 1m17s
2025-04-17 21:04:43 -05:00
gary ac29f7a0f2 Merge commit 'ec6cf92c4763be5933ee6debbf97bce25b9fcfc9' 2025-04-17 20:12:48 -05:00
gary 89ae226b1d [keel] Improve correctness
Build / build (push) Successful in 1m18s
2025-04-17 01:17:40 -05:00
gary 477834ac04 [keel] Cleanup
Build / build (push) Successful in 1m16s
2025-04-17 01:06:08 -05:00
gary 97b707b61c [keel] Fix MSVC build
Build / build (push) Successful in 1m16s
2025-04-17 01:01:22 -05:00
gary e86180e842 [nostalgia/core/keel] Consistency cleanup
Build / build (push) Successful in 1m16s
2025-04-17 00:39:34 -05:00
gary 035ba8810f [keel,nostalgia] Fix converter type names 2025-04-17 00:37:05 -05:00
gary f1c2113dd3 [keel] Fix some completely incomprehensible build break in GCC12...
Build / build (push) Successful in 1m16s
2025-04-17 00:32:38 -05:00
gary 56b79f414d [keel,nostalgia] Further simplify writing type converters
Build / build (push) Failing after 14s
2025-04-17 00:22:47 -05:00
gary 844656d557 [nostalgia/gfx/keel] Update type converter style
Build / build (push) Successful in 1m14s
2025-04-16 23:12:24 -05:00
gary 849aceb86d [keel] Add cleaner way to write type converters 2025-04-16 23:11:47 -05:00
gary eef51a6d2b [olympic] Improve error handling in file-to-cpp 2025-04-16 20:11:28 -05:00
gary c84b85102c [nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 1m15s
2025-04-15 22:05:46 -05:00
gary 3fe62464c3 [nostalgia/sample_project] Add NS_Logo32
Build / build (push) Successful in 1m18s
2025-04-14 22:20:06 -05:00
gary db55fc722f [nostalgia/player] Cleanup 2025-04-14 22:05:23 -05:00
gary 2094450898 [studio] Cleanup
Build / build (push) Successful in 1m22s
2025-04-14 22:00:05 -05:00
gary 889bec04b1 [nostalgia/gfx/studio/tilesheet] Cleanup 2025-04-13 23:20:49 -05:00
gary ac1e34d4cd [nostalgia] Update release notes
Build / build (push) Successful in 1m19s
2025-04-13 00:37:32 -05:00
gary 55ed75f44d [nostalgia/gfx/studio/tilesheet] Fix selection clearing to work when clicking outside image
Build / build (push) Successful in 1m19s
2025-04-13 00:33:06 -05:00
gary 2751872c59 [nostalgia] Cleanup file-to-cpp output
Build / build (push) Successful in 1m15s
2025-04-12 16:50:09 -05:00
gary 2a3cd35cc4 [nostalgia] Fix release notes version, add d2025.02.1
Build / build (push) Waiting to run
2025-04-12 16:45:58 -05:00
gary b66f459f75 [nostalgia] Cleanup icon rsrc generation
Build / build (push) Waiting to run
2025-04-12 16:40:49 -05:00
gary 3910f4e77c [nostalgia] Fix debug and gba-run commands in Makefile
Build / build (push) Waiting to run
2025-04-12 14:04:41 -05:00
gary c0e96216ae [turbine] Make accessor functions take const ref to Context
Build / build (push) Waiting to run
2025-04-12 13:49:43 -05:00
gary f9512d72e8 [turbine/glfw] Fix implicit conversion
Build / build (push) Waiting to run
2025-04-12 00:22:49 -05:00
gary b7f2c169ec [nostalgia/studio/gfx] Fix typo
Build / build (push) Waiting to run
2025-04-11 23:14:57 -05:00
gary 1e5057d6e6 [nostalgia] Add app icon note to release notes
Build / build (push) Waiting to run
2025-04-11 23:12:36 -05:00
gary c6255e3224 [nostalgia/studio] Add icon 16 src
Build / build (push) Waiting to run
2025-04-11 23:06:42 -05:00
gary 02230ef619 [turbine,studio,nostalgia/studio] Add support for window icon scaling, expand icons sizes for Nostalgia Studio
Build / build (push) Waiting to run
2025-04-11 22:45:11 -05:00
gary 9b6b60e4d1 [turbine] Cleanup
Build / build (push) Waiting to run
2025-04-11 21:47:26 -05:00
gary b9a26ab61e [turbine] Fix GLFWimage member init order
Build / build (push) Waiting to run
2025-04-11 21:44:52 -05:00
gary a521887ddd [studio,turbine] Add support for window icons
Build / build (push) Waiting to run
2025-04-11 21:41:30 -05:00
gary 5ca7e2f226 [ox/fs] Cleanup
Build / build (push) Successful in 1m14s
2025-04-02 01:30:58 -05:00
gary 125a235dd1 [ox/fs] Cleanup
Build / build (push) Successful in 1m26s
2025-04-02 01:29:02 -05:00
gary 91a7129f8f [nostalgia/gfx/keel] Cleanup 2025-04-02 01:07:26 -05:00
gary df48a232ec [nostalgia/studio] Add icon to Windows executable
Build / build (push) Successful in 1m28s
2025-04-02 00:49:13 -05:00
gary ab11b885e6 [keel] Add missing new line to log message
Build / build (push) Successful in 1m25s
2025-03-24 21:02:20 -05:00
gary 36fc25fb7e [studio] Fix closing tab with unsaved changes 2025-03-24 21:02:20 -05:00
gary 4803cca334 [nostalgia/player] Cleanup
Build / build (push) Successful in 1m29s
2025-03-08 22:28:29 -06:00
gary 6bd74611cd [nostalgia] Update release notes
Build / build (push) Successful in 1m28s
2025-02-25 20:02:52 -06:00
gary c3f9cf9a64 [studio] Fix New Project opening project, disable New if no project open
Build / build (push) Has been cancelled
2025-02-25 20:01:33 -06:00
gary 646ab1283f [nostalgia/gfx] Cleanup
Build / build (push) Successful in 1m26s
2025-02-24 21:45:45 -06:00
gary 74cf055610 [nostalgia] Cleanup
Build / build (push) Successful in 1m32s
2025-02-24 19:43:10 -06:00
gary 0d8ba1b154 [nostalgia/gfx] Cleanup formatting mistake
Build / build (push) Successful in 1m26s
2025-02-23 23:21:59 -06:00
gary 20edbb7f38 [buildcore] Map aarch64 to arm64
Build / build (push) Successful in 1m27s
2025-02-23 01:00:12 -06:00
gary 6febc7cc73 [nostalgia] Fix build
Build / build (push) Successful in 1m32s
2025-02-23 00:51:30 -06:00
gary b94d6b5061 [nostalgia] Remove scene package, finish stubbing out sound
Build / build (push) Failing after 21s
2025-02-23 00:49:58 -06:00
gary b3952cabbc [nostalgia] Add build upload step to CI
Build / build (push) Successful in 1m39s
2025-02-22 21:30:35 -06:00
gary 2ffc11b04e Merge commit 'e723ead864edb4bc160e4d69713309174ad9e82e'
Build / build (push) Successful in 1m34s
2025-02-22 20:55:17 -06:00
gary 96cace2cbb [studio] Cleanup 2025-02-22 19:51:55 -06:00
gary 472f5702bd [nostalgia/gfx/studio/tilesheet] Change max export scale to 135
Build / build (push) Successful in 1m32s
2025-02-22 15:31:39 -06:00
gary c0ac4345d3 [studio] Cleanup
Build / build (push) Successful in 1m30s
2025-02-22 15:16:26 -06:00
gary fbebf4ef83 [nostalgia/gfx/studio/tilesheet] Fix export for 4bpp images
Build / build (push) Successful in 1m27s
2025-02-22 00:58:12 -06:00
gary 20513f7749 [nostalgia/sample_project] Add type descriptors 2025-02-21 00:41:04 -06:00
gary 25a7873ea2 [nostalgia,studio] Fix crash that occurred when navigating to file that is not already open
Build / build (push) Successful in 1m32s
2025-02-20 23:57:02 -06:00
gary d0a32e247e [ox/std] Add Vector::remove
Build / build (push) Successful in 1m42s
2025-02-20 23:34:36 -06:00
gary 03d4a5736e [nostalgia,studio] Add ability to navigate from tile sheet to palette color
Build / build (push) Successful in 1m52s
2025-02-20 23:30:50 -06:00
gary a2e41e6527 Merge commit '4e94c925686cdda4b1ac777045dd7a17c7dc0329'
Build / build (push) Successful in 1m38s
2025-02-20 20:11:03 -06:00
gary 40a7caff90 [ox/std] Make bounds checking its own option enable-able in release builds 2025-02-20 20:05:07 -06:00
gary 26fc5565e8 [nostalgia/gfx] Make dangling reference warning suppressions check for GCC 13
Build / build (push) Successful in 1m30s
2025-02-20 19:40:08 -06:00
gary 388541ce32 [nostalgia/player] Cleanup
Build / build (push) Successful in 1m24s
2025-02-20 00:01:29 -06:00
gary 6c194667b9 [nostalgia] Fix NostalgiaGfx lib name, stub out sound package
Build / build (push) Successful in 1m27s
2025-02-19 22:19:16 -06:00
gary 62d0579f40 [ox/fs] Restructure stat error handling to make easier to debug
Build / build (push) Successful in 1m25s
2025-02-19 21:47:47 -06:00
gary 202595b2a6 [keel] Fix loading assets by path 2025-02-19 21:47:00 -06:00
gary cb21ff3f04 Merge commit 'a6b9657268eb3fe139b0c22df27c2cb2efc0013c' 2025-02-19 00:34:26 -06:00
gary 2a8e3c2dc4 [nostalgia/gfx] Remove unnecessary cast
Build / build (push) Successful in 1m26s
2025-02-18 23:01:15 -06:00
gary 998066d377 [ox/std] Add comparison functions
Build / build (push) Successful in 1m24s
2025-02-18 21:46:41 -06:00
gary fefb876fe7 [nostalgia/gfx] Add checks for GCC version for warning suppression
Build / build (push) Successful in 1m24s
2025-02-18 20:33:29 -06:00
gary 5979e9885e [jsoncpp] Up required CMake version 2025-02-18 20:26:47 -06:00
gary a17abe4639 [nfde] Up required CMake version 2025-02-18 20:26:47 -06:00
gary d62f913855 [nostalgia/gfx] Suppress some superfluous warnings
Build / build (push) Failing after 1m9s
2025-02-18 20:22:56 -06:00
gary 12bb7475fc [nostalgia/gfx/studio/tilesheet] Adjust pixel line size on Windows
Build / build (push) Successful in 1m25s
2025-02-18 20:19:51 -06:00
gary df2c7e2b67 [nostalgia] Update release notes
Build / build (push) Successful in 1m26s
2025-02-08 18:10:49 -06:00
gary 713aec887b [buildcore] Change mypy invokation
Build / build (push) Successful in 1m28s
2025-02-07 20:38:44 -06:00
gary 3089cd7afc Change builder type to olympic
Build / build (push) Has been cancelled
2025-02-07 20:34:22 -06:00
gary 00638bc812 [nostalgia/gfx/studio/tilesheet] Mark DrawCommands as obsolete if no changes
Build / build (push) Successful in 3m37s
2025-02-05 20:26:47 -06:00
gary e002109829 [studio] Make undo/redo skip over obsolete commands 2025-02-05 20:26:03 -06:00
gary b4798fd2ab [nostalgia/gfx/studio/tilesheet] Make rotate only available for square subsheets or selections
Build / build (push) Successful in 3m39s
2025-02-05 01:54:41 -06:00
gary 3c804bf62a [studio] Give MakeCopy popup an error message for files that already exist
Build / build (push) Successful in 3m36s
2025-02-03 23:30:07 -06:00
gary d39d552bd9 [nostalgia/studio] Update icon to higher resolution 2025-02-03 23:29:26 -06:00
gary b7202a2b0d [nostalgia/player] Disable Keel mods on GBA
Build / build (push) Successful in 3m34s
2025-02-03 22:48:07 -06:00
gary 4e27a4c1f5 [nostalgia/core/studio/tilesheet] Fix palette path display update
Build / build (push) Successful in 3m37s
2025-02-03 22:43:20 -06:00
gary 4ef31762d0 [nostalgia/core/studio/tilesheet] Cleanup 2025-02-03 22:43:02 -06:00
gary 8b22a8f339 [keel] Make buildUuidMap only read the first 40 bytes of each file 2025-02-03 20:29:06 -06:00
gary d45ff05bcd [ox/fs] Add new partial file read functions 2025-02-03 20:28:25 -06:00
gary 671dd86206 [keel,studio] Add Make Copy option to ProjectExplorer
Build / build (push) Successful in 3m46s
2025-02-03 02:01:40 -06:00
gary 0abadc1850 [studio] Fix QuestionPopup to only emit a response when there is a response
Build / build (push) Successful in 3m36s
2025-02-03 00:35:37 -06:00
gary 4e068d628c [studio] Fix misrender flash on tab close 2025-02-03 00:19:14 -06:00
gary 4461f99fa4 [studio] Add Ctrl-W shortcut for closing active tab
Build / build (push) Successful in 3m36s
2025-02-02 23:13:15 -06:00
gary cd1f4bdaa3 [studio] Add confirmation for closing file with unsaved changes 2025-02-02 23:07:59 -06:00
gary 4728699585 [studio] Add combobox that will take string views
Build / build (push) Successful in 3m47s
2025-02-02 20:46:08 -06:00
gary 105a1e5559 [nostalgia/core/studio/tilesheet] Rework operation ctrls into a dropbox
Build / build (push) Failing after 1m1s
2025-02-02 20:43:01 -06:00
gary 1bc18e34a8 [nostalgia/core/studio/tilesheet] Add ability to rotate a selection 2025-02-02 20:22:20 -06:00
gary fb8d295fcb [nostalgia/core/studio/tilesheet] Add rotate functionality 2025-02-02 14:46:21 -06:00
gary 8459d3baea Merge commit 'c42adc290cd8a27d01bb6d9877032dd2c963a4b7' 2025-02-01 22:55:46 -06:00
gary 804d78e116 [nostalgia/gfx/studio] Cleanup
Build / build (push) Successful in 3m32s
2025-02-01 15:14:24 -06:00
gary 5351e9aa0a [nostalgia/core/studio/tilesheet] Add line drawing tool
Build / build (push) Successful in 3m36s
2025-02-01 14:14:09 -06:00
gary b5954f15c5 [studio] Restore context menu for root dir, but exclude Delete
Build / build (push) Successful in 3m33s
2025-01-29 18:47:48 -06:00
gary 5dce9dd377 [studio] Suppress context menu for root dir in ProjectExplorer
Build / build (push) Successful in 3m32s
2025-01-28 01:27:51 -06:00
gary 0570f76236 [ox/fs] Fix PassThroughFS::stripSlash
Build / build (push) Successful in 3m32s
2025-01-28 01:18:44 -06:00
gary e22b658a67 [studio] Fix isParentOf check in Project to ensure child dir path ends with /
Build / build (push) Has been cancelled
2025-01-28 01:04:17 -06:00
gary 56b9cb6ebf [studio] Fix file explorer to treat empty directories as directories
Build / build (push) Successful in 3m32s
2025-01-27 23:31:58 -06:00
gary eaa9a2415e [keel] Make reloadAsset check if file is loaded 2025-01-27 21:59:57 -06:00
gary 95256a9a0d [studio] Make rename file give error message if the file already exists
Build / build (push) Successful in 3m32s
2025-01-27 00:54:58 -06:00
gary 2286238abc [studio] Make rename file accept input upon pressing Enter if text input is focused
Build / build (push) Successful in 3m36s
2025-01-27 00:33:14 -06:00
gary 13f0bf57e4 [studio] Make deleting a file close tabs associated with it 2025-01-27 00:30:27 -06:00
gary 8eb1ac215b [studio] Fix not to try moving a parent directory to its child
Build / build (push) Successful in 3m34s
2025-01-27 00:10:25 -06:00
gary e132f2fd1b [studio] Make file move do nothing if the file already exists 2025-01-26 23:59:13 -06:00
gary 12f6b22c8b [nostalgia/gfx/studio/palette] Cleanup 2025-01-26 23:35:03 -06:00
gary 6c858e0c4e [nostalgia/gfx/studio/tilesheet] UI cleanup
Build / build (push) Successful in 3m35s
2025-01-26 22:30:39 -06:00
gary c6b58f7c63 [nostalgia] Update release notes
Build / build (push) Successful in 3m35s
2025-01-26 22:16:04 -06:00
gary a22aafaf96 [nostalgia/gfx/studio/palette] Add ability to reorder Palette pages 2025-01-26 22:12:57 -06:00
gary 6298ac3a21 [nostalgia] Update release notes
Build / build (push) Successful in 3m28s
2025-01-26 20:58:22 -06:00
gary cd63afacfe [studio] Remove Ctrl-0 tab shortcut 2025-01-26 20:53:47 -06:00
gary 2859183742 [nostalgia/gfx/studio/tilesheet] Add the ability to move subsheets 2025-01-26 20:46:15 -06:00
gary 8d04af691e Merge commit 'ab760b064fd6a302bad13274e0e02b2b2c957b67' 2025-01-26 15:42:50 -06:00
gary 055165974e [nostalgia/sample_project] Update test assets 2025-01-26 15:41:40 -06:00
gary be51838775 [nostalgia/gfx/studio/tilesheet] Add flip x and flip y functionality
Build / build (push) Successful in 3m33s
2025-01-26 15:41:13 -06:00
gary 1207dadee8 [studio] Add ability to move directories
Build / build (push) Successful in 3m29s
2025-01-26 09:38:27 -06:00
gary 109e1898cc [studio] Add ability to drag files between directories
Build / build (push) Successful in 3m29s
2025-01-26 02:03:54 -06:00
gary a24bf7ffb9 [studio] Fix config to update when open file name changes 2025-01-26 01:01:48 -06:00
gary 046834c2b9 [studio,nostalgia] Update tab name when corresponding file's name changes
Build / build (push) Successful in 3m30s
2025-01-26 00:52:11 -06:00
gary f840240aac [nostalgia/gfx/studio/tilesheeteditor] Rework system for tracking current palette path
Build / build (push) Successful in 3m29s
2025-01-25 22:59:51 -06:00
gary cfa91d3d39 [keel,studio] Add ability to rename files 2025-01-25 22:59:01 -06:00
gary f7a7a66a6a [ox/event] Add Signal::connectionCnt 2025-01-25 22:58:18 -06:00
gary 5145595d57 [ox/std] Fix HashMap collision handling 2025-01-25 22:16:42 -06:00
gary f01d303381 [ox/std] Fix UPtr compare with nullptr 2025-01-25 20:13:47 -06:00
gary 098c8cb844 [nostalgia/gfx/studio] Make move color commands affect all pages
Build / build (push) Successful in 3m25s
2025-01-24 23:46:26 -06:00
gary 04ad0f0264 [studio] Add drag/drop functions that use model TypeName for name
Build / build (push) Successful in 3m23s
2025-01-24 23:26:30 -06:00
gary 695e7a4561 [nostalgia/gfx/studio/paletteeditor] Change move color mechanism to use drag/drop
Build / build (push) Failing after 54s
2025-01-24 23:19:45 -06:00
gary 7d53028faf [studio] Cleanup 2025-01-24 00:21:28 -06:00
gary 6c34198f58 Merge commit '897a59cdad66e593fd45eece9414d8414fa7f1ae' 2025-01-23 23:51:13 -06:00
gary 7e3e046109 [ox/model] Fix possible infinite recursion
Build / build (push) Successful in 3m26s
2025-01-23 23:48:40 -06:00
gary f63c58169f [studio] Add filepickerpopup.hpp to studio.hpp 2025-01-23 22:19:59 -06:00
gary e40b11246d [nostalgia/gfx/studio/paletteeditor] Fix num key shortcuts to ignore if ctrl is down
Build / build (push) Successful in 3m25s
2025-01-23 21:56:47 -06:00
gary 161194c8b2 [nostalgia/gfx/studio/tilesheeteditor] Add FilePicker to for choosing a Palette
Build / build (push) Successful in 3m25s
2025-01-23 21:24:10 -06:00
gary 48603ea2c5 [studio] Make tabs not draw while closing 2025-01-23 21:24:10 -06:00
gary e2f2a17315 [studio] Add FilePickerPopup 2025-01-23 21:24:10 -06:00
gary e8a0ce88c5 Merge commit 'dff9f81e073bb994d5ce96a6eaa1bfa547f1fdf4'
Build / build (push) Waiting to run
2025-01-23 21:21:58 -06:00
gary 82e2ea747f [studio] Fix NewMenu to track prev stage correctly when going back two stages 2025-01-23 21:13:58 -06:00
gary ff666eda9b [studio] Make NewMenu default Name field to focus when it appears
Build / build (push) Successful in 3m30s
2025-01-23 00:55:10 -06:00
gary 0d8b82ba49 [studio] Cleanup
Build / build (push) Successful in 3m10s
2025-01-23 00:32:03 -06:00
gary 5598dfdd87 [nostalgia/player] Update hardcoded tilesheet refs to new file ext
Build / build (push) Successful in 3m16s
2025-01-23 00:19:35 -06:00
gary 6ef462adcc [keel] Add clearer Error handling 2025-01-23 00:15:55 -06:00
gary 9511cb5719 [studio] Fix prev tracking
Build / build (push) Successful in 3m16s
2025-01-22 23:37:44 -06:00
gary 1cc1d561e2 [studio] Add a file explorer to NewMenu to choose where new files go
Build / build (push) Successful in 4m16s
2025-01-22 23:11:08 -06:00
gary d15a0df7da [studio] Make reusable FileTreeModel 2025-01-22 01:04:25 -06:00
gary e1282b6bae [studio] Fix build
Build / build (push) Successful in 3m23s
2025-01-22 00:58:43 -06:00
gary 5fe7c14ccb [nostalgia/sample_project] Rename TileSheet files using new file ext
Build / build (push) Failing after 52s
2025-01-21 23:40:19 -06:00
gary 42165ba2d6 [nostalgia/gfx] Change default file extension for TileSheets to nts 2025-01-21 23:35:55 -06:00
gary 1af4da43ad [nostalgia] Update release notes
Build / build (push) Successful in 3m22s
2025-01-21 22:56:59 -06:00
gary 4fa879a09e [nostalgia/sample_project] Update NS_Logo.ng to final TileSheetV5 format
Build / build (push) Has been cancelled
2025-01-21 22:54:27 -06:00
gary fd8f1a29c6 [nostalgia] Add release notes document
Build / build (push) Successful in 3m24s
2025-01-21 22:45:55 -06:00
gary 9fda2763ba [nostalgia/gfx] Make TileSheetV5::defaultPalette a string instead of FileAddress 2025-01-21 22:44:55 -06:00
gary cda23ac4af [ox/std] Change ox::String::operator[](size_t) const return a reference 2025-01-21 22:43:57 -06:00
gary c36b244dd3 [nostalgia/gfx] Cleanup, add PaletteV5, restore mistakenly removed function 2025-01-21 22:17:13 -06:00
gary 335d278f5e [ox/oc] Fix integer read for signed/unsigned 2025-01-21 22:15:36 -06:00
gary f987b02c65 [nostalgia/gfx] Move to TileSheetV5
Build / build (push) Successful in 3m23s
2025-01-21 02:21:01 -06:00
gary 3c056276c1 [turbine,nostalgia] Cleanup 2025-01-20 23:19:07 -06:00
gary 87e2fdefcf [ox/std] Make UAnyPtr uncopyable 2025-01-20 20:42:00 -06:00
gary 672b92b363 [nostalgia/gfx/studio] Remove accidental version tag in default Palette
Build / build (push) Successful in 3m23s
2025-01-20 03:13:01 -06:00
gary 762a6517b2 [nostalgia] Rename core to gfx 2025-01-20 03:11:35 -06:00
gary d141154a45 Merge commit '38777cfac8868b3628332090260710d5ac26aba0'
Build / build (push) Successful in 3m23s
2025-01-20 02:15:45 -06:00
gary 6170647c0c [nostalgia,studio] Proper fix for input filtering 2025-01-20 02:10:48 -06:00
gary 48e45c7dd6 [studio] Cleanup 2025-01-20 01:34:00 -06:00
gary 5d3d9229b7 [nostalgia/core/studio/paletteeditor] Ignore keyboard input when popup is open 2025-01-20 01:33:23 -06:00
gary d54e93d836 [studio] Cleanup 2025-01-20 00:16:16 -06:00
gary 830f8fe3e4 [studio,nostalgia/core/studio] Give default Palette created studio a default page
Build / build (push) Successful in 3m23s
2025-01-19 20:53:27 -06:00
gary 7b638538aa Merge commit '8e0b6ffbabb10f8a6e9ad7e9f07e0ba1d039a02e' 2025-01-19 20:18:56 -06:00
gary 2016f6e605 [studio] Fix DeleteConfirmation 'No' option to not delete file
Build / build (push) Successful in 3m22s
2025-01-19 20:17:35 -06:00
gary 240effd305 Merge commit '7e20f7200963cd0b22f84cc46e10db12b6c13806' 2025-01-19 19:04:24 -06:00
gary 6bc629e02c [nostalgia/core/studio/tilesheeteditor] Replace Palette combobox with a readonly text input
Build / build (push) Successful in 3m21s
2025-01-19 19:02:44 -06:00
gary f6f2acd67b [nostalgia/core/studio/tilesheeteditor] Add back file type check for palette drop 2025-01-19 18:21:50 -06:00
gary 0146d38405 [nostalgia/core/studio/tilesheeteditor] Manually merge in changes that were lost in conflict
Build / build (push) Successful in 3m19s
2025-01-19 18:18:52 -06:00
gary 75d8e7bb89 [nostalgia/core/studio/paletteeditor] Fix crash that occurs when removing last color 2025-01-19 17:56:21 -06:00
gary 6b53eaf6b1 [ox/std] Fix string append issues
Build / build (push) Successful in 3m22s
2025-01-19 16:51:05 -06:00
gary 16c32273ac [nostalgia/core/studio/tilesheeteditor] Fix palette drop target to only take palettes 2025-01-19 16:49:31 -06:00
gary 1567a6e29d [applib] Fix build 2025-01-19 14:32:08 -06:00
gary 89d543bcbc Merge commit '7b7d59cf63d77cf7ab6daf6ed7122eef97954555' 2025-01-19 13:39:31 -06:00
gary d68e64931b [nostalgia/core/studio/tilesheeteditor] Add support for dragging palette to palette selector
Build / build (push) Successful in 3m22s
2025-01-19 11:41:48 -06:00
gary 1cbc576286 [studio] Complete drag/drop support for files 2025-01-19 11:41:08 -06:00
gary 500b93562c [studio] Make new dir window OK on Enter key
Build / build (push) Successful in 3m17s
2025-01-19 09:33:17 -06:00
gary 800ca85176 [ox/std] Fix possible error that occurs with appending on boundary of small string size
Build / build (push) Successful in 3m20s
2025-01-19 09:26:06 -06:00
gary cc466a9f1d [studio] Add support for adding and deleting directories 2025-01-19 09:06:16 -06:00
gary 9d1155843e [nostalgia] Rename player from 'nostalgia' to 'Nostalgia'
Build / build (push) Successful in 3m24s
2025-01-19 01:48:53 -06:00
gary a2139c09b2 [studio] Cleanup unused member 2025-01-19 01:44:26 -06:00
gary a3e5f27ab8 [ox/std] Fix Mac build 2025-01-19 01:43:38 -06:00
gary 643f95ec80 [studio] Add confirmation dialog for file deletion, move deletion to Project
Build / build (push) Successful in 3m16s
2025-01-19 01:15:33 -06:00
gary 6924147686 [studio] Add ability to add file through dir context menu
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
gary 6e2b4fa7b4 [nostalgia] Cleanup player run in Makefile 2025-01-18 23:33:55 -06:00
gary 4e5c749918 [studio] Add support for deleting files
Build / build (push) Successful in 3m16s
2025-01-18 22:32:12 -06:00
gary 66229de77f [ox/fs] FileSystem fixes with removing files 2025-01-18 22:31:19 -06:00
gary 7eb37c5318 [nostalgia/core/studio/paletteeditor] Fix adding page if there is no existing page
Build / build (push) Successful in 3m17s
2025-01-18 21:29:36 -06:00
gary 7a21b20711 [nostalgia/core] Replace ContextDeleter with safeDelete(Context*)
Build / build (push) Successful in 3m15s
2025-01-18 20:57:15 -06:00
gary 894be237f2 [ox/std] Drop ox:: qualifier from safeDelete function for pointee 2025-01-18 20:56:24 -06:00
gary 92e9d9cbfc [keel,studio] Add support for New Item templates
Build / build (push) Failing after 1m3s
2025-01-18 20:16:29 -06:00
gary b29b9a9b3a [ox/std] Add UAnyPtr 2025-01-18 20:11:42 -06:00
gary 721f844214 [nostalgia/core/studio/tilesheeteditor] Fix subsheet and palette scrolling 2025-01-18 20:08:09 -06:00
gary a3d6a58cc8 [nostalgia/core/studio] Fix library cpp file ownership
Build / build (push) Successful in 3m10s
2025-01-17 21:50:42 -06:00
gary e598e7fe27 [nostalgia,keel] Add ability to types Obj to Obj
Build / build (push) Successful in 3m10s
2025-01-15 23:44:18 -06:00
gary ba9e720f9f [ox/model] Fix ModelTypeName_v to use requireModelTypeName 2025-01-15 23:34:58 -06:00
gary 8e816a261f [nostalgia/core/studio] Cleanup, fix possible TileSheet fill tool failure
Build / build (push) Successful in 3m11s
2025-01-14 23:06:12 -06:00
gary 5b9929ab3d [keel] Add detail to preload logging 2025-01-14 21:20:13 -06:00
gary ceb54b3f1b [nostalgia/core/opengl] Cleanup 2025-01-14 21:18:22 -06:00
gary 8764444758 [nostalgia/core] Add clearCbb functions
Build / build (push) Successful in 3m12s
2025-01-14 21:13:42 -06:00
gary ce9a0b1fdb [nostalgia/core/opengl] Cleanup memcpys 2025-01-14 21:13:10 -06:00
gary f7a468ea1e [ox/std] Add spancpy 2025-01-14 21:10:18 -06:00
gary 861d177a27 [studio] Cleanup
Build / build (push) Successful in 3m12s
2025-01-13 22:58:39 -06:00
gary 3936756b36 [nostalgia/developer-handbook] Update error handling to reflect the enablement of exceptions for GBA build 2025-01-13 22:53:12 -06:00
gary 3e78ec3fe5 [studio] Cleanup 2025-01-13 22:40:08 -06:00
gary 3c3d53b40c [studio] Ensure Editor tabs do first draw immediately, fix shift key being missed with tab shortcuts
Build / build (push) Successful in 3m14s
2025-01-13 22:29:48 -06:00
gary 151d7c5736 [nostalgia/core/gba] Fix partial tilesheet loading overrun
Build / build (push) Successful in 3m11s
2025-01-13 22:03:36 -06:00
gary 4e4d8d2c3f [nostalgia/core/gba] Make panic use standard abort call 2025-01-13 21:37:29 -06:00
gary 03d1fd2857 [ox/std] Add and integrate standard abort call 2025-01-13 20:39:21 -06:00
gary 6701decc91 [gbabuildcore] Enable exceptions 2025-01-13 20:18:28 -06:00
gary 6cff526647 [teagba] Add symbols needed for enabling exceptions 2025-01-13 20:17:10 -06:00
gary dd50bd0249 [studio] Remap toggle explorer keyboard shortcut, add Ctrl+1-0 mappings for jumping between tabs
Build / build (push) Successful in 3m17s
2025-01-13 01:14:57 -06:00
gary 55a1660242 [nostalgia/core] Fix TileSheet validation/repair to ensure pixels gets cleared if there are subsheets
Build / build (push) Successful in 3m10s
2025-01-12 16:06:24 -06:00
gary ed365dfef5 [studio] Fix new project menu to return an appropriately sized string for name 2025-01-12 15:04:31 -06:00
gary 23a09e4a13 [nostalgia/core/studio] Fix SubSheet editor to return an appropriately sized string 2025-01-12 14:55:50 -06:00
gary b69e7ebb98 [nostalgia/core/studio/tilesheeteditor] Fix select all not to go beyond end
Build / build (push) Successful in 3m10s
2025-01-11 16:21:10 -06:00
gary 418d6e3f22 [nostalgia/core/studio] Fix crash that occurs when a non-leaf node subsheet is selected
Build / build (push) Successful in 3m11s
2025-01-11 16:06:48 -06:00
gary c44d8678cb [nostalgia/core/studio] Fix tile insert to correct input when inserting past the last tile
Build / build (push) Successful in 3m11s
2025-01-11 15:38:11 -06:00
gary eb4cd7106d [nostalgia/core/studio] Fix tile insert to work on last tile
Build / build (push) Successful in 3m9s
2025-01-11 15:23:57 -06:00
gary d259770f32 Merge commit '4ea4a61d542777a270c4e2c283e0e986fc9eec9c'
Build / build (push) Successful in 3m9s
2025-01-11 12:32:00 -06:00
gary 80bad608f7 [keel] Fix reloadAsset 2025-01-11 03:39:38 -06:00
gary 2bce9a2baf [ox/std] Add non-const SmallMap::pairs 2025-01-11 03:37:27 -06:00
gary 791b7746f3 [nostalgia] Update liccor file
Build / build (push) Successful in 3m18s
2025-01-08 23:13:14 -06:00
gary 842e3587fd [nostalgia] Update .gitignore for new location of scripts dir 2025-01-08 23:13:02 -06:00
gary 318e79004b [ox] Update liccor file 2025-01-08 23:12:28 -06:00
gary 9f338a7429 [ox] Run liccor
Build / build (push) Successful in 3m18s
2025-01-08 23:03:05 -06:00
gary 645e48af7b [nostalgia,olympic] Run liccor 2025-01-08 23:02:08 -06:00
gary ef92c8df13 [nostalgia] Make pkg-gba.py force lower case for pack tool
Build / build (push) Successful in 3m9s
2025-01-08 22:01:27 -06:00
gary 849d50be8e [nostalgia/core] Make getTileIdx return an Optional 2025-01-08 21:34:01 -06:00
gary 845092f114 [turbine] Make common turbine.cpp file private to its target 2025-01-08 21:33:23 -06:00
gary 75819a1797 [ox/std] Add SmallMap::values() 2025-01-08 21:31:46 -06:00
gary d66da85753 [ox/std] SmallMap fixes, add findIdx function 2025-01-07 20:59:04 -06:00
gary 98ddb08abd [nostalgia] Cleanup
Build / build (push) Successful in 3m18s
2025-01-05 20:55:49 -06:00
gary 8d1701b0bb [turbine/glfw] Ensure window opens with a standard mandatory refresh period
Build / build (push) Successful in 3m19s
2025-01-04 23:49:04 -06:00
gary 1048e522fd [imgui] Make ImGui not an object lib 2025-01-04 23:42:43 -06:00
gary ee59da4aa3 [glad] Make glad not an object lib 2025-01-04 23:42:43 -06:00
gary 1ba64cb5d8 Merge commit '07610a5af2aaaac9cfcdcf8359b33f7df40d46cd'
Build / build (push) Successful in 3m15s
2025-01-04 01:29:09 -06:00
gary 462bebf6dd [nostalgia/core] Cleanup unused function declaration 2025-01-04 01:26:02 -06:00
gary e3f84c4e75 [studio] Make first tab not draw before selected tab when window opens 2025-01-04 01:12:48 -06:00
gary 6837a0556d [keel] Make AssetManager take StringViewCR for assetId
Build / build (push) Successful in 3m16s
2025-01-04 01:11:05 -06:00
gary ede2c8ca37 [keel] Make AssetTypeManager(Loader) move loader
Build / build (push) Successful in 3m23s
2025-01-04 01:05:04 -06:00
gary f50367f7d5 [ox/std] Add hash.hpp to install
Build / build (push) Successful in 3m31s
2025-01-03 00:26:10 -06:00
gary e758e03d2b [nostalgia,olympic] Update for ox::Error changes
Build / build (push) Successful in 3m20s
2025-01-01 23:43:32 -06:00
gary 835e3270ce [ox] Make Error use std::source_location 2025-01-01 23:42:46 -06:00
gary 480dd5ece4 [ox/std] Cleanup
Build / build (push) Successful in 3m25s
2025-01-01 22:57:20 -06:00
gary dba6bb5800 [ox/std] Make Vector(initializer_list) use list size as capacity
Build / build (push) Successful in 3m55s
2025-01-01 22:37:28 -06:00
gary 40a456e54a [ox/std] Add Vector::shrink_to_fit 2025-01-01 22:32:57 -06:00
gary bf5be00c12 Merge commit 'dc96270ca5e882e41f6b657be14a20e8bd2ad501'
Build / build (push) Successful in 3m14s
2024-12-21 20:13:20 -06:00
gary dc7c2559d6 [studio] Make selection tracker not go below 0 2024-12-21 20:06:48 -06:00
gary a75c4a11d3 [nfde] Address CMake warning, remove unwanted logging
Build / build (push) Successful in 2m45s
2024-12-21 17:07:23 -06:00
gary 347a165762 [sample_project] Update type descriptors
Build / build (push) Successful in 2m55s
2024-12-21 02:45:24 -06:00
gary fd64bfae13 [keel] Fix a use after free, cleanup
Build / build (push) Waiting to run
2024-12-21 02:42:19 -06:00
gary aaeec20ac9 [nostalgia/player] Fix build 2024-12-21 02:42:05 -06:00
gary 37030f9c11 [keel] Cleanup pack tool 2024-12-21 02:41:56 -06:00
gary 462f2bca4c [nostalgia,olympic] Change macro names to comply with broader conventions 2024-12-21 02:41:19 -06:00
gary dc72500b98 [glutils] Change macro names to comply with broader conventions 2024-12-18 22:04:39 -06:00
gary 962fe8bc22 [ox] Change macro names to comply with broader conventions 2024-12-18 22:04:25 -06:00
gary 305eb62647 [studio] Fix build
Build / build (push) Waiting to run
2024-12-18 21:41:15 -06:00
gary 4754359a21 [ox/std] Cleanup Vec2
Build / build (push) Has been cancelled
2024-12-15 01:26:41 -06:00
gary dc07f3d58b [studio] Change FilePicker consturctor to take StringParams 2024-12-15 01:20:29 -06:00
gary fcdcfd10d1 [ox/std] Run liccor
Build / build (push) Successful in 2m52s
2024-12-14 14:33:43 -06:00
gary b74f6a7ace [studio,turbine] Run liccor 2024-12-14 14:33:06 -06:00
gary ac7e5be187 [ox] Remove OxException
Build / build (push) Successful in 2m52s
2024-12-14 00:40:05 -06:00
gary ed910c0beb [nostalgia/core/studio/tilesheeteditor] Fix access overflow on out of bounds Fill command
Build / build (push) Successful in 2m51s
2024-12-13 22:24:58 -06:00
gary 345fb03857 [ox] Remove OxError 2024-12-13 22:06:47 -06:00
gary 9881253f2a [glutils] Cleanup OxError 2024-12-13 22:06:26 -06:00
gary 96d27eecd1 [nostalgia,olympic] Cleanup 2024-12-13 22:00:03 -06:00
549 changed files with 38363 additions and 8372 deletions
+1
View File
@@ -0,0 +1 @@
sample_project text eol=lf
+8 -1
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
+3 -1
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
+1 -1
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.
+45 -9
View File
@@ -1,35 +1,49 @@
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
${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-player
build-player:
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME_CAP}
.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: run-studio .PHONY: run-studio
run-studio: build run-studio: build
${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 +52,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
+1 -1
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
+6 -1
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
+2
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
+2 -2
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")
+10 -1
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
)
+23 -23
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;
+52 -29
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);
@@ -83,13 +83,13 @@ static ox::Result<GLShader> buildShader(
ox::Vector<char> errMsg(ox::units::KB); ox::Vector<char> errMsg(ox::units::KB);
glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data()); glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data());
oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data()); oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data());
return OxError(1, "shader compile error"); return ox::Error(1, "shader compile error");
} }
return shader; return shader;
} }
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept {
oxRequireM(program, buildShaderProgram( OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader, src.vertShader,
src.fragShader, src.fragShader,
src.geomShader)); src.geomShader));
@@ -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,27 +113,27 @@ 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());
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs); glAttachShader(prgm, vs);
if (geo.c_str() && geo.bytes() != 0) { if (geo.c_str() && geo.bytes() != 0) {
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad")); OX_REQUIRE(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
glAttachShader(prgm, gs); glAttachShader(prgm, gs);
} }
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad")); OX_REQUIRE(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
glAttachShader(prgm, fs); glAttachShader(prgm, fs);
glLinkProgram(prgm); glLinkProgram(prgm);
return prgm; return prgm;
@@ -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);
} }
+9 -1
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
@@ -20,3 +20,11 @@ target_include_directories(
imgui SYSTEM PUBLIC imgui SYSTEM PUBLIC
. .
) )
install(
TARGETS
imgui
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
+12 -4
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)
@@ -10,7 +10,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF) option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF)
endif() endif()
option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT}) option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT})
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT}) # DrinkingTea: begin
if(NOT DEFINED NFD_INSTALL)
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT})
endif()
# DrinkingTea: end
set(nfd_PLATFORM Undefined) set(nfd_PLATFORM Undefined)
if(WIN32) if(WIN32)
@@ -21,7 +25,9 @@ elseif(UNIX AND NOT APPLE)
set(nfd_PLATFORM PLATFORM_UNIX) set(nfd_PLATFORM PLATFORM_UNIX)
endif() endif()
message("nfd Platform: ${nfd_PLATFORM}") # DrinkingTea: begin
#message("nfd Platform: ${nfd_PLATFORM}")
# DrinkingTea: end
set(nfd_COMPILER Undefined) set(nfd_COMPILER Undefined)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
@@ -33,7 +39,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C
set(nfd_COMPILER COMPILER_GNU) set(nfd_COMPILER COMPILER_GNU)
endif() endif()
message("nfd Compiler: ${nfd_COMPILER}") # DrinkingTea: begin
#message("nfd Compiler: ${nfd_COMPILER}")
# DrinkingTea: end
# Use latest C++ by default (should be the best one), but let user override it # Use latest C++ by default (should be the best one), but let user override it
if(NOT DEFINED CMAKE_CXX_STANDARD) if(NOT DEFINED CMAKE_CXX_STANDARD)
+1 -1
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
+1 -1
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}")
+41 -41
View File
@@ -97,12 +97,12 @@ ox::Result<uint64_t> caller8(int i) {
``` ```
Lastly, there are a few macros available to help in passing ```ox::Error```s Lastly, there are a few macros available to help in passing ```ox::Error```s
back up the call stack, ```oxReturnError```, ```oxThrowError```, and back up the call stack, ```OX_RETURN_ERROR```, ```OX_THROW_ERROR```, and
```oxRequire```. ```OX_REQUIRE```.
```oxReturnError``` is by far the more helpful of the two. ```OX_RETURN_ERROR``` is by far the more helpful of the two.
```oxReturnError``` will return an ```ox::Error``` if it is not 0 and ```OX_RETURN_ERROR``` will return an ```ox::Error``` if it is not 0 and
```oxThrowError``` will throw an ```ox::Error``` if it is not 0. ```OX_THROW_ERROR``` will throw an ```ox::Error``` if it is not 0.
Since ```ox::Error``` is always nodiscard, you must do something with them. Since ```ox::Error``` is always nodiscard, you must do something with them.
In rare cases, you may not have anything you can do with them or you may know In rare cases, you may not have anything you can do with them or you may know
@@ -113,13 +113,13 @@ This should be used sparingly.
```cpp ```cpp
void studioCode() { void studioCode() {
auto [val, err] = foo(1); auto [val, err] = foo(1);
oxThrowError(err); OX_THROW_ERROR(err);
doStuff(val); doStuff(val);
} }
ox::Error engineCode() noexcept { ox::Error engineCode() noexcept {
auto [val, err] = foo(1); auto [val, err] = foo(1);
oxReturnError(err); OX_RETURN_ERROR(err);
doStuff(val); doStuff(val);
return {}; return {};
} }
@@ -136,19 +136,19 @@ Both macros will also take the ```ox::Result``` directly:
```cpp ```cpp
void studioCode() { void studioCode() {
auto valerr = foo(1); auto valerr = foo(1);
oxThrowError(valerr); OX_THROW_ERROR(valerr);
doStuff(valerr.value); doStuff(valerr.value);
} }
ox::Error engineCode() noexcept { ox::Error engineCode() noexcept {
auto valerr = foo(1); auto valerr = foo(1);
oxReturnError(valerr); OX_RETURN_ERROR(valerr);
doStuff(valerr.value); doStuff(valerr.value);
return {}; return {};
} }
``` ```
Ox also has the ```oxRequire``` macro, which will initialize a value if there is no error, and return if there is. Ox also has the ```OX_REQUIRE``` macro, which will initialize a value if there is no error, and return if there is.
It aims to somewhat emulate the ```?``` operator in Rust and Swift. It aims to somewhat emulate the ```?``` operator in Rust and Swift.
Rust ```?``` operator: Rust ```?``` operator:
@@ -163,23 +163,23 @@ fn f2() -> Result<i32, i32> {
} }
``` ```
```oxRequire```: ```OX_REQUIRE```:
```cpp ```cpp
ox::Result<int> f() noexcept { ox::Result<int> f() noexcept {
// do stuff // do stuff
} }
ox::Result<int> f2() noexcept { ox::Result<int> f2() noexcept {
oxRequire(i, f()); // const auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxReturnError(oxConcat(oxRequire_err_, __LINE__)) OX_REQUIRE(i, f()); // const auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__))
return i + 4; return i + 4;
} }
``` ```
```oxRequire``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code. ```OX_REQUIRE``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code.
```oxRequire``` by default creates a const, but there is also an ```oxRequireM``` (oxRequire Mutable) ```OX_REQUIRE``` by default creates a const, but there is also an ```OX_REQUIRE_M``` (OX_REQUIRE Mutable)
variant for creating a non-const value. variant for creating a non-const value.
* ```oxRequireM``` - oxRequire Mutable * ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
### Logging and Output ### Logging and Output
@@ -268,19 +268,19 @@ constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaPalette> auto *pal) n
h->template setTypeInfo<NostalgiaPalette>(); h->template setTypeInfo<NostalgiaPalette>();
// it is also possible to provide the type name and type version as function arguments // it is also possible to provide the type name and type version as function arguments
//h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1); //h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1);
oxReturnError(h->field("colors", &pal->colors)); OX_RETURN_ERROR(h->field("colors", &pal->colors));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept { constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept {
h->template setTypeInfo<NostalgiaGraphic>(); h->template setTypeInfo<NostalgiaGraphic>();
oxReturnError(h->field("bpp", &ng->bpp)); OX_RETURN_ERROR(h->field("bpp", &ng->bpp));
oxReturnError(h->field("rows", &ng->rows)); OX_RETURN_ERROR(h->field("rows", &ng->rows));
oxReturnError(h->field("columns", &ng->columns)); OX_RETURN_ERROR(h->field("columns", &ng->columns));
oxReturnError(h->field("defaultPalette", &ng->defaultPalette)); OX_RETURN_ERROR(h->field("defaultPalette", &ng->defaultPalette));
oxReturnError(h->field("pal", &ng->pal)); OX_RETURN_ERROR(h->field("pal", &ng->pal));
oxReturnError(h->field("pixels", &ng->pixels)); OX_RETURN_ERROR(h->field("pixels", &ng->pixels));
return {}; return {};
} }
``` ```
@@ -315,9 +315,9 @@ class FileAddress {
template<typename T> template<typename T>
constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept { constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
h->template setTypeInfo<FileAddress::Data>(); h->template setTypeInfo<FileAddress::Data>();
oxReturnError(h->fieldCString("path", &obj->path)); OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path)); OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode)); OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {}; return {};
} }
@@ -327,13 +327,13 @@ constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept {
// cannot read from object in Reflect operation // cannot read from object in Reflect operation
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
int8_t type = 0; int8_t type = 0;
oxReturnError(io->field("type", &type)); OX_RETURN_ERROR(io->field("type", &type));
oxReturnError(io->field("data", UnionView(&fa->m_data, 0))); OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, 0)));
} else { } else {
auto type = static_cast<int8_t>(fa->m_type); auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(io->field("type", &type)); OX_RETURN_ERROR(io->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type); fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} }
return {}; return {};
} }
@@ -343,13 +343,13 @@ constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept {
There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models: There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models:
```cpp ```cpp
oxModelBegin(NostalgiaGraphic) OX_MODEL_BEGIN(NostalgiaGraphic)
oxModelField(bpp) OX_MODEL_FIELD(bpp)
oxModelField(rows) OX_MODEL_FIELD(rows)
oxModelField(columns) OX_MODEL_FIELD(columns)
oxModelField(defaultPalette) OX_MODEL_FIELD(defaultPalette)
oxModelField(pal) OX_MODEL_FIELD(pal)
oxModelField(pixels) OX_MODEL_FIELD(pixels)
oxModelEnd() oxModelEnd()
``` ```
@@ -392,7 +392,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readMC(buff, pal)); OX_RETURN_ERROR(ox::readMC(buff, pal));
return pal; return pal;
} }
``` ```
@@ -405,7 +405,7 @@ ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB); ox::Buffer buffer(ox::units::MB);
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(buffer.data(), buffer.size(), pal, &sz)); OX_RETURN_ERROR(ox::writeMC(buffer.data(), buffer.size(), pal, &sz));
buffer.resize(sz); buffer.resize(sz);
return buffer; return buffer;
} }
@@ -428,7 +428,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readOC(buff, &pal)); OX_RETURN_ERROR(ox::readOC(buff, &pal));
return pal; return pal;
} }
``` ```
@@ -440,7 +440,7 @@ ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept {
ox::Buffer buffer(ox::units::MB); ox::Buffer buffer(ox::units::MB);
oxReturnError(ox::writeOC(buffer.data(), buffer.size(), pal)); OX_RETURN_ERROR(ox::writeOC(buffer.data(), buffer.size(), pal));
return buffer; return buffer;
} }
@@ -462,7 +462,7 @@ ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept {
ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept {
NostalgiaPalette pal; NostalgiaPalette pal;
oxReturnError(ox::readClaw(buff, pal)); OX_RETURN_ERROR(ox::readClaw(buff, pal));
return pal; return pal;
} }
``` ```
+12 -12
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,32 +40,32 @@ 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;
} }
Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept { Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_bools.at(arg)); OX_REQUIRE(out, m_bools.at(arg));
return *out; return *out;
} }
Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept { Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept {
oxRequire(out, m_strings.at(argName)); OX_REQUIRE(out, m_strings.at(argName));
return *out; return *out;
} }
Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept { Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_ints.at(arg)); OX_REQUIRE(out, m_ints.at(arg));
return *out; return *out;
} }
+1 -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
+1 -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
+1 -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
+17 -17
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -18,7 +18,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
size_t outSz{}; size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1; auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
buffRaw += fmtSz; buffRaw += fmtSz;
@@ -26,7 +26,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += fmtSz; outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1; auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
buffRaw += s2Size; buffRaw += s2Size;
@@ -34,7 +34,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += s2Size; outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1; auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
buffRaw += s3Size; buffRaw += s3Size;
@@ -48,7 +48,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffLen = buff.size(); auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw); auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
StringView const fmt(buffRaw, s1Size); StringView const fmt(buffRaw, s1Size);
@@ -57,7 +57,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw); auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
StringView const typeName(buffRaw, s2Size); StringView const typeName(buffRaw, s2Size);
@@ -66,7 +66,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s3End = ox::strchr(buffRaw, ';', buffLen); auto const s3End = ox::strchr(buffRaw, ';', buffLen);
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
StringView const versionStr(buffRaw, s3Size); StringView const versionStr(buffRaw, s3Size);
@@ -78,36 +78,36 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} else if (fmt == "O1") { } else if (fmt == "O1") {
hdr.fmt = ClawFormat::Organic; hdr.fmt = ClawFormat::Organic;
} else { } else {
return OxError(4, "Claw format does not match any supported format/version combo"); return ox::Error(4, "Claw format does not match any supported format/version combo");
} }
hdr.typeName = typeName; hdr.typeName = typeName;
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion); std::ignore = ox::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(ox::BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
return {{header.data, header.dataSize}}; return {{header.data, header.dataSize}};
} }
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept { Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
auto const [t, tdErr] = ts.getLoad( auto const [t, tdErr] = ts.getLoad(
header.typeName, header.typeVersion, header.typeParams); header.typeName, header.typeVersion, header.typeParams);
if (tdErr) { if (tdErr) {
return OxError(3, "Could not load type descriptor"); return ox::Error(3, "Could not load type descriptor");
} }
ModelObject obj; ModelObject obj;
oxReturnError(obj.setType(t)); OX_RETURN_ERROR(obj.setType(t));
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
{ {
ox::BufferReader br({header.data, header.dataSize}); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
} }
case ClawFormat::Organic: case ClawFormat::Organic:
@@ -115,16 +115,16 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader({header.data, header.dataSize}); OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
#else #else
break; break;
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
} }
+7 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -40,12 +40,12 @@ Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
template<typename T> template<typename T>
Error readClaw(ox::BufferView buff, T &val) { Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
if (header.typeName != getModelTypeName<T>()) { if (header.typeName != getModelTypeName<T>()) {
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); return ox::Error(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
} }
if (header.typeVersion != getModelTypeVersion<T>()) { if (header.typeVersion != getModelTypeVersion<T>()) {
return OxError(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch"); return ox::Error(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch");
} }
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
@@ -65,15 +65,15 @@ Error readClaw(ox::BufferView buff, T &val) {
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
Result<T> readClaw(ox::BufferView buff) { Result<T> readClaw(ox::BufferView buff) {
Result<T> val; Result<T> val;
oxReturnError(readClaw(buff, val.value)); OX_RETURN_ERROR(readClaw(buff, val.value));
return val; return val;
} }
+1 -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
+36 -36
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -62,45 +62,45 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
int unionIdx = 0; int unionIdx = 0;
if constexpr(T::opType() != ox::OpType::Reflect) { if constexpr(T::opType() != ox::OpType::Reflect) {
unionIdx = obj->unionIdx; unionIdx = obj->unionIdx;
} }
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
static std::map<ox::StringView, ox::Error(*)()> tests = { static std::map<ox::StringView, ox::Error(*)()> tests = {
@@ -109,24 +109,24 @@ 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");
oxAssert(ch.typeVersion == 2, "Type version wrong"); oxAssert(ch.typeVersion == 2, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"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");
oxAssert(ch.typeVersion == 3, "Type version wrong"); oxAssert(ch.typeVersion == 3, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -134,7 +134,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3"); constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1})); OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.size() + 1}));
oxExpect(actual, expected); oxExpect(actual, expected);
return ox::Error{}; return ox::Error{};
} }
@@ -145,8 +145,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
// This test doesn't confirm much, but it does show that the writer // This test doesn't confirm much, but it does show that the writer
// doesn't segfault // doesn't segfault
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal)); OX_RETURN_ERROR(ox::writeClaw(ts, ox::ClawFormat::Metal));
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -191,7 +191,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
} }
+1 -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
+15 -15
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -39,7 +39,7 @@ struct TypeInfoCatcher {
} }
constexpr Error field(...) noexcept { constexpr Error field(...) noexcept {
return OxError(0); return {};
} }
static constexpr auto opType() { static constexpr auto opType() {
@@ -76,21 +76,21 @@ template<typename T>
ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept { ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept {
switch (fmt) { switch (fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
oxReturnError(write(writer, "M2;")); OX_RETURN_ERROR(write(writer, "M2;"));
break; break;
case ClawFormat::Organic: case ClawFormat::Organic:
oxReturnError(write(writer, "O1;")); OX_RETURN_ERROR(write(writer, "O1;"));
break; break;
default: default:
return OxError(1); return ox::Error(1);
} }
oxReturnError(write(writer, detail::getTypeName(t))); OX_RETURN_ERROR(write(writer, detail::getTypeName(t)));
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
const auto tn = detail::getTypeVersion(t); const auto tn = detail::getTypeVersion(t);
if (tn > -1) { if (tn > -1) {
oxReturnError(ox::writeItoa(tn, writer)); OX_RETURN_ERROR(ox::writeItoa(tn, writer));
} }
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
return {}; return {};
} }
@@ -102,19 +102,19 @@ Result<Buffer> writeClaw(
std::size_t buffReserveSz = 2 * units::KB) noexcept { std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer out(buffReserveSz); Buffer out(buffReserveSz);
BufferWriter bw(&out, 0); BufferWriter bw(&out, 0);
oxReturnError(detail::writeClawHeader(bw, &t, fmt)); OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt));
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
if (fmt == ClawFormat::Metal) { if (fmt == ClawFormat::Metal) {
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
} else if (fmt == ClawFormat::Organic) { } else if (fmt == ClawFormat::Organic) {
oxRequire(data, writeOC(t)); OX_REQUIRE(data, writeOC(t));
oxReturnError(bw.write(data.data(), data.size())); OX_RETURN_ERROR(bw.write(data.data(), data.size()));
} }
#else #else
if (fmt != ClawFormat::Metal) { if (fmt != ClawFormat::Metal) {
return OxError(1, "OC is not supported in this build"); return ox::Error(1, "OC is not supported in this build");
} }
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
#endif #endif
out.resize(bw.tellp()); out.resize(bw.tellp());
return out; return out;
+1 -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
+1 -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
+22 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -57,7 +57,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype(f(args...))>::value) { if constexpr(detail::isError<decltype(f(args...))>::value) {
oxThrowError(f(args...)); OX_THROW_ERROR(f(args...));
} else { } else {
f(args...); f(args...);
} }
@@ -76,7 +76,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
f(args...); f(args...);
} }
@@ -107,7 +107,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
(m_receiver->*(m_methodPtr))(args...); (m_receiver->*(m_methodPtr))(args...);
} }
@@ -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;
@@ -193,11 +198,11 @@ Error Signal<Args...>::disconnectObject(const void *receiver) const noexcept {
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@@ -213,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 OxError(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);
} }
} }
@@ -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;
@@ -381,11 +391,11 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@@ -398,9 +408,9 @@ void Signal<Error(Args...)>::emit(Args... args) const noexcept {
template<class... Args> template<class... Args>
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept { Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
oxReturnError(f->call(ox::forward<Args>(args)...)); OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
} }
return OxError(0); return {};
} }
} }
+6 -6
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,7 +17,7 @@ struct TestStruct: public ox::SignalHandler {
int value = 0; int value = 0;
ox::Error method(int i) noexcept { ox::Error method(int i) noexcept {
value = i; value = i;
return OxError(0); return ox::Error(0);
} }
}; };
@@ -27,13 +27,13 @@ std::map<ox::StringView, std::function<ox::Error()>> tests = {
[] { [] {
ox::Signal<ox::Error(int)> signal; ox::Signal<ox::Error(int)> signal;
signal.connect([](int i) -> ox::Error { signal.connect([](int i) -> ox::Error {
return OxError(i != 5); return ox::Error(i != 5);
}); });
TestStruct ts; TestStruct ts;
signal.connect(&ts, &TestStruct::method); signal.connect(&ts, &TestStruct::method);
oxReturnError(signal.emitCheckError(5)); OX_RETURN_ERROR(signal.emitCheckError(5));
oxReturnError(OxError(ts.value != 5)); OX_RETURN_ERROR(ox::Error(ts.value != 5));
return OxError(0); return ox::Error(0);
} }
}, },
}; };
+1 -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
+54 -54
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
@@ -207,12 +207,12 @@ Error FileStoreTemplate<size_t>::format(void *buffer, std::size_t bufferSize) {
auto fsData = nb->malloc(sizeof(FileStoreData)).value; auto fsData = nb->malloc(sizeof(FileStoreData)).value;
if (!fsData.valid()) { if (!fsData.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
auto data = nb->template dataOf<FileStoreData>(fsData); auto data = nb->template dataOf<FileStoreData>(fsData);
if (!data.valid()) { if (!data.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
new (data) FileStoreData; new (data) FileStoreData;
return {}; return {};
@@ -223,24 +223,24 @@ Error FileStoreTemplate<size_t>::setSize(std::size_t size) {
if (m_buffSize >= size) { if (m_buffSize >= size) {
return m_buffer->setSize(static_cast<size_t>(size)); return m_buffer->setSize(static_cast<size_t>(size));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) { Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
++item->links; ++item->links;
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::decLinks(uint64_t id) { Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
--item->links; --item->links;
if (item->links == 0) { if (item->links == 0) {
oxReturnError(remove(item)); OX_RETURN_ERROR(remove(item));
} }
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
@@ -249,7 +249,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id); oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id);
auto existing = find(id); auto existing = find(id);
if (!canWrite(existing, dataSize)) { if (!canWrite(existing, dataSize)) {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
existing = find(id); existing = find(id);
} }
@@ -269,7 +269,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
// if first malloc failed, compact and try again // if first malloc failed, compact and try again
if (!dest.valid()) { if (!dest.valid()) {
oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting"); oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting");
oxReturnError(compact()); OX_RETURN_ERROR(compact());
dest = m_buffer->malloc(dataSize).value; dest = m_buffer->malloc(dataSize).value;
} }
if (dest.valid()) { if (dest.valid()) {
@@ -298,16 +298,16 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
dest->id.get(), dest.offset(), destData.size()); dest->id.get(), dest.offset(), destData.size());
fsData->rootNode = dest.offset(); fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return OxError(0); return {};
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
} }
} }
} }
oxReturnError(m_buffer->free(dest)); OX_RETURN_ERROR(m_buffer->free(dest));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
@@ -322,7 +322,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1, "Could not find requested item"); return ox::Error(1, "Could not find requested item");
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@@ -335,7 +335,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), outSize); "Item data section size: {}, Expected size: {}", srcData.size(), outSize);
return OxError(1, "Invalid inode"); return ox::Error(1, "Invalid inode");
} }
ox::memcpy(out, srcData, srcData.size()); ox::memcpy(out, srcData, srcData.size());
@@ -353,7 +353,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@@ -366,7 +366,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@@ -386,7 +386,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@@ -399,7 +399,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@@ -422,30 +422,30 @@ ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(uint64_t id)
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize() { Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
const auto newSize = static_cast<std::size_t>(size() - available()); const auto newSize = static_cast<std::size_t>(size() - available());
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
oxReturnError(m_buffer->setSize(newSize)); OX_RETURN_ERROR(m_buffer->setSize(newSize));
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) { if (m_buffer->size() > size) {
return OxError(1); return ox::Error{1, "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);
oxReturnError(m_buffer->setSize(static_cast<size_t>(size))); OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
} }
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const { Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const {
oxRequire(inode, find(static_cast<size_t>(id)).validate()); OX_REQUIRE(inode, find(static_cast<size_t>(id)).validate());
return StatInfo { return StatInfo {
id, id,
inode->links, inode->links,
@@ -477,16 +477,16 @@ char *FileStoreTemplate<size_t>::buff() {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) { for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
oxReturnError(cb(i->fileType, i.ptr().offset(), i.ptr().end())); OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
} }
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() { Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
for (auto i = 0; i < 100; i++) { for (auto i = 0; i < 100; i++) {
auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>); auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>);
@@ -494,7 +494,7 @@ Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>:
return inode; return inode;
} }
} }
return OxError(2); return ox::Error(2);
} }
template<typename size_t> template<typename size_t>
@@ -503,10 +503,10 @@ Error FileStoreTemplate<size_t>::compact() {
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
if (isFirstItem) { if (isFirstItem) {
isFirstItem = false; isFirstItem = false;
return OxError(0); return {};
} }
if (!item.valid()) { if (!item.valid()) {
return OxError(1); return ox::Error(1);
} }
oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset()); oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset());
// update rootInode if this is it // update rootInode if this is it
@@ -524,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
parent->right = item; parent->right = item;
} }
} }
return OxError(0); return {};
}); });
} }
@@ -544,15 +544,15 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
fsData->rootNode = item; fsData->rootNode = item;
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return OxError(0); return {};
} else { } else {
return placeItem(root, item); return placeItem(root, item);
} }
@@ -562,7 +562,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth > 5000) { if (depth > 5000) {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(2); return ox::Error(2);
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@@ -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 OxError(0); return {};
} else { } else {
return placeItem(right, item, depth + 1); return placeItem(right, item, depth + 1);
} }
@@ -586,13 +586,13 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = left->right; item->right = left->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0); return {};
} else { } else {
return placeItem(left, item, depth + 1); return placeItem(left, item, depth + 1);
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself.");
return OxError(1, "Cannot insert an item on itself."); return ox::Error(1, "Cannot insert an item on itself.");
} }
} }
@@ -600,9 +600,9 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
@@ -624,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else { } else {
fsData->rootNode = 0; fsData->rootNode = 0;
} }
return OxError(0); return {};
} else { } else {
return unplaceItem(root, item); return unplaceItem(root, item);
} }
@@ -634,7 +634,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth >= 5000) { if (depth >= 5000) {
oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(1, "Excessive recursion depth, stopping before stack overflow."); return ox::Error(1, "Excessive recursion depth, stopping before stack overflow.");
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@@ -653,25 +653,25 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
return unplaceItem(left, item, depth + 1); return unplaceItem(left, item, depth + 1);
} }
} else { } else {
return OxError(1); return ox::Error(1);
} }
if (item->right) { if (item->right) {
oxReturnError(placeItem(m_buffer->ptr(item->right))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->right)));
} }
if (item->left) { if (item->left) {
oxReturnError(placeItem(m_buffer->ptr(item->left))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
} }
return OxError(0); return {};
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::remove(ItemPtr item) { Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) { if (item.valid()) {
oxReturnError(unplaceItem(item)); OX_RETURN_ERROR(unplaceItem(item));
oxReturnError(m_buffer->free(item)); OX_RETURN_ERROR(m_buffer->free(item));
return OxError(0); return {};
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
+30 -30
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,10 +52,10 @@ 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 OxError(1); return ox::Error(1);
} }
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept { ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
@@ -141,11 +141,11 @@ template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::init() noexcept { Error Directory<FileStore, InodeId_t>::init() noexcept {
constexpr auto Size = sizeof(Buffer); constexpr auto Size = sizeof(Buffer);
oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId); oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId);
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory))); OX_RETURN_ERROR(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory)));
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
m_size = 0; m_size = 0;
return OxError(1); return ox::Error(1);
} }
new (buff) Buffer(Size); new (buff) Buffer(Size);
m_size = Size; m_size = Size;
@@ -158,21 +158,21 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
oxTrace("ox.fs.Directory.mkdir", path.fullPath()); oxTrace("ox.fs.Directory.mkdir", path.fullPath());
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
auto childInode = find(PathIterator(name)); auto childInode = find(PathIterator(name));
if (!childInode.ok()) { if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled, // if this is not the last item in the path and parents is disabled,
// return an error // return an error
if (!parents && path.hasNext()) { if (!parents && path.hasNext()) {
return OxError(1); return ox::Error(1);
} }
childInode = m_fs.generateInodeId(); childInode = m_fs.generateInodeId();
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value); oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
oxLogError(childInode.error); oxLogError(childInode.error);
oxReturnError(childInode.error); OX_RETURN_ERROR(childInode.error);
// initialize the directory // initialize the directory
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
oxReturnError(child.init()); OX_RETURN_ERROR(child.init());
auto err = write(PathIterator(name), childInode.value); auto err = write(PathIterator(name), childInode.value);
if (err) { if (err) {
oxLogError(err); oxLogError(err);
@@ -183,7 +183,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
} }
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
if (path.hasNext()) { if (path.hasNext()) {
oxReturnError(child.mkdir(path.next(), parents)); OX_RETURN_ERROR(child.mkdir(path.next(), parents));
} }
} }
return {}; return {};
@@ -196,45 +196,45 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
if (path.next().hasNext()) { // not yet at target directory, recurse to next one if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}", oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
name, path.fullPath()); name, path.fullPath());
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(nextChild, findEntry(name)); OX_REQUIRE(nextChild, findEntry(name));
oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild); oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild);
if (nextChild) { if (nextChild) {
return Directory(m_fs, nextChild).write(path.next(), inode); return Directory(m_fs, nextChild).write(path.next(), inode);
} else { } else {
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name); oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name);
return OxError(1, "File not found and not allowed to create it."); return ox::Error(1, "File not found and not allowed to create it.");
} }
} else { } else {
oxTrace("ox.fs.Directory.write", path.fullPath()); oxTrace("ox.fs.Directory.write", path.fullPath());
oxReturnError(path.next(name)); OX_RETURN_ERROR(path.next(name));
// insert the new entry on this directory // insert the new entry on this directory
// get the name // get the name
// find existing version of directory // find existing version of directory
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId); oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
oxRequire(oldStat, m_fs.stat(m_inodeId)); OX_REQUIRE(oldStat, m_fs.stat(m_inodeId));
oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size); oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size);
auto old = m_fs.read(m_inodeId).template to<Buffer>(); auto old = m_fs.read(m_inodeId).template to<Buffer>();
if (!old.valid()) { if (!old.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
return OxError(1, "Could not read existing version of Directory"); return ox::Error(1, "Could not read existing version of Directory");
} }
const auto pathSize = name.len() + 1; const auto pathSize = name.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);
if (cpy == nullptr) { if (cpy == nullptr) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
return OxError(1, "Could not allocate memory for copy of Directory"); return ox::Error(1, "Could not allocate memory for copy of Directory");
} }
oxReturnError(cpy->setSize(newSize)); OX_RETURN_ERROR(cpy->setSize(newSize));
auto val = cpy->malloc(entryDataSize).value; auto val = cpy->malloc(entryDataSize).value;
if (!val.valid()) { if (!val.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
return OxError(1, "Could not allocate memory for new directory entry"); return ox::Error(1, "Could not allocate memory for new directory entry");
} }
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name); oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name);
oxReturnError(val->init(inode, name, val.size())); OX_RETURN_ERROR(val->init(inode, name, val.size()));
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory)); return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
} }
} }
@@ -242,7 +242,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxTrace("ox.fs.Directory.remove", name); oxTrace("ox.fs.Directory.remove", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (buff.valid()) { if (buff.valid()) {
@@ -251,7 +251,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
if (name == data->name) { if (name == data->name) {
oxReturnError(buff->free(i)); OX_RETURN_ERROR(buff->free(i));
} }
} else { } else {
oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
@@ -259,7 +259,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
} }
} else { } else {
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer"); oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
return OxError(1, "Could not find directory buffer"); return ox::Error(1, "Could not find directory buffer");
} }
return {}; return {};
} }
@@ -271,13 +271,13 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer"); oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
return OxError(1, "Could not directory buffer"); return ox::Error(1, "Could not directory buffer");
} }
oxTrace("ox.fs.Directory.ls", "Found directory buffer."); oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
oxReturnError(cb(data->name, data->inode)); OX_RETURN_ERROR(cb(data->name, data->inode));
} else { } else {
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
} }
@@ -291,7 +291,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer"); oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer");
return OxError(2, "Could not findEntry directory buffer"); return ox::Error(2, "Could not findEntry directory buffer");
} }
oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size()); oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size());
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
@@ -307,15 +307,15 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
} }
} }
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present"); oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
return OxError(1, "Entry not present"); return ox::Error(1, "Entry not present");
} }
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept { Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept {
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(v, findEntry(name)); OX_REQUIRE(v, findEntry(name));
// recurse if not at end of path // recurse if not at end of path
if (auto p = path.next(); p.valid()) { if (auto p = path.next(); p.valid()) {
Directory dir(m_fs, v); Directory dir(m_fs, v);
+5 -3
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;
+14 -17
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>
@@ -89,7 +86,7 @@ class FileAddress {
case FileAddressType::Inode: case FileAddressType::Inode:
return m_data.inode; return m_data.inode;
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@@ -100,7 +97,7 @@ class FileAddress {
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
return ox::CStringView(m_data.constPath); return ox::CStringView(m_data.constPath);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@@ -154,29 +151,29 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept {
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress::Data>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress::Data>());
oxReturnError(h->fieldCString("path", &obj->path)); OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path)); OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode)); OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
int8_t type = -1; int8_t type = -1;
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, type))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, type)));
} else if constexpr(T::opType() == OpType::Read) { } else if constexpr(T::opType() == OpType::Read) {
auto type = static_cast<int8_t>(fa->m_type); auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type); fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto const type = static_cast<int8_t>(fa->m_type); auto const type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} }
return {}; return {};
} }
+50 -23
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21,7 +21,7 @@ Result<const char*> MemFS::directAccess(const FileAddress &addr) const noexcept
case FileAddressType::Path: case FileAddressType::Path:
return directAccess(StringView(addr.getPath().value)); return directAccess(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@@ -33,46 +33,73 @@ Error FileSystem::read(const FileAddress &addr, void *buffer, std::size_t size)
case FileAddressType::Path: case FileAddressType::Path:
return readFilePath(StringView(addr.getPath().value), buffer, size); return readFilePath(StringView(addr.getPath().value), buffer, size);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
Result<Buffer> FileSystem::read(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 {
oxRequire(s, stat(addr)); OX_REQUIRE(s, stat(addr));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(read(addr, buff.data(), buff.size())); OX_RETURN_ERROR(read(addr, buff.data(), buff.size()));
return buff; return buff;
} }
Result<Buffer> FileSystem::read(StringViewCR path) noexcept { Result<Buffer> FileSystem::read(StringViewCR path) noexcept {
oxRequire(s, statPath(path)); OX_REQUIRE(s, statPath(path));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(readFilePath(path, buff.data(), buff.size())); OX_RETURN_ERROR(readFilePath(path, buff.data(), buff.size()));
return buff; return buff;
} }
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 OxError(2, "Unsupported for path lookups"); return readFilePathRange(addr.getPath().value, readStart, readSize, buffer, size);
default: default:
return OxError(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 OxError(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 {
@@ -83,7 +110,7 @@ Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t si
case FileAddressType::Path: case FileAddressType::Path:
return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType); return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@@ -95,7 +122,7 @@ Result<FileStat> FileSystem::stat(const FileAddress &addr) const noexcept {
case FileAddressType::Path: case FileAddressType::Path:
return statPath(StringView(addr.getPath().value)); return statPath(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }
+116 -81
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;
@@ -81,36 +101,36 @@ class FileSystem {
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
inline Error write(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.
*/ */
@@ -284,69 +312,69 @@ FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept {
oxReturnError(FileStore::format(buff, static_cast<size_t>(buffSize))); OX_RETURN_ERROR(FileStore::format(buff, static_cast<size_t>(buffSize)));
FileStore fs(buff, static_cast<size_t>(buffSize)); FileStore fs(buff, static_cast<size_t>(buffSize));
constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2; constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2;
Directory rootDir(fs, rootDirInode); Directory rootDir(fs, rootDirInode);
oxReturnError(rootDir.init()); OX_RETURN_ERROR(rootDir.init());
FileSystemData fd; FileSystemData fd;
fd.rootDirInode = rootDirInode; fd.rootDirInode = rootDirInode;
oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get()); oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get());
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(fs.write(InodeFsData, &fd, sizeof(fd)));
if (!fs.read(fd.rootDirInode).valid()) { if (!fs.read(fd.rootDirInode).valid()) {
oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory"); oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return {};
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept {
oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive); oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive);
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
return rootDir.mkdir(path, recursive); return rootDir.mkdir(path, recursive);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept { Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequireM(inode, rootDir.find(src)); OX_REQUIRE_M(inode, rootDir.find(src));
oxReturnError(rootDir.write(dest, inode)); OX_RETURN_ERROR(rootDir.write(dest, inode));
oxReturnError(rootDir.remove(src)); OX_RETURN_ERROR(rootDir.remove(src));
return OxError(0); return {};
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
oxTrace("ox.fs.FileSystemTemplate.readFilePath", path); oxTrace("ox.fs.FileSystemTemplate.readFilePath", path);
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(s, stat(path)); OX_REQUIRE(s, stat(path));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept { Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
return directAccessInode(inode); return directAccessInode(inode);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode); oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode);
oxRequire(s, stat(inode)); OX_REQUIRE(s, stat(inode));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
@@ -357,39 +385,18 @@ 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()) { OX_REQUIRE(s, stat(path));
return OxError(1, "Data not valid"); return readFileInodeRange(s.inode, readStart, readSize, buffer, buffSize);
}
return reinterpret_cast<char*>(data.get());
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept { Error FileSystemTemplate<FileStore, Directory>::removePath(StringViewCR path, bool recursive) noexcept {
Vector<String> out; OX_REQUIRE(fd, fileSystemData());
oxReturnError(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name);
return OxError(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);
oxRequire(s, stat(path));
Directory dir(m_fs, s.inode);
return dir.ls(cb);
}
template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept {
oxRequire(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
oxRequire(st, statInode(inode)); OX_REQUIRE(st, statInode(inode));
if (st.fileType == FileType::NormalFile || recursive) { if (st.fileType == FileType::NormalFile || recursive) {
if (auto err = rootDir.remove(path)) { if (auto err = rootDir.remove(path)) {
// removal failed, try putting the index back // removal failed, try putting the index back
@@ -398,9 +405,37 @@ Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool r
} }
} else { } else {
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return {};
}
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>
@@ -410,7 +445,7 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept { Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer)); OX_RETURN_ERROR(m_fs.resize(static_cast<size_t>(size), buffer));
return {}; return {};
} }
@@ -423,23 +458,23 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path); oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path);
auto [inode, err] = find(path); auto [inode, err] = find(path);
if (err) { if (err) {
oxReturnError(m_fs.generateInodeId().moveTo(inode)); OX_RETURN_ERROR(m_fs.generateInodeId().moveTo(inode));
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
oxReturnError(rootDir.write(path, inode)); OX_RETURN_ERROR(rootDir.write(path, inode));
} }
oxReturnError(writeFileInode(inode, buffer, size, fileType)); OX_RETURN_ERROR(writeFileInode(inode, buffer, size, fileType));
return {}; return {};
} }
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));
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept {
oxRequire(s, m_fs.stat(inode)); OX_REQUIRE(s, m_fs.stat(inode));
FileStat out; FileStat out;
out.inode = s.inode; out.inode = s.inode;
out.links = s.links; out.links = s.links;
@@ -450,7 +485,7 @@ Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t in
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept {
oxRequire(inode, find(path)); OX_REQUIRE(inode, find(path));
return stat(inode); return stat(inode);
} }
@@ -487,25 +522,25 @@ bool FileSystemTemplate<FileStore, Directory>::valid() const noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept { Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept {
FileSystemData fd; FileSystemData fd;
oxReturnError(m_fs.read(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(m_fs.read(InodeFsData, &fd, sizeof(fd)));
return fd; return fd;
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept { Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
// return root as a special case // return root as a special case
if (path == "/") { if (path == "/") {
return static_cast<uint64_t>(fd.rootDirInode); return static_cast<uint64_t>(fd.rootDirInode);
} }
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(out, rootDir.find(path)); OX_REQUIRE(out, rootDir.find(path));
return static_cast<uint64_t>(out); return static_cast<uint64_t>(out);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept { Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
return Directory(m_fs, fd.rootDirInode); return Directory(m_fs, fd.rootDirInode);
} }
+51 -31
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directories(p, ec); success = std::filesystem::create_directories(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} else { } else {
std::error_code ec; std::error_code ec;
@@ -48,26 +48,26 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directory(p, ec); success = std::filesystem::create_directory(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} }
return OxError(success ? 0 : 1); return ox::Error(success ? 0 : 1);
} }
Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept { Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
std::error_code ec; std::error_code ec;
std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec); std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec);
if (ec.value()) { if (ec.value()) {
return OxError(1); return ox::Error(1);
} }
return OxError(0); return {};
} }
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
Vector<String> out; Vector<String> out;
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (const auto &p : di) { for (const auto &p : di) {
const auto u8p = p.path().filename().u8string(); const auto u8p = p.path().filename().u8string();
out.emplace_back(reinterpret_cast<const char*>(u8p.c_str())); out.emplace_back(reinterpret_cast<const char*>(u8p.c_str()));
@@ -75,22 +75,14 @@ Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
return out; return out;
} }
Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept {
if (recursive) {
return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
} else {
return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0);
}
}
Error PassThroughFS::resize(uint64_t, void*) noexcept { Error PassThroughFS::resize(uint64_t, void*) noexcept {
// unsupported // unsupported
return OxError(1, "resize is not supported by PassThroughFS"); return ox::Error(1, "resize is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept { Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept {
// unsupported // unsupported
return OxError(1, "statInode(uint64_t) is not supported by PassThroughFS"); return ox::Error(1, "statInode(uint64_t) is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept { Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
@@ -101,7 +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);
oxReturnError(OxError(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};
} }
@@ -112,14 +106,14 @@ uint64_t PassThroughFS::spaceNeeded(uint64_t size) const noexcept {
Result<uint64_t> PassThroughFS::available() const noexcept { Result<uint64_t> PassThroughFS::available() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.available; return s.available;
} }
Result<uint64_t> PassThroughFS::size() const noexcept { Result<uint64_t> PassThroughFS::size() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.capacity; return s.capacity;
} }
@@ -128,7 +122,7 @@ char *PassThroughFS::buff() noexcept {
} }
Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept { Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept {
return OxError(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS"); return ox::Error(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS");
} }
bool PassThroughFS::valid() const noexcept { bool PassThroughFS::valid() const noexcept {
@@ -147,24 +141,51 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
if (size > buffSize) { if (size > buffSize) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path); oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
return OxError(1); return ox::Error(1);
} }
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize)); file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return OxError(2); return ox::Error(2);
} }
return OxError(0); return {};
} }
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
// unsupported // unsupported
return OxError(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS"); return ox::Error(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS");
}
Error PassThroughFS::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 OxError(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS"); return ox::Error(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS");
}
Error PassThroughFS::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 {
@@ -174,19 +195,18 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size)); f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return OxError(1); return ox::Error(1);
} }
return OxError(0); return {};
} }
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
// unsupported // unsupported
return OxError(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS"); return ox::Error(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS");
} }
std::string_view PassThroughFS::stripSlash(StringView path) noexcept { std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
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()};
+9 -6
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;
@@ -92,11 +95,11 @@ template<typename F>
Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept { Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (auto &p : di) { for (auto &p : di) {
oxReturnError(cb(p.path().filename().c_str(), 0)); OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
} }
return OxError(0); return {};
} }
} }
+14 -14
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,9 +36,9 @@ 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 OxError(0); return {};
} else { } else {
return OxError(1); return ox::Error(1);
} }
} }
@@ -47,11 +47,11 @@ Error PathIterator::get(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
if (m_iterator >= m_maxSize) { if (m_iterator >= m_maxSize) {
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize); oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
return OxError(1); return ox::Error(1);
} }
if (!ox::strlen(&m_path[m_iterator])) { if (!ox::strlen(&m_path[m_iterator])) {
oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])"); oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])");
return OxError(1); return ox::Error(1);
} }
auto start = m_iterator; auto start = m_iterator;
if (m_path[start] == '/') { if (m_path[start] == '/') {
@@ -67,14 +67,14 @@ Error PathIterator::get(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength || size == 0) { if (size >= MaxFileNameLength || size == 0) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
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 {};
} }
@@ -83,9 +83,9 @@ Error PathIterator::get(StringView &fileName) {
*/ */
Error PathIterator::next(StringView &fileName) { Error PathIterator::next(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = OxError(0); retval = {};
if (m_path[m_iterator] == '/') { if (m_path[m_iterator] == '/') {
m_iterator++; m_iterator++;
} }
@@ -100,25 +100,25 @@ Error PathIterator::next(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength) { if (size >= MaxFileNameLength) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
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;
} }
Result<std::size_t> PathIterator::nextSize() const { Result<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
auto it = m_iterator; auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) { if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = OxError(0); retval = {};
if (m_path[it] == '/') { if (m_path[it] == '/') {
it++; it++;
} }
+1 -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
+1 -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
+1 -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
+15 -15
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -284,14 +284,14 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
addr = m_header.firstItem; addr = m_header.firstItem;
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state.");
return OxError(1, "NodeBuffer is in invalid state."); return ox::Error(1, "NodeBuffer is in invalid state.");
} }
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize); oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize);
auto out = ItemPtr(this, m_header.size, addr, fullSize); auto out = ItemPtr(this, m_header.size, addr, fullSize);
if (!out.valid()) { if (!out.valid()) {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown"); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown");
return OxError(1, "NodeBuffer::malloc: unknown failure"); return ox::Error(1, "NodeBuffer::malloc: unknown failure");
} }
ox::memset(out, 0, fullSize); ox::memset(out, 0, fullSize);
new (out) Item; new (out) Item;
@@ -304,7 +304,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
first->prev = out.offset(); first->prev = out.offset();
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid first element pointer.");
} }
if (oldLast.valid()) { if (oldLast.valid()) {
@@ -314,7 +314,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
if (out.offset() != first.offset()) { if (out.offset() != first.offset()) {
// if this is not the first allocation, there should be an oldLast // if this is not the first allocation, there should be an oldLast
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid last element pointer.");
} }
out->prev = out.offset(); out->prev = out.offset();
} }
@@ -323,7 +323,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
return out; return out;
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available()); oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available());
return OxError(1); return ox::Error(1);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@@ -346,15 +346,15 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} else { } else {
if (!prev.valid()) { if (!prev.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset());
return OxError(1); return ox::Error(1);
} }
if (!next.valid()) { if (!next.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset());
return OxError(1); return ox::Error(1);
} }
} }
m_header.bytesUsed -= item.size(); m_header.bytesUsed -= item.size();
return OxError(0); return {};
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@@ -365,12 +365,12 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end); oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end);
if (end > size) { if (end > size) {
// resizing to less than buffer size // resizing to less than buffer size
return OxError(1); return ox::Error(1);
} else { } else {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end; auto data = reinterpret_cast<uint8_t*>(this) + end;
ox::memset(data, 0, size - end); ox::memset(data, 0, size - end);
return OxError(0); return {};
} }
} }
@@ -401,14 +401,14 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
auto dest = ptr(sizeof(*this)); auto dest = ptr(sizeof(*this));
while (dest.offset() <= src.offset()) { while (dest.offset() <= src.offset()) {
if (!src.valid()) { if (!src.valid()) {
return OxError(1); return ox::Error(1);
} }
if (!dest.valid()) { if (!dest.valid()) {
return OxError(2); return ox::Error(2);
} }
// move node // move node
ox::memcpy(dest, src, src->fullSize()); ox::memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest)); OX_RETURN_ERROR(cb(src, dest));
// update surrounding nodes // update surrounding nodes
auto prev = ptr(dest->prev); auto prev = ptr(dest->prev);
if (prev.valid()) { if (prev.valid()) {
@@ -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 OxError(0); return {};
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
+2 -2
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
@@ -254,7 +254,7 @@ constexpr Result<Ptr<T, size_t, minOffset>> Ptr<T, size_t, minOffset>::validate(
if (valid()) { if (valid()) {
return *this; return *this;
} }
return OxError(1); return ox::Error(1);
} }
} }
+26 -20
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,19 +52,19 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(buffer->free(a1), "Free failed."); oxAssert(buffer->free(a1), "Free failed.");
oxAssert(buffer->free(a2), "Free failed."); oxAssert(buffer->free(a2), "Free failed.");
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed."); oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"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");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -77,17 +77,17 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxExpect(buff, "usr"); oxExpect(buff, "usr");
oxAssert(it.next(buff), "PathIterator::next returned error"); oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "share"); oxExpect(buff, "share");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"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 OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -99,38 +99,42 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"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");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"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
return OxError(0); 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);
} }
}, },
{ {
"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 OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -142,7 +146,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto subPtr = p.subPtr<uint64_t>(50); auto subPtr = p.subPtr<uint64_t>(50);
oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid."); oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -155,7 +159,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto first = list->firstItem(); auto first = list->firstItem();
oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item"); oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item");
oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid"); oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -163,9 +167,11 @@ 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);
@@ -176,7 +182,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
size_t str1ReadSize = 0; size_t str1ReadSize = 0;
oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed."); oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -203,7 +209,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxTrace("ox.fs.test.Directory") << "write 3"; oxTrace("ox.fs.test.Directory") << "write 3";
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed"); oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@@ -220,7 +226,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed"); oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
return OxError(0); return ox::Error(0);
} }
}, },
}, },
+15 -13
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20,7 +20,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
std::ifstream file(path, std::ios::binary | std::ios::ate); std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.good()) { if (!file.good()) {
oxErrorf("Could not find OxFS file: {}", path); oxErrorf("Could not find OxFS file: {}", path);
return OxError(1, "Could not find OxFS file"); return ox::Error(1, "Could not find OxFS file");
} }
try { try {
const auto size = static_cast<std::size_t>(file.tellg()); const auto size = static_cast<std::size_t>(file.tellg());
@@ -30,52 +30,54 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
return Buff{buff, size}; return Buff{buff, size};
} catch (const std::ios_base::failure &e) { } catch (const std::ios_base::failure &e) {
oxErrorf("Could not read OxFS file: {}", e.what()); oxErrorf("Could not read OxFS file: {}", e.what());
return OxError(2, "Could not read OxFS file"); return ox::Error(2, "Could not read OxFS file");
} }
} }
static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept { static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept {
oxRequire(buff, loadFsBuff(path)); OX_REQUIRE(buff, loadFsBuff(path));
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
} }
static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept { static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (args.size() < 2) { if (args.size() < 2) {
oxErr("Must provide a directory to ls\n"); oxErr("Must provide a directory to ls\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(files, fs->ls(args[1])); OX_REQUIRE(files, fs->ls(args[1]));
for (const auto &file : files) { for (const auto &file : files) {
oxOutf("{}\n", file); oxOutf("{}\n", file);
} }
return OxError(0); return {};
} }
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 {
if (args.size() < 2) { if (args.size() < 2) {
oxErr("Must provide a path to a file to read\n"); oxErr("Must provide a path to a file to read\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(buff, fs->read(ox::StringView(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 OxError(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 {
if (argc < 3) { if (argc < 3) {
oxErr("OxFS file and subcommand arguments are required\n"); oxErr("OxFS file and subcommand arguments are required\n");
return OxError(1); return ox::Error(1);
} }
auto const args = ox::Span{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const fsPath = args[1]; auto const fsPath = args[1];
ox::String subCmd(args[2]); ox::String subCmd(args[2]);
oxRequire(fs, loadFs(fsPath)); OX_REQUIRE(fs, loadFs(fsPath));
if (subCmd == "ls") { if (subCmd == "ls") {
return runLs(fs.get(), args + 2); return runLs(fs.get(), args + 2);
} else if (subCmd == "read") { } else if (subCmd == "read") {
return runRead(fs.get(), args + 2); return runRead(fs.get(), args + 2);
} }
return OxError(1); return ox::Error(1);
} }
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
+5 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34,7 +34,7 @@ class CirculerBuffer {
constexpr ox::Error put(char v) noexcept { constexpr ox::Error put(char v) noexcept {
return write(&v, 1); return write(&v, 1);
if (1 > avail()) { if (1 > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
m_buff[m_writePt] = v; m_buff[m_writePt] = v;
++m_writePt; ++m_writePt;
@@ -43,7 +43,7 @@ class CirculerBuffer {
constexpr ox::Error write(const char *buff, std::size_t sz) noexcept { constexpr ox::Error write(const char *buff, std::size_t sz) noexcept {
if (sz > avail()) { if (sz > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// write seg 1 // write seg 1
@@ -63,7 +63,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END
constexpr ox::Error seekp(std::size_t bytesFwd) noexcept { constexpr ox::Error seekp(std::size_t bytesFwd) noexcept {
if (bytesFwd > avail()) { if (bytesFwd > avail()) {
return OxError(1, "Insufficient space in buffer to seek that far ahead"); return ox::Error(1, "Insufficient space in buffer to seek that far ahead");
} }
m_writePt += bytesFwd; m_writePt += bytesFwd;
if (m_writePt > m_buff.size()) { if (m_writePt > m_buff.size()) {
@@ -73,7 +73,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END
} }
constexpr ox::Error seekp(int, ios_base::seekdir) noexcept { constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
return OxError(1, "Unimplemented"); return ox::Error(1, "Unimplemented");
} }
[[nodiscard]] [[nodiscard]]
+2 -2
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)); \
} \ } \
+8 -3
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
@@ -64,7 +64,7 @@ ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept {
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(5590); addr.sin_port = htons(5590);
m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(static_cast<Socket>(m_socket), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(connect(static_cast<Socket>(m_socket), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
return sendInit({.appName = ox::BasicString<128>(appName)}); return sendInit({.appName = ox::BasicString<128>(appName)});
} }
@@ -75,7 +75,7 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
const auto sent = ::send(static_cast<Socket>(m_socket), buff, static_cast<LenType>(len), 0); const auto sent = ::send(static_cast<Socket>(m_socket), buff, static_cast<LenType>(len), 0);
if (sent < 0) { if (sent < 0) {
std::ignore = std::fprintf(stderr, "Could not send msg\n"); std::ignore = std::fprintf(stderr, "Could not send msg\n");
return OxError(1, "Could not send msg"); return ox::Error(1, "Could not send msg");
} }
totalSent += static_cast<std::size_t>(sent); totalSent += static_cast<std::size_t>(sent);
} }
@@ -91,6 +91,7 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
} }
void LoggerConn::msgSend() noexcept { void LoggerConn::msgSend() noexcept {
try {
while (true) { while (true) {
std::unique_lock lk(m_waitMut); std::unique_lock lk(m_waitMut);
m_waitCond.wait(lk); m_waitCond.wait(lk);
@@ -109,6 +110,10 @@ void LoggerConn::msgSend() noexcept {
std::ignore = send(tmp.data(), 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");
}
} }
} }
+6 -6
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -45,13 +45,13 @@ class LoggerConn: public trace::Logger {
ox::Error send(trace::MsgId msgId, const auto &msg) noexcept { ox::Error send(trace::MsgId msgId, const auto &msg) noexcept {
ox::Array<char, 10 * ox::units::KB> buff; ox::Array<char, 10 * ox::units::KB> buff;
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(&buff[0], buff.size(), msg, &sz)); OX_RETURN_ERROR(ox::writeMC(&buff[0], buff.size(), msg, &sz));
//std::printf("sz: %lu\n", sz); //std::printf("sz: %lu\n", sz);
oxRequire(szBuff, serialize(static_cast<uint32_t>(sz))); OX_REQUIRE(szBuff, serialize(static_cast<uint32_t>(sz)));
std::unique_lock buffLk(m_buffMut); std::unique_lock buffLk(m_buffMut);
oxReturnError(m_buff.put(static_cast<char>(msgId))); OX_RETURN_ERROR(m_buff.put(static_cast<char>(msgId)));
oxReturnError(m_buff.write(szBuff.data(), szBuff.size())); OX_RETURN_ERROR(m_buff.write(szBuff.data(), szBuff.size()));
oxReturnError(m_buff.write(buff.data(), sz)); OX_RETURN_ERROR(m_buff.write(buff.data(), sz));
buffLk.unlock(); buffLk.unlock();
m_waitCond.notify_one(); m_waitCond.notify_one();
return {}; return {};
+1 -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
+16 -6
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
@@ -71,7 +71,9 @@ constexpr McInt encodeInteger(I pInput) noexcept {
// 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; uint64_t val = 0;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&val, &input, sizeof(input)); ox::memcpy(&val, &input, sizeof(input));
OX_ALLOW_UNSAFE_BUFFERS_END
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
@@ -94,7 +96,9 @@ 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;
} }
@@ -104,7 +108,9 @@ constexpr McInt encodeInteger(I pInput) noexcept {
auto intermediate = auto intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
OX_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;
} }
@@ -135,19 +141,19 @@ static_assert(countBytes(0b1111'1111) == 9);
template<typename I> template<typename I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept { constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
uint8_t firstByte = 0; uint8_t firstByte = 0;
oxReturnError(rdr.read(&firstByte, 1)); OX_RETURN_ERROR(rdr.read(&firstByte, 1));
oxReturnError(rdr.seekg(-1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte); const auto bytes = countBytes(firstByte);
if (bytes == 9) { if (bytes == 9) {
*bytesRead = bytes; *bytesRead = bytes;
I out = 0; I out = 0;
oxReturnError(rdr.seekg(1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
oxReturnError(rdr.read(&out, sizeof(I))); OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
return fromLittleEndian<I>(out); return fromLittleEndian<I>(out);
} }
*bytesRead = bytes; *bytesRead = bytes;
uint64_t decoded = 0; uint64_t decoded = 0;
oxReturnError(rdr.read(&decoded, bytes)); OX_RETURN_ERROR(rdr.read(&decoded, bytes));
decoded >>= bytes; decoded >>= bytes;
// move sign bit // move sign bit
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
@@ -160,7 +166,9 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
ox::Array<uint32_t, 2> d = {}; ox::Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&d[0], &decoded, sizeof(decoded)); ox::memcpy(&d[0], &decoded, sizeof(decoded));
OX_ALLOW_UNSAFE_BUFFERS_END
auto bit = negBit; auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
d[0] |= 1 << bit; d[0] |= 1 << bit;
@@ -175,7 +183,9 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
d[0] = d[1]; d[0] = d[1];
d[1] = d0Tmp; d[1] = d0Tmp;
} }
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&out, &d[0], sizeof(out)); ox::memcpy(&out, &d[0], sizeof(out));
OX_ALLOW_UNSAFE_BUFFERS_END
return out; return out;
} }
} }
+1 -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
+1 -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
+8 -8
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -47,7 +47,7 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
constexpr auto blockBits = sizeof(m_mapBlock); constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits; auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] { if (m_mapBlockIdx != blockIdx) [[unlikely]] {
oxReturnError(loadMapBlock(blockIdx)); OX_RETURN_ERROR(loadMapBlock(blockIdx));
} }
idx %= blockBits; idx %= blockBits;
return (m_mapBlock >> idx) & 1; return (m_mapBlock >> idx) & 1;
@@ -55,12 +55,12 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
template<Reader_c Reader> template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept { constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{}; ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv // Warning: narrow-conv
oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0; m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) { for (auto i = 0ull; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i; m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
@@ -110,7 +110,7 @@ constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexce
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1; return (m_map[i / 8] >> (i % 8)) & 1;
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }
@@ -156,7 +156,7 @@ OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }
+1 -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
+51 -51
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -194,10 +194,10 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field)); auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
*val = result.value; *val = result.value;
oxReturnError(result); OX_RETURN_ERROR(result);
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
// array handler // array handler
@@ -207,20 +207,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *v
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
if (valLen >= len) { if (valLen >= len) {
auto reader = child({}); auto reader = child({});
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxReturnError(handler.field({}, &val[i])); OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
} else { } else {
oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen); oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen);
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
} }
} }
@@ -234,29 +234,29 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto &val) { constexpr auto loopBody = [](auto &handler, auto &val) {
oxRequire(keyLen, handler.stringLength(nullptr)); OX_REQUIRE(keyLen, handler.stringLength(nullptr));
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
auto wkeyPtr = wkey.get(); auto wkeyPtr = wkey.get();
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1)); OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
return handler.field("", &val[wkeyPtr]); return handler.field("", &val[wkeyPtr]);
}; };
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(loopBody(handler, *val)); OX_RETURN_ERROR(loopBody(handler, *val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -266,11 +266,11 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
oxReturnError(ox::resizeVector(*val, len)); OX_RETURN_ERROR(ox::resizeVector(*val, len));
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
} }
oxReturnError(ox::resizeVector(*val, 0)); OX_RETURN_ERROR(ox::resizeVector(*val, 0));
} }
++m_field; ++m_field;
return {}; return {};
@@ -278,9 +278,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
if (len > val->size()) { if (len > val->size()) {
return OxError(1, "Input array is too long"); return ox::Error(1, "Input array is too long");
} }
} }
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
@@ -291,7 +291,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) { if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child(""); auto reader = child("");
oxReturnError(model(reader.interface(), val)); OX_RETURN_ERROR(model(reader.interface(), val));
} }
} }
++m_field; ++m_field;
@@ -305,7 +305,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U,
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) { if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx())); auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
oxReturnError(model(reader.interface(), val.get())); OX_RETURN_ERROR(model(reader.interface(), val.get()));
} }
} }
++m_field; ++m_field;
@@ -319,18 +319,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
const auto cap = size; const auto cap = size;
*val = BasicString<SmallStringSize>(cap); *val = BasicString<SmallStringSize>(cap);
auto data = val->data(); auto data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -340,12 +340,12 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
*val = IString<L>(); *val = IString<L>();
oxReturnError(val->resize(size)); OX_RETURN_ERROR(val->resize(size));
auto const data = val->data(); auto const data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
@@ -359,18 +359,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
if (size > buffLen) { if (size > buffLen) {
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
// re-allocate in case too small // re-allocate in case too small
auto data = val; auto data = val;
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -378,17 +378,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate in case too small // re-allocate in case too small
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
auto data = ox::Span{*val, size + 1}; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data.data(), size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -397,7 +397,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate if too small // re-allocate if too small
if (buffLen < size + 1) { if (buffLen < size + 1) {
safeDelete(*val); safeDelete(*val);
@@ -406,7 +406,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
} }
auto data = ox::Span{*val, size + 1}; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data.data(), size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} else { } else {
auto data = *val; auto data = *val;
@@ -416,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -425,15 +425,15 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
if (!pass) { if (!pass) {
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
} }
return out; return out;
} }
} }
return OxError(1); return ox::Error(1);
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -443,7 +443,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead); auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
oxReturnError(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur)); OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
return len; return len;
} }
} }
@@ -457,14 +457,14 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead); auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
oxReturnError(result); OX_RETURN_ERROR(result);
*val = result.value; *val = result.value;
} else { } else {
*val = 0; *val = 0;
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -474,20 +474,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
T val; T val;
oxReturnError(handler.field("", &val)); OX_RETURN_ERROR(handler.field("", &val));
oxReturnError(cb(i, &val)); OX_RETURN_ERROR(cb(i, &val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -548,7 +548,7 @@ Error readMC(ox::BufferView buff, T &val) noexcept {
template<typename T> template<typename T>
Result<T> readMC(ox::BufferView buff) noexcept { Result<T> readMC(ox::BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readMC(buff, val.value)); OX_RETURN_ERROR(readMC(buff, val.value));
return val; return val;
} }
+55 -55
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -62,47 +62,47 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("CString", &obj->CString)); OX_RETURN_ERROR(io->fieldCString("CString", &obj->CString));
return OxError(0); return ox::Error(0);
} }
oxModelBegin(TestStructNest) OX_MODEL_BEGIN(TestStructNest)
oxModelField(Bool) OX_MODEL_FIELD(Bool)
oxModelField(Int) OX_MODEL_FIELD(Int)
oxModelField(IString) OX_MODEL_FIELD(IString)
oxModelEnd() OX_MODEL_END()
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if constexpr(T::opType() == ox::OpType::Reflect) { if constexpr(T::opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("IString", &obj->IString)); OX_RETURN_ERROR(io->field("IString", &obj->IString));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Vector", &obj->Vector)); OX_RETURN_ERROR(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Vector2", &obj->Vector2)); OX_RETURN_ERROR(io->field("Vector2", &obj->Vector2));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
return OxError(0); return ox::Error(0);
} }
std::map<ox::StringView, ox::Error(*)()> tests = { std::map<ox::StringView, ox::Error(*)()> tests = {
@@ -114,9 +114,9 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// doesn't segfault // doesn't segfault
ox::Array<char, 1024> buff; ox::Array<char, 1024> buff;
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts)); OX_RETURN_ERROR(ox::writeMC(buff.data(), buff.size(), ts));
oxReturnError(ox::writeMC(ts)); OX_RETURN_ERROR(ox::writeMC(ts));
return OxError(0); return ox::Error(0);
} }
}, },
@@ -157,7 +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()); oxDebugf("{}", testOut.IString.size());
oxExpect(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");
@@ -176,7 +176,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch"); oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch"); oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -189,28 +189,28 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) { static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) {
if (val.length != expected.size()) { if (val.length != expected.size()) {
std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n'; std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n';
return OxError(1); return ox::Error(1);
} }
for (std::size_t i = 0; i < expected.size(); i++) { for (std::size_t i = 0; i < expected.size(); i++) {
if (expected[i] != val.data[i]) { if (expected[i] != val.data[i]) {
std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n'; std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n';
std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n'; std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
return OxError(1); return ox::Error(1);
} }
} }
return OxError(0); return ox::Error(0);
}; };
constexpr auto check64 = [](McInt val, auto expected) { constexpr auto check64 = [](McInt val, auto expected) {
if (val.length != 9) { if (val.length != 9) {
std::cout << "val.length: " << val.length << '\n'; std::cout << "val.length: " << val.length << '\n';
return OxError(1); return ox::Error(1);
} }
ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]); ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]);
if (expected != decoded) { if (expected != decoded) {
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n'; std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
// signed positive // signed positive
oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail"); oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail");
@@ -247,7 +247,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// code deduplication // code deduplication
oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail");
oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -260,12 +260,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
using ox::mc::decodeInteger; using ox::mc::decodeInteger;
static constexpr auto check = [](auto val) { static constexpr auto check = [](auto val) {
auto result = decodeInteger<decltype(val)>(encodeInteger(val)); auto result = decodeInteger<decltype(val)>(encodeInteger(val));
oxReturnError(result.error); OX_RETURN_ERROR(result.error);
if (result.value != val) { if (result.value != val) {
std::cout << "Bad value: " << result.value << ", expected: " << val << '\n'; std::cout << "Bad value: " << result.value << ", expected: " << val << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
oxAssert(check(uint32_t(14)), "Decode of 14 failed."); oxAssert(check(uint32_t(14)), "Decode of 14 failed.");
oxAssert(check(int8_t(-1)), "Decode of -1 failed."); oxAssert(check(int8_t(-1)), "Decode of -1 failed.");
@@ -291,7 +291,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(check(0xffffffff), "Decode of 0xffffffff failed."); oxAssert(check(0xffffffff), "Decode of 0xffffffff failed.");
oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed."); oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed.");
oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed."); oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed.");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -319,7 +319,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type)); OX_RETURN_ERROR(testOut.setType(type));
oxAssert(ox::readMC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@@ -344,7 +344,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed"); oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -371,7 +371,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::BufferReader br({dataBuff, dataBuffLen}); ox::BufferReader br({dataBuff, dataBuffLen});
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br, OX_RETURN_ERROR(ox::walkModel<ox::MetalClawReader>(type, br,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n'; //std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@@ -454,10 +454,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }
+1 -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
+1 -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
+55 -50
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -117,12 +117,12 @@ class MetalClawWriter {
bool fieldSet = false; bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
}; };
@@ -181,50 +181,55 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val)
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *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()); const auto strLen = mc::encodeInteger(val->size());
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
// write the string // write the string
oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len()))); OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->size())));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t L> template<std::size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *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(const char*, const char *const*val, std::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) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// this strlen is tolerated because sometimes 0 gets passed to
// the size param, which is a lie
// this code should be cleaned up at some point...
const auto strLen = *val ? ox::strlen(*val) : 0; const auto strLen = *val ? ox::strlen(*val) : 0;
OX_ALLOW_UNSAFE_BUFFERS_END
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
@@ -243,14 +248,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
@@ -264,11 +269,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer}; ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@@ -282,11 +287,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@@ -298,23 +303,23 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::s
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxReturnError(handler.field("", &val[i])); OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
@@ -326,32 +331,32 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
// write map // write map
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
// double len for both key and value // double len for both key and value
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2)); OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error { constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.len(); const auto keyLen = key.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);
oxReturnError(handler.fieldCString("", wkey.get(), keyLen)); OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
oxRequireM(value, val.at(key)); OX_REQUIRE_M(value, val.at(key));
return handler.field("", value); return handler.field("", value);
}; };
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i]; auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val)); OX_RETURN_ERROR(loopBody(handler, key, *val));
} }
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
@@ -362,7 +367,7 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
const Vector<String>&, const Vector<String>&,
std::size_t fields) noexcept { std::size_t fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1; const auto fieldPresenceLen = (fields - 1) / 8 + 1;
oxReturnError(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields)); m_fieldPresence.setFields(static_cast<int>(fields));
@@ -372,33 +377,33 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
template<Writer_c Writer> template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept { ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp(); const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP)); OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write( OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()), reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size())); m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end)); OX_RETURN_ERROR(m_writer.seekp(end));
return {}; return {};
} }
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer); MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter}; ModelHandlerInterface handler{&mcWriter};
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
oxReturnError(mcWriter.finalize()); OX_RETURN_ERROR(mcWriter.finalize());
return {}; return {};
} }
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz); Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0); BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
buff.resize(bw.tellp()); buff.resize(bw.tellp());
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw{{buff, buffLen}}; CharBuffWriter bw{{buff, buffLen}};
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {
*sizeOut = bw.tellp(); *sizeOut = bw.tellp();
} }
+7 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -11,9 +11,9 @@
#include <ox/std/concepts.hpp> #include <ox/std/concepts.hpp>
// oxModelFwdDecl is necessary because Apple-Clang is broken... // oxModelFwdDecl is necessary because Apple-Clang is broken...
#define oxModelFwdDecl(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>()); #define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>());
#define oxModelEnd() return OxError(0); } #define OX_MODEL_END() return {}; }
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName)); #define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); #define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
+1 -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
+1 -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
+25 -25
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);
@@ -76,20 +76,20 @@ struct Subscript {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<Subscript>()); OX_RETURN_ERROR(io->template setTypeInfo<Subscript>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint32_t st = 0; uint32_t st = 0;
oxReturnError(io->field("subscriptType", &st)); OX_RETURN_ERROR(io->field("subscriptType", &st));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
} else { } else {
auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
type->subscriptType = static_cast<Subscript::SubscriptType>(pt); type->subscriptType = static_cast<Subscript::SubscriptType>(pt);
} }
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("smallSzLen", &type->smallSzLen)); OX_RETURN_ERROR(io->field("smallSzLen", &type->smallSzLen));
return {}; return {};
} }
@@ -185,37 +185,37 @@ constexpr auto buildTypeId(const DescriptorType &t) noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorType>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorType>());
oxReturnError(io->field("typeName", &type->typeName)); OX_RETURN_ERROR(io->field("typeName", &type->typeName));
oxReturnError(io->field("typeVersion", &type->typeVersion)); OX_RETURN_ERROR(io->field("typeVersion", &type->typeVersion));
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint8_t pt = 0; uint8_t pt = 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else { } else {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
type->primitiveType = static_cast<PrimitiveType>(pt); type->primitiveType = static_cast<PrimitiveType>(pt);
} }
oxReturnError(io->field("typeParams", &type->typeParams)); OX_RETURN_ERROR(io->field("typeParams", &type->typeParams));
oxReturnError(io->field("fieldList", &type->fieldList)); OX_RETURN_ERROR(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable)); OX_RETURN_ERROR(io->field("preloadable", &type->preloadable));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorField>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorField>());
oxReturnError(io->field("typeId", &field->typeId)); OX_RETURN_ERROR(io->field("typeId", &field->typeId));
oxReturnError(io->field("fieldName", &field->fieldName)); OX_RETURN_ERROR(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels)); OX_RETURN_ERROR(io->field("subscriptLevels", &field->subscriptLevels));
oxReturnError(io->field("subscriptStack", &field->subscriptStack)); OX_RETURN_ERROR(io->field("subscriptStack", &field->subscriptStack));
// defaultValue is unused now, but leave placeholder for backwards compatibility // defaultValue is unused now, but leave placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); OX_RETURN_ERROR(io->field("defaultValue", &defaultValue));
return {}; return {};
} }
@@ -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 OxError(0); return {};
} }
#endif #endif
+1 -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
+11 -11
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
@@ -205,9 +205,9 @@ 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 OxError(0); return {};
} }
return OxError(1); return ox::Error(1);
} }
// array handler // array handler
@@ -220,9 +220,9 @@ 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 OxError(0); return {};
} }
return OxError(1); return ox::Error(1);
} }
template<typename T, bool force> template<typename T, bool force>
@@ -231,9 +231,9 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return OxError(0); return {};
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
@@ -254,7 +254,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept
return {}; return {};
} }
} }
return OxError(1); return ox::Error(1);
} }
template<typename ...Args> template<typename ...Args>
@@ -384,11 +384,11 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
std::allocator<T> a; std::allocator<T> a;
T *t = a.allocate(1); T *t = a.allocate(1);
oxReturnError(model(&handler, t)); OX_RETURN_ERROR(model(&handler, t));
a.deallocate(t, 1); a.deallocate(t, 1);
} else { } else {
auto t = ox_malloca(sizeof(T), T); auto t = ox_malloca(sizeof(T), T);
oxReturnError(model(&handler, t.get())); OX_RETURN_ERROR(model(&handler, t.get()));
} }
return writer.definition(); return writer.definition();
} }
@@ -397,7 +397,7 @@ template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
return writer.definition(); return writer.definition();
} }
+5 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31,25 +31,25 @@ class FieldCounter {
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U) noexcept { constexpr ox::Error field(StringViewCR, U) noexcept {
++fields; ++fields;
return OxError(0); return {};
} }
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept { constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
++fields; ++fields;
return OxError(0); return {};
} }
template<typename U, typename Handler> template<typename U, typename Handler>
constexpr Error field(StringViewCR, Handler) { constexpr Error field(StringViewCR, Handler) {
++fields; ++fields;
return OxError(0); return {};
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
++fields; ++fields;
return OxError(0); return {};
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
+1 -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
+1 -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
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -135,8 +135,8 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>()); return m_handler->field(name, &v->template get<ModelValueArray>());
} }
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type())); oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(OxError(1), "invalid type"); oxPanic(ox::Error(1), "invalid type");
return OxError(1, "invalid type"); return ox::Error(1, "invalid type");
} }
// array handler, with callback to allow handling individual elements // array handler, with callback to allow handling individual elements
+16 -16
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -56,19 +56,19 @@ class MemberList {
template<typename T> template<typename T>
constexpr Error field(const char*, T *v) noexcept { constexpr Error field(const char*, T *v) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T *v, int) noexcept { constexpr Error field(const char*, T *v, int) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return {};
} }
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> u) noexcept { constexpr Error field(const char*, UnionView<U, force> u) noexcept {
vars[m_i++] = static_cast<void*>(u.get()); vars[m_i++] = static_cast<void*>(u.get());
return OxError(0); return {};
} }
template<typename T> template<typename T>
@@ -107,7 +107,7 @@ class Copier {
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]); auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
dst = src; dst = src;
++m_i; ++m_i;
return OxError(0); return {};
} }
} }
@@ -119,7 +119,7 @@ class Copier {
dst = src; dst = src;
} }
++m_i; ++m_i;
return OxError(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 OxError(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 OxError(0); return {};
} }
} }
@@ -181,7 +181,7 @@ class Mover {
src = FT{}; src = FT{};
} }
++m_i; ++m_i;
return OxError(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 OxError(0); return {};
} }
template<typename T = void> template<typename T = void>
@@ -228,10 +228,10 @@ class Equals {
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]); const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return {};
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
@@ -242,11 +242,11 @@ class Equals {
const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i]; const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i];
if (!(dst == src)) { if (!(dst == src)) {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
++m_i; ++m_i;
return OxError(0); return {};
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@@ -255,10 +255,10 @@ class Equals {
const auto &src = *u.get(); const auto &src = *u.get();
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return {};
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
+4 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12,12 +12,12 @@ namespace ox {
static_assert([]() -> ox::Error { static_assert([]() -> ox::Error {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
if (v.type() != ModelValue::Type::SignedInteger32) { if (v.type() != ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
//oxReturnError(v.set<int32_t>(5)); //oxReturnError(v.set<int32_t>(5));
return {}; return {};
}() == OxError(0)); }() == ox::Error{});
} }
+42 -42
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept { constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept { constexpr auto &get() noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@@ -242,7 +242,7 @@ class ModelValueArray {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@@ -401,7 +401,7 @@ class ModelValueVector {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@@ -519,7 +519,7 @@ class ModelObject {
ModelValue value; ModelValue value;
}; };
protected: protected:
oxModelFriend(ModelObject); OX_MODEL_FRIEND(ModelObject);
friend ModelValue; friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder; Vector<UniquePtr<Field>> m_fieldsOrder;
HashMap<String, ModelValue*> m_fields; HashMap<String, ModelValue*> m_fields;
@@ -634,18 +634,18 @@ class ModelObject {
if (m_fields.contains(k)) { if (m_fields.contains(k)) {
return *m_fields.at(k).value; return *m_fields.at(k).value;
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
constexpr Error set(const String &k, T &&val) noexcept { constexpr Error set(const String &k, T &&val) noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
*t = ox::forward<T>(val); *t = ox::forward<T>(val);
return {}; return {};
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return *v; return *v;
} }
@@ -670,13 +670,13 @@ class ModelObject {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelObject"); return ox::Error(1, "Cannot load a non-struct type to ModelObject");
} }
m_type = type; m_type = type;
for (const auto &f : type->fieldList) { for (const auto &f : type->fieldList) {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
oxReturnError(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels)); OX_RETURN_ERROR(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels));
m_fields[field->name] = &field->value; m_fields[field->name] = &field->value;
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
} }
@@ -722,7 +722,7 @@ class ModelUnion {
static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept { static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept {
UniquePtr<ModelUnion> out(new ModelUnion); UniquePtr<ModelUnion> out(new ModelUnion);
oxReturnError(out->setType(type)); OX_RETURN_ERROR(out->setType(type));
return out; return out;
} }
@@ -731,7 +731,7 @@ class ModelUnion {
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return &(*v)->value; return &(*v)->value;
} }
@@ -763,7 +763,7 @@ class ModelUnion {
[[nodiscard]] [[nodiscard]]
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept { constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
return &(*t)->value; return &(*t)->value;
} }
@@ -790,7 +790,7 @@ class ModelUnion {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelUnion"); return ox::Error(1, "Cannot load a non-struct type to ModelUnion");
} }
m_fields.clear(); m_fields.clear();
m_fieldsOrder.clear(); m_fieldsOrder.clear();
@@ -799,7 +799,7 @@ class ModelUnion {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
field->idx = i; field->idx = i;
oxReturnError(field->value.setType(f.type, SubscriptStack{static_cast<size_t>(f.subscriptLevels)}, f.subscriptLevels)); OX_RETURN_ERROR(field->value.setType(f.type, SubscriptStack{static_cast<size_t>(f.subscriptLevels)}, f.subscriptLevels));
m_fields[field->name] = field.get(); m_fields[field->name] = field.get();
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
++i; ++i;
@@ -967,21 +967,21 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept {
} }
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelObject>( OX_RETURN_ERROR(h->template setTypeInfo<ModelObject>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return {};
} }
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelUnion>( OX_RETURN_ERROR(h->template setTypeInfo<ModelUnion>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return {};
} }
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
@@ -997,7 +997,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 +1030,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;
@@ -1087,12 +1087,12 @@ constexpr Error ModelValue::setType(
if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) { if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) {
m_type = Type::InlineArray; m_type = Type::InlineArray;
m_data.array = new ModelValueArray; m_data.array = new ModelValueArray;
oxReturnError(m_data.array->setType(type, subscriptStack, subscriptLevels - 1)); OX_RETURN_ERROR(m_data.array->setType(type, subscriptStack, subscriptLevels - 1));
oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length))); OX_RETURN_ERROR(m_data.array->setSize(static_cast<size_t>(subscript.length)));
} else { } else {
m_type = Type::Vector; m_type = Type::Vector;
m_data.vec = new ModelValueVector; m_data.vec = new ModelValueVector;
oxReturnError(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1)); OX_RETURN_ERROR(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1));
} }
return {}; return {};
} else if (type->typeName == types::Bool) { } else if (type->typeName == types::Bool) {
@@ -1121,15 +1121,15 @@ constexpr Error ModelValue::setType(
} else if (type->primitiveType == PrimitiveType::Struct) { } else if (type->primitiveType == PrimitiveType::Struct) {
m_type = Type::Object; m_type = Type::Object;
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if (type->primitiveType == PrimitiveType::Union) { } else if (type->primitiveType == PrimitiveType::Union) {
m_type = Type::Union; m_type = Type::Union;
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} }
oxAssert(m_type != Type::Undefined, "No type set"); oxAssert(m_type != Type::Undefined, "No type set");
return OxError(0); return {};
} }
template<typename T> template<typename T>
@@ -1141,11 +1141,11 @@ constexpr Error ModelValue::setType() noexcept {
// rather than using getValue<type>() // rather than using getValue<type>()
if constexpr(type == Type::Object) { if constexpr(type == Type::Object) {
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if constexpr(type == Type::Union) { } else if constexpr(type == Type::Union) {
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} else if constexpr(type == Type::String) { } else if constexpr(type == Type::String) {
m_data.str = new String; m_data.str = new String;
} else if constexpr(type == Type::Vector) { } else if constexpr(type == Type::Vector) {
@@ -1176,7 +1176,7 @@ template<typename T>
constexpr Error ModelValue::set(const T &v) noexcept { constexpr Error ModelValue::set(const T &v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@@ -1184,14 +1184,14 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = v; value = v;
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error ModelValue::set(T &&v) noexcept { constexpr Error ModelValue::set(T &&v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@@ -1199,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = std::move(v); value = std::move(v);
return OxError(0); return {};
} }
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept { constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {
@@ -1223,7 +1223,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 +1261,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;
+1 -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
+6 -6
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,8 +17,8 @@ struct TestType {
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
}; };
oxModelBegin(TestType) OX_MODEL_BEGIN(TestType)
oxModelEnd() OX_MODEL_END()
struct TestType2 { struct TestType2 {
}; };
@@ -38,12 +38,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
"ModelValue", "ModelValue",
[] { [] {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
//v.m_type = ox::ModelValue::getType<int32_t>(); //v.m_type = ox::ModelValue::getType<int32_t>();
if (v.type() != ox::ModelValue::Type::SignedInteger32) { if (v.type() != ox::ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
oxReturnError(v.set<int32_t>(5)); OX_RETURN_ERROR(v.set<int32_t>(5));
return ox::Error{}; return ox::Error{};
} }
}, },
+12 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return {};
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
return OxError(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 OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error fieldCString(const char*, T) noexcept { constexpr Error fieldCString(const char*, T) noexcept {
return OxError(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);
}(); }();
} }
+1 -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
+11 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31,7 +31,7 @@ class TypeStore {
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion, constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
const TypeParamPack &typeParams) const noexcept { const TypeParamPack &typeParams) const noexcept {
const auto typeId = buildTypeId(name, typeVersion, typeParams); const auto typeId = buildTypeId(name, typeVersion, typeParams);
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@@ -40,7 +40,7 @@ class TypeStore {
constexpr auto typeName = ModelTypeName_v<T>; constexpr auto typeName = ModelTypeName_v<T>;
constexpr auto typeVersion = ModelTypeVersion_v<T>; constexpr auto typeVersion = ModelTypeVersion_v<T>;
const auto typeId = buildTypeId(typeName, typeVersion, {}); const auto typeId = buildTypeId(typeName, typeVersion, {});
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@@ -56,15 +56,19 @@ class TypeStore {
auto [val, err] = m_cache.at(typeId); auto [val, err] = m_cache.at(typeId);
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeId)); OX_REQUIRE_M(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) { for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeId).moveTo(f.type)); if (typeId == f.typeId) {
f.type = dt.get();
} else {
OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type));
}
} }
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
out = std::move(dt); out = std::move(dt);
return out.get(); return out.get();
} else { } else {
return OxError(1, "Type not available"); return ox::Error(1, "Type not available");
} }
} }
return val->get(); return val->get();
@@ -102,7 +106,7 @@ class TypeStore {
protected: protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept { virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return OxError(1); return ox::Error(1);
} }
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version, Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version,
+13 -13
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -50,7 +50,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler
template<typename Reader, typename T> template<typename Reader, typename T>
constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept { constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept {
oxRequire(out, m_typeStack.back()); OX_REQUIRE(out, m_typeStack.back());
return *out; return *out;
} }
@@ -87,9 +87,9 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
walker->pushNamePath(field.fieldName); walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) { if (field.subscriptLevels) {
// add array handling // add array handling
oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); OX_REQUIRE(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true));
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
oxReturnError(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen)); OX_RETURN_ERROR(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen));
DescriptorField f(field); // create mutable copy DescriptorField f(field); // create mutable copy
--f.subscriptLevels; --f.subscriptLevels;
String subscript; String subscript;
@@ -98,7 +98,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
subscript += static_cast<uint64_t>(i); subscript += static_cast<uint64_t>(i);
subscript += "]"; subscript += "]";
walker->pushNamePath(subscript); walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker)); OX_RETURN_ERROR(parseField(f, &child, walker));
walker->popNamePath(); walker->popNamePath();
} }
rdr->nextField(); rdr->nextField();
@@ -108,40 +108,40 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
case PrimitiveType::SignedInteger: case PrimitiveType::SignedInteger:
case PrimitiveType::Bool: case PrimitiveType::Bool:
case PrimitiveType::String: case PrimitiveType::String:
oxReturnError(walker->read(field, rdr)); OX_RETURN_ERROR(walker->read(field, rdr));
break; break;
case PrimitiveType::Struct: case PrimitiveType::Struct:
case PrimitiveType::Union: case PrimitiveType::Union:
if (rdr->fieldPresent(field.fieldName.c_str())) { if (rdr->fieldPresent(field.fieldName.c_str())) {
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
walker->pushType(field.type); walker->pushType(field.type);
oxReturnError(model(&child, walker)); OX_RETURN_ERROR(model(&child, walker));
walker->popType(); walker->popType();
rdr->nextField(); rdr->nextField();
} else { } else {
// skip and discard absent field // skip and discard absent field
int discard; int discard;
oxReturnError(rdr->field(field.fieldName.c_str(), &discard)); OX_RETURN_ERROR(rdr->field(field.fieldName.c_str(), &discard));
} }
break; break;
} }
} }
walker->popNamePath(); walker->popNamePath();
return OxError(0); return {};
} }
template<typename Reader, typename FH> template<typename Reader, typename FH>
constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept { constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
oxRequire(type, walker->type()); OX_REQUIRE(type, walker->type());
auto typeName = type->typeName.c_str(); auto typeName = type->typeName.c_str();
auto typeVersion = type->typeVersion; auto typeVersion = type->typeVersion;
auto typeParams = type->typeParams; auto typeParams = type->typeParams;
auto &fields = type->fieldList; auto &fields = type->fieldList;
oxReturnError(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size())); OX_RETURN_ERROR(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size()));
for (const auto &field : fields) { for (const auto &field : fields) {
oxReturnError(parseField(field, rdr, walker)); OX_RETURN_ERROR(parseField(field, rdr, walker));
} }
return OxError(0); return {};
} }
template<typename Reader, typename Handler> template<typename Reader, typename Handler>
+1 -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
+16 -16
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,11 +15,11 @@ namespace ox {
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t 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 OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@@ -27,7 +27,7 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
} }
Error OrganicClawReader::field(const char *key, bool *val) noexcept { Error OrganicClawReader::field(const char *key, bool *val) noexcept {
auto err = OxError(0); ox::Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@@ -45,7 +45,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} else if (jv.isBool()) { } else if (jv.isBool()) {
*val = jv.asBool(); *val = jv.asBool();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = OxError(0); ox::Error err{};
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@@ -67,13 +67,13 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<std::size_t>(end - begin);
auto data = val; auto data = val;
if (strSize >= buffLen) { if (strSize >= buffLen) {
err = OxError(2, "String size exceeds capacity of destination"); err = ox::Error(2, "String size exceeds capacity of destination");
} else { } else {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} }
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
} }
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
auto err = OxError(0); ox::Error err{};
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
auto &data = *val; auto &data = *val;
@@ -98,7 +98,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
auto err = OxError(0); ox::Error err{};
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@@ -126,7 +126,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = nullptr; data[strSize] = nullptr;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -135,7 +135,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
Error OrganicClawReader::field(const char *key, UUID *val) noexcept { Error OrganicClawReader::field(const char *key, UUID *val) noexcept {
UUIDStr str; UUIDStr str;
oxReturnError(field(key, &str)); OX_RETURN_ERROR(field(key, &str));
return UUID::fromString(str).moveTo(*val); return UUID::fromString(str).moveTo(*val);
} }
@@ -147,7 +147,7 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
if (jv.isArray()) { if (jv.isArray()) {
return jv.size(); return jv.size();
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
[[nodiscard]] [[nodiscard]]
@@ -161,7 +161,7 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
jv.getString(&begin, &end); jv.getString(&begin, &end);
return static_cast<std::size_t>(end - begin); return static_cast<std::size_t>(end - begin);
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept { OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {
+35 -26
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>
@@ -133,7 +137,7 @@ class OrganicClawReader {
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept { Error OrganicClawReader::field(const char *key, T *val) noexcept {
auto err = OxError(0); ox::Error err{};
try { try {
if constexpr (is_integer_v<T>) { if constexpr (is_integer_v<T>) {
if (targetValid()) { if (targetValid()) {
@@ -144,21 +148,25 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
if (jv.empty()) { if (jv.empty()) {
*val = 0; *val = 0;
} else if (rightType) { } else if (rightType) {
*val = static_cast<T>(jv.asUInt()); if constexpr(ox::is_signed_v<T>) {
*val = static_cast<T>(jv.asInt64());
} else { } else {
err = OxError(1, "Type mismatch"); *val = static_cast<T>(jv.asUInt64());
}
} else {
err = ox::Error(1, "Type mismatch");
} }
} }
} else if constexpr (isVector_v<T>) { } else if constexpr (isVector_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
oxReturnError(ox::resizeVector(*val, srcSize)); OX_RETURN_ERROR(ox::resizeVector(*val, srcSize));
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) { } else if constexpr (isArray_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
if (srcSize > val->size()) { if (srcSize > val->size()) {
err = OxError(1, "Input array is too long"); err = ox::Error(1, "Input array is too long");
} else { } else {
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} }
@@ -169,11 +177,12 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val); err = model(&handler, val);
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
} catch (Json::LogicError const&) { } catch (Json::LogicError const&e) {
err = OxError(1, "error reading JSON data"); oxDebugf("JSON error: {}", e.what());
err = ox::Error(1, "error reading JSON data");
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
@@ -181,7 +190,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
template<typename U, bool force> template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = OxError(0); ox::Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty() || jv.isObject()) { if (jv.empty() || jv.isObject()) {
@@ -189,7 +198,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val.get()); err = model(&handler, val.get());
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -198,7 +207,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
auto err = OxError(0); ox::Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@@ -206,7 +215,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -215,7 +224,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
auto err = OxError(0); ox::Error err{};
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@@ -223,7 +232,7 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@@ -235,27 +244,27 @@ template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept { Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) { if (!srcVal.isNull() && !srcVal.isArray()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
if (srcSize > valLen) { if (srcSize > valLen) {
return OxError(1); return ox::Error(1);
} }
OrganicClawReader r(srcVal); OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxReturnError(handler.field("", &val[i])); OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
return OxError(0); return {};
} }
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept { Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isObject()) { if (!srcVal.isObject()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto keys = srcVal.getMemberNames(); auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
@@ -263,9 +272,9 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
oxReturnError(handler.field(k, &val->operator[](k))); OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
} }
return OxError(0); return {};
} }
Error readOC(BufferView buff, auto &val) noexcept { Error readOC(BufferView buff, auto &val) noexcept {
@@ -277,7 +286,7 @@ Error readOC(BufferView buff, auto &val) noexcept {
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 OxError(1, "Could not parse JSON"); return ox::Error(1, "Could not parse JSON");
} }
OrganicClawReader reader(buff.data(), buff.size()); OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
@@ -285,20 +294,20 @@ OX_ALLOW_UNSAFE_BUFFERS_END
} catch (const Error &err) { } catch (const Error &err) {
return err; return err;
} catch (...) { } catch (...) {
return OxError(1, "Unknown Error"); return ox::Error(1, "Unknown Error");
} }
} }
template<typename T> template<typename T>
Result<T> readOC(BufferView buff) noexcept { Result<T> readOC(BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readOC(buff, val.value)); OX_RETURN_ERROR(readOC(buff, val.value));
return val; return val;
} }
template<typename T> template<typename T>
Result<T> readOC(ox::StringView json) noexcept { Result<T> readOC(ox::StringView json) noexcept {
return readOC<T>(ox::BufferView{json.data(), json.len()}); return readOC<T>(ox::BufferView{json.data(), json.size()});
} }
} }
+37 -37
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -74,45 +74,45 @@ struct TestStruct {
}; };
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if (io->opType() == ox::OpType::Reflect) { if (io->opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
TestStruct::TestStruct(TestStruct &&other) noexcept { TestStruct::TestStruct(TestStruct &&other) noexcept {
@@ -184,7 +184,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -210,7 +210,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value)); OX_RETURN_ERROR(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readOC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@@ -234,7 +234,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@@ -259,7 +259,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
ox::TypeStore typeStore; ox::TypeStore typeStore;
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(), OX_RETURN_ERROR(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(),
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f,
ox::OrganicClawReader *rdr) -> ox::Error { ox::OrganicClawReader *rdr) -> ox::Error {
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@@ -341,10 +341,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
@@ -32,7 +32,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) no
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept { Error OrganicClawWriter::field(const char *key, const UUID *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;
+30 -22
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>
@@ -42,7 +46,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const int16_t *val) noexcept { Error field(const char *key, const int16_t *val) noexcept {
@@ -50,7 +54,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const int32_t *val) noexcept { Error field(const char *key, const int32_t *val) noexcept {
@@ -58,7 +62,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const int64_t *val) noexcept { Error field(const char *key, const int64_t *val) noexcept {
@@ -66,7 +70,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
@@ -75,7 +79,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const uint16_t *val) noexcept { Error field(const char *key, const uint16_t *val) noexcept {
@@ -83,7 +87,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const uint32_t *val) noexcept { Error field(const char *key, const uint32_t *val) noexcept {
@@ -91,7 +95,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(const char *key, const uint64_t *val) noexcept { Error field(const char *key, const uint64_t *val) noexcept {
@@ -99,7 +103,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Error field(char const*key, bool const*val) noexcept { Error field(char const*key, bool const*val) noexcept {
@@ -122,8 +126,8 @@ class OrganicClawWriter {
for (std::size_t i = 0; i < keys.size(); ++i) { for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
if (k) [[likely]] { if (k) [[likely]] {
oxRequireM(value, val->at(k)); OX_REQUIRE_M(value, val->at(k));
oxReturnError(handler.field(k, value)); OX_RETURN_ERROR(handler.field(k, value));
} }
} }
value(key) = w.m_json; value(key) = w.m_json;
@@ -134,7 +138,7 @@ class OrganicClawWriter {
template<std::size_t L> template<std::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;
@@ -143,11 +147,11 @@ class OrganicClawWriter {
template<std::size_t L> template<std::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 OxError(0); return {};
} }
Error fieldCString(const char*, const char *const*val, int len) noexcept; Error fieldCString(const char*, const char *const*val, int len) noexcept;
@@ -201,13 +205,13 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxReturnError(handler.field({}, &val[i])); OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
} }
value(key) = w.m_json; value(key) = w.m_json;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
template<typename T> template<typename T>
@@ -227,13 +231,13 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
} else if (val && targetValid()) { } else if (val && targetValid()) {
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
if (!w.m_json.empty() || m_json.isArray()) { if (!w.m_json.empty() || m_json.isArray()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
template<typename U, bool force> template<typename U, bool force>
@@ -241,36 +245,40 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
if (targetValid()) { if (targetValid()) {
OrganicClawWriter w(val.idx()); OrganicClawWriter w(val.idx());
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return {};
} }
Result<ox::Buffer> writeOC(const auto &val) noexcept { Result<ox::Buffer> writeOC(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<Buffer> buff; Result<Buffer> buff;
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<ox::String> writeOCString(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<ox::String> buff; Result<ox::String> buff;
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;
} }
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -63,7 +63,7 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
template<typename T> template<typename T>
constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept { constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field(nullptr, &val[i])); OX_RETURN_ERROR(field(nullptr, &val[i]));
} }
return {}; return {};
} }
+1 -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
+1 -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
+35 -35
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -162,7 +162,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::UnionView
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val.get())); OX_RETURN_ERROR(pad(val.get()));
m_unionIdx.emplace_back(val.idx()); m_unionIdx.emplace_back(val.idx());
const auto err = preload<PlatSpec, U>(this, val.get()); const auto err = preload<PlatSpec, U>(this, val.get());
m_unionIdx.pop_back(); m_unionIdx.pop_back();
@@ -175,13 +175,13 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const T *val)
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val)); OX_RETURN_ERROR(pad(val));
if constexpr(ox::is_integral_v<T>) { if constexpr(ox::is_integral_v<T>) {
return ox::serialize(m_writer, PlatSpec::correctEndianness(*val)); return ox::serialize(m_writer, PlatSpec::correctEndianness(*val));
} else if constexpr(ox::is_pointer_v<T>) { } else if constexpr(ox::is_pointer_v<T>) {
const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart; const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart;
oxReturnError(field(name, *val)); OX_RETURN_ERROR(field(name, *val));
oxReturnError(endAlloc()); OX_RETURN_ERROR(endAlloc());
return ox::serialize(m_writer, PlatSpec::correctEndianness(a)); return ox::serialize(m_writer, PlatSpec::correctEndianness(a));
} else if constexpr(ox::isVector_v<T>) { } else if constexpr(ox::isVector_v<T>) {
return fieldVector(name, val); return fieldVector(name, val);
@@ -211,19 +211,19 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::BasicStri
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
}; };
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto restore = m_writer.tellp(); const auto restore = m_writer.tellp();
std::size_t a = 0; std::size_t a = 0;
if (sz && sz >= SmallStringSize) { if (sz && sz >= SmallStringSize) {
oxReturnError(ox::allocate(m_writer, sz).moveTo(a)); OX_RETURN_ERROR(ox::allocate(m_writer, sz).moveTo(a));
} else { } else {
a = restore; a = restore;
} }
vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart); vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart);
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
oxReturnError(m_writer.write(val->data(), sz)); OX_RETURN_ERROR(m_writer.write(val->data(), sz));
oxReturnError(m_writer.seekp(restore)); OX_RETURN_ERROR(m_writer.seekp(restore));
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items); m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items);
return {}; return {};
} }
@@ -234,12 +234,12 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const ox::Arra
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
// serialize the Array elements // serialize the Array elements
if constexpr(sz) { if constexpr(sz) {
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(name, &(*val)[i])); OX_RETURN_ERROR(this->interface()->field(name, &(*val)[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@@ -253,11 +253,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
return {}; return {};
} }
if (cnt) { if (cnt) {
oxReturnError(pad(*val)); OX_RETURN_ERROR(pad(*val));
// serialize the array // serialize the array
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(this->interface()->field(nullptr, &val[i])); OX_RETURN_ERROR(this->interface()->field(nullptr, &val[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@@ -267,11 +267,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept { constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept {
m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp())); m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp()));
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@@ -280,11 +280,11 @@ template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc( constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(
std::size_t sz, size_t align, std::size_t restore) noexcept { std::size_t sz, size_t align, std::size_t restore) noexcept {
m_allocStack.emplace_back(restore, ox::ios_base::beg); m_allocStack.emplace_back(restore, ox::ios_base::beg);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@@ -295,7 +295,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
return m_writer.seekp(0, ox::ios_base::end); return m_writer.seekp(0, ox::ios_base::end);
} }
const auto &si = *m_allocStack.back().unwrap(); const auto &si = *m_allocStack.back().unwrap();
oxReturnError(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir)); OX_RETURN_ERROR(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir));
m_allocStack.pop_back(); m_allocStack.pop_back();
m_allocStart.pop_back(); m_allocStart.pop_back();
return {}; return {};
@@ -304,12 +304,12 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept { constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept {
for (const auto &p : m_ptrs) { for (const auto &p : m_ptrs) {
oxReturnError(m_writer.seekp(p.loc)); OX_RETURN_ERROR(m_writer.seekp(p.loc));
const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>( const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>(
static_cast<typename PlatSpec::PtrType>(p.value + offset)); static_cast<typename PlatSpec::PtrType>(p.value + offset));
oxReturnError(ox::serialize(m_writer, val)); OX_RETURN_ERROR(ox::serialize(m_writer, val));
} }
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
return {}; return {};
} }
@@ -354,39 +354,39 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept { StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto vecValPt = m_writer.tellp(); const auto vecValPt = m_writer.tellp();
// serialize the Vector elements // serialize the Vector elements
if (val->size()) { if (val->size()) {
const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size(); const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size();
const auto align = alignOf<PlatSpec>((*val)[0]); const auto align = alignOf<PlatSpec>((*val)[0]);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(p, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(p, ox::allocate(m_writer, sz + padding));
p += padding; p += padding;
oxReturnError(m_writer.seekp(p)); OX_RETURN_ERROR(m_writer.seekp(p));
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(nullptr, &val->operator[](i))); OX_RETURN_ERROR(this->interface()->field(nullptr, &val->operator[](i)));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
vecVal.items = PlatSpec::correctEndianness( vecVal.items = PlatSpec::correctEndianness(
static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart)); static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart));
oxReturnError(m_writer.seekp(vecValPt)); OX_RETURN_ERROR(m_writer.seekp(vecValPt));
} else { } else {
vecVal.items = 0; vecVal.items = 0;
} }
// serialize the Vector // serialize the Vector
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items); m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items);
return {}; return {};
} }
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept { constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept {
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
for (auto const&v : *val) { for (auto const&v : *val) {
oxReturnError(this->interface()->field({}, &v)); OX_RETURN_ERROR(this->interface()->field({}, &v));
} }
return {}; return {};
} }
@@ -405,7 +405,7 @@ constexpr size_t Preloader<PlatSpec>::calcPadding(size_t align) const noexcept {
template<typename PlatSpec, typename T> template<typename PlatSpec, typename T>
constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept { constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept {
oxReturnError(model(pl->interface(), obj)); OX_RETURN_ERROR(model(pl->interface(), obj));
return pl->pad(obj); return pl->pad(obj);
} }
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -74,7 +74,7 @@ template<typename T, bool force>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept {
pad(val.get()); pad(val.get());
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@@ -91,7 +91,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2024 gary@drinkingtea.net * Copyright 2015 - 2025 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -43,7 +43,7 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
template<typename T, bool force> template<typename T, bool force>
constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept { constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept {
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@@ -80,7 +80,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }
+1
View File
@@ -109,6 +109,7 @@ install(
error.hpp error.hpp
fmt.hpp fmt.hpp
hardware.hpp hardware.hpp
hash.hpp
hashmap.hpp hashmap.hpp
heapmgr.hpp heapmgr.hpp
ignore.hpp ignore.hpp
+14 -2
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;
+77 -14
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,18 +15,22 @@
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(ox::Span<char> s) 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(ox::Span<char> s) noexcept override {
oxAssert(s.size() >= sizeof(Wrap), "too small buffer"); oxAssert(s.size() >= sizeof(Wrap), "too small buffer");
@@ -39,39 +43,60 @@ 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{}; WrapBase *m_wrapPtr{};
ox::Array<char, sizeof(Wrap<void*>)> m_wrapData; ox::Array<char, sizeof(Wrap<void*>)> m_wrapData;
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); m_wrapPtr = new Wrap<T>(ptr);
} else { } else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); m_wrapPtr = new(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); m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
} }
} }
constexpr ~AnyPtr() noexcept { constexpr AnyPtrT(AnyPtrT &&other) noexcept {
if (other) {
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr);
}
other.m_wrapPtr = {};
}
}
constexpr ~AnyPtrT() noexcept {
if constexpr(unique) {
free();
}
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); ox::safeDelete(m_wrapPtr);
} }
} }
template<typename T> template<typename T>
constexpr AnyPtr &operator=(T *ptr) noexcept { constexpr AnyPtrT &operator=(T *ptr) noexcept {
if (std::is_constant_evaluated()) { if constexpr(unique) {
free();
} else if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); ox::safeDelete(m_wrapPtr);
}
if (std::is_constant_evaluated()) {
m_wrapPtr = new Wrap(ptr); m_wrapPtr = new Wrap(ptr);
} else { } else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); m_wrapPtr = new(m_wrapData.data()) Wrap(ptr);
@@ -79,10 +104,12 @@ class AnyPtr {
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_wrapPtr);
}
if (ptr) {
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData); m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData);
} else { } else {
m_wrapPtr = nullptr; m_wrapPtr = nullptr;
@@ -91,10 +118,40 @@ class AnyPtr {
return *this; return *this;
} }
constexpr AnyPtrT &operator=(AnyPtrT &&ptr) noexcept {
if (this != &ptr) {
if constexpr(unique) {
free();
} else if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr);
}
if (ptr) {
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData);
if (std::is_constant_evaluated()) {
ox::safeDelete(ptr.m_wrapPtr);
ptr.m_wrapPtr = nullptr;
}
} else {
m_wrapPtr = nullptr;
}
}
return *this;
}
constexpr operator bool() const noexcept { constexpr operator bool() const noexcept {
return m_wrapPtr && *m_wrapPtr; return m_wrapPtr && *m_wrapPtr;
} }
constexpr void free() noexcept {
if (m_wrapPtr) {
m_wrapPtr->free();
}
if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr);
}
m_wrapPtr = nullptr;
}
template<typename T> template<typename T>
[[nodiscard]] [[nodiscard]]
constexpr T *get() const noexcept { constexpr T *get() const noexcept {
@@ -104,6 +161,12 @@ class AnyPtr {
return dynamic_cast<Wrap<T>*>(m_wrapPtr)->data; return dynamic_cast<Wrap<T>*>(m_wrapPtr)->data;
#endif #endif
} }
}; };
} }
using AnyPtr = detail::AnyPtrT<false>;
using UAnyPtr = detail::AnyPtrT<true>;
}
+3 -3
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(__FILE__, __LINE__, i, size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept { constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow"); boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
+26 -14
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
@@ -7,6 +7,7 @@
*/ */
#include "fmt.hpp" #include "fmt.hpp"
#include "realstd.hpp"
#include "stacktrace.hpp" #include "stacktrace.hpp"
#include "trace.hpp" #include "trace.hpp"
@@ -14,14 +15,14 @@
namespace ox { namespace ox {
void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept { void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) { if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
} }
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err)); oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) { if (err.src.file_name() != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.file, err.line); oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
} }
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
printStackTrace(2); printStackTrace(2);
@@ -32,16 +33,22 @@ void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err)
#endif #endif
} }
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept { #if __GNUC__
__attribute__((weak))
#endif
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err); panic(StringView{file}, line, StringView{panicMsg}, err);
} }
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept { void assertFailFuncRuntime(
StringViewCR file,
int const line,
StringViewCR assertTxt,
StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); auto const st = genStackTrace(2);
output += genStackTrace(2); oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); abort();
std::abort();
#else #else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
@@ -49,20 +56,25 @@ void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt,
#endif #endif
} }
void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept { void assertFailFuncRuntime(
StringViewCR file,
int const line,
[[maybe_unused]] Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept {
#if defined(OX_USE_STDLIB) #if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg); auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) { if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg); msg += sfmt("\tError Message:\t{}\n", err.msg);
} }
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err)); msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) { if (err.src.file_name() != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line); msg += sfmt("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
} }
msg += genStackTrace(2); msg += genStackTrace(2);
oxErr(msg); oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line); oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort(); abort();
#else #else
constexprPanic(file, line, assertMsg); constexprPanic(file, line, assertMsg);
#endif #endif

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