Compare commits

...

280 Commits

Author SHA1 Message Date
7f56a77e7d [nostalgia/studio] Add version to Nostalgia Studio
All checks were successful
Build / build (push) Successful in 2m17s
2023-12-31 23:20:40 -06:00
055d64b125 [olympic] Add support for an AppLib app specific version
All checks were successful
Build / build (push) Successful in 2m20s
2023-12-31 23:18:17 -06:00
de9f842640 [ox/std] Add error.hpp include to memory.hpp
All checks were successful
Build / build (push) Successful in 2m15s
2023-12-31 22:52:10 -06:00
200e586768 Add .idea to .gitignore 2023-12-31 22:52:10 -06:00
f1609519a7 [olympic] Cleanup 2023-12-31 22:52:10 -06:00
e452d9db4f [nostalgia] Add python3-mypy to Debian deps 2023-12-31 22:52:10 -06:00
43a87b606e [nostalgia] Ensure pkg-gba reads .current_build without a new line
All checks were successful
Build / build (push) Successful in 2m20s
2023-12-30 13:59:10 -06:00
8acc6244d5 [olympic/keel] Improve error clarity on pack some common failures 2023-12-30 13:58:42 -06:00
bd2aeee276 [ox/claw] Improve error clarity when loading ModelObjects 2023-12-30 13:57:51 -06:00
89fab5cc20 [ox/fs] Remove stdc++fs from library list on Linux
All checks were successful
Build / build (push) Successful in 2m10s
2023-12-30 01:05:46 -06:00
1c06ea677f [nostalgia] Add links to Tonc and GBATEK to developer-handbook
All checks were successful
Build / build (push) Successful in 2m7s
2023-12-29 19:05:10 -06:00
6b948ee069 Merge commit '932c3e57e93d63dc98c454015afea941416ff423'
All checks were successful
Build / build (push) Successful in 2m8s
2023-12-29 18:44:06 -06:00
72dddcaee5 [ox] Fix TypeDescWriter segfault 2023-12-29 18:42:59 -06:00
7c824e910c [nostalgia] Remove Jenkinsfiles
All checks were successful
Build / build (push) Successful in 2m5s
2023-12-29 02:28:53 -06:00
a0c8146396 [nostalgia/core/studio] East const some function args
All checks were successful
Build / build (push) Successful in 2m5s
2023-12-29 00:06:18 -06:00
d5b232f5d5 [olympic/studio] Fix array bounds issue
All checks were successful
Build / build (push) Successful in 2m5s
2023-12-28 23:52:31 -06:00
c79fe3be43 [buildcore] Make CMake configure failure trigger failed return code
Some checks failed
Build / build (push) Has been cancelled
2023-12-28 23:50:30 -06:00
1df4e78084 [olympic/studio] Add new project menu, make file creation open file
Some checks failed
Build / build (push) Failing after 2m7s
2023-12-28 23:45:38 -06:00
ffbdb09c31 [olympic/turbine/glfw] Add shift key support 2023-12-28 23:41:33 -06:00
b35a956e4f [olympic/studio] Cleanup unused expression
All checks were successful
Build / build (push) Successful in 2m10s
2023-12-28 01:08:35 -06:00
d3847caab4 [olympic/studio] Make Project::writeObj only write descriptor if it does not already exist or if debug build
All checks were successful
Build / build (push) Successful in 2m9s
2023-12-28 00:24:18 -06:00
ae066a914c [olympic/studio] Fix Project::writeObj to ensure parent directory of file exists
All checks were successful
Build / build (push) Successful in 2m7s
2023-12-28 00:06:15 -06:00
67543af806 [ox/oc] Remove some unnecessary code
All checks were successful
Build / build (push) Successful in 2m3s
2023-12-27 23:50:02 -06:00
6b774ec285 [ox/oc] Fix array writing to write all values
All checks were successful
Build / build (push) Successful in 2m6s
This is necessary because OC array sizes are determined through the presence of the data.
2023-12-27 23:47:52 -06:00
4b9758f478 [nostalgia/core] Move most TileSheet member functions out of class
All checks were successful
Build / build (push) Successful in 2m4s
2023-12-27 23:10:38 -06:00
bf12b15fe6 [nostalgia/sample_project] Update some tilesheets to version 4 format 2023-12-26 20:28:55 -06:00
a7328eb5ef [nostalgia/core/studio] Reduce indent for Subsheet editor 2023-12-26 20:18:07 -06:00
b52124a0c5 [nostalgia/core/studio] Revert new subsheet index increment to happen after index assignment 2023-12-26 20:14:30 -06:00
eae9972f85 [nostalgia/sample_project] Add missing type descriptors 2023-12-26 18:55:35 -06:00
d83e392964 [nostalgia/core] Cleanup, revert CompactTileSheet version to 1
All checks were successful
Build / build (push) Successful in 2m2s
2023-12-26 18:50:33 -06:00
e2d0a784f1 [olympic/keel] Cleanup 2023-12-26 18:37:02 -06:00
f08821422a [nostalgia/core/studio] Change TileSheets to back to MC
All checks were successful
Build / build (push) Successful in 2m4s
2023-12-26 17:56:03 -06:00
6a2954f82b [nostalgia/core] Remove id from TileSheetV3::Subsheet, add TileSheetV4
Some checks failed
Build / build (push) Has been cancelled
2023-12-26 17:28:41 -06:00
9c19655ce2 [nostalgia/core] Fix build, add SubSheet ID to SubSheet Editor view
All checks were successful
Build / build (push) Successful in 2m5s
2023-12-26 16:37:09 -06:00
087c834b25 [nostalgia/core/studio] Fix Add SubSheet to increment idIt before using it
Some checks failed
Build / build (push) Failing after 23s
2023-12-26 16:34:40 -06:00
79bdbf2eaa [nostalgia/core] Add id to TileSheetV3::SubSheet model 2023-12-26 16:31:54 -06:00
2bdc3def74 [nostalgia/core/opengl] Implement flip X and flip Y for BG tiles
All checks were successful
Build / build (push) Successful in 2m4s
2023-12-26 12:34:35 -06:00
e7a663901a [nostalgia/core/opengl] Fix duplicate and missing symbol
All checks were successful
Build / build (push) Successful in 2m6s
2023-12-26 11:59:14 -06:00
ffdc0ddb97 [nostalgia/core] Add support for specifying palette banks
Some checks failed
Build / build (push) Failing after 40s
2023-12-26 11:54:31 -06:00
e941781f21 [ox/std] Cleanup Result::copyTo variants
All checks were successful
Build / build (push) Successful in 2m4s
2023-12-25 00:54:59 -06:00
b869f490c3 [ox/std] Add or_value to Optional, Result
All checks were successful
Build / build (push) Successful in 2m4s
2023-12-25 00:51:17 -06:00
caf8d93c21 [nostalgia] Delete .gitlab-ci.yml
All checks were successful
Build / build (push) Successful in 2m6s
2023-12-25 00:42:36 -06:00
afbf2caf97 [nostalgia] Remove conan from devenv
All checks were successful
Build / build (push) Successful in 2m5s
2023-12-24 06:41:18 -06:00
20914eaade [nostalgia] Add Gitea action file 2023-12-24 06:38:28 -06:00
c5f76ff558 [nostalgia/core] Add setBgBpp function 2023-12-23 21:33:52 -06:00
050339ba09 [nostalgia] Update developer-handbook 2023-12-23 19:08:18 -06:00
45ec39f77b [ox/std] Add Result::orVal 2023-12-23 17:52:20 -06:00
319fbb2600 [nostalgia] Add .lldbinit 2023-12-23 17:41:18 -06:00
f43d97a17e [nostalgia] Add missing type descriptors 2023-12-23 17:40:17 -06:00
a0974637a3 [nostalgia] Add missing test tilesheets 2023-12-23 17:39:43 -06:00
c90a8449be [olympic/turbine] Fix some broken CMake vars 2023-12-23 15:30:54 -06:00
95dcd6bee7 [teagba] Fix not to rely on TURBINE_BUILD_TYPE 2023-12-23 15:30:22 -06:00
5b167fd53b [nfde] Bump minimum CMake for NFDE to silence CMake warning 2023-12-23 15:01:21 -06:00
a701a241eb [imgui] Add target_include_directories for ImGui 2023-12-23 14:35:12 -06:00
9907bb8f1d [nostalgia] Allow building Studio mods without Studio app 2023-12-23 14:34:32 -06:00
9cb6bd4a32 [teagba] Cleanup CMake 2023-12-23 12:25:12 -06:00
2dba592a42 [nostalgia,olympic] Cleanup CMake 2023-12-23 12:23:47 -06:00
978f2f9c4f [nostalgia/core/gba] Cleanup 2023-12-23 01:50:26 -06:00
2bad4ee416 Add OLYMPIC_BUILD_STUDIO CMake var 2023-12-23 01:25:51 -06:00
46d1313797 [nostalgia/core] Get TileSheetSet working with 8bpp setting 2023-12-23 01:24:56 -06:00
fcf6f00797 [nostalgia/core] Get TileSheetSet working 2023-12-22 22:38:46 -06:00
ef6e3af735 [ox/model] Fix infinite recursion caused by have a vector of the same type in ModelValue 2023-12-22 19:44:04 -06:00
80d0df2f46 [ox/fs] Cleanup FileAddress model 2023-12-22 19:40:30 -06:00
9db10ec4a1 [ox/mc] Fix serialization of negative numbers in non-64 bit values 2023-12-22 19:36:42 -06:00
c460e0f9e0 [olympic/studio] Fix NewMenu to clear item name on reopen 2023-12-22 04:49:13 -06:00
3fa9d132ae [ox/mc] Fix issue with -1 union index 2023-12-22 04:42:13 -06:00
907ead2948 [ox/std] Fix Optional deref operator, in_place constructor 2023-12-22 04:41:39 -06:00
8526b3fa51 [nostalgia/core] Add loading multiple tile sheets 2023-12-22 01:03:41 -06:00
6de0e882e9 [teagba] Change sprite buffer to fully update on every VSync 2023-12-22 01:02:24 -06:00
d29118d783 [nostalgia/core] Cleanup graphics API 2023-12-21 21:18:31 -06:00
8395128efa [teagba] Update to newer conventions 2023-12-21 21:18:01 -06:00
77c86b9516 [ox/preloader] Add missing typenames 2023-12-20 23:04:34 -06:00
6d2a20e8bd [nostalgia/core/opengl] Allow GL implementation to customize sprite count and size 2023-12-20 23:01:56 -06:00
056284c857 [sample_project] Add ~ and | to charset 2023-12-20 22:08:26 -06:00
3787f6adb2 Make gitignore ignore all .gba and .sav files 2023-12-20 22:06:49 -06:00
ce34d450b9 [nostalgia/player] Turn player back into test sandbox 2023-12-20 20:13:54 -06:00
8fa47e961d [nostalgia/core/opengl] Disable depth testing once core scene is drawn 2023-12-20 19:22:47 -06:00
4e4cec1b64 [teagba] Change a reinterpret_cast to bit_cast 2023-12-20 19:01:31 -06:00
9840b6fdee [nostalgia/core] Add a background priority option 2023-12-20 19:00:23 -06:00
d0c90c39e0 [nostalgia/core/opengl] Cleanup priority, ensure sprites draw over BGs by default 2023-12-20 18:59:41 -06:00
7ba6fb3ac5 [ox/fs] Fix log message 2023-12-19 23:38:29 -06:00
8dd6adc554 [nostalgia/core] Specify a maximum for priority level 2023-12-19 23:06:14 -06:00
0093778f64 [nostalgia/core/opengl] Cleanup sprite enable/disable code 2023-12-19 22:55:41 -06:00
59016ee894 [nostalgia/core] Fix OpenGL sprites, add priority 2023-12-19 22:37:18 -06:00
2b8dbb88b2 [teagba] Fix applySpriteUpdates to reset update counter 2023-12-17 18:40:12 -06:00
7bc1d90be8 Restore some global CMake setting that were moved to nostalgia 2023-12-16 20:08:26 -06:00
cfb7d4f861 [nostalgia/studio] Add icon 2023-12-16 10:51:14 -06:00
7a6e94959c [nostalgia] Move nostalgia install vars to nostalgia dir CMakeLists.txt 2023-12-16 10:45:04 -06:00
eb1846278b [nostalgia/studio] Update app name 2023-12-16 10:35:28 -06:00
00c2a39dba [olympic] Cleanup 2023-12-16 03:05:57 -06:00
56f59b29fe [nostalgia/core/studio] Add scale option to TileSheet export 2023-12-16 02:58:54 -06:00
9b11fa4e91 [olympic/keel] Fix some unsafe pointer accesses, disconnect signals on asset move 2023-12-15 01:33:08 -06:00
72e54da017 [olympic/turbine] East const Turbine, cleanup 2023-12-15 00:54:55 -06:00
58d13a3ad9 [olympic/studio/modlib] East const Studio 2023-12-15 00:49:55 -06:00
5ae6df7e05 [olympic/applib] East const applib 2023-12-15 00:26:31 -06:00
f71d4d3efd [olympic/keel] Finish east consting Keel 2023-12-15 00:22:56 -06:00
4b824ddef4 [olympic] Change readClaw to take ref to TypeStore 2023-12-14 23:56:14 -06:00
8b3b8d50d6 [ox/claw] Change readClaw to take ref to TypeStore 2023-12-14 23:56:02 -06:00
1f2e9917f1 [nostalgia/core/opengl] Cleanup fragment shader 2023-12-14 23:47:00 -06:00
13ddbd981e [olympic,nostalgia] Cleanup some reinterpret_casts 2023-12-14 23:39:30 -06:00
3a781f6704 [ox/std] Improve r/l-value correctness of Result::to, make unwrap nodiscard 2023-12-14 22:41:05 -06:00
30909f85a3 [ox/std] Fix Result::copyTo 2023-12-14 22:33:03 -06:00
9cc27f5be9 [ox/std] Fix error handling for Result::copyTo 2023-12-14 22:28:16 -06:00
cdc7428eb6 [olympic,nostalgia] Update Result copyTo and moveTo calls to take refs 2023-12-14 22:26:55 -06:00
d31938ba4f [ox] Make Result copyTo and moveTo take refs 2023-12-14 22:26:17 -06:00
935099f8d4 [nostalgia] Re-enable Scene module 2023-12-14 22:03:39 -06:00
63608229e1 [nostalgia/scene/studio] Remove Scene maker from New Item wizard 2023-12-14 22:01:26 -06:00
e6803af22f [ox/mc] Fix more Clang issues 2023-12-14 21:35:02 -06:00
db961739ad [olympic/studio] Fix several crashes 2023-12-14 21:34:46 -06:00
2167a46266 [olympic/studio] Make copy/cut/paste enabled function noexcept 2023-12-14 19:37:24 -06:00
d1c6ab9f77 [nostalgia/core/studio] Cleanup TileSheetEditor, make it set copy/cut/paste enabled/disabled 2023-12-14 19:36:10 -06:00
c426decd99 [ox/oc] Fix C string writing 2023-12-14 19:28:14 -06:00
496afd66ea [ox/fs] Fix segfault in FileAddress 2023-12-14 19:27:47 -06:00
ad7f696a71 [glutils] Fix GLFrameBuffer to use right delete function 2023-12-14 19:08:37 -06:00
819e93bb1c [olympic/studio,nostalgia] Change Editor item name to item path, make
TileSheetEditorImGui inherit from Editor
2023-12-13 23:15:53 -06:00
960889749d [ox] Fix some template issue that come up with some versions of Clang, fix empty string read in OC 2023-12-13 22:46:13 -06:00
1b93b2038f [olympic,nostalgia] Move item name/path studio::Editor 2023-12-12 23:06:14 -06:00
d056323679 [nostalgia,olympic] Remove src as include directory 2023-12-12 20:31:05 -06:00
b10d9b6118 [developer-handbook] Cleanup ordering of Claw section 2023-12-12 20:24:31 -06:00
bd44fcf6ad [nfde] Update minimum CMake version 2023-12-12 20:24:20 -06:00
a1de7fbd8a [olympic,nostalgia] Make Applib an interface library that publicly exports applib.cpp 2023-12-12 20:23:54 -06:00
debeb83119 [glutils] Move glutils to deps 2023-12-11 22:57:59 -06:00
e2545a956b [olympic] Move keel, turbine, and studio to olympic 2023-12-11 22:48:22 -06:00
a60765b338 Use project name in Makefile throughout and pass to pkg-gba 2023-12-11 22:26:20 -06:00
dc233286b4 [nostalgia] Update logo 2023-12-11 22:21:45 -06:00
5b929b8796 [nostalgia] Move Olympic app parameters to NostalgiaProfile library 2023-12-11 22:21:01 -06:00
aea1aabcd7 [nostalgia] Restructure module register guards to behave more like include guards 2023-12-11 22:19:10 -06:00
3b8a9af97b [keel] Remove NostalgiaKeelModules as a dependency of keel 2023-12-11 22:16:16 -06:00
d54853a8b5 [studio/applib] Cleanup 2023-12-10 22:18:48 -06:00
d06412a6fe [nostalgia/tools] Remove old pack.cpp file 2023-12-10 22:16:23 -06:00
937e88ce7a [keel] Add missing file 2023-12-10 22:14:06 -06:00
9a5bdebbd7 [nostalgia] Rename nost-pack to nostalgia-pack 2023-12-10 22:12:02 -06:00
a2361c3fd9 [keel,nostalgia] AppLib-ize nost-pack 2023-12-10 22:10:37 -06:00
d6f0fe0cc8 [studio/applib] Remove separate logger instantiation 2023-12-10 21:35:01 -06:00
e3b2c66d70 [olympic/applib] Change applib run arguments 2023-12-10 21:33:45 -06:00
6dec1bf5ed [olympic/applib] Cleanup unused header 2023-12-10 21:10:35 -06:00
af1f674bc0 [olympic/applib] Move run function to olympic namespace 2023-12-10 21:07:17 -06:00
6a1e2f7566 [olympic/applib] Make applib module loading optional 2023-12-10 20:59:15 -06:00
393259a010 [nostalgia,olympic,studio] Add Olympic applib system, convert Studio to use it 2023-12-10 20:39:08 -06:00
b6b59e77f5 [nostalgia/core/studio] Cleanup TileSheetEditor commands 2023-12-10 17:27:18 -06:00
4a94672fdc [nostalgia/core/studio] Fix some use after move bugs 2023-12-10 17:17:03 -06:00
d22c968561 [nostalgia/core/studio] String hygiene change 2023-12-10 17:13:42 -06:00
79c85c2a33 [turbine] Cleanup 2023-12-10 17:03:58 -06:00
3ac3b7b5e6 [nostalgia,studio] Cleanup 2023-12-10 17:03:51 -06:00
8c9ebbedae [nostalgia,studio] Replace some String returns with StringView 2023-12-10 15:09:51 -06:00
dbd98fe18b [nostalgia/core/studio] Really pedantic formatting change 2023-12-10 02:00:54 -06:00
7418a7126a [nostalgia/core/studio] Restructure core studio for maintainability 2023-12-10 01:50:52 -06:00
d5a1e11ec5 [nostalgia/scene/studio] Fix vertical resizing to crop from bottom of view 2023-12-10 00:16:02 -06:00
f4a93d8419 [glutils] Change frame buffers to just use linear filtering 2023-12-10 00:10:51 -06:00
e923c73c91 [nostalgia/scene/studio] Simplify check for framebuffer resizing 2023-12-09 23:53:34 -06:00
4a9f035014 Disable some annoying clang-tidy warnings 2023-12-09 23:39:03 -06:00
b5ee68c90b [nostalgia/scene/studio] Fix SceneEditorView to work after switching tabs 2023-12-09 23:24:14 -06:00
e906237d76 [nostalgia/core/opengl] Remove debug line 2023-12-09 23:23:39 -06:00
6bcf29b8f2 [nostalgia/core] Cleanup 2023-12-09 23:20:48 -06:00
406388c042 [README] Add libgtk-3-dev to Debian dependency list 2023-12-09 23:20:12 -06:00
371044d63d [nostalgia] Fix scaling of SceneEditorView not to be completely broken 2023-12-09 23:18:04 -06:00
62c671e823 [nostalgia/core] Cleanup on TileSheet 2023-12-09 17:46:16 -06:00
0ac494998f [glutils] Add wrapper function around resizeInitFrameBuffer 2023-12-09 17:13:58 -06:00
500c012713 [nostalgia/core/studio] Cleanup TileSheetEditor constructor 2023-12-09 17:12:04 -06:00
1c4fb80702 Remove debug build from GitLab CI 2023-12-09 15:18:51 -06:00
a4fac4c1d3 [ox/fs] Some cleanup for FileAddress 2023-12-09 15:06:06 -06:00
115941a787 [nostalgia/core/studio] Fix palette selection reversion on undo of palette change 2023-12-09 12:57:16 -06:00
65a179e314 [nostalgia/player] Make error output actually check for error 2023-12-09 11:22:10 -06:00
eed240eacc [ox/mc] Fix test struct model, fix zeroing out of empty vectors in unions 2023-12-09 11:21:27 -06:00
cc7c7ac9d7 [ox/std] Fix more functions to work with UPter custom deleters 2023-12-09 01:33:33 -06:00
9a80196fa6 [nostalgia/core] Make Context definition private 2023-12-09 01:27:31 -06:00
8804819e17 [ox/model] Remove another const_cast 2023-12-09 00:50:14 -06:00
ade6af8698 [ox] Add optional typename to satisfy clangd 2023-12-09 00:49:37 -06:00
cd0958c691 [ox] Cleanup some const_casts 2023-12-09 00:49:03 -06:00
40a3c28fbf [turbine] Remove dead code 2023-12-09 00:32:39 -06:00
def994f406 [turbine/glfw] Enable GLFW_OPENGL_FORWARD_COMPAT on all platforms 2023-12-09 00:18:10 -06:00
e808859e29 [nostalgia/player] Give player a mechanism for reporting failure in release builds 2023-12-09 00:14:30 -06:00
9e9f30fb18 [nostalgia/core] Fix some GL rendering issues 2023-12-09 00:05:14 -06:00
facde6bdce [keel,nostalgia,studio,turbine] Cleanup structure of Turbine 2023-12-09 00:03:31 -06:00
1298051a1a [ox/std] Give UPter alias the other template parameter of UniquePtr 2023-12-08 22:33:36 -06:00
f169c96e78 [ox/claw] Remove ReadClaw from build 2023-12-07 00:15:08 -06:00
1547e8e550 Add OX_NODEBUG to GitLab CI 2023-12-07 00:08:37 -06:00
795b1add64 [nostalgia,studio] Fix includes 2023-12-06 23:59:03 -06:00
db91ea6a63 [glutils,nostalgia] Ptr to ref changes 2023-12-06 23:56:49 -06:00
7e19f45c69 [ox/std] Add SpanView::data() 2023-12-05 22:51:18 -06:00
57ba1caf90 [nostalgia] Cleanup headers 2023-12-05 22:50:03 -06:00
a5bdad448f [nostalgia/core] Cleanup headers, TileSheet versioning 2023-12-05 22:37:22 -06:00
54fcbb1a33 [studio] Adjust size of NewMenu, sort items, rename Quit to Cancel 2023-12-04 21:45:59 -06:00
195fd7a113 [nostalgia,studio] Cleanup, simplify string handling 2023-12-04 21:45:23 -06:00
0d606643f5 [ox/mc,ox/oc] Fix write for ox::Array, cleanup 2023-12-04 21:43:22 -06:00
402f54b3e3 [sample_project] Add ox FileAddress type descriptors 2023-12-04 00:45:59 -06:00
ed5fc079ee [studio/modlib] Fix project data directory in Project 2023-12-04 00:45:31 -06:00
140005799f [glutils,nostalgia/core] Move GlslVersion from GlUtils to Nostalgia Core 2023-12-04 00:40:25 -06:00
7d9a1676e8 [ox/claw] Test cleanup 2023-12-04 00:26:08 -06:00
b61f81abf0 [ox] Make tests more consistent 2023-12-04 00:22:00 -06:00
775efbddc8 [keel] Formatting fixes 2023-12-03 23:49:02 -06:00
1505d7ea37 [keel,nostalgia/tools,studio] Convert some pointers to references 2023-12-03 22:48:30 -06:00
26a2d340d6 [keel,studio] Cleanup string handling 2023-12-03 22:26:25 -06:00
ce514d586c [keel] Cleanup string handling 2023-12-03 22:15:22 -06:00
5cbf789374 [ox/std] Add lastIndexOf(StringView, char) 2023-12-03 22:14:42 -06:00
3f83a254d2 [keel] Fix UUID to path lookups to fail properly 2023-12-03 22:02:00 -06:00
348193ae9e [nostalgia,studio] Cleanup string handling 2023-12-03 22:01:38 -06:00
6b7c002a10 [nostalgia] Style updates 2023-12-03 21:14:20 -06:00
34081a0414 [turbine/gba] Make wake up time static 2023-12-03 20:38:23 -06:00
d23b69ce17 [nostalgia,studio] Cleanup 2023-12-03 19:59:27 -06:00
5717d67462 [nostalgia/core] Cleanup 2023-12-03 19:10:27 -06:00
7666bcc2db [keel,nostalgia] Cleanup pack, move toward further library-ization 2023-12-03 19:09:23 -06:00
8f5173e52a [ox/std] Add CStringView::CStringView(StringLiteral) 2023-12-03 19:06:37 -06:00
9ab3543b32 [ox/std] Rename Result::get to Result::copyTo 2023-12-03 19:03:42 -06:00
d16bbef282 [ox/std] Remove ox_strcpy 2023-12-03 19:03:08 -06:00
a8db357360 [ox/fs] Cleanup unnecessary constructors in FileAddress 2023-12-03 19:02:36 -06:00
566b724d36 [nostalgia] Update to new FileAddress constructor 2023-12-03 10:18:33 -06:00
b13eb0ef70 [ox/fs] Make FileAddress constructor take a StringLiteral 2023-12-03 10:17:24 -06:00
9855a0bcf0 [ox/std] Cleanup 2023-12-02 04:02:42 -06:00
611e2fa7cb [ox/std] Cleanup 2023-12-02 01:13:03 -06:00
95d9aee0cf [ox/std] Cleanup stdlib/non-stdlib specific build path in logging 2023-12-02 00:26:18 -06:00
3de03bf1fd [ox] Make String::String(String const&) explicit 2023-12-01 23:39:40 -06:00
742427584a [keel,nostalgia/core] Remove implicit String::String(String const&) calls 2023-12-01 23:38:59 -06:00
91fd0d0786 Disable GLFW tests, example programs, and docs in build 2023-12-01 23:00:17 -06:00
53262c53c4 [keel] Fix formatting 2023-12-01 22:54:27 -06:00
b212385b17 [studio] Cleanup ItemMaker constructors 2023-12-01 22:54:00 -06:00
453e08497d [keel,nostalgia] Make core calls take Context references instead of pointers 2023-12-01 22:53:21 -06:00
72c130d8a9 [ox/std] Fix Result move constructor, add & and && variants of unwrap 2023-12-01 22:50:25 -06:00
9904399724 [keel,studio,turbine] Finish removing implicit String(const char*) calls 2023-12-01 22:44:24 -06:00
1a1c8ae6cc [ox] Make ox::String::String(const char*) explicit 2023-12-01 22:36:24 -06:00
e9822bf124 [nostalgia,studio] Remove implicit ox::String::String(const char*) calls 2023-12-01 22:35:02 -06:00
644abd7f22 Get rid of separate test stage in gitlab-ci 2023-12-01 01:03:53 -06:00
1e8d8c8b9e [buildcore] Use python3 variable instead of python3 directly 2023-12-01 01:00:58 -06:00
eccb8c4fb3 Make gitlab-ci build release and test with release, debug, and asan 2023-12-01 00:53:51 -06:00
6b3974eb93 [buildcore] Make mypy run with python3 -m 2023-12-01 00:51:23 -06:00
f6058f4e07 Add gitlab-ci file 2023-12-01 00:50:45 -06:00
ecb09930db [turbine/glfw] Partially revert debug change 2023-12-01 00:06:58 -06:00
fc5e63a4d7 [ox/std] Make substr support CStringView, and always return a StringView 2023-11-30 23:15:51 -06:00
232a166833 [keel,nostalgia,studio] Make keel use references in place of a lot of pointers 2023-11-30 23:15:16 -06:00
95ba8eb138 [glutils] Do some cleanup with ox::CStringView 2023-11-30 22:06:03 -06:00
a37df08c19 [keel] Make Context::appName a BasicString<32> to generally avoid allocations while ensuring that Context owns a copy 2023-11-30 21:46:17 -06:00
0fc7e7005c [keel,nostalgia/tools/pack,studio] Cleanup 2023-11-30 21:45:03 -06:00
68a0dd9660 [ox/std] Give Vector MaybeSV in places where it makes sense 2023-11-30 21:28:11 -06:00
d635a954fa [ox/std] Add missing file, add more string types 2023-11-30 21:24:05 -06:00
d0f19fd51d [teagba] Make some globals static 2023-11-30 01:29:53 -06:00
dd16577b50 [ox/fs] Change substr function form 2023-11-30 01:02:29 -06:00
c0aa119155 [ox/fs] Add FileSystem::write variants that take Spans 2023-11-30 01:02:05 -06:00
3c9ce4436a [ox/fs] Make FileAddress::getPath return a StringView 2023-11-30 01:01:01 -06:00
2a692fc46e [ox/std] Add Span::data() 2023-11-30 01:00:38 -06:00
e543131f0d [nostalgia,studio] Cleanup Studio 2023-11-30 00:57:47 -06:00
c085c50b30 [nostalgia/pack] Update for Keel 2023-11-30 00:56:53 -06:00
bb8fb0469a [keel] Cleanup pack 2023-11-29 20:33:09 -06:00
15bc41dd35 [ox/std] Fix StringView(BaseStringView const&) constructor 2023-11-29 00:35:34 -06:00
85e7375f6f [buildcore] Cleanup 2023-11-28 23:34:12 -06:00
da98aa864c [keel,nostalgia,studio,turbine] Fixes for ox::String explicit change 2023-11-28 23:32:29 -06:00
3a62650d62 [ox/std] Make String(StringView) constructor explicit, add StringLiteral 2023-11-28 23:31:11 -06:00
7008ebfb40 [ox/std] Make HashMap use StringView for string lookups 2023-11-28 23:29:10 -06:00
709dc36d0b [ox/mc] Fix read test 2023-11-27 22:02:38 -06:00
540ed9b3f9 [keel,nostalgia,turbine] Change log channel delimiter from :: to . 2023-11-25 20:59:01 -06:00
ecc49a63b0 [ox] Change log channel delimiter from :: to . 2023-11-25 20:58:35 -06:00
c8ad05215f [glutils] Fix destructors 2023-11-24 13:46:46 -06:00
79b6046813 [nostalgia/studio] Fix main argc and argv for Windows 2023-11-24 11:10:28 -06:00
ed5271166e Update developer handbook 2023-11-23 18:22:22 -06:00
b946e428ad [keel,nostalgia,turbine] Cleanup 2023-11-23 01:46:11 -06:00
a84a829769 [ox] Cleanup String/StringView conversions, MallocaPtr 2023-11-23 01:34:16 -06:00
5b91ad25c2 [teagba] Fix MSVC warning 2023-11-14 20:24:21 -06:00
98983d1229 [nostalgia/core] Cleanup 2023-11-14 20:23:50 -06:00
b12097769e [ox/std] Fix MSVC warnings 2023-11-14 20:23:21 -06:00
99a7a2cbfc [buildcore] Fix arch output for host_env to be more consistent 2023-11-14 20:21:49 -06:00
e9c5134286 [ox/model] Fix compile error when instantiating ModelHandlerAdaptor for readers 2023-11-14 20:21:02 -06:00
b7a1236bae [ox/model] Fix MSVC warning 2023-11-14 20:19:25 -06:00
d386bc8c91 [ox/mc] Fix MC read alloca in a loop 2023-11-13 23:42:09 -06:00
3eec0a149d [ox/mc] Cleanup 2023-11-13 22:59:11 -06:00
8d2c8df014 [ox/mc] Fix an unwanted formatting "correction" from Visual Studio 2023-11-13 21:53:21 -06:00
18ace3ceff [ox/mc] Fix use of uncaptured var in lambda 2023-11-13 21:50:11 -06:00
8ddc8f40e5 [buildcore] Fix hostevn cmd to return OS instead of hostname 2023-11-13 21:46:53 -06:00
d7a6bc4ae4 [nostalgia/core/opengl] Fix sprite drawing for instances of core that are not application wide 2023-11-13 21:43:35 -06:00
597a8c736e [ox/mc] Fix alloca use in loop 2023-11-12 00:53:25 -06:00
d9b676d1b2 [ox/std] 32 bit system fixes 2023-11-12 00:41:47 -06:00
158115c29f [ox] Fix most MSVC warnings 2023-11-12 00:31:13 -06:00
109f272650 [nostalgia] More changes to accommodate for Windows 2023-11-12 00:14:52 -06:00
77e475980d [ox/model] Restore assert in modelFieldCount 2023-11-11 23:30:34 -06:00
f6d2d96ff9 [turbine] Cleanup 2023-11-11 23:24:21 -06:00
81d092e967 [buildcore] Windows fixes 2023-11-11 22:35:34 -06:00
3fbb2a0086 [ox/logconn] MSVC fixes 2023-11-11 21:57:25 -06:00
59c11e5309 [nostalgia] Make Windows builds of player and studio WIN32 apps 2023-11-11 21:45:23 -06:00
ce20282be0 [ox/std] MSVC fix 2023-11-11 21:14:59 -06:00
7ee52db6a1 [ox] MSVC fixes 2023-11-11 20:24:11 -06:00
868adae053 [nostalgia] Cleanup 2023-11-05 10:19:27 -06:00
4ae6fd7c17 [ox/std] Add uint_t 2023-11-05 10:18:39 -06:00
327 changed files with 7978 additions and 6074 deletions

