Compare commits

...

831 Commits

Author SHA1 Message Date
257e857116 [ox/std] Add move operator to String 2020-06-20 02:58:32 -05:00
0035faa416 [ox/std] Make Vector::push_back use copy constructor instead of copy assign 2020-06-20 02:58:20 -05:00
5c34c26080 [ox/mc] Fix string allocation size 2020-06-20 02:55:25 -05:00
b6f8c9e242 [ox] Add HashMap<String, T> to serializaton handlers 2020-06-19 07:34:04 -05:00
0698353fbf [nostalgia/core/studio] Fix TileSheetEditor crash on save after increasing grid size 2020-06-19 01:41:42 -05:00
9576f78abf [ox/model] Fix TypeDescWriter NameCatcher to have opType of WriteDefinition 2020-06-17 06:44:31 -05:00
7b07edd9e4 [ox/std] Rename is_signed to is_signed_v 2020-06-17 06:36:26 -05:00
a5b01bb0d7 [ox/fs] Cleanup 2020-06-17 01:53:35 -05:00
1c5fed05bf [ox/std] Make ox_strncmp a template 2020-06-17 01:52:28 -05:00
d4983cf3c6 [nostalgia/studio] Replace garbage last character with \n 2020-06-17 01:43:10 -05:00
fc246ee396 [nostalgia/pack] Make pack ignore /.nostalgia 2020-06-17 01:36:01 -05:00
167e470091 [nostalgia/studio] Remove garbage last character in OC files 2020-06-16 05:43:44 -05:00
dae719f78a [nostalgia/studio] Make OxFS tree view hide files starting with . 2020-06-16 05:01:49 -05:00
df96407669 [nostalgia/studio] Make Project write out type data with data 2020-06-16 04:42:18 -05:00
17762b40b7 [ox/oc] Fix write to ignore null objects passed in 2020-06-16 04:41:43 -05:00
4f4ec089fd [ox/model] Fix model descriptor writing to handle Vector, etc. 2020-06-16 04:40:43 -05:00
f58c658be1 [ox/fs] Make PassthroughFS mkdir pass mkdir -p on existing directory 2020-06-16 04:39:15 -05:00
e92e980fde [ox/std] Change toError(ox::ValErr<T>) to toError(const ox::ValErr<T>&) 2020-06-16 00:45:24 -05:00
71b6c72c46 [ox/model] Add opType method to TypeDescWriter 2020-06-16 00:23:03 -05:00
da75443d4c [nostalgia] Move conan install's --build missing to correct position 2020-06-15 23:41:33 -05:00
a45692fa4c [nostalgia/sample_project] Update project files to have new type IDs 2020-06-15 23:38:06 -05:00
112c2c4212 [ox/fs] Change Claw type IDs to domain based namespaces 2020-06-15 23:16:34 -05:00
f8fb458e32 [nostalgia] Change Claw type IDs to domain based namespaces 2020-06-15 23:15:49 -05:00
20f4d50ad6 [ox/std] Add missing includes to CMake install and std.hpp 2020-06-15 04:54:52 -05:00
0eaf54bd22 [nostalgia/tools/pack] Cleanup debug code 2020-06-15 04:44:07 -05:00
978dd70770 [nostalgia] Switch tools to use Claw 2020-06-15 01:40:59 -05:00
9a49761c01 [nostalgia/core/sdl] Switch from MC to Claw 2020-06-15 01:38:28 -05:00
880e6e49d6 [nostalgia/fs] Fix Directory to write back out as a Directory 2020-06-15 01:34:48 -05:00
4a221e52db [ox/claw] Add strip header function 2020-06-15 01:34:22 -05:00
4f1593a0ed [nostalgia] Make gba-pkg's project an argument 2020-06-14 19:02:38 -05:00
18166f6123 [nostalgia/jenkins/gba] Add artifact 2020-06-13 22:32:34 -05:00
228b6dd031 [nostalgia] Fix DEVKITPRO bin paths for Jenkins 2020-06-13 04:24:49 -05:00
a1a0abe83b [nostalgia] Make setup-build only overwrite current_build for native builds 2020-06-13 04:18:37 -05:00
77ece05bf1 [nostalgia/jenkins] Fix GBA Jenkinsfile 2020-06-13 04:15:04 -05:00
9e624619b3 [nostalgia/jenkins] Add Jenkinsfile for GBA builder 2020-06-13 04:08:59 -05:00
5c5c62dc55 [nostalgia/core/studio] Fix TileSheetEditor not to display context menu when right click is not on tile 2020-06-13 03:37:38 -05:00
53358d2e03 [nostaliga/sample_project] Update to use Claw instead of bare MetalClaw 2020-06-13 03:36:19 -05:00
c178a2273b [ox/std] Fix macOS build 2020-06-05 19:47:29 -05:00
f86d0e697a [nostalgia/studio] Replace deprecated call for Qt 5.15 2020-06-05 19:42:37 -05:00
4d806021d0 [ox/claw] Fix TypeInfoCatcher to fit model handler API 2020-05-29 20:24:09 -05:00
98a0c42040 [nostalgia/core/gba][ox/std] Move heap manager from NostalgiaCore to OxStd 2020-05-29 19:44:10 -05:00
0eb33f823c [nostalgia/core/gba] Fix GBA build issues 2020-05-17 04:20:59 -05:00
2dad1688b5 [ox] Fix GBA build 2020-05-17 04:20:43 -05:00
f1110bd849 [nostalgia] Make Linux Jenkinsfile only target Linux builders 2020-05-16 22:53:16 -05:00
b1a0fcbc57 [ox/claw] Add missing write.cpp 2020-05-16 22:47:51 -05:00
e3e00b1716 [nostalgia] Move Jenkinsfile to allow for platform specificity 2020-05-16 22:46:48 -05:00
faaddd1234 [ox/claw] Fix TypeVersion writing 2020-05-16 22:35:54 -05:00
f37515707f [nostalgia] Make Jenkinsfile do ASAN builds 2020-05-16 17:16:17 -05:00
86652ca8d4 [nostalgia] Fix Mac build 2020-05-09 18:44:37 -05:00
819959745d [ox] Fix Mac build and fix MC to increment field counter on empty string 2020-05-08 21:32:56 -05:00
f91874182e [ox/model] Add preloadable attribute to type descriptor 2020-05-08 01:32:36 -05:00
dfb17c851b [nostalgia] Break out Jenkinsfile steps 2020-05-06 20:59:29 -05:00
e2952ec8c1 [ox/claw] Add Claw 2020-05-06 20:38:39 -05:00
9560ccf476 [nostalgia] Remove conan Qt, as it is currently being ignored 2020-05-05 00:03:58 -05:00
e7ea76a7ac [nostalgia] Explicitly list certain dependencies that were causing problems on Fedora 2020-05-04 19:25:10 -05:00
bae54a906b [nostalgia] Add CMake option to disable engine build 2020-05-04 18:22:42 -05:00
b0f268f371 [nostalgia] Make test run build in Makefile 2020-05-04 18:21:48 -05:00
b39735bb08 [nostalgia] Update Jenkinsfile to force conan remote add 2020-05-04 18:20:50 -05:00
6af681bad6 [nostalgia/core] Enable sign conversion warning publicly 2020-04-16 23:51:06 -05:00
9b84d9d8e0 [nostalgia/world] Fix sign conversion 2020-04-16 23:50:30 -05:00
4694bb9dd7 [nostalgia/tools/pack] Fix sign conversion 2020-04-16 23:49:08 -05:00
f758566041 [nostalgia/studio] Add PathExistsValidator 2020-04-16 23:47:08 -05:00
cef5fcd86f [nostalgia/core/userland] Enable sign-conversion warning 2020-04-16 23:44:06 -05:00
8e297f32d4 [nostalgia/core] Move Nostalgia graphics type models to new setTypeInfo 2020-04-16 23:40:22 -05:00
be16229bf7 [nostalgia/core/sdl] Initialize texture lists 2020-04-16 23:39:18 -05:00
11e500520a [nostalgia] Make ox headers system headers 2020-04-16 23:37:35 -05:00
00e645e7a3 [nostalgia/sample_project] Update for new FileAddress 2020-04-16 23:34:45 -05:00
3ff4a59373 [ox/fs] Make FileAddress model use builtin union support 2020-04-16 23:34:08 -05:00
5265a94a80 [ox/oc] Add support for allocating for strings 2020-04-16 23:28:52 -05:00
b3fa531aa0 [ox/model] Add support to SerStr for allocating string 2020-04-16 22:44:50 -05:00
8753d39b66 [ox/std] Fix OxError for release builds and fix ox::Error assignment operator 2020-04-16 22:19:27 -05:00
ed0bf268ba [ox/fs] Add model definition for FileAddress 2020-04-15 21:02:35 -05:00
d0f5819072 [ox/oc] Add union support 2020-04-13 23:36:27 -05:00
d2e7528dae [ox/mc] Fix int reads not to clear out unions 2020-04-13 02:37:08 -05:00
1d07890668 [ox] Add support for unions to model and mc 2020-04-13 02:28:38 -05:00
82a07737ec [nostalgia] Update README 2020-04-11 03:07:52 -05:00
9091f9bd02 [nostalgia] Add profile setting to libstdc++11 in Jenkinsfile 2020-04-09 23:39:24 -05:00
5d95b188d8 [ox/model] Harmonize make the interface for walking over models 2020-04-09 22:57:03 -05:00
a4000f6497 [ox/std] Fix assert for !OX_USE_STDLIB 2020-04-08 23:30:14 -05:00
12c5339295 [nostalgia] Update JsonCpp in conanfile 2020-04-08 03:55:52 -05:00
4064592acc [nostalgia/core/studio] Remove implicit sign conversions 2020-04-07 22:27:28 -05:00
b9c2f3631d [nostalgia/core] Remove implicit sign conversions 2020-04-07 22:10:34 -05:00
d2ec3b8350 [ox/fs] Remove explicit linking of C++ standard file system library 2020-04-07 22:04:23 -05:00
19422ced3e [ox/std] Add move constructor and set null terminator for String 2020-04-07 22:03:19 -05:00
540e67fcd8 [ox/std] Add support for messages in ox::Error 2020-04-07 22:02:07 -05:00
89854a584a [ox/oc] Add OrganicClaw 2020-04-07 22:00:14 -05:00
8b74920270 [ox/std] Fix implicit sign conversion 2020-04-05 19:48:47 -05:00
a74cd1c926 [nostalgia/core/studio] Fix build error in NewTileSheetWizard 2020-04-02 00:58:40 -05:00
5189fefaa1 [nostalgia/core/studio] Move NewTileSheetWizard validation to accept 2020-03-31 22:01:32 -05:00
23c8a5eefc [nostalgia/core] Remove unused file 2020-03-31 21:55:06 -05:00
90c83a492c [nostlgia/core/studio] Implement add color button for PaletteEditor 2020-03-31 21:52:53 -05:00
c99b60186d [ox/std] Fix Vector::expandCap not to delete old array an not new one 2020-03-31 21:42:47 -05:00
64ee637b74 [nostalgia/core/studio] Add NewPaletteWizard and implement NewTileSheetWizard 2020-03-31 21:11:41 -05:00
5cec2cf819 [nostalgia/studio] Add project path to file name function 2020-03-31 21:10:40 -05:00
680881003c [ox/mc] Fix false positive buffer overflow check when string is last item in MC buffer 2020-03-31 20:40:29 -05:00
d7b5f51fdc [ox/mc] Prevent reading array length of absent array 2020-03-30 23:59:01 -05:00
33047fc047 [nostalgia/core/studio] Remove Tile Count field from tile sheet importer 2020-03-30 23:00:44 -05:00
74ef768b6f [nostalgia/core/studio] Add missing override 2020-03-30 20:51:37 -05:00
d457d9688c [nostalgia/studio] Make open tab errors print file and line 2020-03-30 20:50:51 -05:00
267f8eca67 [nostalgia/core/studio] Fix magic numbers in imgconv and make it figure out tile sheet dimensions 2020-03-30 20:49:02 -05:00
e7ae031ce7 [nostalgia/core/studio] Cleanup 2020-03-30 20:09:45 -05:00
5f0217545c [nostalgia/core/studio] Make TileSheetEditor not highlight color cell 2020-03-30 00:43:54 -05:00
5a5905d257 [nostalgia/core/studio] Fix TileSheetEditor to clear pixel data on reload 2020-03-29 23:48:07 -05:00
2e7a81563d [nostalgia/core/studio] Add PaletteEditor 2020-03-29 23:38:32 -05:00
4c6e053e81 [nostalgia/core/studio] Make TileSheetEditor reload when the current palette is updated 2020-03-29 19:00:02 -05:00
11cb4d5a44 [nostalgia/core] Add color 16 functions 2020-03-29 13:35:23 -05:00
a81582d3cd [nostalgia/studio] Make Editor's itemName and exportable const 2020-03-29 13:34:10 -05:00
4011773374 [ox/std] Add insert method to Vector 2020-03-29 13:32:17 -05:00
1d8f8566c5 [nostalgia/core/studio] Fix ng export to only attempt export if output file is given 2020-03-29 13:31:19 -05:00
5f8104efea [nostalgia/core/studio] Make color selection table uneditable 2020-03-27 20:43:35 -05:00
5cc96228f4 [nostalgia/core/studio] Fix drag left click not to update tile sheet 2020-03-27 20:43:17 -05:00
e65e4e44cb [nostalgia/core/studio] Cleanup 2020-03-26 01:39:02 -05:00
8d4fc0e346 [nostalgia/core/studio] Add ability to export tile sheet to png 2020-03-26 01:21:19 -05:00
cd5c3afce7 [nostalgia/common] constexpr-ize Point 2020-03-26 01:19:08 -05:00
a2c012ead4 [nostalgia][core][sdl] Fix bug in loading 8 bpp ng files 2020-03-25 02:05:09 -05:00
26747a6d0f [nostalgia/studio] Add Export menu item and hook 2020-03-24 21:42:42 -05:00
f90a6e30ea [nostalgia/studio] Move undo stack to Editor 2020-03-23 23:25:05 -05:00
362aeef3c7 [nostalgia/core/studio] Remove option for bundled tile sheet palette 2020-03-23 01:48:28 -05:00
350b4ad6c2 [nostalgia/core/sdl] Make draw always report FPS to oxTrace 2020-03-23 01:22:58 -05:00
887167add2 [nostalgia/core/sdl] Add sleep 1 ms to main loop 2020-03-22 21:57:17 -05:00
4dab05aef5 [nostalgia/core/qt] Add missing return nostalgia::core::shutdownGfx 2020-03-22 19:01:45 -05:00
43318acffa [nostalgia/core] Make load tile sheet default to defaultPalette 2020-03-22 18:56:52 -05:00
6d2155d1ed [nostalgia/core] Add support for implementation data to Context and move SDL data to it 2020-03-22 18:30:33 -05:00
0e2276bab8 [nostalgia/core] Add pragma once to context.hpp 2020-03-22 17:53:59 -05:00
95d58d04fb [nostalgia/core/studio] Fix delete tile undo to restore pixel data 2020-03-22 02:06:21 -05:00
d7d0690575 [nostalgia/sample_project] Add Dirt 2020-03-22 01:37:21 -05:00
7ae0befc37 [nostalgia/core/studio] Add delete tile 2020-03-22 01:34:09 -05:00
4ae0becf79 [nostalgia] Add blank to Charset of sample_project 2020-03-22 01:27:27 -05:00
5aeddd87e3 [nostalgia/core/studio] Add ability to insert tile 2020-03-22 01:24:53 -05:00
4f3497326f [nostalgia/core/studio] Make default palette changes save to NostalgiaGraphics 2020-03-19 19:34:32 -05:00
80aae23dc0 [nostalgia/studio] Cleanup 2020-03-19 19:33:55 -05:00
2f4868f59e [nostalgia/core/studio] Add ability for TileSheetEditor to switch palettes 2020-03-19 02:09:26 -05:00
c45ec45457 [nostalgia/core/sdl] Add disabled FPS logging 2020-03-19 02:08:30 -05:00
aa1b5fa4cf [ox/std] Add missing declaration for String::String(const String&) 2020-03-19 01:56:44 -05:00
464b541f67 [nostalgia/tools/pack] Cleanup 2020-03-19 01:54:14 -05:00
e1d3fe0d6b [nostalgia/studio] Add ability to subscribe to updates to files 2020-03-19 01:52:31 -05:00
4273e72e74 [ox/std] Add copy constructor to String 2020-03-16 00:12:09 -05:00
e0a2676d54 [ox/std] Add String::operator=(const String&) 2020-03-15 14:31:43 -05:00
1313b562bd [ox] Remove bstring.hpp include from string.hpp 2020-03-15 14:29:18 -05:00
f7bdd5042d [ox/std] Add String::operator+ methods 2020-03-15 02:17:11 -05:00
412b187c4f [ox/std] Add bstring.hpp to install 2020-03-15 01:20:28 -05:00
38acb5dfc3 [nostalgia/std] Add String as alternative to BString, which uses heap allocations 2020-03-14 16:33:08 -05:00
317cfabc72 [nostalgia/core/gba] Update NostalgiaGraphic format 2020-03-11 19:02:28 -05:00
5ac257de48 [nostalgia/core/userland] Remove mem.cpp 2020-03-11 18:55:18 -05:00
48decc83f6 [nostalgia] Add support for ccache 2020-03-11 00:21:46 -05:00
6ada347ec4 [nostalgia/studio] Cleanup save hooks and add unsaved changes marker to tabs 2020-03-11 00:20:40 -05:00
bf00ff0e41 [nostalgia/core] Add ability to save tile sheets and store columns and rows in ng file 2020-03-11 00:17:07 -05:00
748fea3d43 [nostalgia/core/studio] Stub out saveItem in TileSheetEditor 2020-02-29 00:31:43 -06:00
320d8c1143 [nostalgia/studio] Add save action and cleanup 2020-02-29 00:28:32 -06:00
eddf89a321 [nostalgia/studio] Fix timing of setting HiDPI options 2020-02-25 20:30:36 -06:00
fb5cd6603f [nostalgia/core/gba] Cleanup class/struct inconsistency 2020-02-25 20:29:33 -06:00
4fa431c10b [nostalgia/studio] Add missing include 2020-02-25 20:28:59 -06:00
7ca34da417 [nostalgia/core/studio] Replace TileSheetEditor ScrollView scrolling with manual version 2020-02-25 20:26:35 -06:00
f762e658de [nostalgia] Add launch.vs.json 2020-02-16 14:18:22 -06:00
2133896165 [nostalgia] Update liccor for 2020 2020-02-16 14:16:16 -06:00
4571a95a06 [ox] Fix OxConfig to include Model library 2020-02-16 14:08:28 -06:00
aecb6d55e4 [nostalgia/core/studio] Add null check needed in the destruction phase 2020-02-16 13:55:22 -06:00
2fb0ddf709 [nostalgia/studio] Fix JSON errors to only display when error occurs 2020-02-16 13:45:06 -06:00
1269ee7fad [nostalgia] Fix oxPanic parameter order 2020-02-16 02:06:05 -06:00
da3c9107db [ox/std] Fix type in hardware detection 2020-02-16 02:03:28 -06:00
2a1919208d [nostalgia/studio] Remove debug code 2020-02-16 01:55:32 -06:00
2cff1add56 [nostalgia/studio] Add missing rpath entry 2020-02-16 01:50:23 -06:00
debb3eb981 [nostalgia/studio] Get Studio running with MSVC 2020-02-16 01:45:37 -06:00
74e6a4cbff [ox/std] Fix oxPanic parameter order 2020-02-16 01:43:54 -06:00
5c710051c5 [nostalgia/studio] Fix symbol export issues for MSVC 2020-02-15 12:34:31 -06:00
36b6542bf3 [ox/std] Fix hardware detection to work in MSVC 2020-02-15 12:24:43 -06:00
0abc07e31b Merge branch 'master' of github.com:gtalent/nostalgia 2020-02-15 11:53:52 -06:00
1ec8d721f1 [nostalgia/studio] Get building in MSVC 2020-02-15 11:53:39 -06:00
7df2244f65 [nostalgia] Add make conan to Jenkinsfile 2020-02-12 22:34:49 -06:00
c2b4595c33 [ox/std] Make unrecognized hardware trigger compile error 2020-02-12 22:13:34 -06:00
f06806dafd [nostalgia] Remove overriding of input NOSTALIGA_BUILD_STUDIO setting 2020-02-12 22:04:35 -06:00
c5f0825edb [ox/mc] Fix signed/unsigned comparison in field bitmap 2020-02-12 22:04:35 -06:00
517551348a [ox/fs] Fix GCC/Clang incompatibility 2020-02-12 22:04:35 -06:00
cdf62cbb98 [nostalgia] Get building in MSVC 2020-02-12 22:04:35 -06:00
4cbf1b9a9a [ox] Get building in MSVC 2020-02-12 22:04:35 -06:00
a66f1499a4 [nostalgia/core/gba] Move cstartup.cpp back to gbastartup 2020-02-12 01:56:43 -06:00
29734d5ee1 [nostalgia/tools/pack] Fix oxAssert to use new parameter order 2020-02-11 21:58:24 -06:00
2c582617e3 [nostalgia/core] Always run GBA CMake file and add media.cpp 2020-02-11 21:48:48 -06:00
87968a87f0 [nostalgia/core/gba] Fix memory range 2020-02-11 21:47:48 -06:00
9d4d3cd331 [nostalgia/core/gba] Move cstartup.cpp to NostalgiaCore-GBA 2020-02-11 21:45:48 -06:00
553cde0d0c [ox/fs] Replace uint8_t with char for buffers 2020-02-11 21:42:09 -06:00
90f94dbfc2 [nostalgia/core] Add PassthroughFS support to loadRomFs 2020-02-11 21:34:55 -06:00
fffc66f18b [nostalgia/core/gba] Add test for malloc and unify panic systems 2020-02-11 21:17:10 -06:00
ea14ccac3a [ox/std] Leave panic unimplemented when C++ stdlib is absent 2020-02-11 21:10:36 -06:00
e59499b127 [ox/std] Fix oxIgnoreError to not completely ignore the statement it encompases 2020-02-11 00:07:37 -06:00
afab2f6878 [nostalgia/core] Add loadRomFs 2020-02-01 00:47:08 -06:00
e927c51b61 [ox/fs] Give FileSystem ability to cleanup FS buffer 2020-02-01 00:11:59 -06:00
dd008c3a08 [ox/std] Remove constexpr from ox::bit_cast 2020-01-31 23:53:55 -06:00
54a78ff04e [nostalgia/core/gba] Rewrite heap allocator 2020-01-31 23:53:20 -06:00
878c944ebf [ox/std] Add bit_cast 2020-01-31 19:43:23 -06:00
d9b363330b [ox/std] Rename bitops.hpp to bit.hpp to mirror the new bit in C++20 2020-01-31 19:06:26 -06:00
c9f91c16c2 [ox/fs] Add exception handling to PassthroughFS for fstream usage 2020-01-25 15:18:08 -06:00
5f56a5cc9b [nostalgia] Add build missing option to conan invocation 2020-01-25 00:37:55 -06:00
6cb449ae19 [nostalgia] Add conanbuild to .gitignore 2020-01-25 00:34:40 -06:00
d93c6dff10 [nostalgia] Add sample project 2020-01-25 00:16:44 -06:00
41030161df [nostalgia/core/gba] Change type of MEM_ROM 2020-01-25 00:08:25 -06:00
2d4f1054fd [nostalgia/tools/pack] Replace oxAssert with oxPanic where error is known 2020-01-25 00:07:06 -06:00
52026ba1a3 [ox/fs] Add oxPanic and remove ErrorInfo 2020-01-25 00:04:47 -06:00
c214f3334a [ox] Remove gdblogger 2020-01-24 23:33:57 -06:00
cda6eb92f3 [nostalgia] Add missing changes for CMake to set dist directory 2020-01-24 23:29:16 -06:00
02c8fb1880 [ox] Remove .gdbinit 2020-01-24 23:27:28 -06:00
7bd1f56f93 [nostalgia] Remove .gdbinit 2020-01-24 23:26:59 -06:00
22680ffaf0 [nostalgia] Cleanup unnecessary cast 2020-01-24 23:21:25 -06:00
892fec6905 [nostalgia/tools/pack] Cleanup 2020-01-24 23:09:48 -06:00
a2c8df83c6 [nostalgia/tools/pack] Remove using namespaces 2020-01-24 22:57:28 -06:00
8037bc9535 [ox/fs] Remove unnecessary PassthroughFS fstream close 2020-01-24 22:48:05 -06:00
70925cbde4 [nostalgia/pack] Cleanup error handling and file I/O 2020-01-24 22:29:35 -06:00
e38cf01f07 [nostalgia/core/userland] Replace C file I/O with C++ file I/O to comply with handbook 2020-01-24 19:04:48 -06:00
e8760cd714 [nostalgia] Cleanup setup-build 2020-01-24 18:56:13 -06:00
d1d979d2f1 [nostalgia] Add section to Developer Handbook about mixing C and C++ 2020-01-24 18:55:29 -06:00
615e06aa50 [nostalgia] Remove unused files 2020-01-15 23:28:04 -06:00
7edfc16f25 [nostalgia] Make Makefile more portable 2020-01-14 20:38:26 -06:00
fe91d042db [nostalgia] Updated gba-pkg to use .current_build 2020-01-14 20:25:04 -06:00
33fe14ffa1 [nostalgia] Actually make Ninja usage universal... 2020-01-14 20:16:27 -06:00
1e879b93b7 [nostalgia] Remove remaining C-style casts 2020-01-14 18:50:30 -06:00
6287663957 [nostalgia] Make GBA builds use Ninja 2020-01-14 18:36:47 -06:00
1d49c965fe [nostalgia/player] Remove unused CMake target 2020-01-14 18:36:26 -06:00
441edf0d37 [nostalgia] Fix setup-build cmake invokation 2020-01-12 21:53:57 -06:00
f59ad72ca2 [gbastartup] Make c_start return main(...) 2020-01-12 21:18:21 -06:00
0f3b71e63f [nostalgia/player] Explicitly run FS desctructor, as it is allocated with alloca 2020-01-12 20:54:32 -06:00
1890b4101e [nostalgia/player] Make no-FS case an error 2020-01-12 20:47:53 -06:00
bda4e643af [nostalgia/player] Cleanup main 2020-01-12 20:46:12 -06:00
03fc6280c9 [gbastartup] Add main parameters for GBA build 2020-01-12 20:45:20 -06:00
04727ae57a [nostalgia/core] Add unloadRom function 2020-01-12 20:44:57 -06:00
84ee494834 [ox/fs] Make PassthroughFS presence define more export freindly 2020-01-12 20:43:39 -06:00
08483e6e2f [nostalgia] Remove need for run-make and "current" symlinks 2020-01-09 18:30:35 -06:00
2fab740bf5 [nostalgia/core] Remove common as dependency 2020-01-07 18:34:54 -06:00
5f4cff3c00 [nostalgia/core/studio] Add changing of column/row display configuration 2020-01-04 19:54:33 -06:00
91b959ff9d [nostalgia] Add .PHONY to Makefile and cleanup unused commands 2020-01-03 20:00:58 -06:00
038f0ee493 [nostalgia/studio] Move OxFSTreeView out of Studio lib 2020-01-01 19:30:07 -06:00
3afaa0fc85 [ox/fs] Cleanup 2019-12-31 20:08:50 -06:00
e050339311 Merge branch 'conan' 2019-12-31 17:43:24 -06:00
61a5d100b0 [nostalgia] Add conan command to Makefile 2019-12-31 17:42:48 -06:00
2049931937 [nostalgia/core] Cleanup color channel conversion 2019-12-31 17:34:34 -06:00
0d46cee20d [nostalgia] Get building with Conan 2019-12-30 22:51:35 -06:00
bd1fc01ca1 [nostalgia/core/studio] Obsolete UpdatePixelCommands that change nothing 2019-12-22 21:35:00 -06:00
4b832dd3d7 [ox/fs] Change PassThroughFS to use fstream instead of C file IO for compatibility reasons 2019-12-22 00:30:08 -06:00
942d548fdd [nostalgia] Make BUILD_STUDIO setting a build parameter 2019-12-20 00:13:23 -06:00
9187bcf62b [ox/std] Fix __has_include logic 2019-12-19 23:43:33 -06:00
8c576ef9c5 [ox] Replace __attribute__((packed)) with OX_PACKED 2019-12-19 23:38:17 -06:00
1499f42361 [nostalgia/core/studio] Cleanup pixel data QML exposure 2019-12-15 00:37:06 -06:00
edae4563ff [nostalgia/studio] Cleanup main 2019-12-07 02:14:24 -06:00
c6ecbd6d12 [nostalgia/studio] Actually add studio::Editor... 2019-12-06 23:46:12 -06:00
536435c057 [nostalgia/core/studio] Fix undo operation in TileSheetEditor 2019-12-06 23:28:18 -06:00
ecde378aba [nostalgia/studio] Hook up QUndoGroup in MainWindow to tabs 2019-12-06 23:27:36 -06:00
dd3e5913ed [nostalgia/core/studio] Make TileSheetEditor a studio::Editor 2019-12-06 19:23:45 -06:00
641c6ae637 [nostalgia/studio] Add studio::Editor type as base type for editors 2019-12-06 19:22:07 -06:00
a8bed71255 [nostalgia] Globally enable PIC for non-bare metal builds 2019-12-06 01:11:30 -06:00
540def399e [nostalgia/core/qt] Fix Core-Qt install location 2019-12-06 01:06:10 -06:00
37b6095e13 [nostalgia/core/studio] Add command sequence grouping to tile sheet editor 2019-12-06 00:50:32 -06:00
1edd322352 [nostalgia/core/studio] Add support for dragging cursor around tile sheet editor 2019-12-05 23:38:51 -06:00
38ae116356 [nostalgia/core/gba] Fix BPP setting in tile sheet loader 2019-12-05 23:36:49 -06:00
8fd49469c9 [nostalgia/core/studio] Fix bad PixelUpdate merging code that could keep wrong duplicate 2019-12-05 02:07:03 -06:00
70022d5a96 [nostalgia/core/studio] Fix index lookup for updating pixel color 2019-12-05 01:32:52 -06:00
01ad572499 [nostalgia/core/studio] Make Pixel updates in TileSheetEditor use undo stack 2019-12-03 18:01:00 -06:00
e407ad7246 [nostalgia/core] Add basic color selection and basic tilesheet editing 2019-12-01 00:52:00 -06:00
2e5263764c [nostalgia/core/studio] Add copyright headers to QML files 2019-11-27 14:36:56 -06:00
474230ae97 [nostalgia/core/studio] Make TileSheetEditor's implementation better match data 2019-11-27 14:10:22 -06:00
a9f55ebd02 [nostalgia/core] Rename core::Color to core::Color16 and add core::Color32 2019-11-27 13:53:41 -06:00
1b08d0f851 [nostalgia/player] Replace C header with C++ equivalent 2019-11-26 23:48:39 -06:00
528f9be635 [nostalgia] Add Qt Quick as dependency 2019-11-26 23:47:08 -06:00
d06724ffe1 [nostalgia/core/studio] Fix tile sheet editor to correctly iterate over tiles 2019-11-26 23:46:04 -06:00
d37cd50d99 [nostalgia] Add About to Developer Handbook 2019-11-26 23:36:42 -06:00
8f21670439 [nostalgia/core/studio] Start tile sheet editor 2019-11-26 23:23:12 -06:00
69666a0b31 [nostalgia/core/gba] Fix typo 2019-11-26 23:22:16 -06:00
1d600186cd [ox/fs] Cleanup, Fix FileLocation to make copy of non-const strings 2019-11-26 23:18:38 -06:00
147a37ac6e [ox/std] Cleanup 2019-11-26 23:18:19 -06:00
f634c208ac [nostalgia/studio] Flesh out editor tab system and cleanup studio::Project to use exceptions instead of returning error codes 2019-11-26 23:15:02 -06:00
aa34239eb5 [nostalgia] Start developer handbook 2019-11-23 02:17:34 -06:00
965e280b53 [nostalgia/tools] Remove debug code 2019-11-14 04:57:34 -06:00
45dd2e38e3 [nostalgia/core/gba] Cleanup 2019-11-14 04:51:53 -06:00
ee58ba4e9b [nostalgia] Fix run-studio on Mac 2019-11-13 20:37:23 -06:00
0fbe1b96c3 [nostalgia/core/gba] Add missing section multiplier to TILE_ADDR section index 2019-11-12 21:26:41 -06:00
4247ac0651 [nostalgia/core/gba] Remove unused header 2019-11-12 20:34:57 -06:00
e5a66e1160 [nostalgia/player] Fix loading from directory 2019-11-09 19:01:20 -06:00
7d5595b405 [nostalgia/player] Give player the ability to load from rom file or directory 2019-11-09 18:07:28 -06:00
71b38b243e [nostalgia/core] Replace puts loc param with column and row params 2019-11-09 17:56:50 -06:00
5dc74e6fd7 [ox/std] Fix constexpr-ness of ox_memset 2019-11-09 01:24:15 -06:00
2f45cbe6d9 [gbastartup] Cleanup 2019-11-09 00:36:26 -06:00
e470a1da09 [ox/std] Add ox_inhibit_loop_to_libcall for memset and memcpy 2019-11-09 00:06:05 -06:00
ddb158e433 [ox/fs] Fix Directory allocating too much space 2019-11-07 00:34:07 -06:00
d033335350 [ox/ptrarith] Make NodeBuffer clear all memory before using it 2019-11-07 00:33:34 -06:00
3cc6ca215e [ox/fs] Fix Directory to allocate enough space for new entry 2019-11-04 18:30:17 -06:00
561cf9e2b4 [nostalgia] Fix some broken Makefile commands 2019-11-03 23:31:47 -06:00
876a0a2a23 [nostalgia/player] Remove unused custom startup file 2019-11-03 23:29:47 -06:00
0d0ebc8437 [deps] Add GbaStartup library from devkitPro as dependency 2019-11-03 23:25:25 -06:00
628b4d656b [nostalgia/core] Move puts function out of core implementations to core 2019-11-03 23:20:13 -06:00
758907ab5a [nostalgia] Restore GBA support 2019-11-03 22:25:45 -06:00
deaa293c67 [ox/fs] Fix problems with creating and reading directories 2019-11-03 16:44:57 -06:00
c30ef720c4 [ox/ptrarith] Fix Ptr type's derefernce operator 2019-11-03 16:44:22 -06:00
693e7324ed [ox/mc] Fix buffer overrun issues 2019-11-03 16:42:42 -06:00
7699ae2294 [ox/fs] Remove bad TODO 2019-11-01 18:01:09 -05:00
7105c19c72 [nostalgia/core/gba] Add hardware target types for loading tile maps and palettes 2019-11-01 01:31:11 -05:00
0825c9869a [ox/mc] Add support for individual element readers for arrays 2019-11-01 01:28:29 -05:00
9da47f75c0 [ox/fs] Add support for direct access to FS memory 2019-11-01 01:28:04 -05:00
73377068c6 [nostalgia/core] Cleanup CMake config 2019-10-31 00:23:25 -05:00
3a0b41d2cc [ox/fs] Remove debug line 2019-10-31 00:16:09 -05:00
7f5f74e2a6 [ox/fs] Fix various file system bugs 2019-10-31 00:07:39 -05:00
fc337922ac [ox/std] Add missing null terminator to ox_strncpy 2019-10-31 00:06:11 -05:00
ce94af3f00 [nostalgia/core] Fix GBA compile errors 2019-10-28 00:42:26 -05:00
4f81c47734 [ox] Fix GBA compile errors 2019-10-28 00:40:56 -05:00
bae1908c3b [nostalgia/core] Cleanup 2019-10-27 19:48:32 -05:00
52c4744242 [nostalgia/core] Add support for drawing NostalgiaGraphics in SDL 2019-10-27 16:24:38 -05:00
79a1a6f896 [ox/fs] Add modelWrite to FileAddress and add copy constructor and assignment 2019-10-27 16:22:37 -05:00
656039e011 [ox/std] Replace Error with a multi-field struct 2019-10-27 16:21:41 -05:00
3df78cd515 [nostalgia/common] Update to C++17 namespace nesting 2019-10-27 16:19:49 -05:00
4ca4c31539 [ox/mc] Fix read to resize Vectors before writing to them 2019-10-25 21:48:43 -05:00
37009a7923 [nostalgia/tools/pack] Remove Qt as dependency 2019-10-23 17:39:40 -05:00
a60e7c27b7 [nostalgia/core/studio] Rename New Palette option to External 2019-10-23 00:23:06 -05:00
3bc48c04f7 [nostalgia] Fix build configuration commands in Jenkinsfile 2019-10-22 23:57:48 -05:00
9147a91cc0 [nostalgia] Add agent to Jenkinsfile 2019-10-22 23:56:05 -05:00
0a809037ac [nostalgia/core/studio] Move imgconv to Core Studio 2019-10-22 23:49:12 -05:00
aa171fa069 [nostalgia/core] Remove Write distictions from Graphic and Palette models 2019-10-22 19:37:02 -05:00
adb23d9d6c [nostalgia] Remove Dockerfile from Jenkinsfile 2019-10-22 19:33:19 -05:00
92103bfc41 [nostalgia] Add external palettes to tilesheet system 2019-10-22 19:23:14 -05:00
fbdb48a1ee [ox/fs] Add modelWrite handler to FileAddress 2019-10-22 18:54:19 -05:00
5a0ba33b4c [nostalgia] Remove NostalgiaTool library 2019-10-17 17:50:06 -05:00
54ac86fce7 [ox/fs] Add FileAddress support to FileSystem 2019-10-12 11:56:49 -05:00
ce7c416fb7 [ox/fs] Remove Boost FS usage 2019-10-09 18:59:52 -05:00
aefd65b9e9 [nostalgia] Run liccor 2019-08-17 18:33:31 -05:00
32b345ed0b [nostalgia] Update nested namespaces for C++17 2019-08-03 22:43:17 -05:00
8cd38dccbf [nostalgia/studio] Replace int errors with ox::Error 2019-08-03 22:32:39 -05:00
3c45558dfc [ox/std] Add bitwise not to strong int 2019-08-01 23:20:17 -05:00
2fb1c7e401 [nostalgia/core/gba] Fix strong Error issues 2019-07-31 00:07:23 -05:00
6138d0a37e [ox] Fix GCC warnings 2019-07-31 00:06:47 -05:00
df8e1d31d6 [nostalgia] Fix for explicit ValErr::operator T 2019-07-30 23:08:40 -05:00
c27cc56e31 [ox] Make ValErr::operator T() explicit 2019-07-30 19:00:01 -05:00
2b536ff053 [ox/model] Fix storng int Error errors 2019-07-29 22:58:06 -05:00
ff4adaebf1 [ox/mc] Fix FieldPresenceIndicator to return correct value when overflow occurs 2019-07-29 22:55:17 -05:00
142387aa04 [ox/std] Improve ability to create unique int types, regardless of underlying type 2019-07-28 00:57:50 -05:00
b107dc756b [nostalgia] Switch to strong int Error 2019-07-28 00:32:42 -05:00
f4b336dd77 [ox] Make Error use a strong int 2019-07-28 00:15:10 -05:00
3c86aae616 [ox/std] Fix several problems that arose when trying to use strong ints 2019-07-27 23:56:49 -05:00
6485a780a7 [ox/std] Add strongly typed integer wrapper 2019-07-26 21:32:42 -05:00
c87e92da71 [ox/ptrarith] Add nodiscard to Error return of NodeBuffer::compact 2019-07-25 20:05:00 -05:00
deaa1f13f5 [ox/fs] Add missing nodiscards on ox::Error returns 2019-07-25 19:53:14 -05:00
da2b588deb [nostalgia/core/gba] Change charset to lookup by path 2019-07-24 23:33:01 -05:00
d53430abbc [ox/std] Give AllocAlias separate size option 2019-07-24 07:58:52 -05:00
382df7b2af [nostalgia/tools/pack] Add missing nost-pack changes to actually write ROM 2019-07-23 21:18:01 -05:00
84feeb8c1f [nostalgia/tools/pack] Cleanup 2019-07-22 23:17:08 -05:00
8a562e1cc5 [nostalgia] Update gba-pkg script to use new nost-pack 2019-07-21 23:54:30 -05:00
2d2cd2bbb6 [ox/fs] Add Error return to FileStore compact 2019-07-20 18:46:52 -05:00
22378d0a9f [ox/std] Fix alignment of Vector elements 2019-07-19 22:11:01 -05:00
32d7c7b9e2 [ox/std] Fix syntax error in std::is_union_v 2019-07-19 22:10:32 -05:00
8fa5488d77 [ox/fs] Fix FileStoreTemplate::compact to skip first item and correctly find parent 2019-07-19 20:14:09 -05:00
31b75d1e50 [ox/ptrarith] Fix NodeBuffer::compact to iterate over items when item already in correct location 2019-07-19 19:53:50 -05:00
d55089b582 [ox/ptrarith] Fix NodeBuffer::compact to correclty update dest.prev 2019-07-18 20:31:51 -05:00
69f918664d [nostalgia] Cleanup CMake ON/OFF switches 2019-07-17 22:58:56 -05:00
cb8f26046a [ox/fs] Cleanup Directory test 2019-07-17 21:36:03 -05:00
969af651d3 [ox/fs] Add error return to resize 2019-07-17 21:35:07 -05:00
fb4a768415 [ox/fs] Add better error handling to Directory 2019-07-17 21:31:12 -05:00
62593c48a6 [nostalgia] Upgrade devenv to Fedora 30 2019-07-17 21:27:34 -05:00
25c629f570 [ox/ptrarith] Expand tests 2019-07-17 21:25:33 -05:00
ea2bf8998b [ox/clargs] Link with OxStd 2019-07-17 21:17:10 -05:00
0efe94db45 [ox/fs] Fix extraneous alloc and update rootInode in compact 2019-07-17 20:43:14 -05:00
dc03e01cf8 [ox/ptrarith] Fix NodeBuffer::malloc to correctly update the old last's prev 2019-07-17 20:12:28 -05:00
ffce1dc4df [ox/std] Fix warning about unused private variable 2019-07-16 18:36:45 -05:00
02d92449f9 [ox/std] Add is_union_v and is_class_v 2019-07-15 18:15:14 -05:00
0b218f57c2 [ox/std] Fix Vector copy assignment to allocate as char* 2019-07-15 18:10:00 -05:00
16a09d6814 [ox/std] Make Vector only call constructor and destructor on valid items 2019-07-12 22:48:10 -05:00
806eaa229a [ox/std] Add log message for asserts 2019-07-08 23:18:54 -05:00
7b034be393 [ox/ptrarith] Add asserts to Ptr::operator T* 2019-07-08 23:13:30 -05:00
d4212abe3b [ox/fs] Fix PassthroughFS to pull in defines from header before check 2019-07-07 22:08:39 -05:00
ee9cdbe1e7 [ox/fs] Fix issues with PassthroughFS Boost port 2019-07-06 01:49:28 -05:00
845373e049 [ox/fs] Make macOS builds use Boost FileSystem 2019-07-06 00:09:42 -05:00
6493a5e10e [ox/ptrarith] Disable ptrarith tests when OX_RUN_TESTS is not set 2019-06-29 23:52:43 -05:00
41d6c7188c [ox] Remove -Wshadow, too pedantic 2019-06-28 23:56:17 -05:00
00ed62c04c [nostalgia/studio] Replace use of deprecated qSort with std::sort 2019-06-27 21:25:58 -05:00
959807c08b [ox/model] Fix name shadowing 2019-06-26 23:47:10 -05:00
8730c6380c [ox] Add -Wshadow warning 2019-06-26 21:54:41 -05:00
472249cd6d [ox] Ensure all gdblogger messages always end with a new line 2019-06-26 20:45:48 -05:00
0c7f8c8b5e [ox/nodebuffer] Fix bounds checking in Ptr generation 2019-06-25 08:19:59 -05:00
3adf0df9c7 [ox/ptrarith] Fix NodeBuffer to properly handle removing only node 2019-06-25 00:39:49 -05:00
6571129686 [ox/fs] Add resize compactor 2019-06-22 17:23:24 -05:00
baff558ff2 [ox/fs] Enforce error handling in Directory 2019-06-22 11:52:55 -05:00
74d1bb08fe [nostalgia/tools/pack] Add missing error checking 2019-06-22 02:08:28 -05:00
74fe0c55cc [ox/fs] Enforce error checking of FS function calls 2019-06-22 02:07:20 -05:00
6a5b16c644 [nostalgia/tools/pack] Add verify, cleanup linking options, cleanup error handling 2019-06-22 01:29:55 -05:00
04929302d7 [ox/fs] Rename confusing parameters in FileStoreTemplate::read 2019-06-22 00:40:23 -05:00
3938cb0282 [ox/fs] Cleanup FileStoreTemplate::read 2019-06-21 23:30:06 -05:00
db04367579 [ox/fs] Cleanup hard-to-read code 2019-06-20 23:24:36 -05:00
c87eed730e [ox/fs] Fix Ox FS tests to run again 2019-06-20 23:24:03 -05:00
7b6b53b7d3 [ox/fs] Remove unused parents parameter from Director::write 2019-06-20 22:55:26 -05:00
a204aa8c48 [ox/fs] Move large test allocations to heap 2019-06-20 21:41:32 -05:00
8e82ba2f2e [ox/fs] Fix mkdir -p 2019-06-20 20:42:25 -05:00
eed1a1a94e [nostalgia] Fix GBA build to use altered CMake modules path 2019-06-20 07:50:12 -05:00
9c70aab4a6 [nostalgia] Cleanup CMake files 2019-06-20 00:18:47 -05:00
d9a596649c [nostalgia] Change conanfile.txt with conanfile.py 2019-06-20 00:06:22 -05:00
7725abeac8 [nostalgia] Cleanup CMakeLists.txt 2019-06-19 23:43:58 -05:00
ad85c59107 [ox] Fix CMake inconsistency that broke PC builds 2019-06-19 23:32:59 -05:00
5705fd3d00 [ox/std] Add OX_USE_STDLIB as exported definition on OxStd 2019-06-19 23:32:18 -05:00
c9df80fb73 [nostalgia/studio] Remove deprecated function call for Qt 5.13 2019-06-19 21:09:11 -05:00
67b2764dc7 [nostalgia/tools/pack] Cleanup unnecessary use of Qt 2019-06-17 23:11:01 -05:00
e58407f156 [nostalgia/tools/pack] Add input checking to nost-pack 2019-06-17 23:09:20 -05:00
eb8f292181 [nostalgia/tools] Cleanup 2019-06-17 22:57:49 -05:00
b839af9207 [nostalgia/player] Cleanup 2019-06-16 22:46:24 -05:00
56601b7c4f [nostalgia] Add conanfile.txt 2019-06-16 22:44:33 -05:00
6ace1e641c [ox/std] Add units.hpp to std.hpp and CMake install 2019-06-16 22:43:19 -05:00
5f41a2665b [nostalgia/tools] Add NostalgiaPack library 2019-06-16 22:42:03 -05:00
5ceb0e5f83 [ox/std] Add memory unit consts (KB, MB, GB, TB) 2019-06-16 22:08:10 -05:00
5834201fbb [ox/std] Add ValErr support to oxReturnError 2019-06-16 19:00:47 -05:00
98d045827e [ox/std] Fix placement new declaration to use stdlib declaration if available 2019-06-16 01:04:57 -05:00
14a40bdcd6 [ox/std] Remove usage of stdlib from substitutes... 2019-06-16 00:53:21 -05:00
47ce0408d5 [ox/std] Add substitutes file with missing __cxa_pure_virtual handler 2019-06-15 23:24:58 -05:00
de210c5c7e [ox/fs] Cleanup 2019-06-15 12:16:11 -05:00
eba7d402c9 [nostalgia/player] Replace main with _start in GBA builds 2019-06-15 12:05:08 -05:00
36d8aeabd3 [ox] Fix incorrect setting of build config when passed in from another CMakeLists.txt 2019-06-15 09:44:04 -05:00
30ff7be0e4 [ox] Make code only compile as PIC if a bare metal build 2019-06-15 02:39:46 -05:00
238bc58f66 [ox/std] Fix several issues found compiling on FreeBSD 2019-06-14 19:36:46 -05:00
2b60c04f1a [ox/std] Add gcc library as dependency when building with GCC 2019-06-14 18:19:43 -05:00
1bf3809b47 [ox] Merge branch 'master' of github.com:gtalent/nostalgia 2019-06-14 18:13:50 -05:00
0c05d298d0 [nostalgia] Merge branch 'master' of github.com:gtalent/nostalgia 2019-06-14 18:12:45 -05:00
829357faaf [nostalgia/core] Update for newer versions of ox 2019-06-14 07:56:53 -05:00
22c9e4bdb2 [ox] Remove OC reference 2019-06-14 07:53:00 -05:00
11029c93c8 [ox/std] Add missing ARM7TDMI functions, some are just stubs for now 2019-06-14 07:50:38 -05:00
87c65a70b0 [nostalgia] Remove vscode directory 2019-06-14 07:45:45 -05:00
096509c2be [ox] Fix GCC errors 2019-06-06 18:50:06 -05:00
23b662c2aa [nostalgia] Enable and fix -Wextra warnings 2019-03-30 17:30:56 -05:00
5afe78d015 [nostalgia] Enable and fix several warnings 2019-03-30 17:15:21 -05:00
05c0eb2f78 [ox/fs] Add base path access to PassthroughFS 2019-03-30 17:13:56 -05:00
5dbe160633 [ox/std] Uglify OxError parameter name to prevent name conflicts 2019-03-30 17:13:03 -05:00
5b57f4279a [nostalgia/core/studio] Remove unused BPP field from tile sheet import wizard 2019-03-30 17:06:56 -05:00
6baa9a251c [nostalgia] Add new pack library to bundle project into OxFS 2019-03-30 17:06:22 -05:00
941d714630 [nostalgia/core] Replace old namespace nesting with C++17 nesting 2019-03-28 06:24:20 -05:00
2830eb76b6 [ox] Fix setup_build script for GBA 2019-03-18 22:33:09 -05:00
b229645dd3 [nostalgia/studio] Fix OxFS tree view to only show current level of tree 2019-03-18 22:30:49 -05:00
f191ade18b [ox/mc] Make VLI encode/decode constexpr 2019-03-18 19:26:58 -05:00
b33cd06031 [ox] Get building with devkitARM again 2019-03-18 00:19:04 -05:00
22da505869 [ox/fs] Remove bad debug code from FileStore::unplaceItem 2019-03-17 23:18:54 -05:00
fa3f7801d2 [ox/fs] Remove inode on decLinks if links is 0 2019-03-17 23:16:41 -05:00
7cfe9aad8e [ox/fs] Properly implement FileStore unplaceItem and move ! to correct canWrite 2019-03-17 23:14:17 -05:00
7ac6ec609a [nostalgia] Add missing ox namespace to ox::Error usages 2019-03-17 22:41:48 -05:00
245eba8d5b [ox/fs] Switch some FS test asserts to check for ox::Error instead of 0 2019-03-17 22:39:59 -05:00
07112682c6 [ox/ptrarith] Fix compact not to cycle back to start 2019-03-17 22:39:20 -05:00
7a2033da60 [ox/fs] Fix unnecessary FileStore compacting 2019-03-17 22:37:42 -05:00
c9d816503d [ox/std] Fix string number/char* append 2019-03-17 17:57:17 -05:00
38400e4406 [nostalgia] Replace int with ox::Error 2019-03-17 16:26:22 -05:00
52b9316858 [ox/std] Replace int with ox::Error where appropriate 2019-03-17 14:13:49 -05:00
94afbd4f60 [nostalgia] Move from old Serialization API to new Model API 2019-03-17 13:43:00 -05:00
d139eb9729 [ox/std] Move std::size_t delcaration to beginning of std/types.hpp 2019-03-17 13:21:04 -05:00
bbd1d187b2 [ox/model] Rename ioOp and op to model and field 2019-03-17 13:18:46 -05:00
bf6469b4a3 [ox] Rename Serialization package to Model 2019-03-17 13:04:18 -05:00
cf7ba595aa [ox/std] Cleanup 2019-03-17 03:05:00 -05:00
e0605edb6e [ox/mc] Use VLI encoding for integers 2019-03-17 03:04:39 -05:00
817e3fcef1 [ox/mc] Add bytes read to decodeInteger and fix overreading 2019-03-17 01:11:12 -05:00
df44abc316 [ox/mc] Add VLI decode 2019-03-17 00:04:00 -05:00
341dbf14ae [ox/mc] Fix VLI encoding not to chop off ends of >24 bit integers 2019-03-16 23:54:53 -05:00
1780657789 [ox/std] Add Siged and Unsiged templates 2019-03-16 15:50:37 -05:00
585ff0a1fe [ox/std] Add raw to byteswap type 2019-03-16 14:51:09 -05:00
9f805f761d [ox/std] Add noexcept to bitops functions 2019-03-16 14:50:32 -05:00
10b3757558 [ox/std] Add is_signed 2019-03-16 14:49:16 -05:00
e4aab88831 [ox/mc] Fix VLI encoding to handle negatives 2019-03-16 14:41:43 -05:00
a9b7b00011 [ox/ser] Fix to use Error instead of int 2019-03-16 14:39:50 -05:00
80dd6282f5 [ox/std] Add integer size templates 2019-03-16 14:28:11 -05:00
17fc48aa26 [ox/mc] Finish encoding for variable length integers 2019-03-15 01:30:38 -05:00
9e55e5f63c [nostalgia/world] Cleanup field counts for models 2019-03-13 20:22:08 -05:00
e31f51648c [ox/ser] Cleanup 2019-03-13 17:53:33 -05:00
538fcdb43c [ox/ser] Rename McStr to SerStr 2019-03-08 21:26:21 -06:00
4330c015a5 [ox/ser] Fix byte lengths of integer types 2019-03-08 00:21:33 -06:00
e45122184e [ox/mc] Rename FieldPresenceMask to FieldPresenceIndicator 2019-03-07 23:00:59 -06:00
f218ec44af [ox] Split generalizable portion MC into ser package 2019-03-07 21:47:46 -06:00
fa1cf8bb73 [ox] Prefix build setup targets with configure- 2019-03-07 18:04:57 -06:00
e41cb307a7 [nostalgia] Change setup-* targets to configure-* 2019-03-07 18:04:25 -06:00
7ff3b59801 [ox] Change make target to all 2019-03-07 18:02:05 -06:00
5a9ab80753 [nostalgia] Allow studio to build without NOSTALGIA_QT_PATH 2019-03-07 18:00:08 -06:00
c63a18b1dd [nostalgia/devenv] Remove pwsh and libc++ 2019-03-07 17:58:42 -06:00
cd91f6b60a [ox/mc] Add basic walking of data by data descriptor 2019-03-07 06:05:08 -06:00
8b7db3d544 [ox/fs] Remove designated initializer usage 2019-03-04 23:13:55 -06:00
c1fa5dc287 [ox/std] Remove mc usage from std 2019-03-04 22:39:38 -06:00
9f78e2320f [ox/std] Remove implicit signed/unsigned conversions 2019-03-04 21:22:35 -06:00
40dac704d0 [ox/mc] Replace int errors with Error 2019-03-04 21:16:30 -06:00
d51acfd033 [ox/std] Make ox_strlen return std::size 2019-03-04 20:15:53 -06:00
e10594b006 [ox] Enable new compiler warnings 2019-03-04 19:56:57 -06:00
0c570438e4 [ox/fs] Remove C99 designated initializer usage 2019-03-04 19:42:48 -06:00
9844416a4e [ox/std] Remove C-style casts 2019-03-04 19:42:22 -06:00
564ca7511c [ox/std] Add pop_back to Vector 2019-03-02 22:10:12 -06:00
21f5a34b75 [ox/mc] Fix build issues encountered when using MetalClawDefWriter 2019-02-28 23:12:20 -06:00
652b603ec6 [ox/fs] Fix FS to use stdc++fs when building with GNU 2019-02-28 23:10:50 -06:00
ae260e6479 [nostalgia/tools] Remove linking of OxTrace 2019-02-27 23:23:41 -06:00
4b14478e8e [nostalgia] Cleanup Makefile consistency issues 2019-02-27 23:23:10 -06:00
dc3fe3c18e [ox/std] Add maybe_unused to assert check in test to allow release builds 2019-02-25 21:50:52 -06:00
6ddd44828b [ox/std] Add != to BString 2019-02-25 21:46:54 -06:00
0ea44e5ead [ox/mc] Remove walk.cpp from CMake 2019-02-25 20:48:51 -06:00
00544de1d1 [nostalgia] Remove OxTrace linking 2019-02-25 20:48:28 -06:00
c32fe257cc [nostalgia] Add gdblogger config 2019-02-25 20:45:57 -06:00
76830ae91c [nostalgia] Cleanup unnecessary explicit library linkages in CMake files 2019-02-25 20:04:57 -06:00
fb3e94b45c [nostalgia] Fix ioOps to use setTypeInfo instead of setFields 2019-02-25 20:02:15 -06:00
def449607c [ox/mc] Add Walker 2019-02-24 23:57:31 -06:00
3facd25794 [ox] Remove redundant null check before delete 2019-02-24 23:52:14 -06:00
d3f78982e6 [ox/std] Remove incorrect noexcepts from HashMap 2019-02-24 23:49:14 -06:00
805244f796 [ox/std] Add nodiscard to bitops, byteswap, and strops 2019-02-24 09:36:04 -06:00
5a1d1c0a2f [ox] Move buildinfo and trace packages into std 2019-02-23 23:15:09 -06:00
57aa0d556c [ox] Remove VS Code directory 2019-02-23 11:52:44 -06:00
765315b69c [nostalgia] Add option to build without Studio 2019-02-14 23:38:14 +00:00
6b66127691 [ox/std] Add missing constexprs to BString methods 2019-02-14 05:15:53 +00:00
1c64096c38 [ox/mc] Add McStr to wrap C style strings to distinguish them from arrays 2019-02-13 02:42:33 +00:00
c7e9a95a3f [ox/mc] Fix DefWriter to properly detect when to write Types 2019-02-12 06:20:05 +00:00
c8f39af001 [ox/mc] Add Vector handler to Reader and Writer 2019-02-12 05:02:40 +00:00
5c51e17156 [ox/mc] Add Vector handler to DefWriter, add static_assert tests 2019-02-12 03:58:14 +00:00
1c6e40220b [ox/mc] Fix MetalClawDefWriter OpType 2019-02-11 06:51:01 +00:00
75aeedb7b5 [ox/mc] Add def writer 2019-02-11 05:59:33 +00:00
96c56e2589 [ox/std] Make BString constexpr 2019-02-10 07:52:22 +00:00
52536fcb97 [ox/std] Remove unused include from assert.hpp 2019-02-09 07:43:58 +00:00
1a2733f5ce [ox/mc] Fix MC test's incorrect reporting of number of fields 2019-02-09 07:39:55 +00:00
a0290c315a [ox/std] Add missing pragma once to HashMap header 2019-02-09 04:29:32 +00:00
b656fbc3d4 [Nostalgia] Add symlink of compile_commands.json to project root in setup 2019-02-08 23:35:59 +00:00
9ca27361dc [ox/std] Add expand to HashMap 2019-02-03 01:13:35 -06:00
87e6b8d19f [ox/std] Add HashMap 2019-02-02 21:06:42 -06:00
8da1b77aa5 [nostalgia] Port setup-build back to Bash 2019-02-02 21:04:54 -06:00
af0e24d9bf [nostalgia] Switch Studio to PassThroughFS 2019-01-15 22:33:13 -06:00
e5c5c0da43 [ox] Add gdblogger 2019-01-15 22:32:54 -06:00
791c076b51 [ox/fs] Strip leading slashes in PassThroughFS paths 2019-01-15 22:01:30 -06:00
ec6326001d [ox/std] Fix ox_malloca to work outside ox namespace 2019-01-15 17:39:33 -06:00
59ee1ada56 [ox/fs] Add PassthroughFS 2019-01-11 19:39:20 -06:00
55119253da [ox/fs] Make format method static 2018-12-29 22:29:03 -06:00
713aa7380f [ox/fs] Remove old file system code 2018-10-29 22:56:01 -05:00
fdc227cb72 [ox/fs] Fix log channel 2018-10-21 15:29:33 -05:00
77c88515b2 [ox] Make cmake directory structure more consistent with project 2018-10-21 07:21:25 -05:00
f21cb465e6 [ox] Add gdblogger integration 2018-10-21 07:20:49 -05:00
4b70330710 [ox/fs] Fix Directory::mkdir 2018-10-21 07:19:40 -05:00
0ba964a475 [ox/std] Make asserts generate stack traces 2018-09-02 21:11:39 -05:00
72b9437ef5 [ox/fs] Add extra checks to FileSystem test 2018-09-02 10:20:01 -05:00
1770c8a1e2 [ox/fs] Remove abstract FileStore class 2018-09-01 23:52:43 -05:00
6648d941c9 [ox/trace] Add delimiter setter to trace handlers 2018-09-01 21:52:26 -05:00
cbfd9566d1 [ox/fs] Fix FileSystemTemplate::write to create Directory path index 2018-09-01 16:28:36 -05:00
0c6a557878 [ox/fs] Make Directory type a type parameter in FileSystemTemplate 2018-09-01 15:52:59 -05:00
6a82e96db7 [ox] Add vscode files 2018-09-01 15:11:37 -05:00
1f4781f06a [nostalgia] Update Ox includes 2018-09-01 14:46:24 -05:00
e4e8f141b6 [ox/fs] Fix -p write 2018-09-01 01:56:20 -05:00
9472043d80 [ox/fs] Remove completely pointless uses of ox_malloca 2018-09-01 01:17:12 -05:00
e918f2e60e [ox/std] Cleanup MallocaPtr on heap determination 2018-09-01 00:37:53 -05:00
32e2878fb1 [ox/std] Fix errCode extraction incorrect bit shift 2018-08-19 00:06:37 -05:00
338199be12 [ox/std] Further constexpr OxError 2018-08-19 00:02:13 -05:00
f12de38211 [ox/std] Fix oxReturnError to not re-originate the Error 2018-08-18 23:57:59 -05:00
a1b8de0cb0 [ox/fs] Add recursive check on directory remove 2018-08-18 23:49:29 -05:00
40f8af85a8 [ox/fs] Fill out new FileSystem method stubs 2018-08-18 23:41:31 -05:00
3d3ea32357 [ox/fs] Remove erroneous error case 2018-07-31 21:59:58 -05:00
2e19e297d9 [ox/trace] Add environment variable to enable logging 2018-07-30 22:12:20 -05:00
95b72d19fb [nostalgia] Update devenv to Fedora 28 2018-07-30 21:38:30 -05:00
324e28e5f2 [ox/fs] Update FileStore interface 2018-07-30 21:35:36 -05:00
c8ff73b56e [ox/fs] Add template instantiations for FileSystemTemplate 2018-07-30 21:34:40 -05:00
61f77767bf [ox/fs] Add more logging to mkdir test 2018-07-30 21:32:36 -05:00
d97247ffe0 [ox/fs] Fix initial root dir inode 2018-07-30 21:28:16 -05:00
b3bac826f1 [ox/fs] Add missing error and recursion termination checking to Directory::mkdir 2018-07-30 21:12:42 -05:00
71af674eef [ox/fs] Fix inode generation check to check for outside the reserved range 2018-07-30 21:05:36 -05:00
00339ee4fd [ox/fs] Fix PathIterator::valid to check iterator against max size 2018-07-30 21:01:07 -05:00
de2e1bd1d6 [ox/std] Fix onMask's default bits value to use the number of bits instead of bytes 2018-07-08 01:40:53 -05:00
7b9c7ddde4 [ox/std] Change how alloca determines which implementation to use 2018-07-07 14:37:57 -05:00
d28f727742 [ox/std] Add oxReturnError 2018-07-07 14:37:31 -05:00
87b580a72a [ox/std] Add MaxValue constexpr template 2018-07-07 14:36:27 -05:00
86b36b48a3 [ox/trace] Cleanup oxLogError's output 2018-07-07 14:34:36 -05:00
35df47eaf8 [ox/buffer] Add new log messages to NodeBuffer 2018-07-07 14:33:16 -05:00
c35f7abc5b [ox/fs] Add fullPath method to PathIterator 2018-07-07 14:27:17 -05:00
e1494f4ed0 [ox/trace] Fix error logging to not log chars as ints 2018-07-06 22:51:19 -05:00
a6b9de9a59 [ox] Fix OxFS 2 Directory test 2018-06-06 23:30:57 -05:00
ea7cf59ec7 [ox] Add file:line error tracing 2018-05-31 22:45:57 -05:00
956415a6a2 [ox/std] Fix MallocaPtr's move constructor to null out other's m_val 2018-05-31 22:38:36 -05:00
8e7fb4394b [ox/std] Fix packed errors 2018-05-28 20:07:23 -05:00
0da80081f3 [ox/std] Add optional file/line information to ox::Error 2018-05-26 10:20:06 -05:00
d49f35f0f3 [nostalgia] Add OX_USE_STDLIB setting main CMakeLists.txt 2018-05-19 01:47:23 -05:00
2b6ffa3c3f [ox/std] Make assert prints more noticable 2018-05-17 23:26:34 -05:00
a0e336712f [ox/trace] Add column structure to stdout trace messages 2018-05-17 23:12:19 -05:00
0b86f437f0 [ox/std] Make MallocaPtr::operator= delete the old value 2018-05-11 18:27:39 -05:00
99b77e868d [ox/buffer] Remove and and or keywords 2018-05-06 09:53:06 -05:00
610f6f4246 [ox] Fix to build with MinGW 2018-05-05 02:34:55 -05:00
1e82dacd6d [ox/std] Fix new.hpp to correctly look for includes under MinGW 2018-05-04 01:15:37 -05:00
423f575386 [ox/fs] Cleanup 2018-05-04 00:21:50 -05:00
6eec25e4c0 [ox/std] Add ox_strncpy and ox_strnlen 2018-05-04 00:16:24 -05:00
1c16ef2601 [ox/std] Remove copy constructor and operator from MallocaPtr 2018-05-03 23:27:15 -05:00
78a819b360 [ox/trace] Remove use of ::size_t 2018-05-03 01:41:47 -05:00
a8e1197ad0 [ox] Cleanup 2018-05-03 01:33:47 -05:00
576a05a038 [ox/std] Fix non-stdlib version of ox_malloca 2018-05-03 01:32:46 -05:00
87f4964df5 [ox/std] Add some notable missing comments 2018-05-03 01:21:59 -05:00
3a70c0972b [ox/std] Remove ox_freea 2018-05-03 01:17:06 -05:00
ecbeabff48 [ox/std] Add MallocaPtr 2018-05-03 01:12:36 -05:00
85a98222d4 [ox/fs] Cleanup 2018-05-02 22:36:44 -05:00
8a07554c1d [nostalgia] Update vscode settings 2018-05-02 22:32:02 -05:00
a13b369792 [ox/buffer] Add copy constructor to NodeBuffer 2018-05-02 21:12:18 -05:00
6236214be6 [ox/buffer] Add to to Ptr 2018-05-02 21:11:00 -05:00
ad956ffd70 [ox/fs] Fix DirectoryEntry base size 2018-05-02 21:09:31 -05:00
06013211d4 [ox/fs] Fix FileStoreItem::data bounds 2018-05-02 19:45:45 -05:00
a8f185ea57 [ox/std] Fix malloca allocation size 2018-05-01 19:09:34 -05:00
ae31e7f929 [ox/std] Add alloca and malloca 2018-05-01 00:43:25 -05:00
ae484e22c7 [ox/std] Change stddef to use cstddef if using stdlib 2018-04-30 21:08:00 -05:00
f64bcce564 [ox/std] Make rotateLeft a template so it can operate on any size int 2018-04-30 21:05:21 -05:00
4e3c98bcb5 [ox/std] Add missing includes to CMake install 2018-04-28 12:10:53 -05:00
24fbb8ba86 [ox/fs] Add new FileStore write 2018-04-28 12:01:33 -05:00
59cc34b4e8 [ox/fs] Add new Directory type 2018-04-23 22:51:49 -05:00
aeee05be89 [ox/std] Add const to BString's const-able methods 2018-04-14 14:15:04 -05:00
a8b1e25e89 [nostalgia] Fix make purge to delete entire build directory 2018-04-14 11:03:00 -05:00
fc3ec47330 [ox] Move NodeBuffer and Ptr to ptrarith package 2018-04-14 11:01:42 -05:00
b2245cc3b2 [ox] Change make purge to delete root build directory 2018-04-14 00:08:35 -05:00
ec40d80e6d [ox] Remove permanent build directory 2018-04-13 23:52:02 -05:00
7644dfc879 [nostalgia] Add test to Jenkinsfile 2018-04-13 20:53:59 -05:00
263c14e0ff [nostalgia] Cleanup 2018-04-13 19:30:13 -05:00
5ba2936773 [nostalgia/devenv] Set devkitARM environment variable 2018-04-13 19:27:04 -05:00
e463b81e16 [nostalgia] Rename make devenv to make devenv-create 2018-04-13 19:24:45 -05:00
7fe47a237d [nostalgia] Remove usages of ::size_t 2018-04-13 19:23:42 -05:00
26032a9d88 [nostalgia/devenv] Remove dependency on external devenv Docker image 2018-04-13 18:32:25 -05:00
ef8b7d2792 [nostalgia] Set compiler in dev environment 2018-04-13 17:42:20 -05:00
6db4a31916 [ox/std] Make types use cstdint if OX_USE_STDLIB is enabled 2018-04-13 07:41:03 -05:00
77db01b015 [nostalgia] Add Powershell to dev environment 2018-04-13 00:48:14 -05:00
e2fe6f7320 [nostalgia] Add Jenkinsfile 2018-04-12 23:02:36 -05:00
3ebc4e92eb [ox/fs] Add const subPtr methods to ox::fs::Ptr 2018-04-12 19:41:12 -05:00
b8c54eba0c [ox/std] Remove ::size_t 2018-04-12 19:35:16 -05:00
ad62d4c012 [ox/std] Conform size_t to standard 2018-04-12 19:23:12 -05:00
57a9221fb3 [ox/std] Remove bigEndianAdapt 2018-04-12 07:43:58 -05:00
b6f27416c0 [ox/fs] Fix invalid test invocations 2018-04-12 00:26:33 -05:00
9541287d4a [ox/fs] Fix a read/write issue in new FileStore 2018-04-12 00:03:02 -05:00
8094e0fe4d [ox/std] Make strops constexpr functions and use static_assert for tests 2018-04-10 22:35:39 -05:00
585d79a219 Make ASAN a distinct build type from Debug 2018-03-17 23:44:02 -05:00
4c23a2d761 Change buildinfo namespace to defines
Defines better reflects that these are from the defines given for the
current file's compile options, not the options used when building the
Ox libraries being linked against.
2018-03-16 20:29:19 -05:00
e19e70e065 Add read by type to new FileStore 2018-03-15 21:39:07 -05:00
8378af7564 Fix FileStoreData to properly zero out on init 2018-03-15 21:01:26 -05:00
381c739e46 Add missing read to new FileStore 2018-03-15 19:32:40 -05:00
2afef8a741 Make ox::LittleEndian methods constexpr 2018-03-15 18:10:52 -05:00
9d70927ad4 Fix to pass FileStore::readWrite test for new FileStore 2018-03-15 01:03:16 -05:00
db7eb9a397 Add __buildinfo package to ox 2018-03-15 00:38:23 -05:00
b16d781826 Add missing trace message for NodeBuffer::malloc failure case 2018-03-14 00:52:47 -05:00
080ca9df86 Fix new FileStore to correctly initialize the first item 2018-03-14 00:39:08 -05:00
ccf308d022 Fix issues with int to string conversion in ox string operations 2018-03-14 00:20:04 -05:00
13a394e07f Cleanup main CMakeLists.txt to better match CMake conventions 2018-03-13 20:26:12 -05:00
0041d68807 Cleanup main CMakeLists.txt to better match CMake conventions 2018-03-13 20:26:05 -05:00
127c6525f7 Add missing check to ItemPtr and instantiate FileStore32 in FS library 2018-03-13 01:55:25 -05:00
9447967f12 Fully instantiate old FileStore and FileSystem 2018-03-12 20:12:23 -05:00
2ce09ff08a Make new FileStore remove old inode on write 2018-03-11 08:58:14 -05:00
efe8bf3e46 Add write to new FileStore 2018-03-10 23:31:44 -06:00
4d86f0e3d9 Replace C casts with static and reinterpret casts in MC 2018-03-10 01:11:38 -06:00
086b406748 Remove some unnecessary operators from ox::LittleEndian 2018-03-09 21:48:16 -06:00
56ed98268f Add some missing compiler checks to the main CMakeLists.txt 2018-03-09 21:46:47 -06:00
493060955b Cleanup build files 2018-03-09 21:46:17 -06:00
a2cf756f4a Add missing checks to oxfstool 2018-03-09 21:44:41 -06:00
16e0fddaca Remove second copy of mc/optype.hpp 2018-03-08 20:48:00 -06:00
4d6eb5752e Fix nodebuffer.hpp install name 2018-03-08 00:42:08 -06:00
af4ab51df4 Add minimum offset checking to FS Ptr 2018-03-08 00:41:46 -06:00
b77a41abd2 Add NodeBuffer init to FileStore format 2018-03-08 00:24:02 -06:00
2e29f48810 Make FS linked list Item a template parameter 2018-03-07 22:40:38 -06:00
3e63b2f816 Add missing validity checks to file store 2018-03-07 00:15:42 -06:00
3151b5508e Flesh out new file store's alloc 2018-03-06 23:07:39 -06:00
c5bf8591e3 Remove assert implementation on non-stdlib builds, as the asserts use stdlib 2018-03-05 23:14:49 -06:00
c871806822 Cleanup build files 2018-03-05 23:09:50 -06:00
381bfd27a8 Fix warnings 2018-03-05 23:08:54 -06:00
957b94a48d Add asserts.hpp to std.hpp 2018-03-05 23:08:10 -06:00
cfc95b2dd1 Add asserts to ox::fs::Ptr 2018-03-05 23:07:40 -06:00
b616d9c0f2 Add ox_assert to ox/std 2018-03-05 23:07:04 -06:00
85c747ad1a Add missing consts to methods in ox::LittleEndian 2018-03-05 20:39:36 -06:00
e1305a240e Start on new FileStore and add test 2018-03-05 20:28:07 -06:00
cd38c961a3 Add missing operators to LittleEndian type 2018-02-19 21:05:00 -06:00
21e72a0513 Add contiguous linked list type for the new file store 2018-02-18 01:03:14 -06:00
193492c518 Add ox::LittleEndian template 2018-02-17 02:13:19 -06:00
b8a6b47b29 Replace manual library suffix check with QLibrary::isLibrary 2018-02-16 17:16:29 -06:00
d96b8646ce Cleanup new project wizard 2018-02-16 01:10:51 -06:00
4368c1ae4a Remove unnecesary cleanup tasks from Studio MainWindow 2018-02-16 00:54:01 -06:00
c2c87e0363 Restructure plugin system to be more portable 2018-02-16 00:41:00 -06:00
2b8b5661eb Fix Mac VSCode run 2018-02-15 23:20:47 -06:00
7f3cda0ab3 Add ioOp for TraceMsg and cleanup MetalClaw 2018-02-15 22:22:55 -06:00
2b5c34279c Cleanup memory management in Project 2018-02-15 22:21:13 -06:00
de89f86a26 Fix studio for HiDPI on Mac 2018-02-14 22:28:36 -06:00
9d013ff481 Change Mac bunlde to use CMake's Mac bundle feature 2018-02-14 21:05:20 -06:00
7e31eda638 Add static_assert size checks to types.hpp 2018-02-13 19:44:14 -06:00
d3b8e6089b Fix FS include path in Nostalgia 2018-02-13 19:20:20 -06:00
d5b0bb69df Start fleshing out tracing library 2018-02-13 19:13:31 -06:00
7856d4e0bf Fix (u)intmax_t to work on Mac 2018-02-09 00:36:06 -06:00
12c7d8f1c9 Fix to actually use C++14 2018-02-08 00:14:36 -06:00
0b6254a4fb Fix setup-build.ps1 for GBA builds 2018-02-07 21:29:57 -06:00
2141b12b29 Add support for building with a different Qt 2018-02-06 19:20:07 -06:00
e7a396655c Rename Log package to Trace 2018-02-03 14:26:47 -06:00
fc9726b3ec Rename bstring to BString for consistency 2018-02-02 01:30:56 -06:00
690cee7199 Fix FS refactor build issue 2018-02-02 01:29:41 -06:00
d72f11cbdb Run liccor 2018-02-02 01:25:33 -06:00
3edc8be1aa Remove debug code from FileStore 2018-02-02 01:21:54 -06:00
f430d6d398 Update nostalgia to work with file system changes 2018-02-02 01:15:53 -06:00
637c9f24c2 Breakup file system code into smaller files 2018-02-02 01:15:15 -06:00
9ce4835000 Run liccor for 2018 2018-01-30 00:00:39 -06:00
68bb2729d7 Add new Zone wizard 2018-01-29 23:57:15 -06:00
eebce9924d Add compile_commands.json to .gitignore 2018-01-29 23:44:35 -06:00
1692142bae Add VSCode files 2018-01-29 23:44:12 -06:00
3600d88987 Add some overflow checks to FS 2018-01-29 21:57:08 -06:00
04e5af6fe6 Run liccor 2018-01-29 21:55:58 -06:00
3892d52eec Cleanup .gitignore 2018-01-28 00:29:37 -06:00
27b08561e1 Rewrite setup_build in Powershell 2018-01-28 00:26:50 -06:00
ce9bbb7558 Simplify run-make script 2018-01-28 00:25:19 -06:00
e45db79a77 Cleanup ox::Vector organization 2017-12-24 01:45:50 -06:00
7e1866ade9 Remove permanent build directory 2017-12-23 23:38:21 -06:00
ebdd31315d Fix Vector::resize to delete old array 2017-12-23 20:35:10 -06:00
48de8f2561 Fix ox::Vector::~Vector to use delete[] instead of delete 2017-12-23 20:28:15 -06:00
1d65ca210f Rename larray to vector 2017-12-23 20:25:24 -06:00
61de47fd00 Add larray class to ox/std 2017-12-23 17:25:21 -06:00
3d77d6425e Merge commit '12371c21d206cb07a5db91fc81d55cd740bd12f0' 2017-12-22 00:32:18 -06:00
12371c21d2 Squashed 'deps/ox/' changes from c63e0c1..bf5c4e2
bf5c4e2 Add missing optype.hpp file
fdcc303 Removed unused CMake file
4e1f304 Fix version mismatch when loading FileSystems
565c56e Increment FileStore version for inode ID size change
64543b7 Bump FileStore32's InodeId type to uint16_t
fe062cf Add methods for getting array and string length of Metal Claw fields
8deae14 Add general ioOp that will call ioOpRead or ioOpWrite
009cf99 Add OpType for Metal Claw operators
1cf6164 Remove array globals from OxStd, as they were causing section overlaps on GBA
3ffba29 Add op(const char*, (u)int8_t) methods to MetalClaw
489736d Add an optional sizeOut parameter to Metal Claw write
443a62c Fix ArrayLength type case in Metal Claw writer
a46fc8b Add MetalClaw to OxConfig.cmake

