Compare commits
488 Commits
39eb82596b
...
release-d2
Author | SHA1 | Date | |
---|---|---|---|
889fe04255 | |||
eed115b287 | |||
7233da75ea | |||
30797c710b | |||
e8041121d0 | |||
d054528e49 | |||
09d840cfd0 | |||
aeb1ef3b12 | |||
b66f61c217 | |||
b089bf460b | |||
cd60c4abaf | |||
d1845448c3 | |||
c4f6ee0026 | |||
17f28d43d1 | |||
043df533b7 | |||
bec75d2eba | |||
f624c720f9 | |||
204e5bbff4 | |||
1ecf197a9e | |||
74a8a7d751 | |||
331f721292 | |||
63486c23d4 | |||
47a6a410c4 | |||
d82c082256 | |||
227f3cd9f5 | |||
20ff0f89fe | |||
4061b8314e | |||
18bb50626d | |||
6a4b48221f | |||
d2a3cfa72e | |||
7c4e2a6564 | |||
e30ebce4c0 | |||
7163947efd | |||
0a0a6e306d | |||
97bc9332d3 | |||
9caf7099b6 | |||
fda1280d29 | |||
59aa4ad21a | |||
1a8afa1a98 | |||
cdbc2d6cc8 | |||
acd93337d4 | |||
cebd3b0a0f | |||
43e2e2155b | |||
be1f90955b | |||
0f2c18d554 | |||
0c0ccd1a69 | |||
1b629da8fc | |||
32e4702dc7 | |||
6b47133c22 | |||
0764720f9a | |||
78955376d6 | |||
a00a0bd2ff | |||
ed4f0e1f2b | |||
ea1feb726e | |||
e9a6a09629 | |||
d7f309750e | |||
84205879d4 | |||
ebf3a6961e | |||
eeb2a5a151 | |||
453f2750dd | |||
189ba4c545 | |||
057738088e | |||
272eabc732 | |||
a02566697a | |||
dfd27afd67 | |||
6bfe184261 | |||
700d7016d5 | |||
922323833c | |||
3b8d13dce3 | |||
a20d7fd923 | |||
6808adc8a1 | |||
abc076d657 | |||
1b790a34c4 | |||
9220271630 | |||
7941a514ba | |||
0c09c5306e | |||
3ff91af86b | |||
79b42e1df7 | |||
5eec9085f8 | |||
af7c89564c | |||
2c0e02277c | |||
e3c74637db | |||
41e08d67aa | |||
50f3479d10 | |||
1616ca7018 | |||
3fa247e3d4 | |||
27f1df8f33 | |||
a4f0c7cdb5 | |||
6a52319156 | |||
205f2a698c | |||
82f02896c9 | |||
aa43cb3d8d | |||
05d08a7687 | |||
c6750d50fc | |||
dade484d87 | |||
04f3d6b491 | |||
b015fe88b7 | |||
db2dc28f92 | |||
74fb051ef2 | |||
24fda7d589 | |||
a60cdf0a61 | |||
b97d7d9956 | |||
ce1eea817d | |||
9a0a2fd46a | |||
4e50889b5c | |||
9c0acf1b8f | |||
ee05118478 | |||
a41e93c582 | |||
59fa39070f | |||
c55994f67d | |||
e81d28a681 | |||
0626c2a815 | |||
dbcd37d7ea | |||
10a12f2ab2 | |||
2667be88f6 | |||
5972d8acef | |||
9c026e1a6c | |||
1dff26d895 | |||
ff2eb5b11b | |||
6a500345b4 | |||
28b1c6dcf4 | |||
ef9cb8bea4 | |||
0d106bde21 | |||
f038b89ab4 | |||
b75bbc4d20 | |||
227dd68a4f | |||
02db760b8c | |||
09c57545bc | |||
b9fddd47c2 | |||
f128664a81 | |||
e84df7801e | |||
caa59f3724 | |||
1cf09433e8 | |||
9948346ce4 | |||
aa8200beed | |||
961ab75662 | |||
124c7029bd | |||
d740609c8e | |||
5d1f680a51 | |||
08be822bdd | |||
c2e34b6456 | |||
173d3f4bc7 | |||
8a29c0952c | |||
5848bc8eb7 | |||
7ba66787f8 | |||
e367575974 | |||
2bc2003caa | |||
b31062e609 | |||
e4285bd48b | |||
a76638cc86 | |||
5433fd9b1d | |||
b46cb65b7f | |||
877349df46 | |||
5418c06296 | |||
dd9c1100c3 | |||
db82aee7c7 | |||
edf15858ca | |||
d1efbb2ffa | |||
051623f4b5 | |||
055d64b125 | |||
de9f842640 | |||
200e586768 | |||
f1609519a7 | |||
e452d9db4f | |||
43a87b606e | |||
8acc6244d5 | |||
bd2aeee276 | |||
89fab5cc20 | |||
1c06ea677f | |||
6b948ee069 | |||
72dddcaee5 | |||
7c824e910c | |||
a0c8146396 | |||
d5b232f5d5 | |||
c79fe3be43 | |||
1df4e78084 | |||
ffbdb09c31 | |||
b35a956e4f | |||
d3847caab4 | |||
ae066a914c | |||
67543af806 | |||
6b774ec285 | |||
4b9758f478 | |||
bf12b15fe6 | |||
a7328eb5ef | |||
b52124a0c5 | |||
eae9972f85 | |||
d83e392964 | |||
e2d0a784f1 | |||
f08821422a | |||
6a2954f82b | |||
9c19655ce2 | |||
087c834b25 | |||
79bdbf2eaa | |||
2bdc3def74 | |||
e7a663901a | |||
ffdc0ddb97 | |||
e941781f21 | |||
b869f490c3 | |||
caf8d93c21 | |||
afbf2caf97 | |||
20914eaade | |||
c5f76ff558 | |||
050339ba09 | |||
45ec39f77b | |||
319fbb2600 | |||
f43d97a17e | |||
a0974637a3 | |||
c90a8449be | |||
95dcd6bee7 | |||
5b167fd53b | |||
a701a241eb | |||
9907bb8f1d | |||
9cb6bd4a32 | |||
2dba592a42 | |||
978f2f9c4f | |||
2bad4ee416 | |||
46d1313797 | |||
fcf6f00797 | |||
ef6e3af735 | |||
80d0df2f46 | |||
9db10ec4a1 | |||
c460e0f9e0 | |||
3fa9d132ae | |||
907ead2948 | |||
8526b3fa51 | |||
6de0e882e9 | |||
d29118d783 | |||
8395128efa | |||
77c86b9516 | |||
6d2a20e8bd | |||
056284c857 | |||
3787f6adb2 | |||
ce34d450b9 | |||
8fa47e961d | |||
4e4cec1b64 | |||
9840b6fdee | |||
d0c90c39e0 | |||
7ba6fb3ac5 | |||
8dd6adc554 | |||
0093778f64 | |||
59016ee894 | |||
2b8dbb88b2 | |||
7bc1d90be8 | |||
cfb7d4f861 | |||
7a6e94959c | |||
eb1846278b | |||
00c2a39dba | |||
56f59b29fe | |||
9b11fa4e91 | |||
72e54da017 | |||
58d13a3ad9 | |||
5ae6df7e05 | |||
f71d4d3efd | |||
4b824ddef4 | |||
8b3b8d50d6 | |||
1f2e9917f1 | |||
13ddbd981e | |||
3a781f6704 | |||
30909f85a3 | |||
9cc27f5be9 | |||
cdc7428eb6 | |||
d31938ba4f | |||
935099f8d4 | |||
63608229e1 | |||
e6803af22f | |||
db961739ad | |||
2167a46266 | |||
d1c6ab9f77 | |||
c426decd99 | |||
496afd66ea | |||
ad7f696a71 | |||
819e93bb1c | |||
960889749d | |||
1b93b2038f | |||
d056323679 | |||
b10d9b6118 | |||
bd44fcf6ad | |||
a1de7fbd8a | |||
debeb83119 | |||
e2545a956b | |||
a60765b338 | |||
dc233286b4 | |||
5b929b8796 | |||
aea1aabcd7 | |||
3b8a9af97b | |||
d54853a8b5 | |||
d06412a6fe | |||
937e88ce7a | |||
9a5bdebbd7 | |||
a2361c3fd9 | |||
d6f0fe0cc8 | |||
e3b2c66d70 | |||
6dec1bf5ed | |||
af1f674bc0 | |||
6a1e2f7566 | |||
393259a010 | |||
b6b59e77f5 | |||
4a94672fdc | |||
d22c968561 | |||
79c85c2a33 | |||
3ac3b7b5e6 | |||
8c9ebbedae | |||
dbd98fe18b | |||
7418a7126a | |||
d5a1e11ec5 | |||
f4a93d8419 | |||
e923c73c91 | |||
4a9f035014 | |||
b5ee68c90b | |||
e906237d76 | |||
6bcf29b8f2 | |||
406388c042 | |||
371044d63d | |||
62c671e823 | |||
0ac494998f | |||
500c012713 | |||
1c4fb80702 | |||
a4fac4c1d3 | |||
115941a787 | |||
65a179e314 | |||
eed240eacc | |||
cc7c7ac9d7 | |||
9a80196fa6 | |||
8804819e17 | |||
ade6af8698 | |||
cd0958c691 | |||
40a3c28fbf | |||
def994f406 | |||
e808859e29 | |||
9e9f30fb18 | |||
facde6bdce | |||
1298051a1a | |||
f169c96e78 | |||
1547e8e550 | |||
795b1add64 | |||
db91ea6a63 | |||
7e19f45c69 | |||
57ba1caf90 | |||
a5bdad448f | |||
54fcbb1a33 | |||
195fd7a113 | |||
0d606643f5 | |||
402f54b3e3 | |||
ed5fc079ee | |||
140005799f | |||
7d9a1676e8 | |||
b61f81abf0 | |||
775efbddc8 | |||
1505d7ea37 | |||
26a2d340d6 | |||
ce514d586c | |||
5cbf789374 | |||
3f83a254d2 | |||
348193ae9e | |||
6b7c002a10 | |||
34081a0414 | |||
d23b69ce17 | |||
5717d67462 | |||
7666bcc2db | |||
8f5173e52a | |||
9ab3543b32 | |||
d16bbef282 | |||
a8db357360 | |||
566b724d36 | |||
b13eb0ef70 | |||
9855a0bcf0 | |||
611e2fa7cb | |||
95d9aee0cf | |||
3de03bf1fd | |||
742427584a | |||
91fd0d0786 | |||
53262c53c4 | |||
b212385b17 | |||
453e08497d | |||
72c130d8a9 | |||
9904399724 | |||
1a1c8ae6cc | |||
e9822bf124 | |||
644abd7f22 | |||
1e8d8c8b9e | |||
eccb8c4fb3 | |||
6b3974eb93 | |||
f6058f4e07 | |||
ecb09930db | |||
fc5e63a4d7 | |||
232a166833 | |||
95ba8eb138 | |||
a37df08c19 | |||
0fc7e7005c | |||
68a0dd9660 | |||
d635a954fa | |||
d0f19fd51d | |||
dd16577b50 | |||
c0aa119155 | |||
3c9ce4436a | |||
2a692fc46e | |||
e543131f0d | |||
c085c50b30 | |||
bb8fb0469a | |||
15bc41dd35 | |||
85e7375f6f | |||
da98aa864c | |||
3a62650d62 | |||
7008ebfb40 | |||
709dc36d0b | |||
540ed9b3f9 | |||
ecc49a63b0 | |||
c8ad05215f | |||
79b6046813 | |||
ed5271166e | |||
b946e428ad | |||
a84a829769 | |||
5b91ad25c2 | |||
98983d1229 | |||
b12097769e | |||
99a7a2cbfc | |||
e9c5134286 | |||
b7a1236bae | |||
d386bc8c91 | |||
3eec0a149d | |||
8d2c8df014 | |||
18ace3ceff | |||
8ddc8f40e5 | |||
d7a6bc4ae4 | |||
597a8c736e | |||
d9b676d1b2 | |||
158115c29f | |||
109f272650 | |||
77e475980d | |||
f6d2d96ff9 | |||
81d092e967 | |||
3fbb2a0086 | |||
59c11e5309 | |||
ce20282be0 | |||
7ee52db6a1 | |||
868adae053 | |||
4ae6fd7c17 | |||
4d09eecb0d | |||
66d7627ed8 | |||
bd9e27f977 | |||
ebb8b12c4e | |||
1f78ea1f37 | |||
4ab710b155 | |||
5eaa86a934 | |||
ba30caa9b2 | |||
72346162a5 | |||
5cdf241321 | |||
b797b937f8 | |||
206b2825c8 | |||
b6f86551e9 | |||
1a7e551025 | |||
cc0da5dd6a | |||
e0bdb06b2a | |||
6e0de04591 | |||
897ee83984 | |||
84e82b224b | |||
257389129f | |||
6bd7a84ddd | |||
f4ef762952 | |||
c1c41cfc99 | |||
987cd34df0 | |||
da6eb40966 | |||
ead3fd39c4 | |||
d2b77804ff | |||
df709ad391 | |||
020a3ec3f4 | |||
e5a7d8c0a9 | |||
ea266da691 | |||
30017fd32e | |||
22f8504e5a | |||
f514b33b06 | |||
6e94c2be8d | |||
3b24d6dee7 | |||
660c320ee9 | |||
4cf96878a9 | |||
9ceb1df49e | |||
ddcb53a535 | |||
8ba461d77c | |||
2b7e3c93e0 | |||
016f567c04 | |||
79d43b56fb | |||
261b28f59f | |||
d04d48124e | |||
280130c3cd | |||
e89751dd72 | |||
da27447a4a | |||
6166ab15db |
@ -4,10 +4,9 @@ Checks: '-*,
|
|||||||
cppcoreguidelines-interfaces-global-init,
|
cppcoreguidelines-interfaces-global-init,
|
||||||
cppcoreguidelines-narrowing-conversions,
|
cppcoreguidelines-narrowing-conversions,
|
||||||
cppcoreguidelines-pro-type-member-init,
|
cppcoreguidelines-pro-type-member-init,
|
||||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
-cppcoreguidelines-pro-type-static-cast-downcast,
|
||||||
cppcoreguidelines-slicing,
|
cppcoreguidelines-slicing,
|
||||||
google-default-arguments,
|
google-default-arguments,
|
||||||
google-explicit-constructor,
|
|
||||||
google-runtime-operator,
|
google-runtime-operator,
|
||||||
hicpp-exception-baseclass,
|
hicpp-exception-baseclass,
|
||||||
hicpp-multiway-paths-covered,
|
hicpp-multiway-paths-covered,
|
||||||
@ -53,10 +52,12 @@ readability-uniqueptr-delete-release,
|
|||||||
readability-use-anyofallof,
|
readability-use-anyofallof,
|
||||||
cert-*,
|
cert-*,
|
||||||
misc-*,
|
misc-*,
|
||||||
|
-misc-include-cleaner
|
||||||
-misc-use-anonymous-namespace,
|
-misc-use-anonymous-namespace,
|
||||||
readability-duplicate-include,
|
readability-duplicate-include,
|
||||||
-misc-non-private-member-variables-in-classes,
|
-misc-non-private-member-variables-in-classes,
|
||||||
-misc-no-recursion,
|
-misc-no-recursion,
|
||||||
|
-misc-include-cleaner,
|
||||||
bugprone-*,
|
bugprone-*,
|
||||||
clang-analyzer-*,
|
clang-analyzer-*,
|
||||||
modernize-*,
|
modernize-*,
|
||||||
|
19
.gitea/workflows/build.yaml
Normal file
19
.gitea/workflows/build.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Build
|
||||||
|
run-name: ${{ gitea.actor }} build and test
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: nostalgia
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- run: make purge configure-debug
|
||||||
|
- run: make build
|
||||||
|
- run: make test
|
||||||
|
- run: make purge configure-asan
|
||||||
|
- run: make build
|
||||||
|
- run: make test
|
||||||
|
- run: make purge configure-release
|
||||||
|
- run: make build
|
||||||
|
- run: make test
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -2,9 +2,12 @@
|
|||||||
.clangd
|
.clangd
|
||||||
.current_build
|
.current_build
|
||||||
.conanbuild
|
.conanbuild
|
||||||
|
.idea
|
||||||
.mypy_cache
|
.mypy_cache
|
||||||
.stfolder
|
.stfolder
|
||||||
|
.stignore
|
||||||
scripts/__pycache__
|
scripts/__pycache__
|
||||||
|
pyenv
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
ROM.oxfs
|
ROM.oxfs
|
||||||
Session.vim
|
Session.vim
|
||||||
@ -13,8 +16,7 @@ compile_commands.json
|
|||||||
dist
|
dist
|
||||||
graph_info.json
|
graph_info.json
|
||||||
imgui.ini
|
imgui.ini
|
||||||
nostalgia.gba
|
*.gba
|
||||||
nostalgia.sav
|
*.sav
|
||||||
nostalgia_media.oxfs
|
|
||||||
studio_state.json
|
studio_state.json
|
||||||
tags
|
tags
|
||||||
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
22
.idea/codeStyles/Project.xml
generated
22
.idea/codeStyles/Project.xml
generated
@ -1,22 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<Objective-C>
|
|
||||||
<option name="INDENT_NAMESPACE_MEMBERS" value="0" />
|
|
||||||
<option name="INDENT_CLASS_MEMBERS" value="8" />
|
|
||||||
<option name="INDENT_VISIBILITY_KEYWORDS" value="4" />
|
|
||||||
</Objective-C>
|
|
||||||
<Objective-C-extensions>
|
|
||||||
<extensions>
|
|
||||||
<pair source="cpp" header="hpp" fileNamingConvention="LOWERCASE" />
|
|
||||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
|
||||||
<pair source="cu" header="cuh" fileNamingConvention="NONE" />
|
|
||||||
</extensions>
|
|
||||||
</Objective-C-extensions>
|
|
||||||
<codeStyleSettings language="ObjectiveC">
|
|
||||||
<indentOptions>
|
|
||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
|
||||||
<option name="SMART_TABS" value="true" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="DrinkingTea" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
17
.idea/fileTemplates/internal/C++ Class Header.h
generated
17
.idea/fileTemplates/internal/C++ Class Header.h
generated
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2021 gary@drinkingtea.net
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[[#pragma]]# once
|
|
||||||
|
|
||||||
${NAMESPACES_OPEN}
|
|
||||||
|
|
||||||
class ${NAME} {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
${NAMESPACES_CLOSE}
|
|
13
.idea/fileTemplates/internal/C++ Class.cc
generated
13
.idea/fileTemplates/internal/C++ Class.cc
generated
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2021 gary@drinkingtea.net
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[[#include]]# "${HEADER_FILENAME}"
|
|
||||||
|
|
||||||
${NAMESPACES_OPEN}
|
|
||||||
|
|
||||||
${NAMESPACES_CLOSE}
|
|
24
.idea/inspectionProfiles/Project_Default.xml
generated
24
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,24 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
|
|
||||||
<option name="clangTidyChecks" value="-*,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-convert-member-functions-to-static,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-make-member-function-const,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof,cert-*,misc-*,readability-duplicate-include,-misc-non-private-member-variables-in-classes,-misc-no-recursion,bugprone-*,clang-analyzer-*,modernize-*,portability-*,-modernize-use-trailing-return-type,-bugprone-easily-swappable-parameters" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="Clazy" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="ConstantConditionsOC" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="ConstantFunctionResult" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="ConstantParameter" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="DanglingPointers" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="EndlessLoop" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="InfiniteRecursion" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="LocalValueEscapesScope" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="LoopDoesntUseConditionVariable" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="NullDereference" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="NullDereferences" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="UnreachableCallsOfFunction" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="UnreachableCode" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="UnusedParameter" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="UnusedValue" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
17
.idea/misc.xml
generated
17
.idea/misc.xml
generated
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompDBSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<CompDBProjectSettings>
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</CompDBProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="CompDBWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
</project>
|
|
8
.idea/nostalgia.iml
generated
8
.idea/nostalgia.iml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="Python" name="Python facet">
|
|
||||||
<configuration sdkName="Python 3.8" />
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
</module>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -2,4 +2,4 @@
|
|||||||
source:
|
source:
|
||||||
- src
|
- src
|
||||||
copyright_notice: |-
|
copyright_notice: |-
|
||||||
Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
1
.lldbinit
Normal file
1
.lldbinit
Normal file
@ -0,0 +1 @@
|
|||||||
|
type summary add --summary-string "${var.m_buff.m_items}" ox::String
|
@ -11,34 +11,26 @@ endif()
|
|||||||
|
|
||||||
include(deps/buildcore/base.cmake)
|
include(deps/buildcore/base.cmake)
|
||||||
|
|
||||||
set(NOSTALGIA_BUILD_PLAYER ON CACHE BOOL "Build Player")
|
|
||||||
set(NOSTALGIA_BUILD_STUDIO ON CACHE BOOL "Build Studio")
|
|
||||||
set(OX_ENABLE_TRACEHOOK OFF CACHE BOOL "Generate OxTraceHook shared library for uprobes")
|
set(OX_ENABLE_TRACEHOOK OFF CACHE BOOL "Generate OxTraceHook shared library for uprobes")
|
||||||
|
|
||||||
if(BUILDCORE_TARGET STREQUAL "gba")
|
if(BUILDCORE_TARGET STREQUAL "gba")
|
||||||
set(NOSTALGIA_BUILD_STUDIO OFF)
|
|
||||||
set(TURBINE_BUILD_TYPE "GBA")
|
|
||||||
include(deps/gbabuildcore/base.cmake)
|
include(deps/gbabuildcore/base.cmake)
|
||||||
else()
|
else()
|
||||||
set(TURBINE_BUILD_TYPE "Native")
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_MACOSX_RPATH OFF)
|
set(CMAKE_MACOSX_RPATH OFF)
|
||||||
set(CMAKE_INSTALL_NAME_DIR "@executable_path/../Library/nostalgia")
|
|
||||||
set(NOSTALGIA_DIST_BIN nostalgia-studio.app/Contents/MacOS)
|
|
||||||
set(NOSTALGIA_DIST_LIB nostalgia-studio.app/Contents/Library)
|
|
||||||
set(NOSTALGIA_DIST_MODULE nostalgia-studio.app/Contents/Plugins)
|
|
||||||
set(NOSTALGIA_DIST_RESOURCES nostalgia-studio.app/Contents/Resources)
|
|
||||||
set(NOSTALGIA_DIST_MAC_APP_CONTENTS nostalgia-studio.app/Contents)
|
|
||||||
else()
|
else()
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../lib/ox" "$ORIGIN/../lib/nostalgia" "$ORIGIN/../")
|
if(UNIX)
|
||||||
|
set(BUILD_SHARED_LIBS ON)
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
||||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||||
set(NOSTALGIA_DIST_BIN bin)
|
|
||||||
set(NOSTALGIA_DIST_LIB lib)
|
|
||||||
set(NOSTALGIA_DIST_MODULE lib/nostalgia/modules)
|
|
||||||
set(NOSTALGIA_DIST_RESOURCES share)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(deps/ox)
|
add_subdirectory(deps/ox)
|
||||||
@ -50,14 +42,18 @@ add_subdirectory(deps/teagba)
|
|||||||
if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
||||||
include_directories(
|
include_directories(
|
||||||
SYSTEM
|
SYSTEM
|
||||||
deps/glfw/deps
|
|
||||||
deps/glfw/include
|
deps/glfw/include
|
||||||
deps/imgui
|
deps/imgui
|
||||||
deps/imgui/backends
|
deps/imgui/backends
|
||||||
deps/nfde/src/include
|
deps/nfde/src/include
|
||||||
|
/usr/local/include
|
||||||
)
|
)
|
||||||
add_subdirectory(deps/glad)
|
add_subdirectory(deps/glad)
|
||||||
|
set(GLFW_BUILD_EXAMPLES OFF)
|
||||||
|
set(GLFW_BUILD_TESTS OFF)
|
||||||
|
set(GLFW_BUILD_DOCS OFF)
|
||||||
add_subdirectory(deps/glfw)
|
add_subdirectory(deps/glfw)
|
||||||
|
add_subdirectory(deps/glutils)
|
||||||
add_subdirectory(deps/imgui)
|
add_subdirectory(deps/imgui)
|
||||||
add_subdirectory(deps/lodepng)
|
add_subdirectory(deps/lodepng)
|
||||||
add_subdirectory(deps/nfde)
|
add_subdirectory(deps/nfde)
|
||||||
|
@ -31,7 +31,6 @@ RUN dnf install -y clang \
|
|||||||
python3-pip \
|
python3-pip \
|
||||||
libglvnd-devel \
|
libglvnd-devel \
|
||||||
gtk3-devel
|
gtk3-devel
|
||||||
RUN pip install conan
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Install devkitARM
|
# Install devkitARM
|
||||||
|
25
Makefile
25
Makefile
@ -1,39 +1,40 @@
|
|||||||
PROJECT_NAME=nostalgia
|
BC_VAR_PROJECT_NAME=nostalgia
|
||||||
|
BC_VAR_PROJECT_NAME_CAP=Nostalgia
|
||||||
BUILDCORE_PATH=deps/buildcore
|
BUILDCORE_PATH=deps/buildcore
|
||||||
include ${BUILDCORE_PATH}/base.mk
|
include ${BUILDCORE_PATH}/base.mk
|
||||||
|
|
||||||
ifeq ($(OS),darwin)
|
ifeq ($(BC_VAR_OS),darwin)
|
||||||
NOSTALGIA_STUDIO=./build/${HOST}/${CURRENT_BUILD}/src/nostalgia/studio/nostalgia-studio.app/Contents/MacOS/nostalgia-studio
|
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio
|
||||||
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
|
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
|
||||||
else
|
else
|
||||||
NOSTALGIA_STUDIO=./build/${HOST}/${CURRENT_BUILD}/src/nostalgia/studio/nostalgia-studio
|
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio
|
||||||
MGBA=mgba-qt
|
MGBA=mgba-qt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: pkg-gba
|
.PHONY: pkg-gba
|
||||||
pkg-gba: install
|
pkg-gba: build
|
||||||
${ENV_RUN} ./scripts/pkg-gba sample_project
|
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build
|
run: build
|
||||||
./build/${HOST}/${CURRENT_BUILD}/src/nostalgia/player/nostalgia sample_project
|
./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||||
.PHONY: run-studio
|
.PHONY: run-studio
|
||||||
run-studio: build
|
run-studio: build
|
||||||
${NOSTALGIA_STUDIO}
|
${NOSTALGIA_STUDIO}
|
||||||
.PHONY: gba-run
|
.PHONY: gba-run
|
||||||
gba-run: pkg-gba
|
gba-run: pkg-gba
|
||||||
${MGBA} nostalgia.gba
|
${MGBA} ${BC_VAR_PROJECT_NAME}.gba
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug: build
|
debug: build
|
||||||
${DEBUGGER} ./build/${HOST}/${CURRENT_BUILD}/src/nostalgia/player/nostalgia sample_project
|
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||||
.PHONY: debug-studio
|
.PHONY: debug-studio
|
||||||
debug-studio: build
|
debug-studio: build
|
||||||
${DEBUGGER} ${NOSTALGIA_STUDIO}
|
${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO}
|
||||||
|
|
||||||
.PHONY: configure-gba
|
.PHONY: configure-gba
|
||||||
configure-gba:
|
configure-gba:
|
||||||
${ENV_RUN} ${SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=release --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=release --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
|
||||||
.PHONY: configure-gba-debug
|
.PHONY: configure-gba-debug
|
||||||
configure-gba-debug:
|
configure-gba-debug:
|
||||||
${ENV_RUN} ${SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
@ -8,6 +8,15 @@
|
|||||||
* Install Ninja, Make, and CMake
|
* Install Ninja, Make, and CMake
|
||||||
* Consider also installing ccache for faster subsequent build times
|
* Consider also installing ccache for faster subsequent build times
|
||||||
|
|
||||||
|
### Debian
|
||||||
|
|
||||||
|
For Debian (and probably other Linux distros, but the package names will
|
||||||
|
probably differ), install the following additional packages:
|
||||||
|
* pkg-config
|
||||||
|
* xorg-dev
|
||||||
|
* libgtk-3-dev
|
||||||
|
* python3-mypy
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
Build options: release, debug, asan, gba, gba-debug
|
Build options: release, debug, asan, gba, gba-debug
|
||||||
|
188
deps/buildcore/base.mk
vendored
188
deps/buildcore/base.mk
vendored
@ -9,89 +9,99 @@
|
|||||||
ifeq (${OS},Windows_NT)
|
ifeq (${OS},Windows_NT)
|
||||||
SHELL := powershell.exe
|
SHELL := powershell.exe
|
||||||
.SHELLFLAGS := -NoProfile -Command
|
.SHELLFLAGS := -NoProfile -Command
|
||||||
OS=windows
|
BC_VAR_OS=windows
|
||||||
HOST_ENV=${OS}
|
|
||||||
else
|
else
|
||||||
OS=$(shell uname | tr [:upper:] [:lower:])
|
BC_VAR_OS=$(shell uname | tr [:upper:] [:lower:])
|
||||||
HOST_ENV=${OS}-$(shell uname -m)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEVENV=devenv$(shell pwd | sed 's/\//-/g')
|
ifneq ($(shell which python3 2> /dev/null),)
|
||||||
DEVENV_IMAGE=${PROJECT_NAME}-devenv
|
BC_CMD_HOST_PY3=python3
|
||||||
ifneq ($(shell which docker 2> /dev/null),)
|
else
|
||||||
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
|
ifeq ($(shell python -c 'import sys; print(sys.version_info[0])'),3)
|
||||||
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
|
BC_CMD_HOST_PY3=python
|
||||||
|
else
|
||||||
|
echo 'Please install Python3 on host'
|
||||||
|
exit 1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(shell ${ENV_RUN} which python3 2> /dev/null),)
|
ifdef BC_VAR_USE_DOCKER_DEVENV
|
||||||
PYTHON3=python3
|
ifneq ($(shell which docker 2> /dev/null),)
|
||||||
else
|
BC_VAR_DEVENV=devenv$(shell pwd | sed 's/\//-/g')
|
||||||
ifeq ($(shell ${ENV_RUN} python -c 'import sys; print(sys.version_info[0])'),3)
|
BC_VAR_DEVENV_IMAGE=${BC_VAR_PROJECT_NAME}-devenv
|
||||||
PYTHON3=python
|
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${BC_VAR_DEVENV} 2>&1),running)
|
||||||
|
BC_CMD_ENVRUN=docker exec -i -t --user $(shell id -u ${USER}) ${BC_VAR_DEVENV}
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
ifneq ($(shell ${BC_CMD_ENVRUN} which python3 2> /dev/null),)
|
||||||
|
BC_CMD_PY3=${BC_CMD_ENVRUN} python3
|
||||||
|
else
|
||||||
|
ifeq ($(shell ${BC_CMD_ENVRUN} python -c 'import sys; print(sys.version_info[0])'),3)
|
||||||
|
BC_CMD_PY3=${BC_CMD_ENVRUN} python
|
||||||
|
else
|
||||||
|
echo 'Please install Python3 in devenv'
|
||||||
|
exit 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
BC_CMD_PY3=${BC_CMD_HOST_PY3}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SCRIPTS=${BUILDCORE_PATH}/scripts
|
BC_VAR_SCRIPTS=${BUILDCORE_PATH}/scripts
|
||||||
SETUP_BUILD=${PYTHON3} ${SCRIPTS}/setup-build.py
|
BC_CMD_SETUP_BUILD=${BC_CMD_PY3} ${BC_VAR_SCRIPTS}/setup-build.py
|
||||||
PYBB=${PYTHON3} ${SCRIPTS}/pybb.py
|
BC_CMD_PYBB=${BC_CMD_PY3} ${BC_VAR_SCRIPTS}/pybb.py
|
||||||
CMAKE_BUILD=${PYBB} cmake-build
|
BC_CMD_HOST_PYBB=${BC_CMD_HOST_PY3} ${BC_VAR_SCRIPTS}/pybb.py
|
||||||
GET_ENV=${PYBB} getenv
|
BC_CMD_CMAKE_BUILD=${BC_CMD_PYBB} cmake-build
|
||||||
CTEST=${PYBB} ctest-all
|
BC_CMD_GETENV=${BC_CMD_PYBB} getenv
|
||||||
RM_RF=${PYBB} rm
|
BC_CMD_CTEST=${BC_CMD_PYBB} ctest-all
|
||||||
HOST=$(shell ${PYBB} hostname)
|
BC_CMD_RM_RF=${BC_CMD_PYBB} rm
|
||||||
BUILDCORE_HOST_SPECIFIC_BUILDPATH=$(shell ${GET_ENV} BUILDCORE_HOST_SPECIFIC_BUILDPATH)
|
BC_CMD_MKDIR_P=${BC_CMD_PYBB} mkdir
|
||||||
ifneq (${BUILDCORE_HOST_SPECIFIC_BUILDPATH},)
|
BC_CMD_CAT=${BC_CMD_PYBB} cat
|
||||||
BUILD_PATH=build/${HOST}
|
BC_CMD_DEBUGGER=${BC_CMD_PYBB} debug
|
||||||
else
|
BC_CMD_HOST_DEBUGGER=${BC_CMD_HOST_PYBB} debug
|
||||||
BUILD_PATH=build
|
BC_VAR_HOSTENV=$(shell ${BC_CMD_ENVRUN} ${BC_CMD_PYBB} hostenv)
|
||||||
endif
|
BC_VAR_BUILD_PATH=build
|
||||||
ifdef USE_VCPKG
|
BC_VAR_CURRENT_BUILD=$(BC_VAR_HOSTENV)-$(shell ${BC_CMD_ENVRUN} ${BC_CMD_CAT} .current_build)
|
||||||
ifndef VCPKG_DIR_BASE
|
|
||||||
VCPKG_DIR_BASE=.vcpkg
|
|
||||||
endif
|
|
||||||
ifndef VCPKG_VERSION
|
|
||||||
VCPKG_VERSION=2020.06
|
|
||||||
endif
|
|
||||||
VCPKG_TOOLCHAIN=--toolchain=${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
|
|
||||||
endif
|
|
||||||
ifeq ($(OS),darwin)
|
|
||||||
DEBUGGER=lldb --
|
|
||||||
else
|
|
||||||
DEBUGGER=gdb --args
|
|
||||||
endif
|
|
||||||
|
|
||||||
VCPKG_DIR=$(VCPKG_DIR_BASE)/$(VCPKG_VERSION)-$(HOST_ENV)
|
ifdef BC_VAR_USE_VCPKG
|
||||||
CURRENT_BUILD=$(HOST_ENV)-$(shell ${ENV_RUN} ${PYBB} cat .current_build)
|
ifndef BC_VAR_VCPKG_DIR_BASE
|
||||||
|
BC_VAR_VCPKG_DIR_BASE=.vcpkg
|
||||||
|
endif
|
||||||
|
ifndef BC_VAR_VCPKG_VERSION
|
||||||
|
BC_VAR_VCPKG_VERSION=2023.08.09
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build:
|
build:
|
||||||
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH}
|
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH}
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install:
|
install:
|
||||||
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} install
|
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} install
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} clean
|
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} clean
|
||||||
.PHONY: purge
|
.PHONY: purge
|
||||||
purge:
|
purge:
|
||||||
${ENV_RUN} ${RM_RF} .current_build
|
${BC_CMD_RM_RF} .current_build
|
||||||
${ENV_RUN} ${RM_RF} ${BUILD_PATH}
|
${BC_CMD_RM_RF} ${BC_VAR_BUILD_PATH}
|
||||||
${ENV_RUN} ${RM_RF} dist
|
${BC_CMD_RM_RF} dist
|
||||||
|
${BC_CMD_RM_RF} compile_commands.json
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build
|
test: build
|
||||||
${ENV_RUN} mypy ${SCRIPTS}
|
${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
|
||||||
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} test
|
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
|
||||||
.PHONY: test-verbose
|
.PHONY: test-verbose
|
||||||
test-verbose: build
|
test-verbose: build
|
||||||
${ENV_RUN} ${CTEST} ${BUILD_PATH} --output-on-failure
|
${BC_CMD_CTEST} ${BC_VAR_BUILD_PATH} --output-on-failure
|
||||||
.PHONY: test-rerun-verbose
|
.PHONY: test-rerun-verbose
|
||||||
test-rerun-verbose: build
|
test-rerun-verbose: build
|
||||||
${ENV_RUN} ${CTEST} ${BUILD_PATH} --rerun-failed --output-on-failure
|
${BC_CMD_CTEST} ${BC_VAR_BUILD_PATH} --rerun-failed --output-on-failure
|
||||||
|
|
||||||
|
ifdef BC_VAR_USE_DOCKER_DEVENV
|
||||||
.PHONY: devenv-image
|
.PHONY: devenv-image
|
||||||
devenv-image:
|
devenv-image:
|
||||||
docker build . -t ${DEVENV_IMAGE}
|
docker build . -t ${BC_VAR_DEVENV_IMAGE}
|
||||||
.PHONY: devenv-create
|
.PHONY: devenv-create
|
||||||
devenv-create:
|
devenv-create:
|
||||||
docker run -d \
|
docker run -d \
|
||||||
@ -103,73 +113,77 @@ devenv-create:
|
|||||||
-v $(shell pwd):/usr/src/project \
|
-v $(shell pwd):/usr/src/project \
|
||||||
-v /dev/shm:/dev/shm \
|
-v /dev/shm:/dev/shm \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
--name ${DEVENV} \
|
--name ${BC_VAR_DEVENV} \
|
||||||
-t ${DEVENV_IMAGE} bash
|
-t ${BC_VAR_DEVENV_IMAGE} bash
|
||||||
.PHONY: devenv-destroy
|
.PHONY: devenv-destroy
|
||||||
devenv-destroy:
|
devenv-destroy:
|
||||||
docker rm -f ${DEVENV}
|
docker rm -f ${BC_VAR_DEVENV}
|
||||||
ifdef ENV_RUN
|
ifdef BC_CMD_ENVRUN
|
||||||
.PHONY: devenv-shell
|
.PHONY: devenv-shell
|
||||||
devenv-shell:
|
devenv-shell:
|
||||||
${ENV_RUN} bash
|
${BC_CMD_ENVRUN} bash
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef USE_VCPKG
|
ifdef BC_VAR_USE_VCPKG
|
||||||
|
|
||||||
|
BC_VAR_VCPKG_TOOLCHAIN=--toolchain=${BC_VAR_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
|
||||||
|
BC_VAR_VCPKG_DIR=$(BC_VAR_VCPKG_DIR_BASE)/$(BC_VAR_VCPKG_VERSION)-$(BC_VAR_HOSTENV)
|
||||||
|
|
||||||
.PHONY: vcpkg
|
.PHONY: vcpkg
|
||||||
vcpkg: ${VCPKG_DIR} vcpkg-install
|
vcpkg: ${BC_VAR_VCPKG_DIR} vcpkg-install
|
||||||
|
|
||||||
${VCPKG_DIR}:
|
${BC_VAR_VCPKG_DIR}:
|
||||||
${ENV_RUN} ${RM_RF} ${VCPKG_DIR}
|
${BC_CMD_RM_RF} ${BC_VAR_VCPKG_DIR}
|
||||||
${ENV_RUN} mkdir -p ${VCPKG_DIR_BASE}
|
${BC_CMD_PYBB} mkdir ${BC_VAR_VCPKG_DIR_BASE}
|
||||||
${ENV_RUN} git clone -b release --depth 1 --branch ${VCPKG_VERSION} https://github.com/microsoft/vcpkg.git ${VCPKG_DIR}
|
${BC_CMD_ENVRUN} git clone -b release --depth 1 --branch ${BC_VAR_VCPKG_VERSION} https://github.com/microsoft/vcpkg.git ${BC_VAR_VCPKG_DIR}
|
||||||
ifneq (${OS},windows)
|
ifneq (${BC_VAR_OS},windows)
|
||||||
${ENV_RUN} ${VCPKG_DIR}/bootstrap-vcpkg.sh
|
${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/bootstrap-vcpkg.sh
|
||||||
else
|
else
|
||||||
${ENV_RUN} ${VCPKG_DIR}/bootstrap-vcpkg.bat
|
${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/bootstrap-vcpkg.bat
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: vcpkg-install
|
.PHONY: vcpkg-install
|
||||||
vcpkg-install:
|
vcpkg-install:
|
||||||
ifneq (${OS},windows)
|
ifneq (${BC_VAR_OS},windows)
|
||||||
${VCPKG_DIR}/vcpkg install ${VCPKG_PKGS}
|
${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/vcpkg install ${BC_VAR_VCPKG_PKGS}
|
||||||
else
|
else
|
||||||
${VCPKG_DIR}/vcpkg install --triplet x64-windows ${VCPKG_PKGS}
|
${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/vcpkg install --triplet x64-windows ${BC_VAR_VCPKG_PKGS}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
else ifdef USE_CONAN # USE_VCPKG ################################################
|
else ifdef USE_CONAN # USE_VCPKG / USE_CONAN ####################################
|
||||||
|
|
||||||
.PHONY: setup-conan
|
.PHONY: setup-conan
|
||||||
conan-config:
|
conan-config:
|
||||||
${ENV_RUN} conan profile new ${PROJECT_NAME} --detect --force
|
${BC_CMD_ENVRUN} conan profile new ${BC_VAR_PROJECT_NAME} --detect --force
|
||||||
ifeq ($(OS),linux)
|
ifeq ($(BC_VAR_OS),linux)
|
||||||
${ENV_RUN} conan profile update settings.compiler.libcxx=libstdc++11 ${PROJECT_NAME}
|
${BC_CMD_ENVRUN} conan profile update settings.compiler.libcxx=libstdc++11 ${BC_VAR_PROJECT_NAME}
|
||||||
else
|
else
|
||||||
${ENV_RUN} conan profile update settings.compiler.cppstd=20 ${PROJECT_NAME}
|
${BC_CMD_ENVRUN} conan profile update settings.compiler.cppstd=20 ${BC_VAR_PROJECT_NAME}
|
||||||
ifeq ($(OS),windows)
|
ifeq ($(BC_VAR_OS),windows)
|
||||||
${ENV_RUN} conan profile update settings.compiler.runtime=static ${PROJECT_NAME}
|
${BC_CMD_ENVRUN} conan profile update settings.compiler.runtime=static ${BC_VAR_PROJECT_NAME}
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: conan
|
.PHONY: conan
|
||||||
conan:
|
conan:
|
||||||
${ENV_RUN} ${PYBB} conan-install ${PROJECT_NAME}
|
${BC_CMD_PYBB} conan-install ${BC_VAR_PROJECT_NAME}
|
||||||
endif # USE_VCPKG ###############################################
|
endif # USE_CONAN ###############################################
|
||||||
|
|
||||||
ifeq (${OS},darwin)
|
ifeq (${BC_VAR_OS},darwin)
|
||||||
.PHONY: configure-xcode
|
.PHONY: configure-xcode
|
||||||
configure-xcode:
|
configure-xcode:
|
||||||
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_tool=xcode --current_build=0 --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_tool=xcode --current_build=0 --build_root=${BC_VAR_BUILD_PATH}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: configure-release
|
.PHONY: configure-release
|
||||||
configure-release:
|
configure-release:
|
||||||
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=release --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=release --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
|
||||||
.PHONY: configure-debug
|
.PHONY: configure-debug
|
||||||
configure-debug:
|
configure-debug:
|
||||||
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=debug --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
|
||||||
.PHONY: configure-asan
|
.PHONY: configure-asan
|
||||||
configure-asan:
|
configure-asan:
|
||||||
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=asan --build_root=${BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=asan --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
|
||||||
|
75
deps/buildcore/scripts/pybb.py
vendored
75
deps/buildcore/scripts/pybb.py
vendored
@ -18,18 +18,20 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
|
import util
|
||||||
def mkdir(path: str):
|
|
||||||
if not os.path.exists(path):
|
|
||||||
os.mkdir(path)
|
|
||||||
|
|
||||||
|
|
||||||
# this exists because Windows is utterly incapable of providing a proper rm -rf
|
def mkdir(path: str) -> int:
|
||||||
def rm(path: str):
|
try:
|
||||||
if (os.path.exists(path) or os.path.islink(path)) and not os.path.isdir(path):
|
util.mkdir_p(path)
|
||||||
os.remove(path)
|
except Exception:
|
||||||
elif os.path.isdir(path):
|
return 1
|
||||||
shutil.rmtree(path)
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def rm_multi(paths: List[str]):
|
||||||
|
for path in paths:
|
||||||
|
util.rm(path)
|
||||||
|
|
||||||
|
|
||||||
def ctest_all() -> int:
|
def ctest_all() -> int:
|
||||||
@ -70,16 +72,13 @@ def conan() -> int:
|
|||||||
err = 0
|
err = 0
|
||||||
try:
|
try:
|
||||||
mkdir(conan_dir)
|
mkdir(conan_dir)
|
||||||
except:
|
except Exception:
|
||||||
return 1
|
return 1
|
||||||
if err != 0:
|
if err != 0:
|
||||||
return err
|
return err
|
||||||
args = ['conan', 'install', '../', '--build=missing', '-pr', project_name]
|
args = ['conan', 'install', '../', '--build=missing', '-pr', project_name]
|
||||||
os.chdir(conan_dir)
|
os.chdir(conan_dir)
|
||||||
err = subprocess.run(args).returncode
|
return subprocess.run(args).returncode
|
||||||
if err != 0:
|
|
||||||
return err
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def cat(paths: List[str]) -> int:
|
def cat(paths: List[str]) -> int:
|
||||||
@ -87,48 +86,70 @@ def cat(paths: List[str]) -> int:
|
|||||||
try:
|
try:
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
sys.stdout.write(data)
|
print(data)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
sys.stderr.write('cat: {}: no such file or directory\n'.format(path))
|
sys.stderr.write(f'cat: {path}: no such file or directory\n')
|
||||||
return 1
|
return 1
|
||||||
sys.stdout.write('\n')
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def debug(paths: List[str]) -> int:
|
||||||
|
if shutil.which('gdb') is not None:
|
||||||
|
args = ['gdb', '--args']
|
||||||
|
elif shutil.which('lldb') is not None:
|
||||||
|
args = ['lldb', '--']
|
||||||
|
else:
|
||||||
|
sys.stderr.write('debug: could not find a supported debugger\n')
|
||||||
|
return 1
|
||||||
|
args.extend(paths)
|
||||||
|
return subprocess.run(args).returncode
|
||||||
|
|
||||||
|
|
||||||
def get_env(var_name: str) -> int:
|
def get_env(var_name: str) -> int:
|
||||||
if var_name not in os.environ:
|
if var_name not in os.environ:
|
||||||
return 1
|
return 1
|
||||||
sys.stdout.write(os.environ[var_name])
|
print(os.environ[var_name])
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def hostname() -> int:
|
def hostname() -> int:
|
||||||
sys.stdout.write(platform.node())
|
print(platform.node())
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def host_env() -> int:
|
||||||
|
os_name = platform.system().lower()
|
||||||
|
arch = util.get_arch()
|
||||||
|
print(f'{os_name}-{arch}')
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def clarg(idx: int) -> Optional[str]:
|
||||||
|
return sys.argv[idx] if len(sys.argv) > idx else None
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
err = 0
|
err = 0
|
||||||
if sys.argv[1] == 'mkdir':
|
if sys.argv[1] == 'mkdir':
|
||||||
try:
|
err = mkdir(sys.argv[2])
|
||||||
mkdir(sys.argv[2])
|
|
||||||
except:
|
|
||||||
err = 1
|
|
||||||
elif sys.argv[1] == 'rm':
|
elif sys.argv[1] == 'rm':
|
||||||
for i in range(2, len(sys.argv)):
|
rm_multi(sys.argv[2:])
|
||||||
rm(sys.argv[i])
|
|
||||||
elif sys.argv[1] == 'conan-install':
|
elif sys.argv[1] == 'conan-install':
|
||||||
err = conan()
|
err = conan()
|
||||||
elif sys.argv[1] == 'ctest-all':
|
elif sys.argv[1] == 'ctest-all':
|
||||||
err = ctest_all()
|
err = ctest_all()
|
||||||
elif sys.argv[1] == 'cmake-build':
|
elif sys.argv[1] == 'cmake-build':
|
||||||
err = cmake_build(sys.argv[2], sys.argv[3] if len(sys.argv) > 3 else None)
|
err = cmake_build(sys.argv[2], clarg(3))
|
||||||
elif sys.argv[1] == 'cat':
|
elif sys.argv[1] == 'cat':
|
||||||
err = cat(sys.argv[2:])
|
err = cat(sys.argv[2:])
|
||||||
|
elif sys.argv[1] == 'debug':
|
||||||
|
err = debug(sys.argv[2:])
|
||||||
elif sys.argv[1] == 'getenv':
|
elif sys.argv[1] == 'getenv':
|
||||||
err = get_env(sys.argv[2])
|
err = get_env(sys.argv[2])
|
||||||
elif sys.argv[1] == 'hostname':
|
elif sys.argv[1] == 'hostname':
|
||||||
err = hostname()
|
err = hostname()
|
||||||
|
elif sys.argv[1] == 'hostenv':
|
||||||
|
err = host_env()
|
||||||
else:
|
else:
|
||||||
sys.stderr.write('Command not found\n')
|
sys.stderr.write('Command not found\n')
|
||||||
err = 1
|
err = 1
|
||||||
|
52
deps/buildcore/scripts/setup-build.py
vendored
52
deps/buildcore/scripts/setup-build.py
vendored
@ -15,18 +15,35 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pybb import mkdir, rm
|
import util
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--target', help='Platform target',
|
parser.add_argument(
|
||||||
default='{:s}-{:s}'.format(sys.platform, platform.machine()))
|
'--target',
|
||||||
parser.add_argument('--build_type', help='Build type (asan,debug,release)', default='release')
|
help='Platform target',
|
||||||
parser.add_argument('--build_tool', help='Build tool (default,xcode)', default='')
|
default=f'{util.get_os()}-{util.get_arch()}')
|
||||||
parser.add_argument('--build_root', help='Path to the root of build directories (must be in project dir)', default='build')
|
parser.add_argument(
|
||||||
parser.add_argument('--toolchain', help='Path to CMake toolchain file', default='')
|
'--build_type',
|
||||||
parser.add_argument('--current_build', help='Indicates whether or not to make this the active build', default=1)
|
help='Build type (asan,debug,release)',
|
||||||
|
default='release')
|
||||||
|
parser.add_argument(
|
||||||
|
'--build_tool',
|
||||||
|
help='Build tool (default,xcode)',
|
||||||
|
default='')
|
||||||
|
parser.add_argument(
|
||||||
|
'--build_root',
|
||||||
|
help='Path to the root build directory (must be in project dir)',
|
||||||
|
default='build')
|
||||||
|
parser.add_argument(
|
||||||
|
'--toolchain',
|
||||||
|
help='Path to CMake toolchain file',
|
||||||
|
default='')
|
||||||
|
parser.add_argument(
|
||||||
|
'--current_build',
|
||||||
|
help='Indicates whether or not to make this the active build',
|
||||||
|
default=1)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.build_type == 'asan':
|
if args.build_type == 'asan':
|
||||||
@ -64,10 +81,10 @@ def main() -> int:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
project_dir = os.getcwd()
|
project_dir = os.getcwd()
|
||||||
build_dir = '{:s}/{:s}/{:s}'.format(project_dir, args.build_root, build_config)
|
build_dir = f'{project_dir}/{args.build_root}/{build_config}'
|
||||||
rm(build_dir)
|
util.rm(build_dir)
|
||||||
cmake_cmd = [
|
cmake_cmd = [
|
||||||
'cmake', '-S', project_dir, '-B', build_dir, build_tool,
|
'cmake', '-S', project_dir, '-B', build_dir,
|
||||||
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
|
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
|
||||||
'-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain),
|
'-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain),
|
||||||
'-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg),
|
'-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg),
|
||||||
@ -75,22 +92,27 @@ def main() -> int:
|
|||||||
'-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config),
|
'-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config),
|
||||||
'-DBUILDCORE_TARGET={:s}'.format(args.target),
|
'-DBUILDCORE_TARGET={:s}'.format(args.target),
|
||||||
]
|
]
|
||||||
|
if build_tool != '':
|
||||||
|
cmake_cmd.append(build_tool)
|
||||||
if qt_path != '':
|
if qt_path != '':
|
||||||
cmake_cmd.append(qt_path)
|
cmake_cmd.append(qt_path)
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
cmake_cmd.append('-A x64')
|
cmake_cmd.append('-A x64')
|
||||||
|
|
||||||
subprocess.run(cmake_cmd)
|
cmake_err = subprocess.run(cmake_cmd).returncode
|
||||||
|
if cmake_err != 0:
|
||||||
|
return cmake_err
|
||||||
|
|
||||||
mkdir('dist')
|
util.mkdir_p('dist')
|
||||||
if int(args.current_build) != 0:
|
if int(args.current_build) != 0:
|
||||||
cb = open('.current_build', 'w')
|
cb = open('.current_build', 'w')
|
||||||
cb.write(args.build_type)
|
cb.write(args.build_type)
|
||||||
cb.close()
|
cb.close()
|
||||||
|
|
||||||
rm('compile_commands.json')
|
util.rm('compile_commands.json')
|
||||||
if platform.system() != 'Windows':
|
if platform.system() != 'Windows':
|
||||||
os.symlink('{:s}/compile_commands.json'.format(build_dir), 'compile_commands.json')
|
os.symlink(f'{build_dir}/compile_commands.json',
|
||||||
|
'compile_commands.json')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
38
deps/buildcore/scripts/util.py
vendored
Normal file
38
deps/buildcore/scripts/util.py
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2016 - 2021 gary@drinkingtea.net
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
def mkdir_p(path: str):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
os.mkdir(path)
|
||||||
|
|
||||||
|
|
||||||
|
# this exists because Windows is utterly incapable of providing a proper rm -rf
|
||||||
|
def rm(path: str):
|
||||||
|
file_exists = os.path.exists(path)
|
||||||
|
is_link = os.path.islink(path)
|
||||||
|
is_dir = os.path.isdir(path)
|
||||||
|
if (file_exists or is_link) and not is_dir:
|
||||||
|
os.remove(path)
|
||||||
|
elif os.path.isdir(path):
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
|
||||||
|
def get_os() -> str:
|
||||||
|
return platform.system().lower()
|
||||||
|
|
||||||
|
|
||||||
|
def get_arch() -> str:
|
||||||
|
arch = platform.machine()
|
||||||
|
if arch.lower() == 'amd64':
|
||||||
|
arch = 'x86_64'
|
||||||
|
return arch
|
4
deps/gbabuildcore/cmake/modules/GBA.cmake
vendored
4
deps/gbabuildcore/cmake/modules/GBA.cmake
vendored
@ -24,8 +24,8 @@ add_definitions(-DARM7)
|
|||||||
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_RUNTIME_OUTPUT_DIRECTORY}/${EXE_NAME}.bin)
|
||||||
set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})
|
set(FI ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${EXE_NAME})
|
||||||
message(STATUS ${FO})
|
message(STATUS ${FO})
|
||||||
|
|
||||||
# run objcopy
|
# run objcopy
|
||||||
|
2
deps/glfw/src/CMakeLists.txt
vendored
2
deps/glfw/src/CMakeLists.txt
vendored
@ -88,7 +88,7 @@ if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE)
|
|||||||
LANGUAGE C)
|
LANGUAGE C)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(glfw OBJECT ${glfw_SOURCES} ${glfw_HEADERS})
|
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||||
set_target_properties(glfw PROPERTIES
|
set_target_properties(glfw PROPERTIES
|
||||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||||
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
||||||
|
6
deps/glutils/.liccor.yml
vendored
Normal file
6
deps/glutils/.liccor.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
source:
|
||||||
|
- include
|
||||||
|
- src
|
||||||
|
copyright_notice: |-
|
||||||
|
Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
10
deps/glutils/CMakeLists.txt
vendored
Normal file
10
deps/glutils/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
project(GlUtils CXX)
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
install(
|
||||||
|
DIRECTORY
|
||||||
|
include/glutils
|
||||||
|
DESTINATION
|
||||||
|
include
|
||||||
|
)
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -9,15 +9,17 @@
|
|||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include <ox/std/bounds.hpp>
|
#include <ox/std/bounds.hpp>
|
||||||
|
#include <ox/std/cstringview.hpp>
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
|
#include <ox/std/size.hpp>
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
#include <ox/std/vector.hpp>
|
#include <ox/std/vector.hpp>
|
||||||
|
|
||||||
namespace glutils {
|
namespace glutils {
|
||||||
|
|
||||||
constexpr ox::StringView GlslVersion = "#version 330";
|
struct Empty {
|
||||||
|
virtual ~Empty() noexcept = default;
|
||||||
struct Empty {};
|
};
|
||||||
|
|
||||||
struct TextureBase {
|
struct TextureBase {
|
||||||
|
|
||||||
@ -41,6 +43,8 @@ struct TextureBase {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~TextureBase() noexcept = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +64,7 @@ struct GLObject: public Base {
|
|||||||
o.id = 0;
|
o.id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~GLObject() noexcept {
|
~GLObject() noexcept override {
|
||||||
del(id);
|
del(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +111,7 @@ extern template struct GLObject<deleteProgram>;
|
|||||||
extern template struct GLObject<deleteShader>;
|
extern template struct GLObject<deleteShader>;
|
||||||
|
|
||||||
using GLBuffer = GLObject<deleteBuffer>;
|
using GLBuffer = GLObject<deleteBuffer>;
|
||||||
using GLFrameBuffer = GLObject<deleteBuffer>;
|
using GLFrameBuffer = GLObject<deleteFrameBuffer>;
|
||||||
using GLRenderBuffer = GLObject<deleteRenderBuffer>;
|
using GLRenderBuffer = GLObject<deleteRenderBuffer>;
|
||||||
using GLShader = GLObject<deleteShader>;
|
using GLShader = GLObject<deleteShader>;
|
||||||
using GLProgram = GLObject<deleteProgram>;
|
using GLProgram = GLObject<deleteProgram>;
|
||||||
@ -146,10 +150,39 @@ class FrameBufferBind {
|
|||||||
|
|
||||||
void bind(const FrameBuffer &fb) noexcept;
|
void bind(const FrameBuffer &fb) noexcept;
|
||||||
|
|
||||||
|
struct ShaderVarSet {
|
||||||
|
GLsizei len{};
|
||||||
|
ox::String name;
|
||||||
|
};
|
||||||
|
|
||||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo = nullptr) noexcept;
|
struct ProgramSource {
|
||||||
|
ox::Vector<glutils::ShaderVarSet> const shaderParams;
|
||||||
|
GLsizei const rowLen = [this] {
|
||||||
|
GLsizei len{};
|
||||||
|
for (auto const&v : shaderParams) {
|
||||||
|
len += v.len;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}();
|
||||||
|
GLsizei const vboLen = rowLen * 4;
|
||||||
|
ox::String const vertShader{};
|
||||||
|
ox::String const fragShader{};
|
||||||
|
ox::String const geomShader{};
|
||||||
|
};
|
||||||
|
|
||||||
ox::Result<GLProgram> buildShaderProgram(const ox::String &vert, const ox::String &frag, const ox::String &geo = "") noexcept;
|
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept;
|
||||||
|
|
||||||
|
ox::Result<GLProgram> buildShaderProgram(
|
||||||
|
ox::CStringView const&vert,
|
||||||
|
ox::CStringView const&frag,
|
||||||
|
ox::CStringView const&geo = "") noexcept;
|
||||||
|
|
||||||
|
void setupShaderParams(
|
||||||
|
GLProgram const&shader,
|
||||||
|
ox::Vector<ShaderVarSet> const&vars,
|
||||||
|
GLsizei vertexRowLen) noexcept;
|
||||||
|
|
||||||
|
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept;
|
||||||
|
|
||||||
glutils::GLVertexArray generateVertexArrayObject() noexcept;
|
glutils::GLVertexArray generateVertexArrayObject() noexcept;
|
||||||
|
|
||||||
@ -158,10 +191,14 @@ glutils::GLBuffer generateBuffer() noexcept;
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
FrameBuffer generateFrameBuffer(int width, int height) noexcept;
|
FrameBuffer generateFrameBuffer(int width, int height) noexcept;
|
||||||
|
|
||||||
|
void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes a FrameBuffer, and creates if it does not already exist.
|
* Resizes a FrameBuffer, and creates if it does not already exist.
|
||||||
*/
|
*/
|
||||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept;
|
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||||
|
|
||||||
|
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept;
|
||||||
|
|
||||||
struct BufferSet {
|
struct BufferSet {
|
||||||
glutils::GLVertexArray vao;
|
glutils::GLVertexArray vao;
|
||||||
@ -172,9 +209,9 @@ struct BufferSet {
|
|||||||
ox::Vector<GLuint> elements;
|
ox::Vector<GLuint> elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sendVbo(const BufferSet &bs) noexcept;
|
void sendVbo(BufferSet const&bs) noexcept;
|
||||||
|
|
||||||
void sendEbo(const BufferSet &bs) noexcept;
|
void sendEbo(BufferSet const&bs) noexcept;
|
||||||
|
|
||||||
void clearScreen() noexcept;
|
void clearScreen() noexcept;
|
||||||
|
|
@ -3,19 +3,17 @@ add_library(
|
|||||||
glutils.cpp
|
glutils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
GlUtils PUBLIC
|
||||||
|
../include
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
GlUtils PUBLIC
|
GlUtils PUBLIC
|
||||||
OxStd
|
OxStd
|
||||||
glad
|
glad
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
glutils.hpp
|
|
||||||
DESTINATION
|
|
||||||
include/glutils
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
GlUtils
|
GlUtils
|
@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/std/assert.hpp>
|
#include <ox/std/assert.hpp>
|
||||||
#include <ox/std/bstring.hpp>
|
#include <ox/std/istring.hpp>
|
||||||
#include <ox/std/trace.hpp>
|
#include <ox/std/trace.hpp>
|
||||||
|
|
||||||
#include "glutils.hpp"
|
#include "glutils/glutils.hpp"
|
||||||
|
|
||||||
namespace glutils {
|
namespace glutils {
|
||||||
|
|
||||||
@ -88,25 +88,55 @@ static ox::Result<GLShader> buildShader(
|
|||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo) noexcept {
|
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
|
||||||
GLProgram prgm(glCreateProgram());
|
oxRequireM(program, buildShaderProgram(
|
||||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad"));
|
src.vertShader,
|
||||||
glAttachShader(prgm, vs);
|
src.fragShader,
|
||||||
if (geo && ox_strlen(geo) != 0) {
|
src.geomShader));
|
||||||
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo, "gshad"));
|
setupShaderParams(program, src.shaderParams, src.rowLen);
|
||||||
glAttachShader(prgm, gs);
|
return std::move(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupShaderParams(
|
||||||
|
GLProgram const&shader,
|
||||||
|
ox::Vector<ShaderVarSet> const&vars,
|
||||||
|
GLsizei vertexRowLen) noexcept {
|
||||||
|
// setup vars
|
||||||
|
for (auto lenWritten = 0LU; auto const&v : vars) {
|
||||||
|
auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str()));
|
||||||
|
glEnableVertexAttribArray(attr);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
attr, v.len, GL_FLOAT, GL_FALSE,
|
||||||
|
vertexRowLen * static_cast<GLsizei>(sizeof(float)),
|
||||||
|
std::bit_cast<void*>(uintptr_t{lenWritten * sizeof(float)}));
|
||||||
|
lenWritten += static_cast<size_t>(v.len);
|
||||||
}
|
}
|
||||||
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag, "fshad"));
|
}
|
||||||
glAttachShader(prgm, fs);
|
|
||||||
glLinkProgram(prgm);
|
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept {
|
||||||
return prgm;
|
// get row len
|
||||||
|
GLsizei vertexRowLen{};
|
||||||
|
for (auto const&v : vars) {
|
||||||
|
vertexRowLen += v.len;
|
||||||
|
}
|
||||||
|
setupShaderParams(shader, vars, vertexRowLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<GLProgram> buildShaderProgram(
|
ox::Result<GLProgram> buildShaderProgram(
|
||||||
const ox::String &vert,
|
ox::CStringView const&vert,
|
||||||
const ox::String &frag,
|
ox::CStringView const&frag,
|
||||||
const ox::String &geo) noexcept {
|
ox::CStringView const&geo) noexcept {
|
||||||
return buildShaderProgram(vert.c_str(), frag.c_str(), geo.c_str());
|
GLProgram prgm(glCreateProgram());
|
||||||
|
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
|
||||||
|
glAttachShader(prgm, vs);
|
||||||
|
if (geo.c_str() && geo.bytes() != 0) {
|
||||||
|
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
|
||||||
|
glAttachShader(prgm, gs);
|
||||||
|
}
|
||||||
|
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
|
||||||
|
glAttachShader(prgm, fs);
|
||||||
|
glLinkProgram(prgm);
|
||||||
|
return prgm;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLVertexArray generateVertexArrayObject() noexcept {
|
GLVertexArray generateVertexArrayObject() noexcept {
|
||||||
@ -133,8 +163,9 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
|||||||
glGenTextures(1, &fb.color.id);
|
glGenTextures(1, &fb.color.id);
|
||||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
||||||
// depth texture
|
// depth texture
|
||||||
glGenRenderbuffers(1, &fb.depth.id);
|
glGenRenderbuffers(1, &fb.depth.id);
|
||||||
@ -150,21 +181,19 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
|||||||
return fb;
|
return fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||||
if (!*fb) {
|
|
||||||
*fb = generateFrameBuffer(width, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
width = ox::max(1, width);
|
width = ox::max(1, width);
|
||||||
height = ox::max(1, height);
|
height = ox::max(1, height);
|
||||||
fb->width = width;
|
fb.width = width;
|
||||||
fb->height = height;
|
fb.height = height;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, *fb);
|
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||||
// color texture
|
// color texture
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->color);
|
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
// depth texture
|
// depth texture
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth);
|
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||||
// restore primary FB
|
// restore primary FB
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
@ -172,13 +201,25 @@ void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
|||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendVbo(const BufferSet &bs) noexcept {
|
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||||
|
if (!fb) {
|
||||||
|
fb = generateFrameBuffer(width, height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resizeFrameBuffer(fb, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
|
||||||
|
resizeInitFrameBuffer(fb, sz.width, sz.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendVbo(BufferSet const&bs) noexcept {
|
||||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendEbo(const BufferSet &bs) noexcept {
|
void sendEbo(BufferSet const&bs) noexcept {
|
||||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
|
5
deps/imgui/CMakeLists.txt
vendored
5
deps/imgui/CMakeLists.txt
vendored
@ -15,3 +15,8 @@ add_library(
|
|||||||
backends/imgui_impl_glfw.cpp
|
backends/imgui_impl_glfw.cpp
|
||||||
backends/imgui_impl_opengl3.cpp
|
backends/imgui_impl_opengl3.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
imgui SYSTEM PUBLIC
|
||||||
|
.
|
||||||
|
)
|
8
deps/lodepng/CMakeLists.txt
vendored
8
deps/lodepng/CMakeLists.txt
vendored
@ -12,3 +12,11 @@ target_include_directories(
|
|||||||
lodepng PUBLIC SYSTEM
|
lodepng PUBLIC SYSTEM
|
||||||
include
|
include
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
lodepng
|
||||||
|
DESTINATION
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
)
|
||||||
|
4
deps/nfde/CMakeLists.txt
vendored
4
deps/nfde/CMakeLists.txt
vendored
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(nativefiledialog-extended)
|
project(nativefiledialog-extended)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
@ -11,7 +11,7 @@ if(WIN32)
|
|||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(nfd_PLATFORM PLATFORM_MACOS)
|
set(nfd_PLATFORM PLATFORM_MACOS)
|
||||||
elseif(UNIX AND NOT APPLE)
|
elseif(UNIX AND NOT APPLE)
|
||||||
set(nfd_PLATFORM PLATFORM_LINUX)
|
set(nfd_PLATFORM PLATFORM_UNIX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message("nfd Platform: ${nfd_PLATFORM}")
|
message("nfd Platform: ${nfd_PLATFORM}")
|
||||||
|
13
deps/nfde/src/CMakeLists.txt
vendored
13
deps/nfde/src/CMakeLists.txt
vendored
@ -10,13 +10,12 @@ if(nfd_PLATFORM STREQUAL PLATFORM_WIN32)
|
|||||||
list(APPEND SOURCE_FILES nfd_win.cpp)
|
list(APPEND SOURCE_FILES nfd_win.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(nfd_PLATFORM STREQUAL PLATFORM_LINUX)
|
if(nfd_PLATFORM STREQUAL PLATFORM_UNIX)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
# for Linux, we support GTK3 and xdg-desktop-portal
|
# for Linux, we support GTK3 and xdg-desktop-portal
|
||||||
option(NFD_PORTAL "Use xdg-desktop-portal instead of GTK" OFF)
|
option(NFD_PORTAL "Use xdg-desktop-portal instead of GTK" OFF)
|
||||||
if(NOT NFD_PORTAL)
|
if(NOT NFD_PORTAL)
|
||||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
pkg_check_modules(GTK3 REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
message("Using GTK version: ${GTK3_VERSION}")
|
|
||||||
list(APPEND SOURCE_FILES nfd_gtk.cpp)
|
list(APPEND SOURCE_FILES nfd_gtk.cpp)
|
||||||
else()
|
else()
|
||||||
pkg_check_modules(DBUS REQUIRED dbus-1)
|
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||||
@ -31,19 +30,17 @@ if(nfd_PLATFORM STREQUAL PLATFORM_MACOS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Define the library
|
# Define the library
|
||||||
add_library(${TARGET_NAME} OBJECT
|
add_library(${TARGET_NAME}
|
||||||
${SOURCE_FILES})
|
${SOURCE_FILES})
|
||||||
|
|
||||||
# Allow includes from include/
|
# Allow includes from include/
|
||||||
target_include_directories(${TARGET_NAME}
|
target_include_directories(${TARGET_NAME}
|
||||||
PUBLIC include/)
|
PUBLIC include/)
|
||||||
|
|
||||||
if(nfd_PLATFORM STREQUAL PLATFORM_LINUX)
|
if(nfd_PLATFORM STREQUAL PLATFORM_UNIX)
|
||||||
if(NOT NFD_PORTAL)
|
if(NOT NFD_PORTAL)
|
||||||
target_include_directories(${TARGET_NAME}
|
|
||||||
PRIVATE ${GTK3_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(${TARGET_NAME}
|
target_link_libraries(${TARGET_NAME}
|
||||||
PRIVATE ${GTK3_LIBRARIES})
|
PRIVATE PkgConfig::GTK3)
|
||||||
else()
|
else()
|
||||||
target_include_directories(${TARGET_NAME}
|
target_include_directories(${TARGET_NAME}
|
||||||
PRIVATE ${DBUS_INCLUDE_DIRS})
|
PRIVATE ${DBUS_INCLUDE_DIRS})
|
||||||
|
2
deps/ox/.liccor.yml
vendored
2
deps/ox/.liccor.yml
vendored
@ -2,7 +2,7 @@
|
|||||||
source:
|
source:
|
||||||
- src
|
- src
|
||||||
copyright_notice: |-
|
copyright_notice: |-
|
||||||
Copyright 2015 - 2022 gary@drinkingtea.net
|
Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
3
deps/ox/CMakeLists.txt
vendored
3
deps/ox/CMakeLists.txt
vendored
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.19)
|
cmake_minimum_required(VERSION 3.19)
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||||
|
|
||||||
project(Ox)
|
project(Ox CXX)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
|
||||||
include(address_sanitizer)
|
include(address_sanitizer)
|
||||||
@ -82,4 +82,5 @@ if(OX_USE_STDLIB)
|
|||||||
set(JSONCPP_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/jsoncpp/include")
|
set(JSONCPP_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/jsoncpp/include")
|
||||||
add_subdirectory(deps/jsoncpp)
|
add_subdirectory(deps/jsoncpp)
|
||||||
endif()
|
endif()
|
||||||
|
add_subdirectory(deps/cityhash)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
30
deps/ox/deps/cityhash/CMakeLists.txt
vendored
Normal file
30
deps/ox/deps/cityhash/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||||
|
|
||||||
|
project(CityHash CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
set(NOSTALGIA_BUILD_PLAYER OFF)
|
||||||
|
set(NOSTALGIA_BUILD_STUDIO_APP OFF)
|
||||||
|
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_MACOSX_RPATH OFF)
|
||||||
|
else()
|
||||||
|
if(UNIX)
|
||||||
|
set(BUILD_SHARED_LIBS ON)
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
||||||
|
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(CityHash INTERFACE)
|
||||||
|
target_include_directories(CityHash INTERFACE include)
|
674
deps/ox/deps/cityhash/include/cityhash/city.h
vendored
Normal file
674
deps/ox/deps/cityhash/include/cityhash/city.h
vendored
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
// Copyright (c) 2011 Google, Inc.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
||||||
|
//
|
||||||
|
// http://code.google.com/p/cityhash/
|
||||||
|
//
|
||||||
|
// This file provides a few functions for hashing strings. All of them are
|
||||||
|
// high-quality functions in the sense that they pass standard tests such
|
||||||
|
// as Austin Appleby's SMHasher. They are also fast.
|
||||||
|
//
|
||||||
|
// For 64-bit x86 code, on short strings, we don't know of anything faster than
|
||||||
|
// CityHash64 that is of comparable quality. We believe our nearest competitor
|
||||||
|
// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
|
||||||
|
// tables and most other hashing (excluding cryptography).
|
||||||
|
//
|
||||||
|
// For 64-bit x86 code, on long strings, the picture is more complicated.
|
||||||
|
// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
|
||||||
|
// CityHashCrc128 appears to be faster than all competitors of comparable
|
||||||
|
// quality. CityHash128 is also good but not quite as fast. We believe our
|
||||||
|
// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
|
||||||
|
// other 64-bit CPUs, but for long strings we know that Spooky is slightly
|
||||||
|
// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
|
||||||
|
// Note that CityHashCrc128 is declared in citycrc.h.
|
||||||
|
//
|
||||||
|
// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
|
||||||
|
// is of comparable quality. We believe our nearest competitor is Murmur3A.
|
||||||
|
// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
|
||||||
|
//
|
||||||
|
// Functions in the CityHash family are not suitable for cryptography.
|
||||||
|
//
|
||||||
|
// Please see CityHash's README file for more details on our performance
|
||||||
|
// measurements and so on.
|
||||||
|
//
|
||||||
|
// WARNING: This code has been only lightly tested on big-endian platforms!
|
||||||
|
// It is known to work well on little-endian platforms that have a small penalty
|
||||||
|
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
|
||||||
|
// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
|
||||||
|
// bug reports are welcome.
|
||||||
|
//
|
||||||
|
// By the way, for some hash functions, given strings a and b, the hash
|
||||||
|
// of a+b is easily derived from the hashes of a and b. This property
|
||||||
|
// doesn't hold for any hash functions in this file.
|
||||||
|
|
||||||
|
#ifndef CITY_HASH_H_
|
||||||
|
#define CITY_HASH_H_
|
||||||
|
|
||||||
|
#if __has_include(<cstdint>)
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned uint_t;
|
||||||
|
#if defined(__arm__) || defined(__ppc__)
|
||||||
|
typedef long long int64_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
typedef __INTMAX_TYPE__ intmax_t;
|
||||||
|
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||||
|
#else
|
||||||
|
typedef long int64_t;
|
||||||
|
typedef unsigned long uint64_t;
|
||||||
|
typedef int64_t intmax_t;
|
||||||
|
typedef uint64_t uintmax_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_LP64) || defined(__ppc64__) || defined(__aarch64__)
|
||||||
|
typedef long intptr_t;
|
||||||
|
typedef unsigned long uintptr_t;
|
||||||
|
#elif defined(_WIN64)
|
||||||
|
typedef int64_t intptr_t;
|
||||||
|
typedef uint64_t uintptr_t;
|
||||||
|
#elif defined(_LP32) || defined(__ppc__) || defined(_WIN32) || defined(__arm__)
|
||||||
|
typedef int32_t intptr_t;
|
||||||
|
typedef uint32_t uintptr_t;
|
||||||
|
#else
|
||||||
|
#error intptr_t, and uintptr_t undefined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using size_t = decltype(alignof(int));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cityhash::detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_reference {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_reference<T&> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_reference<T&&> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using remove_reference_t = typename remove_reference<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr remove_reference_t<T> &&move(T &&t) noexcept {
|
||||||
|
return static_cast<remove_reference_t<T>&&>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using remove_reference_t = typename remove_reference<T>::type;
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
struct pair {
|
||||||
|
T1 first{};
|
||||||
|
T2 second{};
|
||||||
|
constexpr pair() noexcept = default;
|
||||||
|
constexpr pair(T1 a, T2 b) noexcept: first(detail::move(a)), second(detail::move(b)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr void swap(T &a, T &b) noexcept {
|
||||||
|
auto temp = detail::move(a);
|
||||||
|
a = detail::move(b);
|
||||||
|
b = detail::move(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace cityhash {
|
||||||
|
|
||||||
|
using uint128 = cityhash::detail::pair<uint64_t, uint64_t>;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr T byteSwap(T i) noexcept {
|
||||||
|
if constexpr(sizeof(T) == 1) {
|
||||||
|
return i;
|
||||||
|
} else if constexpr(sizeof(T) == 2) {
|
||||||
|
return static_cast<T>(i << 8) | static_cast<T>(i >> 8);
|
||||||
|
} else if constexpr(sizeof(T) == 4) {
|
||||||
|
return ((i >> 24) & 0x000000ff) |
|
||||||
|
((i >> 8) & 0x0000ff00) |
|
||||||
|
((i << 8) & 0x00ff0000) |
|
||||||
|
((i << 24) & 0xff000000);
|
||||||
|
} else if constexpr(sizeof(T) == 8) {
|
||||||
|
return ((i >> 56) & 0x00000000000000ff) |
|
||||||
|
((i >> 40) & 0x000000000000ff00) |
|
||||||
|
((i >> 24) & 0x0000000000ff0000) |
|
||||||
|
((i >> 8) & 0x00000000ff000000) |
|
||||||
|
((i << 8) & 0x000000ff00000000) |
|
||||||
|
((i << 24) & 0x0000ff0000000000) |
|
||||||
|
((i << 40) & 0x00ff000000000000) |
|
||||||
|
((i << 56) & 0xff00000000000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t Uint128Low64(const uint128& x) noexcept { return x.first; }
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t Uint128High64(const uint128& x) noexcept { return x.second; }
|
||||||
|
|
||||||
|
// Hash 128 input bits down to 64 bits of output.
|
||||||
|
// This is intended to be a reasonably good hash function.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t Hash128to64(const uint128& x) noexcept {
|
||||||
|
// Murmur-inspired hashing.
|
||||||
|
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
|
||||||
|
uint64_t a = (detail::Uint128Low64(x) ^ detail::Uint128High64(x)) * kMul;
|
||||||
|
a ^= (a >> 47);
|
||||||
|
uint64_t b = (detail::Uint128High64(x) ^ a) * kMul;
|
||||||
|
b ^= (b >> 47);
|
||||||
|
b *= kMul;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t UNALIGNED_LOAD64(const char *p) noexcept {
|
||||||
|
uint64_t result{};
|
||||||
|
result |= static_cast<uint64_t>(p[0]);
|
||||||
|
result |= static_cast<uint64_t>(p[1]) << 8;
|
||||||
|
result |= static_cast<uint64_t>(p[2]) << 16;
|
||||||
|
result |= static_cast<uint64_t>(p[3]) << 24;
|
||||||
|
result |= static_cast<uint64_t>(p[4]) << 32;
|
||||||
|
result |= static_cast<uint64_t>(p[5]) << 40;
|
||||||
|
result |= static_cast<uint64_t>(p[6]) << 48;
|
||||||
|
result |= static_cast<uint64_t>(p[7]) << 56;
|
||||||
|
//memcpy(&result, p, sizeof(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t UNALIGNED_LOAD32(const char *p) noexcept {
|
||||||
|
uint32_t result{};
|
||||||
|
result |= static_cast<uint32_t>(p[0]);
|
||||||
|
result |= static_cast<uint32_t>(p[1]) << 8;
|
||||||
|
result |= static_cast<uint32_t>(p[2]) << 16;
|
||||||
|
result |= static_cast<uint32_t>(p[3]) << 24;
|
||||||
|
//memcpy(&result, p, sizeof(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
#define uint32_in_expected_order(x) (detail::byteSwap<uint32_t>(x))
|
||||||
|
#define uint64_in_expected_order(x) (detail::byteSwap<uint64_t>(x))
|
||||||
|
#else
|
||||||
|
#define uint32_in_expected_order(x) (x)
|
||||||
|
#define uint64_in_expected_order(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIKELY)
|
||||||
|
#if HAVE_BUILTIN_EXPECT
|
||||||
|
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||||
|
#else
|
||||||
|
#define LIKELY(x) (x)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t Fetch64(const char *p) noexcept {
|
||||||
|
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Fetch32(const char *p) noexcept {
|
||||||
|
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some primes between 2^63 and 2^64 for various uses.
|
||||||
|
constexpr uint64_t k0 = 0xc3a5c85c97cb3127ULL;
|
||||||
|
constexpr uint64_t k1 = 0xb492b66fbe98f273ULL;
|
||||||
|
constexpr uint64_t k2 = 0x9ae16a3b2f90404fULL;
|
||||||
|
|
||||||
|
// Magic numbers for 32-bit hashing. Copied from Murmur3.
|
||||||
|
constexpr uint32_t c1 = 0xcc9e2d51;
|
||||||
|
constexpr uint32_t c2 = 0x1b873593;
|
||||||
|
|
||||||
|
// A 32-bit to 32-bit integer hash copied from Murmur3.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t fmix(uint32_t h) noexcept {
|
||||||
|
h ^= h >> 16;
|
||||||
|
h *= 0x85ebca6b;
|
||||||
|
h ^= h >> 13;
|
||||||
|
h *= 0xc2b2ae35;
|
||||||
|
h ^= h >> 16;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Rotate32(uint32_t val, int shift) noexcept {
|
||||||
|
// Avoid shifting by 32: doing so yields an undefined result.
|
||||||
|
return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PERMUTE3
|
||||||
|
#define PERMUTE3(a, b, c) do { detail::swap(a, b); detail::swap(a, c); } while (0)
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Mur(uint32_t a, uint32_t h) noexcept {
|
||||||
|
// Helper from Murmur3 for combining two 32-bit values.
|
||||||
|
a *= detail::c1;
|
||||||
|
a = Rotate32(a, 17);
|
||||||
|
a *= detail::c2;
|
||||||
|
h ^= a;
|
||||||
|
h = Rotate32(h, 19);
|
||||||
|
return h * 5 + 0xe6546b64;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Hash32Len13to24(const char *s, size_t len) noexcept {
|
||||||
|
uint32_t a = Fetch32(s - 4 + (len >> 1));
|
||||||
|
uint32_t b = Fetch32(s + 4);
|
||||||
|
uint32_t c = Fetch32(s + len - 8);
|
||||||
|
uint32_t d = Fetch32(s + (len >> 1));
|
||||||
|
uint32_t e = Fetch32(s);
|
||||||
|
uint32_t f = Fetch32(s + len - 4);
|
||||||
|
uint32_t h = static_cast<uint32_t>(len);
|
||||||
|
|
||||||
|
return detail::fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Hash32Len0to4(const char *s, size_t len) noexcept {
|
||||||
|
uint32_t b = 0;
|
||||||
|
uint32_t c = 9;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
auto const v = static_cast<signed char>(s[i]);
|
||||||
|
b = b * detail::c1 + static_cast<uint32_t>(v);
|
||||||
|
c ^= b;
|
||||||
|
}
|
||||||
|
return detail::fmix(Mur(b, Mur(static_cast<uint32_t>(len), c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t Hash32Len5to12(const char *s, size_t len) noexcept {
|
||||||
|
uint32_t a = static_cast<uint32_t>(len), b = a * 5, c = 9, d = b;
|
||||||
|
a += Fetch32(s);
|
||||||
|
b += Fetch32(s + len - 4);
|
||||||
|
c += Fetch32(s + ((len >> 1) & 4));
|
||||||
|
return detail::fmix(Mur(c, Mur(b, Mur(a, d))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise right rotate. Normally this will compile to a single
|
||||||
|
// instruction, especially if the shift is a manifest constant.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t Rotate(uint64_t val, int shift) noexcept {
|
||||||
|
// Avoid shifting by 64: doing so yields an undefined result.
|
||||||
|
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t ShiftMix(uint64_t val) noexcept {
|
||||||
|
return val ^ (val >> 47);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t HashLen16(uint64_t u, uint64_t v) noexcept {
|
||||||
|
return Hash128to64(uint128(u, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) noexcept {
|
||||||
|
// Murmur-inspired hashing.
|
||||||
|
uint64_t a = (u ^ v) * mul;
|
||||||
|
a ^= (a >> 47);
|
||||||
|
uint64_t b = (v ^ a) * mul;
|
||||||
|
b ^= (b >> 47);
|
||||||
|
b *= mul;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t HashLen0to16(const char *s, size_t len) noexcept {
|
||||||
|
if (len >= 8) {
|
||||||
|
uint64_t mul = detail::k2 + len * 2;
|
||||||
|
uint64_t a = detail::Fetch64(s) + detail::k2;
|
||||||
|
uint64_t b = detail::Fetch64(s + len - 8);
|
||||||
|
uint64_t c = detail::Rotate(b, 37) * mul + a;
|
||||||
|
uint64_t d = (detail::Rotate(a, 25) + b) * mul;
|
||||||
|
return HashLen16(c, d, mul);
|
||||||
|
}
|
||||||
|
if (len >= 4) {
|
||||||
|
uint64_t mul = detail::k2 + len * 2;
|
||||||
|
uint64_t a = Fetch32(s);
|
||||||
|
return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
uint8_t a = static_cast<uint8_t>(s[0]);
|
||||||
|
uint8_t b = static_cast<uint8_t>(s[len >> 1]);
|
||||||
|
uint8_t c = static_cast<uint8_t>(s[len - 1]);
|
||||||
|
uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
|
||||||
|
uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
|
||||||
|
return ShiftMix(y * detail::k2 ^ z * detail::k0) * detail::k2;
|
||||||
|
}
|
||||||
|
return detail::k2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This probably works well for 16-byte strings as well, but it may be overkill
|
||||||
|
// in that case.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t HashLen17to32(const char *s, size_t len) noexcept {
|
||||||
|
uint64_t mul = detail::k2 + len * 2;
|
||||||
|
uint64_t a = detail::Fetch64(s) * detail::k1;
|
||||||
|
uint64_t b = detail::Fetch64(s + 8);
|
||||||
|
uint64_t c = detail::Fetch64(s + len - 8) * mul;
|
||||||
|
uint64_t d = detail::Fetch64(s + len - 16) * detail::k2;
|
||||||
|
return HashLen16(detail::Rotate(a + b, 43) + detail::Rotate(c, 30) + d,
|
||||||
|
a + detail::Rotate(b + detail::k2, 18) + c, mul);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||||
|
// Callers do best to use "random-looking" values for a and b.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr detail::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
|
||||||
|
uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) noexcept {
|
||||||
|
a += w;
|
||||||
|
b = detail::Rotate(b + a + z, 21);
|
||||||
|
uint64_t c = a;
|
||||||
|
a += x;
|
||||||
|
a += y;
|
||||||
|
b += detail::Rotate(a, 44);
|
||||||
|
return detail::pair(a + z, b + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr detail::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
|
||||||
|
const char* s, uint64_t a, uint64_t b) noexcept {
|
||||||
|
return WeakHashLen32WithSeeds(detail::Fetch64(s),
|
||||||
|
detail::Fetch64(s + 8),
|
||||||
|
detail::Fetch64(s + 16),
|
||||||
|
detail::Fetch64(s + 24),
|
||||||
|
a,
|
||||||
|
b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an 8-byte hash for 33 to 64 bytes.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t HashLen33to64(const char *s, size_t len) noexcept {
|
||||||
|
uint64_t mul = detail::k2 + len * 2;
|
||||||
|
uint64_t a = detail::Fetch64(s) * detail::k2;
|
||||||
|
uint64_t b = detail::Fetch64(s + 8);
|
||||||
|
uint64_t c = detail::Fetch64(s + len - 24);
|
||||||
|
uint64_t d = detail::Fetch64(s + len - 32);
|
||||||
|
uint64_t e = detail::Fetch64(s + 16) * detail::k2;
|
||||||
|
uint64_t f = detail::Fetch64(s + 24) * 9;
|
||||||
|
uint64_t g = detail::Fetch64(s + len - 8);
|
||||||
|
uint64_t h = detail::Fetch64(s + len - 16) * mul;
|
||||||
|
uint64_t u = detail::Rotate(a + g, 43) + (detail::Rotate(b, 30) + c) * 9;
|
||||||
|
uint64_t v = ((a + g) ^ d) + f + 1;
|
||||||
|
uint64_t w = detail::byteSwap((u + v) * mul) + h;
|
||||||
|
uint64_t x = detail::Rotate(e + f, 42) + c;
|
||||||
|
uint64_t y = (detail::byteSwap((v + w) * mul) + g) * mul;
|
||||||
|
uint64_t z = e + f + c;
|
||||||
|
a = detail::byteSwap((x + z) * mul + y) + b;
|
||||||
|
b = ShiftMix((z + a) * mul + d + h) * mul;
|
||||||
|
return b + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
||||||
|
// of any length representable in signed long. Based on City and Murmur.
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint128 CityMurmur(const char *s, size_t len, uint128 seed) noexcept {
|
||||||
|
uint64_t a = detail::Uint128Low64(seed);
|
||||||
|
uint64_t b = detail::Uint128High64(seed);
|
||||||
|
uint64_t c = 0;
|
||||||
|
uint64_t d = 0;
|
||||||
|
if (len <= 16) {
|
||||||
|
a = ShiftMix(a * detail::k1) * detail::k1;
|
||||||
|
c = b * detail::k1 + HashLen0to16(s, len);
|
||||||
|
d = ShiftMix(a + (len >= 8 ? detail::Fetch64(s) : c));
|
||||||
|
} else {
|
||||||
|
c = HashLen16(detail::Fetch64(s + len - 8) + detail::k1, a);
|
||||||
|
d = HashLen16(b + len, c + detail::Fetch64(s + len - 16));
|
||||||
|
a += d;
|
||||||
|
// len > 16 here, so do...while is safe
|
||||||
|
do {
|
||||||
|
a ^= ShiftMix(detail::Fetch64(s) * detail::k1) * detail::k1;
|
||||||
|
a *= detail::k1;
|
||||||
|
b ^= a;
|
||||||
|
c ^= ShiftMix(detail::Fetch64(s + 8) * detail::k1) * detail::k1;
|
||||||
|
c *= detail::k1;
|
||||||
|
d ^= c;
|
||||||
|
s += 16;
|
||||||
|
len -= 16;
|
||||||
|
} while (len > 16);
|
||||||
|
}
|
||||||
|
a = HashLen16(a, c);
|
||||||
|
b = HashLen16(d, b);
|
||||||
|
return uint128(a ^ b, HashLen16(b, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint32_t CityHash32(const char *s, size_t len) noexcept {
|
||||||
|
if (len <= 24) {
|
||||||
|
return len <= 12 ?
|
||||||
|
(len <= 4 ? detail::Hash32Len0to4(s, len) : detail::Hash32Len5to12(s, len)) :
|
||||||
|
detail::Hash32Len13to24(s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// len > 24
|
||||||
|
uint32_t h = static_cast<uint32_t>(len), g = detail::c1 * h, f = g;
|
||||||
|
uint32_t a0 = detail::Rotate32(detail::Fetch32(s + len - 4) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a1 = detail::Rotate32(detail::Fetch32(s + len - 8) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a2 = detail::Rotate32(detail::Fetch32(s + len - 16) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a3 = detail::Rotate32(detail::Fetch32(s + len - 12) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a4 = detail::Rotate32(detail::Fetch32(s + len - 20) * detail::c1, 17) * detail::c2;
|
||||||
|
h ^= a0;
|
||||||
|
h = detail::Rotate32(h, 19);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
h ^= a2;
|
||||||
|
h = detail::Rotate32(h, 19);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
g ^= a1;
|
||||||
|
g = detail::Rotate32(g, 19);
|
||||||
|
g = g * 5 + 0xe6546b64;
|
||||||
|
g ^= a3;
|
||||||
|
g = detail::Rotate32(g, 19);
|
||||||
|
g = g * 5 + 0xe6546b64;
|
||||||
|
f += a4;
|
||||||
|
f = detail::Rotate32(f, 19);
|
||||||
|
f = f * 5 + 0xe6546b64;
|
||||||
|
size_t iters = (len - 1) / 20;
|
||||||
|
do {
|
||||||
|
uint32_t a0 = detail::Rotate32(detail::Fetch32(s) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a1 = detail::Fetch32(s + 4);
|
||||||
|
uint32_t a2 = detail::Rotate32(detail::Fetch32(s + 8) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a3 = detail::Rotate32(detail::Fetch32(s + 12) * detail::c1, 17) * detail::c2;
|
||||||
|
uint32_t a4 = detail::Fetch32(s + 16);
|
||||||
|
h ^= a0;
|
||||||
|
h = detail::Rotate32(h, 18);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
f += a1;
|
||||||
|
f = detail::Rotate32(f, 19);
|
||||||
|
f = f * detail::c1;
|
||||||
|
g += a2;
|
||||||
|
g = detail::Rotate32(g, 18);
|
||||||
|
g = g * 5 + 0xe6546b64;
|
||||||
|
h ^= a3 + a1;
|
||||||
|
h = detail::Rotate32(h, 19);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
g ^= a4;
|
||||||
|
g = detail::byteSwap(g) * 5;
|
||||||
|
h += a4 * 5;
|
||||||
|
h = detail::byteSwap(h);
|
||||||
|
f += a0;
|
||||||
|
PERMUTE3(f, h, g);
|
||||||
|
s += 20;
|
||||||
|
} while (--iters != 0);
|
||||||
|
g = detail::Rotate32(g, 11) * detail::c1;
|
||||||
|
g = detail::Rotate32(g, 17) * detail::c1;
|
||||||
|
f = detail::Rotate32(f, 11) * detail::c1;
|
||||||
|
f = detail::Rotate32(f, 17) * detail::c1;
|
||||||
|
h = detail::Rotate32(h + g, 19);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
h = detail::Rotate32(h, 17) * detail::c1;
|
||||||
|
h = detail::Rotate32(h + f, 19);
|
||||||
|
h = h * 5 + 0xe6546b64;
|
||||||
|
h = detail::Rotate32(h, 17) * detail::c1;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t CityHash64(const char *s, size_t len) noexcept {
|
||||||
|
if (len <= 32) {
|
||||||
|
if (len <= 16) {
|
||||||
|
return detail::HashLen0to16(s, len);
|
||||||
|
} else {
|
||||||
|
return detail::HashLen17to32(s, len);
|
||||||
|
}
|
||||||
|
} else if (len <= 64) {
|
||||||
|
return detail::HashLen33to64(s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For strings over 64 bytes we hash the end first, and then as we
|
||||||
|
// loop we keep 56 bytes of state: v, w, x, y, and z.
|
||||||
|
uint64_t x = detail::Fetch64(s + len - 40);
|
||||||
|
uint64_t y = detail::Fetch64(s + len - 16) + detail::Fetch64(s + len - 56);
|
||||||
|
uint64_t z = detail::HashLen16(detail::Fetch64(s + len - 48) + len, detail::Fetch64(s + len - 24));
|
||||||
|
detail::pair<uint64_t, uint64_t> v = detail::WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||||
|
detail::pair<uint64_t, uint64_t> w = detail::WeakHashLen32WithSeeds(s + len - 32, y + detail::k1, x);
|
||||||
|
x = x * detail::k1 + detail::Fetch64(s);
|
||||||
|
|
||||||
|
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||||
|
len = (len - 1) & ~static_cast<size_t>(63);
|
||||||
|
do {
|
||||||
|
x = detail::Rotate(x + y + v.first + detail::Fetch64(s + 8), 37) * detail::k1;
|
||||||
|
y = detail::Rotate(y + v.second + detail::Fetch64(s + 48), 42) * detail::k1;
|
||||||
|
x ^= w.second;
|
||||||
|
y += v.first + detail::Fetch64(s + 40);
|
||||||
|
z = detail::Rotate(z + w.first, 33) * detail::k1;
|
||||||
|
v = detail::WeakHashLen32WithSeeds(s, v.second * detail::k1, x + w.first);
|
||||||
|
w = detail::WeakHashLen32WithSeeds(s + 32, z + w.second, y + detail::Fetch64(s + 16));
|
||||||
|
detail::swap(z, x);
|
||||||
|
s += 64;
|
||||||
|
len -= 64;
|
||||||
|
} while (len != 0);
|
||||||
|
return detail::HashLen16(detail::HashLen16(v.first, w.first) + detail::ShiftMix(y) * detail::k1 + z,
|
||||||
|
detail::HashLen16(v.second, w.second) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t CityHash64WithSeeds(const char *s, size_t len,
|
||||||
|
uint64_t seed0, uint64_t seed1) noexcept {
|
||||||
|
return detail::HashLen16(CityHash64(s, len) - seed0, seed1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) noexcept {
|
||||||
|
return CityHash64WithSeeds(s, len, detail::k2, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) noexcept {
|
||||||
|
if (len < 128) {
|
||||||
|
return detail::CityMurmur(s, len, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||||
|
// v, w, x, y, and z.
|
||||||
|
detail::pair<uint64_t, uint64_t> v, w;
|
||||||
|
uint64_t x = detail::Uint128Low64(seed);
|
||||||
|
uint64_t y = detail::Uint128High64(seed);
|
||||||
|
uint64_t z = len * detail::k1;
|
||||||
|
v.first = detail::Rotate(y ^ detail::k1, 49) * detail::k1 + detail::Fetch64(s);
|
||||||
|
v.second = detail::Rotate(v.first, 42) * detail::k1 + detail::Fetch64(s + 8);
|
||||||
|
w.first = detail::Rotate(y + z, 35) * detail::k1 + x;
|
||||||
|
w.second = detail::Rotate(x + detail::Fetch64(s + 88), 53) * detail::k1;
|
||||||
|
|
||||||
|
// This is the same inner loop as CityHash64(), manually unrolled.
|
||||||
|
do {
|
||||||
|
x = detail::Rotate(x + y + v.first + detail::Fetch64(s + 8), 37) * detail::k1;
|
||||||
|
y = detail::Rotate(y + v.second + detail::Fetch64(s + 48), 42) * detail::k1;
|
||||||
|
x ^= w.second;
|
||||||
|
y += v.first + detail::Fetch64(s + 40);
|
||||||
|
z = detail::Rotate(z + w.first, 33) * detail::k1;
|
||||||
|
v = detail::WeakHashLen32WithSeeds(s, v.second * detail::k1, x + w.first);
|
||||||
|
w = detail::WeakHashLen32WithSeeds(s + 32, z + w.second, y + detail::Fetch64(s + 16));
|
||||||
|
detail::swap(z, x);
|
||||||
|
s += 64;
|
||||||
|
x = detail::Rotate(x + y + v.first + detail::Fetch64(s + 8), 37) * detail::k1;
|
||||||
|
y = detail::Rotate(y + v.second + detail::Fetch64(s + 48), 42) * detail::k1;
|
||||||
|
x ^= w.second;
|
||||||
|
y += v.first + detail::Fetch64(s + 40);
|
||||||
|
z = detail::Rotate(z + w.first, 33) * detail::k1;
|
||||||
|
v = detail::WeakHashLen32WithSeeds(s, v.second * detail::k1, x + w.first);
|
||||||
|
w = detail::WeakHashLen32WithSeeds(s + 32, z + w.second, y + detail::Fetch64(s + 16));
|
||||||
|
detail::swap(z, x);
|
||||||
|
s += 64;
|
||||||
|
len -= 128;
|
||||||
|
} while (LIKELY(len >= 128));
|
||||||
|
x += detail::Rotate(v.first + z, 49) * detail::k0;
|
||||||
|
y = y * detail::k0 + detail::Rotate(w.second, 37);
|
||||||
|
z = z * detail::k0 + detail::Rotate(w.first, 27);
|
||||||
|
w.first *= 9;
|
||||||
|
v.first *= detail::k0;
|
||||||
|
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
||||||
|
for (size_t tail_done = 0; tail_done < len; ) {
|
||||||
|
tail_done += 32;
|
||||||
|
y = detail::Rotate(x + y, 42) * detail::k0 + v.second;
|
||||||
|
w.first += detail::Fetch64(s + len - tail_done + 16);
|
||||||
|
x = x * detail::k0 + w.first;
|
||||||
|
z += w.second + detail::Fetch64(s + len - tail_done);
|
||||||
|
w.second += v.first;
|
||||||
|
v = detail::WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
|
||||||
|
v.first *= detail::k0;
|
||||||
|
}
|
||||||
|
// At this point our 56 bytes of state should contain more than
|
||||||
|
// enough information for a strong 128-bit hash. We use two
|
||||||
|
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
||||||
|
x = detail::HashLen16(x, v.first);
|
||||||
|
y = detail::HashLen16(y + z, w.first);
|
||||||
|
return uint128(detail::HashLen16(x + v.second, w.second) + y,
|
||||||
|
detail::HashLen16(x + w.second, y + v.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint128 CityHash128(const char *s, size_t len) noexcept {
|
||||||
|
return len >= 16 ?
|
||||||
|
CityHash128WithSeed(s + 16, len - 16,
|
||||||
|
uint128(detail::Fetch64(s), detail::Fetch64(s + 8) + detail::k0)) :
|
||||||
|
CityHash128WithSeed(s, len, uint128(detail::k0, detail::k1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CITY_HASH_H_
|
15
deps/ox/src/ox/CMakeLists.txt
vendored
15
deps/ox/src/ox/CMakeLists.txt
vendored
@ -1,3 +1,18 @@
|
|||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
set(OX_OS_WINDOWS TRUE)
|
||||||
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
|
set(OX_OS_FREEBSD TRUE)
|
||||||
|
else()
|
||||||
|
set(OX_OS_FREEBSD FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
set(OX_OS_LINUX TRUE)
|
||||||
|
else()
|
||||||
|
set(OX_OS_LINUX FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(OX_USE_STDLIB)
|
if(OX_USE_STDLIB)
|
||||||
add_subdirectory(oc)
|
add_subdirectory(oc)
|
||||||
endif()
|
endif()
|
||||||
|
14
deps/ox/src/ox/clargs/clargs.cpp
vendored
14
deps/ox/src/ox/clargs/clargs.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
@ -13,7 +13,7 @@ namespace ox {
|
|||||||
|
|
||||||
ClArgs::ClArgs(int argc, const char **args) noexcept {
|
ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||||
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
|
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
|
||||||
String arg = args[i];
|
auto arg = String(args[i]);
|
||||||
if (arg[0] == '-') {
|
if (arg[0] == '-') {
|
||||||
while (arg[0] == '-' && arg.len()) {
|
while (arg[0] == '-' && arg.len()) {
|
||||||
arg = arg.substr(1);
|
arg = arg.substr(1);
|
||||||
@ -21,13 +21,13 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
|
|||||||
m_bools[arg] = true;
|
m_bools[arg] = true;
|
||||||
// parse additional arguments
|
// parse additional arguments
|
||||||
if (i < static_cast<unsigned>(argc) && args[i + 1]) {
|
if (i < static_cast<unsigned>(argc) && args[i + 1]) {
|
||||||
String val = args[i + 1];
|
auto val = String(args[i + 1]);
|
||||||
if (val.len() && val[i] != '-') {
|
if (val.len() && val[i] != '-') {
|
||||||
if (val == "false") {
|
if (val == "false") {
|
||||||
m_bools[arg] = false;
|
m_bools[arg] = false;
|
||||||
}
|
}
|
||||||
m_strings[arg] = val;
|
m_strings[arg] = val;
|
||||||
if (auto r = ox_atoi(val.c_str()); r.error == 0) {
|
if (auto r = ox::atoi(val.c_str()); r.error == 0) {
|
||||||
m_ints[arg] = r.value;
|
m_ints[arg] = r.value;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
@ -42,9 +42,9 @@ bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept {
|
|||||||
return !err ? *value : defaultValue;
|
return !err ? *value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept {
|
String ClArgs::getString(ox::CRStringView arg, ox::StringView defaultValue) const noexcept {
|
||||||
auto [value, err] = m_strings.at(arg);
|
auto [value, err] = m_strings.at(arg);
|
||||||
return !err ? *value : defaultValue;
|
return !err ? ox::String(*value) : ox::String(defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {
|
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {
|
||||||
|
6
deps/ox/src/ox/clargs/clargs.hpp
vendored
6
deps/ox/src/ox/clargs/clargs.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -26,7 +26,7 @@ class ClArgs {
|
|||||||
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
|
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
String getString(ox::CRStringView argName, const char *defaultValue) const noexcept;
|
String getString(ox::CRStringView argName, ox::StringView defaultValue) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;
|
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;
|
||||||
|
12
deps/ox/src/ox/claw/CMakeLists.txt
vendored
12
deps/ox/src/ox/claw/CMakeLists.txt
vendored
@ -5,7 +5,6 @@ add_library(
|
|||||||
write.cpp
|
write.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_compile_options(OxClaw PRIVATE -Wsign-conversion)
|
target_compile_options(OxClaw PRIVATE -Wsign-conversion)
|
||||||
target_compile_options(OxClaw PRIVATE -Wconversion)
|
target_compile_options(OxClaw PRIVATE -Wconversion)
|
||||||
@ -17,6 +16,17 @@ target_link_libraries(
|
|||||||
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#if(OX_USE_STDLIB)
|
||||||
|
# add_executable(
|
||||||
|
# readclaw
|
||||||
|
# readclaw.cpp
|
||||||
|
# )
|
||||||
|
# target_link_libraries(
|
||||||
|
# readclaw PUBLIC
|
||||||
|
# OxClaw
|
||||||
|
# )
|
||||||
|
#endif()
|
||||||
|
|
||||||
install(TARGETS OxClaw
|
install(TARGETS OxClaw
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
|
4
deps/ox/src/ox/claw/claw.hpp
vendored
4
deps/ox/src/ox/claw/claw.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
4
deps/ox/src/ox/claw/format.hpp
vendored
4
deps/ox/src/ox/claw/format.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
111
deps/ox/src/ox/claw/read.cpp
vendored
111
deps/ox/src/ox/claw/read.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -12,34 +12,66 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept {
|
ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
|
||||||
const auto s1End = ox_strchr(buff, ';', buffLen);
|
auto buffRaw = buff.data();
|
||||||
|
auto buffLen = buff.size();
|
||||||
|
size_t outSz{};
|
||||||
|
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
|
||||||
if (!s1End) {
|
if (!s1End) {
|
||||||
return OxError(1, "Could not read Claw header");
|
return OxError(1, "Could not read Claw header");
|
||||||
}
|
}
|
||||||
const auto s1Size = static_cast<std::size_t>(s1End - buff);
|
auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
|
||||||
const String fmt(buff, s1Size);
|
buffRaw += fmtSz;
|
||||||
buff += s1Size + 1;
|
buffLen -= fmtSz;
|
||||||
buffLen -= s1Size + 1;
|
outSz += fmtSz;
|
||||||
|
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
|
||||||
const auto s2End = ox_strchr(buff, ';', buffLen);
|
|
||||||
if (!s2End) {
|
if (!s2End) {
|
||||||
return OxError(2, "Could not read Claw header");
|
return OxError(2, "Could not read Claw header");
|
||||||
}
|
}
|
||||||
const auto s2Size = static_cast<std::size_t>(s2End - buff);
|
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
|
||||||
const String typeName(buff, s2Size);
|
buffRaw += s2Size;
|
||||||
buff += s2Size + 1;
|
buffLen -= s2Size;
|
||||||
buffLen -= s2Size + 1;
|
outSz += s2Size;
|
||||||
|
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
|
||||||
const auto s3End = ox_strchr(buff, ';', buffLen);
|
|
||||||
if (!s3End) {
|
if (!s3End) {
|
||||||
return OxError(3, "Could not read Claw header");
|
return OxError(3, "Could not read Claw header");
|
||||||
}
|
}
|
||||||
const auto s3Size = static_cast<std::size_t>(s3End - buff);
|
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
|
||||||
const String versionStr(buff, s3Size);
|
buffRaw += s3Size;
|
||||||
buff += s3Size + 1;
|
buffLen -= s3Size;
|
||||||
buffLen -= s3Size + 1;
|
outSz += s3Size;
|
||||||
|
return {{buff.data() + fmtSz, outSz - fmtSz - 1}};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
|
||||||
|
auto buffRaw = buff.data();
|
||||||
|
auto buffLen = buff.size();
|
||||||
|
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
|
||||||
|
if (!s1End) {
|
||||||
|
return OxError(1, "Could not read Claw header");
|
||||||
|
}
|
||||||
|
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
|
||||||
|
StringView const fmt(buffRaw, s1Size);
|
||||||
|
buffRaw += s1Size + 1;
|
||||||
|
buffLen -= s1Size + 1;
|
||||||
|
|
||||||
|
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
|
||||||
|
if (!s2End) {
|
||||||
|
return OxError(2, "Could not read Claw header");
|
||||||
|
}
|
||||||
|
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
|
||||||
|
StringView const typeName(buffRaw, s2Size);
|
||||||
|
buffRaw += s2Size + 1;
|
||||||
|
buffLen -= s2Size + 1;
|
||||||
|
|
||||||
|
auto const s3End = ox::strchr(buffRaw, ';', buffLen);
|
||||||
|
if (!s3End) {
|
||||||
|
return OxError(3, "Could not read Claw header");
|
||||||
|
}
|
||||||
|
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
|
||||||
|
StringView const versionStr(buffRaw, s3Size);
|
||||||
|
buffRaw += s3Size + 1;
|
||||||
|
buffLen -= s3Size + 1;
|
||||||
ClawHeader hdr;
|
ClawHeader hdr;
|
||||||
if (fmt == "M2") {
|
if (fmt == "M2") {
|
||||||
hdr.fmt = ClawFormat::Metal;
|
hdr.fmt = ClawFormat::Metal;
|
||||||
@ -49,38 +81,31 @@ Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcep
|
|||||||
return OxError(4, "Claw format does not match any supported format/version combo");
|
return OxError(4, "Claw format does not match any supported format/version combo");
|
||||||
}
|
}
|
||||||
hdr.typeName = typeName;
|
hdr.typeName = typeName;
|
||||||
if (auto r = ox_atoi(versionStr.c_str()); r.error == 0) {
|
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
|
||||||
hdr.typeVersion = r.value;
|
hdr.data = buffRaw;
|
||||||
}
|
|
||||||
hdr.data = buff;
|
|
||||||
hdr.dataSize = buffLen;
|
hdr.dataSize = buffLen;
|
||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept {
|
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept {
|
||||||
return readClawHeader(buff.data(), buff.size());
|
oxRequire(header, readClawHeader(buff));
|
||||||
|
return {{header.data, header.dataSize}};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept {
|
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
|
||||||
oxRequire(header, readClawHeader(buff, buffLen));
|
oxRequire(header, readClawHeader(buff));
|
||||||
Buffer out(header.dataSize);
|
auto const [t, tdErr] = ts.getLoad(
|
||||||
ox_memcpy(out.data(), header.data, out.size());
|
header.typeName, header.typeVersion, header.typeParams);
|
||||||
return out;
|
if (tdErr) {
|
||||||
}
|
return OxError(3, "Could not load type descriptor");
|
||||||
|
}
|
||||||
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
|
|
||||||
return stripClawHeader(buff.data(), buff.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz) noexcept {
|
|
||||||
oxRequire(header, readClawHeader(buff, buffSz));
|
|
||||||
oxRequire(t, ts->getLoad(header.typeName, header.typeVersion, header.typeParams));
|
|
||||||
ModelObject obj;
|
ModelObject obj;
|
||||||
oxReturnError(obj.setType(t));
|
oxReturnError(obj.setType(t));
|
||||||
switch (header.fmt) {
|
switch (header.fmt) {
|
||||||
case ClawFormat::Metal:
|
case ClawFormat::Metal:
|
||||||
{
|
{
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
ox::BufferReader br({header.data, header.dataSize});
|
||||||
|
MetalClawReader reader(br);
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
oxReturnError(model(&handler, &obj));
|
oxReturnError(model(&handler, &obj));
|
||||||
return obj;
|
return obj;
|
||||||
@ -88,7 +113,7 @@ Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz
|
|||||||
case ClawFormat::Organic:
|
case ClawFormat::Organic:
|
||||||
{
|
{
|
||||||
#ifdef OX_USE_STDLIB
|
#ifdef OX_USE_STDLIB
|
||||||
OrganicClawReader reader(header.data, header.dataSize);
|
OrganicClawReader reader({header.data, header.dataSize});
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
oxReturnError(model(&handler, &obj));
|
oxReturnError(model(&handler, &obj));
|
||||||
return obj;
|
return obj;
|
||||||
@ -102,8 +127,4 @@ Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz
|
|||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept {
|
|
||||||
return readClaw(ts, buff.data(), buff.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
42
deps/ox/src/ox/claw/read.hpp
vendored
42
deps/ox/src/ox/claw/read.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/span.hpp>
|
||||||
#include <ox/mc/read.hpp>
|
#include <ox/mc/read.hpp>
|
||||||
#ifdef OX_USE_STDLIB
|
#ifdef OX_USE_STDLIB
|
||||||
#include <ox/oc/read.hpp>
|
#include <ox/oc/read.hpp>
|
||||||
@ -31,17 +32,15 @@ struct ClawHeader {
|
|||||||
std::size_t dataSize = 0;
|
std::size_t dataSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept;
|
ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept;
|
||||||
|
|
||||||
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept;
|
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept;
|
||||||
|
|
||||||
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept;
|
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
|
||||||
|
|
||||||
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Error readClaw(const char *buff, std::size_t buffLen, T *val) {
|
Error readClaw(ox::BufferView buff, T &val) {
|
||||||
oxRequire(header, readClawHeader(buff, buffLen));
|
oxRequire(header, readClawHeader(buff));
|
||||||
if (header.typeName != getModelTypeName<T>()) {
|
if (header.typeName != getModelTypeName<T>()) {
|
||||||
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
|
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
|
||||||
}
|
}
|
||||||
@ -51,15 +50,16 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
|
|||||||
switch (header.fmt) {
|
switch (header.fmt) {
|
||||||
case ClawFormat::Metal:
|
case ClawFormat::Metal:
|
||||||
{
|
{
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
ox::BufferReader br({header.data, header.dataSize});
|
||||||
|
MetalClawReader reader(br);
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
return model(&handler, val);
|
return model(&handler, &val);
|
||||||
}
|
}
|
||||||
case ClawFormat::Organic:
|
case ClawFormat::Organic:
|
||||||
{
|
{
|
||||||
#ifdef OX_USE_STDLIB
|
#ifdef OX_USE_STDLIB
|
||||||
OrganicClawReader reader(header.data, header.dataSize);
|
OrganicClawReader reader(header.data, header.dataSize);
|
||||||
return model(&reader, val);
|
return model(&reader, &val);
|
||||||
#else
|
#else
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -71,24 +71,12 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Result<T> readClaw(const char *buff, std::size_t buffLen) {
|
Result<T> readClaw(ox::BufferView buff) {
|
||||||
T val;
|
Result<T> val;
|
||||||
oxReturnError(readClaw(buff, buffLen, &val));
|
oxReturnError(readClaw(buff, val.value));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept;
|
||||||
Error readClaw(const Buffer &buff, T *val) {
|
|
||||||
return readClaw<T>(buff.data(), buff.size(), val);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
Result<T> readClaw(const Buffer &buff) {
|
|
||||||
return readClaw<T>(buff.data(), buff.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz) noexcept;
|
|
||||||
|
|
||||||
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
30
deps/ox/src/ox/claw/readclaw.cpp
vendored
Normal file
30
deps/ox/src/ox/claw/readclaw.cpp
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
#include <ox/std/trace.hpp>
|
||||||
|
|
||||||
|
#include "claw.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **args) {
|
||||||
|
if (argc > 2) {
|
||||||
|
oxErr("Too many arguments");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto const file = argc == 1 ? stdin : fopen(args[1], "r");
|
||||||
|
if (fseek(file, 0, SEEK_END)) {
|
||||||
|
oxErr("Could not get file size\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
auto const size = static_cast<std::size_t>(ftell(file));
|
||||||
|
oxDebugf("{}", size);
|
||||||
|
return 0;
|
||||||
|
}
|
9
deps/ox/src/ox/claw/test/CMakeLists.txt
vendored
9
deps/ox/src/ox/claw/test/CMakeLists.txt
vendored
@ -8,7 +8,8 @@ target_link_libraries(
|
|||||||
OxClaw
|
OxClaw
|
||||||
)
|
)
|
||||||
|
|
||||||
add_test("[ox/claw] ClawTest ClawHeaderReader" ClawTest ClawHeaderReader)
|
add_test("[ox/claw] ClawHeaderReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader)
|
||||||
add_test("[ox/claw] ClawTest ClawHeaderReader2" ClawTest ClawHeaderReader2)
|
add_test("[ox/claw] ClawHeaderReader2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader2)
|
||||||
add_test("[ox/claw] ClawTest ClawWriter" ClawTest ClawWriter)
|
add_test("[ox/claw] ClawHeaderReadTypeId" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReadTypeId)
|
||||||
add_test("[ox/claw] ClawTest ClawReader" ClawTest ClawReader)
|
add_test("[ox/claw] ClawWriter" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawWriter)
|
||||||
|
add_test("[ox/claw] ClawReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawReader)
|
||||||
|
48
deps/ox/src/ox/claw/test/tests.cpp
vendored
48
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -8,11 +8,7 @@
|
|||||||
|
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <ox/claw/format.hpp>
|
#include <ox/claw/format.hpp>
|
||||||
#include <ox/claw/read.hpp>
|
#include <ox/claw/read.hpp>
|
||||||
#include <ox/claw/write.hpp>
|
#include <ox/claw/write.hpp>
|
||||||
@ -33,7 +29,7 @@ struct TestStructNest {
|
|||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
bool Bool = false;
|
bool Bool = false;
|
||||||
uint32_t Int = 0;
|
uint32_t Int = 0;
|
||||||
ox::BString<32> String = "";
|
ox::IString<32> String = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestStruct {
|
struct TestStruct {
|
||||||
@ -51,7 +47,7 @@ struct TestStruct {
|
|||||||
int32_t Int8 = 0;
|
int32_t Int8 = 0;
|
||||||
int unionIdx = 1;
|
int unionIdx = 1;
|
||||||
TestUnion Union;
|
TestUnion Union;
|
||||||
ox::BString<32> String = "";
|
ox::IString<32> String = "";
|
||||||
uint32_t List[4] = {0, 0, 0, 0};
|
uint32_t List[4] = {0, 0, 0, 0};
|
||||||
TestStructNest EmptyStruct;
|
TestStructNest EmptyStruct;
|
||||||
TestStructNest Struct;
|
TestStructNest Struct;
|
||||||
@ -107,13 +103,13 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<std::string_view, ox::Error(*)()> tests = {
|
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"ClawHeaderReader",
|
"ClawHeaderReader",
|
||||||
[] {
|
[] {
|
||||||
ox::String hdr = "O1;com.drinkingtea.ox.claw.test.Header;2;";
|
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
|
||||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
|
||||||
oxAssert(err, "Error parsing header");
|
oxAssert(err, "Error parsing header");
|
||||||
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
|
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
|
||||||
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
|
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
|
||||||
@ -124,8 +120,8 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
|||||||
{
|
{
|
||||||
"ClawHeaderReader2",
|
"ClawHeaderReader2",
|
||||||
[] {
|
[] {
|
||||||
ox::String hdr = "M2;com.drinkingtea.ox.claw.test.Header2;3;";
|
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
|
||||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
|
||||||
oxAssert(err, "Error parsing header");
|
oxAssert(err, "Error parsing header");
|
||||||
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
|
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
|
||||||
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
|
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
|
||||||
@ -133,6 +129,16 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ClawHeaderReadTypeId",
|
||||||
|
[] {
|
||||||
|
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
|
||||||
|
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
|
||||||
|
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
|
||||||
|
oxExpect(actual, expected);
|
||||||
|
return ox::Error{};
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ClawWriter",
|
"ClawWriter",
|
||||||
[] {
|
[] {
|
||||||
@ -160,7 +166,7 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
|||||||
testIn.Struct.String = "Test String 2";
|
testIn.Struct.String = "Test String 2";
|
||||||
const auto [buff, err] = ox::writeMC(testIn);
|
const auto [buff, err] = ox::writeMC(testIn);
|
||||||
oxAssert(err, "writeClaw failed");
|
oxAssert(err, "writeClaw failed");
|
||||||
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readClaw failed");
|
oxAssert(ox::readMC(buff, testOut), "readClaw failed");
|
||||||
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
||||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||||
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
||||||
@ -192,14 +198,14 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char **args) {
|
int main(int argc, const char **args) {
|
||||||
int retval = -1;
|
if (argc < 2) {
|
||||||
if (argc > 0) {
|
oxError("Must specify test to run");
|
||||||
auto testName = args[1];
|
|
||||||
if (tests.find(testName) != tests.end()) {
|
|
||||||
retval = static_cast<int>(tests[testName]());
|
|
||||||
} else {
|
|
||||||
retval = 1;
|
|
||||||
}
|
}
|
||||||
|
auto const testName = args[1];
|
||||||
|
auto const func = tests.find(testName);
|
||||||
|
if (func != tests.end()) {
|
||||||
|
oxAssert(func->second(), "Test returned Error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return retval;
|
return -1;
|
||||||
}
|
}
|
||||||
|
4
deps/ox/src/ox/claw/write.cpp
vendored
4
deps/ox/src/ox/claw/write.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "write.hpp"
|
#include "write.hpp"
|
||||||
|
10
deps/ox/src/ox/claw/write.hpp
vendored
10
deps/ox/src/ox/claw/write.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -61,14 +61,14 @@ struct type_version<T, decltype((void) T::TypeVersion, -1)> {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr const char *getTypeName(const T *t) noexcept {
|
constexpr const char *getTypeName(const T *t) noexcept {
|
||||||
TypeInfoCatcher tnc;
|
TypeInfoCatcher tnc;
|
||||||
oxIgnoreError(model(&tnc, t));
|
std::ignore = model(&tnc, t);
|
||||||
return tnc.name;
|
return tnc.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr int getTypeVersion(const T *t) noexcept {
|
constexpr int getTypeVersion(const T *t) noexcept {
|
||||||
TypeInfoCatcher tnc;
|
TypeInfoCatcher tnc;
|
||||||
oxIgnoreError(model(&tnc, t));
|
std::ignore = model(&tnc, t);
|
||||||
return tnc.version;
|
return tnc.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noe
|
|||||||
oxReturnError(writer.put(';'));
|
oxReturnError(writer.put(';'));
|
||||||
const auto tn = detail::getTypeVersion(t);
|
const auto tn = detail::getTypeVersion(t);
|
||||||
if (tn > -1) {
|
if (tn > -1) {
|
||||||
oxReturnError(ox::itoa(tn, writer));
|
oxReturnError(ox::writeItoa(tn, writer));
|
||||||
}
|
}
|
||||||
oxReturnError(writer.put(';'));
|
oxReturnError(writer.put(';'));
|
||||||
return {};
|
return {};
|
||||||
|
4
deps/ox/src/ox/event/event.hpp
vendored
4
deps/ox/src/ox/event/event.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
4
deps/ox/src/ox/event/signal.cpp
vendored
4
deps/ox/src/ox/event/signal.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "signal.hpp"
|
#include "signal.hpp"
|
||||||
|
14
deps/ox/src/ox/event/signal.hpp
vendored
14
deps/ox/src/ox/event/signal.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -245,7 +245,7 @@ class Signal<Error(Args...)> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error call(Args... args) noexcept final {
|
Error call(Args... args) noexcept final {
|
||||||
return f(args...);
|
return f(ox::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ class Signal<Error(Args...)> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error call(Args... args) noexcept final {
|
Error call(Args... args) noexcept final {
|
||||||
return (m_receiver->*(m_methodPtr))(args...);
|
return (m_receiver->*(m_methodPtr))(ox::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup(Signal *signal) noexcept final {
|
void cleanup(Signal *signal) noexcept final {
|
||||||
@ -286,7 +286,7 @@ class Signal<Error(Args...)> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error call(Args... args) noexcept final {
|
Error call(Args... args) noexcept final {
|
||||||
return (m_receiver->*(m_methodPtr))(args...);
|
return (m_receiver->*(m_methodPtr))(ox::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup(Signal*) noexcept final {
|
void cleanup(Signal*) noexcept final {
|
||||||
@ -391,14 +391,14 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
|
|||||||
template<class... Args>
|
template<class... Args>
|
||||||
void Signal<Error(Args...)>::emit(Args... args) const noexcept {
|
void Signal<Error(Args...)>::emit(Args... args) const noexcept {
|
||||||
for (auto &f : m_slots) {
|
for (auto &f : m_slots) {
|
||||||
oxIgnoreError(f->call(args...));
|
std::ignore = f->call(ox::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
|
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
|
||||||
for (auto &f : m_slots) {
|
for (auto &f : m_slots) {
|
||||||
oxReturnError(f->call(args...));
|
oxReturnError(f->call(ox::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
2
deps/ox/src/ox/event/test/CMakeLists.txt
vendored
2
deps/ox/src/ox/event/test/CMakeLists.txt
vendored
@ -7,4 +7,4 @@ add_executable(
|
|||||||
|
|
||||||
target_link_libraries(EventTest OxEvent)
|
target_link_libraries(EventTest OxEvent)
|
||||||
|
|
||||||
add_test("[ox/event] Test 1" EventTest "test1")
|
add_test("[ox/event] Test 1" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/EventTest "test1")
|
||||||
|
18
deps/ox/src/ox/event/test/tests.cpp
vendored
18
deps/ox/src/ox/event/test/tests.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
@ -21,7 +21,7 @@ struct TestStruct: public ox::SignalHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, std::function<ox::Error()>> tests = {
|
std::map<ox::StringView, std::function<ox::Error()>> tests = {
|
||||||
{
|
{
|
||||||
"test1",
|
"test1",
|
||||||
[] {
|
[] {
|
||||||
@ -39,12 +39,14 @@ std::map<std::string, std::function<ox::Error()>> tests = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char **args) {
|
int main(int argc, const char **args) {
|
||||||
if (argc > 1) {
|
if (argc < 2) {
|
||||||
auto testName = args[1];
|
oxError("Must specify test to run");
|
||||||
if (tests.find(testName) != tests.end()) {
|
|
||||||
oxAssert(tests[testName](), "Test returned Error");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
auto const testName = args[1];
|
||||||
|
auto const func = tests.find(testName);
|
||||||
|
if (func != tests.end()) {
|
||||||
|
oxAssert(func->second(), "Test returned Error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
7
deps/ox/src/ox/fs/CMakeLists.txt
vendored
7
deps/ox/src/ox/fs/CMakeLists.txt
vendored
@ -16,12 +16,6 @@ if(NOT MSVC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT OX_BARE_METAL)
|
if(NOT OX_BARE_METAL)
|
||||||
if(NOT APPLE AND NOT MSVC)
|
|
||||||
target_link_libraries(
|
|
||||||
OxFS PUBLIC
|
|
||||||
stdc++fs
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
set_property(
|
set_property(
|
||||||
TARGET
|
TARGET
|
||||||
OxFS
|
OxFS
|
||||||
@ -44,7 +38,6 @@ if(NOT OX_BARE_METAL)
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
oxfs-tool
|
oxfs-tool
|
||||||
OxFS
|
OxFS
|
||||||
OxStd
|
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "filestoretemplate.hpp"
|
#include "filestoretemplate.hpp"
|
||||||
|
112
deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
vendored
112
deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -204,12 +204,12 @@ Error FileStoreTemplate<size_t>::format(void *buffer, std::size_t bufferSize) {
|
|||||||
auto nb = new (buffer) Buffer(static_cast<size_t>(bufferSize));
|
auto nb = new (buffer) Buffer(static_cast<size_t>(bufferSize));
|
||||||
auto fsData = nb->malloc(sizeof(FileStoreData)).value;
|
auto fsData = nb->malloc(sizeof(FileStoreData)).value;
|
||||||
if (!fsData.valid()) {
|
if (!fsData.valid()) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::format::fail", "Could not read data section of FileStoreData");
|
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
|
||||||
return OxError(1, "Could not read data section of FileStoreData");
|
return OxError(1, "Could not read data section of FileStoreData");
|
||||||
}
|
}
|
||||||
auto data = nb->template dataOf<FileStoreData>(fsData);
|
auto data = nb->template dataOf<FileStoreData>(fsData);
|
||||||
if (!data.valid()) {
|
if (!data.valid()) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::format::fail", "Could not read data section of FileStoreData");
|
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
|
||||||
return OxError(1, "Could not read data section of FileStoreData");
|
return OxError(1, "Could not read data section of FileStoreData");
|
||||||
}
|
}
|
||||||
new (data) FileStoreData;
|
new (data) FileStoreData;
|
||||||
@ -244,7 +244,7 @@ Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t dataSize, uint8_t fileType) {
|
Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t dataSize, uint8_t fileType) {
|
||||||
const auto id = static_cast<size_t>(id64);
|
const auto id = static_cast<size_t>(id64);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write", "Attempting to write to inode {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id);
|
||||||
auto existing = find(id);
|
auto existing = find(id);
|
||||||
if (!canWrite(existing, dataSize)) {
|
if (!canWrite(existing, dataSize)) {
|
||||||
oxReturnError(compact());
|
oxReturnError(compact());
|
||||||
@ -254,10 +254,10 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
|
|||||||
if (canWrite(existing, dataSize)) {
|
if (canWrite(existing, dataSize)) {
|
||||||
// delete the old node if it exists
|
// delete the old node if it exists
|
||||||
if (existing.valid()) {
|
if (existing.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write", "Freeing old version of inode found at offset: {}", existing.offset());
|
oxTracef("ox.fs.FileStoreTemplate.write", "Freeing old version of inode found at offset: {}", existing.offset());
|
||||||
auto err = m_buffer->free(existing);
|
auto err = m_buffer->free(existing);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::write::fail", "Free of old version of inode failed");
|
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Free of old version of inode failed");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
existing = nullptr;
|
existing = nullptr;
|
||||||
@ -266,12 +266,12 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
|
|||||||
auto dest = m_buffer->malloc(dataSize).value;
|
auto dest = m_buffer->malloc(dataSize).value;
|
||||||
// if first malloc failed, compact and try again
|
// if first malloc failed, compact and try again
|
||||||
if (!dest.valid()) {
|
if (!dest.valid()) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::write", "Allocation failed, compacting");
|
oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting");
|
||||||
oxReturnError(compact());
|
oxReturnError(compact());
|
||||||
dest = m_buffer->malloc(dataSize).value;
|
dest = m_buffer->malloc(dataSize).value;
|
||||||
}
|
}
|
||||||
if (dest.valid()) {
|
if (dest.valid()) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::write", "Memory allocated");
|
oxTrace("ox.fs.FileStoreTemplate.write", "Memory allocated");
|
||||||
dest->id = id;
|
dest->id = id;
|
||||||
dest->fileType = fileType;
|
dest->fileType = fileType;
|
||||||
auto destData = m_buffer->template dataOf<uint8_t>(dest);
|
auto destData = m_buffer->template dataOf<uint8_t>(dest);
|
||||||
@ -279,27 +279,27 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
|
|||||||
oxAssert(destData.size() == dataSize, "Allocation size does not match data.");
|
oxAssert(destData.size() == dataSize, "Allocation size does not match data.");
|
||||||
// write data if any was provided
|
// write data if any was provided
|
||||||
if (data != nullptr) {
|
if (data != nullptr) {
|
||||||
ox_memcpy(destData, data, dest->size());
|
ox::memcpy(destData, data, dest->size());
|
||||||
oxTrace("ox::fs::FileStoreTemplate::write", "Data written");
|
oxTrace("ox.fs.FileStoreTemplate.write", "Data written");
|
||||||
}
|
}
|
||||||
auto fsData = fileStoreData();
|
auto fsData = fileStoreData();
|
||||||
if (fsData) {
|
if (fsData) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write", "Searching for root node at {}", fsData->rootNode.get());
|
oxTracef("ox.fs.FileStoreTemplate.write", "Searching for root node at {}", fsData->rootNode.get());
|
||||||
auto root = m_buffer->ptr(fsData->rootNode);
|
auto root = m_buffer->ptr(fsData->rootNode);
|
||||||
if (root.valid()) {
|
if (root.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write",
|
oxTracef("ox.fs.FileStoreTemplate.write",
|
||||||
"Placing {} on {} at {}", dest->id.get(), root->id.get(), destData.offset());
|
"Placing {} on {} at {}", dest->id.get(), root->id.get(), destData.offset());
|
||||||
return placeItem(dest);
|
return placeItem(dest);
|
||||||
} else {
|
} else {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write",
|
oxTracef("ox.fs.FileStoreTemplate.write",
|
||||||
"Initializing root inode: {} (offset: {}, data size: {})",
|
"Initializing root inode: {} (offset: {}, data size: {})",
|
||||||
dest->id.get(), dest.offset(), destData.size());
|
dest->id.get(), dest.offset(), destData.size());
|
||||||
fsData->rootNode = dest.offset();
|
fsData->rootNode = dest.offset();
|
||||||
oxTracef("ox::fs::FileStoreTemplate::write", "Root inode: {}", dest->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::write::fail", "Could not place item due to absence of FileStore header.");
|
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,28 +315,28 @@ Error FileStoreTemplate<size_t>::remove(uint64_t id) {
|
|||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
|
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
|
||||||
auto src = find(static_cast<size_t>(id));
|
auto src = find(static_cast<size_t>(id));
|
||||||
// error check
|
// error check
|
||||||
if (!src.valid()) {
|
if (!src.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not find requested item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
|
||||||
return OxError(1, "Could not find requested item");
|
return OxError(1, "Could not find requested item");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}",
|
oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
|
||||||
id, src.offset(), srcData.offset());
|
id, src.offset(), srcData.offset());
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::outSize", "{} {} {}", srcData.offset(), srcData.size(), outSize);
|
oxTracef("ox.fs.FileStoreTemplate.read.outSize", "{} {} {}", srcData.offset(), srcData.size(), outSize);
|
||||||
|
|
||||||
// error check
|
// error check
|
||||||
if (!(srcData.valid() && srcData.size() <= outSize)) {
|
if (!(srcData.valid() && srcData.size() <= outSize)) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not read data section of item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail",
|
oxTracef("ox.fs.FileStoreTemplate.read.fail",
|
||||||
"Item data section size: {}, Expected size: {}", srcData.size(), outSize);
|
"Item data section size: {}, Expected size: {}", srcData.size(), outSize);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox_memcpy(out, srcData, srcData.size());
|
ox::memcpy(out, srcData, srcData.size());
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = src.size();
|
*size = src.size();
|
||||||
}
|
}
|
||||||
@ -346,28 +346,28 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
|
|||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t readSize, void *out, FsSize_t *size) const {
|
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t readSize, void *out, FsSize_t *size) const {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
|
||||||
auto src = find(static_cast<size_t>(id));
|
auto src = find(static_cast<size_t>(id));
|
||||||
// error check
|
// error check
|
||||||
if (!src.valid()) {
|
if (!src.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not find requested item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}",
|
oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
|
||||||
id, src.offset(), srcData.offset());
|
id, src.offset(), srcData.offset());
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
|
oxTracef("ox.fs.FileStoreTemplate.read.readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
|
||||||
|
|
||||||
// error check
|
// error check
|
||||||
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
|
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not read data section of item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail",
|
oxTracef("ox.fs.FileStoreTemplate.read.fail",
|
||||||
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
|
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox_memcpy(out, srcData.get() + readStart, readSize);
|
ox::memcpy(out, srcData.get() + readStart, readSize);
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = src.size();
|
*size = src.size();
|
||||||
}
|
}
|
||||||
@ -379,28 +379,28 @@ template<typename size_t>
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
|
Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
|
||||||
FsSize_t readSize, T *out, FsSize_t *size) const {
|
FsSize_t readSize, T *out, FsSize_t *size) const {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read", "Attempting to read from inode {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
|
||||||
auto src = find(static_cast<size_t>(id));
|
auto src = find(static_cast<size_t>(id));
|
||||||
// error check
|
// error check
|
||||||
if (!src.valid()) {
|
if (!src.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not find requested item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::found", "{} found at {} with data section at {}",
|
oxTracef("ox.fs.FileStoreTemplate.read.found", "{} found at {} with data section at {}",
|
||||||
id, src.offset(), srcData.offset());
|
id, src.offset(), srcData.offset());
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
|
oxTracef("ox.fs.FileStoreTemplate.read.readSize", "{} {} {}", srcData.offset(), srcData.size(), readSize);
|
||||||
|
|
||||||
// error check
|
// error check
|
||||||
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
|
if (!(srcData.valid() && srcData.size() - readStart <= readSize)) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not read data section of item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail",
|
oxTracef("ox.fs.FileStoreTemplate.read.fail",
|
||||||
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
|
"Item data section size: {}, Expected size: {}", srcData.size(), readSize);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox_memcpy(out, srcData.get() + readStart, readSize);
|
ox::memcpy(out, srcData.get() + readStart, readSize);
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = src.size();
|
*size = src.size();
|
||||||
}
|
}
|
||||||
@ -422,9 +422,9 @@ template<typename size_t>
|
|||||||
Error FileStoreTemplate<size_t>::resize() {
|
Error FileStoreTemplate<size_t>::resize() {
|
||||||
oxReturnError(compact());
|
oxReturnError(compact());
|
||||||
const auto newSize = static_cast<std::size_t>(size() - available());
|
const auto newSize = static_cast<std::size_t>(size() - available());
|
||||||
oxTracef("ox::fs::FileStoreTemplate::resize", "resize to: {}", newSize);
|
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
|
||||||
oxReturnError(m_buffer->setSize(newSize));
|
oxReturnError(m_buffer->setSize(newSize));
|
||||||
oxTracef("ox::fs::FileStoreTemplate::resize", "resized to: {}", m_buffer->size());
|
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +506,7 @@ Error FileStoreTemplate<size_t>::compact() {
|
|||||||
if (!item.valid()) {
|
if (!item.valid()) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
oxTracef("ox::fs::FileStoreTemplate::compact::moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset());
|
oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset());
|
||||||
// update rootInode if this is it
|
// update rootInode if this is it
|
||||||
auto fsData = fileStoreData();
|
auto fsData = fileStoreData();
|
||||||
if (fsData && oldAddr == fsData->rootNode) {
|
if (fsData && oldAddr == fsData->rootNode) {
|
||||||
@ -549,7 +549,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
|
|||||||
fsData->rootNode = item;
|
fsData->rootNode = item;
|
||||||
item->left = root->left;
|
item->left = root->left;
|
||||||
item->right = root->right;
|
item->right = root->right;
|
||||||
oxTracef("ox::fs::FileStoreTemplate::placeItem", "Overwrote Root Item: {}", item->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
} else {
|
} else {
|
||||||
return placeItem(root, item);
|
return placeItem(root, item);
|
||||||
@ -559,7 +559,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
|
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
|
||||||
if (depth > 5000) {
|
if (depth > 5000) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail", "Excessive recursion depth, stopping before stack overflow.");
|
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow.");
|
||||||
return OxError(2);
|
return OxError(2);
|
||||||
}
|
}
|
||||||
if (item->id > root->id) {
|
if (item->id > root->id) {
|
||||||
@ -570,7 +570,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
|
|||||||
item->left = right->left;
|
item->left = right->left;
|
||||||
item->right = right->right;
|
item->right = right->right;
|
||||||
}
|
}
|
||||||
oxTracef("ox::fs::FileStoreTemplate::placeItem", "Placed Item: {}", item->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
} else {
|
} else {
|
||||||
return placeItem(right, item, depth + 1);
|
return placeItem(right, item, depth + 1);
|
||||||
@ -583,13 +583,13 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
|
|||||||
item->left = left->left;
|
item->left = left->left;
|
||||||
item->right = left->right;
|
item->right = left->right;
|
||||||
}
|
}
|
||||||
oxTracef("ox::fs::FileStoreTemplate::placeItem", "Placed Item: {}", item->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
} else {
|
} else {
|
||||||
return placeItem(left, item, depth + 1);
|
return placeItem(left, item, depth + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail", "Cannot insert an item on itself.");
|
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself.");
|
||||||
return OxError(1, "Cannot insert an item on itself.");
|
return OxError(1, "Cannot insert an item on itself.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,14 +631,14 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
|
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
|
||||||
if (depth >= 5000) {
|
if (depth >= 5000) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail", "Excessive recursion depth, stopping before stack overflow.");
|
oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow.");
|
||||||
return OxError(1, "Excessive recursion depth, stopping before stack overflow.");
|
return OxError(1, "Excessive recursion depth, stopping before stack overflow.");
|
||||||
}
|
}
|
||||||
if (item->id > root->id) {
|
if (item->id > root->id) {
|
||||||
auto right = m_buffer->ptr(root->right);
|
auto right = m_buffer->ptr(root->right);
|
||||||
if (right->id == item->id) {
|
if (right->id == item->id) {
|
||||||
root->right = 0;
|
root->right = 0;
|
||||||
oxTracef("ox::fs::FileStoreTemplate::unplaceItem", "Unplaced Item: {}", item->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.unplaceItem", "Unplaced Item: {}", item->id.get());
|
||||||
} else {
|
} else {
|
||||||
return unplaceItem(right, item, depth + 1);
|
return unplaceItem(right, item, depth + 1);
|
||||||
}
|
}
|
||||||
@ -646,7 +646,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
|
|||||||
auto left = m_buffer->ptr(root->left);
|
auto left = m_buffer->ptr(root->left);
|
||||||
if (left->id == item->id) {
|
if (left->id == item->id) {
|
||||||
root->left = 0;
|
root->left = 0;
|
||||||
oxTracef("ox::fs::FileStoreTemplate::unplaceItem", "Unplaced Item: {}", item->id.get());
|
oxTracef("ox.fs.FileStoreTemplate.unplaceItem", "Unplaced Item: {}", item->id.get());
|
||||||
} else {
|
} else {
|
||||||
return unplaceItem(left, item, depth + 1);
|
return unplaceItem(left, item, depth + 1);
|
||||||
}
|
}
|
||||||
@ -701,22 +701,22 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::findParen
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(ItemPtr item, InodeId_t id, int depth) const {
|
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(ItemPtr item, InodeId_t id, int depth) const {
|
||||||
if (depth > 5000) {
|
if (depth > 5000) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::find::fail", "Excessive recursion depth, stopping before stack overflow. Search for: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.find.fail", "Excessive recursion depth, stopping before stack overflow. Search for: {}", id);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!item.valid()) {
|
if (!item.valid()) {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::find::fail", "item invalid");
|
oxTrace("ox.fs.FileStoreTemplate.find.fail", "item invalid");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// do search
|
// do search
|
||||||
if (id > item->id) {
|
if (id > item->id) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::find", "Not a match, searching on {}", item->right.get());
|
oxTracef("ox.fs.FileStoreTemplate.find", "Not a match, searching on {}", item->right.get());
|
||||||
return find(m_buffer->ptr(item->right), id, depth + 1);
|
return find(m_buffer->ptr(item->right), id, depth + 1);
|
||||||
} else if (id < item->id) {
|
} else if (id < item->id) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::find", "Not a match, searching on {}", item->left.get());
|
oxTracef("ox.fs.FileStoreTemplate.find", "Not a match, searching on {}", item->left.get());
|
||||||
return find(m_buffer->ptr(item->left), id, depth + 1);
|
return find(m_buffer->ptr(item->left), id, depth + 1);
|
||||||
} else if (id == item->id) {
|
} else if (id == item->id) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::find", "Found {} at {}", id, item.offset());
|
oxTracef("ox.fs.FileStoreTemplate.find", "Found {} at {}", id, item.offset());
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -724,7 +724,7 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(Item
|
|||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(InodeId_t id) const {
|
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(InodeId_t id) const {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::find", "Searching for inode: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.find", "Searching for inode: {}", id);
|
||||||
auto fsData = fileStoreData();
|
auto fsData = fileStoreData();
|
||||||
if (fsData) {
|
if (fsData) {
|
||||||
auto root = m_buffer->ptr(fsData->rootNode);
|
auto root = m_buffer->ptr(fsData->rootNode);
|
||||||
@ -732,10 +732,10 @@ typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::find(Inod
|
|||||||
auto item = find(root, id);
|
auto item = find(root, id);
|
||||||
return item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::find::fail", "No root node");
|
oxTrace("ox.fs.FileStoreTemplate.find.fail", "No root node");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::FileStoreTemplate::find::fail", "No FileStore Data");
|
oxTrace("ox.fs.FileStoreTemplate.find.fail", "No FileStore Data");
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
4
deps/ox/src/ox/fs/filesystem/directory.cpp
vendored
4
deps/ox/src/ox/fs/filesystem/directory.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "directory.hpp"
|
#include "directory.hpp"
|
||||||
|
76
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
76
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -48,14 +48,14 @@ struct OX_PACKED DirectoryEntry {
|
|||||||
auto d = data();
|
auto d = data();
|
||||||
if (d.valid()) {
|
if (d.valid()) {
|
||||||
d->inode = inode;
|
d->inode = inode;
|
||||||
ox_strncpy(d->name, name, ox::min(bufferSize, static_cast<InodeId_t>(MaxFileNameLength)));
|
ox::strncpy(d->name, name, ox::min(bufferSize, static_cast<InodeId_t>(MaxFileNameLength)));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
|
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
|
||||||
oxTracef("ox::fs::DirectoryEntry::data", "{} {} {}", this->fullSize(), sizeof(*this), this->size());
|
oxTracef("ox.fs.DirectoryEntry.data", "{} {} {}", this->fullSize(), sizeof(*this), this->size());
|
||||||
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size(), this->size());
|
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size(), this->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ Directory<FileStore, InodeId_t>::Directory(FileStore fs, uint64_t inodeId) noexc
|
|||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Error Directory<FileStore, InodeId_t>::init() noexcept {
|
Error Directory<FileStore, InodeId_t>::init() noexcept {
|
||||||
constexpr auto Size = sizeof(Buffer);
|
constexpr auto Size = sizeof(Buffer);
|
||||||
oxTracef("ox::fs::Directory::init", "Initializing Directory with Inode ID: {}", m_inodeId);
|
oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId);
|
||||||
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory)));
|
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory)));
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (!buff.valid()) {
|
if (!buff.valid()) {
|
||||||
@ -151,7 +151,7 @@ Error Directory<FileStore, InodeId_t>::init() noexcept {
|
|||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
|
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
|
||||||
if (path.valid()) {
|
if (path.valid()) {
|
||||||
oxTrace("ox::fs::Directory::mkdir", path.fullPath());
|
oxTrace("ox.fs.Directory.mkdir", path.fullPath());
|
||||||
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
||||||
if (nameBuff == nullptr) {
|
if (nameBuff == nullptr) {
|
||||||
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
@ -159,7 +159,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, Fi
|
|||||||
|
|
||||||
// determine if already exists
|
// determine if already exists
|
||||||
auto name = nameBuff;
|
auto name = nameBuff;
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(*name));
|
||||||
auto childInode = find(PathIterator(*name));
|
auto childInode = find(PathIterator(*name));
|
||||||
if (!childInode.ok()) {
|
if (!childInode.ok()) {
|
||||||
// if this is not the last item in the path and parents is disabled,
|
// if this is not the last item in the path and parents is disabled,
|
||||||
@ -168,7 +168,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, Fi
|
|||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
childInode = m_fs.generateInodeId();
|
childInode = m_fs.generateInodeId();
|
||||||
oxTracef("ox::fs::Directory::mkdir", "Generated Inode ID: {}", childInode.value);
|
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
|
||||||
oxLogError(childInode.error);
|
oxLogError(childInode.error);
|
||||||
oxReturnError(childInode.error);
|
oxReturnError(childInode.error);
|
||||||
|
|
||||||
@ -203,34 +203,34 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
|
|||||||
auto name = nameBuff;
|
auto name = nameBuff;
|
||||||
|
|
||||||
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
|
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(*name));
|
||||||
oxTracef("ox::fs::Directory::write", "Attempting to write to next sub-Directory: {} of {}",
|
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
|
||||||
*name, path.fullPath());
|
*name, path.fullPath());
|
||||||
oxRequire(nextChild, findEntry(*name));
|
oxRequire(nextChild, findEntry(*name));
|
||||||
oxTracef("ox::fs::Directory::write", "{}: {}", *name, nextChild);
|
oxTracef("ox.fs.Directory.write", "{}: {}", *name, nextChild);
|
||||||
if (nextChild) {
|
if (nextChild) {
|
||||||
// reuse name because it is a rather large variable and will not be used again
|
// reuse name because it is a rather large variable and will not be used again
|
||||||
// be attentive that this remains true
|
// be attentive that this remains true
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
|
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
|
||||||
} else {
|
} else {
|
||||||
oxTracef("ox::fs::Directory::write", "{} not found and not allowed to create it.", *name);
|
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", *name);
|
||||||
return OxError(1, "File not found and not allowed to create it.");
|
return OxError(1, "File not found and not allowed to create it.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::Directory::write", path.fullPath());
|
oxTrace("ox.fs.Directory.write", path.fullPath());
|
||||||
// insert the new entry on this directory
|
// insert the new entry on this directory
|
||||||
|
|
||||||
// get the name
|
// get the name
|
||||||
oxReturnError(path.next(name));
|
oxReturnError(path.next(*name));
|
||||||
|
|
||||||
// find existing version of directory
|
// find existing version of directory
|
||||||
oxTracef("ox::fs::Directory::write", "Searching for directory inode {}", m_inodeId);
|
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
|
||||||
oxRequire(oldStat, m_fs.stat(m_inodeId));
|
oxRequire(oldStat, m_fs.stat(m_inodeId));
|
||||||
oxTracef("ox::fs::Directory::write", "Found existing directory of size {}", oldStat.size);
|
oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size);
|
||||||
auto old = m_fs.read(m_inodeId).template to<Buffer>();
|
auto old = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (!old.valid()) {
|
if (!old.valid()) {
|
||||||
oxTrace("ox::fs::Directory::write::fail", "Could not read existing version of Directory");
|
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
|
||||||
return OxError(1, "Could not read existing version of Directory");
|
return OxError(1, "Could not read existing version of Directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,20 +239,20 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
|
|||||||
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
|
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
|
||||||
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
|
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
|
||||||
if (cpy == nullptr) {
|
if (cpy == nullptr) {
|
||||||
oxTrace("ox::fs::Directory::write::fail", "Could not allocate memory for copy of Directory");
|
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
|
||||||
return OxError(1, "Could not allocate memory for copy of Directory");
|
return OxError(1, "Could not allocate memory for copy of Directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
oxReturnError(cpy->setSize(newSize));
|
oxReturnError(cpy->setSize(newSize));
|
||||||
auto val = cpy->malloc(entryDataSize).value;
|
auto val = cpy->malloc(entryDataSize).value;
|
||||||
if (!val.valid()) {
|
if (!val.valid()) {
|
||||||
oxTrace("ox::fs::Directory::write::fail", "Could not allocate memory for new directory entry");
|
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
|
||||||
return OxError(1, "Could not allocate memory for new directory entry");
|
return OxError(1, "Could not allocate memory for new directory entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
oxTracef("ox::fs::Directory::write", "Attempting to write Directory entry: {}", name->data());
|
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name->data());
|
||||||
oxReturnError(val->init(inode, name->data(), val.size()));
|
oxReturnError(val->init(inode, name->data(), val.size()));
|
||||||
return m_fs.write(m_inodeId, cpy, cpy->size(), static_cast<uint8_t>(FileType::Directory));
|
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,12 +263,12 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
|
|||||||
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
}
|
}
|
||||||
auto &name = *nameBuff;
|
auto &name = *nameBuff;
|
||||||
oxReturnError(path.get(&name));
|
oxReturnError(path.get(name));
|
||||||
|
|
||||||
oxTrace("ox::fs::Directory::remove", name);
|
oxTrace("ox.fs.Directory.remove", name);
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (buff.valid()) {
|
if (buff.valid()) {
|
||||||
oxTrace("ox::fs::Directory::remove", "Found directory buffer.");
|
oxTrace("ox.fs.Directory.remove", "Found directory buffer.");
|
||||||
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
||||||
auto data = i->data();
|
auto data = i->data();
|
||||||
if (data.valid()) {
|
if (data.valid()) {
|
||||||
@ -276,11 +276,11 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
|
|||||||
oxReturnError(buff->free(i));
|
oxReturnError(buff->free(i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::Directory::remove", "INVALID DIRECTORY ENTRY");
|
oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::Directory::remove::fail", "Could not find directory buffer");
|
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
|
||||||
return OxError(1, "Could not find directory buffer");
|
return OxError(1, "Could not find directory buffer");
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -289,20 +289,20 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
|
|||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
template<typename F>
|
template<typename F>
|
||||||
Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
|
Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
|
||||||
oxTrace("ox::fs::Directory::ls");
|
oxTrace("ox.fs.Directory.ls");
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (!buff.valid()) {
|
if (!buff.valid()) {
|
||||||
oxTrace("ox::fs::Directory::ls::fail", "Could not directory buffer");
|
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
|
||||||
return OxError(1, "Could not directory buffer");
|
return OxError(1, "Could not directory buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
oxTrace("ox::fs::Directory::ls", "Found directory buffer.");
|
oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
|
||||||
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
||||||
auto data = i->data();
|
auto data = i->data();
|
||||||
if (data.valid()) {
|
if (data.valid()) {
|
||||||
oxReturnError(cb(data->name, data->inode));
|
oxReturnError(cb(data->name, data->inode));
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::Directory::ls", "INVALID DIRECTORY ENTRY");
|
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,26 +311,26 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
|
|||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
|
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
|
||||||
oxTrace("ox::fs::Directory::findEntry", name);
|
oxTrace("ox.fs.Directory.findEntry", name);
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (!buff.valid()) {
|
if (!buff.valid()) {
|
||||||
oxTrace("ox::fs::Directory::findEntry::fail", "Could not findEntry directory buffer");
|
oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer");
|
||||||
return OxError(2, "Could not findEntry directory buffer");
|
return OxError(2, "Could not findEntry directory buffer");
|
||||||
}
|
}
|
||||||
oxTracef("ox::fs::Directory::findEntry", "Found directory buffer, size: {}", buff.size());
|
oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size());
|
||||||
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
||||||
auto data = i->data();
|
auto data = i->data();
|
||||||
if (data.valid()) {
|
if (data.valid()) {
|
||||||
oxTracef("ox::fs::Directory::findEntry", "Comparing \"{}\" to \"{}\"", name, data->name);
|
oxTracef("ox.fs.Directory.findEntry", "Comparing \"{}\" to \"{}\"", name, data->name);
|
||||||
if (name == data->name) {
|
if (name == data->name) {
|
||||||
oxTracef("ox::fs::Directory::findEntry", "\"{}\" match found.", name);
|
oxTracef("ox.fs.Directory.findEntry", "\"{}\" match found.", name);
|
||||||
return static_cast<InodeId_t>(data->inode);
|
return static_cast<InodeId_t>(data->inode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::fs::Directory::findEntry") << "INVALID DIRECTORY ENTRY";
|
oxTrace("ox.fs.Directory.findEntry") << "INVALID DIRECTORY ENTRY";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oxTrace("ox::fs::Directory::findEntry::fail", "Entry not present");
|
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
|
||||||
return OxError(1, "Entry not present");
|
return OxError(1, "Entry not present");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(Path
|
|||||||
|
|
||||||
// determine if already exists
|
// determine if already exists
|
||||||
auto name = nameBuff;
|
auto name = nameBuff;
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(*name));
|
||||||
|
|
||||||
oxRequire(v, findEntry(*name));
|
oxRequire(v, findEntry(*name));
|
||||||
// recurse if not at end of path
|
// recurse if not at end of path
|
||||||
|
46
deps/ox/src/ox/fs/filesystem/filelocation.cpp
vendored
46
deps/ox/src/ox/fs/filesystem/filelocation.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/model/modelops.hpp>
|
#include <ox/model/modelops.hpp>
|
||||||
@ -36,13 +36,6 @@ FileAddress::FileAddress(ox::CRStringView path) noexcept {
|
|||||||
m_type = FileAddressType::Path;
|
m_type = FileAddressType::Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAddress::FileAddress(char *path) noexcept {
|
|
||||||
auto pathSize = ox_strlen(path) + 1;
|
|
||||||
m_data.path = new char[pathSize];
|
|
||||||
memcpy(m_data.path, path, pathSize);
|
|
||||||
m_type = FileAddressType::Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return *this;
|
return *this;
|
||||||
@ -52,9 +45,14 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
|||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FileAddressType::Path:
|
case FileAddressType::Path:
|
||||||
{
|
{
|
||||||
auto strSize = ox_strlen(other.m_data.path) + 1;
|
if (other.m_data.path) {
|
||||||
|
auto strSize = ox::strlen(other.m_data.path) + 1;
|
||||||
m_data.path = new char[strSize];
|
m_data.path = new char[strSize];
|
||||||
ox_memcpy(m_data.path, other.m_data.path, strSize);
|
ox::memcpy(m_data.path, other.m_data.path, strSize);
|
||||||
|
} else {
|
||||||
|
m_data.constPath = "";
|
||||||
|
m_type = FileAddressType::ConstPath;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FileAddressType::ConstPath:
|
case FileAddressType::ConstPath:
|
||||||
@ -90,6 +88,32 @@ FileAddress &FileAddress::operator=(FileAddress &&other) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileAddress::operator==(FileAddress const&other) const noexcept {
|
||||||
|
if (m_type != other.m_type) {
|
||||||
|
auto const aIsPath =
|
||||||
|
m_type == FileAddressType::Path || m_type == FileAddressType::ConstPath;
|
||||||
|
auto const bIsPath =
|
||||||
|
other.m_type == FileAddressType::Path || other.m_type == FileAddressType::ConstPath;
|
||||||
|
if (!(aIsPath && bIsPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (m_type) {
|
||||||
|
case FileAddressType::ConstPath:
|
||||||
|
case FileAddressType::Path: {
|
||||||
|
auto const a = getPath();
|
||||||
|
auto const b = other.getPath();
|
||||||
|
return (other.m_type == FileAddressType::ConstPath || other.m_type == FileAddressType::Path)
|
||||||
|
&& (a.value == b.value);
|
||||||
|
}
|
||||||
|
case FileAddressType::Inode:
|
||||||
|
return m_data.inode == other.m_data.inode;
|
||||||
|
case FileAddressType::None:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileAddress::operator==(CRStringView path) const noexcept {
|
bool FileAddress::operator==(CRStringView path) const noexcept {
|
||||||
auto [p, err] = getPath();
|
auto [p, err] = getPath();
|
||||||
if (err) {
|
if (err) {
|
||||||
|
113
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
113
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -22,10 +22,13 @@ enum class FileAddressType: int8_t {
|
|||||||
Inode,
|
Inode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept;
|
||||||
|
|
||||||
class FileAddress {
|
class FileAddress {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
friend constexpr Error model(T*, CommonPtrWith<FileAddress> auto*) noexcept;
|
friend constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
|
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
|
||||||
@ -41,13 +44,10 @@ class FileAddress {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileAddressType m_type = FileAddressType::None;
|
FileAddressType m_type = FileAddressType::None;
|
||||||
Data m_data;
|
Data m_data{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FileAddress() noexcept {
|
constexpr FileAddress() noexcept = default;
|
||||||
m_data.inode = 0;
|
|
||||||
m_type = FileAddressType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAddress(const FileAddress &other) noexcept;
|
FileAddress(const FileAddress &other) noexcept;
|
||||||
|
|
||||||
@ -59,13 +59,7 @@ class FileAddress {
|
|||||||
|
|
||||||
explicit FileAddress(CRStringView path) noexcept;
|
explicit FileAddress(CRStringView path) noexcept;
|
||||||
|
|
||||||
template<std::size_t SmallStrSz>
|
constexpr FileAddress(ox::StringLiteral path) noexcept;
|
||||||
explicit FileAddress(const ox::BasicString<SmallStrSz> &path) noexcept: FileAddress(StringView(path)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit FileAddress(char *path) noexcept;
|
|
||||||
|
|
||||||
explicit constexpr FileAddress(const char *path) noexcept;
|
|
||||||
|
|
||||||
constexpr ~FileAddress() noexcept;
|
constexpr ~FileAddress() noexcept;
|
||||||
|
|
||||||
@ -73,6 +67,8 @@ class FileAddress {
|
|||||||
|
|
||||||
FileAddress &operator=(FileAddress &&other) noexcept;
|
FileAddress &operator=(FileAddress &&other) noexcept;
|
||||||
|
|
||||||
|
bool operator==(const FileAddress &other) const noexcept;
|
||||||
|
|
||||||
bool operator==(CRStringView path) const noexcept;
|
bool operator==(CRStringView path) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -86,7 +82,6 @@ class FileAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr Result<uint64_t> getInode() const noexcept {
|
constexpr Result<uint64_t> getInode() const noexcept {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FileAddressType::Inode:
|
case FileAddressType::Inode:
|
||||||
@ -96,12 +91,12 @@ class FileAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Result<const char*> getPath() const noexcept {
|
constexpr Result<ox::CStringView> getPath() const noexcept {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FileAddressType::Path:
|
case FileAddressType::Path:
|
||||||
return m_data.path;
|
return ox::CStringView(m_data.path);
|
||||||
case FileAddressType::ConstPath:
|
case FileAddressType::ConstPath:
|
||||||
return m_data.constPath;
|
return ox::CStringView(m_data.constPath);
|
||||||
default:
|
default:
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
@ -124,8 +119,8 @@ class FileAddress {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr FileAddress::FileAddress(const char *path) noexcept {
|
constexpr FileAddress::FileAddress(ox::StringLiteral path) noexcept {
|
||||||
m_data.constPath = path;
|
m_data.constPath = path.c_str();
|
||||||
m_type = FileAddressType::ConstPath;
|
m_type = FileAddressType::ConstPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,45 +128,6 @@ constexpr FileAddress::~FileAddress() noexcept {
|
|||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
|
||||||
return FileAddress::Data::TypeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
|
||||||
return FileAddress::TypeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
|
||||||
oxReturnError(io->template setTypeInfo<FileAddress::Data>());
|
|
||||||
oxReturnError(io->fieldCString("path", &obj->path));
|
|
||||||
oxReturnError(io->fieldCString("constPath", &obj->path));
|
|
||||||
oxReturnError(io->field("inode", &obj->inode));
|
|
||||||
return OxError(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
|
||||||
oxReturnError(io->template setTypeInfo<FileAddress>());
|
|
||||||
if constexpr(T::opType() == OpType::Reflect) {
|
|
||||||
int8_t type = 0;
|
|
||||||
oxReturnError(io->field("type", &type));
|
|
||||||
oxReturnError(io->field("data", UnionView(&fa->m_data, 0)));
|
|
||||||
} else if constexpr(T::opType() == OpType::Read) {
|
|
||||||
auto type = static_cast<int8_t>(fa->m_type);
|
|
||||||
oxReturnError(io->field("type", &type));
|
|
||||||
fa->m_type = static_cast<FileAddressType>(type);
|
|
||||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
|
||||||
} else if constexpr(T::opType() == OpType::Write) {
|
|
||||||
auto type = static_cast<int8_t>(fa->m_type);
|
|
||||||
oxReturnError(io->field("type", &type));
|
|
||||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
|
||||||
}
|
|
||||||
return OxError(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr void FileAddress::cleanup() noexcept {
|
constexpr void FileAddress::cleanup() noexcept {
|
||||||
if (m_type == FileAddressType::Path) {
|
if (m_type == FileAddressType::Path) {
|
||||||
safeDeleteArray(m_data.path);
|
safeDeleteArray(m_data.path);
|
||||||
@ -184,4 +140,43 @@ constexpr void FileAddress::clear() noexcept {
|
|||||||
m_type = FileAddressType::None;
|
m_type = FileAddressType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
||||||
|
return FileAddress::Data::TypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||||
|
return FileAddress::TypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||||
|
oxReturnError(h->template setTypeInfo<FileAddress::Data>());
|
||||||
|
oxReturnError(h->fieldCString("path", &obj->path));
|
||||||
|
oxReturnError(h->fieldCString("constPath", &obj->path));
|
||||||
|
oxReturnError(h->field("inode", &obj->inode));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||||
|
oxReturnError(h->template setTypeInfo<FileAddress>());
|
||||||
|
if constexpr(T::opType() == OpType::Reflect) {
|
||||||
|
int8_t type = -1;
|
||||||
|
oxReturnError(h->field("type", &type));
|
||||||
|
oxReturnError(h->field("data", UnionView(&fa->m_data, type)));
|
||||||
|
} else if constexpr(T::opType() == OpType::Read) {
|
||||||
|
auto type = static_cast<int8_t>(fa->m_type);
|
||||||
|
oxReturnError(h->field("type", &type));
|
||||||
|
fa->m_type = static_cast<FileAddressType>(type);
|
||||||
|
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||||
|
} else if constexpr(T::opType() == OpType::Write) {
|
||||||
|
auto const type = static_cast<int8_t>(fa->m_type);
|
||||||
|
oxReturnError(h->field("type", &type));
|
||||||
|
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
deps/ox/src/ox/fs/filesystem/filesystem.cpp
vendored
4
deps/ox/src/ox/fs/filesystem/filesystem.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
|
30
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
30
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -1,14 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
|
#include <ox/std/span.hpp>
|
||||||
|
|
||||||
#include <ox/fs/filestore/filestoretemplate.hpp>
|
#include <ox/fs/filestore/filestoretemplate.hpp>
|
||||||
#include <ox/fs/filesystem/filelocation.hpp>
|
#include <ox/fs/filesystem/filelocation.hpp>
|
||||||
@ -66,10 +67,18 @@ class FileSystem {
|
|||||||
return writeFilePath(path, buffer, size, FileType::NormalFile);
|
return writeFilePath(path, buffer, size, FileType::NormalFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error write(CRStringView path, ox::Span<char> const&buff) noexcept {
|
||||||
|
return write(path, buff.data(), buff.size(), FileType::NormalFile);
|
||||||
|
}
|
||||||
|
|
||||||
Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept {
|
Error write(uint64_t inode, const void *buffer, uint64_t size) noexcept {
|
||||||
return write(inode, buffer, size, FileType::NormalFile);
|
return write(inode, buffer, size, FileType::NormalFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept {
|
||||||
|
return write(inode, buff.data(), buff.size(), FileType::NormalFile);
|
||||||
|
}
|
||||||
|
|
||||||
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
||||||
|
|
||||||
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
inline Error write(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
@ -165,6 +174,8 @@ class FileSystemTemplate: public MemFS {
|
|||||||
|
|
||||||
FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*) = detail::fsBuffFree) noexcept;
|
FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*) = detail::fsBuffFree) noexcept;
|
||||||
|
|
||||||
|
explicit FileSystemTemplate(ox::Buffer &buffer) noexcept;
|
||||||
|
|
||||||
explicit FileSystemTemplate(FileStore fs) noexcept;
|
explicit FileSystemTemplate(FileStore fs) noexcept;
|
||||||
|
|
||||||
~FileSystemTemplate() noexcept override;
|
~FileSystemTemplate() noexcept override;
|
||||||
@ -238,6 +249,11 @@ FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(FileStore fs) noexc
|
|||||||
m_fs = fs;
|
m_fs = fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename FileStore, typename Directory>
|
||||||
|
FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(ox::Buffer &buffer) noexcept:
|
||||||
|
m_fs(buffer.data(), static_cast<std::size_t>(buffer.size())) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*)) noexcept:
|
FileSystemTemplate<FileStore, Directory>::FileSystemTemplate(void *buffer, uint64_t bufferSize, void(*freeBuffer)(char*)) noexcept:
|
||||||
m_fs(buffer, static_cast<std::size_t>(bufferSize)),
|
m_fs(buffer, static_cast<std::size_t>(bufferSize)),
|
||||||
@ -262,11 +278,11 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
|
|||||||
|
|
||||||
FileSystemData fd;
|
FileSystemData fd;
|
||||||
fd.rootDirInode = rootDirInode;
|
fd.rootDirInode = rootDirInode;
|
||||||
oxTracef("ox::fs::FileSystemTemplate::format", "rootDirInode: {}", fd.rootDirInode.get());
|
oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get());
|
||||||
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd)));
|
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd)));
|
||||||
|
|
||||||
if (!fs.read(fd.rootDirInode).valid()) {
|
if (!fs.read(fd.rootDirInode).valid()) {
|
||||||
oxTrace("ox::fs::FileSystemTemplate::format::error", "FileSystemTemplate::format did not correctly create root directory");
|
oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory");
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +291,7 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
|
|||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::mkdir(CRStringView path, bool recursive) noexcept {
|
Error FileSystemTemplate<FileStore, Directory>::mkdir(CRStringView path, bool recursive) noexcept {
|
||||||
oxTracef("ox::fs::FileSystemTemplate::mkdir", "path: {}, recursive: {}", path, recursive);
|
oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive);
|
||||||
oxRequireM(rootDir, this->rootDir());
|
oxRequireM(rootDir, this->rootDir());
|
||||||
return rootDir.mkdir(path, recursive);
|
return rootDir.mkdir(path, recursive);
|
||||||
}
|
}
|
||||||
@ -345,7 +361,7 @@ Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(CRStringView
|
|||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
template<typename F>
|
template<typename F>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::ls(CRStringView path, F cb) const {
|
Error FileSystemTemplate<FileStore, Directory>::ls(CRStringView path, F cb) const {
|
||||||
oxTracef("ox::fs::FileSystemTemplate::ls", "path: {}", path);
|
oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
|
||||||
oxRequire(s, stat(path));
|
oxRequire(s, stat(path));
|
||||||
Directory dir(m_fs, s.inode);
|
Directory dir(m_fs, s.inode);
|
||||||
return dir.ls(cb);
|
return dir.ls(cb);
|
||||||
@ -364,7 +380,7 @@ Error FileSystemTemplate<FileStore, Directory>::remove(CRStringView path, bool r
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("FileSystemTemplate::remove::fail", "Tried to remove directory without recursive setting.");
|
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
|
24
deps/ox/src/ox/fs/filesystem/passthroughfs.cpp
vendored
24
deps/ox/src/ox/fs/filesystem/passthroughfs.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
@ -24,14 +24,14 @@ PassThroughFS::PassThroughFS(CRStringView dirPath) {
|
|||||||
PassThroughFS::~PassThroughFS() noexcept = default;
|
PassThroughFS::~PassThroughFS() noexcept = default;
|
||||||
|
|
||||||
String PassThroughFS::basePath() const noexcept {
|
String PassThroughFS::basePath() const noexcept {
|
||||||
return m_path.string().c_str();
|
return ox::String(m_path.string().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
|
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
const auto p = m_path / stripSlash(path);
|
const auto p = m_path / stripSlash(path);
|
||||||
const auto u8p = p.u8string();
|
const auto u8p = p.u8string();
|
||||||
oxTrace("ox::fs::PassThroughFS::mkdir", std::bit_cast<const char*>(u8p.c_str()));
|
oxTrace("ox.fs.PassThroughFS.mkdir", std::bit_cast<const char*>(u8p.c_str()));
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
const auto isDir = std::filesystem::is_directory(p, ec);
|
const auto isDir = std::filesystem::is_directory(p, ec);
|
||||||
@ -98,10 +98,10 @@ Result<FileStat> PassThroughFS::statPath(CRStringView path) const noexcept {
|
|||||||
const auto p = m_path / stripSlash(path);
|
const auto p = m_path / stripSlash(path);
|
||||||
const FileType type = std::filesystem::is_directory(p, ec) ?
|
const FileType type = std::filesystem::is_directory(p, ec) ?
|
||||||
FileType::Directory : FileType::NormalFile;
|
FileType::Directory : FileType::NormalFile;
|
||||||
oxTracef("ox::fs::PassThroughFS::statInode", "{} {}", ec.message(), path);
|
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
|
||||||
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
|
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
|
||||||
oxTracef("ox::fs::PassThroughFS::statInode", "{} {}", ec.message(), path);
|
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
|
||||||
oxTracef("ox::fs::PassThroughFS::statInode::size", "{} {}", path, size);
|
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
|
||||||
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
|
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
|
||||||
return FileStat{0, 0, size, type};
|
return FileStat{0, 0, size, type};
|
||||||
}
|
}
|
||||||
@ -147,12 +147,12 @@ Error PassThroughFS::readFilePath(CRStringView path, void *buffer, std::size_t b
|
|||||||
const std::size_t size = static_cast<std::size_t>(file.tellg());
|
const std::size_t size = static_cast<std::size_t>(file.tellg());
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
if (size > buffSize) {
|
if (size > buffSize) {
|
||||||
oxTracef("ox::fs::PassThroughFS::read::error", "Read failed: Buffer too small: {}", path);
|
oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize));
|
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize));
|
||||||
} catch (const std::fstream::failure &f) {
|
} catch (const std::fstream::failure &f) {
|
||||||
oxTracef("ox::fs::PassThroughFS::read::error", "Read of {} failed: {}", path, f.what());
|
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
|
||||||
return OxError(2);
|
return OxError(2);
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -174,7 +174,7 @@ Error PassThroughFS::writeFilePath(CRStringView path, const void *buffer, uint64
|
|||||||
std::ofstream f(p, std::ios::binary);
|
std::ofstream f(p, std::ios::binary);
|
||||||
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
|
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
|
||||||
} catch (const std::fstream::failure &f) {
|
} catch (const std::fstream::failure &f) {
|
||||||
oxTracef("ox::fs::PassThroughFS::read::error", "Write of {} failed: {}", path, f.what());
|
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -186,9 +186,9 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
|
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
|
||||||
const auto pathLen = ox_strlen(path);
|
const auto pathLen = ox::strlen(path);
|
||||||
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
|
for (auto i = 0u; i < pathLen && path[0] == '/'; i++) {
|
||||||
path = path.substr(1);
|
path = substr(path, 1);
|
||||||
}
|
}
|
||||||
return {path.data(), path.bytes()};
|
return {path.data(), path.bytes()};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
93
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
93
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/std/memops.hpp>
|
#include <ox/std/memops.hpp>
|
||||||
@ -19,7 +19,7 @@ PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t it
|
|||||||
m_iterator = iterator;
|
m_iterator = iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathIterator::PathIterator(const char *path): PathIterator(path, ox_strlen(path)) {
|
PathIterator::PathIterator(const char *path): PathIterator(path, ox::strlen(path)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PathIterator::PathIterator(CRStringView path): PathIterator(path.data(), path.bytes()) {
|
PathIterator::PathIterator(CRStringView path): PathIterator(path.data(), path.bytes()) {
|
||||||
@ -29,10 +29,10 @@ PathIterator::PathIterator(CRStringView path): PathIterator(path.data(), path.by
|
|||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
*/
|
*/
|
||||||
Error PathIterator::dirPath(char *out, std::size_t outSize) {
|
Error PathIterator::dirPath(char *out, std::size_t outSize) {
|
||||||
const auto idx = ox_lastIndexOf(m_path, '/', m_maxSize);
|
const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
|
||||||
const auto size = static_cast<std::size_t>(idx + 1);
|
const auto size = static_cast<std::size_t>(idx + 1);
|
||||||
if (idx >= 0 && size < outSize) {
|
if (idx >= 0 && size < outSize) {
|
||||||
ox_memcpy(out, m_path, size);
|
ox::memcpy(out, m_path, size);
|
||||||
out[size] = 0;
|
out[size] = 0;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
} else {
|
} else {
|
||||||
@ -44,12 +44,12 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) {
|
|||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
*/
|
*/
|
||||||
Error PathIterator::fileName(char *out, std::size_t outSize) {
|
Error PathIterator::fileName(char *out, std::size_t outSize) {
|
||||||
auto idx = ox_lastIndexOf(m_path, '/', m_maxSize);
|
auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
idx++; // pass up the preceding /
|
idx++; // pass up the preceding /
|
||||||
std::size_t fileNameSize = static_cast<size_t>(ox_strlen(&m_path[idx]));
|
std::size_t fileNameSize = static_cast<size_t>(ox::strlen(&m_path[idx]));
|
||||||
if (fileNameSize < outSize) {
|
if (fileNameSize < outSize) {
|
||||||
ox_memcpy(out, &m_path[idx], fileNameSize);
|
ox::memcpy(out, &m_path[idx], fileNameSize);
|
||||||
out[fileNameSize] = 0;
|
out[fileNameSize] = 0;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
} else {
|
} else {
|
||||||
@ -61,14 +61,15 @@ Error PathIterator::fileName(char *out, std::size_t outSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gets the get item in the path
|
// Gets the get item in the path
|
||||||
Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
|
Error PathIterator::get(IString<MaxFileNameLength> &fileName) {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
|
std::ignore = fileName.resize(MaxFileNameLength);
|
||||||
if (m_iterator >= m_maxSize) {
|
if (m_iterator >= m_maxSize) {
|
||||||
oxTracef("ox::fs::PathIterator::get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
|
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
if (!ox_strlen(&m_path[m_iterator])) {
|
if (!ox::strlen(&m_path[m_iterator])) {
|
||||||
oxTrace("ox::fs::PathIterator::get", "!ox_strlen(&m_path[m_iterator])");
|
oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])");
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
auto start = m_iterator;
|
auto start = m_iterator;
|
||||||
@ -76,88 +77,78 @@ Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
|
|||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
// end is at the next /
|
// end is at the next /
|
||||||
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
|
const char *substr = ox::strchr(&m_path[start], '/', m_maxSize - start);
|
||||||
// correct end if it is invalid, which happens if there is no next /
|
// correct end if it is invalid, which happens if there is no next /
|
||||||
if (!substr) {
|
if (!substr) {
|
||||||
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
|
substr = ox::strchr(&m_path[start], 0, m_maxSize - start);
|
||||||
}
|
}
|
||||||
const auto end = static_cast<size_t>(substr - m_path);
|
const auto end = static_cast<size_t>(substr - m_path);
|
||||||
size = end - start;
|
size = end - start;
|
||||||
// cannot fit the output in the output parameter
|
// cannot fit the output in the output parameter
|
||||||
if (size >= pathOutSize || size == 0) {
|
if (size >= MaxFileNameLength || size == 0) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
ox_memcpy(pathOut, &m_path[start], size);
|
ox::memcpy(fileName.data(), &m_path[start], size);
|
||||||
// truncate trailing /
|
// truncate trailing /
|
||||||
if (size && pathOut[size - 1] == '/') {
|
if (size && fileName[size - 1] == '/') {
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
pathOut[size] = 0; // end with null terminator
|
oxReturnError(fileName.resize(size));
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the get item in the path
|
/**
|
||||||
Error PathIterator::next(char *pathOut, std::size_t pathOutSize) {
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
|
Error PathIterator::next(IString<MaxFileNameLength> &fileName) {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
auto retval = OxError(1);
|
auto retval = OxError(1);
|
||||||
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
|
std::ignore = fileName.resize(MaxFileNameLength);
|
||||||
|
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
|
||||||
retval = OxError(0);
|
retval = OxError(0);
|
||||||
if (m_path[m_iterator] == '/') {
|
if (m_path[m_iterator] == '/') {
|
||||||
m_iterator++;
|
m_iterator++;
|
||||||
}
|
}
|
||||||
const auto start = m_iterator;
|
const auto start = m_iterator;
|
||||||
// end is at the next /
|
// end is at the next /
|
||||||
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
|
const char *substr = ox::strchr(&m_path[start], '/', m_maxSize - start);
|
||||||
// correct end if it is invalid, which happens if there is no next /
|
// correct end if it is invalid, which happens if there is no next /
|
||||||
if (!substr) {
|
if (!substr) {
|
||||||
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
|
substr = ox::strchr(&m_path[start], 0, m_maxSize - start);
|
||||||
}
|
}
|
||||||
const auto end = static_cast<size_t>(substr - m_path);
|
const auto end = static_cast<size_t>(substr - m_path);
|
||||||
size = end - start;
|
size = end - start;
|
||||||
// cannot fit the output in the output parameter
|
// cannot fit the output in the output parameter
|
||||||
if (size >= pathOutSize) {
|
if (size >= MaxFileNameLength) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
ox_memcpy(pathOut, &m_path[start], size);
|
ox::memcpy(fileName.data(), &m_path[start], size);
|
||||||
}
|
}
|
||||||
// truncate trailing /
|
// truncate trailing /
|
||||||
if (size && pathOut[size - 1] == '/') {
|
if (size && fileName[size - 1] == '/') {
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
pathOut[size] = 0; // end with null terminator
|
fileName[size] = 0; // end with null terminator
|
||||||
|
oxReturnError(fileName.resize(size));
|
||||||
m_iterator += size;
|
m_iterator += size;
|
||||||
return retval;
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<std::size_t> PathIterator::nextSize() const {
|
Result<std::size_t> PathIterator::nextSize() const {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
auto retval = OxError(1);
|
auto retval = OxError(1);
|
||||||
auto it = m_iterator;
|
auto it = m_iterator;
|
||||||
if (it < m_maxSize && ox_strlen(&m_path[it])) {
|
if (it < m_maxSize && ox::strlen(&m_path[it])) {
|
||||||
retval = OxError(0);
|
retval = OxError(0);
|
||||||
if (m_path[it] == '/') {
|
if (m_path[it] == '/') {
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
const auto start = it;
|
const auto start = it;
|
||||||
// end is at the next /
|
// end is at the next /
|
||||||
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
|
const char *substr = ox::strchr(&m_path[start], '/', m_maxSize - start);
|
||||||
// correct end if it is invalid, which happens if there is no next /
|
// correct end if it is invalid, which happens if there is no next /
|
||||||
if (!substr) {
|
if (!substr) {
|
||||||
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
|
substr = ox::strchr(&m_path[start], 0, m_maxSize - start);
|
||||||
}
|
}
|
||||||
const auto end = static_cast<std::size_t>(substr - m_path);
|
const auto end = static_cast<std::size_t>(substr - m_path);
|
||||||
size = end - start;
|
size = end - start;
|
||||||
@ -168,16 +159,16 @@ Result<std::size_t> PathIterator::nextSize() const {
|
|||||||
|
|
||||||
bool PathIterator::hasNext() const {
|
bool PathIterator::hasNext() const {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
|
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
|
||||||
std::size_t start = m_iterator;
|
std::size_t start = m_iterator;
|
||||||
if (m_path[start] == '/') {
|
if (m_path[start] == '/') {
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
// end is at the next /
|
// end is at the next /
|
||||||
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
|
const char *substr = ox::strchr(&m_path[start], '/', m_maxSize - start);
|
||||||
// correct end if it is invalid, which happens if there is no next /
|
// correct end if it is invalid, which happens if there is no next /
|
||||||
if (!substr) {
|
if (!substr) {
|
||||||
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
|
substr = ox::strchr(&m_path[start], 0, m_maxSize - start);
|
||||||
}
|
}
|
||||||
const auto end = static_cast<std::size_t>(substr - m_path);
|
const auto end = static_cast<std::size_t>(substr - m_path);
|
||||||
size = end - start;
|
size = end - start;
|
||||||
@ -192,16 +183,16 @@ bool PathIterator::valid() const {
|
|||||||
PathIterator PathIterator::next() const {
|
PathIterator PathIterator::next() const {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
auto iterator = m_iterator;
|
auto iterator = m_iterator;
|
||||||
if (iterator < m_maxSize && ox_strlen(&m_path[iterator])) {
|
if (iterator < m_maxSize && ox::strlen(&m_path[iterator])) {
|
||||||
if (m_path[iterator] == '/') {
|
if (m_path[iterator] == '/') {
|
||||||
iterator++;
|
iterator++;
|
||||||
}
|
}
|
||||||
const auto start = iterator;
|
const auto start = iterator;
|
||||||
// end is at the next /
|
// end is at the next /
|
||||||
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
|
const char *substr = ox::strchr(&m_path[start], '/', m_maxSize - start);
|
||||||
// correct end if it is invalid, which happens if there is no next /
|
// correct end if it is invalid, which happens if there is no next /
|
||||||
if (!substr) {
|
if (!substr) {
|
||||||
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
|
substr = ox::strchr(&m_path[start], 0, m_maxSize - start);
|
||||||
}
|
}
|
||||||
const auto end = static_cast<std::size_t>(substr - m_path);
|
const auto end = static_cast<std::size_t>(substr - m_path);
|
||||||
size = end - start;
|
size = end - start;
|
||||||
|
20
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
20
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -13,7 +13,7 @@
|
|||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
constexpr std::size_t MaxFileNameLength = 255;
|
constexpr std::size_t MaxFileNameLength = 255;
|
||||||
using FileName = BString<MaxFileNameLength>;
|
using FileName = IString<MaxFileNameLength>;
|
||||||
|
|
||||||
class PathIterator {
|
class PathIterator {
|
||||||
private:
|
private:
|
||||||
@ -41,22 +41,12 @@ class PathIterator {
|
|||||||
/**
|
/**
|
||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
*/
|
*/
|
||||||
Error next(char *pathOut, std::size_t pathOutSize);
|
Error next(FileName &fileName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
*/
|
*/
|
||||||
Error get(char *pathOut, std::size_t pathOutSize);
|
Error get(FileName &fileName);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 0 if no error
|
|
||||||
*/
|
|
||||||
Error next(FileName *fileName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 0 if no error
|
|
||||||
*/
|
|
||||||
Error get(FileName *fileName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
|
4
deps/ox/src/ox/fs/filesystem/types.hpp
vendored
4
deps/ox/src/ox/fs/filesystem/types.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
4
deps/ox/src/ox/fs/fs.hpp
vendored
4
deps/ox/src/ox/fs/fs.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
58
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
58
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -37,7 +37,7 @@ class OX_PACKED NodeBuffer {
|
|||||||
Iterator(NodeBuffer *buffer, ItemPtr current) noexcept {
|
Iterator(NodeBuffer *buffer, ItemPtr current) noexcept {
|
||||||
m_buffer = buffer;
|
m_buffer = buffer;
|
||||||
m_current = current;
|
m_current = current;
|
||||||
oxTrace("ox::ptrarith::Iterator::start") << current.offset();
|
oxTrace("ox.ptrarith.Iterator.start") << current.offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const Item*() const noexcept {
|
operator const Item*() const noexcept {
|
||||||
@ -77,7 +77,7 @@ class OX_PACKED NodeBuffer {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool hasNext() noexcept {
|
bool hasNext() noexcept {
|
||||||
if (m_current.valid()) {
|
if (m_current.valid()) {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
|
oxTrace("ox.ptrarith.NodeBuffer.Iterator.hasNext.current") << m_current.offset();
|
||||||
auto next = m_buffer->next(m_current);
|
auto next = m_buffer->next(m_current);
|
||||||
return next.valid() && m_buffer->firstItem() != next;
|
return next.valid() && m_buffer->firstItem() != next;
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class OX_PACKED NodeBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void next() noexcept {
|
void next() noexcept {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++;
|
oxTrace("ox.ptrarith.NodeBuffer.Iterator.next") << m_it++;
|
||||||
if (hasNext()) {
|
if (hasNext()) {
|
||||||
m_current = m_buffer->next(m_current);
|
m_current = m_buffer->next(m_current);
|
||||||
} else {
|
} else {
|
||||||
@ -173,15 +173,15 @@ class OX_PACKED NodeBuffer {
|
|||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
|
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
|
||||||
m_header.size = static_cast<size_t>(size);
|
m_header.size = static_cast<size_t>(size);
|
||||||
ox_memset(this + 1, 0, size - sizeof(*this));
|
ox::memset(this + 1, 0, size - sizeof(*this));
|
||||||
oxTracef("ox::NodeBuffer::constructor", "{}", m_header.firstItem.get());
|
oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept {
|
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get());
|
oxTracef("ox.ptrarith.NodeBuffer.copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get());
|
||||||
ox_memset(this + 1, 0, size - sizeof(*this));
|
ox::memset(this + 1, 0, size - sizeof(*this));
|
||||||
ox_memcpy(this, &other, size);
|
ox::memcpy(this, &other, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
@ -191,7 +191,7 @@ const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iter
|
|||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() noexcept {
|
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() noexcept {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::iterator::size", "{}", m_header.size.get());
|
oxTracef("ox.ptrarith.NodeBuffer.iterator.size", "{}", m_header.size.get());
|
||||||
return Iterator(this, firstItem());
|
return Iterator(this, firstItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t
|
|||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::malloc(std::size_t size) noexcept {
|
Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::malloc(std::size_t size) noexcept {
|
||||||
const auto sz = static_cast<std::size_t>(size);
|
const auto sz = static_cast<std::size_t>(size);
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::malloc", "Size: {}", sz);
|
oxTracef("ox.ptrarith.NodeBuffer.malloc", "Size: {}", sz);
|
||||||
size_t fullSize = static_cast<size_t>(sz + sizeof(Item));
|
size_t fullSize = static_cast<size_t>(sz + sizeof(Item));
|
||||||
if (m_header.size - m_header.bytesUsed >= fullSize) {
|
if (m_header.size - m_header.bytesUsed >= fullSize) {
|
||||||
auto last = lastItem();
|
auto last = lastItem();
|
||||||
@ -277,21 +277,21 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
|
|||||||
} else {
|
} else {
|
||||||
// there is no first item, so this must be the first item
|
// there is no first item, so this must be the first item
|
||||||
if (!m_header.firstItem) {
|
if (!m_header.firstItem) {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::malloc", "No first item, initializing.");
|
oxTrace("ox.ptrarith.NodeBuffer.malloc", "No first item, initializing.");
|
||||||
m_header.firstItem = static_cast<size_t>(sizeof(m_header));
|
m_header.firstItem = static_cast<size_t>(sizeof(m_header));
|
||||||
addr = m_header.firstItem;
|
addr = m_header.firstItem;
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail", "NodeBuffer is in invalid state.");
|
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state.");
|
||||||
return OxError(1, "NodeBuffer is in invalid state.");
|
return OxError(1, "NodeBuffer is in invalid state.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize);
|
oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize);
|
||||||
auto out = ItemPtr(this, m_header.size, addr, fullSize);
|
auto out = ItemPtr(this, m_header.size, addr, fullSize);
|
||||||
if (!out.valid()) {
|
if (!out.valid()) {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail", "Unknown");
|
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown");
|
||||||
return OxError(1, "NodeBuffer::malloc: unknown failure");
|
return OxError(1, "NodeBuffer::malloc: unknown failure");
|
||||||
}
|
}
|
||||||
ox_memset(out, 0, fullSize);
|
ox::memset(out, 0, fullSize);
|
||||||
new (out) Item;
|
new (out) Item;
|
||||||
out->setSize(sz);
|
out->setSize(sz);
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
|
|||||||
if (first.valid()) {
|
if (first.valid()) {
|
||||||
first->prev = out.offset();
|
first->prev = out.offset();
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail", "NodeBuffer malloc failed due to invalid first element pointer.");
|
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer.");
|
||||||
return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer.");
|
return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,22 +311,22 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
|
|||||||
} else { // check to see if this is the first allocation
|
} else { // check to see if this is the first allocation
|
||||||
if (out.offset() != first.offset()) {
|
if (out.offset() != first.offset()) {
|
||||||
// if this is not the first allocation, there should be an oldLast
|
// if this is not the first allocation, there should be an oldLast
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::malloc::fail", "NodeBuffer malloc failed due to invalid last element pointer.");
|
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer.");
|
||||||
return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer.");
|
return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer.");
|
||||||
}
|
}
|
||||||
out->prev = out.offset();
|
out->prev = out.offset();
|
||||||
}
|
}
|
||||||
m_header.bytesUsed += out.size();
|
m_header.bytesUsed += out.size();
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::malloc", "Offset: {}", out.offset());
|
oxTracef("ox.ptrarith.NodeBuffer.malloc", "Offset: {}", out.offset());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::malloc::fail", "Insufficient space: {} needed, {} available", fullSize, available());
|
oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available());
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
|
Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::free", "offset: {}", item.offset());
|
oxTracef("ox.ptrarith.NodeBuffer.free", "offset: {}", item.offset());
|
||||||
auto prev = this->prev(item);
|
auto prev = this->prev(item);
|
||||||
auto next = this->next(item);
|
auto next = this->next(item);
|
||||||
if (prev.valid() && next.valid()) {
|
if (prev.valid() && next.valid()) {
|
||||||
@ -338,16 +338,16 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// only one item, null out first
|
// only one item, null out first
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::free", "Nulling out firstItem.");
|
oxTrace("ox.ptrarith.NodeBuffer.free", "Nulling out firstItem.");
|
||||||
m_header.firstItem = 0;
|
m_header.firstItem = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!prev.valid()) {
|
if (!prev.valid()) {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::free::fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset());
|
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset());
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
if (!next.valid()) {
|
if (!next.valid()) {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::free::fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset());
|
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset());
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,17 +357,17 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
|
|||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
|
Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::setSize", "{} to {}", m_header.size.get(), size);
|
oxTracef("ox.ptrarith.NodeBuffer.setSize", "{} to {}", m_header.size.get(), size);
|
||||||
auto last = lastItem();
|
auto last = lastItem();
|
||||||
auto end = last.valid() ? last.end() : sizeof(m_header);
|
auto end = last.valid() ? last.end() : sizeof(m_header);
|
||||||
oxTracef("ox::ptrarith::NodeBuffer::setSize", "end: {}", end);
|
oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end);
|
||||||
if (end > size) {
|
if (end > size) {
|
||||||
// resizing to less than buffer size
|
// resizing to less than buffer size
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
} else {
|
} else {
|
||||||
m_header.size = static_cast<size_t>(size);
|
m_header.size = static_cast<size_t>(size);
|
||||||
auto data = reinterpret_cast<uint8_t*>(this) + end;
|
auto data = reinterpret_cast<uint8_t*>(this) + end;
|
||||||
ox_memset(data, 0, size - end);
|
ox::memset(data, 0, size - end);
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +405,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
|
|||||||
return OxError(2);
|
return OxError(2);
|
||||||
}
|
}
|
||||||
// move node
|
// move node
|
||||||
ox_memcpy(dest, src, src->fullSize());
|
ox::memcpy(dest, src, src->fullSize());
|
||||||
oxReturnError(cb(src, dest));
|
oxReturnError(cb(src, dest));
|
||||||
// update surrounding nodes
|
// update surrounding nodes
|
||||||
auto prev = ptr(dest->prev);
|
auto prev = ptr(dest->prev);
|
||||||
|
8
deps/ox/src/ox/fs/ptrarith/ptr.hpp
vendored
8
deps/ox/src/ox/fs/ptrarith/ptr.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -224,7 +224,7 @@ constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(s
|
|||||||
template<typename T, typename size_t, size_t minOffset>
|
template<typename T, typename size_t, size_t minOffset>
|
||||||
template<typename SubT>
|
template<typename SubT>
|
||||||
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
|
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
|
||||||
oxTracef("ox::fs::Ptr::subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
||||||
return subPtr<SubT>(offset, m_itemSize - offset);
|
return subPtr<SubT>(offset, m_itemSize - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t
|
|||||||
template<typename T, typename size_t, size_t minOffset>
|
template<typename T, typename size_t, size_t minOffset>
|
||||||
template<typename SubT>
|
template<typename SubT>
|
||||||
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
|
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
|
||||||
oxTracef("ox::fs::Ptr::subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
||||||
return subPtr<SubT>(offset, m_itemSize - offset);
|
return subPtr<SubT>(offset, m_itemSize - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
27
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
@ -6,24 +6,23 @@ add_executable(
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
FSTests
|
FSTests
|
||||||
OxFS
|
OxFS
|
||||||
OxStd
|
|
||||||
OxMetalClaw
|
OxMetalClaw
|
||||||
)
|
)
|
||||||
|
|
||||||
add_test("[ox/fs] PtrArith::setSize" FSTests PtrArith::setSize)
|
add_test("[ox/fs] PtrArith::setSize" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PtrArith::setSize)
|
||||||
|
|
||||||
add_test("[ox/fs] PathIterator::next1" FSTests PathIterator::next1)
|
add_test("[ox/fs] PathIterator::next1" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::next1)
|
||||||
add_test("[ox/fs] PathIterator::next2" FSTests PathIterator::next2)
|
add_test("[ox/fs] PathIterator::next2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::next2)
|
||||||
add_test("[ox/fs] PathIterator::next3" FSTests PathIterator::next3)
|
add_test("[ox/fs] PathIterator::next3" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::next3)
|
||||||
add_test("[ox/fs] PathIterator::next4" FSTests PathIterator::next4)
|
add_test("[ox/fs] PathIterator::next4" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::next4)
|
||||||
add_test("[ox/fs] PathIterator::next5" FSTests PathIterator::next5)
|
add_test("[ox/fs] PathIterator::next5" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::next5)
|
||||||
add_test("[ox/fs] PathIterator::hasNext" FSTests PathIterator::hasNext)
|
add_test("[ox/fs] PathIterator::hasNext" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::hasNext)
|
||||||
|
|
||||||
add_test("[ox/fs] PathIterator::dirPath" FSTests PathIterator::dirPath)
|
add_test("[ox/fs] PathIterator::dirPath" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::dirPath)
|
||||||
add_test("[ox/fs] PathIterator::fileName" FSTests PathIterator::fileName)
|
add_test("[ox/fs] PathIterator::fileName" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::fileName)
|
||||||
|
|
||||||
add_test("[ox/fs] NodeBuffer::insert" FSTests "NodeBuffer::insert")
|
add_test("[ox/fs] NodeBuffer::insert" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "NodeBuffer::insert")
|
||||||
add_test("[ox/fs] FileStore::readWrite" FSTests "FileStore::readWrite")
|
add_test("[ox/fs] FileStore::readWrite" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileStore::readWrite")
|
||||||
|
|
||||||
add_test("[ox/fs] Directory" FSTests "Directory")
|
add_test("[ox/fs] Directory" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "Directory")
|
||||||
add_test("[ox/fs] FileSystem" FSTests "FileSystem")
|
add_test("[ox/fs] FileSystem" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileSystem")
|
||||||
|
126
deps/ox/src/ox/fs/test/tests.cpp
vendored
126
deps/ox/src/ox/fs/test/tests.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// make sure asserts are enabled for the test file
|
// make sure asserts are enabled for the test file
|
||||||
@ -26,15 +26,15 @@ struct OX_PACKED NodeType: public ox::ptrarith::Item<T> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tests = {
|
const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"PtrArith::setSize",
|
"PtrArith::setSize",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
using BuffPtr_t = uint32_t;
|
using BuffPtr_t = uint32_t;
|
||||||
ox::Vector<char> buff(5 * ox::units::MB);
|
ox::Vector<char> buff(5 * ox::units::MB);
|
||||||
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
|
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
|
||||||
using String = ox::BString<6>;
|
using String = ox::IString<6>;
|
||||||
auto a1 = buffer->malloc(sizeof(String)).value;
|
auto a1 = buffer->malloc(sizeof(String)).value;
|
||||||
auto a2 = buffer->malloc(sizeof(String)).value;
|
auto a2 = buffer->malloc(sizeof(String)).value;
|
||||||
oxAssert(a1.valid(), "Allocation 1 failed.");
|
oxAssert(a1.valid(), "Allocation 1 failed.");
|
||||||
@ -57,85 +57,85 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next1",
|
"PathIterator::next1",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "/usr/share/charset.gbag";
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next2",
|
"PathIterator::next2",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "/usr/share/";
|
auto const path = ox::String("/usr/share/");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next3",
|
"PathIterator::next3",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "/";
|
auto const path = ox::String("/");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next4",
|
"PathIterator::next4",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "usr/share/charset.gbag";
|
auto const path = ox::String("usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next5",
|
"PathIterator::next5",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "usr/share/";
|
auto const path = ox::String("usr/share/");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::dirPath",
|
"PathIterator::dirPath",
|
||||||
[] (std::string_view) {
|
[] (ox::StringView) {
|
||||||
ox::String path = "/usr/share/charset.gbag";
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||||
oxAssert(it.dirPath(buff, path.len()) == 0 && ox_strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::fileName",
|
"PathIterator::fileName",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::String path = "/usr/share/charset.gbag";
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||||
oxAssert(it.fileName(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
|
oxAssert(it.fileName(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::hasNext",
|
"PathIterator::hasNext",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
const auto path = "/file1";
|
const auto path = "/file1";
|
||||||
ox::PathIterator it(path, ox_strlen(path));
|
ox::PathIterator it(path, ox::strlen(path));
|
||||||
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
|
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
|
||||||
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
|
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -143,7 +143,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Ptr::subPtr",
|
"Ptr::subPtr",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
constexpr auto buffLen = 5000;
|
constexpr auto buffLen = 5000;
|
||||||
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
|
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
|
||||||
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
|
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
|
||||||
@ -155,7 +155,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"NodeBuffer::insert",
|
"NodeBuffer::insert",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
constexpr auto buffLen = 5000;
|
constexpr auto buffLen = 5000;
|
||||||
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
||||||
oxAssert(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed");
|
oxAssert(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed");
|
||||||
@ -168,12 +168,12 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FileStore::readWrite",
|
"FileStore::readWrite",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
constexpr auto buffLen = 5000;
|
constexpr auto buffLen = 5000;
|
||||||
constexpr auto str1 = "Hello, World!";
|
constexpr auto str1 = "Hello, World!";
|
||||||
constexpr auto str1Len = ox_strlen(str1) + 1;
|
constexpr auto str1Len = ox::strlen(str1) + 1;
|
||||||
constexpr auto str2 = "Hello, Moon!";
|
constexpr auto str2 = "Hello, Moon!";
|
||||||
constexpr auto str2Len = ox_strlen(str2) + 1;
|
constexpr auto str2Len = ox::strlen(str2) + 1;
|
||||||
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
||||||
oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed.");
|
oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed.");
|
||||||
ox::FileStore32 fileStore(list, buffLen);
|
ox::FileStore32 fileStore(list, buffLen);
|
||||||
@ -189,26 +189,26 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Directory",
|
"Directory",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::Vector<uint8_t> fsBuff(5000);
|
ox::Vector<uint8_t> fsBuff(5000);
|
||||||
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
|
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
|
||||||
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
|
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
|
||||||
ox::Directory32 dir(fileStore, 105);
|
ox::Directory32 dir(fileStore, 105);
|
||||||
|
|
||||||
oxTrace("ox::fs::test::Directory") << "Init";
|
oxTrace("ox.fs.test.Directory") << "Init";
|
||||||
oxAssert(dir.init(), "Init failed");
|
oxAssert(dir.init(), "Init failed");
|
||||||
|
|
||||||
oxTrace("ox::fs::test::Directory") << "write 1";
|
oxTrace("ox.fs.test.Directory") << "write 1";
|
||||||
oxAssert(dir.write("/file1", 1), "Directory write of file1 failed");
|
oxAssert(dir.write("/file1", 1), "Directory write of file1 failed");
|
||||||
|
|
||||||
oxTrace("ox::fs::test::Directory") << "find";
|
oxTrace("ox.fs.test.Directory") << "find";
|
||||||
oxAssert(dir.find("file1").error, "Could not find file1");
|
oxAssert(dir.find("file1").error, "Could not find file1");
|
||||||
oxAssert(dir.find("file1").value == 1, "Could not find file1");
|
oxAssert(dir.find("file1").value == 1, "Could not find file1");
|
||||||
|
|
||||||
oxTrace("ox::fs::test::Directory") << "write 2";
|
oxTrace("ox.fs.test.Directory") << "write 2";
|
||||||
oxAssert(dir.write("/file3", 3), "Directory write of file3 failed");
|
oxAssert(dir.write("/file3", 3), "Directory write of file3 failed");
|
||||||
|
|
||||||
oxTrace("ox::fs::test::Directory") << "write 3";
|
oxTrace("ox.fs.test.Directory") << "write 3";
|
||||||
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
|
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
|
||||||
|
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -216,13 +216,13 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FileSystem",
|
"FileSystem",
|
||||||
[](std::string_view) {
|
[](ox::StringView) {
|
||||||
ox::Vector<uint8_t> fsBuff(5000);
|
ox::Vector<uint8_t> fsBuff(5000);
|
||||||
oxTrace("ox::fs::test::FileSystem") << "format";
|
oxTrace("ox.fs.test.FileSystem") << "format";
|
||||||
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
||||||
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
|
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
|
||||||
|
|
||||||
oxTrace("ox::fs::test::FileSystem") << "mkdir";
|
oxTrace("ox.fs.test.FileSystem") << "mkdir";
|
||||||
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
|
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
|
||||||
oxAssert(fs.stat("/dir").error, "mkdir failed");
|
oxAssert(fs.stat("/dir").error, "mkdir failed");
|
||||||
oxAssert(fs.mkdir("/l1d1/l2d1/l3d1", true), "mkdir failed");
|
oxAssert(fs.mkdir("/l1d1/l2d1/l3d1", true), "mkdir failed");
|
||||||
@ -237,16 +237,16 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char **args) {
|
int main(int argc, const char **args) {
|
||||||
int retval = -1;
|
if (argc < 2) {
|
||||||
if (argc > 1) {
|
oxError("Must specify test to run");
|
||||||
std::string_view testName = args[1];
|
return -1;
|
||||||
std::string_view testArg;
|
|
||||||
if (args[2]) {
|
|
||||||
testArg = args[2];
|
|
||||||
}
|
}
|
||||||
if (tests.find(testName) != tests.end()) {
|
ox::StringView const testName = args[1];
|
||||||
retval = static_cast<int>(tests.at(testName)(testArg));
|
ox::StringView const testArg = args[2] ? args[2] : nullptr;
|
||||||
|
auto const func = tests.find(testName);
|
||||||
|
if (func != tests.end()) {
|
||||||
|
oxAssert(func->second(testArg), "Test returned Error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
return -1;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
6
deps/ox/src/ox/fs/tool.cpp
vendored
6
deps/ox/src/ox/fs/tool.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -67,7 +67,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
|
|||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
const auto fsPath = argv[1];
|
const auto fsPath = argv[1];
|
||||||
ox::String subCmd = argv[2];
|
ox::String subCmd(argv[2]);
|
||||||
oxRequire(fs, loadFs(fsPath));
|
oxRequire(fs, loadFs(fsPath));
|
||||||
if (subCmd == "ls") {
|
if (subCmd == "ls") {
|
||||||
return runLs(fs.get(), argc - 2, argv + 2);
|
return runLs(fs.get(), argc - 2, argv + 2);
|
||||||
|
2
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
2
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
@ -20,6 +20,8 @@ target_link_libraries(
|
|||||||
OxLogConn PUBLIC
|
OxLogConn PUBLIC
|
||||||
OxStd
|
OxStd
|
||||||
OxMetalClaw
|
OxMetalClaw
|
||||||
|
$<$<BOOL:${OX_OS_FREEBSD}>:pthread>
|
||||||
|
$<$<BOOL:${OX_OS_WINDOWS}>:ws2_32>
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
12
deps/ox/src/ox/logconn/circularbuff.hpp
vendored
12
deps/ox/src/ox/logconn/circularbuff.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -47,13 +47,13 @@ class CirculerBuffer {
|
|||||||
}
|
}
|
||||||
// write seg 1
|
// write seg 1
|
||||||
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
|
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
|
||||||
ox_memcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
|
ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
|
||||||
m_writePt += sz;
|
m_writePt += sz;
|
||||||
if (seg1Sz != sz) {
|
if (seg1Sz != sz) {
|
||||||
m_writePt -= m_buff.size();
|
m_writePt -= m_buff.size();
|
||||||
// write seg 2
|
// write seg 2
|
||||||
const auto seg2Sz = sz - seg1Sz;
|
const auto seg2Sz = sz - seg1Sz;
|
||||||
ox_memcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
|
ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
|
||||||
oxAssert(m_buff[0] == buff[seg1Sz], "break");
|
oxAssert(m_buff[0] == buff[seg1Sz], "break");
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -70,7 +70,7 @@ class CirculerBuffer {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ox::Error seekp(int, ios_base::seekdir) {
|
constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
|
||||||
return OxError(1, "Unimplemented");
|
return OxError(1, "Unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,13 +84,13 @@ class CirculerBuffer {
|
|||||||
const auto bytesRead = ox::min(outSize, m_buff.size() - avail());
|
const auto bytesRead = ox::min(outSize, m_buff.size() - avail());
|
||||||
// read seg 1
|
// read seg 1
|
||||||
const auto seg1Sz = ox::min(bytesRead, m_buff.size() - m_readPt);
|
const auto seg1Sz = ox::min(bytesRead, m_buff.size() - m_readPt);
|
||||||
ox_memcpy(&out[0], &m_buff[m_readPt], seg1Sz);
|
ox::listcpy(&out[0], &m_buff[m_readPt], seg1Sz);
|
||||||
m_readPt += bytesRead;
|
m_readPt += bytesRead;
|
||||||
if (seg1Sz != bytesRead) {
|
if (seg1Sz != bytesRead) {
|
||||||
m_readPt -= m_buff.size();
|
m_readPt -= m_buff.size();
|
||||||
// read seg 2
|
// read seg 2
|
||||||
const auto seg2Sz = bytesRead - seg1Sz;
|
const auto seg2Sz = bytesRead - seg1Sz;
|
||||||
ox_memcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
|
ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
|
||||||
}
|
}
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
2
deps/ox/src/ox/logconn/def.hpp
vendored
2
deps/ox/src/ox/logconn/def.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
31
deps/ox/src/ox/logconn/logconn.cpp
vendored
31
deps/ox/src/ox/logconn/logconn.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -7,21 +7,38 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef OX_USE_STDLIB
|
#ifdef OX_USE_STDLIB
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstdio>
|
#else
|
||||||
|
#include <winsock.h>
|
||||||
|
#undef interface
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ox/std/bit.hpp>
|
|
||||||
|
|
||||||
#include "logconn.hpp"
|
#include "logconn.hpp"
|
||||||
|
|
||||||
|
#include <ox/std/bit.hpp>
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
using namespace trace;
|
using namespace trace;
|
||||||
|
|
||||||
|
void closeSock(auto s) noexcept {
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(s);
|
||||||
|
#else
|
||||||
|
close(s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
LoggerConn::LoggerConn() noexcept: m_netThread([this]{this->msgSend();}) {
|
LoggerConn::LoggerConn() noexcept: m_netThread([this]{this->msgSend();}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +47,7 @@ LoggerConn::~LoggerConn() noexcept {
|
|||||||
m_waitCond.notify_one();
|
m_waitCond.notify_one();
|
||||||
m_netThread.join();
|
m_netThread.join();
|
||||||
if (m_socket) {
|
if (m_socket) {
|
||||||
close(m_socket);
|
closeSock(m_socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +58,7 @@ ox::Error LoggerConn::initConn(ox::CRStringView appName) noexcept {
|
|||||||
addr.sin_port = htons(5590);
|
addr.sin_port = htons(5590);
|
||||||
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
|
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
|
||||||
return sendInit({.appName = appName});
|
return sendInit({.appName = ox::BasicString<128>(appName)});
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
|
ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
|
||||||
@ -81,7 +98,7 @@ void LoggerConn::msgSend() noexcept {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//std::printf("LoggerConn: sending %lu bytes\n", read);
|
//std::printf("LoggerConn: sending %lu bytes\n", read);
|
||||||
oxIgnoreError(send(tmp.data(), read));
|
std::ignore = send(tmp.data(), read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
deps/ox/src/ox/logconn/logconn.hpp
vendored
2
deps/ox/src/ox/logconn/logconn.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
10
deps/ox/src/ox/mc/err.hpp
vendored
10
deps/ox/src/ox/mc/err.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -11,9 +11,9 @@
|
|||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MC_PRESENCEMASKOUTBOUNDS = 1,
|
McPresenceMapOverflow = 1,
|
||||||
MC_BUFFENDED = 2,
|
McBuffEnded = 2,
|
||||||
MC_OUTBUFFENDED = 4
|
McOutputBuffEnded = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
47
deps/ox/src/ox/mc/intops.hpp
vendored
47
deps/ox/src/ox/mc/intops.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
#include <ox/std/math.hpp>
|
#include <ox/std/math.hpp>
|
||||||
#include <ox/std/memops.hpp>
|
#include <ox/std/memops.hpp>
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
|
||||||
namespace ox::mc {
|
namespace ox::mc {
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ constexpr std::size_t highestBit(I val) noexcept {
|
|||||||
if constexpr(is_signed_v<I>) {
|
if constexpr(is_signed_v<I>) {
|
||||||
--shiftStart;
|
--shiftStart;
|
||||||
}
|
}
|
||||||
for (auto i = shiftStart; i < MaxValue<decltype(i)>; --i) {
|
for (auto i = shiftStart; i > 0; --i) {
|
||||||
const auto bitValue = (val >> i) & 1;
|
const auto bitValue = (val >> i) & 1;
|
||||||
if (bitValue) {
|
if (bitValue) {
|
||||||
highestBit = i;
|
highestBit = i;
|
||||||
@ -63,13 +64,14 @@ struct McInt {
|
|||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr McInt encodeInteger(I input) noexcept {
|
constexpr McInt encodeInteger(I pInput) noexcept {
|
||||||
|
auto const input = ox::ResizedInt_t<I, 64>{pInput};
|
||||||
McInt out;
|
McInt out;
|
||||||
const auto inputNegative = is_signed_v<I> && input < 0;
|
const auto inputNegative = is_signed_v<I> && input < 0;
|
||||||
// move input to uint64_t to allow consistent bit manipulation, and to avoid
|
// move input to uint64_t to allow consistent bit manipulation, and to avoid
|
||||||
// overflow concerns
|
// overflow concerns
|
||||||
uint64_t val = 0;
|
uint64_t val = 0;
|
||||||
ox_memcpy(&val, &input, sizeof(I));
|
ox::memcpy(&val, &input, sizeof(input));
|
||||||
if (val) {
|
if (val) {
|
||||||
// bits needed to represent number factoring in space possibly
|
// bits needed to represent number factoring in space possibly
|
||||||
// needed for signed bit
|
// needed for signed bit
|
||||||
@ -92,7 +94,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
|||||||
}
|
}
|
||||||
if (bytes == 9) {
|
if (bytes == 9) {
|
||||||
out.data[0] = bytesIndicator;
|
out.data[0] = bytesIndicator;
|
||||||
ox_memcpy(&out.data[1], &leVal, sizeof(I));
|
ox::memcpy(&out.data[1], &leVal, 8);
|
||||||
if (inputNegative) {
|
if (inputNegative) {
|
||||||
out.data[1] |= 0b1000'0000;
|
out.data[1] |= 0b1000'0000;
|
||||||
}
|
}
|
||||||
@ -102,7 +104,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
|||||||
auto intermediate =
|
auto intermediate =
|
||||||
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
|
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
|
||||||
static_cast<uint64_t>(bytesIndicator);
|
static_cast<uint64_t>(bytesIndicator);
|
||||||
ox_memcpy(out.data, &intermediate, sizeof(intermediate));
|
ox::memcpy(out.data, &intermediate, sizeof(intermediate));
|
||||||
}
|
}
|
||||||
out.length = bytes;
|
out.length = bytes;
|
||||||
}
|
}
|
||||||
@ -114,7 +116,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
|||||||
* length integer.
|
* length integer.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static constexpr std::size_t countBytes(unsigned b) noexcept {
|
constexpr std::size_t countBytes(unsigned b) noexcept {
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
while ((b >> i) & 1) ++i;
|
while ((b >> i) & 1) ++i;
|
||||||
return i + 1;
|
return i + 1;
|
||||||
@ -131,17 +133,21 @@ static_assert(countBytes(0b0111'1111) == 8);
|
|||||||
static_assert(countBytes(0b1111'1111) == 9);
|
static_assert(countBytes(0b1111'1111) == 9);
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Result<I> decodeInteger(const uint8_t buff[9], std::size_t buffLen, std::size_t *bytesRead) noexcept {
|
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
|
||||||
const auto bytes = countBytes(buff[0]);
|
uint8_t firstByte = 0;
|
||||||
|
oxReturnError(rdr.read(&firstByte, 1));
|
||||||
|
oxReturnError(rdr.seekg(-1, ox::ios_base::cur));
|
||||||
|
const auto bytes = countBytes(firstByte);
|
||||||
if (bytes == 9) {
|
if (bytes == 9) {
|
||||||
*bytesRead = bytes;
|
*bytesRead = bytes;
|
||||||
I out = 0;
|
I out = 0;
|
||||||
ox_memcpy(&out, &buff[1], sizeof(I));
|
oxReturnError(rdr.seekg(1, ox::ios_base::cur));
|
||||||
|
oxReturnError(rdr.read(&out, sizeof(I)));
|
||||||
return fromLittleEndian<I>(out);
|
return fromLittleEndian<I>(out);
|
||||||
} else if (buffLen >= bytes) {
|
}
|
||||||
*bytesRead = bytes;
|
*bytesRead = bytes;
|
||||||
uint64_t decoded = 0;
|
uint64_t decoded = 0;
|
||||||
ox_memcpy(&decoded, &buff[0], bytes);
|
oxReturnError(rdr.read(&decoded, bytes));
|
||||||
decoded >>= bytes;
|
decoded >>= bytes;
|
||||||
// move sign bit
|
// move sign bit
|
||||||
if constexpr(is_signed_v<I>) {
|
if constexpr(is_signed_v<I>) {
|
||||||
@ -152,7 +158,9 @@ constexpr Result<I> decodeInteger(const uint8_t buff[9], std::size_t buffLen, st
|
|||||||
// fill in all bits between encoded sign and real sign with 1s
|
// fill in all bits between encoded sign and real sign with 1s
|
||||||
// split it up because the 32-bit ARM can't shift more than 32 bits
|
// split it up because the 32-bit ARM can't shift more than 32 bits
|
||||||
ox::Array<uint32_t, 2> d = {};
|
ox::Array<uint32_t, 2> d = {};
|
||||||
ox_memcpy(d.data(), &decoded, sizeof(decoded));
|
//d[0] = decoded & 0xffff'ffff;
|
||||||
|
//d[1] = decoded >> 32;
|
||||||
|
ox::memcpy(d.data(), &decoded, sizeof(decoded));
|
||||||
auto bit = negBit;
|
auto bit = negBit;
|
||||||
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
|
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
|
||||||
d[0] |= 1 << bit;
|
d[0] |= 1 << bit;
|
||||||
@ -167,19 +175,18 @@ constexpr Result<I> decodeInteger(const uint8_t buff[9], std::size_t buffLen, st
|
|||||||
d[0] = d[1];
|
d[0] = d[1];
|
||||||
d[1] = d0Tmp;
|
d[1] = d0Tmp;
|
||||||
}
|
}
|
||||||
ox_memcpy(&out, d.data(), sizeof(out));
|
ox::memcpy(&out, d.data(), sizeof(out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return static_cast<I>(decoded);
|
return static_cast<I>(decoded);
|
||||||
}
|
|
||||||
return OxError(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Result<I> decodeInteger(McInt m) noexcept {
|
Result<I> decodeInteger(McInt m) noexcept {
|
||||||
std::size_t bytesRead;
|
std::size_t bytesRead{};
|
||||||
return decodeInteger<I>(m.data, 9, &bytesRead);
|
BufferReader br({reinterpret_cast<const char*>(m.data), 9});
|
||||||
|
return decodeInteger<I>(br, &bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
deps/ox/src/ox/mc/mc.hpp
vendored
4
deps/ox/src/ox/mc/mc.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
8
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
8
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template class FieldBitmapReader<uint8_t*>;
|
template class FieldBitmapWriterBase<uint8_t*>;
|
||||||
template class FieldBitmapReader<const uint8_t*>;
|
template class FieldBitmapWriterBase<const uint8_t*>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
89
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
89
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
@ -1,28 +1,84 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/array.hpp>
|
||||||
|
#include <ox/std/bit.hpp>
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
#include <ox/std/types.hpp>
|
#include <ox/std/types.hpp>
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
|
||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template<typename T>
|
template<Reader_c Reader>
|
||||||
class FieldBitmapReader {
|
class FieldBitmapReader {
|
||||||
|
protected:
|
||||||
|
mutable std::size_t m_mapBlockIdx = ~std::size_t{0};
|
||||||
|
mutable uint64_t m_mapBlock = 0;
|
||||||
|
std::size_t m_mapStart = 0;
|
||||||
|
Reader &m_reader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
|
||||||
|
|
||||||
|
constexpr Result<bool> get(std::size_t i) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
|
||||||
|
m_mapStart(reader.tellg()),
|
||||||
|
m_reader(reader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept {
|
||||||
|
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||||
|
auto const blockIdx = idx / blockBits;
|
||||||
|
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||||
|
oxReturnError(loadMapBlock(blockIdx));
|
||||||
|
}
|
||||||
|
idx %= blockBits;
|
||||||
|
return (m_mapBlock >> idx) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
|
||||||
|
oxRequire(g, m_reader.tellg());
|
||||||
|
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||||
|
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||||
|
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||||
|
// Warning: narrow-conv
|
||||||
|
oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||||
|
m_mapBlock = 0;
|
||||||
|
for (auto i = 0ull; auto b : mapBlock) {
|
||||||
|
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||||
|
i += 8;
|
||||||
|
}
|
||||||
|
m_mapBlockIdx = idx;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class FieldBitmapWriterBase {
|
||||||
protected:
|
protected:
|
||||||
T m_map = nullptr;
|
T m_map = nullptr;
|
||||||
std::size_t m_mapLen = 0;
|
std::size_t m_mapLen = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FieldBitmapReader(T map, std::size_t maxLen) noexcept;
|
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept;
|
||||||
|
|
||||||
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
|
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
|
||||||
|
|
||||||
@ -38,45 +94,45 @@ class FieldBitmapReader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr FieldBitmapReader<T>::FieldBitmapReader(T map, std::size_t maxLen) noexcept {
|
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept {
|
||||||
m_map = map;
|
m_map = map;
|
||||||
m_mapLen = maxLen;
|
m_mapLen = maxLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto FieldBitmapReader<T>::setBuffer(T map, std::size_t maxLen) noexcept {
|
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept {
|
||||||
m_map = map;
|
m_map = map;
|
||||||
m_mapLen = maxLen;
|
m_mapLen = maxLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Result<bool> FieldBitmapReader<T>::get(std::size_t i) const noexcept {
|
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept {
|
||||||
if (i / 8 < m_mapLen) {
|
if (i / 8 < m_mapLen) {
|
||||||
return (m_map[i / 8] >> (i % 8)) & 1;
|
return (m_map[i / 8] >> (i % 8)) & 1;
|
||||||
} else {
|
} else {
|
||||||
return OxError(MC_PRESENCEMASKOUTBOUNDS);
|
return OxError(McPresenceMapOverflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr void FieldBitmapReader<T>::setFields(int fields) noexcept {
|
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept {
|
||||||
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr void FieldBitmapReader<T>::setMaxLen(int maxLen) noexcept {
|
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept {
|
||||||
m_mapLen = static_cast<std::size_t>(maxLen);
|
m_mapLen = static_cast<std::size_t>(maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr int64_t FieldBitmapReader<T>::getMaxLen() const noexcept {
|
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
|
||||||
return static_cast<int64_t>(m_mapLen);
|
return static_cast<int64_t>(m_mapLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern template class FieldBitmapReader<uint8_t*>;
|
extern template class FieldBitmapWriterBase<uint8_t*>;
|
||||||
extern template class FieldBitmapReader<const uint8_t*>;
|
extern template class FieldBitmapWriterBase<const uint8_t*>;
|
||||||
|
|
||||||
class FieldBitmap: public FieldBitmapReader<uint8_t*> {
|
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
|
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
|
||||||
@ -85,7 +141,8 @@ class FieldBitmap: public FieldBitmapReader<uint8_t*> {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept: FieldBitmapReader<uint8_t*>(map, maxLen) {
|
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
|
||||||
|
FieldBitmapWriterBase<uint8_t*>(map, maxLen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
||||||
@ -97,7 +154,7 @@ constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
return OxError(MC_PRESENCEMASKOUTBOUNDS);
|
return OxError(McPresenceMapOverflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
deps/ox/src/ox/mc/read.cpp
vendored
10
deps/ox/src/ox/mc/read.cpp
vendored
@ -1,11 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ox/model/modelhandleradaptor.hpp>
|
||||||
|
#include <ox/std/buffer.hpp>
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
|
||||||
|
#include "read.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
|
template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
425
deps/ox/src/ox/mc/read.hpp
vendored
425
deps/ox/src/ox/mc/read.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -15,6 +15,7 @@
|
|||||||
#include <ox/model/types.hpp>
|
#include <ox/model/types.hpp>
|
||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
|
#include <ox/std/optional.hpp>
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
#include <ox/std/trace.hpp>
|
#include <ox/std/trace.hpp>
|
||||||
#include <ox/std/vector.hpp>
|
#include <ox/std/vector.hpp>
|
||||||
@ -26,22 +27,20 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
class MetalClawReaderTemplate {
|
class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<Reader>, ox::OpType::Read> {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FieldBitmapReader<const uint8_t*> m_fieldPresence;
|
FieldBitmapReader<Reader> m_fieldPresence;
|
||||||
std::size_t m_fields = 0;
|
std::size_t m_fields = 0;
|
||||||
std::size_t m_field = 0;
|
std::size_t m_field = 0;
|
||||||
int m_unionIdx = -1;
|
ox::Optional<int> m_unionIdx;
|
||||||
std::size_t m_buffIt = 0;
|
Reader &m_reader;
|
||||||
std::size_t m_buffLen = 0;
|
|
||||||
const uint8_t *m_buff = nullptr;
|
|
||||||
MetalClawReaderTemplate<HandlerMaker> *m_parent = nullptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen, int unionIdx = -1,
|
explicit constexpr MetalClawReaderTemplate(
|
||||||
MetalClawReaderTemplate<HandlerMaker> *parent = nullptr) noexcept;
|
Reader &reader,
|
||||||
|
ox::Optional<int> const&unionIdx = {}) noexcept;
|
||||||
|
|
||||||
constexpr ~MetalClawReaderTemplate() noexcept;
|
constexpr ~MetalClawReaderTemplate() noexcept;
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ class MetalClawReaderTemplate {
|
|||||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||||
|
|
||||||
template<std::size_t L>
|
template<std::size_t L>
|
||||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
constexpr Error field(const char*, IString<L> *val) noexcept;
|
||||||
|
|
||||||
constexpr Error fieldCString(const char*, char *val, std::size_t buffLen) noexcept;
|
constexpr Error fieldCString(const char*, char *val, std::size_t buffLen) noexcept;
|
||||||
|
|
||||||
@ -95,8 +94,7 @@ class MetalClawReaderTemplate {
|
|||||||
/**
|
/**
|
||||||
* Reads an string length from the current location in the buffer.
|
* Reads an string length from the current location in the buffer.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
constexpr Result<StringLength> stringLength(const char *name) noexcept;
|
||||||
constexpr StringLength stringLength(const char *name) noexcept;
|
|
||||||
|
|
||||||
template<typename T = std::nullptr_t>
|
template<typename T = std::nullptr_t>
|
||||||
constexpr ox::Error setTypeInfo(
|
constexpr ox::Error setTypeInfo(
|
||||||
@ -109,7 +107,7 @@ class MetalClawReaderTemplate {
|
|||||||
* Returns a MetalClawReader to parse a child object.
|
* Returns a MetalClawReader to parse a child object.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker> child(const char *name, int unionIdx = -1) noexcept;
|
constexpr MetalClawReaderTemplate<Reader> child(const char *name, ox::Optional<int> unionIdx = {}) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not the next field to be read is present.
|
* Indicates whether or not the next field to be read is present.
|
||||||
@ -128,142 +126,130 @@ class MetalClawReaderTemplate {
|
|||||||
|
|
||||||
constexpr void nextField() noexcept;
|
constexpr void nextField() noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
static constexpr auto opType() noexcept {
|
|
||||||
return OpType::Read;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Error readInteger(I *val) noexcept;
|
constexpr Error readInteger(I *val) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker>::MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen,
|
constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate(
|
||||||
int unionIdx,
|
Reader &reader,
|
||||||
MetalClawReaderTemplate *parent) noexcept:
|
ox::Optional<int> const&unionIdx) noexcept:
|
||||||
m_fieldPresence(buff, buffLen),
|
m_fieldPresence(reader),
|
||||||
m_unionIdx(unionIdx),
|
m_unionIdx(unionIdx),
|
||||||
m_buffLen(buffLen),
|
m_reader(reader) {
|
||||||
m_buff(buff),
|
|
||||||
m_parent(parent) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker>::~MetalClawReaderTemplate() noexcept {
|
constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept {
|
||||||
if (m_parent) {
|
|
||||||
m_parent->m_buffIt += m_buffIt;
|
|
||||||
}
|
|
||||||
if (m_field != m_fields) {
|
if (m_field != m_fields) {
|
||||||
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
|
oxTrace("ox.mc.MetalClawReader.error") << "MetalClawReader: incorrect fields number given";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int8_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int8_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int16_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int16_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int32_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int32_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int64_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int64_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint8_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint8_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint16_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint16_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint32_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint32_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint64_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint64_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, bool *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
auto valErr = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
||||||
*val = valErr.value;
|
*val = result.value;
|
||||||
oxReturnError(valErr.error);
|
oxReturnError(result);
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// array handler
|
// array handler
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
// read the list
|
// read the list
|
||||||
if (valLen >= len) {
|
if (valLen >= len) {
|
||||||
auto reader = child("");
|
auto reader = child({});
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
oxReturnError(handler.field("", &val[i]));
|
oxReturnError(handler.field({}, &val[i]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::mc::read::field(T)") << name << ", size:" << valLen;
|
oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen);
|
||||||
return OxError(MC_OUTBUFFENDED);
|
return OxError(McOutputBuffEnded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMap<String, T> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
oxRequire(g, m_reader.tellg());
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
oxReturnError(m_reader.seekg(g));
|
||||||
// read the list
|
// read the list
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
// this loop body needs to be in a lambda because of the potential alloca call
|
||||||
const auto keyLen = handler.stringLength(nullptr);
|
constexpr auto loopBody = [](auto &handler, auto &val) {
|
||||||
|
oxRequire(keyLen, handler.stringLength(nullptr));
|
||||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||||
auto wkeyPtr = wkey.get();
|
auto wkeyPtr = wkey.get();
|
||||||
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
|
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
|
||||||
oxReturnError(handler.field("", &val->operator[](wkey.get())));
|
return handler.field("", &val[wkeyPtr]);
|
||||||
|
};
|
||||||
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
|
oxReturnError(loopBody(handler, *val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,22 +257,23 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMa
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept {
|
||||||
if constexpr(isVector_v<T>) {
|
if constexpr(isVector_v<T>) {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
// set size of val if the field is present, don't worry about it if not
|
// set size of val if the field is present, don't worry about it if not
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
oxRequire(len, arrayLength(name, false));
|
oxRequire(len, arrayLength(name, false));
|
||||||
val->resize(len);
|
oxReturnError(ox::resizeVector(*val, len));
|
||||||
}
|
|
||||||
return field(name, val->data(), val->size());
|
return field(name, val->data(), val->size());
|
||||||
}
|
}
|
||||||
|
oxReturnError(ox::resizeVector(*val, 0));
|
||||||
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return {};
|
return {};
|
||||||
} else if constexpr(isArray_v<T>) {
|
} else if constexpr(isArray_v<T>) {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
// set size of val if the field is present, don't worry about it if not
|
// set size of val if the field is present, don't worry about it if not
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
oxRequire(len, arrayLength(name, false));
|
oxRequire(len, arrayLength(name, false));
|
||||||
@ -299,11 +286,10 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T
|
|||||||
++m_field;
|
++m_field;
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val) {
|
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
oxReturnError(model(reader.interface(), val));
|
||||||
oxReturnError(model(&handler, val));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
@ -311,44 +297,32 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename U, bool force>
|
template<typename U, bool force>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, UnionView<U, force> val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept {
|
||||||
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val.get()) {
|
if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
auto reader = child("", val.idx());
|
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
|
||||||
auto handler = HandlerMaker(&reader);
|
oxReturnError(model(reader.interface(), val.get()));
|
||||||
oxReturnError(model(&handler, val.get()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<std::size_t SmallStringSize>
|
template<std::size_t SmallStringSize>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(size, mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
const auto cap = size;
|
const auto cap = size;
|
||||||
*val = BasicString<SmallStringSize>(cap);
|
*val = BasicString<SmallStringSize>(cap);
|
||||||
auto data = val->data();
|
auto data = val->data();
|
||||||
// read the string
|
// read the string
|
||||||
if (static_cast<StringLength>(cap) < size) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
return OxError(MC_OUTBUFFENDED);
|
|
||||||
}
|
|
||||||
if (m_buffIt + size > m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
ox_strncpy(data, &m_buff[m_buffIt], size);
|
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
} else {
|
||||||
*val = "";
|
*val = "";
|
||||||
}
|
}
|
||||||
@ -357,81 +331,71 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, BasicS
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<std::size_t L>
|
template<std::size_t L>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, BString<L> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *val) noexcept {
|
||||||
return fieldCString(name, val->data(), val->cap());
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
}
|
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
if (size > buffLen) {
|
*val = IString<L>();
|
||||||
return OxError(MC_OUTBUFFENDED);
|
oxReturnError(val->resize(size));
|
||||||
|
auto const data = val->data();
|
||||||
|
// read the string
|
||||||
|
oxReturnError(m_reader.read(data, size));
|
||||||
|
} else {
|
||||||
|
*val = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_field;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
||||||
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
|
// read the length
|
||||||
|
std::size_t bytesRead = 0;
|
||||||
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
|
if (size > buffLen) {
|
||||||
|
return OxError(McOutputBuffEnded);
|
||||||
}
|
}
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate in case too small
|
// re-allocate in case too small
|
||||||
auto data = val;
|
auto data = val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
|
||||||
data[size] = 0;
|
data[size] = 0;
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val) noexcept {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate in case too small
|
// re-allocate in case too small
|
||||||
safeDelete(*val);
|
safeDelete(*val);
|
||||||
*val = new char[size + 1];
|
*val = new char[size + 1];
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
|
||||||
data[size] = 0;
|
data[size] = 0;
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate if too small
|
// re-allocate if too small
|
||||||
if (buffLen < size + 1) {
|
if (buffLen < size + 1) {
|
||||||
safeDelete(*val);
|
safeDelete(*val);
|
||||||
@ -440,13 +404,8 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*,
|
|||||||
}
|
}
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
|
||||||
data[size] = 0;
|
data[size] = 0;
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -458,18 +417,16 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*,
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Result<ArrayLength> MetalClawReaderTemplate<HandlerMaker>::arrayLength(const char*, bool pass) noexcept {
|
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto out = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead).value;
|
oxRequire(g, m_reader.tellg());
|
||||||
if (pass) {
|
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
if (!pass) {
|
||||||
|
oxReturnError(m_reader.seekg(g));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -477,20 +434,29 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<HandlerMaker>::arrayLength
|
|||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
|
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept {
|
||||||
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
|
// read the length
|
||||||
|
std::size_t bytesRead = 0;
|
||||||
|
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
|
||||||
|
oxReturnError(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::readInteger(I *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
if (m_buffIt >= m_buffLen) {
|
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
|
||||||
oxTrace("ox::MetalClaw::readInteger") << "Buffer ended";
|
oxReturnError(result);
|
||||||
return OxError(MC_BUFFENDED);
|
*val = result.value;
|
||||||
}
|
|
||||||
auto valErr = mc::decodeInteger<I>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(valErr.error);
|
|
||||||
*val = valErr.value;
|
|
||||||
} else {
|
} else {
|
||||||
*val = 0;
|
*val = 0;
|
||||||
}
|
}
|
||||||
@ -499,22 +465,17 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::readInteger(I *val) noexc
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T, typename CB>
|
template<typename T, typename CB>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
|
|
||||||
// read the list
|
// read the list
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
T val;
|
T val;
|
||||||
@ -527,50 +488,38 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb)
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr StringLength MetalClawReaderTemplate<HandlerMaker>::stringLength(const char*) noexcept {
|
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error MetalClawReaderTemplate<HandlerMaker>::setTypeInfo(
|
constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
|
||||||
const char*, int, const Vector<String>&, std::size_t fields) noexcept {
|
const char*, int, const Vector<String>&, std::size_t fields) noexcept {
|
||||||
m_fields = fields;
|
m_fields = fields;
|
||||||
m_buffIt = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
// Warning: narrow-conv
|
||||||
m_fieldPresence.setFields(static_cast<int>(fields));
|
return m_reader.seekg(
|
||||||
m_fieldPresence.setMaxLen(static_cast<int>(m_buffIt));
|
static_cast<int>((fields / 8 + 1) - (fields % 8 == 0)),
|
||||||
return {};
|
ox::ios_base::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker> MetalClawReaderTemplate<HandlerMaker>::child(const char*, int unionIdx) noexcept {
|
constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(
|
||||||
return MetalClawReaderTemplate<HandlerMaker>(m_buff + m_buffIt, m_buffLen - m_buffIt, unionIdx, this);
|
const char*,
|
||||||
|
ox::Optional<int> unionIdx) noexcept {
|
||||||
|
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(const char*) const noexcept {
|
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(const char*) const noexcept {
|
||||||
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(int fieldNo) const noexcept {
|
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int fieldNo) const noexcept {
|
||||||
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int MetalClawReaderTemplate<HandlerMaker>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
||||||
FieldBitmapReader<const uint8_t*> p(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
FieldBitmapReader<Reader> p(m_reader);
|
||||||
p.setFields(static_cast<int>(u.fieldCount()));
|
|
||||||
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
||||||
if (p.get(i)) {
|
if (p.get(i)) {
|
||||||
return static_cast<int>(i);
|
return static_cast<int>(i);
|
||||||
@ -579,32 +528,28 @@ constexpr int MetalClawReaderTemplate<HandlerMaker>::whichFieldPresent(const cha
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::nextField() noexcept {
|
constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
|
||||||
++m_field;
|
++m_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
using MetalClawReader = MetalClawReaderTemplate<[](auto r) {
|
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
|
||||||
return ModelHandlerInterface{r};
|
|
||||||
}>;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
|
Error readMC(ox::BufferView buff, T &val) noexcept {
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(buff), buffLen);
|
BufferReader br(buff);
|
||||||
ModelHandlerInterface handler(&reader);
|
MetalClawReader reader(br);
|
||||||
return model(&handler, val);
|
ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader);
|
||||||
|
return model(&handler, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Result<T> readMC(const char *buff, std::size_t buffLen) noexcept {
|
Result<T> readMC(ox::BufferView buff) noexcept {
|
||||||
T val;
|
Result<T> val;
|
||||||
oxReturnError(readMC(buff, buffLen, &val));
|
oxReturnError(readMC(buff, val.value));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
extern template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
|
||||||
Result<T> readMC(const Buffer &buff) noexcept {
|
|
||||||
return readMC<T>(buff.data(), buff.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
12
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
@ -8,9 +8,9 @@ target_link_libraries(
|
|||||||
OxMetalClaw
|
OxMetalClaw
|
||||||
)
|
)
|
||||||
|
|
||||||
add_test("[ox/mc] McTest Writer" McTest MetalClawWriter)
|
add_test("[ox/mc] Writer" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest MetalClawWriter)
|
||||||
add_test("[ox/mc] McTest Reader" McTest MetalClawReader)
|
add_test("[ox/mc] Reader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest MetalClawReader)
|
||||||
#add_test("[ox/mc] McTest MetalClawDef" McTest MetalClawDef)
|
#add_test("[ox/mc] MetalClawDef" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest MetalClawDef)
|
||||||
add_test("[ox/mc] McTest MetalClawModelValue" McTest MetalClawModelValue)
|
add_test("[ox/mc] MetalClawModelValue" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest MetalClawModelValue)
|
||||||
add_test("[ox/mc] McTest encodeInteger" McTest encodeInteger)
|
add_test("[ox/mc] encodeInteger" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest encodeInteger)
|
||||||
add_test("[ox/mc] McTest decodeInteger" McTest decodeInteger)
|
add_test("[ox/mc] decodeInteger" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/McTest decodeInteger)
|
||||||
|
123
deps/ox/src/ox/mc/test/tests.cpp
vendored
123
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -18,8 +18,8 @@ union TestUnion {
|
|||||||
static constexpr auto TypeName = "TestUnion";
|
static constexpr auto TypeName = "TestUnion";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
bool Bool;
|
bool Bool;
|
||||||
uint32_t Int = 5;
|
uint32_t Int;
|
||||||
char *CString;
|
char *CString{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestStructNest {
|
struct TestStructNest {
|
||||||
@ -27,7 +27,7 @@ struct TestStructNest {
|
|||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
bool Bool = false;
|
bool Bool = false;
|
||||||
uint32_t Int = 0;
|
uint32_t Int = 0;
|
||||||
ox::BString<32> BString = "";
|
ox::IString<32> IString = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestStruct {
|
struct TestStruct {
|
||||||
@ -45,10 +45,11 @@ struct TestStruct {
|
|||||||
int32_t Int8 = 0;
|
int32_t Int8 = 0;
|
||||||
int unionIdx = 1;
|
int unionIdx = 1;
|
||||||
TestUnion Union;
|
TestUnion Union;
|
||||||
ox::String String = "";
|
ox::String String;
|
||||||
ox::BString<32> BString = "";
|
ox::IString<32> IString = "";
|
||||||
uint32_t List[4] = {0, 0, 0, 0};
|
uint32_t List[4] = {0, 0, 0, 0};
|
||||||
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
||||||
|
ox::Vector<uint32_t> Vector2 = {1, 2, 3, 4, 5};
|
||||||
ox::HashMap<ox::String, int> Map;
|
ox::HashMap<ox::String, int> Map;
|
||||||
TestStructNest EmptyStruct;
|
TestStructNest EmptyStruct;
|
||||||
TestStructNest Struct;
|
TestStructNest Struct;
|
||||||
@ -71,13 +72,12 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcep
|
|||||||
oxModelBegin(TestStructNest)
|
oxModelBegin(TestStructNest)
|
||||||
oxModelField(Bool)
|
oxModelField(Bool)
|
||||||
oxModelField(Int)
|
oxModelField(Int)
|
||||||
oxModelField(BString)
|
oxModelField(IString)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
||||||
oxReturnError(io->template setTypeInfo<TestStruct>());
|
oxReturnError(io->template setTypeInfo<TestStruct>());
|
||||||
oxReturnError(io->field("Vector", &obj->Vector));
|
|
||||||
oxReturnError(io->field("Bool", &obj->Bool));
|
oxReturnError(io->field("Bool", &obj->Bool));
|
||||||
oxReturnError(io->field("Int", &obj->Int));
|
oxReturnError(io->field("Int", &obj->Int));
|
||||||
oxReturnError(io->field("Int1", &obj->Int1));
|
oxReturnError(io->field("Int1", &obj->Int1));
|
||||||
@ -95,25 +95,26 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
|
|||||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
||||||
}
|
}
|
||||||
oxReturnError(io->field("String", &obj->String));
|
oxReturnError(io->field("String", &obj->String));
|
||||||
oxReturnError(io->field("BString", &obj->BString));
|
oxReturnError(io->field("IString", &obj->IString));
|
||||||
oxReturnError(io->field("List", obj->List, 4));
|
oxReturnError(io->field("List", obj->List, 4));
|
||||||
|
oxReturnError(io->field("Vector", &obj->Vector));
|
||||||
|
oxReturnError(io->field("Vector2", &obj->Vector2));
|
||||||
oxReturnError(io->field("Map", &obj->Map));
|
oxReturnError(io->field("Map", &obj->Map));
|
||||||
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
|
||||||
oxReturnError(io->field("Struct", &obj->Struct));
|
oxReturnError(io->field("Struct", &obj->Struct));
|
||||||
|
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ox::String, ox::Error(*)()> tests = {
|
std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"MetalClawWriter",
|
"MetalClawWriter",
|
||||||
[] {
|
[] {
|
||||||
// This test doesn't confirm much, but it does show that the writer
|
// This test doesn't confirm much, but it does show that the writer
|
||||||
// doesn't segfault
|
// doesn't segfault
|
||||||
static constexpr size_t buffLen = 1024;
|
ox::Array<char, 1024> buff;
|
||||||
char buff[buffLen];
|
|
||||||
TestStruct ts;
|
TestStruct ts;
|
||||||
oxReturnError(ox::writeMC(buff, buffLen, ts));
|
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts));
|
||||||
oxReturnError(ox::writeMC(ts));
|
oxReturnError(ox::writeMC(ts));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
@ -126,22 +127,23 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
TestStruct testIn, testOut;
|
TestStruct testIn, testOut;
|
||||||
testIn.Bool = true;
|
testIn.Bool = true;
|
||||||
testIn.Int = 42;
|
testIn.Int = 42;
|
||||||
testIn.Union.Int = 42;
|
testIn.IString = "Test String 1";
|
||||||
testIn.String = "Test String 0";
|
testIn.String = "Test String 2";
|
||||||
testIn.BString = "Test String 1";
|
testIn.Vector = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
|
||||||
|
testIn.Vector2 = {};
|
||||||
testIn.List[0] = 1;
|
testIn.List[0] = 1;
|
||||||
testIn.List[1] = 2;
|
testIn.List[1] = 2;
|
||||||
testIn.List[2] = 3;
|
testIn.List[2] = 3;
|
||||||
testIn.List[3] = 4;
|
testIn.List[3] = 4;
|
||||||
testIn.Map["asdf"] = 93;
|
testIn.Struct.Bool = true;
|
||||||
testIn.Map["aoeu"] = 94;
|
|
||||||
testIn.Struct.Bool = false;
|
|
||||||
testIn.Struct.Int = 300;
|
testIn.Struct.Int = 300;
|
||||||
testIn.Struct.BString = "Test String 2";
|
testIn.Struct.IString = "Test String 3";
|
||||||
|
testIn.unionIdx = 1;
|
||||||
|
testIn.Union.Int = 93;
|
||||||
// run tests
|
// run tests
|
||||||
const auto [buff, err] = ox::writeMC(testIn);
|
const auto [buff, err] = ox::writeMC(testIn);
|
||||||
oxAssert(err, "writeMC failed");
|
oxAssert(err, "writeMC failed");
|
||||||
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readMC failed");
|
oxAssert(ox::readMC(buff, testOut), "readMC failed");
|
||||||
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
||||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||||
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
||||||
@ -155,22 +157,24 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
||||||
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
|
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
|
||||||
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
||||||
oxAssert(testIn.BString == testOut.BString, "BString value mismatch");
|
oxDebugf("{}", testOut.IString.len());
|
||||||
|
oxExpect(testIn.IString, testOut.IString);
|
||||||
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
||||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||||
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
||||||
oxAssert(testIn.Vector[0] == testOut.Vector[0], "Vector[0] value mismatch");
|
oxAssert(testIn.Vector.size() == testOut.Vector.size(), "Vector size mismatch");
|
||||||
oxAssert(testIn.Vector[1] == testOut.Vector[1], "Vector[1] value mismatch");
|
for (auto i = 0u; i < testIn.Vector.size(); ++i) {
|
||||||
oxAssert(testIn.Vector[2] == testOut.Vector[2], "Vector[2] value mismatch");
|
oxAssert(testIn.Vector[i] == testOut.Vector[i], ox::sfmt("Vector[{}] value mismatch", i));
|
||||||
oxAssert(testIn.Vector[3] == testOut.Vector[3], "Vector[3] value mismatch");
|
}
|
||||||
|
oxAssert(testIn.Vector2.size() == testOut.Vector2.size(), "Vector2 size mismatch");
|
||||||
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] 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.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
|
||||||
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool 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.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
|
||||||
oxAssert(testIn.EmptyStruct.BString == testOut.EmptyStruct.BString, "EmptyStruct.BString value mismatch");
|
oxAssert(testIn.EmptyStruct.IString == testOut.EmptyStruct.IString, "EmptyStruct.IString value mismatch");
|
||||||
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
|
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
|
||||||
oxAssert(testIn.Struct.BString == testOut.Struct.BString, "Struct.BString value mismatch");
|
oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch");
|
||||||
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
|
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
@ -264,6 +268,9 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
};
|
};
|
||||||
oxAssert(check(uint32_t(14)), "Decode of 14 failed.");
|
oxAssert(check(uint32_t(14)), "Decode of 14 failed.");
|
||||||
|
oxAssert(check(int8_t(-1)), "Decode of -1 failed.");
|
||||||
|
oxAssert(check(int16_t(-1)), "Decode of -1 failed.");
|
||||||
|
oxAssert(check(int32_t(-1)), "Decode of -1 failed.");
|
||||||
oxAssert(check(int64_t(-1)), "Decode of -1 failed.");
|
oxAssert(check(int64_t(-1)), "Decode of -1 failed.");
|
||||||
oxAssert(check(int64_t(-2)), "Decode of -2 failed.");
|
oxAssert(check(int64_t(-2)), "Decode of -2 failed.");
|
||||||
oxAssert(check(int64_t(-127)), "Decode of -127 failed.");
|
oxAssert(check(int64_t(-127)), "Decode of -127 failed.");
|
||||||
@ -297,14 +304,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
TestStruct testIn;
|
TestStruct testIn;
|
||||||
testIn.Bool = true;
|
testIn.Bool = true;
|
||||||
testIn.Int = 42;
|
testIn.Int = 42;
|
||||||
testIn.BString = "Test String 1";
|
testIn.IString = "Test String 1";
|
||||||
testIn.List[0] = 1;
|
testIn.List[0] = 1;
|
||||||
testIn.List[1] = 2;
|
testIn.List[1] = 2;
|
||||||
testIn.List[2] = 3;
|
testIn.List[2] = 3;
|
||||||
testIn.List[3] = 4;
|
testIn.List[3] = 4;
|
||||||
testIn.Struct.Bool = true;
|
testIn.Struct.Bool = true;
|
||||||
testIn.Struct.Int = 300;
|
testIn.Struct.Int = 300;
|
||||||
testIn.Struct.BString = "Test String 2";
|
testIn.Struct.IString = "Test String 2";
|
||||||
testIn.unionIdx = 1;
|
testIn.unionIdx = 1;
|
||||||
testIn.Union.Int = 93;
|
testIn.Union.Int = 93;
|
||||||
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed");
|
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed");
|
||||||
@ -313,28 +320,28 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
oxAssert(typeErr, "Descriptor write failed");
|
oxAssert(typeErr, "Descriptor write failed");
|
||||||
ox::ModelObject testOut;
|
ox::ModelObject testOut;
|
||||||
oxReturnError(testOut.setType(type));
|
oxReturnError(testOut.setType(type));
|
||||||
oxAssert(ox::readMC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
|
||||||
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
|
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||||
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
|
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||||
oxAssert(testOut["BString"].get<ox::String>() == testIn.BString.c_str(), "testOut.String failed");
|
oxAssert(testOut.at("IString").unwrap()->get<ox::String>() == testIn.IString.c_str(), "testOut.String failed");
|
||||||
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
|
oxAssert(testOut.at("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||||
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
|
auto &testOutStruct = testOut.at("Struct").unwrap()->get<ox::ModelObject>();
|
||||||
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
|
auto &testOutUnion = testOut.at("Union").unwrap()->get<ox::ModelUnion>();
|
||||||
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
|
auto &testOutList = testOut.at("List").unwrap()->get<ox::ModelValueVector>();
|
||||||
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
|
auto testOutStructCopy = testOut.at("Struct").unwrap()->get<ox::ModelObject>();
|
||||||
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
|
auto testOutUnionCopy = testOut.at("Union").unwrap()->get<ox::ModelUnion>();
|
||||||
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
|
auto testOutListCopy = testOut.at("List").unwrap()->get<ox::ModelValueVector>();
|
||||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||||
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
oxAssert(testOutStruct.at("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||||
oxAssert(testOutStruct["BString"].get<ox::String>() == testIn.Struct.BString.c_str(), "testOut.Struct.BString failed");
|
oxAssert(testOutStruct.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString failed");
|
||||||
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
oxAssert(testOut.at("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||||
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
oxAssert(testOutUnion.at("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||||
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
oxAssert(testOutStructCopy.at("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||||
oxAssert(testOutStructCopy["BString"].get<ox::String>() == testIn.Struct.BString.c_str(), "testOut.Struct.BString (copy) failed");
|
oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed");
|
||||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
@ -351,19 +358,20 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
TestStruct testIn, testOut;
|
TestStruct testIn, testOut;
|
||||||
testIn.Bool = true;
|
testIn.Bool = true;
|
||||||
testIn.Int = 42;
|
testIn.Int = 42;
|
||||||
testIn.BString = "Test String 1";
|
testIn.IString = "Test String 1";
|
||||||
testIn.List[0] = 1;
|
testIn.List[0] = 1;
|
||||||
testIn.List[1] = 2;
|
testIn.List[1] = 2;
|
||||||
testIn.List[2] = 3;
|
testIn.List[2] = 3;
|
||||||
testIn.List[3] = 4;
|
testIn.List[3] = 4;
|
||||||
testIn.Struct.Bool = false;
|
testIn.Struct.Bool = false;
|
||||||
testIn.Struct.Int = 300;
|
testIn.Struct.Int = 300;
|
||||||
testIn.Struct.BString = "Test String 2";
|
testIn.Struct.IString = "Test String 2";
|
||||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed");
|
oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed");
|
||||||
ox::TypeStore typeStore;
|
ox::TypeStore typeStore;
|
||||||
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
||||||
oxAssert(typeErr, "Descriptor write failed");
|
oxAssert(typeErr, "Descriptor write failed");
|
||||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, dataBuff, dataBuffLen,
|
ox::BufferReader br({dataBuff, dataBuffLen});
|
||||||
|
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br,
|
||||||
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
||||||
//std::cout << f.fieldName.c_str() << '\n';
|
//std::cout << f.fieldName.c_str() << '\n';
|
||||||
auto fieldName = f.fieldName.c_str();
|
auto fieldName = f.fieldName.c_str();
|
||||||
@ -456,11 +464,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char **args) {
|
int main(int argc, const char **args) {
|
||||||
if (argc > 0) {
|
if (argc < 2) {
|
||||||
auto testName = args[1];
|
oxError("Must specify test to run");
|
||||||
if (tests.find(testName) != tests.end()) {
|
|
||||||
oxAssert(tests[testName](), "Test failed...");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
auto const testName = args[1];
|
||||||
|
auto const func = tests.find(testName);
|
||||||
|
if (func != tests.end()) {
|
||||||
|
oxAssert(func->second(), "Test returned Error");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
8
deps/ox/src/ox/mc/types.hpp
vendored
8
deps/ox/src/ox/mc/types.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
using StringLength = uint32_t;
|
using StringLength = std::size_t;
|
||||||
using ArrayLength = uint32_t;
|
using ArrayLength = std::size_t;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
2
deps/ox/src/ox/mc/write.cpp
vendored
2
deps/ox/src/ox/mc/write.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
157
deps/ox/src/ox/mc/write.hpp
vendored
157
deps/ox/src/ox/mc/write.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
#include <ox/std/hashmap.hpp>
|
#include <ox/std/hashmap.hpp>
|
||||||
|
#include <ox/std/optional.hpp>
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
#include <ox/std/types.hpp>
|
#include <ox/std/types.hpp>
|
||||||
#include <ox/std/units.hpp>
|
#include <ox/std/units.hpp>
|
||||||
@ -34,47 +35,38 @@ class MetalClawWriter {
|
|||||||
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
|
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
|
||||||
FieldBitmap m_fieldPresence;
|
FieldBitmap m_fieldPresence;
|
||||||
int m_field = 0;
|
int m_field = 0;
|
||||||
int m_unionIdx = -1;
|
ox::Optional<int> m_unionIdx;
|
||||||
std::size_t m_writerBeginP{};
|
std::size_t m_writerBeginP{};
|
||||||
Writer &m_writer;
|
Writer &m_writer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr explicit MetalClawWriter(Writer &writer, int unionIdx = -1) noexcept;
|
constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept;
|
||||||
|
|
||||||
constexpr ~MetalClawWriter() noexcept = default;
|
constexpr ~MetalClawWriter() noexcept = default;
|
||||||
|
|
||||||
constexpr Error field(const char*, CommonPtrWith<int8_t> auto *val) noexcept;
|
constexpr Error field(const char*, const int8_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<int16_t> auto *val) noexcept;
|
constexpr Error field(const char*, const int16_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<int32_t> auto *val) noexcept;
|
constexpr Error field(const char*, const int32_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<int64_t> auto *val) noexcept;
|
constexpr Error field(const char*, const int64_t *val) noexcept;
|
||||||
|
|
||||||
constexpr Error field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept;
|
constexpr Error field(const char*, const uint8_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept;
|
constexpr Error field(const char*, const uint16_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept;
|
constexpr Error field(const char*, const uint32_t *val) noexcept;
|
||||||
constexpr Error field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept;
|
constexpr Error field(const char*, const uint64_t *val) noexcept;
|
||||||
|
|
||||||
constexpr Error field(const char*, CommonPtrWith<bool> auto *val) noexcept;
|
constexpr Error field(const char*, const bool *val) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error field(const char*, T *val, std::size_t len) noexcept;
|
constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
|
||||||
|
|
||||||
template<std::size_t SmallStringSize>
|
template<std::size_t SmallStringSize>
|
||||||
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
||||||
|
|
||||||
template<std::size_t L>
|
template<std::size_t L>
|
||||||
constexpr Error field(const char*, const BString<L> *val) noexcept;
|
constexpr Error field(const char*, const IString<L> *val) noexcept;
|
||||||
|
|
||||||
template<std::size_t SmallStringSize>
|
|
||||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
|
||||||
|
|
||||||
template<std::size_t L>
|
|
||||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
|
||||||
|
|
||||||
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
|
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
|
||||||
|
|
||||||
@ -84,20 +76,8 @@ class MetalClawWriter {
|
|||||||
|
|
||||||
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
||||||
|
|
||||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
|
||||||
return fieldCString(name, const_cast<const char**>(val), buffLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
|
||||||
return fieldCString(name, const_cast<const char**>(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
|
||||||
return fieldCString(name, const_cast<const char*>(val), buffLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error field(const char*, T *val) noexcept;
|
constexpr Error field(const char*, const T *val) noexcept;
|
||||||
|
|
||||||
template<typename U, bool force = false>
|
template<typename U, bool force = false>
|
||||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||||
@ -135,7 +115,7 @@ class MetalClawWriter {
|
|||||||
private:
|
private:
|
||||||
constexpr Error appendInteger(Integer_c auto val) noexcept {
|
constexpr Error appendInteger(Integer_c auto val) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
auto mi = mc::encodeInteger(val);
|
auto mi = mc::encodeInteger(val);
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
|
||||||
fieldSet = true;
|
fieldSet = true;
|
||||||
@ -151,7 +131,7 @@ extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
|
|||||||
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
|
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx) noexcept:
|
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept:
|
||||||
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
|
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
|
||||||
m_unionIdx(unionIdx),
|
m_unionIdx(unionIdx),
|
||||||
m_writerBeginP(writer.tellp()),
|
m_writerBeginP(writer.tellp()),
|
||||||
@ -159,48 +139,48 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
|
||||||
return appendInteger(*val);
|
return appendInteger(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
|
||||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
|
||||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
@ -211,7 +191,7 @@ template<Writer_c Writer>
|
|||||||
template<std::size_t SmallStringSize>
|
template<std::size_t SmallStringSize>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
// write the length
|
// write the length
|
||||||
const auto strLen = mc::encodeInteger(val->len());
|
const auto strLen = mc::encodeInteger(val->len());
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length));
|
||||||
@ -226,27 +206,15 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<Sm
|
|||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
template<std::size_t L>
|
template<std::size_t L>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L> *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept {
|
||||||
return fieldCString(name, val->data(), val->cap());
|
return fieldCString(name, val->data(), val->len());
|
||||||
}
|
|
||||||
|
|
||||||
template<Writer_c Writer>
|
|
||||||
template<std::size_t SmallStringSize>
|
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
|
|
||||||
return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Writer_c Writer>
|
|
||||||
template<std::size_t L>
|
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, BString<L> *val) noexcept {
|
|
||||||
return fieldCString(name, val->data(), val->cap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
|
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
|
||||||
const auto strLen = *val ? ox_strlen(*val) : 0;
|
const auto strLen = *val ? ox::strlen(*val) : 0;
|
||||||
// write the length
|
// write the length
|
||||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
|
||||||
@ -272,7 +240,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const ch
|
|||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
|
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
// write the length
|
// write the length
|
||||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
|
||||||
@ -287,21 +255,22 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
|
|||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept {
|
||||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||||
return field(nullptr, val->data(), val->size());
|
return field(nullptr, val->data(), val->size());
|
||||||
} else {
|
} else {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
|
auto const writeIdx = m_writer.tellp();
|
||||||
MetalClawWriter<Writer> writer(m_writer);
|
MetalClawWriter<Writer> writer(m_writer);
|
||||||
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
|
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
|
||||||
oxReturnError(model(&handler, val));
|
oxReturnError(model(&handler, val));
|
||||||
oxReturnError(writer.finalize());
|
oxReturnError(writer.finalize());
|
||||||
fieldSet = true;
|
fieldSet = writeIdx != m_writer.tellp();
|
||||||
}
|
}
|
||||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,35 +278,37 @@ template<Writer_c Writer>
|
|||||||
template<typename U, bool force>
|
template<typename U, bool force>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
MetalClawWriter<Writer> writer(m_writer, val.idx());
|
auto const writeIdx = m_writer.tellp();
|
||||||
|
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
|
||||||
ModelHandlerInterface handler{&writer};
|
ModelHandlerInterface handler{&writer};
|
||||||
oxReturnError(model(&handler, val.get()));
|
oxReturnError(model(&handler, val.get()));
|
||||||
oxReturnError(writer.finalize());
|
oxReturnError(writer.finalize());
|
||||||
fieldSet = true;
|
fieldSet = writeIdx != m_writer.tellp();
|
||||||
}
|
}
|
||||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val, std::size_t len) noexcept {
|
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept {
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
// write the length
|
// write the length
|
||||||
const auto arrLen = mc::encodeInteger(len);
|
const auto arrLen = mc::encodeInteger(len);
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
|
||||||
|
auto const writeIdx = m_writer.tellp();
|
||||||
MetalClawWriter<Writer> writer(m_writer);
|
MetalClawWriter<Writer> writer(m_writer);
|
||||||
ModelHandlerInterface handler{&writer};
|
ModelHandlerInterface handler{&writer};
|
||||||
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
// write the array
|
// write the array
|
||||||
for (std::size_t i = 0; i < len; i++) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
oxReturnError(handler.field("", &val[i]));
|
oxReturnError(handler.field("", &val[i]));
|
||||||
}
|
}
|
||||||
oxReturnError(writer.finalize());
|
oxReturnError(writer.finalize());
|
||||||
fieldSet = true;
|
fieldSet = writeIdx != m_writer.tellp();
|
||||||
}
|
}
|
||||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||||
++m_field;
|
++m_field;
|
||||||
@ -350,7 +321,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
|||||||
const auto &keys = val->keys();
|
const auto &keys = val->keys();
|
||||||
const auto len = keys.size();
|
const auto len = keys.size();
|
||||||
bool fieldSet = false;
|
bool fieldSet = false;
|
||||||
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||||
// write the length
|
// write the length
|
||||||
const auto arrLen = mc::encodeInteger(len);
|
const auto arrLen = mc::encodeInteger(len);
|
||||||
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
|
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
|
||||||
@ -359,15 +330,19 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
|||||||
ModelHandlerInterface handler{&writer};
|
ModelHandlerInterface handler{&writer};
|
||||||
// double len for both key and value
|
// double len for both key and value
|
||||||
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2));
|
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2));
|
||||||
// write the array
|
// this loop body needs to be in a lambda because of the potential alloca call
|
||||||
for (std::size_t i = 0; i < len; i++) {
|
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
|
||||||
const auto &key = keys[i];
|
const auto keyLen = key.len();
|
||||||
const auto keyLen = ox_strlen(key);
|
|
||||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||||
memcpy(wkey, key.c_str(), keyLen + 1);
|
memcpy(wkey.get(), key.c_str(), keyLen + 1);
|
||||||
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
|
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
|
||||||
oxRequireM(value, val->at(key));
|
oxRequireM(value, val.at(key));
|
||||||
oxReturnError(handler.field("", value));
|
return handler.field("", value);
|
||||||
|
};
|
||||||
|
// write the array
|
||||||
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
|
auto const&key = keys[i];
|
||||||
|
oxReturnError(loopBody(handler, key, *val));
|
||||||
}
|
}
|
||||||
oxReturnError(writer.finalize());
|
oxReturnError(writer.finalize());
|
||||||
fieldSet = true;
|
fieldSet = true;
|
||||||
@ -377,12 +352,6 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Writer_c Writer>
|
|
||||||
template<typename T>
|
|
||||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, HashMap<String, T> *val) noexcept {
|
|
||||||
return field(name, const_cast<const HashMap<String, T>*>(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Writer_c Writer>
|
template<Writer_c Writer>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
|
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
|
||||||
@ -417,7 +386,7 @@ Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Buffer> writeMC(const auto &val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||||
Buffer buff(buffReserveSz);
|
Buffer buff(buffReserveSz);
|
||||||
BufferWriter bw(&buff, 0);
|
BufferWriter bw(&buff, 0);
|
||||||
oxReturnError(writeMC(bw, val));
|
oxReturnError(writeMC(bw, val));
|
||||||
@ -425,7 +394,7 @@ Result<Buffer> writeMC(const auto &val, std::size_t buffReserveSz = 2 * units::K
|
|||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error writeMC(char *buff, std::size_t buffLen, const auto &val, std::size_t *sizeOut = nullptr) noexcept {
|
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
|
||||||
CharBuffWriter bw(buff, buffLen);
|
CharBuffWriter bw(buff, buffLen);
|
||||||
oxReturnError(writeMC(bw, val));
|
oxReturnError(writeMC(bw, val));
|
||||||
if (sizeOut) {
|
if (sizeOut) {
|
||||||
|
4
deps/ox/src/ox/model/def.hpp
vendored
4
deps/ox/src/ox/model/def.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -13,5 +13,5 @@
|
|||||||
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>());
|
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>());
|
||||||
#define oxModelEnd() return OxError(0); }
|
#define oxModelEnd() return OxError(0); }
|
||||||
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
|
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
|
||||||
#define oxModelFieldRename(serFieldName, objFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
|
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
|
||||||
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith<modelName> auto*) noexcept
|
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith<modelName> auto*) noexcept
|
||||||
|
4
deps/ox/src/ox/model/descread.hpp
vendored
4
deps/ox/src/ox/model/descread.hpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
4
deps/ox/src/ox/model/desctypes.cpp
vendored
4
deps/ox/src/ox/model/desctypes.cpp
vendored
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "desctypes.hpp"
|
#include "desctypes.hpp"
|
||||||
|
6
deps/ox/src/ox/model/desctypes.hpp
vendored
6
deps/ox/src/ox/model/desctypes.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -37,12 +37,12 @@ constexpr auto buildTypeId() noexcept {
|
|||||||
static constexpr auto buildTypeId(CRStringView name, int version,
|
static constexpr auto buildTypeId(CRStringView name, int version,
|
||||||
const TypeParamPack &typeParams = {}) noexcept {
|
const TypeParamPack &typeParams = {}) noexcept {
|
||||||
String tp;
|
String tp;
|
||||||
if (typeParams.size()) {
|
if (!typeParams.empty()) {
|
||||||
tp = "#";
|
tp = "#";
|
||||||
for (const auto &p : typeParams) {
|
for (const auto &p : typeParams) {
|
||||||
tp += p + ",";
|
tp += p + ",";
|
||||||
}
|
}
|
||||||
tp = tp.substr(0, tp.len() - 1);
|
tp.resize(tp.len() - 1);
|
||||||
tp += "#";
|
tp += "#";
|
||||||
}
|
}
|
||||||
return ox::sfmt("{}{};{}", name, tp, version);
|
return ox::sfmt("{}{};{}", name, tp, version);
|
||||||
|
2
deps/ox/src/ox/model/descwrite.cpp
vendored
2
deps/ox/src/ox/model/descwrite.cpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
35
deps/ox/src/ox/model/descwrite.hpp
vendored
35
deps/ox/src/ox/model/descwrite.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -9,7 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
#include <ox/std/bstring.hpp>
|
#include <ox/std/istring.hpp>
|
||||||
#include <ox/std/memory.hpp>
|
#include <ox/std/memory.hpp>
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
#include <ox/std/trace.hpp>
|
#include <ox/std/trace.hpp>
|
||||||
@ -152,7 +152,7 @@ class TypeDescWriter {
|
|||||||
|
|
||||||
template<std::size_t sz>
|
template<std::size_t sz>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr const DescriptorType *type(const BString<sz> *val) const noexcept;
|
constexpr const DescriptorType *type(const IString<sz> *val) const noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -175,7 +175,8 @@ class TypeDescWriter {
|
|||||||
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {}
|
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error TypeDescWriter::setTypeInfo(CRStringView typeName, int typeVersion,
|
constexpr ox::Error TypeDescWriter::setTypeInfo(
|
||||||
|
CRStringView typeName, int typeVersion,
|
||||||
const TypeParamPack &typeParams, std::size_t) noexcept {
|
const TypeParamPack &typeParams, std::size_t) noexcept {
|
||||||
PrimitiveType pt;
|
PrimitiveType pt;
|
||||||
if constexpr(is_union_v<T>) {
|
if constexpr(is_union_v<T>) {
|
||||||
@ -197,7 +198,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, const T*, std::size_t,
|
|||||||
constexpr typename remove_pointer<T>::type *p = nullptr;
|
constexpr typename remove_pointer<T>::type *p = nullptr;
|
||||||
const auto t = type(p);
|
const auto t = type(p);
|
||||||
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
|
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
|
||||||
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
|
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
@ -208,7 +209,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val
|
|||||||
if (m_type) {
|
if (m_type) {
|
||||||
const auto t = type(val);
|
const auto t = type(val);
|
||||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName);
|
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
@ -218,15 +219,17 @@ template<typename T>
|
|||||||
constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept {
|
constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept {
|
||||||
if (m_type) {
|
if (m_type) {
|
||||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||||
return field(name, val->data(), 0, detail::buildSubscriptStack(val));
|
typename T::value_type *data = nullptr;
|
||||||
|
return field(name, data, 0, detail::buildSubscriptStack(val));
|
||||||
} else if constexpr(isSmartPtr_v<T>) {
|
} else if constexpr(isSmartPtr_v<T>) {
|
||||||
return field(name, val->get(), 0, detail::buildSubscriptStack(val));
|
typename T::value_type *data = nullptr;
|
||||||
|
return field(name, data, 0, detail::buildSubscriptStack(val));
|
||||||
} else if constexpr(is_pointer_v<T>) {
|
} else if constexpr(is_pointer_v<T>) {
|
||||||
return field(name, val, 0, detail::buildSubscriptStack(val));
|
return field(name, val, 0, detail::buildSubscriptStack(val));
|
||||||
} else {
|
} else {
|
||||||
const auto t = type(val);
|
const auto t = type(val);
|
||||||
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
|
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
|
||||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, buildTypeId(*t));
|
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, buildTypeId(*t));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +240,7 @@ template<typename ...Args>
|
|||||||
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
|
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
|
||||||
constexpr auto s = "";
|
constexpr auto s = "";
|
||||||
const auto t = type(s);
|
const auto t = type(s);
|
||||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName);
|
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +334,7 @@ constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t sz>
|
template<std::size_t sz>
|
||||||
constexpr const DescriptorType *TypeDescWriter::type(const BString<sz>*) const noexcept {
|
constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept {
|
||||||
constexpr auto PT = PrimitiveType::String;
|
constexpr auto PT = PrimitiveType::String;
|
||||||
return getType(types::BString, 0, PT, 0);
|
return getType(types::BString, 0, PT, 0);
|
||||||
}
|
}
|
||||||
@ -344,7 +347,7 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
|
|||||||
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
||||||
return type;
|
return type;
|
||||||
} else {
|
} else {
|
||||||
auto dt = ox::make_unique<DescriptorType>(tn, typeVersion, pt, typeParams);
|
auto dt = ox::make_unique<DescriptorType>(String(tn), typeVersion, pt, typeParams);
|
||||||
dt->length = b;
|
dt->length = b;
|
||||||
const auto out = dt.get();
|
const auto out = dt.get();
|
||||||
const auto typeId = buildTypeId(tn, typeVersion, typeParams);
|
const auto typeId = buildTypeId(tn, typeVersion, typeParams);
|
||||||
@ -356,15 +359,15 @@ constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typ
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
|
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
|
||||||
TypeDescWriter writer(typeStore);
|
TypeDescWriter writer(typeStore);
|
||||||
ModelHandlerInterface handler(&writer);
|
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
|
||||||
if (std::is_constant_evaluated()) {
|
if (std::is_constant_evaluated()) {
|
||||||
std::allocator<T> a;
|
std::allocator<T> a;
|
||||||
T *t = a.allocate(1);
|
T *t = a.allocate(1);
|
||||||
oxReturnError(model(&handler, t));
|
oxReturnError(model(&handler, t));
|
||||||
a.deallocate(t, 1);
|
a.deallocate(t, 1);
|
||||||
} else {
|
} else {
|
||||||
T *t = reinterpret_cast<T*>(ox_alloca(sizeof(T)));
|
auto t = ox_malloca(sizeof(T), T);
|
||||||
oxReturnError(model(&handler, t));
|
oxReturnError(model(&handler, t.get()));
|
||||||
}
|
}
|
||||||
return writer.definition();
|
return writer.definition();
|
||||||
}
|
}
|
||||||
@ -372,7 +375,7 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
|
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
|
||||||
TypeDescWriter writer(typeStore);
|
TypeDescWriter writer(typeStore);
|
||||||
ModelHandlerInterface handler(&writer);
|
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
|
||||||
oxReturnError(model(&handler, val));
|
oxReturnError(model(&handler, val));
|
||||||
return writer.definition();
|
return writer.definition();
|
||||||
}
|
}
|
||||||
|
2
deps/ox/src/ox/model/fieldcounter.hpp
vendored
2
deps/ox/src/ox/model/fieldcounter.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
6
deps/ox/src/ox/model/metadata.hpp
vendored
6
deps/ox/src/ox/model/metadata.hpp
vendored
@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
#include <ox/std/bstring.hpp>
|
#include <ox/std/istring.hpp>
|
||||||
#include <ox/std/memory.hpp>
|
#include <ox/std/memory.hpp>
|
||||||
#include <ox/std/string.hpp>
|
#include <ox/std/string.hpp>
|
||||||
#include <ox/std/trace.hpp>
|
#include <ox/std/trace.hpp>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user