View File

@@ -4,10 +4,9 @@ Checks: '-*,
cppcoreguidelines-interfaces-global-init, cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions, cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init, cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast, -cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing, cppcoreguidelines-slicing,
google-default-arguments, google-default-arguments,
google-explicit-constructor,
google-runtime-operator, google-runtime-operator,
hicpp-exception-baseclass, hicpp-exception-baseclass,
hicpp-multiway-paths-covered, hicpp-multiway-paths-covered,
@@ -53,6 +52,7 @@ readability-uniqueptr-delete-release,
readability-use-anyofallof, readability-use-anyofallof,
cert-*, cert-*,
misc-*, misc-*,
-misc-include-cleaner
-misc-use-anonymous-namespace, -misc-use-anonymous-namespace,
readability-duplicate-include, readability-duplicate-include,
-misc-non-private-member-variables-in-classes, -misc-non-private-member-variables-in-classes,

View File

@@ -0,0 +1,19 @@
name: Build
run-name: ${{ gitea.actor }} build and test
on: [push]
jobs:
build:
runs-on: nostalgia
steps:
- name: Check out repository code
uses: actions/checkout@v3
- run: make purge configure-debug
- run: make build
- run: make test
- run: make purge configure-asan
- run: make build
- run: make test
- run: make purge configure-release
- run: make build
- run: make test

7
.gitignore vendored
View File

@@ -2,8 +2,10 @@
.clangd .clangd
.current_build .current_build
.conanbuild .conanbuild
.idea
.mypy_cache .mypy_cache
.stfolder .stfolder
.stignore
scripts/__pycache__ scripts/__pycache__
CMakeLists.txt.user CMakeLists.txt.user
ROM.oxfs ROM.oxfs
@@ -13,8 +15,7 @@ compile_commands.json
dist dist
graph_info.json graph_info.json
imgui.ini imgui.ini
nostalgia.gba *.gba
nostalgia.sav *.sav
nostalgia_media.oxfs
studio_state.json studio_state.json
tags tags

1
.lldbinit Normal file
View File

@@ -0,0 +1 @@
type summary add --summary-string "${var.m_buff.m_items}" ox::String

View File

@@ -11,16 +11,11 @@ endif()
include(deps/buildcore/base.cmake) include(deps/buildcore/base.cmake)
set(NOSTALGIA_BUILD_PLAYER ON CACHE BOOL "Build Player")
set(NOSTALGIA_BUILD_STUDIO ON CACHE BOOL "Build Studio")
set(OX_ENABLE_TRACEHOOK OFF CACHE BOOL "Generate OxTraceHook shared library for uprobes") set(OX_ENABLE_TRACEHOOK OFF CACHE BOOL "Generate OxTraceHook shared library for uprobes")
if(BUILDCORE_TARGET STREQUAL "gba") if(BUILDCORE_TARGET STREQUAL "gba")
set(NOSTALGIA_BUILD_STUDIO OFF)
set(TURBINE_BUILD_TYPE "GBA")
include(deps/gbabuildcore/base.cmake) include(deps/gbabuildcore/base.cmake)
else() else()
set(TURBINE_BUILD_TYPE "Native")
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif() endif()
@@ -30,22 +25,12 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if(APPLE) if(APPLE)
set(CMAKE_MACOSX_RPATH OFF) set(CMAKE_MACOSX_RPATH OFF)
set(CMAKE_INSTALL_NAME_DIR "@executable_path/../Library/nostalgia")
set(NOSTALGIA_DIST_BIN nostalgia-studio.app/Contents/MacOS)
set(NOSTALGIA_DIST_LIB nostalgia-studio.app/Contents/Library)
set(NOSTALGIA_DIST_MODULE nostalgia-studio.app/Contents/Plugins)
set(NOSTALGIA_DIST_RESOURCES nostalgia-studio.app/Contents/Resources)
set(NOSTALGIA_DIST_MAC_APP_CONTENTS nostalgia-studio.app/Contents)
else() else()
if(UNIX) if(UNIX)
set(BUILD_SHARED_LIBS ON) set(BUILD_SHARED_LIBS ON)
endif() endif()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(NOSTALGIA_DIST_BIN bin)
set(NOSTALGIA_DIST_LIB lib)
set(NOSTALGIA_DIST_MODULE lib)
set(NOSTALGIA_DIST_RESOURCES share)
endif() endif()
add_subdirectory(deps/ox) add_subdirectory(deps/ox)
@@ -57,7 +42,6 @@ add_subdirectory(deps/teagba)
if(NOT BUILDCORE_TARGET STREQUAL "gba") if(NOT BUILDCORE_TARGET STREQUAL "gba")
include_directories( include_directories(
SYSTEM SYSTEM
deps/glfw/deps
deps/glfw/include deps/glfw/include
deps/imgui deps/imgui
deps/imgui/backends deps/imgui/backends
@@ -65,7 +49,11 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
/usr/local/include /usr/local/include
) )
add_subdirectory(deps/glad) add_subdirectory(deps/glad)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
add_subdirectory(deps/glfw) add_subdirectory(deps/glfw)
add_subdirectory(deps/glutils)
add_subdirectory(deps/imgui) add_subdirectory(deps/imgui)
add_subdirectory(deps/lodepng) add_subdirectory(deps/lodepng)
add_subdirectory(deps/nfde) add_subdirectory(deps/nfde)

View File

@@ -31,7 +31,6 @@ RUN dnf install -y clang \
python3-pip \ python3-pip \
libglvnd-devel \ libglvnd-devel \
gtk3-devel gtk3-devel
RUN pip install conan
############################################################################### ###############################################################################
# Install devkitARM # Install devkitARM

View File

@@ -1,31 +1,32 @@
BC_VAR_PROJECT_NAME=nostalgia BC_VAR_PROJECT_NAME=nostalgia
BC_VAR_PROJECT_NAME_CAP=Nostalgia
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/nostalgia-studio.app/Contents/MacOS/nostalgia-studio NOSTALGIA_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/nostalgia-studio NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio
MGBA=mgba-qt MGBA=mgba-qt
endif endif
.PHONY: pkg-gba .PHONY: pkg-gba
pkg-gba: build pkg-gba: build
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
.PHONY: run .PHONY: run
run: build run: build
./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
.PHONY: run-studio .PHONY: run-studio
run-studio: build run-studio: build
${NOSTALGIA_STUDIO} ${NOSTALGIA_STUDIO}
.PHONY: gba-run .PHONY: gba-run
gba-run: pkg-gba gba-run: pkg-gba
${MGBA} nostalgia.gba ${MGBA} ${BC_VAR_PROJECT_NAME}.gba
.PHONY: debug .PHONY: debug
debug: build debug: build
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project ${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
.PHONY: debug-studio .PHONY: debug-studio
debug-studio: build debug-studio: build
${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO} ${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO}

View File

@@ -14,6 +14,8 @@ For Debian (and probably other Linux distros, but the package names will
probably differ), install the following additional packages: probably differ), install the following additional packages:
* pkg-config * pkg-config
* xorg-dev * xorg-dev
* libgtk-3-dev
* python3-mypy
## Build ## Build

View File

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

View File

@@ -115,10 +115,8 @@ def hostname() -> int:
def host_env() -> int: def host_env() -> int:
os_name = os.uname().sysname.lower() os_name = platform.system().lower()
arch = platform.machine() arch = util.get_arch()
if arch == 'amd64':
arch = 'x86_64'
print(f'{os_name}-{arch}') print(f'{os_name}-{arch}')
return 0 return 0

View File

@@ -84,7 +84,7 @@ def main() -> int:
build_dir = f'{project_dir}/{args.build_root}/{build_config}' build_dir = f'{project_dir}/{args.build_root}/{build_config}'
util.rm(build_dir) util.rm(build_dir)
cmake_cmd = [ cmake_cmd = [
'cmake', '-S', project_dir, '-B', build_dir, build_tool, 'cmake', '-S', project_dir, '-B', build_dir,
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON', '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
'-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain), '-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain),
'-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg), '-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg),
@@ -92,12 +92,16 @@ def main() -> int:
'-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config), '-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config),
'-DBUILDCORE_TARGET={:s}'.format(args.target), '-DBUILDCORE_TARGET={:s}'.format(args.target),
] ]
if build_tool != '':
cmake_cmd.append(build_tool)
if qt_path != '': if qt_path != '':
cmake_cmd.append(qt_path) cmake_cmd.append(qt_path)
if platform.system() == 'Windows': if platform.system() == 'Windows':
cmake_cmd.append('-A x64') cmake_cmd.append('-A x64')
subprocess.run(cmake_cmd) cmake_err = subprocess.run(cmake_cmd).returncode
if cmake_err != 0:
return cmake_err
util.mkdir_p('dist') util.mkdir_p('dist')
if int(args.current_build) != 0: if int(args.current_build) != 0:

View File

@@ -28,11 +28,11 @@ def rm(path: str):
def get_os() -> str: def get_os() -> str:
return os.uname().sysname.lower() return platform.system().lower()
def get_arch() -> str: def get_arch() -> str:
arch = platform.machine() arch = platform.machine()
if arch == 'amd64': if arch.lower() == 'amd64':
arch = 'x86_64' arch = 'x86_64'
return arch return arch

10
deps/glutils/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,10 @@
project(GlUtils CXX)
add_subdirectory(src)
install(
DIRECTORY
include/glutils
DESTINATION
include
)

View File

@@ -9,15 +9,17 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <ox/std/bounds.hpp> #include <ox/std/bounds.hpp>
#include <ox/std/cstringview.hpp>
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/size.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include <ox/std/vector.hpp> #include <ox/std/vector.hpp>
namespace glutils { namespace glutils {
constexpr ox::StringView GlslVersion = "#version 330"; struct Empty {
virtual ~Empty() noexcept = default;
struct Empty {}; };
struct TextureBase { struct TextureBase {
@@ -41,6 +43,8 @@ struct TextureBase {
return *this; return *this;
} }
virtual ~TextureBase() noexcept = default;
}; };
@@ -60,7 +64,7 @@ struct GLObject: public Base {
o.id = 0; o.id = 0;
} }
~GLObject() noexcept { ~GLObject() noexcept override {
del(id); del(id);
} }
@@ -107,7 +111,7 @@ extern template struct GLObject<deleteProgram>;
extern template struct GLObject<deleteShader>; extern template struct GLObject<deleteShader>;
using GLBuffer = GLObject<deleteBuffer>; using GLBuffer = GLObject<deleteBuffer>;
using GLFrameBuffer = GLObject<deleteBuffer>; using GLFrameBuffer = GLObject<deleteFrameBuffer>;
using GLRenderBuffer = GLObject<deleteRenderBuffer>; using GLRenderBuffer = GLObject<deleteRenderBuffer>;
using GLShader = GLObject<deleteShader>; using GLShader = GLObject<deleteShader>;
using GLProgram = GLObject<deleteProgram>; using GLProgram = GLObject<deleteProgram>;
@@ -147,9 +151,7 @@ class FrameBufferBind {
void bind(const FrameBuffer &fb) noexcept; void bind(const FrameBuffer &fb) noexcept;
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo = nullptr) noexcept; ox::Result<GLProgram> buildShaderProgram(ox::CStringView const&vert, ox::CStringView const&frag, ox::CStringView const&geo = "") noexcept;
ox::Result<GLProgram> buildShaderProgram(const ox::String &vert, const ox::String &frag, const ox::String &geo = "") noexcept;
glutils::GLVertexArray generateVertexArrayObject() noexcept; glutils::GLVertexArray generateVertexArrayObject() noexcept;
@@ -161,7 +163,9 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept;
/** /**
* Resizes a FrameBuffer, and creates if it does not already exist. * Resizes a FrameBuffer, and creates if it does not already exist.
*/ */
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;
struct BufferSet { struct BufferSet {
glutils::GLVertexArray vao; glutils::GLVertexArray vao;
@@ -172,9 +176,9 @@ struct BufferSet {
ox::Vector<GLuint> elements; ox::Vector<GLuint> elements;
}; };
void sendVbo(const BufferSet &bs) noexcept; void sendVbo(BufferSet const&bs) noexcept;
void sendEbo(const BufferSet &bs) noexcept; void sendEbo(BufferSet const&bs) noexcept;
void clearScreen() noexcept; void clearScreen() noexcept;

View File

@@ -3,23 +3,21 @@ add_library(
glutils.cpp glutils.cpp
) )
target_include_directories(
GlUtils PUBLIC
../include
)
target_link_libraries( target_link_libraries(
GlUtils PUBLIC GlUtils PUBLIC
OxStd OxStd
glad glad
) )
install(
FILES
glutils.hpp
DESTINATION
include/glutils
)
install( install(
TARGETS TARGETS
GlUtils GlUtils
DESTINATION DESTINATION
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
) )

View File

@@ -6,7 +6,7 @@
#include <ox/std/bstring.hpp> #include <ox/std/bstring.hpp>
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include "glutils.hpp" #include "glutils/glutils.hpp"
namespace glutils { namespace glutils {
@@ -88,27 +88,23 @@ static ox::Result<GLShader> buildShader(
return shader; return shader;
} }
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo) noexcept { ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&vert,
ox::CStringView const&frag,
ox::CStringView const&geo) noexcept {
GLProgram prgm(glCreateProgram()); GLProgram prgm(glCreateProgram());
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad")); oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs); glAttachShader(prgm, vs);
if (geo && ox_strlen(geo) != 0) { if (geo.c_str() && geo.bytes() != 0) {
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo, "gshad")); oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
glAttachShader(prgm, gs); glAttachShader(prgm, gs);
} }
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag, "fshad")); oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
glAttachShader(prgm, fs); glAttachShader(prgm, fs);
glLinkProgram(prgm); glLinkProgram(prgm);
return prgm; return prgm;
} }
ox::Result<GLProgram> buildShaderProgram(
const ox::String &vert,
const ox::String &frag,
const ox::String &geo) noexcept {
return buildShaderProgram(vert.c_str(), frag.c_str(), geo.c_str());
}
GLVertexArray generateVertexArrayObject() noexcept { GLVertexArray generateVertexArrayObject() noexcept {
GLVertexArray vao; GLVertexArray vao;
glGenVertexArrays(1, &vao.id); glGenVertexArrays(1, &vao.id);
@@ -133,8 +129,9 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_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);
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);
@@ -150,21 +147,23 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
return fb; return fb;
} }
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept { void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
if (!*fb) { if (!fb) {
*fb = generateFrameBuffer(width, height); fb = generateFrameBuffer(width, height);
return; return;
} }
width = ox::max(1, width); width = ox::max(1, width);
height = ox::max(1, height); height = ox::max(1, height);
fb->width = width; fb.width = width;
fb->height = height; fb.height = height;
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_MAG_FILTER, GL_LINEAR);
// depth texture // depth texture
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);
// restore primary FB // restore primary FB
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -172,13 +171,17 @@ void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
} }
void sendVbo(const BufferSet &bs) noexcept { void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
resizeInitFrameBuffer(fb, sz.width, sz.height);
}
void sendVbo(BufferSet const&bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size()); const auto 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(const BufferSet &bs) noexcept { void sendEbo(BufferSet const&bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size()); const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);

View File

@@ -15,3 +15,8 @@ add_library(
backends/imgui_impl_glfw.cpp backends/imgui_impl_glfw.cpp
backends/imgui_impl_opengl3.cpp backends/imgui_impl_opengl3.cpp
) )
target_include_directories(
imgui SYSTEM PUBLIC
.
)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.10)
project(nativefiledialog-extended) project(nativefiledialog-extended)
if(NOT MSVC) if(NOT MSVC)

View File

@@ -1,3 +1,6 @@
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(OX_OS_WINDOWS TRUE)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
set(OX_OS_FREEBSD TRUE) set(OX_OS_FREEBSD TRUE)
else() else()

View File