git-subtree-dir: deps/ox
git-subtree-split: bf5c4e2c4712b83befff7da25147902408146dd7
2017-12-22 00:31:12 -06:00
4e50d80f5f Add new World wizard 2017-12-20 22:53:33 -06:00
2edee450aa Add support world drawing 2017-11-09 21:43:59 -06:00
539aa1e7eb Remove array globals from OxStd, as they were causing section overlaps
on GBA
2017-11-09 20:14:25 -06:00
08c7647298 Fix issue with part of memory allocator getting optimized out 2017-11-08 23:33:14 -06:00
3097e12e98 Make org name configurable for Studio 2017-10-21 02:44:53 -05:00
6f31e645ec Move application specific state to QSettings 2017-10-21 02:04:18 -05:00
73e0629ab4 Add support for saving window state 2017-10-21 01:39:18 -05:00
b6b9181c66 Restructure Mac builds as Nostalgia.app 2017-10-20 22:17:40 -05:00
2915b48130 Add Session.vim to .gitignore 2017-10-18 00:00:45 -05:00
cbca442f14 Remove old charset.png 2017-10-17 23:58:44 -05:00
5d5e48e1e9 Removed unused CMake file 2017-10-17 23:52:15 -05:00
263111ef4d Remove unused CMake modules 2017-10-17 23:51:12 -05:00
d76dea463c Fix version mismatch when loading FileSystems 2017-10-17 22:09:28 -05:00
0bc0340c20 Increment FileStore version for inode ID size change 2017-10-17 20:51:04 -05:00
8ac88201d7 Fix issue with RPATH on macOS 2017-10-17 19:16:22 -05:00
5922b72326 Bump FileStore32's InodeId type to uint16_t 2017-10-16 21:53:03 -05:00
6d74a3b48e Fix nost-pack bounds check to width and height instead of colorCount... 2017-10-15 21:50:05 -05:00
2554f8b3e1 Add methods for getting array and string length of Metal Claw fields 2017-10-15 09:04:00 -05:00
d096d00bea Add new[] and delete[] operators 2017-10-15 02:48:37 -05:00
2ed10afef7 Add general ioOp that will call ioOpRead or ioOpWrite 2017-10-15 01:40:20 -05:00
70896b8761 Add OpType for Metal Claw operators 2017-10-15 00:55:25 -05:00
6815402ba1 Fix heap delete to work with the moving of the HeapSegment header 2017-10-14 20:58:06 -05:00
fadfeea744 Fix heap allocator to move header and returned address back appropriately 2017-10-14 20:42:24 -05:00
591c738730 Rename build-rom to gba-pkg 2017-10-14 19:45:40 -05:00
9f2441bc82 Fix heap allocator to not pass the meta data portion as output 2017-10-14 18:11:09 -05:00
26f1993f3d Fill out remaining comments for missing characters in charset table 2017-10-14 13:01:40 -05:00
5b628e7ad7 Fix delete operator to move _heapIdx closer to heap start 2017-10-14 12:54:27 -05:00
f6b027c591 Fix heap delete to mark current as not in use, instead of prev 2017-10-14 03:19:20 -05:00
70cee81406 Add more complete implementation for custom new/delete, add panic 2017-10-14 03:16:06 -05:00
dd4556e4e1 Add custom new to GBA build 2017-10-13 10:53:19 -05:00
9c2e71045f Add ioOp functions for Point and Bounds 2017-10-12 16:12:29 -05:00
507c894c15 Add Context to core 2017-10-12 04:52:46 -05:00
329e8be825 Add IDE switch to CMake options, Add charset.png to dist 2017-10-12 00:34:40 -05:00
30a992efad Fixed gba_build to work with the new build files layout 2017-10-11 21:40:35 -05:00
77e0222201 Remove some debug code 2017-10-11 19:51:24 -05:00
8559ab53cc Squashed 'deps/ox/' content from commit c63e0c1
git-subtree-dir: deps/ox
git-subtree-split: c63e0c1d72f30cfb7b3076c69744b0f53d4d79b1
2017-10-11 19:20:46 -05:00
5f0c1a1c41 Merge commit '8559ab53ccc74e63924b4a9a31bc91ee1dafefa9' as 'deps/ox' 2017-10-11 19:20:46 -05:00
f0efe2f9e0 Remove ox subtree 2017-10-11 19:17:48 -05:00
5923f3f0cf Add nostalgia-studio-dev profile 2017-10-06 10:55:01 -05:00
21be39e2c9 Cleanup magic strings in tilesheet importer 2017-09-10 09:20:40 -05:00
89a7ffd45f Add CMakeLists.txt.user to gitignore 2017-09-10 04:11:56 -05:00
9a3dcd0675 Add gdb-studio command to Makefile 2017-09-10 04:09:39 -05:00
7cac015723 Add binary directory in CMake 2017-09-10 04:06:27 -05:00
34e0baff5a Add checks to OxFSTreeView to filter out . and .. entries 2017-09-10 03:45:23 -05:00
71116f4be9 Merge commit '2d1b146abfdf05e8aebdc11738c84d2592b5c3dd' 2017-09-09 22:58:57 -05:00
2d1b146abf Squashed 'deps/ox/' changes from 56d91c1..4887d55
4887d55 Merge branch 'master' of github.com:wombatant/ox
84533e5 Add walk command.
916d07e Merge branch 'master' of github.com:wombatant/ox into ox_master
31af216 Add operator< for DirectoryListing
218511c Fix mkdir not to overwrite an existing dir
15e05df Remove unused scripts
292caad Add link count to stat in FS
99e459a Add links count field to inodes
3211cc4 Add . and .. directory entries to directores
30c2837 Switch to .liccor.yml
16b6ed3 Add a check to ls to prevent ls-ing of non-directories

git-subtree-dir: deps/ox
git-subtree-split: 4887d55a984c0d9c53d9faa9747ef5e9b7c1674a
2017-09-09 20:10:07 -05:00
11c7c49d7b Add some missing field checks to JSON reader 2017-09-08 18:06:27 -05:00
3e90ec87b9 Add $ORIGIN to RPATH 2017-08-20 07:03:25 -05:00
7a6174953d Fix OxFSTreeView to properly list added files 2017-08-19 15:49:05 -05:00
d8a3cd5dfb Add operator< for DirectoryListing 2017-07-28 01:44:18 -05:00
afe2148a17 Fix mkdir not to overwrite an existing dir 2017-07-02 00:42:48 -05:00
57fe7aafc5 Add default ROM.oxfs for new projects 2017-07-01 05:03:52 -05:00
feb7e4c184 Squashed 'deps/ox/' changes from 68c144f..56d91c1
56d91c1 Fix delete/new[] mismatch
8a07138 Fix m_store delete to use delete[]
b4a6aed Change auto expand to own buff attribute in OxFS
7fa43da Make auto expand loop if necessary
c1e8d07 Fix auto expand condition
d43aecd Add auto expand to OxFS
d778570 Merge branch 'master' of github.com:wombatant/ox
4798e54 Add -s flag to nested make calls
038ca96 Add missing error reporting to file system ls
ac3f12f Remove unnecessary ls from FileSystemTemplate
c19a717 Fix readDirectory use the right type of directory
4a44a23 Add default constructor for DirectoryListing

git-subtree-dir: deps/ox
git-subtree-split: 56d91c18bd8a10b5ca5ff3986e44da3b194a09a0
2017-07-01 02:31:26 -05:00
b63b9ffef2 Merge commit 'feb7e4c18450cf6f0b428ffbc1892fd805aa2a7e' 2017-07-01 02:31:26 -05:00
4ae353a9b6 Add check to guard against doing an ls of a non-directory 2017-07-01 01:31:41 -05:00
ca7a1624b5 Fix delete/new[] mismatch 2017-07-01 01:31:09 -05:00
54f929a883 Make NostalgiaStudio library a shared library 2017-06-30 18:00:10 -05:00
f200472c4f Fix possible memory leaks 2017-06-25 06:14:12 -05:00
f245d7d31f Remove already installed packages from devenv 2017-05-27 04:15:02 -05:00
04211bb1ac Fix new project to write full ROM.oxfs buffer 2017-05-27 04:14:23 -05:00
287168a6cc Fix Wizard accept to work with the setAccept accept funcs 2017-05-26 05:04:49 -05:00
38a3113ab6 Make TileSheet import write tilesheets to ROM FS 2017-05-22 01:37:34 -05:00
bc69e67a5b Add PluginArgs for plugin system 2017-05-21 00:15:47 -05:00
6aab7bf2f2 Fix m_store delete to use delete[] 2017-05-20 03:57:17 -05:00
754607fa2d Open new project after creating it 2017-05-20 02:37:39 -05:00
fc71e02fa4 Remove uses of QByteArray from Project 2017-05-20 02:29:19 -05:00
3d8887c6ac Add -s flag to nested make calls 2017-05-19 20:52:27 -05:00
05107858aa Remove empty json_operator.hpp 2017-05-19 20:32:47 -05:00
92197bce9c Fix nostalgia-studio to build with OxFS changes 2017-05-19 20:19:30 -05:00
9d28d20858 Change auto expand to own buff attribute in OxFS 2017-05-19 20:14:51 -05:00
fea0a2e1c3 Make auto expand loop if necessary 2017-05-19 16:37:07 -05:00
8e17515b27 Fix auto expand condition 2017-05-19 16:36:03 -05:00
e195c10d6d Add auto expand to OxFS 2017-05-19 16:31:29 -05:00
c0d1aab3e0 Merge branch 'master' of github.com:wombatant/nostalgia 2017-05-18 16:44:37 -05:00
806325d649 Fix to build on FreeBSD 2017-05-18 16:39:33 -05:00
ee3b15d885 Switch from .liccor to .liccor.yml 2017-05-17 17:29:28 -05:00
de0005d5ee Merge branch 'master' of github.com:wombatant/nostalgia 2017-05-17 15:24:42 -05:00
2fb59e356c Remove vestigial debug line 2017-05-17 15:16:55 -05:00
6ab8ea640f Fix plugin loading to use .dylib extension on Mac 2017-05-17 03:54:20 -05:00
fb52ca6518 Add plugin system 2017-05-17 00:10:16 -05:00
db8ad57828 Add run-studio to Makefile 2017-05-16 13:53:57 -05:00
cf478dcb43 Fix JSON array read 2017-05-16 13:41:39 -05:00
049f0b2245 Restore ability to build GBA roms 2017-05-16 01:35:32 -05:00
1be4adf333 Rename pofile.json to nostalgia-studio.json and install it in share 2017-05-16 00:31:09 -05:00
4a474de9bc Fix common to install in include/nostalgia/common 2017-05-16 00:23:47 -05:00
6ca6ae82ba Add dist directory for gathering builds 2017-05-16 00:17:22 -05:00
2c43777477 Switch from old-style .liccor to new-style .liccor.yml 2017-05-14 23:44:00 -05:00
0ec41de34e Start moving nost-pack into library 2017-05-14 10:40:48 -05:00
9a920c5a99 Add missing error reporting to file system ls 2017-05-13 23:19:17 -05:00
cafc6b7422 Remove unnecessary ls from FileSystemTemplate 2017-05-13 23:14:21 -05:00
a9887c0803 Finish UI for tile sheet importer 2017-05-13 22:42:56 -05:00
90db4e5f18 Add support for reading studio state 2017-05-13 13:42:26 -05:00
e4337e468b Add setFields method to JSON IO types 2017-05-13 02:22:36 -05:00
de35f76917 Add JsonWriter 2017-05-13 02:08:49 -05:00
e79e3756c5 Start on import wizard and move JSON wrappers into NostalgiaStudio library 2017-05-13 00:21:56 -05:00
03d7b5fd26 Add findutils to devenv 2017-05-12 19:08:28 -05:00
84164ab2d2 Remove ox::fs using from GBA package 2017-05-12 19:07:51 -05:00
bfc87b50b1 Add missing nostalgia directory level in src tree 2017-05-12 17:55:18 -05:00
1b9f8f40f4 Add project explorer 2017-05-12 17:20:54 -05:00
cb427dccd0 Fix project name in main CMakeLists.txt 2017-05-12 16:28:59 -05:00
12d3513a50 Fix readDirectory use the right type of directory 2017-05-12 16:26:59 -05:00
00810e9341 Add default constructor for DirectoryListing 2017-05-12 02:34:11 -05:00
059be4e32a Update Ox 2017-05-12 00:29:58 -05:00
f92c8ab577 Squashed 'deps/ox/' changes from a5166e0..68c144f
68c144f Add ls to file system
1ce2797 Flatten out namespaces to only ox
e0063a7 Cleanup oxfstool format output
a2dfb41 Fix FS read by type to read byte by byte

git-subtree-dir: deps/ox
git-subtree-split: 68c144fe755e1f1a6cebb841b6c37b618a35fa43
2017-05-12 00:26:58 -05:00
89a6196b04 Merge commit 'f92c8ab577b28e108464f9b04eaa529fe0add452' 2017-05-12 00:26:58 -05:00
c548d200b6 Add project explorer dock and tab bar 2017-05-11 18:33:01 -05:00
3901493274 Add open project menu item to Nostalgia Studio 2017-05-10 22:45:18 -05:00
c971969a73 Fix FS read by type to read byte by byte 2017-05-09 11:48:58 -05:00
b1e548b96a Squashed 'deps/ox/' content from commit a5166e0
git-subtree-dir: deps/ox
git-subtree-split: a5166e03bbaea2f200cfc730c69579c3d50ae2a7
2017-05-09 01:06:23 -05:00
bb5939a663 Merge commit 'b1e548b96a0a7fbe37ca269ca56fc97444acb2f1' as 'deps/ox' 2017-05-09 01:06:23 -05:00
8778ce8764 Remove existing ox subtree 2017-05-09 00:59:37 -05:00
32926661a1 Cleanup magic numbers and make charset 4 bpp 2017-05-09 00:06:46 -05:00
325259da28 Remove unnecessary memset from FileStore 2017-05-08 00:05:19 -05:00
8a2ba6c171 Cleanup format of GbaImageData 2017-05-07 21:44:52 -05:00
c4da8394d2 Make file system type read byte by byte
The GBA (and other platforms?) seems to have possible alignment issues
with reading from ROM when it's not byte by byte.
2017-05-07 21:26:22 -05:00
a243a38d4d Point CMake to using the subtree copy of Ox 2017-05-06 12:10:40 -05:00
56fb5595f9 Pull in Ox as git subtree 2017-05-06 12:09:42 -05:00
346b01be07 Start on support for 4 bpp images
This may be all that's needed, but there seems to be another issue
causing the characters to look weird, though that's probably a
filesystem issue.
2017-05-05 18:54:13 -05:00
411a3fe65d Fix a non-constant tr("...") 2017-05-04 01:35:37 -05:00
eec9a9d730 Fix issue with deleting old labels in wizard conclusion 2017-05-04 01:23:06 -05:00
9b46116a83 Upgrade ox 2017-05-04 00:57:01 -05:00
258be70528 Add conclusion page to wizard and prevent recreating already existing
projects
2017-05-03 23:20:53 -05:00
973b7e97b1 Add support for line edit validators in wizards 2017-05-03 21:18:06 -05:00
d7a1d19fdf Change the way studio is linked 2017-05-02 18:31:39 -05:00
be9655c0b1 Fix memory leak in studio project create 2017-04-28 13:02:18 -05:00
df76f9eb2c Upgrade Ox 2017-04-21 06:12:17 -05:00
0231d48c91 Adjust size of New wizard 2017-04-21 06:04:42 -05:00
51124966c3 Make New Project create new projects 2017-04-20 23:15:25 -05:00
9730ef773e Add validation to the new project wizard 2017-04-20 18:35:14 -05:00
681eb55db3 Add UI for New Project wizard 2017-04-20 01:39:13 -05:00
5644250e94 Add setup information for building on macOS 2017-04-19 01:23:07 -05:00
7a6934187a Correct the charset inode read for the charset tiles 2017-04-19 01:06:51 -05:00
e0addbdea2 Add New and Quit menu items to menu bar 2017-04-19 00:41:08 -05:00
c1f9630634 Fix alignment issues with writing to VRAM, which is half-word addressable 2017-04-18 17:49:35 -05:00
661e60c24a Add a profile.json file 2017-04-16 03:00:47 -05:00
b447d4c329 Add Nostalgia Studio profile option 2017-04-16 02:56:47 -05:00
60b4a32995 Start on Nostalgia Studio 2017-04-16 01:00:50 -05:00
6b1ccc7ed2 Add support for writing a smaller number of tiles 2017-04-14 23:40:43 -05:00
36124a1738 Cleanup 2017-04-14 06:13:19 -05:00
e6629ad319 Add numbers to charmap 2017-04-14 06:09:51 -05:00
bf78d45b2f Add puts function and call it for Hello, World! 2017-04-14 05:46:28 -05:00
272 changed files with 20206 additions and 909 deletions

12
.gdblogger.json Normal file
View File

@ -0,0 +1,12 @@
{
"log_functions": [
{
"function": "oxTraceHook",
"ignore_frames": 3,
"file_var": "file",
"line_var": "line",
"channel_var": "ch",
"msg_var": "msg"
}
]
}

18
.gitignore vendored
View File