@@ -13,7 +13,7 @@ namespace ox {
ClArgs::ClArgs(int argc, const char **args) noexcept { ClArgs::ClArgs(int argc, const char **args) noexcept {
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) { for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
String arg = args[i]; auto arg = String(args[i]);
if (arg[0] == '-') { if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) { while (arg[0] == '-' && arg.len()) {
arg = arg.substr(1); arg = arg.substr(1);
@@ -21,7 +21,7 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
m_bools[arg] = true; m_bools[arg] = true;
// parse additional arguments // parse additional arguments
if (i < static_cast<unsigned>(argc) && args[i + 1]) { if (i < static_cast<unsigned>(argc) && args[i + 1]) {
String val = args[i + 1]; auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') { if (val.len() && val[i] != '-') {
if (val == "false") { if (val == "false") {
m_bools[arg] = false; m_bools[arg] = false;
@@ -44,7 +44,7 @@ bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept {
String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept { String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept {
auto [value, err] = m_strings.at(arg); auto [value, err] = m_strings.at(arg);
return !err ? *value : defaultValue; return !err ? ox::String(std::move(*value)) : ox::String(defaultValue);
} }
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept { int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {

View File

@@ -16,16 +16,16 @@ target_link_libraries(
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw> $<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
) )
if(OX_USE_STDLIB) #if(OX_USE_STDLIB)
add_executable( # add_executable(
readclaw # readclaw
readclaw.cpp # readclaw.cpp
) # )
target_link_libraries( # target_link_libraries(
readclaw PUBLIC # readclaw PUBLIC
OxClaw # OxClaw
) # )
endif() #endif()
install(TARGETS OxClaw install(TARGETS OxClaw
LIBRARY DESTINATION lib LIBRARY DESTINATION lib

View File

@@ -72,9 +72,12 @@ Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
return stripClawHeader(buff.data(), buff.size()); return stripClawHeader(buff.data(), buff.size());
} }
Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz) noexcept { Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept {
oxRequire(header, readClawHeader(buff, buffSz)); oxRequire(header, readClawHeader(buff, buffSz));
oxRequire(t, ts->getLoad(header.typeName, header.typeVersion, header.typeParams)); auto const [t, tdErr] = ts.getLoad(header.typeName, header.typeVersion, header.typeParams);
if (tdErr) {
return OxError(3, "Could not load type descriptor");
}
ModelObject obj; ModelObject obj;
oxReturnError(obj.setType(t)); oxReturnError(obj.setType(t));
switch (header.fmt) { switch (header.fmt) {
@@ -103,7 +106,7 @@ Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz
return OxError(1); return OxError(1);
} }
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept { Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept {
return readClaw(ts, buff.data(), buff.size()); return readClaw(ts, buff.data(), buff.size());
} }

View File

@@ -88,8 +88,8 @@ Result<T> readClaw(const Buffer &buff) {
return readClaw<T>(buff.data(), buff.size()); return readClaw<T>(buff.data(), buff.size());
} }
Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz) noexcept; Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept;
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept; Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept;
} }

View File

@@ -8,11 +8,7 @@
#undef NDEBUG #undef NDEBUG
#include <cassert>
#include <iostream>
#include <map> #include <map>
#include <memory>
#include <string>
#include <ox/claw/format.hpp> #include <ox/claw/format.hpp>
#include <ox/claw/read.hpp> #include <ox/claw/read.hpp>
#include <ox/claw/write.hpp> #include <ox/claw/write.hpp>
@@ -107,12 +103,12 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
return OxError(0); return OxError(0);
} }
static std::map<std::string_view, ox::Error(*)()> tests = { static std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
{ {
"ClawHeaderReader", "ClawHeaderReader",
[] { [] {
ox::String hdr = "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.len() + 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");
@@ -124,7 +120,7 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
{ {
"ClawHeaderReader2", "ClawHeaderReader2",
[] { [] {
ox::String hdr = "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.len() + 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");
@@ -192,14 +188,14 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
int retval = -1; if (argc < 2) {
if (argc > 0) { oxError("Must specify test to run");
auto testName = args[1];
if (tests.find(testName) != tests.end()) {
retval = static_cast<int>(tests[testName]());
} else {
retval = 1;
}
} }
return retval; auto const testName = args[1];
auto const func = tests.find(testName);
if (func != tests.end()) {
oxAssert(func->second(), "Test returned Error");
return 0;
}
return -1;
} }

View File

@@ -245,7 +245,7 @@ class Signal<Error(Args...)> {
} }
Error call(Args... args) noexcept final { Error call(Args... args) noexcept final {
return f(args...); return f(ox::forward<Args>(args)...);
} }
}; };
@@ -260,7 +260,7 @@ class Signal<Error(Args...)> {
} }
Error call(Args... args) noexcept final { Error call(Args... args) noexcept final {
return (m_receiver->*(m_methodPtr))(args...); return (m_receiver->*(m_methodPtr))(ox::forward<Args>(args)...);
} }
void cleanup(Signal *signal) noexcept final { void cleanup(Signal *signal) noexcept final {
@@ -286,7 +286,7 @@ class Signal<Error(Args...)> {
} }
Error call(Args... args) noexcept final { Error call(Args... args) noexcept final {
return (m_receiver->*(m_methodPtr))(args...); return (m_receiver->*(m_methodPtr))(ox::forward<Args>(args)...);
} }
void cleanup(Signal*) noexcept final { void cleanup(Signal*) noexcept final {
@@ -391,14 +391,14 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
template<class... Args> template<class... Args>
void Signal<Error(Args...)>::emit(Args... args) const noexcept { void Signal<Error(Args...)>::emit(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
oxIgnoreError(f->call(args...)); oxIgnoreError(f->call(ox::forward<Args>(args)...));
} }
} }
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(args...)); oxReturnError(f->call(ox::forward<Args>(args)...));
} }
return OxError(0); return OxError(0);
} }

View File

@@ -21,7 +21,7 @@ struct TestStruct: public ox::SignalHandler {
} }
}; };
std::map<std::string, std::function<ox::Error()>> tests = { std::map<ox::StringView, std::function<ox::Error()>> tests = {
{ {
"test1", "test1",
[] { [] {
@@ -39,12 +39,14 @@ std::map<std::string, std::function<ox::Error()>> tests = {
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
if (argc > 1) { if (argc < 2) {
auto testName = args[1]; oxError("Must specify test to run");
if (tests.find(testName) != tests.end()) { }
oxAssert(tests[testName](), "Test returned Error"); auto const testName = args[1];
return 0; auto const func = tests.find(testName);
} if (func != tests.end()) {
oxAssert(func->second(), "Test returned Error");
return 0;
} }
return -1; return -1;
} }

View File

@@ -16,12 +16,6 @@ if(NOT MSVC)
endif() endif()
if(NOT OX_BARE_METAL) if(NOT OX_BARE_METAL)
if(NOT APPLE AND NOT MSVC AND NOT ${OX_OS_FREEBSD})
target_link_libraries(
OxFS PUBLIC
stdc++fs
)
endif()
set_property( set_property(
TARGET TARGET
OxFS OxFS
@@ -44,7 +38,6 @@ if(NOT OX_BARE_METAL)
target_link_libraries( target_link_libraries(
oxfs-tool oxfs-tool
OxFS OxFS
OxStd
) )
install( install(

View File

@@ -204,12 +204,12 @@ Error FileStoreTemplate<size_t>::format(void *buffer, std::size_t bufferSize) {
auto nb = new (buffer) Buffer(static_cast<size_t>(bufferSize)); auto nb = new (buffer) Buffer(static_cast<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 OxError(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 OxError(1, "Could not read data section of FileStoreData");
} }
new (data) FileStoreData; new (data) FileStoreData;
@@ -244,7 +244,7 @@ Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t dataSize, uint8_t fileType) { Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t dataSize, uint8_t fileType) {
const auto id = static_cast<size_t>(id64); const auto id = static_cast<size_t>(id64);
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()); oxReturnError(compact());
@@ -254,10 +254,10 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
if (canWrite(existing, dataSize)) { if (canWrite(existing, dataSize)) {
// delete the old node if it exists // delete the old node if it exists
if (existing.valid()) { if (existing.valid()) {
oxTracef("ox::fs::FileStoreTemplate::write", "Freeing old version of inode found at offset: {}", existing.offset()); oxTracef("ox.fs.FileStoreTemplate.write", "Freeing old version of inode found at offset: {}", existing.offset());
auto err = m_buffer->free(existing); auto err = m_buffer->free(existing);
if (err) { if (err) {
oxTrace("ox::fs::FileStoreTemplate::write::fail", "Free of old version of inode failed"); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Free of old version of inode failed");
return err; return err;
} }
existing = nullptr; existing = nullptr;
@@ -266,12 +266,12 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
auto dest = m_buffer->malloc(dataSize).value; auto dest = m_buffer->malloc(dataSize).value;
// 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()); oxReturnError(compact());
dest = m_buffer->malloc(dataSize).value; dest = m_buffer->malloc(dataSize).value;
} }
if (dest.valid()) { if (dest.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write", "Memory allocated"); oxTrace("ox.fs.FileStoreTemplate.write", "Memory allocated");
dest->id = id; dest->id = id;
dest->fileType = fileType; dest->fileType = fileType;
auto destData = m_buffer->template dataOf<uint8_t>(dest); auto destData = m_buffer->template dataOf<uint8_t>(dest);
@@ -280,26 +280,26 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
// write data if any was provided // write data if any was provided
if (data != nullptr) { if (data != nullptr) {
ox_memcpy(destData, data, dest->size()); ox_memcpy(destData, data, dest->size());
oxTrace("ox::fs::FileStoreTemplate::write", "Data written"); oxTrace("ox.fs.FileStoreTemplate.write", "Data written");
} }
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (fsData) { if (fsData) {
oxTracef("ox::fs::FileStoreTemplate::write", "Searching for root node at {}", fsData->rootNode.get()); oxTracef("ox.fs.FileStoreTemplate.write", "Searching for root node at {}", fsData->rootNode.get());
auto root = m_buffer->ptr(fsData->rootNode); auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) { if (root.valid()) {
oxTracef("ox::fs::FileStoreTemplate::write", oxTracef("ox.fs.FileStoreTemplate.write",
"Placing {} on {} at {}", dest->id.get(), root->id.get(), destData.offset()); "Placing {} on {} at {}", dest->id.get(), root->id.get(), destData.offset());
return placeItem(dest); return placeItem(dest);
} else { } else {
oxTracef("ox::fs::FileStoreTemplate::write", oxTracef("ox.fs.FileStoreTemplate.write",
"Initializing root inode: {} (offset: {}, data size: {})", "Initializing root inode: {} (offset: {}, data size: {})",
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 OxError(0);
} }
} else { } else {
oxTrace("ox::fs::FileStoreTemplate::write::fail", "Could not place item due to absence of FileStore header."); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
} }
} }
} }
@@ -315,23 +315,23 @@ Error FileStoreTemplate<size_t>::remove(uint64_t id) {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const { Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id); oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
auto src = find(static_cast<size_t>(id)); auto src = find(static_cast<size_t>(id));
// 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 OxError(1, "Could not find requested item");
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}", oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
id, src.offset(), srcData.offset()); id, src.offset(), srcData.offset());
oxTracef("ox::fs::FileStoreTemplate::read::outSize", "{} {} {}", srcData.offset(), srcData.size(), outSize); oxTracef("ox.fs.FileStoreTemplate.read.outSize", "{} {} {}", srcData.offset(), srcData.size(), outSize);
// error check // error check
if (!(srcData.valid() && srcData.size() <= outSize)) { if (!(srcData.valid() && srcData.size() <= 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); return OxError(1);
} }
@@ -346,23 +346,23 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t readSize, void *out, FsSize_t *size) const { Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t readSize, void *out, FsSize_t *size) const {
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id); oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
auto src = find(static_cast<size_t>(id)); auto src = find(static_cast<size_t>(id));
// 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 OxError(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}", oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
id, src.offset(), srcData.offset()); id, src.offset(), srcData.offset());
oxTracef("ox::fs::FileStoreTemplate::read::readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize); oxTracef("ox.fs.FileStoreTemplate.read.readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
// error check // error check
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) { if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
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 OxError(1);
} }
@@ -379,23 +379,23 @@ template<typename size_t>
template<typename T> template<typename T>
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
FsSize_t readSize, T *out, FsSize_t *size) const { FsSize_t readSize, T *out, FsSize_t *size) const {
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id); oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
auto src = find(static_cast<size_t>(id)); auto src = find(static_cast<size_t>(id));
// 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 OxError(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}", oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
id, src.offset(), srcData.offset()); id, src.offset(), srcData.offset());
oxTracef("ox::fs::FileStoreTemplate::read::readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize); oxTracef("ox.fs.FileStoreTemplate.read.readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
// error check // error check
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) { if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
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 OxError(1);
} }
@@ -422,9 +422,9 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::resize() { Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact()); oxReturnError(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)); oxReturnError(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 OxError(0);
} }
@@ -506,7 +506,7 @@ Error FileStoreTemplate<size_t>::compact() {
if (!item.valid()) { if (!item.valid()) {
return OxError(1); return OxError(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
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (fsData && oldAddr == fsData->rootNode) { if (fsData && oldAddr == fsData->rootNode) {
@@ -549,7 +549,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
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 OxError(0);
} else { } else {
return placeItem(root, item); return placeItem(root, item);
@@ -559,7 +559,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
template<typename size_t> 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 OxError(2);
} }
if (item->id > root->id) { if (item->id > root->id) {
@@ -570,7 +570,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->left = right->left; item->left = right->left;
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 OxError(0);
} else { } else {
return placeItem(right, item, depth + 1); return placeItem(right, item, depth + 1);
@@ -583,13 +583,13 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->left = left->left; item->left = left->left;
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 OxError(0);
} else { } else {
return placeItem(left, item, depth + 1); return placeItem(left, item, depth + 1);
} }
} else { } else {
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail", "Cannot insert an item on itself."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself.");
return OxError(1, "Cannot insert an item on itself."); return OxError(1, "Cannot insert an item on itself.");
} }
} }
@@ -631,14 +631,14 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
template<typename size_t> 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 OxError(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);
if (right->id == item->id) { if (right->id == item->id) {
root->right = 0; root->right = 0;
oxTracef("ox::fs::FileStoreTemplate::unplaceItem", "Unplaced Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.unplaceItem", "Unplaced Item: {}", item->id.get());
} else { } else {
return unplaceItem(right, item, depth + 1); return unplaceItem(right, item, depth + 1);
} }
@@ -646,7 +646,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
auto left = m_buffer->ptr(root->left); auto left = m_buffer->ptr(root->left);
if (left->id == item->id) { if (left->id == item->id) {
root->left = 0; root->left = 0;
oxTracef("ox::fs::FileStoreTemplate::unplaceItem", "Unplaced Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.unplaceItem", "Unplaced Item: {}", item->id.get());
} else { } else {
return unplaceItem(left, item, depth + 1); return unplaceItem(left, item, depth + 1);
} }
@@ -701,22 +701,22 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::findParen
template<typename size_t> template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(ItemPtr item, InodeId_t id, int depth) const { typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(ItemPtr item, InodeId_t id, int depth) const {
if (depth > 5000) { if (depth > 5000) {
oxTracef("ox::fs::FileStoreTemplate::find::fail", "Excessive recursion depth, stopping before stack overflow. Search for: {}", id); oxTracef("ox.fs.FileStoreTemplate.find.fail", "Excessive recursion depth, stopping before stack overflow. Search for: {}", id);
return nullptr; return nullptr;
} }
if (!item.valid()) { if (!item.valid()) {
oxTrace("ox::fs::FileStoreTemplate::find::fail", "item invalid"); oxTrace("ox.fs.FileStoreTemplate.find.fail", "item invalid");
return nullptr; return nullptr;
} }
// do search // do search
if (id > item->id) { if (id > item->id) {
oxTracef("ox::fs::FileStoreTemplate::find", "Not a match, searching on {}", item->right.get()); oxTracef("ox.fs.FileStoreTemplate.find", "Not a match, searching on {}", item->right.get());
return find(m_buffer->ptr(item->right), id, depth + 1); return find(m_buffer->ptr(item->right), id, depth + 1);
} else if (id < item->id) { } else if (id < item->id) {
oxTracef("ox::fs::FileStoreTemplate::find", "Not a match, searching on {}", item->left.get()); oxTracef("ox.fs.FileStoreTemplate.find", "Not a match, searching on {}", item->left.get());
return find(m_buffer->ptr(item->left), id, depth + 1); return find(m_buffer->ptr(item->left), id, depth + 1);
} else if (id == item->id) { } else if (id == item->id) {
oxTracef("ox::fs::FileStoreTemplate::find", "Found {} at {}", id, item.offset()); oxTracef("ox.fs.FileStoreTemplate.find", "Found {} at {}", id, item.offset());
return item; return item;
} }
return nullptr; return nullptr;
@@ -724,7 +724,7 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(Item
template<typename size_t> template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(InodeId_t id) const { typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(InodeId_t id) const {
oxTracef("ox::fs::FileStoreTemplate::find", "Searching for inode: {}", id); oxTracef("ox.fs.FileStoreTemplate.find", "Searching for inode: {}", id);
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (fsData) { if (fsData) {
auto root = m_buffer->ptr(fsData->rootNode); auto root = m_buffer->ptr(fsData->rootNode);
@@ -732,10 +732,10 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(Inod
auto item = find(root, id); auto item = find(root, id);
return item; return item;
} else { } else {
oxTrace("ox::fs::FileStoreTemplate::find::fail", "No root node"); oxTrace("ox.fs.FileStoreTemplate.find.fail", "No root node");
} }
} else { } else {
oxTrace("ox::fs::FileStoreTemplate::find::fail", "No FileStore Data"); oxTrace("ox.fs.FileStoreTemplate.find.fail", "No FileStore Data");
} }
return nullptr; return nullptr;
} }

View File

@@ -55,7 +55,7 @@ struct OX_PACKED DirectoryEntry {
} }
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept { ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
oxTracef("ox::fs::DirectoryEntry::data", "{} {} {}", this->fullSize(), sizeof(*this), this->size()); oxTracef("ox.fs.DirectoryEntry.data", "{} {} {}", this->fullSize(), sizeof(*this), this->size());
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size(), this->size()); return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size(), this->size());
} }
@@ -136,7 +136,7 @@ Directory<FileStore, InodeId_t>::Directory(FileStore fs, uint64_t inodeId) noexc
template<typename FileStore, typename InodeId_t> 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))); oxReturnError(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()) {
@@ -151,7 +151,7 @@ Error Directory<FileStore, InodeId_t>::init() noexcept {
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) { Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
if (path.valid()) { if (path.valid()) {
oxTrace("ox::fs::Directory::mkdir", path.fullPath()); oxTrace("ox.fs.Directory.mkdir", path.fullPath());
// reuse nameBuff if it has already been allocated, as it is a rather large variable // reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) { if (nameBuff == nullptr) {
nameBuff = new (ox_alloca(sizeof(FileName))) FileName; nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
@@ -168,7 +168,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, Fi
return OxError(1); return OxError(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); oxReturnError(childInode.error);
@@ -204,33 +204,33 @@ 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
oxReturnError(path.get(name)); oxReturnError(path.get(name));
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());
oxRequire(nextChild, findEntry(*name)); oxRequire(nextChild, findEntry(*name));
oxTracef("ox::fs::Directory::write", "{}: {}", *name, nextChild); oxTracef("ox.fs.Directory.write", "{}: {}", *name, nextChild);
if (nextChild) { if (nextChild) {
// reuse name because it is a rather large variable and will not be used again // reuse name because it is a rather large variable and will not be used again
// be attentive that this remains true // be attentive that this remains true
name = nullptr; name = nullptr;
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff); return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
} 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 OxError(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());
// insert the new entry on this directory // insert the new entry on this directory
// get the name // get the name
oxReturnError(path.next(name)); oxReturnError(path.next(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)); oxRequire(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 OxError(1, "Could not read existing version of Directory");
} }
@@ -239,20 +239,20 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
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 OxError(1, "Could not allocate memory for copy of Directory");
} }
oxReturnError(cpy->setSize(newSize)); oxReturnError(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 OxError(1, "Could not allocate memory for new directory entry");
} }
oxTracef("ox::fs::Directory::write", "Attempting to write Directory entry: {}", name->data()); oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name->data());
oxReturnError(val->init(inode, name->data(), val.size())); oxReturnError(val->init(inode, name->data(), val.size()));
return m_fs.write(m_inodeId, cpy, cpy->size(), static_cast<uint8_t>(FileType::Directory)); return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
} }
} }
@@ -265,10 +265,10 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
auto &name = *nameBuff; auto &name = *nameBuff;
oxReturnError(path.get(&name)); oxReturnError(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()) {
oxTrace("ox::fs::Directory::remove", "Found directory buffer."); oxTrace("ox.fs.Directory.remove", "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()) {
@@ -276,11 +276,11 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
oxReturnError(buff->free(i)); oxReturnError(buff->free(i));
} }
} else { } else {
oxTrace("ox::fs::Directory::remove", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
} }
} }
} 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 OxError(1, "Could not find directory buffer");
} }
return OxError(0); return OxError(0);
@@ -289,20 +289,20 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
template<typename F> template<typename F>
Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept { Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
oxTrace("ox::fs::Directory::ls"); oxTrace("ox.fs.Directory.ls");
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 OxError(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)); oxReturnError(cb(data->name, data->inode));
} else { } else {
oxTrace("ox::fs::Directory::ls", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
} }
} }
@@ -311,26 +311,26 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept { Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
oxTrace("ox::fs::Directory::findEntry", name); oxTrace("ox.fs.Directory.findEntry", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox::fs::Directory::findEntry::fail", "Could not findEntry directory buffer"); oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer");
return OxError(2, "Could not findEntry directory buffer"); return OxError(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()) {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
oxTracef("ox::fs::Directory::findEntry", "Comparing \"{}\" to \"{}\"", name, data->name); oxTracef("ox.fs.Directory.findEntry", "Comparing \"{}\" to \"{}\"", name, data->name);
if (name == data->name) { if (name == data->name) {
oxTracef("ox::fs::Directory::findEntry", "\"{}\" match found.", name); oxTracef("ox.fs.Directory.findEntry", "\"{}\" match found.", name);
return static_cast<InodeId_t>(data->inode); return static_cast<InodeId_t>(data->inode);
} }
} else { } else {
oxTrace("ox::fs::Directory::findEntry") << "INVALID DIRECTORY ENTRY"; oxTrace("ox.fs.Directory.findEntry") << "INVALID DIRECTORY ENTRY";
} }
} }
oxTrace("ox::fs::Directory::findEntry::fail", "Entry not present"); oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
return OxError(1, "Entry not present"); return OxError(1, "Entry not present");
} }

View File

@@ -36,13 +36,6 @@ FileAddress::FileAddress(ox::CRStringView path) noexcept {
m_type = FileAddressType::Path; m_type = FileAddressType::Path;
} }
FileAddress::FileAddress(char *path) noexcept {
auto pathSize = ox_strlen(path) + 1;
m_data.path = new char[pathSize];
memcpy(m_data.path, path, pathSize);
m_type = FileAddressType::Path;
}
FileAddress &FileAddress::operator=(const FileAddress &other) noexcept { FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
if (this == &other) { if (this == &other) {
return *this; return *this;
@@ -52,9 +45,14 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
switch (m_type) { switch (m_type) {
case FileAddressType::Path: case FileAddressType::Path:
{ {
auto strSize = ox_strlen(other.m_data.path) + 1; if (other.m_data.path) {
m_data.path = new char[strSize]; auto strSize = ox_strlen(other.m_data.path) + 1;
ox_memcpy(m_data.path, other.m_data.path, strSize); m_data.path = new char[strSize];
ox_memcpy(m_data.path, other.m_data.path, strSize);
} else {
m_data.constPath = "";
m_type = FileAddressType::ConstPath;
}
break; break;
} }
case FileAddressType::ConstPath: case FileAddressType::ConstPath:

View File

@@ -25,7 +25,7 @@ enum class FileAddressType: int8_t {
class FileAddress { class FileAddress {
template<typename T> template<typename T>
friend constexpr Error model(T*, CommonPtrWith<FileAddress> auto*) noexcept; friend constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept;
public: public:
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress"; static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
@@ -59,13 +59,7 @@ class FileAddress {
explicit FileAddress(CRStringView path) noexcept; explicit FileAddress(CRStringView path) noexcept;
template<std::size_t SmallStrSz> constexpr FileAddress(ox::StringLiteral path) noexcept;
explicit FileAddress(const ox::BasicString<SmallStrSz> &path) noexcept: FileAddress(StringView(path)) {
}
explicit FileAddress(char *path) noexcept;
explicit constexpr FileAddress(const char *path) noexcept;
constexpr ~FileAddress() noexcept; constexpr ~FileAddress() noexcept;
@@ -86,7 +80,6 @@ class FileAddress {
} }
} }
[[nodiscard]]
constexpr Result<uint64_t> getInode() const noexcept { constexpr Result<uint64_t> getInode() const noexcept {
switch (m_type) { switch (m_type) {
case FileAddressType::Inode: case FileAddressType::Inode:
@@ -96,12 +89,12 @@ class FileAddress {
} }
} }
constexpr Result<const char*> getPath() const noexcept { constexpr Result<ox::StringView> getPath() const noexcept {
switch (m_type) { switch (m_type) {
case FileAddressType::Path: case FileAddressType::Path:
return m_data.path; return ox::StringView(m_data.path);
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
return m_data.constPath; return ox::StringView(m_data.constPath);
default: default:
return OxError(1); return OxError(1);
} }
@@ -124,8 +117,8 @@ class FileAddress {
}; };
constexpr FileAddress::FileAddress(const char *path) noexcept { constexpr FileAddress::FileAddress(ox::StringLiteral path) noexcept {
m_data.constPath = path; m_data.constPath = path.c_str();
m_type = FileAddressType::ConstPath; m_type = FileAddressType::ConstPath;
} }
@@ -133,45 +126,6 @@ constexpr FileAddress::~FileAddress() noexcept {
cleanup(); cleanup();
} }
template<>
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
return FileAddress::Data::TypeName;
}
template<>
constexpr const char *getModelTypeName<FileAddress>() noexcept {
return FileAddress::TypeName;
}
template<typename T>
constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<FileAddress::Data>());
oxReturnError(io->fieldCString("path", &obj->path));
oxReturnError(io->fieldCString("constPath", &obj->path));
oxReturnError(io->field("inode", &obj->inode));
return OxError(0);
}
template<typename T>
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(io->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) {
int8_t type = 0;
oxReturnError(io->field("type", &type));
oxReturnError(io->field("data", UnionView(&fa->m_data, 0)));
} else if constexpr(T::opType() == OpType::Read) {
auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(io->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} else if constexpr(T::opType() == OpType::Write) {
auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(io->field("type", &type));
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
}
return OxError(0);
}
constexpr void FileAddress::cleanup() noexcept { constexpr void FileAddress::cleanup() noexcept {
if (m_type == FileAddressType::Path) { if (m_type == FileAddressType::Path) {
safeDeleteArray(m_data.path); safeDeleteArray(m_data.path);
@@ -184,4 +138,43 @@ constexpr void FileAddress::clear() noexcept {
m_type = FileAddressType::None; m_type = FileAddressType::None;
} }
template<>
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
return FileAddress::Data::TypeName;
}
template<>
constexpr const char *getModelTypeName<FileAddress>() noexcept {
return FileAddress::TypeName;
}
template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress::Data>());
oxReturnError(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode));
return {};
}
template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) {
int8_t type = -1;
oxReturnError(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, type)));
} else if constexpr(T::opType() == OpType::Read) {
auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} else if constexpr(T::opType() == OpType::Write) {
auto const type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
}
return {};
}
} }

View File

@@ -9,6 +9,7 @@
#pragma once #pragma once
#include <ox/std/buffer.hpp> #include <ox/std/buffer.hpp>
#include <ox/std/span.hpp>
#include <ox/fs/filestore/filestoretemplate.hpp> #include <ox/fs/filestore/filestoretemplate.hpp>
#include <ox/fs/filesystem/filelocation.hpp> #include <ox/fs/filesystem/filelocation.hpp>
@@ -66,10 +67,18 @@ class FileSystem {
return writeFilePath(path, buffer, size, FileType::NormalFile); return writeFilePath(path, buffer, size, FileType::NormalFile);
} }
Error write(CRStringView path, ox::Span<char> const&buff) noexcept {
return write(path, buff.data(), buff.size(), FileType::NormalFile);
}
Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept { Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept {
return write(inode, buffer, size, FileType::NormalFile); return write(inode, buffer, size, FileType::NormalFile);
} }
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept {
return write(inode, buff.data(), buff.size(), FileType::NormalFile);
}
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept { inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
@@ -269,11 +278,11 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
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))); oxReturnError(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 OxError(1);
} }
@@ -282,7 +291,7 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::mkdir(CRStringView path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::mkdir(CRStringView 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()); oxRequireM(rootDir, this->rootDir());
return rootDir.mkdir(path, recursive); return rootDir.mkdir(path, recursive);
} }
@@ -352,7 +361,7 @@ Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(CRStringView
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
template<typename F> template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(CRStringView path, F cb) const { Error FileSystemTemplate<FileStore, Directory>::ls(CRStringView path, F cb) const {
oxTracef("ox::fs::FileSystemTemplate::ls", "path: {}", path); oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
oxRequire(s, stat(path)); oxRequire(s, stat(path));
Directory dir(m_fs, s.inode); Directory dir(m_fs, s.inode);
return dir.ls(cb); return dir.ls(cb);
@@ -371,7 +380,7 @@ Error FileSystemTemplate<FileStore, Directory>::remove(CRStringView path, bool r
return err; return err;
} }
} 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 OxError(1);
} }
return OxError(0); return OxError(0);

View File

@@ -24,14 +24,14 @@ PassThroughFS::PassThroughFS(CRStringView dirPath) {
PassThroughFS::~PassThroughFS() noexcept = default; PassThroughFS::~PassThroughFS() noexcept = default;
String PassThroughFS::basePath() const noexcept { String PassThroughFS::basePath() const noexcept {
return m_path.string().c_str(); return ox::String(m_path.string().c_str());
} }
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept { Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
bool success = false; bool success = false;
const auto p = m_path / stripSlash(path); const auto p = m_path / stripSlash(path);
const auto u8p = p.u8string(); const auto u8p = p.u8string();
oxTrace("ox::fs::PassThroughFS::mkdir", std::bit_cast<const char*>(u8p.c_str())); oxTrace("ox.fs.PassThroughFS.mkdir", std::bit_cast<const char*>(u8p.c_str()));
if (recursive) { if (recursive) {
std::error_code ec; std::error_code ec;
const auto isDir = std::filesystem::is_directory(p, ec); const auto isDir = std::filesystem::is_directory(p, ec);
@@ -98,10 +98,10 @@ Result<FileStat> PassThroughFS::statPath(CRStringView path) const noexcept {
const auto p = m_path / stripSlash(path); const auto p = m_path / stripSlash(path);
const FileType type = std::filesystem::is_directory(p, ec) ? const FileType type = std::filesystem::is_directory(p, ec) ?
FileType::Directory : FileType::NormalFile; FileType::Directory : FileType::NormalFile;
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", "{} {}", ec.message(), path); oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
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")); oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
return FileStat{0, 0, size, type}; return FileStat{0, 0, size, type};
} }
@@ -147,12 +147,12 @@ Error PassThroughFS::readFilePath(CRStringView path, void *buffer, std::size_t b
const std::size_t size = static_cast<std::size_t>(file.tellg()); const std::size_t size = static_cast<std::size_t>(file.tellg());
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
if (size > buffSize) { if (size > buffSize) {
oxTracef("ox::fs::PassThroughFS::read::error", "Read failed: Buffer too small: {}", path); oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
return OxError(1); return OxError(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 OxError(2);
} }
return OxError(0); return OxError(0);
@@ -174,7 +174,7 @@ Error PassThroughFS::writeFilePath(CRStringView path, const void *buffer, uint64
std::ofstream f(p, std::ios::binary); std::ofstream f(p, std::ios::binary);
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size)); f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox::fs::PassThroughFS::read::error", "Write of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return OxError(1); return OxError(1);
} }
return OxError(0); return OxError(0);
@@ -188,7 +188,7 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
std::string_view PassThroughFS::stripSlash(StringView path) noexcept { std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
const auto pathLen = ox_strlen(path); const auto pathLen = ox_strlen(path);
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) { for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
path = path.substr(1); path = substr(path, 1);
} }
return {path.data(), path.bytes()}; return {path.data(), path.bytes()};
} }

View File