@ -1,5 +1,15 @@
build/current .current_build
build/gba compile_commands.json
build/*-release build
build/*-debug conanbuild
dist
tags tags
nostalgia.gba
nostalgia.sav
nostalgia_media.oxfs
media_header.txt
studio_state.json
CMakeLists.txt.user
Session.vim
ROM.oxfs
graph_info.json

View File

@ -1,5 +0,0 @@
Copyright 2016-2017 gtalent2@gmail.com
This Source Code Form 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 http://mozilla.org/MPL/2.0/.

9
.liccor.yml Normal file
View File

@ -0,0 +1,9 @@
---
source:
- src
copyright_notice: |-
Copyright 2016 - 2020 gtalent2@gmail.com
This Source Code Form 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 http://mozilla.org/MPL/2.0/.

44
.vs/launch.vs.json Normal file
View File

@ -0,0 +1,44 @@
{
"version": "0.2.1",
"defaults": {},
"configurations": [
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia.exe (Install)",
"name": "nostalgia.exe (Install)",
"args": [
"${projectDir}/sample_project"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia.exe",
"name": "nostalgia.exe",
"args": [
"${projectDir}/sample_project"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia-studio.exe (Install)",
"name": "nostalgia-studio.exe (Install)",
"args": [
"-profile",
"${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "nostalgia-studio.exe",
"name": "nostalgia-studio.exe",
"args": [
"-profile",
"${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json"
]
}
]
}

View File

@ -1,35 +1,128 @@
cmake_minimum_required(VERSION 2.8.8) cmake_minimum_required(VERSION 3.12)
project(wombat) project(nostalgia)
set(WOMBAT_BUILD_TYPE "Native" CACHE STRING "The type of build to produce(Native/GBA)") set(NOSTALGIA_BUILD_TYPE "Native" CACHE STRING "The type of build to produce(Native/GBA)")
set(NOSTALGIA_IDE_BUILD ON CACHE STRING "Build for IDE's to run")
set(NOSTALGIA_QT_PATH "" CACHE STRING "Path to Qt Libraries")
set(NOSTALGIA_BUILD_PLAYER ON CACHE BOOL "Build Player")
set(NOSTALGIA_BUILD_STUDIO ON CACHE BOOL "Build Studio")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
include(address_sanitizer) set(NOSTALGIA_BUILD_STUDIO OFF)
set(OX_BARE_METAL ON)
if (WOMBAT_BUILD_TYPE STREQUAL "GBA") set(OX_USE_STDLIB OFF)
include(GBA) else()
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${NOSTALGIA_QT_PATH})
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif() endif()
add_definitions(
-std=c++11
-Wall
-Wsign-compare
-nostdlib
-fno-exceptions
-fno-rtti
#-g
#-fcolor-diagnostics
#--analyze
#-Os # GCC size optimization flag
)
if (CMAKE_BUILD_TYPE STREQUAL "Release") list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
add_definitions( include(GenerateExportHeader)
-Werror include(address_sanitizer)
)
set(NOSTALGIA_CONAN_PATHS ${CMAKE_SOURCE_DIR}/conanbuild/conan_paths.cmake)
if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA" AND EXISTS ${NOSTALGIA_CONAN_PATHS})
include(${NOSTALGIA_CONAN_PATHS})
endif()
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/dist/${NOSTALGIA_BUILD_CONFIG}")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if(NOT OX_BARE_METAL)
add_definitions(-DOX_USE_STDLIB)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
# enable ccache
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DNDEBUG)
endif()
if(NOT MSVC)
# forces colored output when using ninja
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color")
# enable warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-compare")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused-variable")
if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
include(GBA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=arm7tdmi")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=arm7tdmi")
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
endif()
if(NOSTALGIA_IDE_BUILD)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
if(APPLE)
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_PLUGIN 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()
set(CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../lib/nostalgia" "$ORIGIN/../")
if(NOT ${NOSTALGIA_QT_PATH} STREQUAL "")
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} "${NOSTALGIA_QT_PATH}/lib")
endif()
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(NOSTALGIA_DIST_BIN bin)
set(NOSTALGIA_DIST_LIB lib)
set(NOSTALGIA_DIST_PLUGIN lib/nostalgia/plugins)
set(NOSTALGIA_DIST_RESOURCES share)
endif() endif()
enable_testing() enable_testing()
add_subdirectory(deps/ox)
include_directories(SYSTEM deps/ox/src)
if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
add_subdirectory(deps/gbastartup)
endif()
add_subdirectory(src) add_subdirectory(src)

View File

@ -1,33 +1,61 @@
FROM wombatant/devenv FROM fedora:30
ENV DEVKITPRO /opt/devkitPro RUN dnf update -y
ENV DEVKITARM ${DEVKITPRO}/devkitARM
############################################################################### ###############################################################################
# Install Ox # Install gosu
RUN git clone -b release-0.1 https://github.com/wombatant/ox.git /usr/local/src/ox && \ RUN dnf install -y curl gnupg
cd /usr/local/src/ox && \ RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
# setup build dirs RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64" && \
mkdir -p \ curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64.asc" && \
/usr/local/src/ox/build/release \ gpg --verify /usr/local/bin/gosu.asc && \
/usr/local/src/ox/build/windows \ rm /usr/local/bin/gosu.asc && \
/usr/local/src/ox/build/gba; \ chmod +x /usr/local/bin/gosu
# install Ox for native environment
cd /usr/local/src/ox/build/release && \ ###############################################################################
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../../ && \ # Install dev tools
make -j install; \
# install Ox for GBA RUN dnf install -y clang
cd /usr/local/src/ox/build/gba && \ RUN dnf install -y llvm
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ RUN dnf install -y libasan
-DCMAKE_TOOLCHAIN_FILE=cmake/Modules/GBA.cmake \ RUN dnf install -y mingw64-gcc-c++
-DCMAKE_INSTALL_PREFIX=/opt/devkitPro/devkitARM \ RUN dnf install -y cmake
-DOX_USE_STDLIB=OFF ../../ && \ RUN dnf install -y make
make -j install; \ RUN dnf install -y git
# install Ox for Windows RUN dnf install -y vim
cd /usr/local/src/ox/build/windows && \ RUN dnf install -y sudo
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ RUN dnf install -y fuse-devel
-DCMAKE_TOOLCHAIN_FILE=cmake/Modules/Mingw.cmake \ RUN dnf install -y qt5-devel
-DCMAKE_INSTALL_PREFIX=/usr/x86_64-w64-mingw32 \ RUN dnf install -y findutils
-DOX_BUILD_EXEC=OFF ../../ && \ RUN dnf install -y ninja-build
make -j install RUN dnf install -y libcxx-devel libcxxabi-devel
###############################################################################
# Install devkitARM
#RUN dnf install -y lbzip2
#RUN curl -o /tmp/devkitArm.tar.bz2 -SL https://phoenixnap.dl.sourceforge.net/project/devkitpro/devkitARM/devkitARM_r47/devkitARM_r47-x86_64-linux.tar.bz2
#WORKDIR /opt
#RUN tar xf /tmp/devkitArm.tar.bz2
#ENV DEVKITARM /opt/devkitARM
###############################################################################
# Setup sudoers
ADD devenv/sudoers /etc/sudoers
###############################################################################
# Setup working directory
RUN mkdir /usr/src/project
WORKDIR /usr/src/project
###############################################################################
# Setup entrypoint
ADD devenv/entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
ENV CC clang
ENV CXX clang++

134
Makefile
View File

@ -2,83 +2,113 @@ OS=$(shell uname | tr [:upper:] [:lower:])
HOST_ENV=${OS}-$(shell uname -m) HOST_ENV=${OS}-$(shell uname -m)
DEVENV=devenv$(shell pwd | sed 's/\//-/g') DEVENV=devenv$(shell pwd | sed 's/\//-/g')
DEVENV_IMAGE=nostalgia-devenv DEVENV_IMAGE=nostalgia-devenv
ifneq ($(shell which docker),) CURRENT_BUILD=$(file < .current_build)
ifneq ($(shell which docker 2> /dev/null),)
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running) ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV} ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
endif endif
endif endif
make: ifeq ($(OS),windows)
${ENV_RUN} make -j -C build HOST_ENV=${HOST_ENV} RM_RF=Remove-Item -ErrorAction Ignore -Path -Recurse
preinstall: else
${ENV_RUN} make -j -C build ARGS="preinstall" HOST_ENV=${HOST_ENV} RM_RF=rm -rf
endif
ifeq ($(OS),darwin)
NOSTALGIA_STUDIO=./dist/${CURRENT_BUILD}/nostalgia-studio.app/Contents/MacOS/nostalgia-studio
NOSTALGIA_STUDIO_PROFILE=dist/${CURRENT_BUILD}/nostalgia-studio.app/Contents/Resources/nostalgia-studio.json
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
else
NOSTALGIA_STUDIO=./dist/${CURRENT_BUILD}/bin/nostalgia-studio
NOSTALGIA_STUDIO_PROFILE=dist/${CURRENT_BUILD}/share/nostalgia-studio.json
MGBA=mgba-qt
endif
.PHONY: build
build:
$(foreach file, $(wildcard build/*), cmake --build $(file) --target;)
.PHONY: pkg-gba
pkg-gba:
$(foreach file, $(wildcard build/*), cmake --build $(file) --target install;)
${ENV_RUN} ./scripts/gba-pkg sample_project
.PHONY: install
install: install:
${ENV_RUN} make -j -C build ARGS="install" HOST_ENV=${HOST_ENV} $(foreach file, $(wildcard build/*), cmake --build $(file) --target install;)
.PHONY: clean
clean: clean:
${ENV_RUN} make -j -C build ARGS="clean" HOST_ENV=${HOST_ENV} $(foreach file, $(wildcard build/*), cmake --build $(file) --target clean;)
.PHONY: purge
purge: purge:
${ENV_RUN} rm -rf $$(find build -mindepth 1 -maxdepth 1 -type d) ${ENV_RUN} ${RM_RF} build .current_build dist
test: .PHONY: test
${ENV_RUN} make -j -C build ARGS="test" HOST_ENV=${HOST_ENV} test: build
$(foreach file, $(wildcard build/*), cmake --build $(file) --target test;)
run: make .PHONY: run
./build/current/src/player/nostalgia -debug run: install
gba-run: make ${ENV_RUN} ./dist/${CURRENT_BUILD}/bin/nostalgia sample_project
${ENV_RUN} mgba-qt build/current/src/player/nostalgia.bin .PHONY: run-studio
gdb: make run-studio: install
gdb ./build/current/src/wombat/wombat ${ENV_RUN} ${NOSTALGIA_STUDIO} -profile ${NOSTALGIA_STUDIO_PROFILE}
.PHONY: gba-run
gba-run: pkg-gba
${MGBA} nostalgia.gba
.PHONY: gdb
gdb: install
${ENV_RUN} gdb --args ./dist/${CURRENT_BUILD}/bin/nostalgia sample_project
.PHONY: gdb-studio
gdb-studio: install
${ENV_RUN} gdb --args ${NOSTALGIA_STUDIO} -profile ${NOSTALGIA_STUDIO_PROFILE}
devenv-build: .PHONY: devenv-image
docker build --no-cache . -t ${DEVENV_IMAGE} devenv-image:
devenv: docker build . -t ${DEVENV_IMAGE}
docker run -d -v $(shell pwd):/usr/src/project \ .PHONY: devenv-create
devenv-create:
docker run -d \
-e LOCAL_USER_ID=$(shell id -u ${USER}) \ -e LOCAL_USER_ID=$(shell id -u ${USER}) \
-e DISPLAY=$(DISPLAY) \ -e DISPLAY=$(DISPLAY) \
-e QT_AUTO_SCREEN_SCALE_FACTOR=1 \ -e QT_AUTO_SCREEN_SCALE_FACTOR=1 \
-v /tmp/.X11-unix:/tmp/.X11-unix \ -v /tmp/.X11-unix:/tmp/.X11-unix \
-v /run/dbus/:/run/dbus/ \ -v /run/dbus/:/run/dbus/ \
-v $(shell pwd):/usr/src/project \
-v /dev/shm:/dev/shm \ -v /dev/shm:/dev/shm \
--restart=always \ --restart=always \
--name ${DEVENV} \ --name ${DEVENV} \
-t ${DEVENV_IMAGE} bash -t ${DEVENV_IMAGE} bash
.PHONY: devenv-destroy
devenv-destroy: devenv-destroy:
docker rm -f ${DEVENV} docker rm -f ${DEVENV}
.PHONY: devenv-shell
shell: devenv-shell:
${ENV_RUN} bash ${ENV_RUN} bash
release: .PHONY: conan
${ENV_RUN} rm -rf build/${HOST_ENV}-release conan:
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} @mkdir -p conanbuild && cd conanbuild && conan install ../ --build=missing
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-release build/current
debug: .PHONY: configure-release
${ENV_RUN} rm -rf build/${HOST_ENV}-debug configure-release:
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} debug ${ENV_RUN} ${RM_RF} build/${HOST_ENV}-release
${ENV_RUN} rm -f build/current ${ENV_RUN} ./scripts/setup-build ${HOST_ENV} release
${ENV_RUN} ln -s ${HOST_ENV}-debug build/current
windows: .PHONY: configure-debug
${ENV_RUN} rm -rf build/windows configure-debug:
${ENV_RUN} ./scripts/setup_build windows ${ENV_RUN} ${RM_RF} build/${HOST_ENV}-debug
${ENV_RUN} rm -f build/current ${ENV_RUN} ./scripts/setup-build ${HOST_ENV} debug
${ENV_RUN} ln -s windows build/current
windows-debug: .PHONY: configure-asan
${ENV_RUN} rm -rf build/windows configure-asan:
${ENV_RUN} ./scripts/setup_build windows debug ${ENV_RUN} ${RM_RF} build/${HOST_ENV}-asan
${ENV_RUN} rm -f build/current ${ENV_RUN} ./scripts/setup-build ${HOST_ENV} asan
${ENV_RUN} ln -s windows build/current
gba: .PHONY: configure-gba
${ENV_RUN} rm -rf build/gba-release configure-gba:
${ENV_RUN} ./scripts/setup_build gba ${ENV_RUN} ${RM_RF} build/gba-release
${ENV_RUN} rm -f build/current ${ENV_RUN} ./scripts/setup-build gba release
${ENV_RUN} ln -s gba-release build/current
gba-debug: .PHONY: configure-gba-debug
${ENV_RUN} rm -rf build/gba-debug configure-gba-debug:
${ENV_RUN} ./scripts/setup_build gba debug ${ENV_RUN} ${RM_RF} build/gba-debug
${ENV_RUN} rm -f build/current ${ENV_RUN} ./scripts/setup-build gba debug
${ENV_RUN} ln -s gba-debug build/current

View File

@ -1 +1,19 @@
# Nostalgia # Nostalgia
## Setup
### Linux
Make sure conan is using the C++11 version of libstdc++.
conan profile update settings.compiler.libcxx=libstdc++11 default
### macOS
Install and use gmake instead of the make that comes with the system.
## Build
Build options: release, debug, gba, gba-debug
make purge conan configure-{gba,release,debug} install

View File

@ -1,33 +0,0 @@
all: gba_build gba_debug_build native_build native_debug_build windows_release windows_debug
MAKE=make -j
gba_build:
@if [ -d gba-release ]; then \
${MAKE} -C gba-release ${ARGS}; \
fi
gba_debug_build:
@if [ -d gba-debug ]; then \
${MAKE} -C gba-debug ${ARGS}; \
fi
native_build:
@if [ -d ${HOST_ENV}-release ]; then \
${MAKE} -C ${HOST_ENV}-release ${ARGS}; \
fi
native_debug_build:
@if [ -d ${HOST_ENV}-debug ]; then \
${MAKE} -C ${HOST_ENV}-debug ${ARGS}; \
fi
windows_release:
@if [ -d windows-release ]; then \
${MAKE} -C windows-release ${ARGS}; \
fi
windows_debug:
@if [ -d windows-debug ]; then \
${MAKE} -C windows-debug ${ARGS}; \
fi

View File

@ -1,49 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# - Try to find Jansson
# Once done this will define
# JANSSON_FOUND - System has Jansson
# JANSSON_INCLUDE_DIRS - The Jansson include directories
# JANSSON_LIBRARIES - The libraries needed to use Jansson
# JANSSON_DEFINITIONS - Compiler switches required for using Jansson
find_path(JANSSON_INCLUDE_DIR jansson.h
PATHS
/usr/include
/usr/local/include
)
find_library(JANSSON_LIBRARY
NAMES
jansson
PATHS
/usr/lib
/usr/local/lib
)
set(JANSSON_LIBRARIES ${JANSSON_LIBRARY})
set(JANSSON_INCLUDE_DIRS ${JANSSON_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set JANSSON_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(Jansson DEFAULT_MSG
JANSSON_LIBRARY JANSSON_INCLUDE_DIR)
mark_as_advanced(JANSSON_INCLUDE_DIR JANSSON_LIBRARY)

View File

@ -1,4 +0,0 @@
function(BuildStaticLib libName srcFiles)
endfunction()

View File

@ -1,10 +1,5 @@
set(CMAKE_SYSTEM_NAME "Generic") set(CMAKE_SYSTEM_NAME "Generic")
set(DEVKITARM $ENV{DEVKITARM}) set(DEVKITARM $ENV{DEVKITARM})
set(DEVKITPRO $ENV{DEVKITPRO})
if(NOT DEVKITPRO)
message(FATAL_ERROR "DEVKITPRO environment variable not set")
endif()
if(NOT DEVKITARM) if(NOT DEVKITARM)
message(FATAL_ERROR "DEVKITARM environment variable not set") message(FATAL_ERROR "DEVKITARM environment variable not set")
@ -24,18 +19,10 @@ set(CMAKE_FIND_LIBRARY_PREFIXES lib)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a) set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
set(LINKER_FLAGS "-specs=gba.specs") set(LINKER_FLAGS "-specs=gba.specs")
add_definitions ( add_definitions(-DARM7)
-DARM7
)
function(BuildStaticLib LIBNAME SRCFILES)
add_library(${LIBNAME} OBJECT ${SRCFILES})
set(OBJS ${OBJS} $<TARGET_OBJECTS:${LIBNAME}>)
endfunction()
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
macro(OBJCOPY_FILE EXE_NAME) macro(OBJCOPY_FILE EXE_NAME)
set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin) set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin)
set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}) set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})

9
conanfile.py Normal file
View File

@ -0,0 +1,9 @@
from conans import ConanFile, CMake
class NostalgiaConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
requires = "jsoncpp/1.9.2", "sdl2/2.0.10@bincrafters/stable"
generators = "cmake", "cmake_find_package", "cmake_paths"
#default_options = {
# "sdl2:nas": False
#}

12
deps/gbastartup/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,12 @@
enable_language(C ASM)
add_library(
GbaStartup
gba_crt0.s
cstartup.cpp
)
target_link_libraries(
GbaStartup
OxStd
)

63
deps/gbastartup/cstartup.cpp vendored Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/bit.hpp>
#include <ox/std/heapmgr.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
// this warning is too dumb to realize that it can actually confirm the hard
// coded address aligns with the requirement of HeapSegment, so it must be
// suppressed
#pragma GCC diagnostic ignored "-Wcast-align"
#define MEM_WRAM_BEGIN reinterpret_cast<uint8_t*>(0x02000000)
#define MEM_WRAM_END reinterpret_cast<uint8_t*>(0x0203FFFF)
#define HEAP_BEGIN reinterpret_cast<ox::heapmgr::HeapSegment*>(MEM_WRAM_BEGIN)
// set size to half of WRAM
#define HEAP_SIZE ((MEM_WRAM_END - MEM_WRAM_BEGIN) / 2)
#define HEAP_END reinterpret_cast<ox::heapmgr::HeapSegment*>(MEM_WRAM_BEGIN + HEAP_SIZE)
extern void (*__preinit_array_start[]) (void);
extern void (*__preinit_array_end[]) (void);
extern void (*__init_array_start[]) (void);
extern void (*__init_array_end[]) (void);
namespace ox::heapmgr {
void initHeap(char *heapBegin, char *heapEnd);
}
extern "C" {
void __libc_init_array() {
auto preInits = __preinit_array_end - __preinit_array_start;
for (decltype(preInits) i = 0; i < preInits; i++) {
__preinit_array_start[i]();
}
auto inits = __init_array_end - __init_array_start;
for (decltype(inits) i = 0; i < inits; i++) {
__preinit_array_start[i]();
}
}
int main(int argc, const char **argv);
int c_start() {
const char *args[2] = {"", "rom.oxfs"};
ox::heapmgr::initHeap(ox::bit_cast<char*>(HEAP_BEGIN), ox::bit_cast<char*>(HEAP_END));
return main(2, args);
}
}
#pragma GCC diagnostic pop

258
deps/gbastartup/gba_crt0.s vendored Normal file
View File

@ -0,0 +1,258 @@
/*--------------------------------------------------------------------------------
Copyright devkitPro Project
https://github.com/devkitPro/devkitarm-crtls/blob/master/gba_crt0.s
This Source Code Form 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/.
--------------------------------------------------------------------------------*/
.section ".crt0","ax"
.global _start
.align
.arm
.cpu arm7tdmi
@---------------------------------------------------------------------------------
_start:
@---------------------------------------------------------------------------------
b rom_header_end
.fill 156,1,0 @ Nintendo Logo Character Data (8000004h)
.fill 16,1,0 @ Game Title
.byte 0x30,0x31 @ Maker Code (80000B0h)
.byte 0x96 @ Fixed Value (80000B2h)
.byte 0x00 @ Main Unit Code (80000B3h)
.byte 0x00 @ Device Type (80000B4h)
.fill 7,1,0 @ unused
.byte 0x00 @ Software Version No (80000BCh)
.byte 0xf0 @ Complement Check (80000BDh)
.byte 0x00,0x00 @ Checksum (80000BEh)
@---------------------------------------------------------------------------------
rom_header_end:
@---------------------------------------------------------------------------------
b start_vector @ This branch must be here for proper
@ positioning of the following header.
.GLOBAL __boot_method, __slave_number
@---------------------------------------------------------------------------------
__boot_method:
@---------------------------------------------------------------------------------
.byte 0 @ boot method (0=ROM boot, 3=Multiplay boot)
@---------------------------------------------------------------------------------
__slave_number:
@---------------------------------------------------------------------------------
.byte 0 @ slave # (1=slave#1, 2=slave#2, 3=slave#3)
.byte 0 @ reserved
.byte 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.global start_vector
.align
@---------------------------------------------------------------------------------
start_vector:
@---------------------------------------------------------------------------------
mov r0, #0x4000000 @ REG_BASE
str r0, [r0, #0x208]
mov r0, #0x12 @ Switch to IRQ Mode
msr cpsr, r0
ldr sp, =__sp_irq @ Set IRQ stack
mov r0, #0x1f @ Switch to System Mode
msr cpsr, r0
ldr sp, =__sp_usr @ Set user stack
@---------------------------------------------------------------------------------
@ Enter Thumb mode
@---------------------------------------------------------------------------------
add r0, pc, #1
bx r0
.thumb
ldr r0, =__text_start
lsl r0, #5 @ Was code compiled at 0x08000000 or higher?
bcs DoEWRAMClear @ yes, you can not run it in external WRAM
mov r0, pc
lsl r0, #5 @ Are we running from ROM (0x8000000 or higher) ?
bcc SkipEWRAMClear @ No, so no need to do a copy.
@---------------------------------------------------------------------------------
@ We were started in ROM, silly emulators. :P
@ So we need to copy to ExWRAM.
@---------------------------------------------------------------------------------
mov r2, #2
lsl r2, r2, #24 @ r2= 0x02000000
ldr r3, =__end__ @ last ewram address
sub r3, r2 @ r3= actual binary size
mov r6, r2 @ r6= 0x02000000
lsl r1, r2, #2 @ r1= 0x08000000
bl CopyMem
bx r6 @ Jump to the code to execute
@---------------------------------------------------------------------------------
DoEWRAMClear: @ Clear External WRAM to 0x00
@---------------------------------------------------------------------------------
mov r1, #0x40
lsl r1, #12 @ r1 = 0x40000
lsl r0, r1, #7 @ r0 = 0x2000000
bl ClearMem
@---------------------------------------------------------------------------------
SkipEWRAMClear: @ Clear Internal WRAM to 0x00
@---------------------------------------------------------------------------------
@---------------------------------------------------------------------------------
@ Clear BSS section to 0x00
@---------------------------------------------------------------------------------
ldr r0, =__bss_start__
ldr r1, =__bss_end__
sub r1, r0
bl ClearMem
@---------------------------------------------------------------------------------
@ Clear SBSS section to 0x00
@---------------------------------------------------------------------------------
ldr r0, =__sbss_start__
ldr r1, =__sbss_end__
sub r1, r0
bl ClearMem
@---------------------------------------------------------------------------------
@ Copy initialized data (data section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
ldr r1, =__data_lma
ldr r2, =__data_start__
ldr r4, =__data_end__
bl CopyMemChk
@---------------------------------------------------------------------------------
@ Copy internal work ram (iwram section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
ldr r1,= __iwram_lma
ldr r2,= __iwram_start__
ldr r4,= __iwram_end__
bl CopyMemChk
@---------------------------------------------------------------------------------
@ Copy internal work ram overlay 0 (iwram0 section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
ldr r2,= __load_stop_iwram0
ldr r1,= __load_start_iwram0
sub r3, r2, r1 @ Is there any data to copy?
beq CIW0Skip @ no
ldr r2,= __iwram_overlay_start
bl CopyMem
@---------------------------------------------------------------------------------
CIW0Skip:
@---------------------------------------------------------------------------------
@ Copy external work ram (ewram section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
ldr r1, =__ewram_lma
ldr r2, =__ewram_start
ldr r4, =__ewram_end
bl CopyMemChk
@---------------------------------------------------------------------------------
CEW0Skip:
@---------------------------------------------------------------------------------
@ set heap end
@---------------------------------------------------------------------------------
// fake_heap_end does not appear to exist,
// and Nostalgia has its own heap allocator anyway
//ldr r1, =fake_heap_end
//ldr r0, =__eheap_end
//str r0, [r1]
@---------------------------------------------------------------------------------
@ global constructors
@---------------------------------------------------------------------------------
ldr r3, =__libc_init_array
bl _blx_r3_stub
@---------------------------------------------------------------------------------
@ Jump to user code
@---------------------------------------------------------------------------------
ldr r3, =c_start
bl _blx_r3_stub
@---------------------------------------------------------------------------------
@ Clear memory to 0x00 if length != 0
@---------------------------------------------------------------------------------
@ r0 = Start Address
@ r1 = Length
@---------------------------------------------------------------------------------
ClearMem:
@---------------------------------------------------------------------------------
mov r2,#3 @ These commands are used in cases where
add r1,r2 @ the length is not a multiple of 4,
bic r1,r2 @ even though it should be.
beq ClearMX @ Length is zero so exit
mov r2,#0
@---------------------------------------------------------------------------------
ClrLoop:
@---------------------------------------------------------------------------------
stmia r0!, {r2}
sub r1,#4
bne ClrLoop
@---------------------------------------------------------------------------------
ClearMX:
@---------------------------------------------------------------------------------
bx lr
@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
bx r3
@---------------------------------------------------------------------------------
@ Copy memory if length != 0
@---------------------------------------------------------------------------------
@ r1 = Source Address
@ r2 = Dest Address
@ r4 = Dest Address + Length
@---------------------------------------------------------------------------------
CopyMemChk:
@---------------------------------------------------------------------------------
sub r3, r4, r2 @ Is there any data to copy?
@---------------------------------------------------------------------------------
@ Copy memory
@---------------------------------------------------------------------------------
@ r1 = Source Address
@ r2 = Dest Address
@ r3 = Length
@---------------------------------------------------------------------------------
CopyMem:
@---------------------------------------------------------------------------------
mov r0, #3 @ These commands are used in cases where
add r3, r0 @ the length is not a multiple of 4,
bic r3, r0 @ even though it should be.
beq CIDExit @ Length is zero so exit
@---------------------------------------------------------------------------------
CIDLoop:
@---------------------------------------------------------------------------------
ldmia r1!, {r0}
stmia r2!, {r0}
sub r3, #4
bne CIDLoop
@---------------------------------------------------------------------------------
CIDExit:
@---------------------------------------------------------------------------------
bx lr
.align
.pool
.end

12
deps/ox/.gdblogger.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"log_functions": [
{
"function": "ox::trace::gdblogger::captureLogFunc",
"ignore_frames": 3,
"file_var": "file",
"line_var": "line",
"channel_var": "ch",
"msg_var": "msg"
}
]
}

10
deps/ox/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
build/current
build/gba
build/*-asan
build/*-debug
build/*-release
tags
conanbuildinfo.cmake
conanbuildinfo.txt
conaninfo.txt
graph_info.json

9
deps/ox/.liccor.yml vendored Normal file
View File

@ -0,0 +1,9 @@
---
source:
- src
copyright_notice: |-
Copyright 2015 - 2018 gtalent2@gmail.com
This Source Code Form 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 http://mozilla.org/MPL/2.0/.

11
deps/ox/.travis.yml vendored Normal file
View File

@ -0,0 +1,11 @@
language: cpp
sudo: false
dist: trusty
compiler:
- clang
- gcc
addons:
apt:
packages:
- cmake
script: ./scripts/cibuild

76
deps/ox/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,76 @@
cmake_minimum_required(VERSION 3.13)
project(Ox)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
include(address_sanitizer)
if(NOT DEFINED OX_RUN_TESTS)
set(OX_RUN_TESTS ON)
endif()
if(NOT DEFINED OX_BUILD_EXEC)
set(OX_BUILD_EXEC ON)
endif()
if(NOT DEFINED OX_USE_STDLIB)
set(OX_USE_STDLIB ON)
endif()
if(NOT DEFINED OX_BARE_METAL)
set(OX_BARE_METAL OFF)
endif()
set(OX_RUN_TESTS ${OX_RUN_TESTS} CACHE BOOL "Run tests (ON/OFF)")
set(OX_BUILD_EXEC ${OX_BUILD_EXEC} CACHE BOOL "Build executables (ON/OFF)")
set(OX_USE_STDLIB ${OX_USE_STDLIB} CACHE BOOL "Build libraries that need the std lib (ON/OFF)")
set(OX_BARE_METAL ${OX_BARE_METAL} CACHE BOOL "Bare metal build (TRUE/FALSE)")
# can't run tests without building them
if(NOT OX_BUILD_EXEC OR NOT OX_USE_STDLIB)
set(OX_BUILD_EXEC OFF)
set(OX_RUN_TESTS OFF)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(-DNDEBUG)
else()
add_definitions(-DDEBUG)
endif()
if(NOT OX_USE_STDLIB)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
endif()
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-compare")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused-variable")
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
# forces colored output when using ninja
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color")
endif()
enable_testing()
include_directories("src")
install(FILES OxConfig.cmake DESTINATION lib/ox)
add_subdirectory(src)

373
deps/ox/LICENSE vendored Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form 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 http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

68
deps/ox/Makefile vendored Normal file
View File

@ -0,0 +1,68 @@
OS=$(shell uname | tr [:upper:] [:lower:])
HOST_ENV=${OS}-$(shell uname -m)
DEVENV=devenv$(shell pwd | sed 's/\//-/g')
DEVENV_IMAGE=wombatant/devenv
ifneq ($(shell which docker 2>&1),)
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
endif
endif
all:
${ENV_RUN} ./scripts/run-make build
preinstall:
${ENV_RUN} ./scripts/run-make build preinstall
install:
${ENV_RUN} ./scripts/run-make build install
clean:
${ENV_RUN} ./scripts/run-make build clean
purge:
${ENV_RUN} rm -rf build
test:
${ENV_RUN} ./scripts/run-make build test
devenv:
docker pull ${DEVENV_IMAGE}
docker run -d -v $(shell pwd):/usr/src/project \
-e LOCAL_USER_ID=$(shell id -u ${USER}) \
--name ${DEVENV} -t ${DEVENV_IMAGE} bash
devenv-destroy:
docker rm -f ${DEVENV}
devenv-shell:
${ENV_RUN} bash
configure-release:
${ENV_RUN} rm -rf build/${HOST_ENV}-release
${ENV_RUN} ./scripts/setup_build ${HOST_ENV}
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-release build/current
configure-debug:
${ENV_RUN} rm -rf build/${HOST_ENV}-debug
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} debug
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-debug build/current
configure-asan:
${ENV_RUN} rm -rf build/${HOST_ENV}-asan
${ENV_RUN} ./scripts/setup_build ${HOST_ENV} asan
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s ${HOST_ENV}-asan build/current
configure-windows:
${ENV_RUN} rm -rf build/windows
${ENV_RUN} ./scripts/setup_build windows
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s windows build/current
configure-windows-debug:
${ENV_RUN} rm -rf build/windows
${ENV_RUN} ./scripts/setup_build windows debug
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s windows build/current
configure-gba:
${ENV_RUN} rm -rf build/gba-release
${ENV_RUN} ./scripts/setup_build gba
${ENV_RUN} rm -f build/current
${ENV_RUN} ln -s gba-release build/current

15
deps/ox/OxConfig.cmake vendored Normal file
View File

@ -0,0 +1,15 @@
if("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")
set(Ox_INCLUDE_DIRS /usr/local/include/)
set(OxStd_LIBRARY /usr/local/lib/ox/libOxStd.a)
set(OxFS_LIBRARY /usr/local/lib/ox/libOxFS.a)
set(OxClArgs_LIBRARY /usr/local/lib/ox/libOxClArgs.a)
set(OxMetalClaw_LIBRARY /usr/local/lib/ox/libOxMetalClaw.a)
set(OxModel_LIBRARY /usr/local/lib/ox/libOxModelClaw.a)
else("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")
set(Ox_INCLUDE_DIRS ${CMAKE_FIND_ROOT_PATH}/include/)
set(OxStd_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxStd.a)
set(OxFS_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxFS.a)
set(OxClArgs_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxClArgs.a)
set(OxMetalClaw_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxMetalClaw.a)
set(OxModel_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxModel.a)
endif("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")

24
deps/ox/cmake/modules/GBA.cmake vendored Normal file
View File

@ -0,0 +1,24 @@
set(CMAKE_SYSTEM_NAME "Generic")
set(DEVKITARM $ENV{DEVKITARM})
if(NOT DEVKITARM)
message(FATAL_ERROR "DEVKITARM environment variable not set")
endif()
set(CMAKE_C_COMPILER ${DEVKITARM}/bin/arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER ${DEVKITARM}/bin/arm-none-eabi-g++)
set(CMAKE_FIND_ROOT_PATH ${DEVKITARM})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_LIBRARY_PREFIXES lib)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
set(LINKER_FLAGS "-specs=gba.specs")
add_definitions (
-DARM7
)
include(FindPackageHandleStandardArgs)

18
deps/ox/cmake/modules/Mingw.cmake vendored Normal file
View File

@ -0,0 +1,18 @@
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
# cross compilers to use for C and C++
set(CMAKE_C_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
# set 1st to dir with the cross compiler's C/C++ headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -0,0 +1,52 @@
# This file belongs Nick Overdijk, and is from https://github.com/NickNick/wubwubcmake
# The MIT License (MIT)
#
# Copyright (c) 2013 Nick Overdijk
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.option(USE_ASAN "Enable Address Sanitizer, if your compiler supports it" ON)
option(USE_ASAN "Enable Address Sanitizer, if your compiler supports it" OFF)
if(USE_ASAN)
include(CheckCXXSourceCompiles)
# If the compiler understands -fsanitize=address, add it to the flags (gcc since 4.8 & clang since version 3.2)
set(CMAKE_REQUIRED_FLAGS_BAK "${CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fsanitize=address")
CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" FLAG_FSANA_SUPPORTED)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_BAK}")
if(FLAG_FSANA_SUPPORTED)
set(asan_flag "-fsanitize=address")
else(FLAG_FSANA_SUPPORTED)
# Alternatively, try if it understands -faddress-sanitizer (clang until version 3.2)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -faddress-sanitizer")
CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" FLAG_FASAN_SUPPORTED)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_BAK}")
if(FLAG_FASAN_SUPPORTED)
set(asan_flag "-faddress-sanitizer")
endif(FLAG_FASAN_SUPPORTED)
endif(FLAG_FSANA_SUPPORTED)
if(FLAG_FSANA_SUPPORTED OR FLAG_FASAN_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${asan_flag}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${asan_flag}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${asan_flag}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${asan_flag}")
endif()
endif(USE_ASAN)

8
deps/ox/scripts/cibuild vendored Executable file
View File

@ -0,0 +1,8 @@
#! /usr/bin/env bash
set -e
make -j release
make -j debug
make -j
make -j test

8
deps/ox/scripts/run-make vendored Executable file
View File

@ -0,0 +1,8 @@
#! /usr/bin/env bash
set -e
for f in $(find $1 -maxdepth 1 -mindepth 1 -type d)
do
cmake --build "$f" --target $2 --
done

View File

@ -8,13 +8,16 @@ TARGET=$1
BUILD_TYPE=$2 BUILD_TYPE=$2
if [[ $TARGET == windows ]]; then if [[ $TARGET == windows ]]; then
toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/Modules/Mingw.cmake" toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/modules/Mingw.cmake"
elif [[ $TARGET == gba ]]; then elif [[ $TARGET == gba ]]; then
toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/Modules/GBA.cmake -DWOMBAT_BUILD_TYPE=GBA" toolchain="-DCMAKE_TOOLCHAIN_FILE=cmake/modules/GBA.cmake -DOX_USE_STDLIB=OFF -DCMAKE_INSTALL_PREFIX=$DEVKITARM"
fi fi
if [[ $BUILD_TYPE == debug ]]; then if [[ $BUILD_TYPE == asan ]]; then
buildTypeArgs="-DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug" buildTypeArgs="-DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug"
buildDir="build/${TARGET}-asan"
elif [[ $BUILD_TYPE == debug ]]; then
buildTypeArgs="-DCMAKE_BUILD_TYPE=Debug"
buildDir="build/${TARGET}-debug" buildDir="build/${TARGET}-debug"
else else
buildTypeArgs="-DCMAKE_BUILD_TYPE=Release" buildTypeArgs="-DCMAKE_BUILD_TYPE=Release"
@ -24,7 +27,8 @@ fi
mkdir -p $buildDir mkdir -p $buildDir
pushd $buildDir pushd $buildDir
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-GNinja \
$buildTypeArgs \ $buildTypeArgs \
$toolchain \ $toolchain \
$project $project
popd popd

3
deps/ox/src/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
add_subdirectory(ox)

10
deps/ox/src/ox/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,10 @@
if(${OX_USE_STDLIB})
add_subdirectory(clargs)
add_subdirectory(claw)
add_subdirectory(oc)
endif()
add_subdirectory(fs)
add_subdirectory(mc)
add_subdirectory(ptrarith)
add_subdirectory(model)
add_subdirectory(std)

29
deps/ox/src/ox/clargs/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 2.8)
add_library(
OxClArgs
clargs.cpp
)
set_property(
TARGET
OxClArgs
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
target_link_libraries(OxClArgs OxStd)
install(
FILES
clargs.hpp
DESTINATION
include/ox/clargs
)
install(
TARGETS
OxClArgs
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)

53
deps/ox/src/ox/clargs/clargs.cpp vendored Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/strops.hpp>
#include "clargs.hpp"
namespace ox {
using namespace ::std;
ClArgs::ClArgs(int argc, const char **args) {
for (int i = 0; i < argc; i++) {
string arg = args[i];
if (arg[0] == '-') {
while (arg[0] == '-' && arg.size()) {
arg = arg.substr(1);
}
m_bools[arg] = true;
// parse additional arguments
if (i < argc && args[i + 1]) {
string val = args[i + 1];
if (val.size() && val[i] != '-') {
if (val == "false") {
m_bools[arg] = false;
}
m_strings[arg] = val;
m_ints[arg] = ox_atoi(val.c_str());
i++;
}
}
}
}
}
bool ClArgs::getBool(const char *arg) {
return m_bools[arg];
}
string ClArgs::getString(const char *arg) {
return m_strings[arg];
}
int ClArgs::getInt(const char *arg) {
return m_ints[arg];
}
}

32
deps/ox/src/ox/clargs/clargs.hpp vendored Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <map>
#include <string>
namespace ox {
class ClArgs {
private:
::std::map<::std::string, bool> m_bools;
::std::map<::std::string, ::std::string> m_strings;
::std::map<::std::string, int> m_ints;
public:
ClArgs(int argc, const char **args);
bool getBool(const char *arg);
::std::string getString(const char *arg);
int getInt(const char *arg);
};
}

14
deps/ox/src/ox/claw/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,14 @@
add_library(
OxClaw
read.cpp
write.cpp
)
target_link_libraries(
OxClaw
OxMetalClaw
OxOrganicClaw
)
add_subdirectory(test)

12
deps/ox/src/ox/claw/claw.hpp vendored Normal file
View File

@ -0,0 +1,12 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "read.hpp"
#include "write.hpp"

View File

@ -1,18 +1,19 @@
/* /*
* Copyright 2016-2017 gtalent2@gmail.com * Copyright 2016 - 2020 gtalent2@gmail.com
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#pragma once #pragma once
#include "gfx.hpp" namespace ox {
namespace nostalgia { enum class ClawFormat: int {
namespace core { None,
Metal,
ox::Error init(); Organic,
};
} }
}

68
deps/ox/src/ox/claw/read.cpp vendored Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "read.hpp"
namespace ox {
namespace detail {
ValErr<ClawHeader> readHeader(const char *buff, std::size_t buffLen) noexcept {
const auto s1End = ox_strchr(buff, ';', buffLen);
if (!s1End) {
return OxError(1);
}
const auto s1Size = s1End - buff;
String fmt(buff, s1Size);
buff += s1Size + 1;
buffLen -= s1Size + 1;
const auto s2End = ox_strchr(buff, ';', buffLen);
if (!s2End) {
return OxError(1);
}
const auto s2Size = s2End - buff;
String typeName(buff, s2Size);
buff += s2Size + 1;
buffLen -= s2Size + 1;
const auto s3End = ox_strchr(buff, ';', buffLen);
if (!s3End) {
return OxError(1);
}
const auto s3Size = s3End - buff;
String versionStr(buff, s3Size);
buff += s3Size + 1;
buffLen -= s3Size + 1;
ClawHeader hdr;
if (fmt == "M1") {
hdr.fmt = ClawFormat::Metal;
} else if (fmt == "O1") {
hdr.fmt = ClawFormat::Organic;
} else {
return OxError(1);
}
hdr.typeName = typeName;
hdr.typeVersion = ox_atoi(versionStr.c_str());
hdr.data = buff;
hdr.dataSize = buffLen;
return hdr;
}
}
ValErr<Vector<char>> stripClawHeader(const char *buff, std::size_t buffLen) noexcept {
auto header = detail::readHeader(buff, buffLen);
oxReturnError(header);
Vector<char> out(header.value.dataSize);
ox_memcpy(out.data(), header.value.data, out.size());
return ox::move(out);
}
}

57
deps/ox/src/ox/claw/read.hpp vendored Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/mc/read.hpp>
#include <ox/oc/read.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>
#include "format.hpp"
namespace ox {
namespace detail {
struct ClawHeader {
String typeName;
int typeVersion = -1;
ClawFormat fmt = ClawFormat::None;
const char *data = nullptr;
std::size_t dataSize = 0;
};
[[nodiscard]] ValErr<ClawHeader> readHeader(const char *buff, std::size_t buffLen) noexcept;
}
[[nodiscard]] ValErr<Vector<char>> stripClawHeader(const char *buff, std::size_t buffLen) noexcept;
template<typename T>
[[nodiscard]] Error readClaw(char *buff, std::size_t buffLen, T *val) {
auto header = detail::readHeader(buff, buffLen);
oxReturnError(header);
switch (header.value.fmt) {
case ClawFormat::Metal:
{
MetalClawReader reader(bit_cast<uint8_t*>(header.value.data), buffLen);
return model(&reader, val);
}
case ClawFormat::Organic:
{
OrganicClawReader reader(bit_cast<uint8_t*>(header.value.data), buffLen);
return model(&reader, val);
}
case ClawFormat::None:
return OxError(1);
}
return OxError(1);
}
}

14
deps/ox/src/ox/claw/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,14 @@
add_executable(
ClawTest
tests.cpp
)
target_link_libraries(
ClawTest
OxClaw
)
add_test("Test\\ ClawTest\\ ClawHeaderReader" ClawTest ClawHeaderReader)
add_test("Test\\ ClawTest\\ ClawHeaderReader2" ClawTest ClawHeaderReader2)
add_test("Test\\ ClawTest\\ ClawWriter" ClawTest ClawWriter)
add_test("Test\\ ClawTest\\ ClawReader" ClawTest ClawReader)

206
deps/ox/src/ox/claw/test/tests.cpp vendored Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#undef NDEBUG
#include <assert.h>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <ox/claw/format.hpp>
#include <ox/claw/read.hpp>
#include <ox/claw/write.hpp>
#include <ox/mc/mc.hpp>
#include <ox/model/model.hpp>
#include <ox/std/std.hpp>
union TestUnion {
static constexpr auto TypeName = "TestUnion";
static constexpr auto Fields = 3;
bool Bool;
uint32_t Int = 5;
char String[32];
};
struct TestStructNest {
static constexpr auto TypeName = "TestStructNest";
static constexpr auto Fields = 3;
bool Bool = false;
uint32_t Int = 0;
ox::BString<32> String = "";
};
struct TestStruct {
static constexpr auto TypeName = "TestStruct";
static constexpr auto Fields = 16;
bool Bool = false;
int32_t Int = 0;
int32_t Int1 = 0;
int32_t Int2 = 0;
int32_t Int3 = 0;
int32_t Int4 = 0;
int32_t Int5 = 0;
int32_t Int6 = 0;
int32_t Int7 = 0;
int32_t Int8 = 0;
TestUnion Union;
char *CString = nullptr;
ox::BString<32> String = "";
uint32_t List[4] = {0, 0, 0, 0};
TestStructNest EmptyStruct;
TestStructNest Struct;
~TestStruct() {
delete[] CString;
}
};
template<typename T>
ox::Error model(T *io, TestUnion *obj) {
io->template setTypeInfo<TestUnion>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", ox::SerStr(obj->String)));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStructNest *obj) {
io->template setTypeInfo<TestStructNest>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStruct *obj) {
io->template setTypeInfo<TestStruct>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
oxReturnError(io->field("CString", ox::SerStr(&obj->CString)));
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct));
return OxError(0);
}
std::map<std::string, ox::Error(*)()> tests = {
{
{
"ClawHeaderReader",
[] {
ox::String hdr = "O1;com.drinkingtea.ox.claw.test.Header;2;";
auto [ch, err] = ox::detail::readHeader(hdr.c_str(), hdr.len() + 1);
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
oxAssert(ch.typeVersion == 2, "Type version wrong");
return OxError(0);
}
},
{
"ClawHeaderReader2",
[] {
ox::String hdr = "M1;com.drinkingtea.ox.claw.test.Header2;3;";
auto [ch, err] = ox::detail::readHeader(hdr.c_str(), hdr.len() + 1);
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
oxAssert(ch.typeVersion == 3, "Type version wrong");
return OxError(0);
}
},
{
"ClawWriter",
[] {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
TestStruct ts;
oxReturnError(ox::writeClaw(&ts, ox::ClawFormat::Metal));
return OxError(0);
}
},
{
"ClawReader",
[] {
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
testIn.Union.Int = 42;
testIn.String = "Test String 1";
testIn.CString = new char[ox_strlen("c-string") + 1];
ox_strcpy(testIn.CString, "c-string");
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [buff, err] = ox::writeClaw(&testIn, ox::ClawFormat::Metal);
oxAssert(err, "writeMC failed");
oxAssert(ox::readClaw(buff.data(), buff.size(), &testOut), "writeMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");
oxAssert(testIn.Int2 == testOut.Int2, "Int2 value mismatch");
oxAssert(testIn.Int3 == testOut.Int3, "Int3 value mismatch");
oxAssert(testIn.Int4 == testOut.Int4, "Int4 value mismatch");
oxAssert(testIn.Int5 == testOut.Int5, "Int5 value mismatch");
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
oxAssert(ox_strcmp(testIn.CString, testOut.CString) == 0, "CString value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch");
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
oxAssert(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
oxAssert(testIn.EmptyStruct.String == testOut.EmptyStruct.String, "EmptyStruct.String value mismatch");
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0);
}
},
}
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 0) {
auto testName = args[1];
if (tests.find(testName) != tests.end()) {
retval = tests[testName]();
} else {
retval = 1;
}
}
return retval;
}

23
deps/ox/src/ox/claw/write.cpp vendored Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "write.hpp"
namespace ox::detail {
struct versioned_type {
static constexpr int TypeVersion = 4;
};
struct unversioned_type {
};
static_assert(type_version<versioned_type>::value == 4);
static_assert(type_version<unversioned_type>::value == -1);
}

104
deps/ox/src/ox/claw/write.hpp vendored Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright 2016 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/mc/write.hpp>
#include <ox/oc/write.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>
#include "format.hpp"
namespace ox {
namespace detail {
struct TypeInfoCatcher {
const char *name = nullptr;
template<typename T = void>
constexpr void setTypeInfo(const char *name = T::TypeName, int = T::Fields) noexcept {
this->name = name;
}
constexpr ox::Error field(...) noexcept {
return OxError(0);
}
static constexpr auto opType() {
return OpType::Write;
}
};
template<typename T>
[[nodiscard]] constexpr int getTypeVersion(int version = T::TypeVersion) noexcept {
return version;
}
[[nodiscard]] constexpr int getTypeVersion(...) noexcept {
return -1;
}
template<typename T, typename = int>
struct type_version {
static constexpr auto value = -1;
};
template<typename T>
struct type_version<T, decltype((void) T::TypeVersion, -1)> {
static constexpr auto value = T::TypeVersion;
};
template<typename T>
constexpr const char *getTypeName(T *t) noexcept {
TypeInfoCatcher tnc;
model(&tnc, t);
return tnc.name;
}
template<typename T>
ValErr<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
String out;
switch (fmt) {
case ClawFormat::Metal:
out += "M1;";
break;
case ClawFormat::Organic:
out += "O1;";
break;
default:
return OxError(1);
}
out += detail::getTypeName(t);
out += ";";
const auto tn = detail::type_version<T>::value;
if (tn > -1) {
out += tn;
}
out += ";";
return out;
}
}
template<typename T>
ValErr<Vector<char>> writeClaw(T *t, ClawFormat fmt) {
auto [header, headerErr] = detail::writeClawHeader(t, fmt);
oxReturnError(headerErr);
const auto [data, dataErr] = fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t);
oxReturnError(dataErr);
ox::Vector<char> out(header.len() + data.size());
memcpy(out.data(), header.data(), header.len());
memcpy(out.data() + header.len(), data.data(), data.size());
return out;
}
}

71
deps/ox/src/ox/fs/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,71 @@
add_library(
OxFS
filestore/filestoretemplate.cpp
filesystem/filelocation.cpp
filesystem/pathiterator.cpp
filesystem/directory.cpp
filesystem/filesystem.cpp
filesystem/passthroughfs.cpp
)
if(NOT OX_BARE_METAL)
if(NOT APPLE)
target_link_libraries(
OxFS PUBLIC
stdc++fs
)
endif()
set_property(
TARGET
OxFS
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
endif()
target_link_libraries(
OxFS PUBLIC
OxMetalClaw
)
if(OX_BUILD_EXEC STREQUAL "ON")
#add_executable(
# oxfstool
# toollib.cpp
# oxfstool.cpp
#)
#set_target_properties(oxfstool PROPERTIES OUTPUT_NAME oxfs)
#target_link_libraries(
# oxfstool
# OxFS
# OxMetalClaw
# OxStd
#)
endif()
install(
FILES
filestore/filestoretemplate.hpp
DESTINATION
include/ox/fs/filestore
)
install(
FILES
filesystem/filesystem.hpp
filesystem/pathiterator.hpp
DESTINATION
include/ox/fs/filesystem
)
install(
TARGETS
OxFS
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)
if(OX_RUN_TESTS)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,16 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "filestoretemplate.hpp"
namespace ox {
template class FileStoreTemplate<uint16_t>;
template class FileStoreTemplate<uint32_t>;
}

View File

@ -0,0 +1,777 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/ptrarith/nodebuffer.hpp>
namespace ox {
using InodeId_t = uint64_t;
using FsSize_t = std::size_t;
struct StatInfo {
InodeId_t inode = 0;
InodeId_t links = 0;
FsSize_t size = 0;
uint8_t fileType = 0;
};
template<typename size_t>
struct OX_PACKED FileStoreItem: public ptrarith::Item<size_t> {
ox::LittleEndian<size_t> id = 0;
ox::LittleEndian<uint8_t> fileType = 0;
ox::LittleEndian<size_t> links = 0;
ox::LittleEndian<size_t> left = 0;
ox::LittleEndian<size_t> right = 0;
FileStoreItem() = default;
explicit FileStoreItem(size_t size) {
this->setSize(size);
}
/**
* @return the size of the data + the size of the Item type
*/
size_t fullSize() const {
return sizeof(*this) + this->size();
}
ptrarith::Ptr<uint8_t, std::size_t> data() {
return ptrarith::Ptr<uint8_t, std::size_t>(this, this->fullSize(), sizeof(*this), this->size());
}
};
template<typename size_t>
class FileStoreTemplate {
public:
using InodeId_t = size_t;
private:
using Item = FileStoreItem<size_t>;
using ItemPtr = typename ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>::ItemPtr;
using Buffer = ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>;
static constexpr InodeId_t ReservedInodeEnd = 100;
static constexpr auto MaxInode = MaxValue<size_t> / 2;
struct OX_PACKED FileStoreData {
ox::LittleEndian<size_t> rootNode = 0;
ox::Random random;
};
size_t m_buffSize = 0;
mutable Buffer *m_buffer = nullptr;
public:
FileStoreTemplate() = default;
FileStoreTemplate(void *buff, size_t buffSize);
[[nodiscard]] static Error format(void *buffer, size_t bufferSize);
[[nodiscard]] Error setSize(InodeId_t buffSize);
[[nodiscard]] Error incLinks(InodeId_t id);
[[nodiscard]] Error decLinks(InodeId_t id);
[[nodiscard]] Error write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType = 0);
[[nodiscard]] Error remove(InodeId_t id);
[[nodiscard]] Error read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size = nullptr) const;
[[nodiscard]] Error read(InodeId_t id, FsSize_t readStart, FsSize_t readSize, void *data, FsSize_t *size = nullptr) const;
const ptrarith::Ptr<uint8_t, std::size_t> read(InodeId_t id) const;
/**
* Reads the "file" at the given id. You are responsible for freeing
* the data when done with it.
* @param id id of the "file"
* @param readStart where in the data to start reading
* @param readSize how much data to read
* @param data pointer to the pointer where the data is stored
* @param size pointer to a value that will be assigned the size of data
* @return 0 if read is a success
*/
template<typename T>
[[nodiscard]] ox::Error read(InodeId_t id, FsSize_t readStart,
FsSize_t readSize, T *data,
FsSize_t *size) const;
[[nodiscard]] ValErr<StatInfo> stat(InodeId_t id);
[[nodiscard]] ox::Error resize();
[[nodiscard]] ox::Error resize(std::size_t size, void *newBuff = nullptr);
[[nodiscard]] InodeId_t spaceNeeded(FsSize_t size);
[[nodiscard]] InodeId_t size() const;
[[nodiscard]] InodeId_t available();
[[nodiscard]] char *buff();
[[nodiscard]] Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t));
[[nodiscard]] ValErr<InodeId_t> generateInodeId();
bool valid() const;
[[nodiscard]] ox::Error compact();
private:
FileStoreData *fileStoreData() const;
/**
* Places the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error placeItem(ItemPtr item);
/**
* Places the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error placeItem(ItemPtr root, ItemPtr item, int depth = 0);
/**
* Removes the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error unplaceItem(ItemPtr item);
/**
* Removes the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error unplaceItem(ItemPtr root, ItemPtr item, int depth = 0);
Error remove(ItemPtr item);
/**
* Finds the parent an inode by its ID.
*/
ItemPtr findParent(ItemPtr ptr, size_t id, size_t oldAddr) const;
/**
* Finds an inode by its ID.
*/
ItemPtr find(ItemPtr item, InodeId_t id, int depth = 0) const;
/**
* Finds an inode by its ID.
*/
ItemPtr find(InodeId_t id) const;
/**
* Gets the root inode.
*/
ItemPtr rootInode();
bool canWrite(ItemPtr existing, size_t size);
};
template<typename size_t>
FileStoreTemplate<size_t>::FileStoreTemplate(void *buff, size_t buffSize) {
m_buffSize = buffSize;
m_buffer = reinterpret_cast<ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>*>(buff);
if (!m_buffer->valid(buffSize)) {
m_buffSize = 0;
m_buffer = nullptr;
}
}
template<typename size_t>
Error FileStoreTemplate<size_t>::format(void *buffer, size_t bufferSize) {
auto nb = new (buffer) Buffer(bufferSize);
auto fsData = nb->malloc(sizeof(FileStoreData));
if (fsData.valid()) {
auto data = nb->template dataOf<FileStoreData>(fsData);
if (data.valid()) {
new (data) FileStoreData;
return OxError(0);
} else {
oxTrace("ox::fs::FileStoreTemplate::format::fail") << "Could not read data section of FileStoreData";
}
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::setSize(InodeId_t size) {
if (m_buffSize >= size) {
return m_buffer->setSize(size);
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(InodeId_t id) {
auto item = find(id);
if (item.valid()) {
item->links++;
return OxError(0);
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::decLinks(InodeId_t id) {
auto item = find(id);
if (item.valid()) {
item->links--;
if (item->links == 0) {
remove(item);
}
return OxError(0);
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::write(InodeId_t id, void *data, FsSize_t dataSize, uint8_t fileType) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Attempting to write to inode" << id;
auto existing = find(id);
if (!canWrite(existing, dataSize)) {
oxReturnError(compact());
existing = find(id);
}
if (canWrite(existing, dataSize)) {
// delete the old node if it exists
if (existing.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Freeing old version of inode found at offset:" << existing.offset();
auto err = m_buffer->free(existing);
if (err) {
oxTrace("ox::fs::FileStoreTemplate::write::fail") << "Free of old version of inode failed";
return err;
}
existing = nullptr;
}
// write the given data
auto dest = m_buffer->malloc(dataSize);
// if first malloc failed, compact and try again
if (!dest.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Allocation failed, compacting";
oxReturnError(compact());
dest = m_buffer->malloc(dataSize);
}
if (dest.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Memory allocated";
dest->id = id;
dest->fileType = fileType;
auto destData = m_buffer->template dataOf<uint8_t>(dest);
if (destData.valid()) {
oxAssert(destData.size() == dataSize, "Allocation size does not match data.");
// write data if any was provided
if (data != nullptr) {
ox_memcpy(destData, data, dest->size());
oxTrace("ox::fs::FileStoreTemplate::write") << "Data written";
}
auto fsData = fileStoreData();
if (fsData) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Searching for root node at" << fsData->rootNode;
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Placing" << dest->id << "on" << root->id << "at" << destData.offset();
return placeItem(dest);
} else {
oxTrace("ox::fs::FileStoreTemplate::write") << "Initializing root inode:" << dest->id << "( offset:" << dest.offset()
<< ", data size:" << destData.size() << ")";
fsData->rootNode = dest.offset();
oxTrace("ox::fs::FileStoreTemplate::write") << "Root inode:" << dest->id;
return OxError(0);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::write::fail") << "Could not place item due to absence of FileStore header.";
}
}
}
oxReturnError(m_buffer->free(dest));
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::remove(InodeId_t id) {
return remove(find(id));
}
template<typename size_t>
Error FileStoreTemplate<size_t>::read(InodeId_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
oxTrace("ox::fs::FileStoreTemplate::read") << "Attempting to read from inode" << id;
auto src = find(id);
// error check
if (!src.valid()) {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not find requested item:" << id;
return OxError(1);
}
auto srcData = m_buffer->template dataOf<uint8_t>(src);
oxTrace("ox::fs::FileStoreTemplate::read::found") << id << "found at"<< src.offset()
<< "with data section at" << srcData.offset();
oxTrace("ox::fs::FileStoreTemplate::read::outSize") << srcData.offset() << srcData.size() << outSize;
// error check
if (!(srcData.valid() && srcData.size() <= outSize)) {
oxTrace("ox::fs::FileStoreTemplate::read::fail")
<< "Could not read data section of item:" << id;
oxTrace("ox::fs::FileStoreTemplate::read::fail").del("")
<< "Item data section size: " << srcData.size()
<< ", Expected size: " << outSize;
return OxError(1);
}
ox_memcpy(out, srcData, srcData.size());
if (size) {
*size = src.size();
}
return OxError(0);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart, FsSize_t readSize, void *data, FsSize_t *size) const {
auto src = find(id);
if (src.valid()) {
auto srcData = src->data();
if (srcData.valid()) {
auto sub = srcData.template subPtr<uint8_t>(readStart, readSize);
if (sub.valid()) {
ox_memcpy(data, sub, sub.size());
if (size) {
*size = sub.size();
}
return OxError(0);
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not read requested data sub-section of item:" << id;
}
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not read data section of item:" << id;
}
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not find requested item:" << id;
}
return OxError(1);
}
template<typename size_t>
template<typename T>
Error FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart,
FsSize_t readSize, T *data, FsSize_t *size) const {
auto src = find(id);
if (src.valid()) {
auto srcData = src->data();
if (srcData.valid()) {
auto sub = srcData.template subPtr<uint8_t>(readStart, readSize);
if (sub.valid() && sub.size() % sizeof(T)) {
for (FsSize_t i = 0; i < sub.size() / sizeof(T); i++) {
// do byte-by-byte copy to ensure alignment is right when
// copying to final destination
T tmp;
for (size_t ii = 0; ii < sizeof(T); ii++) {
reinterpret_cast<uint8_t*>(&tmp)[ii] = *(sub.get() + ii);
}
*(data + i) = tmp;
}
if (size) {
*size = sub.size();
}
return OxError(0);
}
}
}
return OxError(1);
}
template<typename size_t>
const ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(InodeId_t id) const {
auto item = find(id);
if (item.valid()) {
return item->data();
} else {
return nullptr;
}
}
template<typename size_t>
ox::Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact());
const auto newSize = size() - available();
oxTrace("ox::fs::FileStoreTemplate::resize") << "resize to:" << newSize;
oxReturnError(m_buffer->setSize(newSize));
oxTrace("ox::fs::FileStoreTemplate::resize") << "resized to:" << m_buffer->size();
return OxError(0);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) {
return OxError(1);
}
m_buffSize = size;
if (newBuff) {
m_buffer = reinterpret_cast<Buffer*>(newBuff);
oxReturnError(m_buffer->setSize(size));
}
return OxError(0);
}
template<typename size_t>
ValErr<StatInfo> FileStoreTemplate<size_t>::stat(InodeId_t id) {
auto inode = find(id);
if (inode.valid()) {
return ValErr<StatInfo>({
id,
inode->links,
inode->size(),
inode->fileType,
});
}
return ValErr<StatInfo>({}, OxError(0));
}
template<typename size_t>
typename FileStoreTemplate<size_t>::InodeId_t FileStoreTemplate<size_t>::spaceNeeded(FsSize_t size) {
return m_buffer->spaceNeeded(size);
}
template<typename size_t>
typename FileStoreTemplate<size_t>::InodeId_t FileStoreTemplate<size_t>::size() const {
return m_buffer->size();
}
template<typename size_t>
typename FileStoreTemplate<size_t>::InodeId_t FileStoreTemplate<size_t>::available() {
return m_buffer->available();
}
template<typename size_t>
char *FileStoreTemplate<size_t>::buff() {
return reinterpret_cast<char*>(m_buffer);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
oxReturnError(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
}
return OxError(0);
}
template<typename size_t>
ValErr<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() {
auto fsData = fileStoreData();
if (fsData) {
for (auto i = 0; i < 100; i++) {
auto inode = fsData->random.gen() % MaxValue<InodeId_t>;
if (inode > ReservedInodeEnd && !find(inode).valid()) {
return inode;
}
}
return {0, OxError(2)};
}
return {0, OxError(1)};
}
template<typename size_t>
ox::Error FileStoreTemplate<size_t>::compact() {
auto isFirstItem = true;
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> ox::Error {
if (isFirstItem) {
isFirstItem = false;
return OxError(0);
}
if (!item.valid()) {
return OxError(1);
}
oxTrace("ox::FileStoreTemplate::compact::moveItem")
<< "Moving Item:" << item->id
<< "from" << oldAddr
<< "to" << item.offset();
// update rootInode if this is it
auto fsData = fileStoreData();
if (fsData && oldAddr == fsData->rootNode) {
fsData->rootNode = item.offset();
}
auto parent = findParent(rootInode(), item->id, oldAddr);
oxAssert(parent.valid() || rootInode() == item.offset(),
"Parent inode not found for item that should have parent.");
if (parent.valid()) {
if (parent->left == oldAddr) {
parent->left = item;
} else if (parent->right == oldAddr) {
parent->right = item;
}
}
return OxError(0);
});
}
template<typename size_t>
typename FileStoreTemplate<size_t>::FileStoreData *FileStoreTemplate<size_t>::fileStoreData() const {
auto first = m_buffer->firstItem();
if (first.valid()) {
auto data = first->data();
if (data.valid()) {
return reinterpret_cast<FileStoreData*>(data.get());
}
}
return nullptr;
}
template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
auto fsData = fileStoreData();
if (fsData) {
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
if (root->id == item->id) {
fsData->rootNode = item;
item->left = root->left;
item->right = root->right;
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Overwrote Root Item:" << item->id;
return OxError(0);
} else {
return placeItem(root, item);
}
}
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth < 5000) {
if (item->id > root->id) {
auto right = m_buffer->ptr(root->right);
if (!right.valid() || right->id == item->id) {
root->right = item.offset();
if (right.valid()) {
item->left = right->left;
item->right = right->right;
}
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return placeItem(right, item, depth + 1);
}
} else if (item->id < root->id) {
auto left = m_buffer->ptr(root->left);
if (!left.valid() || left->id == item->id) {
root->left = item.offset();
if (left.valid()) {
item->left = left->left;
item->right = left->right;
}
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return placeItem(left, item, depth + 1);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail") << "Cannot insert an item on itself.";
return OxError(1);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail") << "Excessive recursion depth, stopping before stack overflow.";
return OxError(2);
}
}
template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
auto fsData = fileStoreData();
if (fsData) {
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
if (root->id == item->id) {
item->left = root->left;
item->right = root->right;
auto left = m_buffer->ptr(item->left);
auto right = m_buffer->ptr(item->right);
if (right.valid()) {
auto oldRoot = fsData->rootNode;
fsData->rootNode = item->right;
if (left.valid()) {
auto err = placeItem(left);
// undo if unable to place the left side of the tree
if (err) {
fsData->rootNode = oldRoot;
return err;
}
}
} else if (left.valid()) {
fsData->rootNode = item->left;
} else {
fsData->rootNode = 0;
}
return OxError(0);
} else {
return unplaceItem(root, item);
}
}
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth >= 5000) {
oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail") << "Excessive recursion depth, stopping before stack overflow.";
return OxError(1);
}
if (item->id > root->id) {
auto right = m_buffer->ptr(root->right);
if (right->id == item->id) {
root->right = 0;
oxTrace("ox::fs::FileStoreTemplate::unplaceItem") << "Unplaced Item:" << item->id;
} else {
return unplaceItem(right, item, depth + 1);
}
} else if (item->id < root->id) {
auto left = m_buffer->ptr(root->left);
if (left->id == item->id) {
root->left = 0;
oxTrace("ox::fs::FileStoreTemplate::unplaceItem") << "Unplaced Item:" << item->id;
} else {
return unplaceItem(left, item, depth + 1);
}
} else {
return OxError(1);
}
if (item->right) {
oxReturnError(placeItem(m_buffer->ptr(item->right)));
}
if (item->left) {
oxReturnError(placeItem(m_buffer->ptr(item->left)));
}
return OxError(0);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) {
oxReturnError(unplaceItem(item));
oxReturnError(m_buffer->free(item));
return OxError(0);
}
return OxError(1);
}
template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::findParent(ItemPtr item, size_t id, size_t oldAddr) const {
// This is a little bit confusing. findParent uses the inode ID to find
// where the target ID should be, but the actual address of that item is
// currently invalid, so we check it against what is known to be the old
// address of the item to confirm that we have the right item.
if (item.valid()) {
if (id > item->id) {
if (item->right == oldAddr) {
return item;
} else {
auto right = m_buffer->ptr(item->right);
return findParent(right, id, oldAddr);
}
} else if (id < item->id) {
if (item->left == oldAddr) {
return item;
} else {
auto left = m_buffer->ptr(item->left);
return findParent(left, id, oldAddr);
}
}
}
return nullptr;
}
template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(ItemPtr item, InodeId_t id, int depth) const {
if (depth > 5000) {
oxTrace("ox::fs::FileStoreTemplate::find::fail") << "Excessive recursion depth, stopping before stack overflow. Search for:" << id;
return nullptr;
}
if (!item.valid()) {
oxTrace("ox::fs::FileStoreTemplate::find::fail") << "item invalid";
return nullptr;
}
if (id > item->id) {
oxTrace("ox::fs::FileStoreTemplate::find") << "Not a match, searching on" << item->right;
return find(m_buffer->ptr(item->right), id, depth + 1);
} else if (id < item->id) {
oxTrace("ox::fs::FileStoreTemplate::find") << "Not a match, searching on" << item->left;
return find(m_buffer->ptr(item->left), id, depth + 1);
} else if (id == item->id) {
oxTrace("ox::fs::FileStoreTemplate::find") << "Found" << id << "at" << item;
return item;
}
return nullptr;
}
template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(InodeId_t id) const {
oxTrace("ox::fs::FileStoreTemplate::find") << "Searching for inode:" << id;
auto fsData = fileStoreData();
if (fsData) {
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
auto item = find(root, id);
return item;
} else {
oxTrace("ox::fs::FileStoreTemplate::find::fail") << "No root node";
}
} else {
oxTrace("ox::fs::FileStoreTemplate::find::fail") << "No FileStore Data";
}
return nullptr;
}
/**
* Gets the root inode.
*/
template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::rootInode() {
auto fsData = fileStoreData();
if (fsData) {
return m_buffer->ptr(fsData->rootNode);
} else {
return nullptr;
}
}
template<typename size_t>
bool FileStoreTemplate<size_t>::canWrite(ItemPtr existing, size_t size) {
return existing.size() >= size || m_buffer->spaceNeeded(size) <= m_buffer->available();
}
template<typename size_t>
bool FileStoreTemplate<size_t>::valid() const {
return m_buffer;
}
extern template class FileStoreTemplate<uint16_t>;
extern template class FileStoreTemplate<uint32_t>;
using FileStore16 = FileStoreTemplate<uint16_t>;
using FileStore32 = FileStoreTemplate<uint32_t>;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "directory.hpp"
namespace ox {
template class Directory<FileStore16, uint16_t>;
template class Directory<FileStore32, uint32_t>;
template struct DirectoryEntry<uint16_t>;
template struct DirectoryEntry<uint32_t>;
}

View File

@ -0,0 +1,373 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/fs/filesystem/pathiterator.hpp>
#include <ox/fs/filestore/filestoretemplate.hpp>
#include <ox/ptrarith/nodebuffer.hpp>
#include <ox/std/byteswap.hpp>
#include "types.hpp"
namespace ox {
template<typename InodeId_t>
struct OX_PACKED DirectoryEntry {
public:
struct OX_PACKED DirectoryEntryData {
// DirectoryEntry fields
LittleEndian<InodeId_t> inode = 0;
char name[MaxFileNameLength];
static constexpr std::size_t spaceNeeded(std::size_t chars) {
return offsetof(DirectoryEntryData, name) + chars;
}
};
// NodeBuffer fields
LittleEndian<InodeId_t> prev = 0;
LittleEndian<InodeId_t> next = 0;
private:
LittleEndian<InodeId_t> m_bufferSize = sizeof(DirectoryEntry);
public:
DirectoryEntry() = default;
[[nodiscard]] ox::Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) {
m_bufferSize = bufferSize;
auto d = data();
if (d.valid()) {
d->inode = inode;
ox_strncpy(d->name, name, ox::min(bufferSize, static_cast<InodeId_t>(MaxFileNameLength)));
return OxError(0);
}
return OxError(1);
}
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() {
oxTrace("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 the size of the data + the size of the Item type
*/
InodeId_t fullSize() const {
return m_bufferSize;
}
InodeId_t size() const {
return fullSize() - sizeof(*this);
}
void setSize(InodeId_t) {
// ignore set value
}
static constexpr std::size_t spaceNeeded(std::size_t chars) {
return sizeof(DirectoryEntry) + offsetof(DirectoryEntryData, name) + chars;
}
};
template<typename FileStore, typename InodeId_t>
class Directory {
private:
using Buffer = ptrarith::NodeBuffer<InodeId_t, DirectoryEntry<InodeId_t>>;
InodeId_t m_inodeId = 0;
std::size_t m_size = 0;
FileStore m_fs;
public:
Directory() = default;
Directory(FileStore fs, InodeId_t inode);
/**
* Initializes Directory.
*/
[[nodiscard]] ox::Error init() noexcept;
[[nodiscard]] ox::Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr);
/**
* @param parents indicates the operation should create non-existent directories in the path, like mkdir -p
*/
[[nodiscard]] ox::Error write(PathIterator it, InodeId_t inode, FileName *nameBuff = nullptr) noexcept;
[[nodiscard]] ox::Error remove(PathIterator it, FileName *nameBuff = nullptr) noexcept;
template<typename F>
[[nodiscard]] ox::Error ls(F cb) noexcept;
[[nodiscard]] ValErr<typename FileStore::InodeId_t> findEntry(const FileName &name) const noexcept;
[[nodiscard]] ValErr<typename FileStore::InodeId_t> find(PathIterator name, FileName *nameBuff = nullptr) const noexcept;
};
template<typename FileStore, typename InodeId_t>
Directory<FileStore, InodeId_t>::Directory(FileStore fs, InodeId_t inodeId) {
m_fs = fs;
m_inodeId = inodeId;
auto buff = m_fs.read(inodeId).template to<Buffer>();
if (buff.valid()) {
m_size = buff.size();
}
}
template<typename FileStore, typename InodeId_t>
ox::Error Directory<FileStore, InodeId_t>::init() noexcept {
constexpr auto Size = sizeof(Buffer);
oxTrace("ox::fs::Directory::init") << "Initializing Directory with Inode ID:" << m_inodeId;
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, FileType_Directory));
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) {
m_size = 0;
return OxError(1);
}
new (buff) Buffer(Size);
m_size = Size;
return OxError(0);
}
template<typename FileStore, typename InodeId_t>
ox::Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
if (path.valid()) {
oxTrace("ox::fs::Directory::mkdir") << path.fullPath();
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = reinterpret_cast<FileName*>(ox_alloca(sizeof(FileName)));
}
// determine if already exists
auto name = nameBuff;
path.get(name);
auto childInode = find(name->c_str());
if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled,
// return an error
if (!parents && path.hasNext()) {
return OxError(1);
}
childInode = m_fs.generateInodeId();
oxTrace("ox::fs::Directory::mkdir") << "Generated Inode ID:" << childInode.value;
oxLogError(childInode.error);
oxReturnError(childInode.error);
// initialize the directory
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
oxReturnError(child.init());
auto err = write(name->c_str(), childInode.value);
if (err) {
oxLogError(err);
// could not index the directory, delete it
oxLogError(m_fs.remove(childInode.value));
return err;
}
}
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
if (path.hasNext()) {
oxReturnError(child.mkdir(path.next(), parents, nameBuff));
}
}
return OxError(0);
}
template<typename FileStore, typename InodeId_t>
ox::Error Directory<FileStore, InodeId_t>::write(PathIterator path, InodeId_t inode, FileName *nameBuff) noexcept {
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = reinterpret_cast<FileName*>(ox_alloca(sizeof(FileName)));
}
auto name = nameBuff;
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxReturnError(path.get(name));
oxTrace("ox::fs::Directory::write") << "Attempting to write to next sub-Directory: "
<< name->c_str() << " of " << path.fullPath();
auto [nextChild, err] = findEntry(*name);
oxReturnError(err);
oxTrace("ox::fs::Directory::write") << name->c_str() << ": " << nextChild;
if (nextChild) {
// reuse name because it is a rather large variable and will not be used again
// be attentive that this remains true
name = nullptr;
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
} else {
oxTrace("ox::fs::Directory::write") << name->c_str()
<< "not found and not allowed to create it.";
return OxError(1);
}
} else {
oxTrace("ox::fs::Directory::write") << path.fullPath();
// insert the new entry on this directory
// get the name
path.next(name);
// find existing version of directory
oxTrace("ox::fs::Directory::write") << "Searching for directory inode" << m_inodeId;
auto oldStat = m_fs.stat(m_inodeId);
oxReturnError(oldStat);
oxTrace("ox::fs::Directory::write") << "Found existing directory of size" << oldStat.value.size;
auto old = m_fs.read(m_inodeId).template to<Buffer>();
if (!old.valid()) {
oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory";
return OxError(1);
}
const auto pathSize = name->len() + 1;
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
const auto newSize = oldStat.value.size + Buffer::spaceNeeded(entryDataSize);
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.value.size);
if (cpy == nullptr) {
oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for copy of Directory";
return OxError(1);
}
// TODO: look for old version of this entry and delete it
oxReturnError(cpy->setSize(newSize));
auto val = cpy->malloc(entryDataSize);
if (!val.valid()) {
oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for new directory entry";
return OxError(1);
}
oxTrace("ox::fs::Directory::write") << "Attempting to write Directory entry:" << name->data();
oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore";
oxReturnError(val->init(inode, name->data(), val.size()));
return m_fs.write(m_inodeId, cpy, cpy->size(), FileType_Directory);
}
}
template<typename FileStore, typename InodeId_t>
ox::Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameBuff) noexcept {
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = reinterpret_cast<FileName*>(ox_alloca(sizeof(FileName)));
}
auto &name = *nameBuff;
oxReturnError(path.get(&name));
oxTrace("ox::fs::Directory::remove") << name.c_str();
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (buff.valid()) {
oxTrace("ox::fs::Directory::remove") << "Found directory buffer.";
for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data();
if (data.valid()) {
if (ox_strncmp(data->name, name.c_str(), name.len()) == 0) {
oxReturnError(buff->free(i));
}
} else {
oxTrace("ox::fs::Directory::remove") << "INVALID DIRECTORY ENTRY";
}
}
} else {
oxTrace("ox::fs::Directory::remove::fail") << "Could not find directory buffer";
return OxError(1);
}
return OxError(0);
}
template<typename FileStore, typename InodeId_t>
template<typename F>
ox::Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
oxTrace("ox::fs::Directory::ls");
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) {
oxTrace("ox::fs::Directory::ls::fail") << "Could not directory buffer";
return OxError(1);
}
oxTrace("ox::fs::Directory::ls") << "Found directory buffer.";
for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data();
if (data.valid()) {
oxReturnError(cb(data->name, data->inode));
} else {
oxTrace("ox::fs::Directory::ls") << "INVALID DIRECTORY ENTRY";
}
}
return OxError(0);
}
template<typename FileStore, typename InodeId_t>
ValErr<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
oxTrace("ox::fs::Directory::findEntry") << name.c_str();
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) {
oxTrace("ox::fs::Directory::findEntry::fail") << "Could not findEntry directory buffer";
return {0, OxError(2)};
}
oxTrace("ox::fs::Directory::findEntry") << "Found directory buffer, size:" << buff.size();
for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data();
if (data.valid()) {
oxTrace("ox::fs::Directory::findEntry").del("") << "Comparing \"" << name.c_str() << "\" to \"" << data->name << "\"";
if (ox_strncmp(data->name, name.c_str(), MaxFileNameLength) == 0) {
oxTrace("ox::fs::Directory::findEntry").del("") << "\"" << name.c_str() << "\" match found.";
return static_cast<InodeId_t>(data->inode);
}
} else {
oxTrace("ox::fs::Directory::findEntry") << "INVALID DIRECTORY ENTRY";
}
}
oxTrace("ox::fs::Directory::findEntry::fail") << "Entry not present";
return {0, OxError(1)};
}
template<typename FileStore, typename InodeId_t>
ValErr<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path, FileName *nameBuff) const noexcept {
// reuse nameBuff if it has already been allocated, as it is a rather large variable
if (nameBuff == nullptr) {
nameBuff = reinterpret_cast<FileName*>(ox_alloca(sizeof(FileName)));
}
// determine if already exists
auto name = nameBuff;
oxReturnError(path.get(name));
auto v = findEntry(name->c_str());
oxReturnError(v);
// recurse if not at end of path
if (auto p = path.next(); p.valid()) {
Directory dir(m_fs, v.value);
name = nullptr;
return dir.find(p, nameBuff);
}
return v;
}
extern template class Directory<FileStore16, uint16_t>;
extern template class Directory<FileStore32, uint32_t>;
extern template struct DirectoryEntry<uint16_t>;
extern template struct DirectoryEntry<uint32_t>;
using Directory16 = Directory<FileStore16, uint16_t>;
using Directory32 = Directory<FileStore32, uint32_t>;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "filelocation.hpp"
namespace ox {
FileAddress::FileAddress() {
m_data.inode = 0;
m_type = FileAddressType::Inode;
}
FileAddress::FileAddress(const FileAddress &other) {
operator=(other);
}
FileAddress::FileAddress(std::nullptr_t) {
}
FileAddress::FileAddress(uint64_t inode) {
m_data.inode = inode;
m_type = FileAddressType::Inode;
}
FileAddress::FileAddress(char *path) {
auto pathSize = ox_strlen(path) + 1;
m_data.path = new char[pathSize];
memcpy(m_data.path, path, pathSize);
m_type = FileAddressType::Path;
}
FileAddress::FileAddress(const char *path) {
m_data.constPath = path;
m_type = FileAddressType::ConstPath;
}
FileAddress::~FileAddress() {
if (m_type == FileAddressType::Path) {
delete[] m_data.path;
m_data.path = nullptr;
}
}
const FileAddress &FileAddress::operator=(const FileAddress &other) {
m_type = other.m_type;
switch (m_type) {
case FileAddressType::Path:
{
auto strSize = ox_strlen(other.m_data.path) + 1;
m_data.path = new char[strSize];
ox_memcpy(m_data.path, other.m_data.path, strSize);
break;
}
case FileAddressType::ConstPath:
case FileAddressType::Inode:
m_data = other.m_data;
break;
case FileAddressType::None:
break;
}
return *this;
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/std.hpp>
#include <ox/model/types.hpp>
namespace ox {
enum class FileAddressType: int8_t {
None = -1,
Path,
ConstPath,
Inode,
};
class FileAddress {
template<typename T>
friend ox::Error model(T*, FileAddress*);
public:
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
static constexpr auto Fields = 2;
union Data {
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress.Data";
static constexpr auto Fields = 3;
char *path;
const char *constPath;
uint64_t inode;
};
protected:
FileAddressType m_type = FileAddressType::None;
Data m_data;
public:
FileAddress();
FileAddress(const FileAddress &other);
FileAddress(std::nullptr_t);
FileAddress(uint64_t inode);
FileAddress(char *path);
FileAddress(const char *path);
~FileAddress();
const FileAddress &operator=(const FileAddress &other);
[[nodiscard]] constexpr FileAddressType type() const noexcept {
switch (m_type) {
case FileAddressType::Path:
case FileAddressType::ConstPath:
return FileAddressType::Path;
default:
return m_type;
}
}
[[nodiscard]] constexpr ValErr<uint64_t> getInode() const noexcept {
switch (m_type) {
case FileAddressType::Inode:
return m_data.inode;
default:
return OxError(1);
}
}
[[nodiscard]] constexpr ValErr<const char*> getPath() const noexcept {
switch (m_type) {
case FileAddressType::Path:
return m_data.path;
case FileAddressType::ConstPath:
return m_data.constPath;
default:
return OxError(1);
}
}
operator bool() const {
return m_type != FileAddressType::None;
}
};
template<typename T>
ox::Error model(T *io, FileAddress::Data *obj) {
io->template setTypeInfo<FileAddress::Data>();
oxReturnError(io->field("path", SerStr(&obj->path)));
oxReturnError(io->field("constPath", SerStr(&obj->path)));
oxReturnError(io->field("inode", &obj->inode));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, FileAddress *fa) {
io->template setTypeInfo<FileAddress>();
oxReturnError(io->field("type", bit_cast<int8_t*>(&fa->m_type)));
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
return OxError(0);
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "filesystem.hpp"
namespace ox {
[[nodiscard]] ox::ValErr<uint8_t*> FileSystem::read(FileAddress addr) {
switch (addr.type()) {
case FileAddressType::Inode:
return read(addr.getInode().value);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return read(addr.getPath().value);
default:
return OxError(1);
}
}
[[nodiscard]] ox::Error FileSystem::read(FileAddress addr, void *buffer, std::size_t size) {
switch (addr.type()) {
case FileAddressType::Inode:
return read(addr.getInode().value, buffer, size);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return read(addr.getPath().value, buffer, size);
default:
return OxError(1);
}
}
[[nodiscard]] ox::Error FileSystem::read(FileAddress addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) {
switch (addr.type()) {
case FileAddressType::Inode:
return read(addr.getInode().value, readStart, readSize, buffer, size);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return read(addr.getPath().value, readStart, readSize, buffer, size);
default:
return OxError(1);
}
}
[[nodiscard]] ox::Error FileSystem::remove(FileAddress addr, bool recursive) {
switch (addr.type()) {
case FileAddressType::Inode:
return remove(addr.getInode().value, recursive);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return remove(addr.getPath().value, recursive);
default:
return OxError(1);
}
}
ox::Error FileSystem::write(FileAddress addr, void *buffer, uint64_t size, uint8_t fileType) {
switch (addr.type()) {
case FileAddressType::Inode:
return write(addr.getInode().value, buffer, size, fileType);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return write(addr.getPath().value, buffer, size, fileType);
default:
return OxError(1);
}
}
ox::ValErr<FileStat> FileSystem::stat(FileAddress addr) {
switch (addr.type()) {
case FileAddressType::Inode:
return stat(addr.getInode().value);
case FileAddressType::ConstPath:
case FileAddressType::Path:
return stat(addr.getPath().value);
default:
return OxError(1);
}
}
template class FileSystemTemplate<FileStore16, Directory16>;
template class FileSystemTemplate<FileStore32, Directory32>;
}

View File

@ -0,0 +1,423 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/fs/filestore/filestoretemplate.hpp>
#include <ox/fs/filesystem/filelocation.hpp>
#include <ox/fs/filesystem/types.hpp>
#include "directory.hpp"
namespace ox {
class FileSystem {
public:
virtual ~FileSystem() = default;
[[nodiscard]] virtual ox::Error mkdir(const char *path, bool recursive = false) = 0;
/**
* Moves an entry from one directory to another.
* @param src the path to the file
* @param dest the path of the destination directory
*/
[[nodiscard]] virtual ox::Error move(const char *src, const char *dest) = 0;
[[nodiscard]] virtual ox::Error read(const char *path, void *buffer, std::size_t buffSize) = 0;
[[nodiscard]] virtual ox::ValErr<uint8_t*> read(const char *path) = 0;
[[nodiscard]] virtual ox::Error read(uint64_t inode, void *buffer, std::size_t size) = 0;
[[nodiscard]] virtual ox::Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) = 0;
[[nodiscard]] virtual ox::ValErr<uint8_t*> read(uint64_t inode) = 0;
[[nodiscard]] ox::Error read(FileAddress addr, void *buffer, std::size_t size);
[[nodiscard]] ox::Error read(FileAddress addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size);
[[nodiscard]] ox::ValErr<uint8_t*> read(FileAddress addr);
[[nodiscard]] virtual ox::Error remove(const char *path, bool recursive = false) = 0;
[[nodiscard]] ox::Error remove(FileAddress addr, bool recursive = false);
[[nodiscard]] virtual ox::Error resize(uint64_t size, void *buffer = nullptr) = 0;
[[nodiscard]] virtual ox::Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0;
[[nodiscard]] virtual ox::Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0;
[[nodiscard]] ox::Error write(FileAddress addr, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile);
[[nodiscard]] virtual ox::ValErr<FileStat> stat(uint64_t inode) = 0;
[[nodiscard]] virtual ox::ValErr<FileStat> stat(const char *path) = 0;
[[nodiscard]] ox::ValErr<FileStat> stat(FileAddress addr);
[[nodiscard]] virtual uint64_t spaceNeeded(uint64_t size) = 0;
[[nodiscard]] virtual uint64_t available() = 0;
[[nodiscard]] virtual uint64_t size() const = 0;
[[nodiscard]] virtual char *buff() = 0;
[[nodiscard]] virtual ox::Error walk(ox::Error(*cb)(uint8_t, uint64_t, uint64_t)) = 0;
[[nodiscard]] virtual bool valid() const = 0;
};
/**
* FileSystemTemplate used to create file system that wraps around a FileStore,
* taking an inode size and a directory type as parameters.
*
* Note: Directory parameter must have a default constructor.
*/
template<typename FileStore, typename Directory>
class FileSystemTemplate: public FileSystem {
private:
static constexpr auto InodeFsData = 2;
struct OX_PACKED FileSystemData {
LittleEndian<typename FileStore::InodeId_t> rootDirInode;
};
FileStore m_fs;
void(*m_freeBuffer)(char*) = nullptr;
public:
FileSystemTemplate() = default;
FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*) = [] (char *buff) { delete buff; });
FileSystemTemplate(FileStore fs);
~FileSystemTemplate();
[[nodiscard]] static ox::Error format(void *buff, uint64_t buffSize);
[[nodiscard]] ox::Error mkdir(const char *path, bool recursive = false) override;
[[nodiscard]] ox::Error move(const char *src, const char *dest) override;
[[nodiscard]] ox::Error read(const char *path, void *buffer, std::size_t buffSize) override;
[[nodiscard]] ox::ValErr<uint8_t*> read(const char*) override;
[[nodiscard]] ox::Error read(uint64_t inode, void *buffer, std::size_t size) override;
[[nodiscard]] ox::Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) override;
[[nodiscard]] ox::ValErr<uint8_t*> read(uint64_t) override;
template<typename F>
[[nodiscard]] ox::Error ls(const char *dir, F cb);
[[nodiscard]] ox::Error remove(const char *path, bool recursive = false) override;
/**
* Resizes FileSystem to minimum possible size.
*/
[[nodiscard]] ox::Error resize();
[[nodiscard]] ox::Error resize(uint64_t size, void *buffer = nullptr) override;
[[nodiscard]] ox::Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
[[nodiscard]] ox::Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
[[nodiscard]] ox::ValErr<FileStat> stat(uint64_t inode) override;
[[nodiscard]] ox::ValErr<FileStat> stat(const char *path) override;
uint64_t spaceNeeded(uint64_t size) override;
uint64_t available() override;
uint64_t size() const override;
char *buff() override;
[[nodiscard]] ox::Error walk(ox::Error(*cb)(uint8_t, uint64_t, uint64_t)) override;
bool valid() const override;
private:
[[nodiscard]] ValErr<FileSystemData> fileSystemData() const noexcept;
/**
* Finds the inode ID at the given path.
*/
[[nodiscard]] ValErr<uint64_t> find(const char *path) const noexcept;
[[nodiscard]] ValErr<Directory> rootDir() const noexcept;
};
template<typename FileStore, typename Directory>
FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(FileStore fs) {
m_fs = fs;
}
template<typename FileStore, typename Directory>
FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*)):
m_fs(buffer, bufferSize),
m_freeBuffer(freeBuffer) {
}
template<typename FileStore, typename Directory>
FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() {
if (m_freeBuffer && m_fs.buff()) {
m_freeBuffer(m_fs.buff());
}
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) {
oxReturnError(FileStore::format(buff, buffSize));
FileStore fs(buff, buffSize);
constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2;
Directory rootDir(fs, rootDirInode);
oxReturnError(rootDir.init());
FileSystemData fd;
fd.rootDirInode = rootDirInode;
oxTrace("ox::fs::FileSystemTemplate::format") << "rootDirInode:" << fd.rootDirInode;
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd)));
if (!fs.read(fd.rootDirInode).valid()) {
oxTrace("ox::fs::FileSystemTemplate::format::error") << "FileSystemTemplate::format did not correctly create root directory";
return OxError(1);
}
return OxError(0);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::mkdir(const char *path, bool recursive) {
oxTrace("ox::fs::FileSystemTemplate::mkdir") << "path:" << path << "recursive:" << recursive;
auto rootDir = this->rootDir();
oxReturnError(rootDir.error);
return rootDir.value.mkdir(path, recursive);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::move(const char *src, const char *dest) {
auto fd = fileSystemData();
oxReturnError(fd.error);
Directory rootDir(m_fs, fd.value.rootDirInode);
auto [inode, err] = rootDir.find(src);
oxReturnError(err);
oxReturnError(rootDir.write(dest, inode));
oxReturnError(rootDir.remove(src));
return OxError(0);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::read(const char *path, void *buffer, std::size_t buffSize) {
auto fd = fileSystemData();
oxReturnError(fd.error);
Directory rootDir(m_fs, fd.value.rootDirInode);
auto [inode, err] = rootDir.find(path);
oxReturnError(err);
return read(inode, buffer, buffSize);
}
template<typename FileStore, typename Directory>
[[nodiscard]] ox::ValErr<uint8_t*> FileSystemTemplate<FileStore, Directory>::read(const char *path) {
auto fd = fileSystemData();
oxReturnError(fd.error);
Directory rootDir(m_fs, fd.value.rootDirInode);
auto [inode, err] = rootDir.find(path);
oxReturnError(err);
return read(inode);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::read(uint64_t inode, void *buffer, std::size_t buffSize) {
return m_fs.read(inode, buffer, buffSize);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) {
return m_fs.read(inode, readStart, readSize, reinterpret_cast<uint8_t*>(buffer), size);
}
template<typename FileStore, typename Directory>
[[nodiscard]] ox::ValErr<uint8_t*> FileSystemTemplate<FileStore, Directory>::read(uint64_t inode) {
auto data = m_fs.read(inode);
if (!data.valid()) {
return OxError(1);
}
return data.get();
}
template<typename FileStore, typename Directory>
template<typename F>
ox::Error FileSystemTemplate<FileStore, Directory>::ls(const char *path, F cb) {
oxTrace("ox::FileSystemTemplate::ls") << "path:" << path;
auto [s, err] = stat(path);
oxReturnError(err);
Directory dir(m_fs, s.inode);
return dir.ls(cb);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::remove(const char *path, bool recursive) {
auto fd = fileSystemData();
oxReturnError(fd.error);
Directory rootDir(m_fs, fd.value.rootDirInode);
auto inode = rootDir.find(path);
oxReturnError(inode.error);
auto st = stat(inode.value);
oxReturnError(st.error);
if (st.value.fileType == FileType_NormalFile || recursive) {
if (auto err = rootDir.remove(path)) {
// removal failed, try putting the index back
oxLogError(rootDir.write(path, inode.value));
return err;
}
} else {
oxTrace("FileSystemTemplate::remove::fail") << "Tried to remove directory without recursive setting.";
return OxError(1);
}
return OxError(0);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::resize() {
return m_fs.resize();
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) {
oxReturnError(m_fs.resize(size, buffer));
return OxError(0);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) {
auto [inode, err] = find(path);
if (err) {
auto generated = m_fs.generateInodeId();
oxReturnError(generated.error);
inode = generated.value;
}
auto rootDir = this->rootDir();
oxReturnError(rootDir.error);
oxReturnError(rootDir.value.write(path, inode));
oxReturnError(write(inode, buffer, size, fileType));
return OxError(0);
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) {
return m_fs.write(inode, buffer, size, fileType);
}
template<typename FileStore, typename Directory>
ValErr<FileStat> FileSystemTemplate<FileStore, Directory>::stat(uint64_t inode) {
auto s = m_fs.stat(inode);
FileStat out;
out.inode = s.value.inode;
out.links = s.value.links;
out.size = s.value.size;
out.fileType = s.value.fileType;
return {out, s.error};
}
template<typename FileStore, typename Directory>
ValErr<FileStat> FileSystemTemplate<FileStore, Directory>::stat(const char *path) {
auto inode = find(path);
if (inode.error) {
return {{}, inode.error};
}
return stat(inode.value);
}
template<typename FileStore, typename Directory>
uint64_t FileSystemTemplate<FileStore, Directory>::spaceNeeded(uint64_t size) {
return m_fs.spaceNeeded(size);
}
template<typename FileStore, typename Directory>
uint64_t FileSystemTemplate<FileStore, Directory>::available() {
return m_fs.available();
}
template<typename FileStore, typename Directory>
uint64_t FileSystemTemplate<FileStore, Directory>::size() const {
return m_fs.size();
}
template<typename FileStore, typename Directory>
char *FileSystemTemplate<FileStore, Directory>::buff() {
return m_fs.buff();
}
template<typename FileStore, typename Directory>
ox::Error FileSystemTemplate<FileStore, Directory>::walk(ox::Error(*cb)(uint8_t, uint64_t, uint64_t)) {
return m_fs.walk(cb);
}
template<typename FileStore, typename Directory>
bool FileSystemTemplate<FileStore, Directory>::valid() const {
return m_fs.valid();
}
template<typename FileStore, typename Directory>
ValErr<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept {
FileSystemData fd;
auto err = m_fs.read(InodeFsData, &fd, sizeof(fd));
if (err != 0) {
return {fd, err};
}
return fd;
}
template<typename FileStore, typename Directory>
ValErr<uint64_t> FileSystemTemplate<FileStore, Directory>::find(const char *path) const noexcept {
auto fd = fileSystemData();
if (fd.error) {
return {0, fd.error};
}
// return root as a special case
if (ox_strcmp(path, "/") == 0) {
return static_cast<uint64_t>(fd.value.rootDirInode);
}
Directory rootDir(m_fs, fd.value.rootDirInode);
auto inode = rootDir.find(path);
if (inode.error) {
return {0, inode.error};
}
return inode.value;
}
template<typename FileStore, typename Directory>
ValErr<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept {
auto fd = fileSystemData();
if (fd.error) {
return {{}, fd.error};
}
return Directory(m_fs, fd.value.rootDirInode);
}
extern template class FileSystemTemplate<FileStore16, Directory16>;
extern template class FileSystemTemplate<FileStore32, Directory32>;
using FileSystem16 = FileSystemTemplate<FileStore16, Directory16>;
using FileSystem32 = FileSystemTemplate<FileStore32, Directory32>;
}

View File

@ -0,0 +1,170 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "passthroughfs.hpp"
#if defined(OX_HAS_PASSTHROUGHFS)
#include <fstream>
namespace ox {
PassThroughFS::PassThroughFS(const char *dirPath) {
m_path = dirPath;
}
PassThroughFS::~PassThroughFS() {
}
std::string PassThroughFS::basePath() {
return m_path.string();
}
Error PassThroughFS::mkdir(const char *path, bool recursive) {
bool success = false;
const auto p = m_path / stripSlash(path);
const auto u8p = p.u8string();
oxTrace("ox::fs::PassThroughFS::mkdir") << u8p.c_str();
if (recursive) {
if (std::filesystem::is_directory(p)) {
success = true;
} else {
success = std::filesystem::create_directories(p);
}
} else {
success = std::filesystem::create_directory(p);
}
return OxError(success ? 0 : 1);
}
Error PassThroughFS::move(const char *src, const char *dest) {
std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest));
return OxError(0);
}
Error PassThroughFS::read(const char *path, void *buffer, std::size_t buffSize) {
try {
std::ifstream file((m_path / stripSlash(path)), std::ios::binary | std::ios::ate);
const std::size_t size = file.tellg();
file.seekg(0, std::ios::beg);
if (size > buffSize) {
oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed: Buffer too small:" << path;
return OxError(1);
}
file.read(static_cast<char*>(buffer), buffSize);
} catch (const std::fstream::failure&) {
oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed:" << path;
throw OxError(2);
}
return OxError(0);
}
ValErr<uint8_t*> PassThroughFS::read(const char*) {
return OxError(1);
}
Error PassThroughFS::read(uint64_t, void*, std::size_t) {
// unsupported
return OxError(1);
}
Error PassThroughFS::read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) {
// unsupported
return OxError(1);
}
ValErr<uint8_t*> PassThroughFS::read(uint64_t) {
return OxError(1);
}
Error PassThroughFS::remove(const char *path, bool recursive) {
if (recursive) {
return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
} else {
return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0);
}
}
ox::Error PassThroughFS::resize(uint64_t, void*) {
// unsupported
return OxError(1);
}
Error PassThroughFS::write(const char *path, void *buffer, uint64_t size, uint8_t) {
auto p = (m_path / stripSlash(path));
try {
std::ofstream f(p, std::ios::binary);
f.write(static_cast<char*>(buffer), size);
} catch (const std::fstream::failure&) {
oxTrace("ox::fs::PassThroughFS::write::error") << "Write failed:" << path;
throw OxError(1);
}
return OxError(0);
}
Error PassThroughFS::write(uint64_t, void*, uint64_t, uint8_t) {
// unsupported
return OxError(1);
}
ValErr<FileStat> PassThroughFS::stat(uint64_t) {
// unsupported
return {{}, OxError(1)};
}
ValErr<FileStat> PassThroughFS::stat(const char *path) {
std::error_code ec;
const auto p = m_path / stripSlash(path);
uint8_t type = std::filesystem::is_directory(p, ec) ?
FileType_Directory : FileType_NormalFile;
oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
uint64_t size = type == FileType_Directory ? 0 : std::filesystem::file_size(p, ec);
oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
oxTrace("PassThroughFS::stat::size") << path << size;
return {{0, 0, size, type}, OxError(ec.value())};
}
uint64_t PassThroughFS::spaceNeeded(uint64_t size) {
return size;
}
uint64_t PassThroughFS::available() {
std::error_code ec;
auto s = std::filesystem::space(m_path, ec);
return s.available;
}
uint64_t PassThroughFS::size() const {
std::error_code ec;
auto s = std::filesystem::space(m_path, ec);
return s.capacity;
}
char *PassThroughFS::buff() {
return nullptr;
}
Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) {
return OxError(1);
}
bool PassThroughFS::valid() const {
return std::filesystem::is_directory(m_path);
}
const char *PassThroughFS::stripSlash(const char *path) {
auto pathLen = ox_strlen(path);
for (decltype(pathLen) i = 0; i < pathLen && path[0] == '/'; i++) {
path++;
}
return path;
}
}
#endif