@@ -64,11 +64,11 @@ Error PathIterator::fileName(char *out, std::size_t outSize) {
Error PathIterator::get(char *pathOut, std::size_t pathOutSize) { Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
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 OxError(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 OxError(1);
} }
auto start = m_iterator; auto start = m_iterator;

View File

@@ -37,7 +37,7 @@ class OX_PACKED NodeBuffer {
Iterator(NodeBuffer *buffer, ItemPtr current) noexcept { Iterator(NodeBuffer *buffer, ItemPtr current) noexcept {
m_buffer = buffer; m_buffer = buffer;
m_current = current; m_current = current;
oxTrace("ox::ptrarith::Iterator::start") << current.offset(); oxTrace("ox.ptrarith.Iterator.start") << current.offset();
} }
operator const Item*() const noexcept { operator const Item*() const noexcept {
@@ -77,7 +77,7 @@ class OX_PACKED NodeBuffer {
[[nodiscard]] [[nodiscard]]
bool hasNext() noexcept { bool hasNext() noexcept {
if (m_current.valid()) { if (m_current.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset(); oxTrace("ox.ptrarith.NodeBuffer.Iterator.hasNext.current") << m_current.offset();
auto next = m_buffer->next(m_current); auto next = m_buffer->next(m_current);
return next.valid() && m_buffer->firstItem() != next; return next.valid() && m_buffer->firstItem() != next;
} }
@@ -85,7 +85,7 @@ class OX_PACKED NodeBuffer {
} }
void next() noexcept { void next() noexcept {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++; oxTrace("ox.ptrarith.NodeBuffer.Iterator.next") << m_it++;
if (hasNext()) { if (hasNext()) {
m_current = m_buffer->next(m_current); m_current = m_buffer->next(m_current);
} else { } else {
@@ -174,12 +174,12 @@ template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept { NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
ox_memset(this + 1, 0, size - sizeof(*this)); ox_memset(this + 1, 0, size - sizeof(*this));
oxTracef("ox::NodeBuffer::constructor", "{}", m_header.firstItem.get()); oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get());
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept { NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept {
oxTracef("ox::ptrarith::NodeBuffer::copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get()); oxTracef("ox.ptrarith.NodeBuffer.copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get());
ox_memset(this + 1, 0, size - sizeof(*this)); ox_memset(this + 1, 0, size - sizeof(*this));
ox_memcpy(this, &other, size); ox_memcpy(this, &other, size);
} }
@@ -191,7 +191,7 @@ const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iter
template<typename size_t, typename Item> template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() noexcept { typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() noexcept {
oxTracef("ox::ptrarith::NodeBuffer::iterator::size", "{}", m_header.size.get()); oxTracef("ox.ptrarith.NodeBuffer.iterator.size", "{}", m_header.size.get());
return Iterator(this, firstItem()); return Iterator(this, firstItem());
} }
@@ -267,7 +267,7 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t
template<typename size_t, typename Item> template<typename size_t, typename Item>
Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::malloc(std::size_t size) noexcept { Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::malloc(std::size_t size) noexcept {
const auto sz = static_cast<std::size_t>(size); const auto sz = static_cast<std::size_t>(size);
oxTracef("ox::ptrarith::NodeBuffer::malloc", "Size: {}", sz); oxTracef("ox.ptrarith.NodeBuffer.malloc", "Size: {}", sz);
size_t fullSize = static_cast<size_t>(sz + sizeof(Item)); size_t fullSize = static_cast<size_t>(sz + sizeof(Item));
if (m_header.size - m_header.bytesUsed >= fullSize) { if (m_header.size - m_header.bytesUsed >= fullSize) {
auto last = lastItem(); auto last = lastItem();
@@ -277,18 +277,18 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
} else { } else {
// there is no first item, so this must be the first item // there is no first item, so this must be the first item
if (!m_header.firstItem) { if (!m_header.firstItem) {
oxTrace("ox::ptrarith::NodeBuffer::malloc", "No first item, initializing."); oxTrace("ox.ptrarith.NodeBuffer.malloc", "No first item, initializing.");
m_header.firstItem = static_cast<size_t>(sizeof(m_header)); m_header.firstItem = static_cast<size_t>(sizeof(m_header));
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 OxError(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 OxError(1, "NodeBuffer::malloc: unknown failure");
} }
ox_memset(out, 0, fullSize); ox_memset(out, 0, fullSize);
@@ -301,7 +301,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
if (first.valid()) { if (first.valid()) {
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 OxError(1, "NodeBuffer malloc failed due to invalid first element pointer.");
} }
@@ -311,22 +311,22 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
} else { // check to see if this is the first allocation } else { // check to see if this is the first allocation
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 OxError(1, "NodeBuffer malloc failed due to invalid last element pointer.");
} }
out->prev = out.offset(); out->prev = out.offset();
} }
m_header.bytesUsed += out.size(); m_header.bytesUsed += out.size();
oxTracef("ox::ptrarith::NodeBuffer::malloc", "Offset: {}", out.offset()); oxTracef("ox.ptrarith.NodeBuffer.malloc", "Offset: {}", out.offset());
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 OxError(1);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept { Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
oxTracef("ox::ptrarith::NodeBuffer::free", "offset: {}", item.offset()); oxTracef("ox.ptrarith.NodeBuffer.free", "offset: {}", item.offset());
auto prev = this->prev(item); auto prev = this->prev(item);
auto next = this->next(item); auto next = this->next(item);
if (prev.valid() && next.valid()) { if (prev.valid() && next.valid()) {
@@ -338,16 +338,16 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} }
} else { } else {
// only one item, null out first // only one item, null out first
oxTrace("ox::ptrarith::NodeBuffer::free", "Nulling out firstItem."); oxTrace("ox.ptrarith.NodeBuffer.free", "Nulling out firstItem.");
m_header.firstItem = 0; m_header.firstItem = 0;
} }
} 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 OxError(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 OxError(1);
} }
} }
@@ -357,10 +357,10 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
template<typename size_t, typename Item> template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept { Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
oxTracef("ox::ptrarith::NodeBuffer::setSize", "{} to {}", m_header.size.get(), size); oxTracef("ox.ptrarith.NodeBuffer.setSize", "{} to {}", m_header.size.get(), size);
auto last = lastItem(); auto last = lastItem();
auto end = last.valid() ? last.end() : sizeof(m_header); auto end = last.valid() ? last.end() : sizeof(m_header);
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 OxError(1);

View File

@@ -224,7 +224,7 @@ constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(s
template<typename T, typename size_t, size_t minOffset> template<typename T, typename size_t, size_t minOffset>
template<typename SubT> template<typename SubT>
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept { constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
oxTracef("ox::fs::Ptr::subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset)); oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
return subPtr<SubT>(offset, m_itemSize - offset); return subPtr<SubT>(offset, m_itemSize - offset);
} }
@@ -237,7 +237,7 @@ constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t
template<typename T, typename size_t, size_t minOffset> template<typename T, typename size_t, size_t minOffset>
template<typename SubT> template<typename SubT>
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept { constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
oxTracef("ox::fs::Ptr::subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset)); oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
return subPtr<SubT>(offset, m_itemSize - offset); return subPtr<SubT>(offset, m_itemSize - offset);
} }

View File

@@ -6,7 +6,6 @@ add_executable(
target_link_libraries( target_link_libraries(
FSTests FSTests
OxFS OxFS
OxStd
OxMetalClaw OxMetalClaw
) )

View File

@@ -26,11 +26,11 @@ struct OX_PACKED NodeType: public ox::ptrarith::Item<T> {
} }
}; };
const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tests = { const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = {
{ {
{ {
"PtrArith::setSize", "PtrArith::setSize",
[](std::string_view) { [](ox::StringView) {
using BuffPtr_t = uint32_t; using BuffPtr_t = uint32_t;
ox::Vector<char> buff(5 * ox::units::MB); ox::Vector<char> buff(5 * ox::units::MB);
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size()); auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
@@ -57,8 +57,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::next1", "PathIterator::next1",
[](std::string_view) { [](ox::StringView) {
ox::String path = "/usr/share/charset.gbag"; auto const path = ox::String("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
@@ -69,8 +69,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::next2", "PathIterator::next2",
[](std::string_view) { [](ox::StringView) {
ox::String path = "/usr/share/"; auto const path = ox::String("/usr/share/");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
@@ -80,8 +80,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::next3", "PathIterator::next3",
[](std::string_view) { [](ox::StringView) {
ox::String path = "/"; auto const path = ox::String("/");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "\0") == 0, "PathIterator shows wrong next"); oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
@@ -90,8 +90,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::next4", "PathIterator::next4",
[](std::string_view) { [](ox::StringView) {
ox::String path = "usr/share/charset.gbag"; auto const path = ox::String("usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
@@ -102,8 +102,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::next5", "PathIterator::next5",
[](std::string_view) { [](ox::StringView) {
ox::String path = "usr/share/"; auto const path = ox::String("usr/share/");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
@@ -113,8 +113,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::dirPath", "PathIterator::dirPath",
[] (std::string_view) { [] (ox::StringView) {
ox::String path = "/usr/share/charset.gbag"; auto const path = ox::String("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.dirPath(buff, path.len()) == 0 && ox_strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); oxAssert(it.dirPath(buff, path.len()) == 0 && ox_strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
@@ -123,8 +123,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::fileName", "PathIterator::fileName",
[](std::string_view) { [](ox::StringView) {
ox::String path = "/usr/share/charset.gbag"; auto const path = ox::String("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.fileName(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name"); oxAssert(it.fileName(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
@@ -133,7 +133,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"PathIterator::hasNext", "PathIterator::hasNext",
[](std::string_view) { [](ox::StringView) {
const auto path = "/file1"; const auto path = "/file1";
ox::PathIterator it(path, ox_strlen(path)); ox::PathIterator it(path, ox_strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
@@ -143,7 +143,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"Ptr::subPtr", "Ptr::subPtr",
[](std::string_view) { [](ox::StringView) {
constexpr auto buffLen = 5000; constexpr auto buffLen = 5000;
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500); ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid."); oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
@@ -155,7 +155,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"NodeBuffer::insert", "NodeBuffer::insert",
[](std::string_view) { [](ox::StringView) {
constexpr auto buffLen = 5000; constexpr auto buffLen = 5000;
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(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed"); oxAssert(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed");
@@ -168,7 +168,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"FileStore::readWrite", "FileStore::readWrite",
[](std::string_view) { [](ox::StringView) {
constexpr auto buffLen = 5000; constexpr auto buffLen = 5000;
constexpr auto str1 = "Hello, World!"; constexpr auto str1 = "Hello, World!";
constexpr auto str1Len = ox_strlen(str1) + 1; constexpr auto str1Len = ox_strlen(str1) + 1;
@@ -189,26 +189,26 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"Directory", "Directory",
[](std::string_view) { [](ox::StringView) {
ox::Vector<uint8_t> fsBuff(5000); ox::Vector<uint8_t> fsBuff(5000);
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed"); oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size()); ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
ox::Directory32 dir(fileStore, 105); ox::Directory32 dir(fileStore, 105);
oxTrace("ox::fs::test::Directory") << "Init"; oxTrace("ox.fs.test.Directory") << "Init";
oxAssert(dir.init(), "Init failed"); oxAssert(dir.init(), "Init failed");
oxTrace("ox::fs::test::Directory") << "write 1"; oxTrace("ox.fs.test.Directory") << "write 1";
oxAssert(dir.write("/file1", 1), "Directory write of file1 failed"); oxAssert(dir.write("/file1", 1), "Directory write of file1 failed");
oxTrace("ox::fs::test::Directory") << "find"; oxTrace("ox.fs.test.Directory") << "find";
oxAssert(dir.find("file1").error, "Could not find file1"); oxAssert(dir.find("file1").error, "Could not find file1");
oxAssert(dir.find("file1").value == 1, "Could not find file1"); oxAssert(dir.find("file1").value == 1, "Could not find file1");
oxTrace("ox::fs::test::Directory") << "write 2"; oxTrace("ox.fs.test.Directory") << "write 2";
oxAssert(dir.write("/file3", 3), "Directory write of file3 failed"); oxAssert(dir.write("/file3", 3), "Directory write of file3 failed");
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 OxError(0);
@@ -216,13 +216,13 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}, },
{ {
"FileSystem", "FileSystem",
[](std::string_view) { [](ox::StringView) {
ox::Vector<uint8_t> fsBuff(5000); ox::Vector<uint8_t> fsBuff(5000);
oxTrace("ox::fs::test::FileSystem") << "format"; oxTrace("ox.fs.test.FileSystem") << "format";
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed"); oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size())); ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
oxTrace("ox::fs::test::FileSystem") << "mkdir"; oxTrace("ox.fs.test.FileSystem") << "mkdir";
oxAssert(fs.mkdir("/dir", true), "mkdir failed"); oxAssert(fs.mkdir("/dir", true), "mkdir failed");
oxAssert(fs.stat("/dir").error, "mkdir failed"); oxAssert(fs.stat("/dir").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d1/l3d1", true), "mkdir failed"); oxAssert(fs.mkdir("/l1d1/l2d1/l3d1", true), "mkdir failed");
@@ -237,16 +237,15 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
int retval = -1; if (argc < 3) {
if (argc > 1) { oxError("Must specify test to run and test argument");
std::string_view testName = args[1];
std::string_view testArg;
if (args[2]) {
testArg = args[2];
}
if (tests.find(testName) != tests.end()) {
retval = static_cast<int>(tests.at(testName)(testArg));
}
} }
return retval; ox::StringView const testName = args[1];
ox::StringView const testArg = args[2] ? args[2] : nullptr;
auto const func = tests.find(testName);
if (func != tests.end()) {
oxAssert(func->second(testArg), "Test returned Error");
return 0;
}
return -1;
} }

View File

@@ -67,7 +67,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
return OxError(1); return OxError(1);
} }
const auto fsPath = argv[1]; const auto fsPath = argv[1];
ox::String subCmd = argv[2]; ox::String subCmd(argv[2]);
oxRequire(fs, loadFs(fsPath)); oxRequire(fs, loadFs(fsPath));
if (subCmd == "ls") { if (subCmd == "ls") {
return runLs(fs.get(), argc - 2, argv + 2); return runLs(fs.get(), argc - 2, argv + 2);

View File

@@ -21,6 +21,7 @@ target_link_libraries(
OxStd OxStd
OxMetalClaw OxMetalClaw
$<$<BOOL:${OX_OS_FREEBSD}>:pthread> $<$<BOOL:${OX_OS_FREEBSD}>:pthread>
$<$<BOOL:${OX_OS_WINDOWS}>:ws2_32>
) )
install( install(

View File

@@ -7,21 +7,38 @@
*/ */
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstdio> #include <cstdio>
#include <ox/std/bit.hpp> #include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#else
#include <winsock.h>
#undef interface
#undef min
#undef max
#endif
#include "logconn.hpp" #include "logconn.hpp"
#include <ox/std/bit.hpp>
namespace ox { namespace ox {
using namespace trace; using namespace trace;
void closeSock(auto s) noexcept {
#ifdef _WIN32
closesocket(s);
#else
close(s);
#endif
}
LoggerConn::LoggerConn() noexcept: m_netThread([this]{this->msgSend();}) { LoggerConn::LoggerConn() noexcept: m_netThread([this]{this->msgSend();}) {
} }
@@ -30,7 +47,7 @@ LoggerConn::~LoggerConn() noexcept {
m_waitCond.notify_one(); m_waitCond.notify_one();
m_netThread.join(); m_netThread.join();
if (m_socket) { if (m_socket) {
close(m_socket); closeSock(m_socket);
} }
} }
@@ -41,7 +58,7 @@ ox::Error LoggerConn::initConn(ox::CRStringView appName) noexcept {
addr.sin_port = htons(5590); addr.sin_port = htons(5590);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
return sendInit({.appName = appName}); return sendInit({.appName = ox::BasicString<128>(appName)});
} }
ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept { ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {

View File

@@ -17,7 +17,7 @@
#include <ox/mc/write.hpp> #include <ox/mc/write.hpp>
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include "circularbuff.hpp" #include "circularbuff.hpp"
namespace ox { namespace ox {

View File

@@ -35,7 +35,7 @@ constexpr std::size_t highestBit(I val) noexcept {
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
--shiftStart; --shiftStart;
} }
for (auto i = shiftStart; i < MaxValue<decltype(i)>; --i) { for (auto i = shiftStart; i > 0; --i) {
const auto bitValue = (val >> i) & 1; const auto bitValue = (val >> i) & 1;
if (bitValue) { if (bitValue) {
highestBit = i; highestBit = i;
@@ -64,13 +64,14 @@ struct McInt {
template<typename I> template<typename I>
[[nodiscard]] [[nodiscard]]
constexpr McInt encodeInteger(I input) noexcept { constexpr McInt encodeInteger(I pInput) noexcept {
auto const input = ox::ResizedInt_t<I, 64>{pInput};
McInt out; McInt out;
const auto inputNegative = is_signed_v<I> && input < 0; const auto inputNegative = is_signed_v<I> && input < 0;
// move input to uint64_t to allow consistent bit manipulation, and to avoid // move input to uint64_t to allow consistent bit manipulation, and to avoid
// overflow concerns // overflow concerns
uint64_t val = 0; uint64_t val = 0;
ox_memcpy(&val, &input, sizeof(I)); ox_memcpy(&val, &input, sizeof(input));
if (val) { if (val) {
// bits needed to represent number factoring in space possibly // bits needed to represent number factoring in space possibly
// needed for signed bit // needed for signed bit
@@ -93,7 +94,7 @@ constexpr McInt encodeInteger(I input) noexcept {
} }
if (bytes == 9) { if (bytes == 9) {
out.data[0] = bytesIndicator; out.data[0] = bytesIndicator;
ox_memcpy(&out.data[1], &leVal, sizeof(I)); ox_memcpy(&out.data[1], &leVal, 8);
if (inputNegative) { if (inputNegative) {
out.data[1] |= 0b1000'0000; out.data[1] |= 0b1000'0000;
} }

View File

@@ -6,6 +6,14 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include <ox/model/modelhandleradaptor.hpp>
#include <ox/std/buffer.hpp>
#include <ox/std/reader.hpp>
#include "read.hpp"
namespace ox { namespace ox {
template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
} }

View File

@@ -15,6 +15,7 @@
#include <ox/model/types.hpp> #include <ox/model/types.hpp>
#include <ox/std/buffer.hpp> #include <ox/std/buffer.hpp>
#include <ox/std/byteswap.hpp> #include <ox/std/byteswap.hpp>
#include <ox/std/optional.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include <ox/std/vector.hpp> #include <ox/std/vector.hpp>
@@ -27,21 +28,19 @@
namespace ox { namespace ox {
template<Reader_c Reader> template<Reader_c Reader>
class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<Reader>> { class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<Reader>, ox::OpType::Read> {
private: private:
FieldBitmapReader<Reader> m_fieldPresence; FieldBitmapReader<Reader> m_fieldPresence;
std::size_t m_fields = 0; std::size_t m_fields = 0;
std::size_t m_field = 0; std::size_t m_field = 0;
int m_unionIdx = -1; ox::Optional<int> m_unionIdx;
Reader &m_reader; Reader &m_reader;
MetalClawReaderTemplate<Reader> *m_parent = nullptr;
public: public:
explicit constexpr MetalClawReaderTemplate( explicit constexpr MetalClawReaderTemplate(
Reader &reader, Reader &reader,
int unionIdx = -1, ox::Optional<int> const&unionIdx = {}) noexcept;
MetalClawReaderTemplate<Reader> *parent = nullptr) noexcept;
constexpr ~MetalClawReaderTemplate() noexcept; constexpr ~MetalClawReaderTemplate() noexcept;
@@ -108,7 +107,7 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
* Returns a MetalClawReader to parse a child object. * Returns a MetalClawReader to parse a child object.
*/ */
[[nodiscard]] [[nodiscard]]
constexpr MetalClawReaderTemplate<Reader> child(const char *name, int unionIdx = -1) noexcept; constexpr MetalClawReaderTemplate<Reader> child(const char *name, ox::Optional<int> unionIdx = {}) noexcept;
/** /**
* Indicates whether or not the next field to be read is present. * Indicates whether or not the next field to be read is present.
@@ -127,11 +126,6 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
constexpr void nextField() noexcept; constexpr void nextField() noexcept;
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Read;
}
private: private:
template<typename I> template<typename I>
constexpr Error readInteger(I *val) noexcept; constexpr Error readInteger(I *val) noexcept;
@@ -141,18 +135,16 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
template<Reader_c Reader> template<Reader_c Reader>
constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate( constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate(
Reader &reader, Reader &reader,
int unionIdx, ox::Optional<int> const&unionIdx) noexcept:
MetalClawReaderTemplate *parent) noexcept:
m_fieldPresence(reader), m_fieldPresence(reader),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_reader(reader), m_reader(reader) {
m_parent(parent) {
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept { constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept {
if (m_field != m_fields) { if (m_field != m_fields) {
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given"; oxTrace("ox.mc.MetalClawReader.error") << "MetalClawReader: incorrect fields number given";
} }
} }
@@ -199,7 +191,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint64_t *va
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept {
if (m_unionIdx == -1 || 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); oxReturnError(result);
@@ -211,7 +203,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n
// array handler // array handler
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -225,7 +217,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *v
oxReturnError(handler.field({}, &val[i])); oxReturnError(handler.field({}, &val[i]));
} }
} else { } else {
oxTracef("ox::mc::read::field(T)", "{}, length: {}", name, valLen); oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen);
return OxError(McOutputBuffEnded); return OxError(McOutputBuffEnded);
} }
} }
@@ -237,7 +229,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *v
template<Reader_c Reader> template<Reader_c Reader>
template<typename T> template<typename T>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept {
if (m_unionIdx == -1 || 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()); oxRequire(g, m_reader.tellg());
@@ -248,12 +240,16 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
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))); oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto &val) {
oxRequire(keyLen, handler.stringLength(nullptr)); oxRequire(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)); oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
oxReturnError(handler.field("", &val->operator[](wkey.get()))); return handler.field("", &val[wkeyPtr]);
};
for (std::size_t i = 0; i < len; ++i) {
oxReturnError(loopBody(handler, *val));
} }
} }
} }
@@ -265,19 +261,19 @@ template<Reader_c Reader>
template<typename T> template<typename T>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept {
if constexpr(isVector_v<T>) { if constexpr(isVector_v<T>) {
if (m_unionIdx == -1 || 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)); oxRequire(len, arrayLength(name, false));
val->resize(len); oxReturnError(ox::resizeVector(*val, len));
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
} }
oxReturnError(ox::resizeVector(*val, 0));
} }
val->resize(0);
++m_field; ++m_field;
return {}; return {};
} else if constexpr(isArray_v<T>) { } else if constexpr(isArray_v<T>) {
if (m_unionIdx == -1 || 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)); oxRequire(len, arrayLength(name, false));
@@ -290,7 +286,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
++m_field; ++m_field;
return {}; return {};
} else { } else {
if ((m_unionIdx == -1 || 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)); oxReturnError(model(reader.interface(), val));
@@ -304,20 +300,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
template<Reader_c Reader> template<Reader_c Reader>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept {
if ((m_unionIdx == -1 || 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("", val.idx()); auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
oxReturnError(model(reader.interface(), val.get())); oxReturnError(model(reader.interface(), val.get()));
} }
} }
++m_field; ++m_field;
return OxError(0); return {};
} }
template<Reader_c Reader> template<Reader_c Reader>
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -383,7 +379,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
template<Reader_c Reader> template<Reader_c Reader>
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -411,7 +407,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
template<Reader_c Reader> template<Reader_c Reader>
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept { constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -428,7 +424,7 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const
template<Reader_c Reader> template<Reader_c Reader>
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept { constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -443,7 +439,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
template<Reader_c Reader> template<Reader_c Reader>
template<typename I> template<typename I>
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
if (m_unionIdx == -1 || 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))) {
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);
@@ -460,7 +456,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
template<Reader_c Reader> template<Reader_c Reader>
template<typename T, typename CB> template<typename T, typename CB>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept { constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept {
if (m_unionIdx == -1 || 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
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
@@ -492,8 +488,10 @@ constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(const char*, int unionIdx) noexcept { constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx, this); const char*,
ox::Optional<int> unionIdx) noexcept {
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx);
} }
template<Reader_c Reader> template<Reader_c Reader>
@@ -529,7 +527,7 @@ template<typename T>
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept { Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
BufferReader br(buff, buffLen); BufferReader br(buff, buffLen);
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader);
return model(&handler, val); return model(&handler, val);
} }
@@ -545,4 +543,6 @@ Result<T> readMC(const Buffer &buff) noexcept {
return readMC<T>(buff.data(), buff.size()); return readMC<T>(buff.data(), buff.size());
} }
extern template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
} }

View File

@@ -45,7 +45,7 @@ struct TestStruct {
int32_t Int8 = 0; int32_t Int8 = 0;
int unionIdx = 1; int unionIdx = 1;
TestUnion Union; TestUnion Union;
ox::String String = ""; ox::String String;
ox::BString<32> BString = ""; ox::BString<32> BString = "";
uint32_t List[4] = {0, 0, 0, 0}; uint32_t List[4] = {0, 0, 0, 0};
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5}; ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
@@ -98,13 +98,14 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
oxReturnError(io->field("BString", &obj->BString)); oxReturnError(io->field("BString", &obj->BString));
oxReturnError(io->field("List", obj->List, 4)); oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Vector", &obj->Vector)); oxReturnError(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Vector2", &obj->Vector2));
oxReturnError(io->field("Map", &obj->Map)); oxReturnError(io->field("Map", &obj->Map));
oxReturnError(io->field("Struct", &obj->Struct)); oxReturnError(io->field("Struct", &obj->Struct));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
return OxError(0); return OxError(0);
} }
std::map<ox::String, ox::Error(*)()> tests = { std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
{ {
"MetalClawWriter", "MetalClawWriter",
@@ -266,6 +267,9 @@ std::map<ox::String, ox::Error(*)()> tests = {
return OxError(0); return OxError(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(int16_t(-1)), "Decode of -1 failed.");
oxAssert(check(int32_t(-1)), "Decode of -1 failed.");
oxAssert(check(int64_t(-1)), "Decode of -1 failed."); oxAssert(check(int64_t(-1)), "Decode of -1 failed.");
oxAssert(check(int64_t(-2)), "Decode of -2 failed."); oxAssert(check(int64_t(-2)), "Decode of -2 failed.");
oxAssert(check(int64_t(-127)), "Decode of -127 failed."); oxAssert(check(int64_t(-127)), "Decode of -127 failed.");
@@ -459,11 +463,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
if (argc > 0) { if (argc < 2) {
auto testName = args[1]; oxError("Must specify test to run");
if (tests.find(testName) != tests.end()) {
oxAssert(tests[testName](), "Test failed...");
}
} }
return 0; auto const testName = args[1];
auto const func = tests.find(testName);
if (func != tests.end()) {
oxAssert(func->second(), "Test returned Error");
return 0;
}
return -1;
} }

View File

@@ -16,6 +16,7 @@
#include <ox/std/buffer.hpp> #include <ox/std/buffer.hpp>
#include <ox/std/byteswap.hpp> #include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp> #include <ox/std/hashmap.hpp>
#include <ox/std/optional.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include <ox/std/units.hpp> #include <ox/std/units.hpp>
@@ -34,48 +35,39 @@ class MetalClawWriter {
ox::Vector<uint8_t, 16> m_presenceMapBuff{}; ox::Vector<uint8_t, 16> m_presenceMapBuff{};
FieldBitmap m_fieldPresence; FieldBitmap m_fieldPresence;
int m_field = 0; int m_field = 0;
int m_unionIdx = -1; ox::Optional<int> m_unionIdx;
std::size_t m_writerBeginP{}; std::size_t m_writerBeginP{};
Writer &m_writer; Writer &m_writer;
public: public:
constexpr explicit MetalClawWriter(Writer &writer, int unionIdx = -1) noexcept; constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept;
constexpr ~MetalClawWriter() noexcept = default; constexpr ~MetalClawWriter() noexcept = default;
constexpr Error field(const char*, CommonPtrWith<int8_t> auto *val) noexcept; constexpr Error field(const char*, const int8_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<int16_t> auto *val) noexcept; constexpr Error field(const char*, const int16_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<int32_t> auto *val) noexcept; constexpr Error field(const char*, const int32_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<int64_t> auto *val) noexcept; constexpr Error field(const char*, const int64_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept; constexpr Error field(const char*, const uint8_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept; constexpr Error field(const char*, const uint16_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept; constexpr Error field(const char*, const uint32_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept; constexpr Error field(const char*, const uint64_t *val) noexcept;
constexpr Error field(const char*, CommonPtrWith<bool> auto *val) noexcept; constexpr Error field(const char*, const bool *val) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, T *val, std::size_t len) noexcept; constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept; constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
template<typename T>
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept; constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
template<std::size_t L> template<std::size_t L>
constexpr Error field(const char*, const BString<L> *val) noexcept; constexpr Error field(const char*, const BString<L> *val) noexcept;
template<std::size_t SmallStringSize>
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
template<std::size_t L>
constexpr Error field(const char*, BString<L> *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept; constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
constexpr Error fieldCString(const char *name, const char **val) noexcept; constexpr Error fieldCString(const char *name, const char **val) noexcept;
@@ -84,20 +76,8 @@ class MetalClawWriter {
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept; constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
return fieldCString(name, const_cast<const char**>(val), buffLen);
}
constexpr Error fieldCString(const char *name, char **val) noexcept {
return fieldCString(name, const_cast<const char**>(val));
}
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
return fieldCString(name, const_cast<const char*>(val), buffLen);
}
template<typename T> template<typename T>
constexpr Error field(const char*, T *val) noexcept; constexpr Error field(const char*, const T *val) noexcept;
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> val) noexcept; constexpr Error field(const char*, UnionView<U, force> val) noexcept;
@@ -135,7 +115,7 @@ class MetalClawWriter {
private: private:
constexpr Error appendInteger(Integer_c auto val) noexcept { constexpr Error appendInteger(Integer_c auto val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length)); oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
fieldSet = true; fieldSet = true;
@@ -151,7 +131,7 @@ extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>; extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
template<Writer_c Writer> template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx) noexcept: constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()), m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_writerBeginP(writer.tellp()), m_writerBeginP(writer.tellp()),
@@ -159,48 +139,48 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx)
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<bool> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
if (m_unionIdx == -1 || 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)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
} }
++m_field; ++m_field;
@@ -211,7 +191,7 @@ 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 == -1 || m_unionIdx == m_field)) { if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->len()); const auto strLen = mc::encodeInteger(val->len());
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length)); oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length));
@@ -230,22 +210,10 @@ constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L
return fieldCString(name, val->data(), val->cap()); return fieldCString(name, val->data(), val->cap());
} }
template<Writer_c Writer>
template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
}
template<Writer_c Writer>
template<std::size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, BString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap());
}
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 == -1 || m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
const auto strLen = *val ? ox_strlen(*val) : 0; const auto strLen = *val ? ox_strlen(*val) : 0;
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
@@ -272,7 +240,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const ch
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
@@ -287,21 +255,22 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
return field(nullptr, val->data(), val->size()); return field(nullptr, val->data(), val->size());
} else { } else {
bool fieldSet = false; bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
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)); oxReturnError(model(&handler, val));
oxReturnError(writer.finalize()); oxReturnError(writer.finalize());
fieldSet = true; fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return {};
} }
} }
@@ -309,35 +278,37 @@ template<Writer_c Writer>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
MetalClawWriter<Writer> writer(m_writer, val.idx()); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get())); oxReturnError(model(&handler, val.get()));
oxReturnError(writer.finalize()); oxReturnError(writer.finalize());
fieldSet = true; fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(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<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val, std::size_t len) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
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))); oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; i++) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field("", &val[i])); oxReturnError(handler.field("", &val[i]));
} }
oxReturnError(writer.finalize()); oxReturnError(writer.finalize());
fieldSet = true; fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
@@ -350,7 +321,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
const auto &keys = val->keys(); const auto &keys = val->keys();
const auto len = keys.size(); const auto len = keys.size();
bool fieldSet = false; bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
@@ -359,15 +330,19 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
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)); oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2));
// write the array // this loop body needs to be in a lambda because of the potential alloca call
for (std::size_t i = 0; i < len; i++) { constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto &key = keys[i]; const auto keyLen = key.len();
const auto keyLen = ox_strlen(key);
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey, key.c_str(), keyLen + 1); memcpy(wkey.get(), key.c_str(), keyLen + 1);
oxReturnError(handler.fieldCString("", wkey.get(), keyLen)); oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
oxRequireM(value, val->at(key)); oxRequireM(value, val.at(key));
oxReturnError(handler.field("", value)); return handler.field("", value);
};
// write the array
for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val));
} }
oxReturnError(writer.finalize()); oxReturnError(writer.finalize());
fieldSet = true; fieldSet = true;
@@ -377,12 +352,6 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char *name, HashMap<String, T> *val) noexcept {
return field(name, const_cast<const HashMap<String, T>*>(val));
}
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo( constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
@@ -417,7 +386,7 @@ Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
return {}; return {};
} }
Result<Buffer> writeMC(const auto &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)); oxReturnError(writeMC(bw, val));
@@ -425,7 +394,7 @@ Result<Buffer> writeMC(const auto &val, std::size_t buffReserveSz = 2 * units::K
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, const auto &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)); oxReturnError(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {

View File

@@ -175,8 +175,9 @@ class TypeDescWriter {
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {} constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {}
template<typename T> template<typename T>
constexpr ox::Error TypeDescWriter::setTypeInfo(CRStringView typeName, int typeVersion, constexpr ox::Error TypeDescWriter::setTypeInfo(
const TypeParamPack &typeParams, std::size_t) noexcept { CRStringView typeName, int typeVersion,
const TypeParamPack &typeParams, std::size_t) noexcept {
PrimitiveType pt; PrimitiveType pt;
if constexpr(is_union_v<T>) { if constexpr(is_union_v<T>) {
pt = PrimitiveType::Union; pt = PrimitiveType::Union;
@@ -197,7 +198,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, const T*, std::size_t,
constexpr typename remove_pointer<T>::type *p = nullptr; constexpr typename remove_pointer<T>::type *p = nullptr;
const auto t = type(p); const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, 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 OxError(0);
} }
return OxError(1); return OxError(1);
@@ -208,7 +209,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val
if (m_type) { if (m_type) {
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return OxError(0); return OxError(0);
} }
return OxError(1); return OxError(1);
@@ -218,15 +219,17 @@ template<typename T>
constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept { constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept {
if (m_type) { if (m_type) {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
return field(name, val->data(), 0, detail::buildSubscriptStack(val)); typename T::value_type *data = nullptr;
return field(name, data, 0, detail::buildSubscriptStack(val));
} else if constexpr(isSmartPtr_v<T>) { } else if constexpr(isSmartPtr_v<T>) {
return field(name, val->get(), 0, detail::buildSubscriptStack(val)); typename T::value_type *data = nullptr;
return field(name, data, 0, detail::buildSubscriptStack(val));
} else if constexpr(is_pointer_v<T>) { } else if constexpr(is_pointer_v<T>) {
return field(name, val, 0, detail::buildSubscriptStack(val)); return field(name, val, 0, detail::buildSubscriptStack(val));
} else { } else {
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, name, 0, SubscriptStack{}, buildTypeId(*t)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, buildTypeId(*t));
return {}; return {};
} }
} }
@@ -237,7 +240,7 @@ template<typename ...Args>
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept { constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
constexpr auto s = ""; constexpr auto s = "";
const auto t = type(s); const auto t = type(s);
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return {}; return {};
} }
@@ -344,7 +347,7 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType"); oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
return type; return type;
} else { } else {
auto dt = ox::make_unique<DescriptorType>(tn, typeVersion, pt, typeParams); auto dt = ox::make_unique<DescriptorType>(String(tn), typeVersion, pt, typeParams);
dt->length = b; dt->length = b;
const auto out = dt.get(); const auto out = dt.get();
const auto typeId = buildTypeId(tn, typeVersion, typeParams); const auto typeId = buildTypeId(tn, typeVersion, typeParams);
@@ -356,15 +359,15 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
template<typename T> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
TypeDescWriter writer(typeStore); TypeDescWriter writer(typeStore);
ModelHandlerInterface handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
std::allocator<T> a; std::allocator<T> a;
T *t = a.allocate(1); T *t = a.allocate(1);
oxReturnError(model(&handler, t)); oxReturnError(model(&handler, t));
a.deallocate(t, 1); a.deallocate(t, 1);
} else { } else {
T *t = reinterpret_cast<T*>(ox_alloca(sizeof(T))); auto t = ox_malloca(sizeof(T), T);
oxReturnError(model(&handler, t)); oxReturnError(model(&handler, t.get()));
} }
return writer.definition(); return writer.definition();
} }
@@ -372,7 +375,7 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
template<typename T> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
TypeDescWriter writer(typeStore); TypeDescWriter writer(typeStore);
ModelHandlerInterface handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
oxReturnError(model(&handler, val)); oxReturnError(model(&handler, val));
return writer.definition(); return writer.definition();
} }

View File

@@ -14,7 +14,7 @@
namespace ox { namespace ox {
template<typename Handler> template<typename Handler, OpType opType_v = Handler::opType()>
class ModelHandlerInterface { class ModelHandlerInterface {
private: private:
Handler *m_handler = nullptr; Handler *m_handler = nullptr;
@@ -25,10 +25,18 @@ class ModelHandlerInterface {
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char *name = T::TypeName, const char* name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const Vector<String> &typeParams = {}, const Vector<String>& typeParams = {}) noexcept {
std::size_t fields = ModelFieldCount_v<T>) noexcept { return m_handler->template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>);
}
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(
const char *name,
int version,
const Vector<String>& typeParams,
std::size_t fields) noexcept {
return m_handler->template setTypeInfo<T>(name, version, typeParams, fields); return m_handler->template setTypeInfo<T>(name, version, typeParams, fields);
} }
@@ -38,28 +46,47 @@ class ModelHandlerInterface {
} }
template<std::size_t len> template<std::size_t len>
constexpr Error fieldCString(const char *name, const char val[len]) noexcept { constexpr Error fieldCString(const char *name, const char val[len]) noexcept requires(opType_v != OpType::Read) {
return m_handler->fieldCString(name, &val[0], len); if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, &val[0], len);
} else {
return {};
}
} }
constexpr Error fieldCString(const char *name, char **val) noexcept { constexpr Error fieldCString(const char *name, char **val) noexcept {
return m_handler->fieldCString(name, val); return m_handler->fieldCString(name, val);
} }
constexpr Error fieldCString(const char *name, const char *const*val) noexcept { constexpr Error fieldCString(const char *name, const char *const*val) noexcept requires(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val); // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val);
} else {
return {};
}
} }
constexpr Error fieldCString(const char *name, const char **val) noexcept { constexpr Error fieldCString(const char *name, const char **val) noexcept requires(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val); // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val);
} else {
return {};
}
} }
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept { constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
return m_handler->fieldCString(name, val, buffLen); return m_handler->fieldCString(name, val, buffLen);
} }
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept { constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept requires(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val, buffLen); // this check looks pointless, but it's to address a Clang bug
if constexpr(opType_v != OpType::Read) {
return m_handler->fieldCString(name, val, buffLen);
} else {
return {};
}
} }
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept { constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
@@ -95,7 +122,7 @@ class ModelHandlerInterface {
case ModelValue::Type::Union: case ModelValue::Type::Union:
{ {
auto &u = v->template get<ModelUnion>(); auto &u = v->template get<ModelUnion>();
if constexpr(Handler::opType() == OpType::Read) { if constexpr(opType_v == OpType::Read) {
u.setActiveField(m_handler->whichFieldPresent(name, u)); u.setActiveField(m_handler->whichFieldPresent(name, u));
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx())); return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
} else { } else {
@@ -169,13 +196,12 @@ class ModelHandlerInterface {
constexpr auto handler() noexcept { constexpr auto handler() noexcept {
return m_handler; return m_handler;
} }
}; };
template<typename Handler> template<typename Handler, ox::OpType opType_v = Handler::opType()>
class ModelHandlerBase { class ModelHandlerBase {
private: private:
ModelHandlerInterface<Handler> m_interface; ModelHandlerInterface<Handler, opType_v> m_interface;
public: public:
constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {} constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {}
constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {} constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {}
@@ -184,6 +210,20 @@ class ModelHandlerBase {
constexpr auto interface() noexcept { constexpr auto interface() noexcept {
return &m_interface; return &m_interface;
} }
[[nodiscard]]
static constexpr ox::OpType opType() noexcept {
return opType_v;
}
}; };
constexpr ox::Error resizeVector(auto &vec, size_t sz) {
if constexpr(ox::is_same_v<decltype(vec.resize(0)), ox::Error>) {
return vec.resize(sz);
} else {
vec.resize(sz);
return {};
}
}
} }

View File

@@ -144,8 +144,6 @@ class ModelValue {
constexpr ModelValue(const ModelValue &other) noexcept; constexpr ModelValue(const ModelValue &other) noexcept;
constexpr ModelValue(ModelValue &other) noexcept;
constexpr ModelValue(ModelValue &&other) noexcept; constexpr ModelValue(ModelValue &&other) noexcept;
template<typename T> template<typename T>
@@ -204,7 +202,8 @@ class ModelValue {
class ModelValueVector { class ModelValueVector {
private: private:
Vector<ModelValue> m_vec; Vector<ModelValue> m_vec;
ModelValue m_templateValue; const DescriptorType *m_type = nullptr;
int m_typeSubscriptLevels = 0;
String m_typeName; String m_typeName;
int m_typeVersion = 0; int m_typeVersion = 0;
@@ -229,14 +228,15 @@ class ModelValueVector {
return m_vec.data(); return m_vec.data();
} }
constexpr void resize(std::size_t sz) noexcept { constexpr ox::Error resize(std::size_t sz) noexcept {
const auto oldSz = m_vec.size(); const auto oldSz = m_vec.size();
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) {
m_vec[i] = m_templateValue; oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels));
} }
} }
return {};
} }
[[nodiscard]] [[nodiscard]]
@@ -250,7 +250,9 @@ class ModelValueVector {
} }
constexpr Error setType(const DescriptorType *type, int subscriptLevels) noexcept { constexpr Error setType(const DescriptorType *type, int subscriptLevels) noexcept {
return m_templateValue.setType(type, subscriptLevels); m_type = type;
m_typeSubscriptLevels = subscriptLevels;
return {};
} }
[[nodiscard]] [[nodiscard]]
@@ -350,7 +352,7 @@ class ModelObject {
constexpr ModelObject(const ModelObject &other) noexcept { constexpr ModelObject(const ModelObject &other) noexcept {
for (const auto &f : other.m_fieldsOrder) { for (const auto &f : other.m_fieldsOrder) {
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value}); auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
m_fields[field->name] = &field->value; m_fields[field->name] = &field->value;
} }
m_type = other.m_type; m_type = other.m_type;
@@ -427,7 +429,7 @@ class ModelObject {
return *this; return *this;
} }
for (const auto &f : other.m_fieldsOrder) { for (const auto &f : other.m_fieldsOrder) {
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value}); auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
m_fields[field->name] = &field->value; m_fields[field->name] = &field->value;
} }
m_type = other.m_type; m_type = other.m_type;
@@ -450,7 +452,7 @@ class ModelObject {
f = val; f = val;
} }
constexpr Result<const ModelValue*> get(const String &k) const noexcept { constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
if (m_fields.contains(k)) { if (m_fields.contains(k)) {
return *m_fields.at(k).value; return *m_fields.at(k).value;
} }
@@ -464,7 +466,7 @@ class ModelObject {
return {}; return {};
} }
constexpr auto &operator[](const String &k) noexcept { constexpr auto &operator[](StringView const&k) noexcept {
auto [v, err] = m_fields.at(k); auto [v, err] = m_fields.at(k);
if (err) [[unlikely]] { if (err) [[unlikely]] {
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str()); oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
@@ -528,7 +530,7 @@ class ModelUnion {
public: public:
constexpr ModelUnion(const ModelUnion &other) noexcept { constexpr ModelUnion(const ModelUnion &other) noexcept {
for (auto i = 0; const auto &f : other.m_fieldsOrder) { for (auto i = 0; const auto &f : other.m_fieldsOrder) {
auto &field = m_fieldsOrder.emplace_back(new Field{i, f->name, f->value}); auto &field = m_fieldsOrder.emplace_back(new Field{i, ox::String(f->name), f->value});
m_fields[field->name] = field.get(); m_fields[field->name] = field.get();
++i; ++i;
} }
@@ -553,7 +555,7 @@ class ModelUnion {
return UniquePtr<ModelUnion>(new ModelUnion(other)); return UniquePtr<ModelUnion>(new ModelUnion(other));
} }
constexpr auto &operator[](const String &k) noexcept { constexpr auto &operator[](StringView const&k) noexcept {
const auto [v, err] = m_fields.at(k); const auto [v, err] = m_fields.at(k);
if (err) [[unlikely]] { if (err) [[unlikely]] {
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str()); oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
@@ -588,7 +590,7 @@ class ModelUnion {
} }
[[nodiscard]] [[nodiscard]]
constexpr Result<const ModelValue*> get(const String &k) const noexcept { constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
oxRequire(t, m_fields.at(k)); oxRequire(t, m_fields.at(k));
return &(*t)->value; return &(*t)->value;
} }
@@ -814,9 +816,6 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
} }
} }
constexpr ModelValue::ModelValue(ModelValue &other) noexcept: ModelValue(const_cast<const ModelValue&>(other)) {
}
constexpr ModelValue::ModelValue(ModelValue &&other) noexcept { constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
m_type = other.m_type; m_type = other.m_type;
switch (m_type) { switch (m_type) {
@@ -1094,14 +1093,12 @@ constexpr ModelValueVector::ModelValueVector(const ModelValueVector &other) noex
for (auto &v : other.m_vec) { for (auto &v : other.m_vec) {
m_vec.emplace_back(v); m_vec.emplace_back(v);
} }
m_templateValue = other.m_templateValue;
m_typeName = other.m_typeName; m_typeName = other.m_typeName;
m_typeVersion = other.m_typeVersion; m_typeVersion = other.m_typeVersion;
} }
constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept { constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept {
m_vec = std::move(other.m_vec); m_vec = std::move(other.m_vec);
m_templateValue = std::move(other.m_templateValue);
m_typeName = std::move(other.m_typeName); m_typeName = std::move(other.m_typeName);
m_typeVersion = other.m_typeVersion; m_typeVersion = other.m_typeVersion;
} }
@@ -1113,7 +1110,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(const ModelValueVector &
for (auto &v : other.m_vec) { for (auto &v : other.m_vec) {
m_vec.emplace_back(v); m_vec.emplace_back(v);
} }
m_templateValue = other.m_templateValue;
m_typeName = other.m_typeName; m_typeName = other.m_typeName;
m_typeVersion = other.m_typeVersion; m_typeVersion = other.m_typeVersion;
return *this; return *this;
@@ -1124,7 +1120,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(ModelValueVector &&other
return *this; return *this;
} }
m_vec = std::move(other.m_vec); m_vec = std::move(other.m_vec);
m_templateValue = std::move(other.m_templateValue);
m_typeName = std::move(other.m_typeName); m_typeName = std::move(other.m_typeName);
m_typeVersion = other.m_typeVersion; m_typeVersion = other.m_typeVersion;
return *this; return *this;

View File

@@ -32,7 +32,7 @@ constexpr auto getModelTypeVersion(TestType2*) noexcept {
return 2; return 2;
} }
std::map<ox::String, ox::Error(*)()> tests = { std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
{ {
"ModelValue", "ModelValue",
@@ -47,6 +47,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
return ox::Error{}; return ox::Error{};
} }
}, },
{ {
"getModelTypeName", "getModelTypeName",
[] { [] {
@@ -55,6 +56,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
return ox::Error{}; return ox::Error{};
} }
}, },
{ {
"getModelTypeVersion", "getModelTypeVersion",
[] { [] {
@@ -67,11 +69,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
if (argc > 0) { if (argc < 2) {
auto testName = args[1]; oxError("Must specify test to run");
if (tests.find(testName) != tests.end()) {
oxAssert(tests[testName](), "Test failed...");
}
} }
return 0; auto const testName = args[1];
auto const func = tests.find(testName);
if (func != tests.end()) {
oxAssert(func->second(), "Test returned Error");
return 0;
}
return -1;
} }

View File

@@ -79,9 +79,6 @@ static_assert(isBasicString_v<ox::BasicString<0ul>>);
static_assert(isBasicString_v<ox::BasicString<8ul>>); static_assert(isBasicString_v<ox::BasicString<8ul>>);
static_assert(isBasicString_v<ox::String>); static_assert(isBasicString_v<ox::String>);
template<typename T>
constexpr bool isOxString_v = isBString_v<T> || isBasicString_v<T>;
template<typename T> template<typename T>
consteval bool isOxVector(const T*) noexcept { consteval bool isOxVector(const T*) noexcept {
return false; return false;

View File

@@ -44,11 +44,11 @@ class TypeStore {
return out->get(); return out->get();
} }
constexpr DescriptorType *getInit(const auto &typeName, int typeVersion, PrimitiveType pt, constexpr DescriptorType *getInit(CRStringView typeName, int typeVersion, PrimitiveType pt,
const TypeParamPack &typeParams) noexcept { const TypeParamPack &typeParams) noexcept {
const auto typeId = buildTypeId(typeName, typeVersion, typeParams); const auto typeId = buildTypeId(typeName, typeVersion, typeParams);
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
out = ox::make_unique<DescriptorType>(typeName, typeVersion, pt, typeParams); out = ox::make_unique<DescriptorType>(String(typeName), typeVersion, pt, typeParams);
return out.get(); return out.get();
} }
@@ -58,7 +58,7 @@ class TypeStore {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeId)); oxRequireM(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) { for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeId).moveTo(&f.type)); oxReturnError(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);

View File

@@ -265,7 +265,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)); oxReturnError(field(key, &str));
return UUID::fromString(str).moveTo(val); return UUID::fromString(str).moveTo(*val);
} }
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept { Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept {

View File

@@ -147,7 +147,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
if constexpr(isVector_v<T>) { 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();
val->resize(srcSize); oxReturnError(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);
@@ -194,7 +194,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
*val = 0; *val = BasicString<L>{};
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {

View File

@@ -53,7 +53,7 @@ struct TestStruct {
int32_t Int8 = 0; int32_t Int8 = 0;
int unionIdx = 1; int unionIdx = 1;
TestUnion Union; TestUnion Union;
ox::String String = ""; ox::String String{""};
uint32_t List[4] = {0, 0, 0, 0}; uint32_t List[4] = {0, 0, 0, 0};
ox::HashMap<ox::String, int> Map; ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct; TestStructNest EmptyStruct;
@@ -124,7 +124,7 @@ constexpr TestStruct &TestStruct::operator=(TestStruct &&other) noexcept {
return *this; return *this;
} }
const std::map<std::string_view, ox::Error(*)()> tests = { const std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
{ {
"OrganicClawWriter", "OrganicClawWriter",
@@ -189,53 +189,53 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
}, },
{ {
"OrganicClawModelValue", "OrganicClawModelValue",
[] { [] {
ox::Buffer dataBuff; ox::Buffer dataBuff;
TestStruct testIn; TestStruct testIn;
testIn.Bool = true; testIn.Bool = true;
testIn.Int = 42; testIn.Int = 42;
testIn.String = "Test String 1"; testIn.String = "Test String 1";
testIn.List[0] = 1; testIn.List[0] = 1;
testIn.List[1] = 2; testIn.List[1] = 2;
testIn.List[2] = 3; testIn.List[2] = 3;
testIn.List[3] = 4; testIn.List[3] = 4;
testIn.Struct.Bool = false; testIn.Struct.Bool = false;
testIn.Struct.Int = 300; testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2"; testIn.Struct.String = "Test String 2";
testIn.unionIdx = 1; testIn.unionIdx = 1;
testIn.Union.Int = 93; testIn.Union.Int = 93;
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed"); oxAssert(ox::writeOC(testIn).moveTo(dataBuff), "Data generation failed");
ox::TypeStore typeStore; ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn); auto type = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value)); oxReturnError(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed"); oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &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");
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed"); oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>(); auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>(); auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>(); auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>(); auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>(); auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>(); auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed"); oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed"); oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed"); oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed"); oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed"); oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong"); oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed"); oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed"); oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed"); oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed"); oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
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 OxError(0);
} }
}, },
{ {
@@ -354,13 +354,11 @@ int main(int argc, const char **args) {
if (argc < 2) { if (argc < 2) {
oxError("Must specify test to run"); oxError("Must specify test to run");
} }
const auto testName = args[1]; auto const testName = args[1];
ox::Error(*test)(); auto const func = tests.find(testName);
try { if (func != tests.end()) {
test = tests.at(testName); oxAssert(func->second(), "Test returned Error");
} catch (const std::out_of_range&) { return 0;
oxErrorf("Test {} not found", testName);
return 1;
} }
return static_cast<int>(test()); return -1;
} }

View File

@@ -26,16 +26,8 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
return OxError(0); return OxError(0);
} }
Error OrganicClawWriter::fieldCString(const char *key, char **val, int len) noexcept {
return fieldCString(key, const_cast<const char**>(val), len);
}
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
return fieldCString(key, const_cast<const char**>(val), {}); return fieldCString(key, const_cast<const char**>(val), static_cast<int>(ox_strlen(val)));
}
Error OrganicClawWriter::fieldCString(const char *key, char **val) noexcept {
return fieldCString(key, const_cast<const char**>(val), {});
} }
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept { Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept {

View File

@@ -36,32 +36,32 @@ class OrganicClawWriter {
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept; explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
Error field(const char *key, CommonPtrWith<int8_t> auto *val) noexcept { Error field(const char *key, const int8_t *val) noexcept {
if (*val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<int16_t> auto *val) noexcept { Error field(const char *key, const int16_t *val) noexcept {
if (*val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<int32_t> auto *val) noexcept { Error field(const char *key, const int32_t *val) noexcept {
if (*val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<int64_t> auto *val) noexcept { Error field(const char *key, const int64_t *val) noexcept {
if (*val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
@@ -69,58 +69,55 @@ class OrganicClawWriter {
} }
Error field(const char *key, CommonPtrWith<uint8_t> auto *val) noexcept { Error field(const char *key, const uint8_t *val) noexcept {
if (*val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<uint16_t> auto *val) noexcept { Error field(const char *key, const uint16_t *val) noexcept {
if (targetValid() && *val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<uint32_t> auto *val) noexcept { Error field(const char *key, const uint32_t *val) noexcept {
if (targetValid() && *val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<uint64_t> auto *val) noexcept { Error field(const char *key, const uint64_t *val) noexcept {
if (targetValid() && *val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return OxError(0);
} }
Error field(const char *key, CommonPtrWith<bool> auto *val) noexcept { Error field(char const*key, bool const*val) noexcept {
if (targetValid() && *val) { if (targetValid() && (*val || m_json.isArray())) {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return {}; return {};
} }
template<typename T>
Error field(const char*, T *val, std::size_t len) noexcept;
template<typename U, bool force = true> template<typename U, bool force = true>
Error field(const char*, UnionView<U, force> val) noexcept; Error field(char const*, UnionView<U, force> val) noexcept;
template<typename T> template<typename T>
Error field(const char *key, const HashMap<String, T> *val) noexcept { Error field(char const*key, HashMap<String, T> const*val) noexcept {
if (targetValid()) { if (targetValid()) {
const auto &keys = val->keys(); const auto &keys = val->keys();
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
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]] {
@@ -134,13 +131,8 @@ class OrganicClawWriter {
return {}; return {};
} }
template<typename T>
Error field(const char *key, HashMap<String, T> *val) noexcept {
return field(key, const_cast<const HashMap<String, T>*>(val));
}
template<std::size_t L> template<std::size_t L>
Error field(const char *key, const BString<L> *val) noexcept { Error field(char const*key, BString<L> const*val) noexcept {
if (targetValid() && val->len()) { if (targetValid() && val->len()) {
value(key) = val->c_str(); value(key) = val->c_str();
} }
@@ -149,16 +141,7 @@ class OrganicClawWriter {
} }
template<std::size_t L> template<std::size_t L>
Error field(const char *key, BString<L> *val) noexcept { Error field(char const*key, BasicString<L> const*val) noexcept {
if (targetValid() && val->len()) {
value(key) = val->c_str();
}
++m_fieldIt;
return {};
}
template<std::size_t L>
Error field(const char *key, const BasicString<L> *val) noexcept {
if (targetValid() && val->len()) { if (targetValid() && val->len()) {
value(key) = val->c_str(); value(key) = val->c_str();
} }
@@ -166,33 +149,35 @@ class OrganicClawWriter {
return OxError(0); return OxError(0);
} }
template<std::size_t L>
Error field(const char *key, BasicString<L> *val) noexcept {
return field(key, const_cast<const BasicString<L>*>(val));
}
Error fieldCString(const char*, const char *const*val, int len) noexcept; Error fieldCString(const char*, const char *const*val, int len) noexcept;
Error fieldCString(const char *name, char **val, int len) noexcept;
Error fieldCString(const char *name, const char *const*val) noexcept; Error fieldCString(const char *name, const char *const*val) noexcept;
Error fieldCString(const char *name, char **val) noexcept;
Error field(const char *key, const UUID *uuid) noexcept; Error field(const char *key, const UUID *uuid) noexcept;
template<typename T> template<typename T>
Error field(const char*, T *val) noexcept; Error field(const char*, const T *val, std::size_t len) noexcept;
template<typename T>
Error field(const char*, const T *val) noexcept;
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion, int = T::TypeVersion) noexcept {
const Vector<String>& = {},
std::size_t = ModelFieldCount_v<T>) noexcept {
return {}; return {};
} }
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {};
}
[[nodiscard]]
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
return OpType::Write; return OpType::Write;
} }
@@ -209,12 +194,12 @@ class OrganicClawWriter {
}; };
template<typename T> template<typename T>
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcept { Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) noexcept {
if (targetValid() && len) { if (targetValid() && len) {
OrganicClawWriter w((Json::Value(Json::arrayValue))); OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field("", &val[i])); oxReturnError(handler.field({}, &val[i]));
} }
value(key) = w.m_json; value(key) = w.m_json;
} }
@@ -223,12 +208,12 @@ Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcep
} }
template<typename T> template<typename T>
Error OrganicClawWriter::field(const char *key, T *val) noexcept { Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
return field(key, val->data(), val->size()); return field(key, val->data(), val->size());
} else if (val && targetValid()) { } else if (val && targetValid()) {
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val)); oxReturnError(model(&handler, val));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
@@ -242,7 +227,7 @@ template<typename U, bool force>
Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept {
if (targetValid()) { if (targetValid()) {
OrganicClawWriter w(val.idx()); OrganicClawWriter w(val.idx());
ModelHandlerInterface handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val.get())); oxReturnError(model(&handler, val.get()));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
@@ -254,7 +239,7 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
Result<Buffer> writeOC(const auto &val) noexcept { Result<Buffer> writeOC(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); oxReturnError(model(&handler, &val));
Json::StreamWriterBuilder jsonBuilder; Json::StreamWriterBuilder jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);

View File

@@ -22,15 +22,22 @@ template<typename PlatSpec, typename T>
constexpr std::size_t sizeOf(const T *t) noexcept; constexpr std::size_t sizeOf(const T *t) noexcept;
template<typename PlatSpec> template<typename PlatSpec>
struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>> { struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpType::Reflect> {
std::size_t biggestAlignment = 1; std::size_t biggestAlignment = 1;
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion, int = T::TypeVersion) noexcept {
const Vector<String>& = {}, return {};
std::size_t = ModelFieldCount_v<T>) noexcept { }
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {}; return {};
} }
@@ -57,11 +64,6 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>> {
return {}; return {};
} }
[[nodiscard]]
static constexpr auto opType() noexcept {
return ox::OpType::Reflect;
}
}; };
} }

View File

@@ -13,6 +13,7 @@
namespace ox { namespace ox {
struct NativePlatSpec { struct NativePlatSpec {
static constexpr std::size_t RomStart = 1024;
using PtrType = uintptr_t; using PtrType = uintptr_t;
using size_t = std::size_t; using size_t = std::size_t;

View File

@@ -6,4 +6,6 @@
namespace ox { namespace ox {
template class Preloader<NativePlatSpec>;
} }

View File

@@ -15,7 +15,6 @@
#include <ox/std/units.hpp> #include <ox/std/units.hpp>
#include <ox/model/modelhandleradaptor.hpp> #include <ox/model/modelhandleradaptor.hpp>
#include "preloader.hpp"
#include "platspecs.hpp" #include "platspecs.hpp"
namespace ox { namespace ox {
@@ -24,7 +23,7 @@ template<typename PlatSpec>
class Preloader; class Preloader;
template<typename PlatSpec> template<typename PlatSpec>
class Preloader: public ModelHandlerBase<Preloader<PlatSpec>> { class Preloader: public ModelHandlerBase<Preloader<PlatSpec>, OpType::Reflect> {
private: private:
using PtrType = typename PlatSpec::PtrType; using PtrType = typename PlatSpec::PtrType;
static constexpr auto PtrSize = sizeof(PtrType); static constexpr auto PtrSize = sizeof(PtrType);
@@ -74,9 +73,16 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>> {
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion, int = T::TypeVersion) noexcept {
const Vector<String>& = {}, return {};
std::size_t = ModelFieldCount_v<T>) noexcept { }
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {}; return {};
} }
@@ -108,11 +114,6 @@ class Preloader: public ModelHandlerBase<Preloader<PlatSpec>> {
return m_buff; return m_buff;
} }
[[nodiscard]]
static constexpr auto opType() noexcept {
return ox::OpType::Write;
}
template<typename T> template<typename T>
constexpr ox::Error pad(const T*) noexcept; constexpr ox::Error pad(const T*) noexcept;
@@ -198,7 +199,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::BasicStri
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)); oxReturnError(ox::allocate(&m_writer, sz).moveTo(a));
} else { } else {
a = restore; a = restore;
} }
@@ -246,7 +247,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const T **val, std:
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(std::size_t sz) noexcept { constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(std::size_t sz) noexcept {
oxRequire(a, ox::allocate(&m_writer, sz)); oxRequire(a, ox::allocate(&m_writer, sz));
m_allocStack.emplace_back(m_writer.tellp()); m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp()));
oxReturnError(m_writer.seekp(a)); oxReturnError(m_writer.seekp(a));
return a; return a;
} }
@@ -265,7 +266,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(si.restore, si.seekdir)); oxReturnError(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir));
m_allocStack.pop_back(); m_allocStack.pop_back();
return {}; return {};
} }
@@ -357,4 +358,6 @@ constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *
return pl->pad(obj); return pl->pad(obj);
} }
extern template class Preloader<NativePlatSpec>;
} }

View File

@@ -24,7 +24,7 @@ template<typename PlatSpec, typename T>
constexpr std::size_t sizeOf(const T *t) noexcept; constexpr std::size_t sizeOf(const T *t) noexcept;
template<typename PlatSpec> template<typename PlatSpec>
class SizeCatcher: public ModelHandlerBase<SizeCatcher<PlatSpec>> { class SizeCatcher: public ModelHandlerBase<SizeCatcher<PlatSpec>, OpType::Reflect> {
private: private:
std::size_t m_size = 0; std::size_t m_size = 0;
@@ -34,9 +34,16 @@ class SizeCatcher: public ModelHandlerBase<SizeCatcher<PlatSpec>> {
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion, int = T::TypeVersion) noexcept {
const Vector<String>& = {}, return {};
std::size_t = ModelFieldCount_v<T>) noexcept { }
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {}; return {};
} }
@@ -54,11 +61,6 @@ class SizeCatcher: public ModelHandlerBase<SizeCatcher<PlatSpec>> {
return m_size; return m_size;
} }
[[nodiscard]]
static constexpr auto opType() noexcept {
return ox::OpType::Reflect;
}
private: private:
constexpr void pad(const auto *val) noexcept; constexpr void pad(const auto *val) noexcept;
}; };
@@ -105,7 +107,7 @@ constexpr std::size_t sizeOf(const T *t) noexcept {
if constexpr(ox::is_integral_v<T>) { if constexpr(ox::is_integral_v<T>) {
return sizeof(T); return sizeof(T);
} else if constexpr(ox::is_pointer_v<T>) { } else if constexpr(ox::is_pointer_v<T>) {
return sizeof(PlatSpec::PtrType); return sizeof(typename PlatSpec::PtrType);
} else { } else {
SizeCatcher<PlatSpec> sc; SizeCatcher<PlatSpec> sc;
const auto err = model(sc.interface(), t); const auto err = model(sc.interface(), t);

View File

@@ -14,7 +14,7 @@
namespace ox { namespace ox {
template<typename PlatSpec> template<typename PlatSpec>
class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>> { class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpType::Reflect> {
private: private:
std::size_t m_size = 0; std::size_t m_size = 0;
@@ -23,9 +23,16 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>> {
template<typename T> template<typename T>
constexpr ox::Error setTypeInfo( constexpr ox::Error setTypeInfo(
const char* = T::TypeName, const char* = T::TypeName,
int = T::TypeVersion, int = T::TypeVersion) noexcept {
const Vector<String>& = {}, return {};
std::size_t = ModelFieldCount_v<T>) noexcept { }
template<typename T>
constexpr ox::Error setTypeInfo(
const char*,
int,
const Vector<String>&,
std::size_t) noexcept {
return {}; return {};
} }
@@ -48,11 +55,6 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>> {
return m_size; return m_size;
} }
[[nodiscard]]
static constexpr auto opType() noexcept {
return ox::OpType::Reflect;
}
private: private:
template<typename T, std::size_t SmallVecSize> template<typename T, std::size_t SmallVecSize>
constexpr ox::Error fieldStr(CRStringView, const ox::BasicString<SmallVecSize> *val) noexcept; constexpr ox::Error fieldStr(CRStringView, const ox::BasicString<SmallVecSize> *val) noexcept;

View File

@@ -118,6 +118,7 @@ install(
std.hpp std.hpp
stddef.hpp stddef.hpp
string.hpp string.hpp
stringliteral.hpp
stringview.hpp stringview.hpp
strongint.hpp strongint.hpp
strops.hpp strops.hpp

View File

@@ -82,7 +82,7 @@ constexpr void expect(CRStringView file, int line, const auto &actual, const aut
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect"); oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual)); oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
printStackTrace(2); printStackTrace(2);
oxTracef("assert::expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line); oxTracef("assert.expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
std::abort(); std::abort();
#else #else
constexprPanic(file, line, "Comparison failed"); constexprPanic(file, line, "Comparison failed");

217
deps/ox/src/ox/std/basestringview.hpp vendored Normal file
View File

@@ -0,0 +1,217 @@
/*
* Copyright 2015 - 2023 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "bit.hpp"
#include "cstrops.hpp"
#include "iterator.hpp"
namespace ox::detail {
class BaseStringView {
public:
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
private:
PtrType m_t = nullptr;
std::size_t m_offset = 0;
std::size_t m_max = 0;
public:
constexpr iterator() noexcept = default;
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
m_t = t;
m_offset = offset;
m_max = max;
}
[[nodiscard]]
constexpr auto offset() const noexcept {
return m_offset;
}
constexpr iterator operator+(std::size_t s) const noexcept {
if constexpr(reverse) {
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
} else {
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
}
}
constexpr auto operator-(const iterator &other) const noexcept {
if constexpr(reverse) {
return m_offset + other.m_offset;
} else {
return m_offset - other.m_offset;
}
}
constexpr iterator operator-(std::size_t s) const noexcept {
if constexpr(reverse) {
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
} else {
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
}
}
constexpr iterator &operator+=(std::size_t s) noexcept {
if constexpr(reverse) {
m_offset = max<std::size_t>(m_offset - s, 0);
} else {
m_offset = min(m_offset + s, m_max);
}
return *this;
}
constexpr iterator &operator-=(std::size_t s) noexcept {
if constexpr(reverse) {
m_offset = min(m_offset + s, m_max);
} else {
m_offset = max<std::size_t>(m_offset - s, 0);
}
return *this;
}
constexpr iterator &operator++() noexcept {
return operator+=(1);
}
constexpr iterator &operator--() noexcept {
return operator-=(1);
}
constexpr RefType operator*() const noexcept {
return m_t[m_offset];
}
constexpr RefType operator[](std::size_t s) const noexcept {
return m_t[s];
}
constexpr bool operator<(const iterator &other) const noexcept {
return m_offset < other.m_offset;
}
constexpr bool operator>(const iterator &other) const noexcept {
return m_offset > other.m_offset;
}
constexpr bool operator<=(const iterator &other) const noexcept {
return m_offset <= other.m_offset;
}
constexpr bool operator>=(const iterator &other) const noexcept {
return m_offset >= other.m_offset;
}
constexpr bool operator==(const iterator &other) const noexcept {
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
}
constexpr bool operator!=(const iterator &other) const noexcept {
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
}
};
private:
const char *m_str = nullptr;
std::size_t m_len = 0;
protected:
constexpr BaseStringView() noexcept = default;
constexpr BaseStringView(BaseStringView const&sv) noexcept = default;
constexpr explicit BaseStringView(std::nullptr_t) noexcept {}
constexpr explicit BaseStringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
constexpr explicit BaseStringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
public:
[[nodiscard]]
constexpr iterator<const char&, const char*> begin() const noexcept {
return {m_str, 0, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*> end() const noexcept {
return {m_str, m_len, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*> cbegin() const noexcept {
return {m_str, 0, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*> cend() const noexcept {
return {m_str, m_len, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
return {m_str, m_len - 1, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> crend() const noexcept {
return {m_str, MaxValue<std::size_t>, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
return {m_str, m_len - 1, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> rend() const noexcept {
return {m_str, MaxValue<std::size_t>, m_len};
}
[[nodiscard]]
constexpr auto bytes() const noexcept {
return m_len;
}
[[nodiscard]]
constexpr auto len() const noexcept {
return m_len;
}
[[nodiscard]]
constexpr auto *data() const noexcept {
return &m_str[0];
}
[[nodiscard]]
constexpr auto &front() const noexcept {
return m_str[0];
}
[[nodiscard]]
constexpr auto &back() const noexcept {
return m_str[m_len - 1];
}
[[nodiscard]]
constexpr auto operator[](std::size_t i) const noexcept {
return m_str[i];
}
protected:
constexpr void set(const char *str, std::size_t len) noexcept {
m_str = str;
m_len = len;
}
};
}

View File

@@ -23,35 +23,10 @@ concept CommonRefWith = ox::is_same_v<typename ox::remove_reference_t<const T&>,
template<typename T, typename U> template<typename T, typename U>
concept same_as = ox::is_same_v<T, T>; concept same_as = ox::is_same_v<T, T>;
template<std::size_t SmallStringSize> template<typename T>
class BasicString; concept OxString_c = isOxString_v<T>;
template<std::size_t sz>
class BString;
class StringView;
namespace detail {
constexpr auto isOxString(const auto*) noexcept {
return false;
}
template<std::size_t sz>
constexpr auto isOxString(const BasicString<sz>*) noexcept {
return true;
}
template<std::size_t sz>
constexpr auto isOxString(const BString<sz>*) noexcept {
return true;
}
constexpr auto isOxString(const StringView*) noexcept {
return true;
}
}
template<typename T> template<typename T>
concept OxString_c = detail::isOxString(static_cast<T*>(nullptr)); concept Integral_c = ox::is_integral_v<T>;
} }

53
deps/ox/src/ox/std/cstringview.hpp vendored Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright 2015 - 2023 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "basestringview.hpp"
#include "bstring.hpp"
#include "string.hpp"
#include "stringliteral.hpp"
namespace ox {
class CStringView: public detail::BaseStringView {
public:
constexpr CStringView() noexcept = default;
constexpr CStringView(CStringView const&sv) noexcept = default;
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.len()) {}
template<std::size_t SmallStrSz>
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
template<std::size_t SmallStrSz>
constexpr CStringView(BString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr CStringView(std::nullptr_t) noexcept {}
constexpr CStringView(const char *str) noexcept: BaseStringView(str) {}
constexpr CStringView(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
constexpr auto &operator=(CStringView const&other) noexcept {
if (&other != this) {
set(other.data(), other.len());
}
return *this;
}
[[nodiscard]]
constexpr const char *c_str() const noexcept {
return data();
}
};
}

145
deps/ox/src/ox/std/cstrops.hpp vendored Normal file
View File

@@ -0,0 +1,145 @@
/*
* Copyright 2015 - 2023 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "types.hpp"
#include "typetraits.hpp"
template<typename T1, typename T2>
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
std::size_t i = 0;
while (i < maxLen && src[i]) {
dest[i] = static_cast<T1Type>(src[i]);
++i;
}
// set null terminator
dest[i] = 0;
return dest;
}
[[nodiscard]]
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
std::size_t len = 0;
for (; len < maxLen && str1[len]; len++);
return len;
}
template<typename T>
[[nodiscard]]
constexpr auto ox_strlen(T const&str1) noexcept {
std::size_t len = 0;
for (; str1[len]; len++);
return len;
}
template<typename T1, typename T2>
[[nodiscard]]
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
auto retval = 0;
auto i = 0u;
while (str1[i] || str2[i]) {
if (str1[i] < str2[i]) {
retval = -1;
break;
} else if (str1[i] > str2[i]) {
retval = 1;
break;
}
i++;
}
return retval;
}
template<typename T1, typename T2>
[[nodiscard]]
constexpr int ox_strncmp(T1 const&str1, T2 const&str2, const std::size_t maxLen) noexcept {
auto retval = 0;
std::size_t i = 0;
while (i < maxLen && (str1[i] || str2[i])) {
if (str1[i] < str2[i]) {
retval = -1;
break;
} else if (str1[i] > str2[i]) {
retval = 1;
break;
}
i++;
}
return retval;
}
[[nodiscard]]
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
for (std::size_t i = 0; i <= maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
[[nodiscard]]
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
for (std::size_t i = 0; i < maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
[[nodiscard]]
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
int retval = -1;
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
if (str[i] == character) {
retval = static_cast<int>(i);
}
}
return retval;
}
template<typename Integer, typename T>
constexpr T ox_itoa(Integer v, T str) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
str[static_cast<std::size_t>(it)] = '-';
it++;
}
while (mod) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
ox::ResizedInt_t<Integer, 64> start = '0';
if (digit >= 10) {
start = 'a';
digit -= 10;
}
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
it++;
}
}
str[static_cast<std::size_t>(it)] = 0;
} else {
// 0 is a special case
str[0] = '0';
str[1] = 0;
}
return str;
}

View File

@@ -17,16 +17,9 @@
#define oxOut(...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", __VA_ARGS__) #define oxOut(...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", __VA_ARGS__)
#define oxErr(...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", __VA_ARGS__) #define oxErr(...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", __VA_ARGS__)
#ifdef OX_USE_STDLIB #define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib #define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__}) #define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
#else
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
#endif
#define oxInfo(...) oxTrace("info", __VA_ARGS__) #define oxInfo(...) oxTrace("info", __VA_ARGS__)
#define oxInfof(...) oxTracef("info", __VA_ARGS__) #define oxInfof(...) oxTracef("info", __VA_ARGS__)
@@ -35,12 +28,7 @@
#ifndef OX_NODEBUG #ifndef OX_NODEBUG
#define oxDebug(...) ox::trace::OutStream(__FILE__, __LINE__, "debug", __VA_ARGS__) #define oxDebug(...) ox::trace::OutStream(__FILE__, __LINE__, "debug", __VA_ARGS__)
#ifdef OX_USE_STDLIB #define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
#else
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
#endif
#else #else
#define oxDebug(...) static_assert(false, "Debug prints were checked in."); #define oxDebug(...) static_assert(false, "Debug prints were checked in.");
#define oxDebugf(...) static_assert(false, "Debug prints were checked in."); #define oxDebugf(...) static_assert(false, "Debug prints were checked in.");

View File

@@ -25,8 +25,6 @@ class exception {
#endif #endif
#include "def.hpp" #include "def.hpp"
#include "defines.hpp"
#include "strongint.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
#include "utility.hpp" #include "utility.hpp"
@@ -132,7 +130,7 @@ struct [[nodiscard]] Result {
T value; T value;
Error error; Error error;
constexpr Result() noexcept: error(0) { constexpr Result() noexcept: value(), error(0) {
} }
template<typename U> template<typename U>
@@ -140,16 +138,16 @@ struct [[nodiscard]] Result {
} }
template<typename U> template<typename U>
constexpr Result(const Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) { constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
} }
constexpr Result(const Error &error) noexcept: error(error) { constexpr Result(const Error &error) noexcept: value(), error(error) {
} }
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(const_cast<type&>(value)), error(error) { constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(value), error(error) {
} }
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(ox::forward<type>(value)), error(error) { constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(std::move(value)), error(error) {
} }
constexpr ~Result() noexcept = default; constexpr ~Result() noexcept = default;
@@ -167,44 +165,139 @@ struct [[nodiscard]] Result {
return error == 0; return error == 0;
} }
constexpr Error get(type *val) const noexcept { constexpr Error copyTo(type &val) const& noexcept {
*val = value;
return error;
}
constexpr Error get(type *val) noexcept {
*val = value;
return error;
}
constexpr Error moveTo(type *val) noexcept {
if (!error) [[likely]] { if (!error) [[likely]] {
*val = std::move(value); val = value;
} }
return error; return error;
} }
constexpr auto &unwrap() noexcept { constexpr Error copyTo(type &val) && noexcept {
if (!error) [[likely]] {
val = std::move(value);
}
return error;
}
constexpr Error moveTo(type &val) noexcept {
if (!error) [[likely]] {
val = std::move(value);
}
return error;
}
[[nodiscard]]
constexpr T &unwrap() & noexcept {
if (error) { if (error) {
oxPanic(error, "Failed unwrap"); oxPanic(error, "Failed unwrap");
} }
return value; return value;
} }
constexpr const auto &unwrap() const noexcept { [[nodiscard]]
constexpr T &&unwrap() && noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
}
return std::move(value);
}
[[nodiscard]]
constexpr T const&unwrap() const & noexcept {
if (error) [[unlikely]] { if (error) [[unlikely]] {
oxPanic(error, "Failed unwrap"); oxPanic(error, "Failed unwrap");
} }
return value; return value;
} }
constexpr ox::Result<T> to(const auto &f) noexcept { [[nodiscard]]
constexpr T &unwrapThrow() & {
if (error) {
throw ox::Exception(error);
}
return value;
}
[[nodiscard]]
constexpr T &&unwrapThrow() && {
if (error) {
throw ox::Exception(error);
}
return std::move(value);
}
[[nodiscard]]
constexpr T const&unwrapThrow() const & {
if (error) {
throw ox::Exception(error);
}
return value;
}
template<typename U = T>
constexpr ox::Result<U> to(auto const&f) & noexcept {
if (error) [[unlikely]] { if (error) [[unlikely]] {
return OxError(1); return error;
} }
return f(value); return f(value);
} }
template<typename U = T>
constexpr ox::Result<U> to(auto const&f) && noexcept {
if (error) [[unlikely]] {
return error;
}
return f(std::move(value));
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T &&alt) const& noexcept {
if (error) {
return std::move(alt);
}
return value;
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T &&alt) && noexcept {
if (error) {
return std::move(alt);
}
return std::move(value);
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) const& noexcept {
if (error) {
return alt;
}
return value;
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) && noexcept {
if (error) {
return alt;
}
return std::move(value);
}
}; };
namespace detail { namespace detail {

View File

@@ -186,14 +186,14 @@ constexpr Fmt<segementCnt> fmtSegments(StringView fmt) noexcept {
template<typename StringType = String, typename ...Args> template<typename StringType = String, typename ...Args>
[[nodiscard]] [[nodiscard]]
constexpr StringType sfmt(StringView fmt, Args... args) noexcept { constexpr StringType sfmt(StringView fmt, Args&&... args) noexcept {
assert(ox::detail::argCount(fmt) == sizeof...(args)); assert(ox::detail::argCount(fmt) == sizeof...(args));
StringType out; StringType out;
const auto fmtSegments = ox::detail::fmtSegments<sizeof...(args)+1>(fmt); const auto fmtSegments = ox::detail::fmtSegments<sizeof...(args)+1>(fmt);
const auto &firstSegment = fmtSegments.segments[0]; const auto &firstSegment = fmtSegments.segments[0];
oxIgnoreError(out.append(firstSegment.str, firstSegment.length)); oxIgnoreError(out.append(firstSegment.str, firstSegment.length));
const detail::FmtArg elements[sizeof...(args)] = {args...}; const detail::FmtArg elements[sizeof...(args)] = {args...};
for (auto i = 0u; i < fmtSegments.size - 1; ++i) { for (size_t i = 0; i < fmtSegments.size - 1; ++i) {
out += elements[i].out; out += elements[i].out;
const auto &s = fmtSegments.segments[i + 1]; const auto &s = fmtSegments.segments[i + 1];
oxIgnoreError(out.append(s.str, s.length)); oxIgnoreError(out.append(s.str, s.length));

View File

@@ -9,6 +9,7 @@
#pragma once #pragma once
#include "algorithm.hpp" #include "algorithm.hpp"
#include "stringview.hpp"
#include "strops.hpp" #include "strops.hpp"
#include "vector.hpp" #include "vector.hpp"
@@ -17,8 +18,9 @@ namespace ox {
template<typename K, typename T> template<typename K, typename T>
class HashMap { class HashMap {
using key_t = K; public:
using value_t = T; using key_t = K;
using value_t = T;
private: private:
struct Pair { struct Pair {
@@ -31,62 +33,49 @@ class HashMap {
public: public:
explicit constexpr HashMap(std::size_t size = 100); explicit constexpr HashMap(std::size_t size = 100);
constexpr HashMap(const HashMap &other); constexpr HashMap(HashMap const&other);
constexpr HashMap(HashMap &&other) noexcept; constexpr HashMap(HashMap &&other) noexcept;
constexpr ~HashMap(); constexpr ~HashMap();
constexpr bool operator==(const HashMap &other) const; constexpr bool operator==(HashMap const&other) const;
constexpr HashMap &operator=(const HashMap &other); constexpr HashMap &operator=(HashMap const&other);
constexpr HashMap &operator=(HashMap &&other); constexpr HashMap &operator=(HashMap &&other) noexcept;
/** constexpr T &operator[](MaybeSV_t<K> const&key);
* K is assumed to be a null terminated string.
*/
constexpr T &operator[](const K &key);
/** constexpr Result<T*> at(MaybeSV_t<K> const&key) noexcept;
* K is assumed to be a null terminated string.
*/
constexpr Result<T*> at(const K &key) noexcept;
/** constexpr Result<const T*> at(MaybeSV_t<K> const&key) const noexcept;
* K is assumed to be a null terminated string.
*/
constexpr Result<const T*> at(const K &key) const noexcept;
constexpr void erase(const K &key); constexpr void erase(MaybeSV_t<K> const&key);
constexpr bool contains(const K &key) const noexcept; [[nodiscard]]
constexpr bool contains(MaybeSV_t<K> const&key) const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr std::size_t size() const noexcept; constexpr std::size_t size() const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr const Vector<K> &keys() const noexcept; constexpr Vector<K> const&keys() const noexcept;
constexpr void clear(); constexpr void clear();
private: private:
constexpr void expand(); constexpr void expand();
/** constexpr static uint64_t hash(Integral_c auto) noexcept;
* K is assumed to be a null terminated string.
*/
constexpr static uint64_t hash(auto) noexcept;
/** constexpr static uint64_t hash(StringView const&) noexcept;
* K is assumed to be a null terminated string.
*/
constexpr Pair *const&access(const Vector<Pair*> &pairs, const K &key) const;
/** template<typename KK>
* K is assumed to be a null terminated string. constexpr Pair *const&access(Vector<Pair*> const&pairs, KK const&key) const;
*/
constexpr Pair *&access(Vector<Pair*> &pairs, const K &key); template<typename KK>
constexpr Pair *&access(Vector<Pair*> &pairs, KK const&key);
}; };
@@ -95,7 +84,7 @@ constexpr HashMap<K, T>::HashMap(std::size_t size): m_pairs(size) {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr HashMap<K, T>::HashMap(const HashMap<K, T> &other) { constexpr HashMap<K, T>::HashMap(HashMap<K, T> const&other) {
m_pairs = other.m_pairs; m_pairs = other.m_pairs;
} }
@@ -111,11 +100,11 @@ constexpr HashMap<K, T>::~HashMap() {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr bool HashMap<K, T>::operator==(const HashMap &other) const { constexpr bool HashMap<K, T>::operator==(HashMap const&other) const {
if (m_keys != other.m_keys) { if (m_keys != other.m_keys) {
return false; return false;
} }
for (int i = 0; i < m_keys.size(); i++) { for (int i = 0; i < m_keys.size(); ++i) {
auto &k = m_keys[i]; auto &k = m_keys[i];
if (at(k) != other.at(k)) { if (at(k) != other.at(k)) {
return false; return false;
@@ -125,7 +114,7 @@ constexpr bool HashMap<K, T>::operator==(const HashMap &other) const {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr HashMap<K, T> &HashMap<K, T>::operator=(const HashMap<K, T> &other) { constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> const&other) {
if (this != &other) { if (this != &other) {
clear(); clear();
m_keys = other.m_keys; m_keys = other.m_keys;
@@ -135,7 +124,7 @@ constexpr HashMap<K, T> &HashMap<K, T>::operator=(const HashMap<K, T> &other) {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> &&other) { constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> &&other) noexcept {
if (this != &other) { if (this != &other) {
clear(); clear();
m_keys = std::move(other.m_keys); m_keys = std::move(other.m_keys);
@@ -145,7 +134,7 @@ constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> &&other) {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr T &HashMap<K, T>::operator[](const K &k) { constexpr T &HashMap<K, T>::operator[](MaybeSV_t<K> const&k) {
auto &p = access(m_pairs, k); auto &p = access(m_pairs, k);
if (p == nullptr) { if (p == nullptr) {
if (static_cast<double>(m_pairs.size()) * 0.7 < if (static_cast<double>(m_pairs.size()) * 0.7 <
@@ -154,13 +143,13 @@ constexpr T &HashMap<K, T>::operator[](const K &k) {
} }
p = new Pair; p = new Pair;
p->key = k; p->key = k;
m_keys.push_back(k); m_keys.emplace_back(k);
} }
return p->value; return p->value;
} }
template<typename K, typename T> template<typename K, typename T>
constexpr Result<T*> HashMap<K, T>::at(const K &k) noexcept { constexpr Result<T*> HashMap<K, T>::at(MaybeSV_t<K> const&k) noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, OxError(1, "value not found for given key")};
@@ -169,7 +158,7 @@ constexpr Result<T*> HashMap<K, T>::at(const K &k) noexcept {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr Result<const T*> HashMap<K, T>::at(const K &k) const noexcept { constexpr Result<const T*> HashMap<K, T>::at(MaybeSV_t<K> const&k) const noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, OxError(1, "value not found for given key")};
@@ -178,14 +167,14 @@ constexpr Result<const T*> HashMap<K, T>::at(const K &k) const noexcept {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr void HashMap<K, T>::erase(const K &k) { constexpr void HashMap<K, T>::erase(MaybeSV_t<K> const&k) {
if (!contains(k)) { if (!contains(k)) {
return; return;
} }
auto h = hash(k) % m_pairs.size(); auto h = hash(k) % m_pairs.size();
while (true) { while (true) {
const auto &p = m_pairs[h]; const auto &p = m_pairs[h];
if (p == nullptr || ox_strcmp(p->key, k) == 0) { if (p == nullptr || p->key == k) {
oxIgnoreError(m_pairs.erase(h)); oxIgnoreError(m_pairs.erase(h));
break; break;
} else { } else {
@@ -196,7 +185,7 @@ constexpr void HashMap<K, T>::erase(const K &k) {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr bool HashMap<K, T>::contains(const K &k) const noexcept { constexpr bool HashMap<K, T>::contains(MaybeSV_t<K> const&k) const noexcept {
return access(m_pairs, k) != nullptr; return access(m_pairs, k) != nullptr;
} }
@@ -206,7 +195,7 @@ constexpr std::size_t HashMap<K, T>::size() const noexcept {
} }
template<typename K, typename T> template<typename K, typename T>
constexpr const Vector<K> &HashMap<K, T>::keys() const noexcept { constexpr Vector<K> const&HashMap<K, T>::keys() const noexcept {
return m_keys; return m_keys;
} }
@@ -223,35 +212,39 @@ template<typename K, typename T>
constexpr void HashMap<K, T>::expand() { constexpr void HashMap<K, T>::expand() {
Vector<Pair*> r; Vector<Pair*> r;
for (std::size_t i = 0; i < m_keys.size(); ++i) { for (std::size_t i = 0; i < m_keys.size(); ++i) {
auto k = m_keys[i]; K k{m_keys[i]};
access(r, k) = std::move(access(m_pairs, k)); access(r, k) = std::move(access(m_pairs, k));
} }
m_pairs = std::move(r); m_pairs = std::move(r);
} }
template<typename K, typename T> template<typename K, typename T>
constexpr uint64_t HashMap<K, T>::hash(auto k) noexcept { constexpr uint64_t HashMap<K, T>::hash(Integral_c auto k) noexcept {
uint64_t sum = 1; uint64_t sum = 1;
if constexpr(is_integral_v<decltype(k)>) { for (auto i = 0u; i < sizeof(K); ++i) {
for (auto i = 0u; i < sizeof(K); ++i) { const auto shift = i * 8;
const auto shift = i * 8; const auto v = static_cast<uint64_t>(k >> shift & 0xff);
const auto v = static_cast<uint64_t>(k >> shift & 0xff); sum += (sum + v) * 7 * sum;
sum += (sum + v) * 7 * sum;
}
} else {
for (auto i = 0u; k[i]; ++i) {
sum += ((sum + static_cast<uint64_t>(k[i])) * 7) * sum;
}
} }
return sum; return sum;
} }
template<typename K, typename T> template<typename K, typename T>
constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(const Vector<Pair*> &pairs, const K &k) const { constexpr uint64_t HashMap<K, T>::hash(StringView const&k) noexcept {
uint64_t sum = 1;
for (auto i = 0u; i < k.len(); ++i) {
sum += ((sum + static_cast<uint64_t>(k[i])) * 7) * sum;
}
return sum;
}
template<typename K, typename T>
template<typename KK>
constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*> const&pairs, KK const&k) const {
auto h = static_cast<std::size_t>(hash(k) % pairs.size()); auto h = static_cast<std::size_t>(hash(k) % pairs.size());
while (true) { while (true) {
const auto &p = pairs[h]; const auto &p = pairs[h];
if (p == nullptr || ox_strcmp(p->key, k) == 0) { if (p == nullptr || p->key == k) {
return p; return p;
} else { } else {
h = (h + 1) % pairs.size(); h = (h + 1) % pairs.size();
@@ -260,18 +253,12 @@ constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(const Vector
} }
template<typename K, typename T> template<typename K, typename T>
constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pairs, const K &k) { template<typename KK>
constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pairs, KK const&k) {
auto h = static_cast<std::size_t>(hash(k) % pairs.size()); auto h = static_cast<std::size_t>(hash(k) % pairs.size());
while (true) { while (true) {
auto &p = pairs[h]; auto &p = pairs[h];
bool matches = [&] { if (p == nullptr || p->key == k) {
if constexpr (is_integral_v<K>) {
return p == nullptr || k == p->key;
} else {
return p == nullptr || ox_strcmp(p->key, k) == 0;
}
}();
if (matches) {
return p; return p;
} else { } else {
h = (h + 1) % pairs.size(); h = (h + 1) % pairs.size();

View File

@@ -39,6 +39,7 @@ constexpr T *construct_at(T *p, Args &&...args ) {
#endif #endif
#include "error.hpp"
#include "utility.hpp" #include "utility.hpp"
@@ -74,6 +75,7 @@ class SharedPtr {
int *m_refCnt = nullptr; int *m_refCnt = nullptr;
public: public:
using value_type = T;
explicit constexpr SharedPtr(T *t = nullptr) noexcept: m_t(t), m_refCnt(new int) { explicit constexpr SharedPtr(T *t = nullptr) noexcept: m_t(t), m_refCnt(new int) {
} }
@@ -180,9 +182,10 @@ template<typename T, typename Deleter = DefaultDelete>
class UniquePtr { class UniquePtr {
private: private:
T *m_t; T *m_t = nullptr;
public: public:
using value_type = T;
explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) { explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) {
} }
@@ -190,8 +193,8 @@ class UniquePtr {
constexpr UniquePtr(const UniquePtr&) = delete; constexpr UniquePtr(const UniquePtr&) = delete;
template<typename U> template<typename U, typename UDeleter>
constexpr UniquePtr(UniquePtr<U> &&other) noexcept { constexpr UniquePtr(UniquePtr<U, UDeleter> &&other) noexcept {
m_t = other.release(); m_t = other.release();
} }
@@ -210,25 +213,25 @@ class UniquePtr {
return m_t; return m_t;
} }
template<typename U> template<typename U, typename UDeleter>
constexpr void reset(UniquePtr<U> &&other = UniquePtr()) { constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
auto t = m_t; auto t = m_t;
m_t = other.release(); m_t = other.release();
Deleter()(t); Deleter()(t);
} }
constexpr UniquePtr &operator=(const UniquePtr<T> &other) = delete; constexpr UniquePtr &operator=(UniquePtr const&other) = delete;
template<typename U> template<typename U, typename UDeleter>
constexpr UniquePtr &operator=(const UniquePtr<U> &other) = delete; constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> const&other) = delete;
constexpr UniquePtr &operator=(UniquePtr<T> &&other) { constexpr UniquePtr &operator=(UniquePtr<T> &&other) noexcept {
reset(std::move(other)); reset(std::move(other));
return *this; return *this;
} }
template<typename U> template<typename U, typename UDeleter>
constexpr UniquePtr &operator=(UniquePtr<U> &&other) { constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> &&other) noexcept {
reset(std::move(other)); reset(std::move(other));
return *this; return *this;
} }
@@ -247,8 +250,8 @@ class UniquePtr {
}; };
template<typename T> template<typename T, typename Deleter = DefaultDelete>
using UPtr = UniquePtr<T>; using UPtr = UniquePtr<T, Deleter>;
template<typename T> template<typename T>
constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept { constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept {
@@ -282,10 +285,20 @@ constexpr bool operator!=(std::nullptr_t, const UniquePtr<T> &p2) noexcept {
} }
template<typename T, typename ...Args> template<typename T, typename U = T, typename ...Args>
[[nodiscard]] [[nodiscard]]
constexpr auto make_unique(Args&&... args) { constexpr auto make_unique(Args&&... args) {
return UniquePtr(new T(ox::forward<Args>(args)...)); return UniquePtr<U>(new T(ox::forward<Args>(args)...));
}
template<typename T, typename U = T, typename ...Args>
[[nodiscard]]
constexpr Result<UniquePtr<U>> make_unique_catch(Args&&... args) noexcept {
try {
return UniquePtr<U>(new T(ox::forward<Args>(args)...));
} catch (ox::Exception const&ex) {
return ex.toError();
}
} }
} }

View File

@@ -35,9 +35,9 @@ constexpr void *operator new[](std::size_t, void *addr) noexcept {
namespace ox { namespace ox {
template<typename T, typename ...Args> template<typename T, typename U = T, typename ...Args>
[[nodiscard]] [[nodiscard]]
constexpr T *make(Args &&...args) noexcept { constexpr U *make(Args &&...args) noexcept {
#ifdef __cpp_exceptions #ifdef __cpp_exceptions
try { try {
return new T(ox::forward<Args>(args)...); return new T(ox::forward<Args>(args)...);
@@ -115,11 +115,11 @@ class MallocaPtr {
return reinterpret_cast<T*>(m_val); return reinterpret_cast<T*>(m_val);
} }
constexpr const T &operator=(MallocaPtr &other) = delete; constexpr MallocaPtr &operator=(MallocaPtr &other) = delete;
constexpr const T &operator=(const MallocaPtr &other) = delete; constexpr MallocaPtr &operator=(const MallocaPtr &other) = delete;
constexpr const T &operator=(MallocaPtr &&other) noexcept { constexpr MallocaPtr &operator=(MallocaPtr &&other) noexcept {
if (m_onHeap && m_val) { if (m_onHeap && m_val) {
delete[] reinterpret_cast<uint8_t*>(m_val); delete[] reinterpret_cast<uint8_t*>(m_val);
} }
@@ -127,6 +127,7 @@ class MallocaPtr {
m_val = other.m_val; m_val = other.m_val;
other.m_onHeap = false; other.m_onHeap = false;
other.m_val = nullptr; other.m_val = nullptr;
return *this;
} }
constexpr const T *operator->() const noexcept { constexpr const T *operator->() const noexcept {
@@ -137,11 +138,11 @@ class MallocaPtr {
return reinterpret_cast<T*>(m_val); return reinterpret_cast<T*>(m_val);
} }
constexpr operator const T*() const noexcept { constexpr explicit operator const T*() const noexcept {
return reinterpret_cast<T*>(m_val); return reinterpret_cast<T*>(m_val);
} }
constexpr operator T*() noexcept { constexpr explicit operator T*() noexcept {
return reinterpret_cast<T*>(m_val); return reinterpret_cast<T*>(m_val);
} }
@@ -153,6 +154,10 @@ class MallocaPtr {
return *reinterpret_cast<T*>(m_val); return *reinterpret_cast<T*>(m_val);
} }
constexpr bool operator==(std::nullptr_t) const noexcept {
return m_val == nullptr;
}
constexpr bool operator==(const MallocaPtr<T> &other) const noexcept { constexpr bool operator==(const MallocaPtr<T> &other) const noexcept {
return m_val == other.m_val && m_onHeap == other.m_onHeap; return m_val == other.m_val && m_onHeap == other.m_onHeap;
} }

View File

@@ -28,7 +28,7 @@ class Optional {
constexpr Optional() noexcept = default; constexpr Optional() noexcept = default;
template<typename ...Args> template<typename ...Args>
explicit constexpr Optional(Args &&... args); explicit constexpr Optional(ox::in_place_t, Args &&... args);
constexpr Optional(const Optional &other) { constexpr Optional(const Optional &other) {
if (other.m_ptr) { if (other.m_ptr) {
@@ -64,20 +64,68 @@ class Optional {
return *m_ptr; return *m_ptr;
} }
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T &&alt) const& noexcept {
if (!m_ptr) {
return std::move(alt);
}
return *m_ptr;
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T &&alt) && noexcept {
if (!m_ptr) {
return std::move(alt);
}
return std::move(*m_ptr);
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) const& noexcept {
if (!m_ptr) {
return alt;
}
return *m_ptr;
}
/**
* Returns parameter alt if Result contains an error.
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) && noexcept {
if (!m_ptr) {
return alt;
}
return std::move(*m_ptr);
}
constexpr T &operator*() & noexcept { constexpr T &operator*() & noexcept {
return m_ptr; return *m_ptr;
} }
constexpr const T &operator*() const & noexcept { constexpr const T &operator*() const & noexcept {
return m_ptr; return *m_ptr;
} }
constexpr T &&operator*() && noexcept { constexpr T &&operator*() && noexcept {
return m_ptr; return *m_ptr;
} }
constexpr const T &&operator*() const && noexcept { constexpr const T &&operator*() const && noexcept {
return m_ptr; return *m_ptr;
} }
constexpr T *operator->() noexcept { constexpr T *operator->() noexcept {
@@ -163,7 +211,7 @@ class Optional {
template<typename T, std::size_t buffSize> template<typename T, std::size_t buffSize>
template<typename... Args> template<typename... Args>
constexpr Optional<T, buffSize>::Optional(Args &&... args) { constexpr Optional<T, buffSize>::Optional(ox::in_place_t, Args &&... args) {
emplace(ox::forward<Args>(args)...); emplace(ox::forward<Args>(args)...);
} }

View File

@@ -10,8 +10,6 @@
#include "bit.hpp" #include "bit.hpp"
#include "iterator.hpp" #include "iterator.hpp"
#include "typetraits.hpp"
#include "types.hpp"
#include "vector.hpp" #include "vector.hpp"
namespace ox { namespace ox {
@@ -27,30 +25,32 @@ class SpanView {
using value_type = T; using value_type = T;
using size_type = std::size_t; using size_type = std::size_t;
template<typename RefType = T&, typename PtrType = T*, bool reverse = false> template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>; using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr SpanView() noexcept {}
template<std::size_t sz> template<std::size_t sz>
constexpr SpanView(ox::Array<T, sz> const&a) noexcept: constexpr SpanView(ox::Array<T, sz> const&a) noexcept:
m_items(a.data()), m_items(a.data()),
m_size(a.size()) { m_size(a.size()) {
} }
template<std::size_t sz, typename Allocator> template<std::size_t sz, typename Allocator>
constexpr SpanView(ox::Vector<T, sz, Allocator> const&v) noexcept: constexpr SpanView(ox::Vector<T, sz, Allocator> const&v) noexcept:
m_items(v.data()), m_items(v.data()),
m_size(v.size()) { m_size(v.size()) {
} }
template<std::size_t sz> template<std::size_t sz>
constexpr SpanView(const T a[sz]) noexcept: constexpr SpanView(const T a[sz]) noexcept:
m_items(a), m_items(a),
m_size(sz) { m_size(sz) {
} }
constexpr SpanView(const T *a, std::size_t sz) noexcept: constexpr SpanView(const T *a, std::size_t sz) noexcept:
m_items(a), m_items(a),
m_size(sz) { m_size(sz) {
} }
constexpr iterator<> begin() noexcept { constexpr iterator<> begin() noexcept {
@@ -105,6 +105,11 @@ class SpanView {
return m_items[i]; return m_items[i];
} }
[[nodiscard]]
constexpr T const*data() const noexcept {
return m_items;
}
[[nodiscard]] [[nodiscard]]
constexpr std::size_t size() const noexcept { constexpr std::size_t size() const noexcept {
return m_size; return m_size;
@@ -216,6 +221,11 @@ class Span {
return m_items[i]; return m_items[i];
} }
[[nodiscard]]
constexpr auto data() const noexcept {
return m_items;
}
[[nodiscard]] [[nodiscard]]
constexpr std::size_t size() const noexcept { constexpr std::size_t size() const noexcept {
return m_size; return m_size;

View File

@@ -15,6 +15,8 @@
#include "bstring.hpp" #include "bstring.hpp"
#include "byteswap.hpp" #include "byteswap.hpp"
#include "concepts.hpp" #include "concepts.hpp"
#include "cstringview.hpp"
#include "cstrops.hpp"
#include "def.hpp" #include "def.hpp"
#include "defer.hpp" #include "defer.hpp"
#include "defines.hpp" #include "defines.hpp"
@@ -37,6 +39,7 @@
#include "stacktrace.hpp" #include "stacktrace.hpp"
#include "stddef.hpp" #include "stddef.hpp"
#include "string.hpp" #include "string.hpp"
#include "stringliteral.hpp"
#include "stringview.hpp" #include "stringview.hpp"
#include "strongint.hpp" #include "strongint.hpp"
#include "strops.hpp" #include "strops.hpp"

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2022 gary@drinkingtea.net * Copyright 2015 - 2023 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a 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,17 +8,15 @@
#pragma once #pragma once
#if defined(OX_USE_STDLIB) #if __has_include(<string>)
#include <string> #include <string>
#endif #endif
#include "algorithm.hpp" #include "algorithm.hpp"
#include "buffer.hpp"
#include "memops.hpp" #include "memops.hpp"
#include "serialize.hpp" #include "serialize.hpp"
#include "stringview.hpp" #include "stringview.hpp"
#include "strops.hpp" #include "strops.hpp"
#include "typetraits.hpp"
#include "vector.hpp" #include "vector.hpp"
namespace ox { namespace ox {
@@ -34,15 +32,15 @@ class BasicString {
constexpr explicit BasicString(std::size_t cap) noexcept; constexpr explicit BasicString(std::size_t cap) noexcept;
constexpr BasicString(const char *str) noexcept; constexpr explicit BasicString(const char *str) noexcept;
constexpr BasicString(const char8_t *str) noexcept; constexpr explicit BasicString(const char8_t *str) noexcept;
constexpr BasicString(const char *str, std::size_t size) noexcept; constexpr BasicString(const char *str, std::size_t size) noexcept;
constexpr BasicString(CRStringView str) noexcept; constexpr explicit BasicString(CRStringView str) noexcept;
constexpr BasicString(const BasicString&) noexcept; constexpr explicit BasicString(BasicString const&) noexcept;
constexpr BasicString(BasicString&&) noexcept; constexpr BasicString(BasicString&&) noexcept;
@@ -120,6 +118,8 @@ class BasicString {
constexpr BasicString &operator=(BasicString &&src) noexcept; constexpr BasicString &operator=(BasicString &&src) noexcept;
constexpr BasicString &operator=(CRStringView src) noexcept;
constexpr BasicString &operator+=(const char *str) noexcept; constexpr BasicString &operator+=(const char *str) noexcept;
constexpr BasicString &operator+=(char *str) noexcept; constexpr BasicString &operator+=(char *str) noexcept;
@@ -130,7 +130,7 @@ class BasicString {
constexpr BasicString &operator+=(StringView src) noexcept; constexpr BasicString &operator+=(StringView src) noexcept;
constexpr BasicString &operator+=(const BasicString &src) noexcept; constexpr BasicString &operator+=(BasicString const&src) noexcept;
constexpr BasicString operator+(const char *str) const noexcept; constexpr BasicString operator+(const char *str) const noexcept;
@@ -140,23 +140,25 @@ class BasicString {
constexpr BasicString operator+(Integer_c auto i) const noexcept; constexpr BasicString operator+(Integer_c auto i) const noexcept;
constexpr BasicString operator+(const BasicString &src) const noexcept; constexpr BasicString operator+(CRStringView src) const noexcept;
constexpr BasicString operator+(BasicString const&src) const noexcept;
constexpr bool operator==(const char *other) const noexcept; constexpr bool operator==(const char *other) const noexcept;
constexpr bool operator==(const OxString_c auto &other) const noexcept; constexpr bool operator==(OxString_c auto const&other) const noexcept;
constexpr bool operator!=(const char *other) const noexcept; constexpr bool operator!=(const char *other) const noexcept;
constexpr bool operator!=(const OxString_c auto &other) const noexcept; constexpr bool operator!=(OxString_c auto const&other) const noexcept;
constexpr bool operator<(const BasicString &other) const noexcept; constexpr bool operator<(BasicString const&other) const noexcept;
constexpr bool operator>(const BasicString &other) const noexcept; constexpr bool operator>(BasicString const&other) const noexcept;
constexpr bool operator<=(const BasicString &other) const noexcept; constexpr bool operator<=(BasicString const&other) const noexcept;
constexpr bool operator>=(const BasicString &other) const noexcept; constexpr bool operator>=(BasicString const&other) const noexcept;
constexpr char operator[](std::size_t i) const noexcept; constexpr char operator[](std::size_t i) const noexcept;
@@ -198,7 +200,7 @@ class BasicString {
return c_str(); return c_str();
} }
#ifdef OX_USE_STDLIB #if __has_include(<string>)
[[nodiscard]] [[nodiscard]]
inline std::string toStdString() const { inline std::string toStdString() const {
return c_str(); return c_str();
@@ -223,19 +225,14 @@ class BasicString {
constexpr std::size_t bytes() const noexcept; constexpr std::size_t bytes() const noexcept;
private: private:
template<std::size_t OtherSize>
constexpr void set(const BasicString<OtherSize> &src) noexcept;
constexpr void set(CRStringView str) noexcept; constexpr void set(CRStringView str) noexcept;
constexpr void set(const char *str) noexcept;
constexpr void set(const char8_t *str) noexcept; constexpr void set(const char8_t *str) noexcept;
}; };
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v>::BasicString() noexcept { constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
if (m_buff.size()) { if (!m_buff.empty()) {
m_buff[0] = 0; m_buff[0] = 0;
} else { } else {
m_buff.push_back(0); m_buff.push_back(0);
@@ -245,14 +242,14 @@ constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) { constexpr BasicString<SmallStringSize_v>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
// GCC complains if you don't do this pretty unnecessary size check // GCC complains if you don't do this pretty unnecessary size check
if (m_buff.size()) { if (!m_buff.empty()) {
m_buff[0] = 0; m_buff[0] = 0;
} }
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept { constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept {
if (m_buff.size()) { if (!m_buff.empty()) {
m_buff[0] = 0; m_buff[0] = 0;
} else { } else {
m_buff.push_back(0); m_buff.push_back(0);
@@ -262,7 +259,7 @@ constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v>::BasicString(const char8_t *str) noexcept { constexpr BasicString<SmallStringSize_v>::BasicString(const char8_t *str) noexcept {
if (m_buff.size()) { if (!m_buff.empty()) {
m_buff[0] = 0; m_buff[0] = 0;
} else { } else {
m_buff.push_back(0); m_buff.push_back(0);
@@ -341,7 +338,15 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(BasicString &&src) noexcept { constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(BasicString &&src) noexcept {
m_buff = std::move(src.m_buff); if (this != &src) {
m_buff = std::move(src.m_buff);
}
return *this;
}
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(CRStringView src) noexcept {
set(src);
return *this; return *this;
} }
@@ -378,7 +383,7 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(const BasicString &src) noexcept { constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(BasicString const&src) noexcept {
oxIgnoreError(append(src.c_str(), src.len())); oxIgnoreError(append(src.c_str(), src.len()));
return *this; return *this;
} }
@@ -415,7 +420,18 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const BasicString &src) const noexcept { constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(CRStringView src) const noexcept {
const std::size_t strLen = src.len();
const auto currentLen = len();
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
cpy.m_buff.resize(m_buff.size() + strLen);
memcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
memcpy(&cpy.m_buff[currentLen], src.data(), strLen + 1);
return cpy;
}
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(BasicString const&src) const noexcept {
const std::size_t strLen = src.len(); const std::size_t strLen = src.len();
const auto currentLen = len(); const auto currentLen = len();
BasicString<SmallStringSize_v> cpy(currentLen + strLen); BasicString<SmallStringSize_v> cpy(currentLen + strLen);
@@ -438,7 +454,7 @@ constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) con
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator==(const OxString_c auto &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator==(OxString_c auto const&other) const noexcept {
return ox::StringView(*this) == ox::StringView(other); return ox::StringView(*this) == ox::StringView(other);
} }
@@ -448,27 +464,27 @@ constexpr bool BasicString<SmallStringSize_v>::operator!=(const char *other) con
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator!=(const OxString_c auto &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator!=(OxString_c auto const&other) const noexcept {
return !operator==(other); return !operator==(other);
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator<(const BasicString &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator<(BasicString const&other) const noexcept {
return ox_strcmp(c_str(), other.c_str()) < 0; return ox_strcmp(c_str(), other.c_str()) < 0;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator>(const BasicString &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator>(BasicString const&other) const noexcept {
return ox_strcmp(c_str(), other.c_str()) > 0; return ox_strcmp(c_str(), other.c_str()) > 0;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator<=(const BasicString &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator<=(BasicString const&other) const noexcept {
return ox_strcmp(c_str(), other.c_str()) < 1; return ox_strcmp(c_str(), other.c_str()) < 1;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator>=(const BasicString &other) const noexcept { constexpr bool BasicString<SmallStringSize_v>::operator>=(BasicString const&other) const noexcept {
return ox_strcmp(c_str(), other.c_str()) > -1; return ox_strcmp(c_str(), other.c_str()) > -1;
} }
@@ -522,31 +538,14 @@ constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
return length; return length;
} }
template<std::size_t SmallStringSize_v>
template<std::size_t OtherSize>
constexpr void BasicString<SmallStringSize_v>::set(const BasicString<OtherSize> &src) noexcept {
std::size_t strBytes = src.bytes();
m_buff.resize(strBytes);
copy_n(src.begin(), strBytes, m_buff.data());
*m_buff.back().value = 0;
}
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr void BasicString<SmallStringSize_v>::set(CRStringView str) noexcept { constexpr void BasicString<SmallStringSize_v>::set(CRStringView str) noexcept {
std::size_t strBytes = str.bytes(); std::size_t const strBytes = str.bytes();
m_buff.resize(strBytes + 1); m_buff.resize(strBytes + 1);
copy_n(str.data(), strBytes, m_buff.data()); copy_n(str.data(), strBytes, m_buff.data());
*m_buff.back().value = 0; *m_buff.back().value = 0;
} }
template<std::size_t SmallStringSize_v>
constexpr void BasicString<SmallStringSize_v>::set(const char *str) noexcept {
std::size_t strBytes = ox_strlen(str) + 1;
m_buff.resize(strBytes);
copy_n(str, strBytes, m_buff.data());
*m_buff.back().value = 0;
}
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept { constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept {
std::size_t strBytes = ox_strlen(str) + 1; std::size_t strBytes = ox_strlen(str) + 1;
@@ -560,6 +559,13 @@ extern template class BasicString<8>;
using String = BasicString<8>; using String = BasicString<8>;
using CRString = String const&; using CRString = String const&;
[[nodiscard]]
constexpr ox::String toString(ox::CRStringView sv) noexcept {
return ox::String(sv);
}
template<typename PlatSpec, std::size_t SmallStringSize_v> template<typename PlatSpec, std::size_t SmallStringSize_v>
[[nodiscard]] [[nodiscard]]
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept { constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {

51
deps/ox/src/ox/std/stringliteral.hpp vendored Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright 2015 - 2022 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "basestringview.hpp"
namespace ox {
/**
* StringLiteral is used for functions that want to ensure that they are taking
* string literals, and not strings outside of the data section of the program
* that might get deleted.
* This type cannot force you to use it correctly, so don't give it something
* that is not a literal.
* If you do this:
* StringLiteral(str.c_str())
* the resulting segfault is on you.
*/
class StringLiteral: public detail::BaseStringView {
public:
constexpr StringLiteral() noexcept = default;
constexpr StringLiteral(StringLiteral const&sv) noexcept = default;
constexpr explicit StringLiteral(std::nullptr_t) noexcept {}
constexpr explicit StringLiteral(const char *str) noexcept: BaseStringView(str) {}
constexpr explicit StringLiteral(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
constexpr auto &operator=(StringLiteral const&other) noexcept {
if (&other != this) {
set(other.data(), other.len());
}
return *this;
}
[[nodiscard]]
constexpr const char *c_str() const noexcept {
return data();
}
};
}

View File

@@ -12,11 +12,8 @@
#include <string_view> #include <string_view>
#endif #endif
#include "bit.hpp" #include "basestringview.hpp"
#include "iterator.hpp" #include "cstrops.hpp"
#include "strops.hpp"
#include "types.hpp"
#include "vector.hpp"
#include "writer.hpp" #include "writer.hpp"
namespace ox { namespace ox {
@@ -27,318 +24,66 @@ class BString;
template<std::size_t buffLen> template<std::size_t buffLen>
class BasicString; class BasicString;
class StringView { class StringView: public detail::BaseStringView {
public:
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
private:
PtrType m_t = nullptr;
std::size_t m_offset = 0;
std::size_t m_max = 0;
public:
constexpr iterator() noexcept = default;
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
m_t = t;
m_offset = offset;
m_max = max;
}
[[nodiscard]]
constexpr auto offset() const noexcept {
return m_offset;
}
constexpr iterator operator+(std::size_t s) const noexcept {
if constexpr(reverse) {
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
} else {
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
}
}
constexpr auto operator-(const iterator &other) const noexcept {
if constexpr(reverse) {
return m_offset + other.m_offset;
} else {
return m_offset - other.m_offset;
}
}
constexpr iterator operator-(std::size_t s) const noexcept {
if constexpr(reverse) {
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
} else {
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
}
}
constexpr iterator &operator+=(std::size_t s) noexcept {
if constexpr(reverse) {
m_offset = max<std::size_t>(m_offset - s, 0);
} else {
m_offset = min(m_offset + s, m_max);
}
return *this;
}
constexpr iterator &operator-=(std::size_t s) noexcept {
if constexpr(reverse) {
m_offset = min(m_offset + s, m_max);
} else {
m_offset = max<std::size_t>(m_offset - s, 0);
}
return *this;
}
constexpr iterator &operator++() noexcept {
return operator+=(1);
}
constexpr iterator &operator--() noexcept {
return operator-=(1);
}
constexpr RefType operator*() const noexcept {
return m_t[m_offset];
}
constexpr RefType operator[](std::size_t s) const noexcept {
return m_t[s];
}
constexpr bool operator<(const iterator &other) const noexcept {
return m_offset < other.m_offset;
}
constexpr bool operator>(const iterator &other) const noexcept {
return m_offset > other.m_offset;
}
constexpr bool operator<=(const iterator &other) const noexcept {
return m_offset <= other.m_offset;
}
constexpr bool operator>=(const iterator &other) const noexcept {
return m_offset >= other.m_offset;
}
constexpr bool operator==(const iterator &other) const noexcept {
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
}
constexpr bool operator!=(const iterator &other) const noexcept {
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
}
};
private:
const char *m_str = nullptr;
std::size_t m_len = 0;
public: public:
constexpr StringView() noexcept = default; constexpr StringView() noexcept = default;
constexpr StringView(const StringView &sv) noexcept = default; constexpr StringView(const StringView &sv) noexcept = default;
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
constexpr StringView(const std::string_view &sv) noexcept: m_str(sv.data()), m_len(sv.size()) {} constexpr StringView(const std::string_view &sv) noexcept: BaseStringView(sv.data(), sv.size()) {}
#endif #endif
template<std::size_t SmallStrSz> constexpr StringView(BaseStringView const&str) noexcept: BaseStringView(str.data(), str.bytes()) {}
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: m_str(str.c_str()), m_len(str.len()) {}
template<std::size_t SmallStrSz> template<std::size_t SmallStrSz>
constexpr StringView(const BString<SmallStrSz> &str) noexcept: m_str(str.c_str()), m_len(str.len()) {} constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
template<std::size_t SmallStrSz>
constexpr StringView(const BString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr StringView(std::nullptr_t) noexcept {} constexpr StringView(std::nullptr_t) noexcept {}
constexpr StringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {} constexpr StringView(const char *str) noexcept: BaseStringView(str) {}
constexpr StringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {} constexpr StringView(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
[[nodiscard]] constexpr auto &operator=(StringView const&other) noexcept {
constexpr iterator<const char&, const char*> begin() const noexcept { if (&other != this) {
return {m_str, 0, m_len}; set(other.data(), other.len());
}
[[nodiscard]]
constexpr iterator<const char&, const char*> end() const noexcept {
return {m_str, m_len, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*> cbegin() const noexcept {
return {m_str, 0, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*> cend() const noexcept {
return {m_str, m_len, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
return {m_str, m_len - 1, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> crend() const noexcept {
return {m_str, MaxValue<std::size_t>, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
return {m_str, m_len - 1, m_len};
}
[[nodiscard]]
constexpr iterator<const char&, const char*, true> rend() const noexcept {
return {m_str, MaxValue<std::size_t>, m_len};
}
[[nodiscard]]
constexpr auto bytes() const noexcept {
return m_len;
}
[[nodiscard]]
constexpr auto len() const noexcept {
return m_len;
}
[[nodiscard]]
constexpr auto *data() const noexcept {
return &m_str[0];
}
[[nodiscard]]
constexpr auto &front() const noexcept {
return m_str[0];
}
[[nodiscard]]
constexpr auto &back() const noexcept {
return m_str[m_len - 1];
}
[[nodiscard]]
constexpr auto substr(std::size_t pos) const noexcept {
if (m_len >= pos) {
return StringView(m_str + pos, m_len - pos);
}
return StringView();
}
[[nodiscard]]
constexpr auto substr(std::size_t start, std::size_t end) const noexcept {
if (m_len >= start && end >= start) {
return StringView(m_str + start, end - start);
}
return StringView();
}
constexpr auto operator[](std::size_t i) const noexcept {
return m_str[i];
}
constexpr ox::StringView &operator=(const StringView &other) noexcept = default;
constexpr auto operator==(const StringView &other) const noexcept {
if (other.len() != len()) {
return false;
}
return ox_strncmp(m_str, other.m_str, len()) == 0;
}
constexpr auto operator<=>(const StringView &str2) const noexcept {
const StringView &str1 = *this;
const auto maxLen = ox::min(str1.len(), str2.len());
const auto a = &str1.front();
const auto b = &str2.front();
for (std::size_t i = 0; i < maxLen && (a[i] || b[i]); ++i) {
if (a[i] < b[i]) {
return -1;
} else if (a[i] > b[i]) {
return 1;
}
}
if (str1.len() > str2.len()) {
return 1;
} else if (str1.len() < str2.len()) {
return -1;
} else {
return 0;
} }
return *this;
} }
}; };
using CRStringView = const StringView&; using CRStringView = const StringView&;
[[nodiscard]] constexpr auto operator==(CRStringView s1, CRStringView s2) noexcept {
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept { if (s2.len() != s1.len()) {
const auto beginningLen = ox::min(beginning.len(), base.len()); return false;
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0; }
return ox_strncmp(s1.data(), s2.data(), s1.len()) == 0;
} }
[[nodiscard]] constexpr auto operator<=>(CRStringView s1, CRStringView s2) noexcept {
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept { const auto maxLen = ox::min(s1.len(), s2.len());
const auto endingLen = ending.len(); const auto a = &s1.front();
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0; const auto b = &s2.front();
} for (std::size_t i = 0; i < maxLen && (a[i] || b[i]); ++i) {
if (a[i] < b[i]) {
constexpr std::size_t find(CRStringView str, char search) noexcept { return -1;
std::size_t i = 0; } else if (a[i] > b[i]) {
for (; i < str.len(); ++i) { return 1;
if (str[i] == search) {
break;
} }
} }
return i; if (s1.len() > s2.len()) {
} return 1;
} else if (s1.len() < s2.len()) {
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept { return -1;
std::size_t i = 0; } else {
for (; i < str.len(); ++i) { return 0;
if (beginsWith(str.substr(i), search)) {
break;
}
} }
return i;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, char del) {
return current.substr(find(current, del) + 1);
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = current.substr(0, next); s.len()) {
out.emplace_back(s);
}
current = current.substr(next);
}
return out;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
return current.substr(find(current, del) + del.len());
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = current.substr(0, next); s.len()) {
out.emplace_back(s);
}
current = current.substr(next);
}
return out;
} }
constexpr auto write(Writer_c auto &writer, ox::CRStringView sv) noexcept { constexpr auto write(Writer_c auto &writer, ox::CRStringView sv) noexcept {
@@ -351,6 +96,22 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
} }
#endif #endif
// Maybe StringView. If T is a string type, MaybeType::type/MaybeSV_t is a
// StringView. This avoids creating unnecessary Strings when taking a
// StringView or C string as a function argument.
template<typename T, bool isStr = isOxString_v<T>>
struct MaybeSV {
using type = T;
};
template<typename T>
struct MaybeSV<T, true> {
using type = ox::StringView;
};
template<typename T>
using MaybeSV_t = typename MaybeSV<T>::type;
} }
constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept { constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept {

View File

@@ -8,126 +8,34 @@
#pragma once #pragma once
#include "cstrops.hpp"
#include "error.hpp" #include "error.hpp"
#include "math.hpp" #include "math.hpp"
#include "stringview.hpp"
#include "types.hpp" #include "types.hpp"
#include "typetraits.hpp" #include "vector.hpp"
#include "writer.hpp" #include "writer.hpp"
template<typename T1, typename T2>
constexpr char *ox_strcpy(T1 dest, T2 src) noexcept {
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
std::size_t i = 0;
while (src[i]) {
dest[i] = static_cast<T1Type>(src[i]);
++i;
}
// set null terminator
dest[i] = 0;
return dest;
}
template<typename T1, typename T2>
constexpr char *ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
std::size_t i = 0;
while (i < maxLen && src[i]) {
dest[i] = static_cast<T1Type>(src[i]);
++i;
}
// set null terminator
dest[i] = 0;
return dest;
}
[[nodiscard]]
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
std::size_t len = 0;
for (; len < maxLen && str1[len]; len++);
return len;
}
template<typename T>
[[nodiscard]]
constexpr auto ox_strlen(T str1) noexcept {
std::size_t len = 0;
for (; str1[len]; len++);
return len;
}
template<typename T1, typename T2>
[[nodiscard]]
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
auto retval = 0;
auto i = 0u;
while (str1[i] || str2[i]) {
if (str1[i] < str2[i]) {
retval = -1;
break;
} else if (str1[i] > str2[i]) {
retval = 1;
break;
}
i++;
}
return retval;
}
template<typename T1, typename T2>
[[nodiscard]]
constexpr int ox_strncmp(T1 str1, T2 str2, const std::size_t maxLen) noexcept {
auto retval = 0;
std::size_t i = 0;
while (i < maxLen && (str1[i] || str2[i])) {
if (str1[i] < str2[i]) {
retval = -1;
break;
} else if (str1[i] > str2[i]) {
retval = 1;
break;
}
i++;
}
return retval;
}
[[nodiscard]]
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
for (std::size_t i = 0; i <= maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
[[nodiscard]]
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
for (std::size_t i = 0; i < maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
[[nodiscard]]
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
int retval = -1;
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
if (str[i] == character) {
retval = static_cast<int>(i);
}
}
return retval;
}
namespace ox { namespace ox {
template<OxString_c Str>
[[nodiscard]]
constexpr ox::StringView substr(Str const&str, std::size_t pos) noexcept {
if (str.len() >= pos) {
return Str(str.data() + pos, str.len() - pos);
}
return Str();
}
template<OxString_c Str>
[[nodiscard]]
constexpr ox::StringView substr(Str const&str, std::size_t start, std::size_t end) noexcept {
if (str.len() >= start && end >= start) {
return Str(str.data() + start, end - start);
}
return Str();
}
template<typename Integer> template<typename Integer>
constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept { constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
if (v) { if (v) {
@@ -160,38 +68,79 @@ constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
return {}; return {};
} }
[[nodiscard]]
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
const auto beginningLen = ox::min(beginning.len(), base.len());
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
}
[[nodiscard]]
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
const auto endingLen = ending.len();
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
}
constexpr std::size_t find(CRStringView str, char search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
if (str[i] == search) {
break;
}
}
return i;
}
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
if (beginsWith(substr(str, i), search)) {
break;
}
}
return i;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, char del) {
return substr(current, find(current, del) + 1);
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = substr(current, 0, next); s.len()) {
out.emplace_back(s);
}
current = substr(current, next);
}
return out;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
return substr(current, find(current, del) + del.len());
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = substr(current, 0, next); s.len()) {
out.emplace_back(s);
}
current = substr(current, next);
}
return out;
}
[[nodiscard]]
constexpr ox::Result<std::size_t> lastIndexOf(ox::CRStringView str, int character) noexcept {
ox::Result<std::size_t> retval = OxError(1, "Character not found");
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
if (str[static_cast<std::size_t>(i)] == character) {
retval = static_cast<std::size_t>(i);
}
}
return retval;
} }
template<typename Integer, typename T>
constexpr T ox_itoa(Integer v, T str) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
str[static_cast<std::size_t>(it)] = '-';
it++;
}
while (mod) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
ox::ResizedInt_t<Integer, 64> start = '0';
if (digit >= 10) {
start = 'a';
digit -= 10;
}
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
it++;
}
}
str[static_cast<std::size_t>(it)] = 0;
} else {
// 0 is a special case
str[0] = '0';
str[1] = 0;
}
return str;
} }

View File

@@ -12,7 +12,7 @@
#include <ox/std/uuid.hpp> #include <ox/std/uuid.hpp>
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
static std::map<ox::String, ox::Error(*)()> tests = { static std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
"malloc", "malloc",
[] { [] {
@@ -105,6 +105,10 @@ static std::map<ox::String, ox::Error(*)()> tests = {
oxAssert(endsWith(str, "df"), "String endsWith is broken"); oxAssert(endsWith(str, "df"), "String endsWith is broken");
oxAssert(!endsWith(str, "awefawe"), "String endsWith is broken"); oxAssert(!endsWith(str, "awefawe"), "String endsWith is broken");
oxAssert(!endsWith(str, "eu"), "String endsWith is broken"); oxAssert(!endsWith(str, "eu"), "String endsWith is broken");
oxAssert(ox::StringView("Write") != ox::String(""), "String / StringView comparison broken");
oxAssert(ox::String("Write") != ox::StringView(""), "String / StringView comparison broken");
oxAssert(ox::String("Write") == ox::StringView("Write"), "String / StringView comparison broken");
oxAssert(ox::String(ox::StringView("Write")) == ox::StringView("Write"), "String / StringView comparison broken");
return OxError(0); return OxError(0);
} }
}, },
@@ -113,6 +117,7 @@ static std::map<ox::String, ox::Error(*)()> tests = {
[] { [] {
ox::Vector<int> v; ox::Vector<int> v;
oxAssert(v.size() == 0, "Initial Vector size not 0"); oxAssert(v.size() == 0, "Initial Vector size not 0");
oxAssert(v.empty(), "Vector::empty() is broken");
auto insertTest = [&v](int val, [[maybe_unused]] std::size_t size) { auto insertTest = [&v](int val, [[maybe_unused]] std::size_t size) {
v.push_back(val); v.push_back(val);
oxReturnError(OxError(v.size() != size, "Vector size incorrect")); oxReturnError(OxError(v.size() != size, "Vector size incorrect"));
@@ -168,7 +173,7 @@ static std::map<ox::String, ox::Error(*)()> tests = {
oxAssert(w.write("aoeu", 4), "write failed"); oxAssert(w.write("aoeu", 4), "write failed");
oxExpect(b.size(), 8u); oxExpect(b.size(), 8u);
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu"); oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu");
ox::StringView qwerty = "qwerty"; ox::StringView constexpr qwerty = "qwerty";
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed"); oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
oxExpect(b.size(), 14u); oxExpect(b.size(), 14u);
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty"); oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
@@ -309,12 +314,14 @@ static std::map<ox::String, ox::Error(*)()> tests = {
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {
if (argc > 1) { if (argc < 2) {
auto testName = args[1]; oxError("Must specify test to run");
if (tests.find(testName) != tests.end()) { }
oxAssert(tests[testName](), "Test returned Error"); auto const testName = args[1];
return 0; auto const func = tests.find(testName);
} if (func != tests.end()) {
oxAssert(func->second(), "Test returned Error");
return 0;
} }
return -1; return -1;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2022 gary@drinkingtea.net * Copyright 2015 - 2023 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a 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,10 +39,10 @@ enum class MsgId: char {
struct TraceMsgRcv { struct TraceMsgRcv {
static constexpr auto TypeName = "net.drinkingtea.ox.trace.TraceMsg"; static constexpr auto TypeName = "net.drinkingtea.ox.trace.TraceMsg";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
BasicString<50> file = ""; BasicString<50> file{""};
int line = 0; int line = 0;
uint64_t time = 0; uint64_t time = 0;
BasicString<50> ch = ""; BasicString<50> ch{""};
BasicString<100> msg; BasicString<100> msg;
}; };
@@ -131,7 +131,7 @@ class OutStream {
m_msg.file = file; m_msg.file = file;
m_msg.line = line; m_msg.line = line;
m_msg.ch = ch; m_msg.ch = ch;
m_msg.msg = msg; m_msg.msg = BasicString<100>(msg);
} }
constexpr OutStream(const char *file, int line, const char *ch, const char *msg = "") noexcept { constexpr OutStream(const char *file, int line, const char *ch, const char *msg = "") noexcept {
@@ -141,39 +141,22 @@ class OutStream {
m_msg.msg = msg; m_msg.msg = msg;
} }
#ifdef OX_USE_STDLIB
template<std::size_t fmtSegmentCnt, typename ...Args> template<std::size_t fmtSegmentCnt, typename ...Args>
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, std::array<detail::FmtArg, fmtSegmentCnt - 1> elements) noexcept { constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args const&...elements) noexcept {
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format."); static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
m_msg.file = file; m_msg.file = file;
m_msg.line = line; m_msg.line = line;
m_msg.ch = ch; m_msg.ch = ch;
const auto &firstSegment = fmtSegments.segments[0]; const auto &firstSegment = fmtSegments.segments[0];
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length)); oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
//const detail::FmtArg elements[sizeof...(args)] = {args...}; //const detail::FmtArg elements[sizeof...(args)] = {args...};
for (auto i = 0u; i < fmtSegments.size - 1; ++i) { for (size_t i = 0; auto const&e : std::initializer_list<detail::FmtArg>{elements...}) {
m_msg.msg += elements[i].out; m_msg.msg += e.out;
const auto &s = fmtSegments.segments[i + 1]; const auto &s = fmtSegments.segments[i + 1];
oxIgnoreError(m_msg.msg.append(s.str, s.length)); oxIgnoreError(m_msg.msg.append(s.str, s.length));
++i;
} }
} }
#else
template<std::size_t fmtSegmentCnt, typename ...Args>
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args... args) noexcept {
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
m_msg.file = file;
m_msg.line = line;
m_msg.ch = ch;
const auto &firstSegment = fmtSegments.segments[0];
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
const detail::FmtArg elements[sizeof...(args)] = {args...};
for (auto i = 0u; i < fmtSegments.size - 1; ++i) {
m_msg.msg += elements[i].out;
const auto &s = fmtSegments.segments[i + 1];
oxIgnoreError(m_msg.msg.append(s.str, s.length));
}
}
#endif
inline ~OutStream() noexcept { inline ~OutStream() noexcept {
oxTraceHook(m_msg.file, m_msg.line, m_msg.ch, m_msg.msg.c_str()); oxTraceHook(m_msg.file, m_msg.line, m_msg.ch, m_msg.msg.c_str());
@@ -257,15 +240,10 @@ class NullStream {
constexpr NullStream(const char*, int, const char*, const char* = "") noexcept { constexpr NullStream(const char*, int, const char*, const char* = "") noexcept {
} }
#ifdef OX_USE_STDLIB
template<std::size_t fmtSegmentCnt, typename ...Args> template<std::size_t fmtSegmentCnt, typename ...Args>
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, std::array<detail::FmtArg, fmtSegmentCnt - 1>) noexcept { constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args const&...elements) noexcept {
static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
} }
#else
template<std::size_t fmtSegmentCnt, typename ...Args>
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args...) noexcept {
}
#endif
template<typename T> template<typename T>
constexpr const NullStream &operator<<(const T&) const noexcept { constexpr const NullStream &operator<<(const T&) const noexcept {

View File

@@ -57,6 +57,8 @@ typedef uint32_t uintptr_t;
#endif #endif
using uint_t = unsigned;
namespace ox { namespace ox {
/** /**
@@ -157,6 +159,8 @@ struct ResizedInt<T, bits, false> {
template<typename T, std::size_t bits> template<typename T, std::size_t bits>
using ResizedInt_t = typename ResizedInt<T, bits>::type; using ResizedInt_t = typename ResizedInt<T, bits>::type;
using ssize_t = Signed<std::size_t>;
} }

View File

@@ -266,4 +266,48 @@ constexpr bool is_move_constructible(bool) {
template<class T> template<class T>
constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0); constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0);
// is String?
template<std::size_t SmallStringSize>
class BasicString;
template<std::size_t sz>
class BString;
class CStringView;
class StringLiteral;
class StringView;
namespace detail {
constexpr auto isOxString(const auto*) noexcept {
return false;
}
template<std::size_t sz>
constexpr auto isOxString(const BasicString<sz>*) noexcept {
return true;
}
template<std::size_t sz>
constexpr auto isOxString(const BString<sz>*) noexcept {
return true;
}
constexpr auto isOxString(const CStringView*) noexcept {
return true;
}
constexpr auto isOxString(const StringLiteral*) noexcept {
return true;
}
constexpr auto isOxString(const StringView*) noexcept {
return true;
}
}
template<typename T>
constexpr auto isOxString_v = detail::isOxString(static_cast<T*>(nullptr));
} }

View File

@@ -12,6 +12,12 @@
namespace ox { namespace ox {
struct in_place_t {
explicit constexpr in_place_t() = default;
};
inline constexpr ox::in_place_t in_place;
template<class T> template<class T>
constexpr T &&forward(remove_reference_t<T> &t) noexcept { constexpr T &&forward(remove_reference_t<T> &t) noexcept {
return static_cast<T&&>(t); return static_cast<T&&>(t);

View File

@@ -10,11 +10,10 @@
#include "array.hpp" #include "array.hpp"
#include "bstring.hpp" #include "bstring.hpp"
#include "buffer.hpp"
#include "random.hpp" #include "random.hpp"
#include "ranges.hpp" #include "ranges.hpp"
#include "stringview.hpp" #include "stringview.hpp"
#include "strops.hpp"
#include "trace.hpp"
namespace ox { namespace ox {
@@ -128,12 +127,12 @@ class UUID {
} }
UUID out; UUID out;
auto valueI = 0u; auto valueI = 0u;
for (auto i = 0u; i < s.len();) { for (size_t i = 0; i < s.len();) {
if (s[i] == '-') { if (s[i] == '-') {
++i; ++i;
continue; continue;
} }
const auto seg = s.substr(i, i + 2); const auto seg = substr(s, i, i + 2);
if (seg.len() != 2) { if (seg.len() != 2) {
return OxError(1, "Invalid UUID"); return OxError(1, "Invalid UUID");
} }

View File

@@ -16,7 +16,7 @@
#include "iterator.hpp" #include "iterator.hpp"
#include "math.hpp" #include "math.hpp"
#include "memory.hpp" #include "memory.hpp"
#include "new.hpp" #include "stringview.hpp"
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"
@@ -254,12 +254,12 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
} }
[[nodiscard]] [[nodiscard]]
constexpr bool contains(const T&) const noexcept(useNoexcept); constexpr bool contains(MaybeSV_t<T> const&) const noexcept(useNoexcept);
constexpr iterator<T&, T*, false> insert( constexpr iterator<T&, T*, false> insert(
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept); std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept);
constexpr iterator<T&, T*, false> insert(std::size_t pos, const T &val) noexcept(useNoexcept); constexpr iterator<T&, T*, false> insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept);
template<typename... Args> template<typename... Args>
constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept); constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept);
@@ -267,7 +267,9 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
template<typename... Args> template<typename... Args>
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept); constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
constexpr void push_back(const T &item) noexcept(useNoexcept); constexpr void push_back(T &&item) noexcept(useNoexcept);
constexpr void push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept);
constexpr void pop_back() noexcept(useNoexcept); constexpr void pop_back() noexcept(useNoexcept);
@@ -324,7 +326,7 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::size_t size) noexce
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept { constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept {
for (auto &item : list) { for (auto &item : list) {
emplace_back(item); emplace_back(std::move(item));
} }
} }
@@ -484,7 +486,7 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) n
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const noexcept(useNoexcept) { constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeSV_t<T> const&v) const noexcept(useNoexcept) {
for (std::size_t i = 0; i < m_size; i++) { for (std::size_t i = 0; i < m_size; i++) {
if (m_items[i] == v) { if (m_items[i] == v) {
return true; return true;
@@ -496,7 +498,7 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false> constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
Vector<T, SmallVectorSize, Allocator>::insert( Vector<T, SmallVectorSize, Allocator>::insert(
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept) { std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
if (m_size + cnt > m_cap) { if (m_size + cnt > m_cap) {
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt); reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
if (pos < m_size) { if (pos < m_size) {
@@ -524,7 +526,7 @@ Vector<T, SmallVectorSize, Allocator>::insert(
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false> constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) noexcept(useNoexcept) { Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
if (m_size == m_cap) { if (m_size == m_cap) {
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos); reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
if (pos < m_size) { if (pos < m_size) {
@@ -581,7 +583,16 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(const T &item) noexcept(useNoexcept) { constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialCap);
}
std::construct_at(&m_items[m_size], std::move(item));
++m_size;
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept) {
if (m_size == m_cap) { if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialCap); reserve(m_cap ? m_cap * 2 : initialCap);
} }

View File

@@ -1,3 +1,5 @@
project(TeaGBA ASM CXX)
add_subdirectory(src) add_subdirectory(src)
install( install(

View File

@@ -49,7 +49,7 @@ using BgCtl = uint16_t;
#define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e) #define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e)
[[nodiscard]] [[nodiscard]]
inline auto &regBgCtl(auto bgIdx) noexcept { inline volatile BgCtl &regBgCtl(uintptr_t bgIdx) noexcept {
return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx); return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx);
} }
@@ -60,7 +60,7 @@ inline auto &regBgCtl(auto bgIdx) noexcept {
#define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c) #define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c)
[[nodiscard]] [[nodiscard]]
inline volatile auto &regBgHofs(auto bgIdx) noexcept { inline volatile uint32_t &regBgHofs(auto bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx); return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx);
} }
@@ -71,7 +71,7 @@ inline volatile auto &regBgHofs(auto bgIdx) noexcept {
#define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e) #define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e)
[[nodiscard]] [[nodiscard]]
inline volatile auto &regBgVofs(auto bgIdx) noexcept { inline volatile uint32_t &regBgVofs(auto bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx); return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx);
} }

View File

@@ -29,15 +29,13 @@ enum DispCtl {
}; };
struct OX_ALIGN8 GbaSpriteAttrUpdate { struct OX_ALIGN8 GbaSpriteAttrUpdate {
uint16_t attr0 = 0; uint16_t attr0 = 0;
uint16_t attr1 = 0; uint16_t attr1 = 0;
uint16_t attr2 = 0; uint16_t attr2 = 0;
uint16_t idx = 0; uint16_t idx = 0;
}; };
extern volatile uint16_t g_spriteUpdates; GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept;
extern ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept; void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;

View File

@@ -8,8 +8,8 @@
namespace teagba { namespace teagba {
inline auto bgSetSbb(volatile BgCtl *bgCtl, unsigned sbb) noexcept { inline auto bgSetSbb(volatile BgCtl &bgCtl, unsigned sbb) noexcept {
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b11111'0000'0000u) | static_cast<BgCtl>(sbb << 8); bgCtl = static_cast<BgCtl>(bgCtl & ~0b11111'0000'0000u) | static_cast<BgCtl>(sbb << 8);
} }
[[nodiscard]] [[nodiscard]]
@@ -17,14 +17,9 @@ constexpr unsigned bgPri(BgCtl bgCtl) noexcept {
return bgCtl & 1; return bgCtl & 1;
} }
[[nodiscard]] inline auto bgSetPri(volatile BgCtl &bgCtl, unsigned pri) noexcept {
inline auto bgPri(const volatile BgCtl *bgCtl) noexcept {
return bgPri(*bgCtl);
}
inline auto bgSetPri(volatile BgCtl *bgCtl, unsigned pri) noexcept {
pri = pri & 0b1; pri = pri & 0b1;
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b1u) | static_cast<BgCtl>(pri << 0); bgCtl = static_cast<BgCtl>(bgCtl & ~0b1u) | static_cast<BgCtl>(pri << 0);
} }
[[nodiscard]] [[nodiscard]]
@@ -32,17 +27,12 @@ constexpr unsigned bgBpp(BgCtl bgCtl) noexcept {
return ((bgCtl >> 7) & 1) ? 8 : 4; return ((bgCtl >> 7) & 1) ? 8 : 4;
} }
[[nodiscard]] inline auto bgSetBpp(volatile BgCtl &bgCtl, unsigned bpp) noexcept {
inline auto bgBpp(const volatile BgCtl *bgCtl) noexcept {
return bgBpp(*bgCtl);
}
inline auto bgSetBpp(volatile BgCtl *bgCtl, unsigned bpp) noexcept {
constexpr auto Bpp8 = 1 << 7; constexpr auto Bpp8 = 1 << 7;
if (bpp == 4) { if (bpp == 4) {
*bgCtl = *bgCtl | ((*bgCtl | Bpp8) ^ Bpp8); // set to use 4 bits per pixel bgCtl = bgCtl | ((bgCtl | Bpp8) ^ Bpp8); // set to use 4 bits per pixel
} else { } else {
*bgCtl = *bgCtl | Bpp8; // set to use 8 bits per pixel bgCtl = bgCtl | Bpp8; // set to use 8 bits per pixel
} }
} }
@@ -51,19 +41,14 @@ constexpr auto bgCbb(BgCtl bgCtl) noexcept {
return (bgCtl >> 2) & 0b11u; return (bgCtl >> 2) & 0b11u;
} }
[[nodiscard]] inline auto bgSetCbb(volatile BgCtl &bgCtl, unsigned cbb) noexcept {
inline auto bgCbb(const volatile BgCtl *bgCtl) noexcept {
return bgCbb(*bgCtl);
}
inline auto bgSetCbb(volatile BgCtl *bgCtl, unsigned cbb) noexcept {
cbb = cbb & 0b11; cbb = cbb & 0b11;
*bgCtl = static_cast<BgCtl>(*bgCtl & ~0b1100u) | static_cast<BgCtl>(cbb << 2); bgCtl = static_cast<BgCtl>(bgCtl & ~0b1100u) | static_cast<BgCtl>(cbb << 2);
} }
constexpr void iterateBgCtl(auto cb) noexcept { constexpr void iterateBgCtl(auto cb) noexcept {
for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) { for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) {
cb(bgCtl); cb(*bgCtl);
} }
} }

View File

@@ -6,7 +6,7 @@ add_library(
gfx.cpp gfx.cpp
) )
if(TURBINE_BUILD_TYPE STREQUAL "GBA") if(BUILDCORE_TARGET STREQUAL "gba")
set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm) set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm)
target_sources( target_sources(
TeaGBA PRIVATE TeaGBA PRIVATE

View File

@@ -10,30 +10,22 @@
namespace teagba { namespace teagba {
volatile uint16_t g_spriteUpdates = 0; static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept {
return g_spriteBuffer[i];
}
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept { void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
// block until g_spriteUpdates is less than buffer len
if (g_spriteUpdates >= g_spriteBuffer.size()) [[unlikely]] {
teagba_vblankintrwait();
}
const auto ie = REG_IE; // disable vblank interrupt handler const auto ie = REG_IE; // disable vblank interrupt handler
REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler
const auto updateCnt = g_spriteUpdates; g_spriteBuffer[upd.idx] = upd;
g_spriteBuffer[updateCnt] = upd;
g_spriteUpdates = updateCnt + 1;
REG_IE = ie; // enable vblank interrupt handler REG_IE = ie; // enable vblank interrupt handler
} }
void applySpriteUpdates() noexcept { void applySpriteUpdates() noexcept {
// copy g_spriteUpdates to allow it to use a register instead of reading for (auto const&oa : g_spriteBuffer) {
// from memory every iteration of the loop, needed because g_spriteUpdates MEM_OAM[oa.idx] = std::bit_cast<uint64_t>(oa);
// is volatile
const unsigned updates = g_spriteUpdates;
for (unsigned i = 0; i < updates; ++i) {
const auto &oa = g_spriteBuffer[i];
MEM_OAM[oa.idx] = *reinterpret_cast<const uint64_t*>(&oa);
} }
} }

View File

@@ -21,29 +21,59 @@ All components have a platform indicator next to them:
(P-) - PC (P-) - PC
* Nostalgia * Nostalgia
* core - platform abstraction and user I/O (PG) * modules
* gba - GBA implementation (-G) * core - graphics system for Nostalgia (PG)
* glfw - GLFW implementation (P-) * gba - GBA implementation (PG)
* userland - common things needed by all non-bare-metal implementations (P-) * opengl - OpenGL implementation (P-)
* studio - studio plugin for core (P-) * studio - studio plugin for core (P-)
* geo - geometry types (PG) * keel - keel plugin for core (PG)
* glutils - OpenGL helpers (P-) * scene - defines & processes map data (PG)
* studio - studio plugin for scene (P-)
* keel - keel plugin for scene (PG)
* player - plays the games (PG) * player - plays the games (PG)
* studio - makes the games (P-) * studio - makes the games (P-)
* tools - command line tools (P-) * tools - command line tools (P-)
* pack - packs a studio project directory into an OxFS file (P-) * pack - packs a studio project directory into an OxFS file (P-)
* world - defines processes map data (PG) * Olympic
* studio - studio plugin for world (P-) * Applib - Library for creating apps as libraries that injects Keel and Studio modules
* Keel - asset management system (PG)
* Studio - where most of the studio code lives as library (P-)
* applib - used for per project studio executables
* modlib - used for studio modules to interact with studio
* Turbine - platform abstraction and user I/O (PG)
* gba - GBA implementation (PG)
* glfw - GLFW implementation (P-)
* deps - project dependencies * deps - project dependencies
* Ox - Library of things useful for portable bare metal and userland code. Not really that external... * Ox - Library of things useful for portable bare metal and userland code. Not really that external...
* clargs - Command Line Args processing (PG) * clargs - Command Line Args processing (PG)
* claw - Reads and writes Metal or Organic Claw with header to indicate which * claw - Reads and writes Metal or Organic Claw with header to indicate which
* event - Qt-like signal system
* fs - file system (PG) * fs - file system (PG)
* logconn - connects logging to Bullock (P-)
* mc - Metal Claw serialization, builds on model (PG) * mc - Metal Claw serialization, builds on model (PG)
* oc - Organic Claw serialization (wrapper around JsonCpp), builds on model (P-) * oc - Organic Claw serialization (wrapper around JsonCpp), builds on model (P-)
* model - Data structure modelling (PG) * model - Data structure modelling (PG)
* preloader - library for handling preloading of data (PG)
* std - Standard-ish Library with a lot missing and some things added (PG) * std - Standard-ish Library with a lot missing and some things added (PG)
* GbaStartup - GBA assembly startup code, mostly pulled from devkitPro under MPL 2.0 (-G) * GlUtils - OpenGL helpers (P-)
* teagba - GBA assembly startup code (mostly pulled from devkitPro under MPL
2.0), and custom GBA hardware interop code (-G)
## Platform Notes
### GBA
The GBA has two major resources for learning about its hardware:
* [Tonc](https://www.coranac.com/tonc/text/toc.htm) - This is basically a short
book on the GBA and low level development.
* [GBATEK](https://rust-console.github.io/gbatek-gbaonly/) - This is a more
concise resource that mostly tells about memory ranges and registers.
#### Graphics
* Background Palette: 256 colors
* Sprite Palette: 256 colors
## Code Base Conventions ## Code Base Conventions
@@ -473,17 +503,14 @@ implements a superset of JSON.
OrganicClaw requires support for 64 bit integers, whereas normal JSON OrganicClaw requires support for 64 bit integers, whereas normal JSON
technically does not. technically does not.
These formats do not currently support floats.
There is also a wrapper format called Claw that provides a header at the There is also a wrapper format called Claw that provides a header at the
beginning of the file and can dynamically switch between the two depending on beginning of the file and can dynamically switch between the two depending on
what the header says is present. what the header says is present.
The Claw header also includes information about the type and type version of The Claw header also includes information about the type and type version of
the data. the data.
Except when the data is exported for loading on the GBA, Claw is always used as
a wrapper around the bare formats.
These formats do not currently support ```float```s.
Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;``` Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;```
That reads: That reads:
@@ -492,6 +519,9 @@ That reads:
* Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette * Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette
* Type version is 1 * Type version is 1
Except when the data is exported for loading on the GBA, Claw is always used as
a wrapper around the bare formats.
#### Metal Claw Example #### Metal Claw Example
##### Read ##### Read
@@ -526,7 +556,7 @@ ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette *pal) noexcept {
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(buffer.data(), buffer.size(), pal, &sz)); oxReturnError(ox::writeMC(buffer.data(), buffer.size(), pal, &sz));
buffer.resize(sz); buffer.resize(sz);
return std::move(buffer); return buffer;
} }
ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette *pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette *pal) noexcept {
@@ -564,7 +594,7 @@ ox::Result<NostalgiaPalette> loadPalette3(const Buffer &buff) noexcept {
ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette *pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette *pal) noexcept {
ox::Buffer buffer(ox::units::MB); ox::Buffer buffer(ox::units::MB);
oxReturnError(ox::writeOC(buffer.data(), buffer.size(), pal)); oxReturnError(ox::writeOC(buffer.data(), buffer.size(), pal));
return std::move(buffer); return buffer;
} }
ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette *pal) noexcept { ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette *pal) noexcept {

View File

@@ -1,45 +0,0 @@
pipeline {
agent {
label 'gba'
}
stages {
stage('Environment') {
steps {
load 'jenkins/shared/env.gy'
sh 'make conan-config'
sh 'make conan'
}
}
stage('Build Tools Debug') {
steps {
sh 'make purge configure-debug'
sh 'make install'
}
}
stage('Build GBA Debug') {
steps {
sh 'make configure-gba-debug'
sh 'make'
sh 'make pkg-gba'
}
}
stage('Build Tools Release') {
steps {
sh 'make purge configure-release'
sh 'make install'
}
}
stage('Build GBA Release') {
steps {
sh 'make configure-gba'
sh 'make'
sh 'make pkg-gba'
}
}
}
post {
always {
archiveArtifacts artifacts: 'nostalgia.gba', fingerprint: true
}
}
}

View File

@@ -1,47 +0,0 @@
pipeline {
agent {
label 'linux-x86_64'
}
stages {
stage('Environment') {
steps {
load 'jenkins/shared/env.gy'
sh 'make conan-config'
sh 'make conan'
}
}
stage('Build Asan') {
steps {
sh 'make purge configure-asan'
sh 'make'
}
}
stage('Test Asan') {
steps {
sh 'make test'
}
}
stage('Build Debug') {
steps {
sh 'make purge configure-debug'
sh 'make'
}
}
stage('Test Debug') {
steps {
sh 'make test'
}
}
stage('Build Release') {
steps {
sh 'make purge configure-release'
sh 'make'
}
}
stage('Test Release') {
steps {
sh 'make test'
}
}
}
}

View File

@@ -1,47 +0,0 @@
pipeline {
agent {
label 'mac-x86_64'
}
stages {
stage('Environment') {
steps {
load 'jenkins/shared/env.gy'
sh 'make conan-config'
sh 'make conan'
}
}
stage('Build Asan') {
steps {
sh 'make purge configure-asan'
sh 'make'
}
}
stage('Test Asan') {
steps {
sh 'make test'
}
}
stage('Build Debug') {
steps {
sh 'make purge configure-debug'
sh 'make'
}
}
stage('Test Debug') {
steps {
sh 'make test'
}
}
stage('Build Release') {
steps {
sh 'make purge configure-release'
sh 'make'
}
}
stage('Test Release') {
steps {
sh 'make test'
}
}
}
}

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