View File

@ -0,0 +1,100 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#if __has_include(<filesystem>)
#include <filesystem>
#include <string>
#define OX_HAS_PASSTHROUGHFS
#endif
#ifdef OX_HAS_PASSTHROUGHFS
#include "filesystem.hpp"
namespace ox {
/**
*
*/
class PassThroughFS: public FileSystem {
private:
std::filesystem::path m_path;
public:
PassThroughFS(const char *dirPath);
~PassThroughFS();
[[nodiscard]] std::string basePath();
ox::Error mkdir(const char *path, bool recursive = false) override;
ox::Error move(const char *src, const char *dest) override;
ox::Error read(const char *path, void *buffer, std::size_t buffSize) override;
ox::ValErr<uint8_t*> read(const char*) override;
ox::Error read(uint64_t inode, void *buffer, std::size_t size) override;
ox::Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) override;
ox::ValErr<uint8_t*> read(uint64_t) override;
template<typename F>
ox::Error ls(const char *dir, F cb);
ox::Error remove(const char *path, bool recursive = false) override;
ox::Error resize(uint64_t size, void *buffer = nullptr) override;
ox::Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
ox::Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
ox::ValErr<FileStat> stat(uint64_t inode) override;
ox::ValErr<FileStat> stat(const char *path) override;
uint64_t spaceNeeded(uint64_t size) override;
uint64_t available() override;
uint64_t size() const override;
char *buff() override;
ox::Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) override;
bool valid() const override;
private:
/**
* Strips the leading slashes from a string.
*/
const char *stripSlash(const char *path);
};
template<typename F>
ox::Error PassThroughFS::ls(const char *dir, F cb) {
for (auto &p : std::filesystem::directory_iterator(m_path / stripSlash(dir))) {
auto u8p = p.path().filename().u8string();
oxReturnError(cb(u8p.c_str(), 0));
}
return OxError(0);
}
}
#endif

View File

@ -0,0 +1,214 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/memops.hpp>
#include <ox/std/strops.hpp>
#include <ox/std/trace.hpp>
#include "pathiterator.hpp"
namespace ox {
PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) {
m_path = path;
m_maxSize = maxSize;
m_iterator = iterator;
}
PathIterator::PathIterator(const char *path): PathIterator(path, ox_strlen(path)) {
}
/**
* @return 0 if no error
*/
Error PathIterator::dirPath(char *out, std::size_t outSize) {
int idx = ox_lastIndexOf(m_path, '/', m_maxSize);
std::size_t size = idx + 1;
if (idx >= 0 && size < outSize) {
ox_memcpy(out, m_path, size);
out[size] = 0;
return OxError(0);
} else {
return OxError(1);
}
}
/**
* @return 0 if no error
*/
Error PathIterator::fileName(char *out, std::size_t outSize) {
auto idx = ox_lastIndexOf(m_path, '/', m_maxSize);
if (idx >= 0) {
idx++; // pass up the preceding /
std::size_t fileNameSize = ox_strlen(&m_path[idx]);
if (fileNameSize < outSize) {
ox_memcpy(out, &m_path[idx], fileNameSize);
out[fileNameSize] = 0;
return OxError(0);
} else {
return OxError(1);
}
} else {
return OxError(2);
}
}
// Gets the get item in the path
Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
std::size_t size = 0;
if (m_iterator >= m_maxSize) {
oxTrace("ox::fs::PathIterator::get") << "m_iterator >= m_maxSize";
return OxError(1);
}
if (!ox_strlen(&m_path[m_iterator])) {
oxTrace("ox::fs::PathIterator::get") << "!ox_strlen(&m_path[m_iterator])";
return OxError(1);
}
auto start = m_iterator;
if (m_path[start] == '/') {
start++;
}
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
std::size_t end = substr - m_path;
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize || size == 0) {
return OxError(1);
}
ox_memcpy(pathOut, &m_path[start], size);
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
return OxError(0);
}
// Gets the get item in the path
Error PathIterator::next(char *pathOut, std::size_t pathOutSize) {
std::size_t size = 0;
auto retval = OxError(1);
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
retval = OxError(0);
if (m_path[m_iterator] == '/') {
m_iterator++;
}
std::size_t start = m_iterator;
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
std::size_t end = substr - m_path;
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize) {
return OxError(1);
}
ox_memcpy(pathOut, &m_path[start], size);
}
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
m_iterator += size;
return retval;
}
/**
* @return 0 if no error
*/
Error PathIterator::get(BString<MaxFileNameLength> *fileName) {
return get(fileName->data(), fileName->cap());
}
/**
* @return 0 if no error
*/
Error PathIterator::next(BString<MaxFileNameLength> *fileName) {
return next(fileName->data(), fileName->cap());
}
ValErr<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0;
auto retval = OxError(1);
auto it = m_iterator;
if (it < m_maxSize && ox_strlen(&m_path[it])) {
retval = OxError(0);
if (m_path[it] == '/') {
it++;
}
std::size_t start = it;
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
std::size_t end = substr - m_path;
size = end - start;
}
it += size;
return {size, retval};
}
bool PathIterator::hasNext() const {
std::size_t size = 0;
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
std::size_t start = m_iterator;
if (m_path[start] == '/') {
start++;
}
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
std::size_t end = substr - m_path;
size = end - start;
}
return size > 0;
}
bool PathIterator::valid() const {
return m_iterator < m_maxSize && m_path[m_iterator] != 0;
}
PathIterator PathIterator::next() const {
std::size_t size = 0;
auto iterator = m_iterator;
if (iterator < m_maxSize && ox_strlen(&m_path[iterator])) {
if (m_path[iterator] == '/') {
iterator++;
}
std::size_t start = iterator;
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
std::size_t end = substr - m_path;
size = end - start;
}
iterator += size;
return PathIterator(m_path, m_maxSize, iterator + 1);
}
const char *PathIterator::fullPath() const {
return m_path;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/std.hpp>
namespace ox {
constexpr std::size_t MaxFileNameLength = 255;
using FileName = BString<MaxFileNameLength>;
class PathIterator {
private:
const char *m_path = nullptr;
std::size_t m_iterator = 0;
std::size_t m_maxSize = 0;
public:
PathIterator(const char *path, std::size_t maxSize, std::size_t iterator = 0);
PathIterator(const char *path);
/**
* @return 0 if no error
*/
Error dirPath(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error fileName(char *out, std::size_t outSize);
/**
* @return 0 if no error
*/
Error next(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error get(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error next(FileName *fileName);
/**
* @return 0 if no error
*/
Error get(FileName *fileName);
/**
* @return 0 if no error
*/
ValErr<std::size_t> nextSize() const;
bool hasNext() const;
bool valid() const;
[[nodiscard]] PathIterator next() const;
const char *fullPath() const;
};
}

44
deps/ox/src/ox/fs/filesystem/types.hpp vendored Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/types.hpp>
namespace ox {
enum FsType {
OxFS_16 = 1,
OxFS_32 = 2,
OxFS_64 = 3
};
enum FileType {
FileType_NormalFile = 1,
FileType_Directory = 2
};
constexpr const char *toString(FileType t) {
switch (t) {
case FileType_NormalFile:
return "Normal File";
case FileType_Directory:
return "Directory";
default:
return "";
}
}
struct FileStat {
uint64_t inode = 0;
uint64_t links = 0;
uint64_t size = 0;
uint8_t fileType = 0;
};
}

15
deps/ox/src/ox/fs/fs.hpp vendored Normal file
View File

@ -0,0 +1,15 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "filestore/filestoretemplate.hpp"
#include "filesystem/filelocation.hpp"
#include "filesystem/filesystem.hpp"
#include "filesystem/passthroughfs.hpp"
#include "filesystem/directory.hpp"

27
deps/ox/src/ox/fs/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,27 @@
add_executable(
FSTests
tests.cpp
)
target_link_libraries(
FSTests
OxFS
OxStd
OxMetalClaw
)
add_test("Test\\ PathIterator::next1" FSTests PathIterator::next1)
add_test("Test\\ PathIterator::next2" FSTests PathIterator::next2)
add_test("Test\\ PathIterator::next3" FSTests PathIterator::next3)
add_test("Test\\ PathIterator::next4" FSTests PathIterator::next4)
add_test("Test\\ PathIterator::next5" FSTests PathIterator::next5)
add_test("Test\\ PathIterator::hasNext" FSTests PathIterator::hasNext)
add_test("Test\\ PathIterator::dirPath" FSTests PathIterator::dirPath)
add_test("Test\\ PathIterator::fileName" FSTests PathIterator::fileName)
add_test("Test\\ NodeBuffer::insert" FSTests "NodeBuffer::insert")
add_test("Test\\ FileStore::readWrite" FSTests "FileStore::readWrite")
add_test("Test\\ Directory" FSTests "Directory")
add_test("Test\\ FileSystem" FSTests "FileSystem")

231
deps/ox/src/ox/fs/test/tests.cpp vendored Normal file
View File

@ -0,0 +1,231 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
// make sure asserts are enabled for the test file
#undef NDEBUG
#include <iostream>
#include <assert.h>
#include <map>
#include <vector>
#include <string>
#include <ox/fs/fs.hpp>
#include <ox/std/std.hpp>
#include <ox/fs/filestore/filestoretemplate.hpp>
#include <ox/fs/filesystem/filesystem.hpp>
using namespace std;
using namespace ox;
map<string, int(*)(string)> tests = {
{
{
"PathIterator::next1",
[](string) {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
return retval;
}
},
{
"PathIterator::next2",
[](string) {
int retval = 0;
string path = "/usr/share/";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
return retval;
}
},
{
"PathIterator::next3",
[](string) {
int retval = 0;
string path = "/";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "\0") == 0);
return retval;
}
},
{
"PathIterator::next4",
[](string) {
int retval = 0;
string path = "usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
return retval;
}
},
{
"PathIterator::next5",
[](string) {
int retval = 0;
string path = "usr/share/";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
return retval;
}
},
{
"PathIterator::dirPath",
[] (string) {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.dirPath(buff, path.size()) == 0 && ox_strcmp(buff, "/usr/share/") == 0);
return retval;
}
},
{
"PathIterator::fileName",
[](string) {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.fileName(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
return retval;
}
},
{
"PathIterator::hasNext",
[](string) {
int retval = 0;
const auto path = "/file1";
PathIterator it(path, ox_strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
return retval;
}
},
{
"Ptr::subPtr",
[](string) {
constexpr auto buffLen = 5000;
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
auto subPtr = p.subPtr<uint64_t>(50);
oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid.");
return 0;
}
},
{
"NodeBuffer::insert",
[](string) {
int err = 0;
constexpr auto buffLen = 5000;
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
oxAssert(list->malloc(50).valid(), "NodeBuffer::insert: malloc 1 failed");
oxAssert(list->malloc(50).valid(), "NodeBuffer::insert: malloc 2 failed");
auto first = list->firstItem();
oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item");
oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid");
return err;
}
},
{
"FileStore::readWrite",
[](string) {
constexpr auto buffLen = 5000;
constexpr auto str1 = "Hello, World!";
constexpr auto str1Len = ox_strlen(str1) + 1;
constexpr auto str2 = "Hello, Moon!";
constexpr auto str2Len = ox_strlen(str2) + 1;
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed.");
ox::FileStore32 fileStore(list, buffLen);
oxAssert(fileStore.write(4, const_cast<char*>(str1), str1Len, 1), "FileStore::write 1 failed.");
oxAssert(fileStore.write(5, const_cast<char*>(str2), str2Len, 1), "FileStore::write 2 failed.");
char str1Read[str1Len];
size_t str1ReadSize = 0;
oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed.");
return 0;
}
},
{
"Directory",
[](string) {
std::vector<uint8_t> fsBuff(5000);
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
ox::Directory32 dir(fileStore, 105);
oxTrace("ox::fs::test::Directory") << "Init";
oxAssert(dir.init(), "Init failed");
oxTrace("ox::fs::test::Directory") << "write 1";
oxAssert(dir.write("/file1", 1), "Directory write of file1 failed");
oxTrace("ox::fs::test::Directory") << "find";
oxAssert(dir.find("file1").error, "Could not find file1");
oxAssert(dir.find("file1").value == 1, "Could not find file1");
oxTrace("ox::fs::test::Directory") << "write 2";
oxAssert(dir.write("/file3", 3), "Directory write of file3 failed");
oxTrace("ox::fs::test::Directory") << "write 3";
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
return 0;
}
},
{
"FileSystem",
[](string) {
std::vector<uint8_t> fsBuff(5000);
oxTrace("ox::fs::test::FileSystem") << "format";
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
oxTrace("ox::fs::test::FileSystem") << "mkdir";
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
oxAssert(fs.stat("/dir").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d1/l3d1", true), "mkdir failed");
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
return 0;
}
},
},
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 1) {
auto testName = args[1];
string testArg = "";
if (args[2]) {
testArg = args[2];
}
if (tests.find(testName) != tests.end()) {
retval = tests[testName](testArg);
}
}
return retval;
}

43
deps/ox/src/ox/mc/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,43 @@
add_library(
OxMetalClaw
presenceindicator.cpp
read.cpp
write.cpp
)
target_link_libraries(
OxMetalClaw PUBLIC
OxModel
OxStd
)
if(NOT OX_BARE_METAL)
set_property(
TARGET
OxMetalClaw
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
endif()
install(
FILES
intops.hpp
err.hpp
mc.hpp
presenceindicator.hpp
read.hpp
types.hpp
write.hpp
DESTINATION
include/ox/mc
)
install(TARGETS OxMetalClaw
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)
if(OX_RUN_TESTS STREQUAL "ON")
add_subdirectory(test)
endif()

19
deps/ox/src/ox/mc/err.hpp vendored Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace ox {
enum {
MC_PRESENCEMASKOUTBOUNDS = 1,
MC_BUFFENDED = 2,
MC_OUTBUFFENDED = 4
};
}

152
deps/ox/src/ox/mc/intops.hpp vendored Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/assert.hpp>
#include <ox/std/bit.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
namespace ox::mc {
template<typename T>
static constexpr auto Bits = sizeof(T) << 3;
/**
* Returns highest bit other than possible signed bit.
* Bit numbering starts at 0.
*/
template<typename I>
[[nodiscard]] constexpr std::size_t highestBit(I val) noexcept {
auto shiftStart = sizeof(I) * 8 - 1;
// find most significant non-sign indicator bit
std::size_t highestBit = 0;
// start at one bit lower if signed
if constexpr(ox::is_signed_v<I>) {
--shiftStart;
}
for (int i = shiftStart; i > -1; --i) {
const auto bitValue = (val >> i) & 1;
if (bitValue) {
highestBit = i;
break;
}
}
return highestBit;
}
static_assert(highestBit(int8_t(0b10000000)) == 0);
static_assert(highestBit(1) == 0);
static_assert(highestBit(2) == 1);
static_assert(highestBit(4) == 2);
static_assert(highestBit(8) == 3);
static_assert(highestBit(uint64_t(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63);
struct McInt {
uint8_t data[9] = {0};
// length of integer in bytes
std::size_t length = 0;
};
template<typename I>
[[nodiscard]] constexpr McInt encodeInteger(I input) noexcept {
McInt out;
// move input to uint64_t to allow consistent bit manipulation, and to avoid
// overflow concerns
uint64_t val = 0;
ox_memcpy(&val, &input, sizeof(I));
if (val) {
// bits needed to represent number factoring in space possibly
// needed for signed bit
const auto bits = highestBit(val) + 1 + (ox::is_signed_v<I> ? 1 : 0);
// bytes needed to store value
std::size_t bytes = bits / 8 + (bits % 8 != 0);
const auto bitsAvailable = bytes * 8; // bits available to integer value
const auto bitsNeeded = bits + bytes;
// factor in bits needed for bytesIndicator (does not affect bytesIndicator)
// bits for integer + bits neded to represent bytes > bits available
if (bitsNeeded > bitsAvailable && bytes != 9) {
++bytes;
}
const auto bytesIndicator = onMask<uint8_t>(bytes - 1);
// ensure we are copying from little endian represenstation
LittleEndian<I> leVal = val;
if (bytes == 9) {
out.data[0] = bytesIndicator;
ox_memcpy(&out.data[1], &leVal, sizeof(I));
} else {
auto intermediate =
static_cast<uint64_t>(leVal.raw()) << bytes |
static_cast<uint64_t>(bytesIndicator);
ox_memcpy(out.data, &intermediate, sizeof(intermediate));
}
out.length = bytes;
}
return out;
}
/**
* Returns the number of bytes indicated by the bytes indicator of a variable
* length integer.
*/
[[nodiscard]] static constexpr std::size_t countBytes(uint8_t b) noexcept {
std::size_t i = 0;
for (; (b >> i) & 1; i++);
return i + 1;
}
static_assert(countBytes(0b00000000) == 1);
static_assert(countBytes(0b00000001) == 2);
static_assert(countBytes(0b00000011) == 3);
static_assert(countBytes(0b00000111) == 4);
static_assert(countBytes(0b00001111) == 5);
static_assert(countBytes(0b00011111) == 6);
static_assert(countBytes(0b00111111) == 7);
static_assert(countBytes(0b01111111) == 8);
static_assert(countBytes(0b11111111) == 9);
template<typename I>
[[nodiscard]] constexpr ValErr<I> decodeInteger(uint8_t buff[9], std::size_t buffLen, std::size_t *bytesRead) noexcept {
const auto bytes = countBytes(buff[0]);
if (bytes == 9) {
*bytesRead = bytes;
I out = 0;
memcpy(&out, &buff[1], sizeof(I));
return {LittleEndian<I>(out), OxError(0)};
} else if (buffLen >= bytes) {
*bytesRead = bytes;
uint64_t decoded = 0;
memcpy(&decoded, &buff[0], bytes);
decoded >>= bytes;
auto out = static_cast<I>(decoded);
// move sign bit
if constexpr(ox::is_signed_v<I>) {
const auto valBits = bytes << 3;
// get sign
uint64_t sign = decoded >> (valBits - 1);
// remove sign
decoded &= uint64_t(~0) ^ (uint64_t(1) << valBits);
// set sign
decoded |= sign << (Bits<I> - 1);
memcpy(&out, &decoded, sizeof(out));
}
return {out, OxError(0)};
}
return {0, OxError(1)};
}
template<typename I>
[[nodiscard]] ValErr<I> decodeInteger(McInt m) noexcept {
std::size_t bytesRead;
return decodeInteger<I>(m.data, 9, &bytesRead);
}
}

14
deps/ox/src/ox/mc/mc.hpp vendored Normal file
View File

@ -0,0 +1,14 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "intops.hpp"
#include "read.hpp"
#include "types.hpp"
#include "write.hpp"

59
deps/ox/src/ox/mc/presenceindicator.cpp vendored Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
#include "err.hpp"
#include "presenceindicator.hpp"
namespace ox {
FieldPresenceIndicator::FieldPresenceIndicator(uint8_t *mask, std::size_t maxLen) {
m_mask = mask;
m_maskLen = maxLen;
}
ValErr<bool> FieldPresenceIndicator::get(std::size_t i) const {
if (i / 8 < m_maskLen) {
return (m_mask[i / 8] >> (i % 8)) & 1;
} else {
return {false, OxError(MC_PRESENCEMASKOUTBOUNDS)};
}
}
Error FieldPresenceIndicator::set(std::size_t i, bool on) {
if (i / 8 < m_maskLen) {
if (on) {
m_mask[i / 8] |= 1 << (i % 8);
} else {
m_mask[i / 8] &= ~(1 << (i % 8));
}
return OxError(0);
} else {
return OxError(MC_PRESENCEMASKOUTBOUNDS);
}
}
void FieldPresenceIndicator::setFields(int fields) noexcept {
m_fields = fields;
m_maskLen = (fields / 8 + 1) - (fields % 8 == 0);
}
int FieldPresenceIndicator::getFields() const noexcept {
return m_fields;
}
void FieldPresenceIndicator::setMaxLen(int maxLen) noexcept {
m_maskLen = maxLen;
}
int FieldPresenceIndicator::getMaxLen() const noexcept {
return m_maskLen;
}
}

39
deps/ox/src/ox/mc/presenceindicator.hpp vendored Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>
namespace ox {
class FieldPresenceIndicator {
private:
uint8_t *m_mask = nullptr;
std::size_t m_maskLen = 0;
std::size_t m_fields = 0;
public:
FieldPresenceIndicator(uint8_t *mask, std::size_t maxLen);
[[nodiscard]] ValErr<bool> get(std::size_t i) const;
[[nodiscard]] Error set(std::size_t i, bool on);
void setFields(int) noexcept;
int getFields() const noexcept;
void setMaxLen(int) noexcept;
int getMaxLen() const noexcept;
};
}

154
deps/ox/src/ox/mc/read.cpp vendored Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/assert.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
#include "read.hpp"
namespace ox {
MetalClawReader::MetalClawReader(uint8_t *buff, std::size_t buffLen, int unionIdx, MetalClawReader *parent) noexcept:
m_fieldPresence(buff, buffLen),
m_unionIdx(unionIdx),
m_buffLen(buffLen),
m_buff(buff),
m_parent(parent) {
}
MetalClawReader::~MetalClawReader() noexcept {
if (m_parent) {
m_parent->m_buffIt += m_buffIt;
}
if (m_field != m_fields) {
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
}
}
Error MetalClawReader::field(const char*, int8_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, int16_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, int32_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, int64_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, uint8_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, uint16_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, uint32_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, uint64_t *val) {
return readInteger(val);
}
Error MetalClawReader::field(const char*, bool *val) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
auto valErr = m_fieldPresence.get(m_field);
*val = valErr.value;
oxReturnError(valErr.error);
}
++m_field;
return OxError(0);
}
Error MetalClawReader::field(const char*, SerStr val) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
if (m_fieldPresence.get(m_field)) {
// read the length
if (m_buffIt >= m_buffLen) {
return OxError(MC_BUFFENDED);
}
std::size_t bytesRead = 0;
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(err);
auto data = val.data(size + 1);
// read the string
if (val.cap() > -1 && static_cast<StringLength>(val.cap()) >= size) {
if (m_buffIt + size <= m_buffLen) {
ox_memcpy(data, &m_buff[m_buffIt], size);
data[size] = 0;
m_buffIt += size;
} else {
return OxError(MC_BUFFENDED);
}
} else {
return OxError(MC_OUTBUFFENDED);
}
} else {
auto data = val.data();
if (data) {
data[0] = 0;
}
}
}
++m_field;
return OxError(0);
}
[[nodiscard]] ValErr<ArrayLength> MetalClawReader::arrayLength(const char*, bool pass) {
if ((m_unionIdx == -1 || m_unionIdx == m_field) && m_fieldPresence.get(m_field)) {
// read the length
if (m_buffIt >= m_buffLen) {
return OxError(MC_BUFFENDED);
}
std::size_t bytesRead = 0;
auto out = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead).value;
if (pass) {
m_buffIt += bytesRead;
}
return out;
}
return OxError(1);
}
[[nodiscard]] StringLength MetalClawReader::stringLength(const char*) {
if ((m_unionIdx == -1 || m_unionIdx == m_field) && m_fieldPresence.get(m_field)) {
// read the length
std::size_t bytesRead = 0;
auto len = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
return len.value;
}
return 0;
}
MetalClawReader MetalClawReader::child(const char*, int unionIdx) {
return MetalClawReader(m_buff + m_buffIt, m_buffLen - m_buffIt, unionIdx, this);
}
bool MetalClawReader::fieldPresent(const char*) const {
return m_fieldPresence.get(m_field).value;
}
bool MetalClawReader::fieldPresent(int fieldNo) const {
return m_fieldPresence.get(fieldNo).value;
}
void MetalClawReader::nextField() noexcept {
++m_field;
}
}

281
deps/ox/src/ox/mc/read.hpp vendored Normal file
View File

@ -0,0 +1,281 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/string.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/vector.hpp>
#include "err.hpp"
#include "intops.hpp"
#include "presenceindicator.hpp"
#include "types.hpp"
namespace ox {
class MetalClawReader {
private:
FieldPresenceIndicator m_fieldPresence;
int m_fields = 0;
int m_field = 0;
int m_unionIdx = -1;
std::size_t m_buffIt = 0;
std::size_t m_buffLen = 0;
uint8_t *m_buff = nullptr;
MetalClawReader *m_parent = nullptr;
public:
MetalClawReader(uint8_t *buff, std::size_t buffLen, int unionIdx = -1, MetalClawReader *parent = nullptr) noexcept;
~MetalClawReader() noexcept;
[[nodiscard]] Error field(const char*, int8_t *val);
[[nodiscard]] Error field(const char*, int16_t *val);
[[nodiscard]] Error field(const char*, int32_t *val);
[[nodiscard]] Error field(const char*, int64_t *val);
[[nodiscard]] Error field(const char*, uint8_t *val);
[[nodiscard]] Error field(const char*, uint16_t *val);
[[nodiscard]] Error field(const char*, uint32_t *val);
[[nodiscard]] Error field(const char*, uint64_t *val);
[[nodiscard]] Error field(const char*, bool *val);
// array handler
template<typename T>
[[nodiscard]] Error field(const char*, T *val, std::size_t len);
// map handler
template<typename T>
[[nodiscard]] Error field(const char*, HashMap<String, T> *val);
// array handler, with callback to allow handling individual elements
template<typename T, typename Handler>
[[nodiscard]] Error field(const char*, Handler handler);
template<typename T>
[[nodiscard]] Error field(const char*, ox::Vector<T> *val);
template<typename T>
[[nodiscard]] Error field(const char*, T *val);
template<typename U>
[[nodiscard]] Error field(const char*, UnionView<U> val);
template<std::size_t L>
[[nodiscard]] Error field(const char*, ox::BString<L> *val);
[[nodiscard]] Error field(const char*, SerStr val);
/**
* Reads an array length from the current location in the buffer.
* @param pass indicates that the parsing should iterate past the array length
*/
[[nodiscard]] ValErr<ArrayLength> arrayLength(const char *name, bool pass = true);
/**
* Reads an string length from the current location in the buffer.
*/
[[nodiscard]] StringLength stringLength(const char *name);
template<typename T = std::nullptr_t>
void setTypeInfo(const char *name = T::TypeName, int fields = T::Fields);
/**
* Returns a MetalClawReader to parse a child object.
*/
[[nodiscard]] MetalClawReader child(const char *name, int unionIdx = -1);
/**
* Indicates whether or not the next field to be read is present.
*/
bool fieldPresent(const char *name) const;
/**
* Indicates whether or not the given field is present.
*/
bool fieldPresent(int fieldNo) const;
void nextField() noexcept;
static constexpr auto opType() {
return OpType::Read;
}
private:
template<typename I>
[[nodiscard]] Error readInteger(I *val);
};
template<typename T>
Error MetalClawReader::field(const char*, T *val) {
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val && m_fieldPresence.get(m_field)) {
auto reader = child("");
oxReturnError(model(&reader, val));
}
++m_field;
return OxError(0);
}
template<typename U>
Error MetalClawReader::field(const char*, UnionView<U> val) {
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val.get() && m_fieldPresence.get(m_field)) {
auto reader = child("", val.idx());
oxReturnError(model(&reader, val.get()));
}
++m_field;
return OxError(0);
}
template<std::size_t L>
Error MetalClawReader::field(const char *name, ox::BString<L> *val) {
return field(name, SerStr(val->data(), val->cap()));
}
template<typename I>
Error MetalClawReader::readInteger(I *val) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
if (m_fieldPresence.get(m_field)) {
std::size_t bytesRead = 0;
if (m_buffIt >= m_buffLen) {
oxTrace("ox::MetalClaw::readInteger") << "Buffer ended";
return OxError(MC_BUFFENDED);
}
auto valErr = mc::decodeInteger<I>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(valErr.error);
*val = valErr.value;
} else {
*val = 0;
}
}
++m_field;
return OxError(0);
}
// array handler
template<typename T>
Error MetalClawReader::field(const char *name, T *val, std::size_t valLen) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
if (m_fieldPresence.get(m_field)) {
// read the length
if (m_buffIt >= m_buffLen) {
return OxError(MC_BUFFENDED);
}
std::size_t bytesRead = 0;
auto len = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(len.error);
// read the list
if (valLen >= len.value) {
auto reader = child("");
reader.setTypeInfo("List", len.value);
for (std::size_t i = 0; i < len.value; i++) {
oxReturnError(reader.field("", &val[i]));
}
} else {
oxTrace("ox::mc::read::field(T)") << name << ", size:" << valLen;
return OxError(MC_OUTBUFFENDED);
}
}
}
++m_field;
return OxError(0);
}
template<typename T>
Error MetalClawReader::field(const char*, HashMap<String, T> *val) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
if (m_fieldPresence.get(m_field)) {
// read the length
if (m_buffIt >= m_buffLen) {
return OxError(MC_BUFFENDED);
}
std::size_t bytesRead = 0;
auto len = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(len.error);
// read the list
auto reader = child("");
reader.setTypeInfo("List", len.value);
for (std::size_t i = 0; i < len.value; i++) {
auto keyLen = reader.stringLength(nullptr);
auto wkey = ox_malloca(keyLen + 1, char, 0);
oxReturnError(reader.field("", SerStr(wkey.get(), keyLen)));
oxReturnError(reader.field("", &val->at(wkey.get())));
}
}
}
++m_field;
return OxError(0);
}
template<typename T, typename Handler>
Error MetalClawReader::field(const char*, Handler handler) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
if (m_fieldPresence.get(m_field)) {
// read the length
if (m_buffIt >= m_buffLen) {
return OxError(MC_BUFFENDED);
}
std::size_t bytesRead = 0;
auto len = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(len.error);
// read the list
auto reader = child("");
reader.setTypeInfo("List", len.value);
for (std::size_t i = 0; i < len.value; i++) {
T val;
oxReturnError(reader.field("", &val));
oxReturnError(handler(i, &val));
}
}
}
++m_field;
return OxError(0);
}
template<typename T>
Error MetalClawReader::field(const char* name, ox::Vector<T> *val) {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
// set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(m_field)) {
const auto [len, err] = arrayLength(name, false);
oxReturnError(err);
val->resize(len);
}
return field(name, val->data(), val->size());
}
return OxError(0);
}
template<typename T>
void MetalClawReader::setTypeInfo(const char*, int fields) {
m_fields = fields;
m_buffIt = (fields / 8 + 1) - (fields % 8 == 0);
m_fieldPresence.setFields(fields);
m_fieldPresence.setMaxLen(m_buffIt);
}
template<typename T>
Error readMC(uint8_t *buff, std::size_t buffLen, T *val) {
MetalClawReader reader(buff, buffLen);
return model(&reader, val);
}
}

15
deps/ox/src/ox/mc/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,15 @@
add_executable(
McTest
tests.cpp
)
target_link_libraries(
McTest
OxMetalClaw
)
add_test("Test\\ McTest\\ Writer" McTest MetalClawWriter)
add_test("Test\\ McTest\\ Reader" McTest MetalClawReader)
add_test("Test\\ McTest\\ MetalClawDef" McTest MetalClawDef)
add_test("Test\\ McTest\\ encodeInteger" McTest encodeInteger)
add_test("Test\\ McTest\\ decodeInteger" McTest decodeInteger)

407
deps/ox/src/ox/mc/test/tests.cpp vendored Normal file
View File

@ -0,0 +1,407 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "ox/std/hashmap.hpp"
#undef NDEBUG
#include <assert.h>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <ox/mc/mc.hpp>
#include <ox/model/model.hpp>
#include <ox/std/std.hpp>
union TestUnion {
static constexpr auto TypeName = "TestUnion";
static constexpr auto Fields = 3;
bool Bool;
uint32_t Int = 5;
char String[32];
};
struct TestStructNest {
static constexpr auto TypeName = "TestStructNest";
static constexpr auto Fields = 3;
bool Bool = false;
uint32_t Int = 0;
ox::BString<32> String = "";
};
struct TestStruct {
static constexpr auto TypeName = "TestStruct";
static constexpr auto Fields = 17;
bool Bool = false;
int32_t Int = 0;
int32_t Int1 = 0;
int32_t Int2 = 0;
int32_t Int3 = 0;
int32_t Int4 = 0;
int32_t Int5 = 0;
int32_t Int6 = 0;
int32_t Int7 = 0;
int32_t Int8 = 0;
TestUnion Union;
char *CString = nullptr;
ox::BString<32> String = "";
uint32_t List[4] = {0, 0, 0, 0};
ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct;
TestStructNest Struct;
~TestStruct() {
delete[] CString;
}
};
template<typename T>
ox::Error model(T *io, TestUnion *obj) {
io->template setTypeInfo<TestUnion>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", ox::SerStr(obj->String)));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStructNest *obj) {
io->template setTypeInfo<TestStructNest>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStruct *obj) {
io->template setTypeInfo<TestStruct>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
oxReturnError(io->field("CString", ox::SerStr(&obj->CString)));
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct));
return OxError(0);
}
std::map<std::string, ox::Error(*)()> tests = {
{
{
"MetalClawWriter",
[] {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
constexpr size_t buffLen = 1024;
uint8_t buff[buffLen];
TestStruct ts;
oxReturnError(ox::writeMC(buff, buffLen, &ts));
return OxError(0);
}
},
{
"MetalClawReader",
[] {
constexpr size_t buffLen = 1024;
uint8_t buff[buffLen];
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
testIn.Union.Int = 42;
testIn.String = "Test String 1";
testIn.CString = new char[ox_strlen("c-string") + 1];
ox_strcpy(testIn.CString, "c-string");
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Map["asdf"] = 93;
testIn.Map["aoeu"] = 94;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed");
oxAssert(ox::readMC(buff, buffLen, &testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");
oxAssert(testIn.Int2 == testOut.Int2, "Int2 value mismatch");
oxAssert(testIn.Int3 == testOut.Int3, "Int3 value mismatch");
oxAssert(testIn.Int4 == testOut.Int4, "Int4 value mismatch");
oxAssert(testIn.Int5 == testOut.Int5, "Int5 value mismatch");
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
oxAssert(ox_strcmp(testIn.CString, testOut.CString) == 0, "CString value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch");
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
oxAssert(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
oxAssert(testIn.EmptyStruct.String == testOut.EmptyStruct.String, "EmptyStruct.String value mismatch");
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0);
}
},
{
"encodeInteger",
[] {
using ox::MaxValue;
using ox::mc::McInt;
using ox::mc::encodeInteger;
constexpr auto check = [](McInt val, std::vector<uint8_t> &&expected) {
if (val.length != expected.size()) {
std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n';
return OxError(1);
}
for (std::size_t i = 0; i < expected.size(); i++) {
if (expected[i] != val.data[i]) {
std::cout << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
return OxError(1);
}
}
return OxError(0);
};
constexpr auto check64 = [](McInt val, auto expected) {
if (val.length != 9) {
std::cout << "val.length: " << val.length << '\n';
return OxError(1);
}
ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]);
if (expected != decoded) {
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
return OxError(1);
}
return OxError(0);
};
oxAssert(check(encodeInteger(int64_t(1)), {0b00000010}), "Encode 1 fail");
oxAssert(check(encodeInteger(int64_t(2)), {0b00000100}), "Encode 2 fail");
oxAssert(check(encodeInteger(int64_t(3)), {0b00000110}), "Encode 3 fail");
oxAssert(check(encodeInteger(int64_t(4)), {0b00001000}), "Encode 4 fail");
oxAssert(check(encodeInteger(int64_t(128)), {0b00000001, 0b10}), "Encode 128 fail");
oxAssert(check(encodeInteger(int64_t(129)), {0b00000101, 0b10}), "Encode 129 fail");
oxAssert(check(encodeInteger(int64_t(130)), {0b00001001, 0b10}), "Encode 130 fail");
oxAssert(check(encodeInteger(int64_t(131)), {0b00001101, 0b10}), "Encode 131 fail");
oxAssert(check(encodeInteger(int64_t(-1)), {255, 255, 255, 255, 255, 255, 255, 255, 255}), "Encode -1 fail");
oxAssert(check(encodeInteger(int64_t(-2)), {255, 254, 255, 255, 255, 255, 255, 255, 255}), "Encode -2 fail");
oxAssert(check(encodeInteger(int64_t(-3)), {255, 253, 255, 255, 255, 255, 255, 255, 255}), "Encode -3 fail");
oxAssert(check(encodeInteger(int64_t(-4)), {255, 252, 255, 255, 255, 255, 255, 255, 255}), "Encode -4 fail");
oxAssert(check(encodeInteger(int64_t(-128)), {255, 128, 255, 255, 255, 255, 255, 255, 255}), "Encode -128 fail");
oxAssert(check(encodeInteger(int64_t(-129)), {255, 127, 255, 255, 255, 255, 255, 255, 255}), "Encode -129 fail");
oxAssert(check(encodeInteger(int64_t(-130)), {255, 126, 255, 255, 255, 255, 255, 255, 255}), "Encode -130 fail");
oxAssert(check(encodeInteger(int64_t(-131)), {255, 125, 255, 255, 255, 255, 255, 255, 255}), "Encode -131 fail");
oxAssert(check(encodeInteger(uint32_t(0xffffffff)), {0b11101111, 255, 255, 255, 0b00011111}), "Encode 0xffffffff fail");
oxAssert(check(encodeInteger(uint64_t(1)), {0b0010}), "Encode 1 fail");
oxAssert(check(encodeInteger(uint64_t(2)), {0b0100}), "Encode 2 fail");
oxAssert(check(encodeInteger(uint64_t(3)), {0b0110}), "Encode 3 fail");
oxAssert(check(encodeInteger(uint64_t(4)), {0b1000}), "Encode 4 fail");
oxAssert(check(encodeInteger(uint64_t(128)), {0b0001, 0b10}), "Encode 128 fail");
oxAssert(check(encodeInteger(uint64_t(129)), {0b0101, 0b10}), "Encode 129 fail");
oxAssert(check(encodeInteger(uint64_t(130)), {0b1001, 0b10}), "Encode 130 fail");
oxAssert(check(encodeInteger(uint64_t(131)), {0b1101, 0b10}), "Encode 131 fail");
// Signed check needs lambda templates to run correctly without
// code deduplication
//oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail");
oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail");
return OxError(0);
}
},
{
"decodeInteger",
[] {
using ox::MaxValue;
using ox::mc::McInt;
using ox::mc::encodeInteger;
using ox::mc::decodeInteger;
constexpr auto check = [](auto val) {
auto result = decodeInteger<decltype(val)>(encodeInteger(val));
oxReturnError(result.error);
if (result.value != val) {
std::cout << "Bad value: " << result.value << ", expected: " << val << '\n';
return OxError(1);
}
return OxError(0);
};
oxAssert(check(uint32_t(14)), "Decode of 14 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(42)), "Decode of 42 failed.");
oxAssert(check(int64_t(130)), "Decode of 130 failed.");
oxAssert(check(int64_t(131)), "Decode of 131 failed.");
oxAssert(check(uint64_t(1)), "Decode of 1 failed.");
oxAssert(check(uint64_t(2)), "Decode of 2 failed.");
oxAssert(check(uint64_t(42)), "Decode of 42 failed.");
oxAssert(check(uint64_t(130)), "Decode of 130 failed.");
oxAssert(check(uint64_t(131)), "Decode of 131 failed.");
oxAssert(check(0xffffffff), "Decode of 0xffffffff failed.");
oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed.");
oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed.");
return OxError(0);
}
},
{
"MetalClawDef",
[] {
//constexpr size_t descBuffLen = 1024;
//uint8_t descBuff[descBuffLen];
constexpr size_t dataBuffLen = 1024;
uint8_t dataBuff[dataBuffLen];
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
testIn.String = "Test String 1";
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
auto type = ox::buildTypeDef(&testIn);
oxAssert(type.error, "Descriptor write failed");
ox::walkModel<ox::MetalClawReader>(type.value, dataBuff, dataBuffLen,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str();
switch (f.type->primitiveType) {
case ox::PrimitiveType::UnsignedInteger:
std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t";
switch (f.type->length) {
case 1: {
uint8_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 2: {
uint16_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 4: {
uint32_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 8: {
uint64_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
}
std::cout << '\n';
break;
case ox::PrimitiveType::SignedInteger:
std::cout << fieldName << ":\tint" << f.type->length * 8 << "_t:\t";
switch (f.type->length) {
case 1: {
int8_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 2: {
int16_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 4: {
int32_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 8: {
int64_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
}
std::cout << '\n';
break;
case ox::PrimitiveType::Bool: {
bool i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << fieldName << ":\t" << "bool:\t\t" << (i ? "true" : "false") << '\n';
break;
}
case ox::PrimitiveType::String: {
ox::Vector<char> v(rdr->stringLength(fieldName) + 1);
//std::cout << rdr->stringLength() << '\n';
oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed.");
std::cout << fieldName << ":\t" << "string:\t\t" << v.data() << '\n';
break;
}
case ox::PrimitiveType::Struct:
break;
case ox::PrimitiveType::Union:
break;
}
return OxError(0);
}
);
delete type.value;
return OxError(0);
}
},
}
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 0) {
auto testName = args[1];
if (tests.find(testName) != tests.end()) {
retval = tests[testName]();
}
}
return retval;
}

View File

@ -1,20 +1,20 @@
/* /*
* Copyright 2016-2017 gtalent2@gmail.com * Copyright 2015 - 2018 gtalent2@gmail.com
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#pragma once
#include <ox/std/string.hpp>
#include <ox/std/strops.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include "gfx.hpp"
namespace nostalgia { namespace ox {
namespace core {
ox::Error init() { using StringLength = uint32_t;
auto err = initGfx(); using ArrayLength = uint32_t;
return err;
}
} }
}

97
deps/ox/src/ox/mc/write.cpp vendored Normal file
View File

@ -0,0 +1,97 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/assert.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
#include <ox/std/trace.hpp>
#include "write.hpp"
namespace ox {
MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
m_fieldPresence(buff, buffLen),
m_unionIdx(unionIdx),
m_buffLen(buffLen),
m_buff(buff) {
}
MetalClawWriter::~MetalClawWriter() noexcept {
if (m_field != m_fields) {
oxTrace("ox::mc::MetalClawWriter::error") << "MetalClawReader: incorrect fields number given";
}
}
Error MetalClawWriter::field(const char*, int8_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, int16_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, int32_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, int64_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, uint8_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, uint16_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, uint32_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, uint64_t *val) noexcept {
return appendInteger(*val);
}
Error MetalClawWriter::field(const char*, bool *val) noexcept {
if (m_unionIdx == -1 || m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(m_field, *val));
}
++m_field;
return OxError(0);
}
Error MetalClawWriter::field(const char*, SerStr val) noexcept {
bool fieldSet = false;
if (val.len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto strLen = mc::encodeInteger(val.len());
if (m_buffIt + strLen.length + val.len() < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], strLen.data, strLen.length);
m_buffIt += strLen.length;
// write the string
ox_memcpy(&m_buff[m_buffIt], val.c_str(), val.len());
m_buffIt += val.len();
fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
++m_field;
return OxError(0);
}
std::size_t MetalClawWriter::size() noexcept {
return m_buffIt;
}
}

249
deps/ox/src/ox/mc/write.hpp vendored Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/bit.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/string.hpp>
#include <ox/std/types.hpp>
#include <ox/std/units.hpp>
#include <ox/std/vector.hpp>
#include "intops.hpp"
#include "err.hpp"
#include "ox/std/hashmap.hpp"
#include "presenceindicator.hpp"
#include "types.hpp"
namespace ox {
class MetalClawWriter {
private:
FieldPresenceIndicator m_fieldPresence;
int m_fields = 0;
int m_field = 0;
int m_unionIdx = -1;
std::size_t m_buffIt = 0;
std::size_t m_buffLen = 0;
uint8_t *m_buff = nullptr;
public:
MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx = -1) noexcept;
~MetalClawWriter() noexcept;
[[nodiscard]] Error field(const char*, int8_t *val) noexcept;
[[nodiscard]] Error field(const char*, int16_t *val) noexcept;
[[nodiscard]] Error field(const char*, int32_t *val) noexcept;
[[nodiscard]] Error field(const char*, int64_t *val) noexcept;
[[nodiscard]] Error field(const char*, uint8_t *val) noexcept;
[[nodiscard]] Error field(const char*, uint16_t *val) noexcept;
[[nodiscard]] Error field(const char*, uint32_t *val) noexcept;
[[nodiscard]] Error field(const char*, uint64_t *val) noexcept;
[[nodiscard]] Error field(const char*, bool *val) noexcept;
template<typename T>
[[nodiscard]] Error field(const char*, T *val, std::size_t len);
template<typename T>
[[nodiscard]] Error field(const char*, Vector<T> *val);
template<typename T>
[[nodiscard]] Error field(const char*, HashMap<String, T> *val);
template<std::size_t L>
[[nodiscard]] Error field(const char*, ox::BString<L> *val) noexcept;
[[nodiscard]] Error field(const char*, SerStr val) noexcept;
template<typename T>
[[nodiscard]] Error field(const char*, T *val);
template<typename U>
[[nodiscard]] Error field(const char*, UnionView<U> val);
template<typename T = std::nullptr_t>
void setTypeInfo(const char *name = T::TypeName, int fields = T::Fields);
std::size_t size() noexcept;
static constexpr auto opType() {
return OpType::Write;
}
private:
template<typename I>
[[nodiscard]] Error appendInteger(I val) noexcept;
};
template<std::size_t L>
Error MetalClawWriter::field(const char *name, ox::BString<L> *val) noexcept {
return field(name, SerStr(val->data(), val->cap()));
}
template<typename T>
Error MetalClawWriter::field(const char*, T *val) {
bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
oxReturnError(model(&writer, val));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
m_field++;
return OxError(0);
}
template<typename U>
Error MetalClawWriter::field(const char*, UnionView<U> val) {
bool fieldSet = false;
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt, val.idx());
oxReturnError(model(&writer, val.get()));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
m_field++;
return OxError(0);
}
template<typename T>
Error MetalClawWriter::field(const char*, T *val, std::size_t len) {
bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length);
m_buffIt += arrLen.length;
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
writer.setTypeInfo<T>("List", len);
// write the array
for (std::size_t i = 0; i < len; i++) {
oxReturnError(writer.field("", &val[i]));
}
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
m_field++;
return OxError(0);
}
template<typename T>
Error MetalClawWriter::field(const char*, Vector<T> *val) {
return field(nullptr, val->data(), val->size());
}
template<typename T>
[[nodiscard]] Error MetalClawWriter::field(const char*, HashMap<String, T> *val) {
auto &keys = val->keys();
auto len = keys.size();
bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) {
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length);
m_buffIt += arrLen.length;
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
// double len for both key and value
writer.setTypeInfo("Map", len * 2);
// write the array
for (std::size_t i = 0; i < len; i++) {
auto &key = keys[i];
const auto keyLen = ox_strlen(key);
auto wkey = static_cast<char*>(ox_alloca(keyLen + 1));
memcpy(wkey, key.c_str(), keyLen + 1);
oxReturnError(writer.field("", SerStr(&wkey, keyLen)));
oxReturnError(writer.field("", &(*val)[key]));
}
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
m_field++;
return OxError(0);
}
template<typename I>
Error MetalClawWriter::appendInteger(I val) noexcept {
bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val);
if (mi.length < m_buffLen) {
fieldSet = true;
ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length);
m_buffIt += mi.length;
} else {
oxReturnError(OxError(MC_BUFFENDED));
}
}
oxReturnError(m_fieldPresence.set(m_field, fieldSet));
m_field++;
return OxError(0);
;
}
template<typename T>
void MetalClawWriter::setTypeInfo(const char*, int fields) {
m_fields = fields;
m_fieldPresence.setFields(fields);
m_buffIt = m_fieldPresence.getMaxLen();
ox_memset(m_buff, 0, m_buffIt);
}
template<typename T>
ValErr<Vector<char>> writeMC(T *val) {
Vector<char> buff(10 * units::MB);
MetalClawWriter writer(bit_cast<uint8_t*>(buff.data()), buff.size());
oxReturnError(model(&writer, val));
buff.resize(writer.size());
return buff;
}
template<typename T>
Error writeMC(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) {
MetalClawWriter writer(buff, buffLen);
auto err = model(&writer, val);
if (sizeOut) {
*sizeOut = writer.size();
}
return err;
}
}

37
deps/ox/src/ox/model/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,37 @@
add_library(
OxModel
desctypes.cpp
descwrite.cpp
)
target_link_libraries(
OxModel PUBLIC
OxStd
)
if(NOT OX_BARE_METAL)
set_property(
TARGET
OxModel
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
endif()
install(
FILES
descread.hpp
desctypes.hpp
descwrite.hpp
optype.hpp
model.hpp
types.hpp
walk.hpp
DESTINATION
include/ox/model
)
install(TARGETS OxModel
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)

View File

@ -0,0 +1,7 @@
<Type> : <TypeName><FieldList>
<FieldList> : <FieldList> | <FieldList><Field>
<Field> : <FieldType><TypeID><FieldName>
<TypeID> : <TypeName> | <TypeName><Type>
<TypeName> : <string>
<FieldType> : <0: single> | <1: list>
<FieldName> : <string>

42
deps/ox/src/ox/model/descread.hpp vendored Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "desctypes.hpp"
namespace ox {
template<typename ReaderBase>
class TypeDescReader: public ReaderBase {
private:
TypeStore m_typeStore;
public:
TypeDescReader(uint8_t *buff, std::size_t buffLen);
const TypeStore &typeStore() const;
};
template<typename ReaderBase>
TypeDescReader<ReaderBase>::TypeDescReader(uint8_t *buff, std::size_t buffLen): ReaderBase(buff, buffLen) {
}
template<typename ReaderBase>
const TypeStore &TypeDescReader<ReaderBase>::typeStore() const {
return m_typeStore;
}
template<typename ReaderBase, typename T>
int readMCDef(uint8_t *buff, std::size_t buffLen, T *val) {
TypeDescReader<ReaderBase> reader(buff, buffLen);
return model(&reader, val);
}
}

19
deps/ox/src/ox/model/desctypes.cpp vendored Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "desctypes.hpp"
namespace ox {
DescriptorField::~DescriptorField() {
if (ownsType) {
delete type;
}
}
}

184
deps/ox/src/ox/model/desctypes.hpp vendored Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/bit.hpp>
#include <ox/std/error.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/bstring.hpp>
#include <ox/std/vector.hpp>
#include "types.hpp"
namespace ox {
using ModelString = BString<100>;
using FieldName = ModelString;
using TypeName = ModelString;
enum class PrimitiveType: uint8_t {
UnsignedInteger = 0,
SignedInteger = 1,
Bool = 2,
// Float = 3, reserved, but not implemented
String = 4,
Struct = 5,
Union = 6,
};
struct DescriptorField {
// order of fields matters
static constexpr auto TypeVersion = 1;
// only serialize type name if type has already been serialized
struct DescriptorType *type = nullptr;
FieldName fieldName;
int subscriptLevels = 0;
// do not serialize the following
TypeName typeName; // gives reference to type for lookup if type is null
bool ownsType = false;
constexpr DescriptorField() noexcept = default;
/**
* Allow for explicit copying.
*/
constexpr explicit DescriptorField(const DescriptorField &other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = false; // is copy, only owns type if move
}
constexpr DescriptorField(DescriptorType *type, const FieldName &fieldName, int subscriptLevels, const TypeName &typeName, bool ownsType) noexcept {
this->type = type;
this->fieldName = fieldName;
this->subscriptLevels = subscriptLevels;
this->typeName = typeName;
this->ownsType = ownsType;
}
constexpr DescriptorField(DescriptorField &&other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = other.ownsType;
other.type = {};
other.fieldName = "";
other.subscriptLevels = {};
other.typeName = "";
other.ownsType = {};
}
~DescriptorField();
const DescriptorField &operator=(DescriptorField &&other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = other.ownsType;
other.type = {};
other.fieldName = "";
other.subscriptLevels = {};
other.typeName = "";
other.ownsType = {};
return *this;
}
};
using FieldList = Vector<DescriptorField>;
struct DescriptorType {
static constexpr auto TypeVersion = 1;
TypeName typeName;
PrimitiveType primitiveType;
// fieldList only applies to structs
FieldList fieldList;
// - number of bytes for integer and float types
// - number of fields for structs and lists
int64_t length = 0;
bool preloadable = false;
DescriptorType() = default;
DescriptorType(TypeName tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) {
}
DescriptorType(TypeName tn, PrimitiveType t, FieldList fl): typeName(tn), primitiveType(t), fieldList(fl) {
}
};
template<typename T>
Error model(T *io, DescriptorType *type) {
io->template setTypeInfo<T>("net.drinkingtea.ox.DescriptorType", 5);
oxReturnError(io->field("typeName", &type->typeName));
oxReturnError(io->field("primitiveType", bit_cast<uint8_t*>(&type->primitiveType)));
oxReturnError(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable));
return OxError(0);
}
template<typename T>
Error modelWrite(T *io, DescriptorField *field) {
auto err = OxError(0);
io->setTypeInfo("ox::DescriptorField", 4);
if (field->ownsType) {
BString<2> empty = "";
oxReturnError(io->field("typeName", SerStr(&empty)));
oxReturnError(io->field("type", field->type));
} else {
oxReturnError(io->field("typeName", SerStr(&field->type->typeName)));
oxReturnError(io->field("type", static_cast<decltype(field->type)>(nullptr)));
}
oxReturnError(io->field("fieldName", &field->fieldName));
// defaultValue is unused now, but leave placeholder for backwards compatibility
int DefaultValue = 0;
oxReturnError(io->field("defaultValue", &DefaultValue));
return err;
}
template<typename T>
Error modelRead(T *io, DescriptorField *field) {
auto err = OxError(0);
auto &typeStore = io->typeStore();
io->setTypeInfo("ox::DescriptorField", 4);
err |= io->field("typeName", &field->typeName);
if (field->typeName == "") {
field->ownsType = true;
if (field->type == nullptr) {
field->type = new DescriptorType;
}
err |= io->field("type", field->type);
typeStore[field->type->typeName] = field->type;
} else {
// should be empty, so discard
DescriptorType t;
err |= io->field("type", &t);
field->type = typeStore[field->typeName];
}
err |= io->field("fieldName", &field->fieldName);
// defaultValue is unused now, but placeholder for backwards compatibility
err |= io->field("defaultValue", nullptr);
return err;
}
using TypeStore = ox::HashMap<ModelString, DescriptorType*>;
}

163
deps/ox/src/ox/model/descwrite.cpp vendored Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/typeinfo.hpp>
#include "descwrite.hpp"
namespace ox {
namespace detail {
struct preloadable_type {
static constexpr auto Preloadable = true;
};
struct non_preloadable_type {
static constexpr auto Preloadable = false;
};
struct non_preloadable_type2 {
};
static_assert(preloadable<preloadable_type>::value);
static_assert(!preloadable<non_preloadable_type>::value);
static_assert(!preloadable<non_preloadable_type2>::value);
}
static_assert([] {
int i = 0;
return indirectionLevels(i) == 0;
}(), "indirectionLevels broken: indirectionLevels(int)");
static_assert([] {
int i = 0;
return indirectionLevels(&i) == 1;
}(), "indirectionLevels broken: indirectionLevels(int*)");
static_assert([] {
int i[2] = {};
return indirectionLevels(i) == 1;
}(), "indirectionLevels broken: indirectionLevels(int[])");
TypeDescWriter::TypeDescWriter(TypeStore *typeStore) {
if (!typeStore) {
m_typeStoreOwnerRef = new TypeStore;
typeStore = m_typeStoreOwnerRef;
}
m_typeStore = typeStore;
}
TypeDescWriter::~TypeDescWriter() {
// does not own it's elements
delete m_typeStoreOwnerRef;
}
DescriptorType *TypeDescWriter::type(int8_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int8_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int16_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int16_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int32_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int32_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int64_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int64_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint8_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint8_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint16_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint16_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint32_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint32_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint64_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint64_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(char*, bool *alreadyExisted) {
constexpr auto TypeName = "B:string";
constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(SerStr, bool *alreadyExisted) {
constexpr auto TypeName = "B:string";
constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(String*, bool *alreadyExisted) {
constexpr auto TypeName = "B:string";
constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(bool*, bool *alreadyExisted) {
constexpr auto TypeName = "B:bool";
constexpr auto PT = PrimitiveType::Bool;
constexpr auto Bytes = 0;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::getType(TypeName tn, PrimitiveType pt, int b, bool *alreadyExisted) {
if (m_typeStore->contains(tn)) {
*alreadyExisted = true;
auto type = m_typeStore->at(tn);
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
return type;
} else {
*alreadyExisted = false;
auto &t = m_typeStore->at(tn);
if (!t) {
t = new DescriptorType;
}
t->typeName = tn;
t->primitiveType = pt;
t->length = b;
return t;
}
}
}

254
deps/ox/src/ox/model/descwrite.hpp vendored Normal file
View File

@ -0,0 +1,254 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/byteswap.hpp>
#include <ox/std/bstring.hpp>
#include <ox/std/string.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/types.hpp>
#include <ox/std/vector.hpp>
#include "desctypes.hpp"
#include "optype.hpp"
#include "types.hpp"
namespace ox {
namespace detail {
template<bool>
struct BoolWrapper {
};
template<typename T, typename = BoolWrapper<true>>
struct preloadable: false_type {};
template<typename T>
struct preloadable<T, BoolWrapper<T::Preloadable>> {
static constexpr bool value = T::Preloadable;
};
}
template<typename T>
static constexpr int indirectionLevels(T) {
return 0;
}
template<typename T>
static constexpr int indirectionLevels(T *t) {
return 1 + indirectionLevels(*t);
}
class TypeDescWriter {
private:
struct NameCatcher {
TypeName name;
template<typename T = std::nullptr_t>
constexpr void setTypeInfo(const char *n = T::TypeName, int = T::Fields) noexcept {
this->name = n;
}
template<typename T>
[[nodiscard]] constexpr ox::Error field(const char*, T*, std::size_t) noexcept {
return OxError(0);
}
template<typename T>
[[nodiscard]] constexpr ox::Error field(const char*, T) noexcept {
return OxError(0);
}
static constexpr auto opType() {
return OpType::WriteDefinition;
}
};
TypeStore *m_typeStoreOwnerRef = nullptr;
TypeStore *m_typeStore = nullptr;
DescriptorType *m_type = nullptr;
public:
explicit TypeDescWriter(TypeStore *typeStore = nullptr);
~TypeDescWriter();
template<typename T>
[[nodiscard]] ox::Error field(const char *name, T *val, std::size_t valLen);
template<typename T>
[[nodiscard]] ox::Error field(const char *name, T val);
template<typename T>
[[nodiscard]] ox::Error field(const char *name, T *val);
template<typename T = std::nullptr_t>
void setTypeInfo(const char *name = T::TypeName, int fields = T::Fields);
[[nodiscard]] DescriptorType *definition() noexcept {
return m_type;
}
static constexpr auto opType() {
return OpType::WriteDefinition;
}
private:
DescriptorType *type(int8_t *val, bool *alreadyExisted);
DescriptorType *type(int16_t *val, bool *alreadyExisted);
DescriptorType *type(int32_t *val, bool *alreadyExisted);
DescriptorType *type(int64_t *val, bool *alreadyExisted);
DescriptorType *type(uint8_t *val, bool *alreadyExisted);
DescriptorType *type(uint16_t *val, bool *alreadyExisted);
DescriptorType *type(uint32_t *val, bool *alreadyExisted);
DescriptorType *type(uint64_t *val, bool *alreadyExisted);
DescriptorType *type(bool *val, bool *alreadyExisted);
DescriptorType *type(char *val, bool *alreadyExisted);
DescriptorType *type(SerStr val, bool *alreadyExisted);
DescriptorType *type(String *val, bool *alreadyExisted);
template<std::size_t sz>
DescriptorType *type(BString<sz> *val, bool *alreadyExisted);
template<typename T>
DescriptorType *type(T *val, bool *alreadyExisted);
template<typename T>
DescriptorType *type(Vector<T> *val, bool *alreadyExisted);
template<typename T>
DescriptorType *type(HashMap<String, T> *val, bool *alreadyExisted);
template<typename U>
DescriptorType *type(UnionView<U> val, bool *alreadyExisted);
DescriptorType *getType(TypeName tn, PrimitiveType t, int b, bool *alreadyExisted);
};
// array handler
template<typename T>
ox::Error TypeDescWriter::field(const char *name, T *val, std::size_t) {
if (m_type) {
constexpr typename ox::remove_pointer<decltype(val)>::type *p = nullptr;
bool alreadyExisted = false;
const auto t = type(p, &alreadyExisted);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
if (t == nullptr) {
type(p, &alreadyExisted);
}
m_type->fieldList.emplace_back(t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted);
return OxError(0);
}
return OxError(1);
}
template<typename T>
ox::Error TypeDescWriter::field(const char *name, T val) {
if (m_type) {
bool alreadyExisted = false;
const auto t = type(val, &alreadyExisted);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted);
return OxError(0);
}
return OxError(1);
}
template<typename T>
ox::Error TypeDescWriter::field(const char *name, T *val) {
if (m_type) {
bool alreadyExisted = false;
const auto t = type(val, &alreadyExisted);
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted);
return OxError(0);
}
return OxError(1);
}
template<std::size_t sz>
DescriptorType *TypeDescWriter::type(BString<sz> *val, bool *alreadyExisted) {
return type(SerStr(val), alreadyExisted);
}
template<typename T>
DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) {
NameCatcher nc;
oxLogError(model(&nc, val));
if (m_typeStore->contains(nc.name)) {
*alreadyExisted = true;
return m_typeStore->at(nc.name);
} else {
TypeDescWriter dw(m_typeStore);
oxLogError(model(&dw, val));
*alreadyExisted = false;
return dw.m_type;
}
}
template<typename T>
DescriptorType *TypeDescWriter::type(Vector<T> *val, bool *alreadyExisted) {
return type(val->data(), alreadyExisted);
}
template<typename T>
DescriptorType *TypeDescWriter::type(HashMap<String, T>*, bool *alreadyExisted) {
return type(static_cast<T*>(nullptr), alreadyExisted);
}
template<typename U>
DescriptorType *TypeDescWriter::type(UnionView<U> val, bool *alreadyExisted) {
return type(val.get(), alreadyExisted);
}
template<typename T>
void TypeDescWriter::setTypeInfo(const char *name, int) {
auto &t = m_typeStore->at(name);
if (!t) {
t = new DescriptorType;
}
m_type = t;
m_type->typeName = name;
if (is_union_v<T>) {
m_type->primitiveType = PrimitiveType::Union;
} else {
m_type->primitiveType = PrimitiveType::Struct;
}
m_type->preloadable = detail::preloadable<T>::value;
}
template<typename T>
[[nodiscard]] ValErr<DescriptorType*> buildTypeDef(T *val) {
TypeDescWriter writer;
Error err = model(&writer, val);
return {writer.definition(), err};
}
template<typename T>
Error writeTypeDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) {
auto def = buildTypeDef(val);
auto err = def.error;
if (!err) {
oxReturnError(writeType(buff, buffLen, def.value, sizeOut));
}
delete def.value;
return err;
}
}

15
deps/ox/src/ox/model/model.hpp vendored Normal file
View File

@ -0,0 +1,15 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "descread.hpp"
#include "desctypes.hpp"
#include "descwrite.hpp"
#include "types.hpp"
#include "walk.hpp"

54
deps/ox/src/ox/model/optype.hpp vendored Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/assert.hpp>
#include <ox/std/error.hpp>
#include <ox/std/strops.hpp>
namespace ox {
namespace OpType {
constexpr auto Read = "Read";
constexpr auto Write = "Write";
constexpr auto WriteDefinition = "WriteDefinition";
}
// empty default implementations of model functions
template<typename T, typename O>
[[nodiscard]] ox::Error modelRead(T*, O*) {
return OxError(1, "Model: modelRead not implemented");
}
template<typename T, typename O>
[[nodiscard]] ox::Error modelWrite(T*, O*) {
return OxError(1, "Model: modelWrite not implemented");
}
template<typename T, typename O>
[[nodiscard]] ox::Error modelWriteDefinition(T*, O*) {
return OxError(1, "Model: modelWriteDefinition not implemented");
}
template<typename T, typename O>
[[nodiscard]] ox::Error model(T *io, O *obj) {
ox::Error err;
if constexpr(ox_strcmp(T::opType(), ox::OpType::Read) == 0) {
err = modelRead(io, obj);
} else if constexpr(ox_strcmp(T::opType(), ox::OpType::Write) == 0) {
err = modelWrite(io, obj);
} else if constexpr(ox_strcmp(T::opType(), ox::OpType::WriteDefinition) == 0) {
err = modelWriteDefinition(io, obj);
}
oxAssert(err, "Missing model function");
return err;
}
}

93
deps/ox/src/ox/model/types.hpp vendored Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/bstring.hpp>
#include <ox/std/strops.hpp>
#include <ox/std/types.hpp>
#include <ox/std/typetraits.hpp>
namespace ox {
class SerStr {
protected:
int m_cap = 0;
char *m_str = nullptr;
char **m_tgt = nullptr;
public:
template<std::size_t sz>
constexpr SerStr(BString<sz> *str) noexcept {
m_str = str->data();
m_cap = str->cap();
}
constexpr SerStr(char *str, int cap) noexcept {
m_str = str;
m_cap = cap;
}
constexpr SerStr(char **tgt, int cap = -1) noexcept {
m_tgt = tgt;
m_str = const_cast<char*>(*tgt);
m_cap = cap;
}
template<std::size_t cap>
constexpr SerStr(char (&str)[cap]) noexcept {
m_str = str;
m_cap = cap;
}
constexpr const char *c_str() noexcept {
return m_str;
}
constexpr char *data(std::size_t sz = 0) noexcept {
if (m_tgt && sz) {
*m_tgt = new char[sz];
m_str = *m_tgt;
m_cap = sz;
}
return m_str;
}
constexpr int len() noexcept {
return m_str ? ox_strlen(m_str) : 0;
}
constexpr int cap() noexcept {
return m_cap;
}
};
template<typename Union>
class UnionView {
protected:
int m_idx = -1;
typename enable_if<is_union_v<Union>, Union>::type *m_union = nullptr;
public:
constexpr explicit UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {
}
constexpr auto idx() noexcept {
return m_idx;
}
constexpr Union *get() noexcept {
return m_union;
}
};
}

155
deps/ox/src/ox/model/walk.hpp vendored Normal file
View File

@ -0,0 +1,155 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/error.hpp>
#include "desctypes.hpp"
namespace ox {
template<typename Reader, typename T>
class DataWalker {
template<typename ReaderBase, typename FH>
friend ox::Error parseField(const DescriptorField &field, ReaderBase *rdr, DataWalker<ReaderBase, FH> *walker);
private:
Vector<const DescriptorType*> m_typeStack;
T m_fieldHandler;
Vector<FieldName> m_path;
Vector<TypeName> m_typePath;
public:
DataWalker(DescriptorType *type, T fieldHandler);
[[nodiscard]] const DescriptorType *type() const noexcept;
[[nodiscard]] ox::Error read(const DescriptorField&, Reader *rdr);
protected:
void pushNamePath(FieldName fn);
void popNamePath();
void pushType(const DescriptorType *type);
void popType();
};
template<typename Reader, typename T>
DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler): m_fieldHandler(fieldHandler) {
m_typeStack.push_back(type);
}
template<typename Reader, typename T>
const DescriptorType *DataWalker<Reader, T>::type() const noexcept {
return m_typeStack.back();
}
template<typename Reader, typename T>
ox::Error DataWalker<Reader, T>::read(const DescriptorField &f, Reader *rdr) {
// get const ref of paths
const auto &pathCr = m_path;
const auto &typePathCr = m_typePath;
return m_fieldHandler(pathCr, typePathCr, f, rdr);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::pushNamePath(FieldName fn) {
m_path.push_back(fn);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::popNamePath() {
m_path.pop_back();
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::pushType(const DescriptorType *type) {
m_typeStack.push_back(type);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::popType() {
m_typeStack.pop_back();
}
template<typename Reader, typename FH>
static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalker<Reader, FH> *walker) {
walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) {
// add array handling
const auto [arrayLen, err] = rdr->arrayLength(field.fieldName.c_str(), true);
oxReturnError(err);
auto child = rdr->child(field.fieldName.c_str());
child.setTypeInfo(field.fieldName.c_str(), arrayLen);
DescriptorField f(field); // create mutable copy
--f.subscriptLevels;
BString<100> subscript;
for (std::size_t i = 0; i < arrayLen; i++) {
subscript = "[";
subscript += i;
subscript += "]";
walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker));
walker->popNamePath();
}
rdr->nextField();
} else {
switch (field.type->primitiveType) {
case PrimitiveType::UnsignedInteger:
case PrimitiveType::SignedInteger:
case PrimitiveType::Bool:
case PrimitiveType::String:
oxReturnError(walker->read(field, rdr));
break;
case PrimitiveType::Struct:
case PrimitiveType::Union:
if (rdr->fieldPresent(field.fieldName.c_str())) {
auto child = rdr->child(field.fieldName.c_str());
walker->pushType(field.type);
oxReturnError(model(&child, walker));
walker->popType();
rdr->nextField();
} else {
// skip and discard absent field
int discard;
oxReturnError(rdr->field(field.fieldName.c_str(), &discard));
}
break;
}
}
walker->popNamePath();
return OxError(0);
}
template<typename Reader, typename FH>
ox::Error model(Reader *rdr, DataWalker<Reader, FH> *walker) {
auto type = walker->type();
if (!type) {
return OxError(1);
}
auto typeName = type->typeName.c_str();
auto &fields = type->fieldList;
rdr->setTypeInfo(typeName, fields.size());
for (std::size_t i = 0; i < fields.size(); i++) {
oxReturnError(parseField(fields[i], rdr, walker));
}
return OxError(0);
}
template<typename Reader, typename Handler>
ox::Error walkModel(DescriptorType *type, uint8_t *data, std::size_t dataLen, Handler handler) {
DataWalker<Reader, Handler> walker(type, handler);
Reader rdr(data, dataLen);
return model(&rdr, &walker);
}
}

40
deps/ox/src/ox/oc/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,40 @@
add_library(
OxOrganicClaw
read.cpp
write.cpp
)
find_package(JsonCpp REQUIRED)
target_compile_options(OxOrganicClaw PRIVATE -Wsign-conversion)
target_link_libraries(
OxOrganicClaw PUBLIC
OxModel
JsonCpp::JsonCpp
)
set_property(
TARGET
OxOrganicClaw
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
oc.hpp
read.hpp
write.hpp
DESTINATION
include/ox/oc
)
install(TARGETS OxOrganicClaw
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)
if(OX_RUN_TESTS STREQUAL "ON")
add_subdirectory(test)
endif()

12
deps/ox/src/ox/oc/oc.hpp vendored Normal file
View File

@ -0,0 +1,12 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "read.hpp"
#include "write.hpp"

255
deps/ox/src/ox/oc/read.cpp vendored Normal file
View File

@ -0,0 +1,255 @@
/*
* Copyright 2015 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/bit.hpp>
#include "read.hpp"
namespace ox {
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) {
auto json = bit_cast<const char*>(buff);
auto jsonLen = ox_strnlen(json, buffSize);
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxError(1, "Could not parse JSON");
}
}
OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxError(1, "Could not parse JSON");
}
}
OrganicClawReader::OrganicClawReader(const Json::Value &json, int unionIdx):
m_json(json),
m_unionIdx(unionIdx) {
}
Error OrganicClawReader::field(const char *key, int8_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int8_t>(jv.asInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, int16_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int16_t>(jv.asInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, int32_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int32_t>(jv.asInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, int64_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isInt() || jv.isInt64()) {
*val = static_cast<int64_t>(jv.asInt64());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, uint8_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint8_t>(jv.asUInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, uint16_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint16_t>(jv.asUInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, uint32_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint32_t>(jv.asUInt());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, uint64_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = 0;
} else if (jv.isUInt() || jv.isUInt64()) {
*val = static_cast<uint64_t>(jv.asUInt64());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, bool *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = false;
} else if (jv.isBool()) {
*val = jv.asBool();
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::field(const char *key, SerStr val) {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {
if (jv.empty()) {
auto data = val.data();
if (data) {
data[0] = 0;
}
} else if (jv.isString()) {
jv.getString(&begin, &end);
auto strSize = end - begin;
auto data = val.data(static_cast<std::size_t>(strSize) + 1);
if (strSize >= val.cap()) {
err = OxError(1, "String size exceeds capacity of destination");
} else {
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
}
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
[[nodiscard]] ValErr<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) {
const auto &jv = value(key);
if (jv.empty()) {
return 0;
}
if (jv.isArray()) {
return jv.size();
}
return OxError(1, "Type mismatch");
}
[[nodiscard]] std::size_t OrganicClawReader::stringLength(const char *key) {
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (jv.empty()) {
return 0;
}
if (jv.isString()) {
jv.getString(&begin, &end);
return static_cast<std::size_t>(end - begin);
}
return OxError(1, "Type mismatch");
}
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) {
return OrganicClawReader(m_json[key], unionIdx);
}
bool OrganicClawReader::fieldPresent(const char *key) {
return !m_json[key].empty();
}
Json::Value &OrganicClawReader::value(const char *key) {
if (m_json.isArray()) {
return m_json[m_fieldIt];
} else {
return m_json[key];
}
}
bool OrganicClawReader::targetValid() noexcept {
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
}
}

204
deps/ox/src/ox/oc/read.hpp vendored Normal file
View File

@ -0,0 +1,204 @@
/*
* Copyright 2015 - 2020 gtalent2@gmail.com
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <json/json.h>
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/memops.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>
namespace ox {
class OrganicClawReader {
private:
Json::Value m_json;
Json::ArrayIndex m_fieldIt = 0;
int m_unionIdx = -1;
public:
OrganicClawReader() = default;
OrganicClawReader(const uint8_t *buff, std::size_t buffSize);
OrganicClawReader(const char *json, std::size_t buffSize);
OrganicClawReader(const Json::Value &json, int unionIdx = -1);
[[nodiscard]] Error field(const char *key, int8_t *val);
[[nodiscard]] Error field(const char *key, int16_t *val);
[[nodiscard]] Error field(const char *key, int32_t *val);
[[nodiscard]] Error field(const char *key, int64_t *val);
[[nodiscard]] Error field(const char *key, uint8_t *val);
[[nodiscard]] Error field(const char *key, uint16_t *val);
[[nodiscard]] Error field(const char *key, uint32_t *val);
[[nodiscard]] Error field(const char *key, uint64_t *val);
[[nodiscard]] Error field(const char *key, bool *val);
// array handler
template<typename T>
[[nodiscard]] Error field(const char *key, T *val, std::size_t len);
template<typename T>
[[nodiscard]] Error field(const char *key, Vector<T> *val);
template<typename T>
[[nodiscard]] Error field(const char*, HashMap<String, T> *val);
template<typename T>
[[nodiscard]] Error field(const char *key, T *val);
template<typename U>
[[nodiscard]] Error field(const char *key, UnionView<U> val);
template<std::size_t L>
[[nodiscard]] Error field(const char *key, ox::BString<L> *val);
[[nodiscard]] Error field(const char *key, SerStr val);
/**
* Reads an array length from the current location in the buffer.
* @param pass indicates that the parsing should iterate past the array length
*/
[[nodiscard]] ValErr<std::size_t> arrayLength(const char *key, bool pass = true);
/**
* Reads an string length from the current location in the buffer.
*/
[[nodiscard]] std::size_t stringLength(const char *name);
template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) {
}
/**
* Returns a OrganicClawReader to parse a child object.
*/
[[nodiscard]] OrganicClawReader child(const char *key, int unionIdx = -1);
// compatibility stub
constexpr void nextField() noexcept {}
bool fieldPresent(const char *key);
static constexpr auto opType() {
return OpType::Read;
}
private:
Json::Value &value(const char *key);
bool targetValid() noexcept;
};
template<typename T>
Error OrganicClawReader::field(const char *key, T *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key);
return model(&reader, val);
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
template<typename U>
Error OrganicClawReader::field(const char *key, UnionView<U> val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key, val.idx());
err = model(&reader, val.get());
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
template<std::size_t L>
Error OrganicClawReader::field(const char *name, ox::BString<L> *val) {
return field(name, SerStr(val->data(), val->cap()));
}
// array handler
template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) {
const auto &srcVal = value(key);
auto srcSize = srcVal.size();
if (srcSize > valLen) {
return OxError(1);
}
OrganicClawReader r(srcVal);
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
oxReturnError(r.field("", &val[i]));
}
return OxError(0);
}
template<typename T>
Error OrganicClawReader::field(const char *key, ox::Vector<T> *val) {
return field(key, val->data(), val->size());
}
template<typename T>
[[nodiscard]] Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) {
const auto &srcVal = value(key);
auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size();
OrganicClawReader r(srcVal);
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
auto k = keys[i].c_str();
oxReturnError(r.field(k, &val->at(k)));
}
return OxError(0);
}
template<typename T>
Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors.
try {
Json::Value doc;
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonSize, &doc, nullptr)) {
return OxError(1, "Could not parse JSON");
}
OrganicClawReader reader(json, jsonSize);
return model(&reader, val);
} catch (Error err) {
return err;
} catch (...) {
return OxError(1, "Unkown Error");
}
}
template<typename T>
ValErr<std::unique_ptr<T>> readOC(const char *json) {
auto val = std::make_unique<T>();
oxReturnError(readOC(json, ox_strlen(json), val.get()));
return {std::move(val), OxError(0)};
}
}

13
deps/ox/src/ox/oc/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,13 @@
add_executable(
OcTest
tests.cpp
)
target_link_libraries(
OcTest
OxOrganicClaw
)
add_test("Test\\ OcTest\\ Writer" OcTest OrganicClawWriter)
add_test("Test\\ OcTest\\ Reader" OcTest OrganicClawReader)
add_test("Test\\ OcTest\\ OrganicClawDef" OcTest OrganicClawDef)

288
deps/ox/src/ox/oc/test/tests.cpp vendored Normal file
View File

@ -0,0 +1,288 @@
/*
* Copyright 2015 - 2020 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#undef NDEBUG
#include <iostream>
#include <map>
#include <string>
#include <ox/model/model.hpp>
#include <ox/oc/oc.hpp>
#include <ox/std/std.hpp>
union TestUnion {
static constexpr auto TypeName = "TestUnion";
static constexpr auto Fields = 3;
bool Bool;
uint32_t Int = 5;
char String[32];
};
struct TestStructNest {
bool Bool = false;
uint32_t Int = 0;
ox::BString<32> String = "";
};
struct TestStruct {
bool Bool = false;
int32_t Int = 0;
int32_t Int1 = 0;
int32_t Int2 = 0;
int32_t Int3 = 0;
int32_t Int4 = 0;
int32_t Int5 = 0;
int32_t Int6 = 0;
int32_t Int7 = 0;
int32_t Int8 = 0;
TestUnion Union;
char *CString = nullptr;
ox::BString<32> String = "";
uint32_t List[4] = {0, 0, 0, 0};
ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct;
TestStructNest Struct;
~TestStruct() {
delete[] CString;
}
};
template<typename T>
ox::Error model(T *io, TestUnion *obj) {
io->template setTypeInfo<TestUnion>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", ox::SerStr(obj->String)));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStructNest *obj) {
io->setTypeInfo("TestStructNest", 3);
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String));
return OxError(0);
}
template<typename T>
ox::Error model(T *io, TestStruct *obj) {
io->setTypeInfo("TestStruct", 17);
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
oxReturnError(io->field("CString", ox::SerStr(&obj->CString)));
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct));
return OxError(0);
}
std::map<std::string, ox::Error(*)()> tests = {
{
{
"OrganicClawWriter",
[] {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
TestStruct ts;
return ox::writeOC(&ts).error;
}
},
{
"OrganicClawReader",
[] {
TestStruct testIn;
testIn.Bool = true;
testIn.Int = 42;
testIn.Union.Int = 52;
testIn.String = "Test String 1";
testIn.CString = new char[ox_strlen("c-string") + 1];
ox_strcpy(testIn.CString, "c-string");
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Map["asdf"] = 93;
testIn.Map["aoeu"] = 94;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [oc, writeErr] = ox::writeOC(&testIn);
oxAssert(writeErr, "writeOC failed");
std::cout << oc.data() << '\n';
auto [testOut, readErr] = ox::readOC<TestStruct>(oc.data());
oxAssert(readErr, "readOC failed");
oxAssert(testIn.Bool == testOut->Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut->Int, "Int value mismatch");
oxAssert(testIn.Int1 == testOut->Int1, "Int1 value mismatch");
oxAssert(testIn.Int2 == testOut->Int2, "Int2 value mismatch");
oxAssert(testIn.Int3 == testOut->Int3, "Int3 value mismatch");
oxAssert(testIn.Int4 == testOut->Int4, "Int4 value mismatch");
oxAssert(testIn.Int5 == testOut->Int5, "Int5 value mismatch");
oxAssert(testIn.Int6 == testOut->Int6, "Int6 value mismatch");
oxAssert(testIn.Int7 == testOut->Int7, "Int7 value mismatch");
oxAssert(testIn.Int8 == testOut->Int8, "Int8 value mismatch");
oxAssert(ox_strcmp(testIn.CString, testOut->CString) == 0, "CString value mismatch");
oxAssert(testIn.Union.Int == testOut->Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut->String, "String value mismatch");
oxAssert(testIn.List[0] == testOut->List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut->List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut->List[2], "List[2] value mismatch");
oxAssert(testIn.List[3] == testOut->List[3], "List[3] value mismatch");
oxAssert(testIn.Map["asdf"] == testOut->Map["asdf"], "Map[\"asdf\"] value mismatch");
oxAssert(testIn.Map["aoeu"] == testOut->Map["aoeu"], "Map[\"aoeu\"] value mismatch");
oxAssert(testIn.EmptyStruct.Bool == testOut->EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
oxAssert(testIn.EmptyStruct.Int == testOut->EmptyStruct.Int, "EmptyStruct.Int value mismatch");
oxAssert(testIn.EmptyStruct.String == testOut->EmptyStruct.String, "EmptyStruct.String value mismatch");
oxAssert(testIn.Struct.Int == testOut->Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.String == testOut->Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut->Struct.Bool, "Struct.Bool value mismatch");
return OxError(0);
}
},
{
"OrganicClawDef",
[] {
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
testIn.String = "Test String 1";
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
auto [oc, ocErr] = ox::writeOC(&testIn);
oxAssert(ocErr, "Data generation failed");
auto type = ox::buildTypeDef(&testIn);
oxAssert(type.error, "Descriptor write failed");
ox::walkModel<ox::OrganicClawReader>(type.value, ox::bit_cast<uint8_t*>(oc.data()), oc.size(),
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, const ox::DescriptorField &f, ox::OrganicClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str();
switch (f.type->primitiveType) {
case ox::PrimitiveType::UnsignedInteger:
std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t";
switch (f.type->length) {
case 1: {
uint8_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 2: {
uint16_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 4: {
uint32_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 8: {
uint64_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
}
std::cout << '\n';
break;
case ox::PrimitiveType::SignedInteger:
std::cout << fieldName << ":\tint" << f.type->length * 8 << "_t:\t";
switch (f.type->length) {
case 1: {
int8_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 2: {
int16_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 4: {
int32_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
case 8: {
int64_t i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << i;
break;
}
}
std::cout << '\n';
break;
case ox::PrimitiveType::Bool: {
bool i = {};
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
std::cout << fieldName << ":\t" << "bool:\t" << (i ? "true" : "false") << '\n';
break;
}
case ox::PrimitiveType::String: {
ox::Vector<char> v(rdr->stringLength(fieldName) + 1);
//std::cout << rdr->stringLength() << '\n';
oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed.");
std::cout << fieldName << ":\t" << "string: " << v.data() << '\n';
break;
}
case ox::PrimitiveType::Struct:
break;
case ox::PrimitiveType::Union:
break;
}
return OxError(0);
}
);
delete type.value;
return OxError(0);
}
},
}
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 0) {
auto testName = args[1];
if (tests.find(testName) != tests.end()) {
retval = tests[testName]();
}
}
return retval;
}

118
deps/ox/src/ox/oc/write.cpp vendored Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#include "write.hpp"
namespace ox {
OrganicClawWriter::OrganicClawWriter(int unionIdx): m_unionIdx(unionIdx) {
}
OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx):
m_json(json),
m_unionIdx(unionIdx) {
}
Error OrganicClawWriter::field(const char *key, int8_t *val) {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int16_t *val) {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int32_t *val) {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int64_t *val) {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint8_t *val) {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint16_t *val) {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint32_t *val) {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint64_t *val) {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, bool *val) {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, ox::String val) {
if (targetValid() && val.len()) {
value(key) = val.c_str();
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, SerStr val) {
if (targetValid() && val.len()) {
value(key) = val.c_str();
}
++m_fieldIt;
return OxError(0);
}
Json::Value &OrganicClawWriter::value(const char *key) {
if (m_json.isArray()) {
return m_json[m_fieldIt];
} else {
return m_json[key];
}
}
}

162
deps/ox/src/ox/oc/write.hpp vendored Normal file
View File

@ -0,0 +1,162 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <json/json.h>
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>
namespace ox {
class OrganicClawWriter {
template<typename T>
friend ValErr<Vector<char>> writeOC(T *val);
protected:
Json::Value m_json;
Json::ArrayIndex m_fieldIt = 0;
int m_unionIdx = -1;
public:
OrganicClawWriter(int unionIdx = -1);
OrganicClawWriter(Json::Value json, int unionIdx = -1);
[[nodiscard]] Error field(const char*, int8_t *val);
[[nodiscard]] Error field(const char*, int16_t *val);
[[nodiscard]] Error field(const char*, int32_t *val);
[[nodiscard]] Error field(const char*, int64_t *val);
[[nodiscard]] Error field(const char*, uint8_t *val);
[[nodiscard]] Error field(const char*, uint16_t *val);
[[nodiscard]] Error field(const char*, uint32_t *val);
[[nodiscard]] Error field(const char*, uint64_t *val);
[[nodiscard]] Error field(const char*, bool *val);
template<typename T>
[[nodiscard]] Error field(const char*, T *val, std::size_t len);
template<typename U>
[[nodiscard]] Error field(const char*, UnionView<U> val);
template<typename T>
[[nodiscard]] Error field(const char*, ox::Vector<T> *val);
template<typename T>
[[nodiscard]] Error field(const char*, HashMap<String, T> *val);
template<std::size_t L>
[[nodiscard]] Error field(const char*, ox::BString<L> *val);
[[nodiscard]] Error field(const char*, ox::String val);
[[nodiscard]] Error field(const char*, SerStr val);
template<typename T>
[[nodiscard]] Error field(const char*, T *val);
template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) {
}
static constexpr auto opType() {
return OpType::Write;
}
private:
constexpr bool targetValid() noexcept {
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
}
Json::Value &value(const char *key);
};
template<typename T>
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) {
if (targetValid()) {
OrganicClawWriter w((Json::Value(Json::arrayValue)));
for (std::size_t i = 0; i < len; ++i) {
oxReturnError(w.field("", &val[i]));
}
value(key) = w.m_json;
}
++m_fieldIt;
return OxError(0);
}
template<std::size_t L>
Error OrganicClawWriter::field(const char *key, ox::BString<L> *val) {
return field(key, SerStr(val->data(), val->cap()));
}
template<typename T>
Error OrganicClawWriter::field(const char *key, T *val) {
if (val && targetValid()) {
OrganicClawWriter w;
oxReturnError(model(&w, val));
if (!w.m_json.isNull()) {
value(key) = w.m_json;
}
}
++m_fieldIt;
return OxError(0);
}
template<typename U>
Error OrganicClawWriter::field(const char *key, UnionView<U> val) {
if (targetValid()) {
OrganicClawWriter w(val.idx());
oxReturnError(model(&w, val.get()));
if (!w.m_json.isNull()) {
value(key) = w.m_json;
}
}
++m_fieldIt;
return OxError(0);
}
template<typename T>
Error OrganicClawWriter::field(const char *key, ox::Vector<T> *val) {
return field(key, val->data(), val->size());
}
template<typename T>
[[nodiscard]] Error OrganicClawWriter::field(const char *key, ox::HashMap<String, T> *val) {
if (targetValid()) {
auto &keys = val->keys();
OrganicClawWriter w;
for (std::size_t i = 0; i < keys.size(); ++i) {
auto k = keys[i].c_str();
oxReturnError(w.field(k, &val->at(k)));
}
value(key) = w.m_json;
}
++m_fieldIt;
return OxError(0);
}
template<typename T>
ValErr<Vector<char>> writeOC(T *val) {
OrganicClawWriter writer;
oxReturnError(model(&writer, val));
Json::StreamWriterBuilder jsonBuilder;
auto str = Json::writeString(jsonBuilder, writer.m_json);
Vector<char> buff(str.size() + 1);
memcpy(buff.data(), str.c_str(), str.size() + 1);
return buff;
}
}

11
deps/ox/src/ox/ptrarith/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,11 @@
install(
FILES
nodebuffer.hpp
ptr.hpp
DESTINATION
include/ox/ptrarith
)
if(OX_RUN_TESTS)
add_subdirectory(test)
endif()

455
deps/ox/src/ox/ptrarith/nodebuffer.hpp vendored Normal file
View File

@ -0,0 +1,455 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/stddef.hpp>
#include <ox/std/trace.hpp>
#include "ptr.hpp"
namespace ox::ptrarith {
template<typename size_t, typename Item>
class OX_PACKED NodeBuffer {
public:
struct OX_PACKED Header {
ox::LittleEndian<size_t> size = sizeof(Header); // capacity
ox::LittleEndian<size_t> bytesUsed = sizeof(Header);
ox::LittleEndian<size_t> firstItem = 0;
};
using ItemPtr = Ptr<Item, size_t, sizeof(Header)>;
class Iterator {
private:
NodeBuffer *m_buffer = nullptr;
ItemPtr m_current;
size_t m_it = 0;
public:
Iterator(NodeBuffer *buffer, ItemPtr current) {
m_buffer = buffer;
m_current = current;
oxTrace("ox::ptrarith::Iterator::start") << current.offset();
}
operator const Item*() const {
return m_current;
}
ItemPtr ptr() {
return m_current;
}
Item *get() {
return m_current;
}
operator ItemPtr() {
return m_current;
}
operator Item*() {
return m_current;
}
const Item *operator->() const {
return m_current;
}
Item *operator->() {
return m_current;
}
[[nodiscard]] bool valid() const noexcept {
return m_current.valid();
}
bool hasNext() {
if (m_current.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
auto next = m_buffer->next(m_current);
return next.valid() && m_buffer->firstItem() != next;
}
return false;
}
void next() {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++;
if (hasNext()) {
m_current = m_buffer->next(m_current);
} else {
m_current = nullptr;
}
}
};
Header m_header;
public:
NodeBuffer();
NodeBuffer(const NodeBuffer &other, size_t size);
explicit NodeBuffer(size_t size);
const Iterator iterator() const;
Iterator iterator();
ItemPtr firstItem();
ItemPtr lastItem();
/**
* @return the data section of the given item
*/
template<typename T>
Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr);
[[nodiscard]] ItemPtr prev(Item *item);
[[nodiscard]] ItemPtr next(Item *item);
/**
* Like pointer but omits checks that assume the memory at the offset has
* already been initialed as an Item.
*/
[[nodiscard]] ItemPtr uninitializedPtr(size_t offset);
[[nodiscard]] ItemPtr ptr(size_t offset);
[[nodiscard]] ItemPtr ptr(void *item);
[[nodiscard]] ItemPtr malloc(size_t size);
[[nodiscard]] ox::Error free(ItemPtr item);
[[nodiscard]] bool valid(size_t maxSize);
/**
* Set size, capacity.
*/
[[nodiscard]] ox::Error setSize(size_t size);
/**
* Get size, capacity.
* @return capacity
*/
size_t size();
/**
* @return the bytes still available in this NodeBuffer
*/
size_t available();
/**
* @return the actual number a bytes need to store the given number of
* bytes
*/
static size_t spaceNeeded(size_t size);
template<typename F>
[[nodiscard]] ox::Error compact(F cb = [](uint64_t, ItemPtr) {});
void truncate();
private:
uint8_t *data();
};
template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(size_t size) {
m_header.size = size;
auto data = reinterpret_cast<uint8_t*>(this) + sizeof(*this);
ox_memset(data, 0, size - sizeof(*this));
oxTrace("ox::NodeBuffer::constructor") << m_header.firstItem;
}
template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, size_t size) {
oxTrace("ox::ptrarith::NodeBuffer::copy") << "other.m_header.firstItem:" << other.m_header.firstItem;
auto data = reinterpret_cast<uint8_t*>(this) + sizeof(*this);
ox_memset(data, 0, size - sizeof(*this));
ox_memcpy(this, &other, size);
}
template<typename size_t, typename Item>
const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() const {
return Iterator(this, firstItem());
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() {
oxTrace("ox::ptrarith::NodeBuffer::iterator::size") << m_header.size;
return Iterator(this, firstItem());
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::firstItem() {
//oxTrace("ox::ptrarith::NodeBuffer::firstItem") << m_header.firstItem;
return ptr(m_header.firstItem);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem() {
auto first = ptr(m_header.firstItem);
if (first.valid()) {
return prev(first);
}
return nullptr;
}
template<typename size_t, typename Item>
template<typename T>
Ptr<T, size_t, sizeof(Item)> NodeBuffer<size_t, Item>::dataOf(ItemPtr ip) {
auto out = ip.template subPtr<T>(sizeof(Item));
oxAssert(out.size() == ip.size() - sizeof(Item), "Sub Ptr has invalid size.");
return out;
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::prev(Item *item) {
return ptr(item->prev);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *item) {
return ptr(item->next);
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::uninitializedPtr(size_t itemOffset) {
// make sure this can be read as an Item, and then use Item::size for the size
std::size_t itemSpace = m_header.size - itemOffset;
if (itemOffset >= sizeof(Header) &&
itemOffset + itemSpace <= size() &&
itemSpace >= sizeof(Item)) {
return ItemPtr(this, m_header.size, itemOffset, itemSpace);
} else {
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset:" << itemOffset;
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset >= sizeof(Header):" << (itemOffset >= sizeof(Header));
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= sizeof(Item):" << (itemSpace >= sizeof(Item));
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= item->fullSize():" << (itemSpace >= item->fullSize());
return ItemPtr(this, m_header.size, 0, 0);
}
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
// make sure this can be read as an Item, and then use Item::size for the size
std::size_t itemSpace = m_header.size - itemOffset;
auto item = reinterpret_cast<Item*>(reinterpret_cast<uint8_t*>(this) + itemOffset);
if (itemOffset >= sizeof(Header) &&
itemOffset + itemSpace <= size() &&
itemSpace >= sizeof(Item) &&
itemSpace >= item->fullSize()) {
return ItemPtr(this, m_header.size, itemOffset, item->fullSize());
} else {
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset:" << itemOffset;
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset >= sizeof(Header):" << (itemOffset >= sizeof(Header));
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= sizeof(Item):" << (itemSpace >= sizeof(Item));
//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= item->fullSize():" << (itemSpace >= item->fullSize());
return ItemPtr(this, m_header.size, 0, 0);
}
}
template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size_t size) {
oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Size:" << size;
size_t fullSize = size + sizeof(Item);
if (m_header.size - m_header.bytesUsed >= fullSize) {
auto last = lastItem();
size_t addr = 0;
if (last.valid()) {
addr = last.offset() + last.size();
} else {
// there is no first item, so this must be the first item
if (!m_header.firstItem) {
oxTrace("ox::ptrarith::NodeBuffer::malloc") << "No first item, initializing.";
m_header.firstItem = sizeof(m_header);
addr = m_header.firstItem;
} else {
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer is in invalid state.";
return nullptr;
}
}
oxTrace("ox::ptrarith::NodeBuffer::malloc") << "buffer size:" << m_header.size
<< ";addr:" << addr
<< ";fullSize:" << fullSize;
auto out = ItemPtr(this, m_header.size, addr, fullSize);
if (!out.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Unknown";
return nullptr;
}
ox_memset(out, 0, fullSize);
new (out) Item;
out->setSize(size);
auto first = firstItem();
auto oldLast = last;
out->next = first.offset();
if (first.valid()) {
first->prev = out.offset();
} else {
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid first element pointer.";
return nullptr;
}
if (oldLast.valid()) {
out->prev = oldLast.offset();
oldLast->next = out.offset();
} else { // check to see if this is the first allocation
if (out.offset() != first.offset()) {
// if this is not the first allocation, there should be an oldLast
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid last element pointer.";
return nullptr;
}
out->prev = out.offset();
}
m_header.bytesUsed += out.size();
oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Offset:" << out.offset();
return out;
}
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Insufficient space:" << fullSize << "needed," << available() << "available";
return nullptr;
}
template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
oxTrace("ox::ptrarith::NodeBuffer::free") << "offset:" << item.offset();
auto prev = this->prev(item);
auto next = this->next(item);
if (prev.valid() && next.valid()) {
if (next != item) {
prev->next = next;
next->prev = prev;
if (item.offset() == m_header.firstItem) {
m_header.firstItem = next;
}
} else {
// only one item, null out first
oxTrace("ox::ptrarith::NodeBuffer::free") << "Nulling out firstItem.";
m_header.firstItem = 0;
}
} else {
if (!prev.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer:" << prev.offset();
return OxError(1);
}
if (!next.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer:" << next.offset();
return OxError(1);
}
}
m_header.bytesUsed -= item.size();
return OxError(0);
}
template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
oxTrace("ox::ptrarith::NodeBuffer::setSize") << m_header.size << "to" << size;
auto last = lastItem();
auto end = last.valid() ? last.end() : sizeof(m_header);
oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end;
if (end > size) {
// resizing to less than buffer size
return OxError(1);
} else {
m_header.size = size;
auto data = reinterpret_cast<uint8_t*>(this) + end;
ox_memset(data, 0, size - end);
return OxError(0);
}
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::size() {
return m_header.size;
}
template<typename size_t, typename Item>
bool NodeBuffer<size_t, Item>::valid(size_t maxSize) {
return m_header.size <= maxSize;
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::available() {
return m_header.size - m_header.bytesUsed;
}
template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::spaceNeeded(size_t size) {
return sizeof(Item) + size;
}
template<typename size_t, typename Item>
template<typename F>
ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
auto src = firstItem();
auto dest = ptr(sizeof(*this));
while (dest.offset() <= src.offset()) {
if (!src.valid()) {
return OxError(1);
}
if (!dest.valid()) {
return OxError(2);
}
// move node
ox_memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest));
// update surrounding nodes
auto prev = ptr(dest->prev);
if (prev.valid()) {
prev->next = dest;
}
auto next = ptr(dest->next);
if (next.valid()) {
next->prev = dest;
}
// update iterators
src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize());
}
return OxError(0);
}
template<typename size_t, typename Item>
void NodeBuffer<size_t, Item>::truncate() {
m_header.size = m_header.bytesUsed;
}
template<typename size_t, typename Item>
uint8_t *NodeBuffer<size_t, Item>::data() {
return reinterpret_cast<uint8_t*>(ptr(sizeof(*this)).get());
}
template<typename size_t>
struct OX_PACKED Item {
public:
ox::LittleEndian<size_t> prev = 0;
ox::LittleEndian<size_t> next = 0;
private:
ox::LittleEndian<size_t> m_size = sizeof(Item);
public:
size_t size() const {
return m_size;
}
void setSize(size_t size) {
m_size = size;
}
};
}

230
deps/ox/src/ox/ptrarith/ptr.hpp vendored Normal file
View File

@ -0,0 +1,230 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form 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 http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/std.hpp>
namespace ox::ptrarith {
template<typename T, typename size_t, size_t minOffset = 1>
class Ptr {
private:
uint8_t *m_dataStart = nullptr;
size_t m_dataSize = 0;
size_t m_itemOffset = 0;
size_t m_itemSize = 0;
// this should be removed later on, but the excessive validation is
// desirable during during heavy development
mutable uint8_t m_validated = false;
public:
inline Ptr() = default;
inline Ptr(std::nullptr_t);
inline Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize = sizeof(T), size_t itemTypeSize = sizeof(T));
[[nodiscard]] inline bool valid() const;
inline size_t size() const;
inline size_t offset() const;
inline size_t end();
inline const T *get() const;
inline T *get();
inline const T *operator->() const;
inline T *operator->();
inline operator const T*() const;
inline operator T*();
inline const T &operator*() const;
inline T &operator*();
inline operator size_t() const;
inline bool operator==(const Ptr<T, size_t, minOffset> &other) const;
inline bool operator!=(const Ptr<T, size_t, minOffset> &other) const;
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size) const;
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset) const;
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset, size_t size);
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> subPtr(size_t offset);
template<typename SubT>
inline const Ptr<SubT, size_t, minOffset> to() const;
};
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::Ptr(std::nullptr_t) {
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize, size_t itemTypeSize) {
// do some sanity checks before assuming this is valid
if (itemSize >= itemTypeSize &&
dataStart &&
itemStart >= minOffset &&
itemStart + itemSize <= dataSize) {
m_dataStart = reinterpret_cast<uint8_t*>(dataStart);
m_dataSize = dataSize;
m_itemOffset = itemStart;
m_itemSize = itemSize;
}
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::valid() const {
m_validated = m_dataStart != nullptr;
return m_validated;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::size() const {
return m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::offset() const {
return m_itemOffset;
}
template<typename T, typename size_t, size_t minOffset>
inline size_t Ptr<T, size_t, minOffset>::end() {
return m_itemOffset + m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline const T *Ptr<T, size_t, minOffset>::get() const {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::get())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::get())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T *Ptr<T, size_t, minOffset>::get() {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::get())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::get())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline const T *Ptr<T, size_t, minOffset>::operator->() const {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator->())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T *Ptr<T, size_t, minOffset>::operator->() {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator->())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator const T*() const {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator const T*())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator const T*())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator T*() {
oxAssert(m_validated, "Unvalidated pointer access. (ox::fs::Ptr::operator T*())");
oxAssert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator T*())");
return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline const T &Ptr<T, size_t, minOffset>::operator*() const {
oxAssert(m_validated, "Unvalidated pointer dereference. (ox::fs::Ptr::operator*())");
oxAssert(valid(), "Invalid pointer dereference. (ox::fs::Ptr::operator*())");
return *reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline T &Ptr<T, size_t, minOffset>::operator*() {
oxAssert(m_validated, "Unvalidated pointer dereference. (ox::fs::Ptr::operator*())");
oxAssert(valid(), "Invalid pointer dereference. (ox::fs::Ptr::operator*())");
return *reinterpret_cast<T*>(m_dataStart + m_itemOffset);
}
template<typename T, typename size_t, size_t minOffset>
inline Ptr<T, size_t, minOffset>::operator size_t() const {
if (m_dataStart && m_itemOffset) {
return m_itemOffset;
}
return 0;
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::operator==(const Ptr<T, size_t, minOffset> &other) const {
return m_dataStart == other.m_dataStart &&
m_itemOffset == other.m_itemOffset &&
m_itemSize == other.m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
inline bool Ptr<T, size_t, minOffset>::operator!=(const Ptr<T, size_t, minOffset> &other) const {
return m_dataStart != other.m_dataStart ||
m_itemOffset != other.m_itemOffset ||
m_itemSize != other.m_itemSize;
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) const {
return Ptr<SubT, size_t, sizeof(T)>(get(), this->size(), offset, size);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const {
oxTrace("ox::fs::Ptr::subPtr") << m_itemOffset << this->size() << offset << m_itemSize << (m_itemSize - offset);
return subPtr<SubT>(offset, m_itemSize - offset);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset, size_t size) {
return Ptr<SubT, size_t, sizeof(T)>(get(), this->size(), offset, size);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) {
oxTrace("ox::fs::Ptr::subPtr") << m_itemOffset << this->size() << offset << m_itemSize << (m_itemSize - offset);
return subPtr<SubT>(offset, m_itemSize - offset);
}
template<typename T, typename size_t, size_t minOffset>
template<typename SubT>
inline const Ptr<SubT, size_t, minOffset> Ptr<T, size_t, minOffset>::to() const {
return Ptr<SubT, size_t, minOffset>(m_dataStart, m_dataSize, m_itemOffset, m_itemSize);
}
}

View File

@ -0,0 +1,11 @@
add_executable(
PtrArithTests
tests.cpp
)
target_link_libraries(
PtrArithTests
OxStd
)
add_test("Test\\ PtrArith::setSize" PtrArithTests PtrArith::setSize)

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