Compare commits
	
		
			561 Commits
		
	
	
		
			a7cf267385
			...
			david/clar
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e009f68fbe | |||
| 671fa54f6f | |||
| 517432679b | |||
| b31c01f724 | |||
| f41213f13f | |||
| 28be7c4650 | |||
| 2f340b13b2 | |||
| 312c818866 | |||
| 0d69d0c4a2 | |||
| 81a0b8c820 | |||
| 172b5aee90 | |||
| 2b5338a9df | |||
| 8a430faf4c | |||
| e59382dd60 | |||
| 3006e77ef3 | |||
| 59c112a69c | |||
| 31b39982c5 | |||
| 5476417be2 | |||
| e03be694c2 | |||
| 490c0368bc | |||
| a24fc407c5 | |||
| e38b85b4f4 | |||
| f7c3c02c4c | |||
| 8f0f1fea39 | |||
| 2f36a3f6f0 | |||
| 07e5bf9054 | |||
| aacff3daf9 | |||
| e27eee50f0 | |||
| fd610454d6 | |||
| e61d4647b5 | |||
| c275c5f5e6 | |||
| fbf49ba511 | |||
| 92f74b27d1 | |||
| 934f0c9232 | |||
| ee9a3e1152 | |||
| 16886cdf1c | |||
| 08b9508d83 | |||
| 69bd968f98 | |||
| 4e7dc66610 | |||
| bea0cf5a0c | |||
| c7bc2a954f | |||
| 7372036a0a | |||
| 7461d832b6 | |||
| 6052798fea | |||
| fae1e73e54 | |||
| 51f2905c9c | |||
| 0c866d1b96 | |||
| fdf39d1a25 | |||
| a523a75e4b | |||
| cdaa64ed3f | |||
| 801d35c823 | |||
| 37b5fcc0f7 | |||
| f5f2c3bee6 | |||
| f6ef2b5acb | |||
| bf958a4a6e | |||
| 6a70e478a6 | |||
| 671b8edaad | |||
| 952637a1ea | |||
| 7569698e95 | |||
| 21713ba945 | |||
| 73273b6fa7 | |||
| 9f040392c7 | |||
| f4f7e5d053 | |||
| f847289bd4 | |||
| 94b0020d15 | |||
| c54c0bad38 | |||
| b9ffae0269 | |||
| 003f3e01c6 | |||
| 9028e74af0 | |||
| f5ccab5f2c | |||
| c27726a4a9 | |||
| 37cfa927d1 | |||
| 0efed70b57 | |||
| baf5fa3199 | |||
| bd24a775b2 | |||
| 857587c18b | |||
| eb3d53c955 | |||
| 14d58f3f5b | |||
| 5f2397903a | |||
| 58e0ecb469 | |||
| 8838bf420e | |||
| bddc544d7c | |||
| a9437191bf | |||
| 9d8da7ccda | |||
| 394b568e72 | |||
| 78e9f70db6 | |||
| 12e5623fe6 | |||
| cfdfb0a8c9 | |||
| 56e665301f | |||
| 7415ce4bd9 | |||
| 05f42150a1 | |||
| 8ea2bc6934 | |||
| c780924122 | |||
| 8c538560ca | |||
| c3e75bdb55 | |||
| 4419dff299 | |||
| e78c405046 | |||
| 6b7c5d896e | |||
| a33a73d73a | |||
| 536999c070 | |||
| e1cfcc8b5f | |||
| 514cb97835 | |||
| 4b5218c4f1 | |||
| 2ca77173d3 | |||
| cce5f52f96 | |||
| b55993294a | |||
| d8f847d707 | |||
| a5535ef59a | |||
| 8419b137e5 | |||
| ed1160ec74 | |||
| 1e21778059 | |||
| 78379f58c8 | |||
| 4322f720ba | |||
| 26f1a6051f | |||
| c4c1d4777b | |||
| fab012d3e7 | |||
| a90380f377 | |||
| 312097a799 | |||
| a40198ab8d | |||
| 52d8c0bdc8 | |||
| c19d7f4ea3 | |||
| 159b7e7ee7 | |||
| c93eec4f05 | |||
| e7e7a22390 | |||
| 26d5048e67 | |||
| 3b8f97cc41 | |||
| f1e68e0a04 | |||
| d6e4ab7a24 | |||
| 2000b2deee | |||
| 7d92400f6d | |||
| cb304ecf28 | |||
| ea17377700 | |||
| c424bde06d | |||
| ee7d5c6d51 | |||
| 99247cee32 | |||
| 7b8ddc189a | |||
| a6814030ee | |||
| 9937a01042 | |||
| abcf2adc56 | |||
| 05f9023550 | |||
| 5ba0bcf963 | |||
| 3ccadba2f5 | |||
| 00e52b6491 | |||
| ae40487990 | |||
| 84b612c693 | |||
| 3c2a6b047e | |||
| 626da322d9 | |||
| 0de428a2e5 | |||
| 8a52df4f76 | |||
| efec6eb3c8 | |||
| 56eeb24900 | |||
| ae81f6b3de | |||
| c1108301c0 | |||
| 83fbe6ac74 | |||
| 80b452833f | |||
| 0fa394333b | |||
| cae7535034 | |||
| df87832324 | |||
| d585794cbe | |||
| 209658549c | |||
| 02383a4aed | |||
| 185a76282a | |||
| b722b4f701 | |||
| 459ab5aad9 | |||
| 565f621cfc | |||
| 9589ca9148 | |||
| 164db5007b | |||
| cbfb167d29 | |||
| e7b83be867 | |||
| 649da5fca8 | |||
| aa095f7680 | |||
| bb99c99f01 | |||
| 7f0dcdd280 | |||
| 6029ad5d47 | |||
| 26fe266b09 | |||
| 091eda7b44 | |||
| 9676ea5978 | |||
| de8ac10653 | |||
| 88a6cd59f3 | |||
| cd43fb7f38 | |||
| 136f422401 | |||
| e773d6f0ee | |||
| 7da2f68d30 | |||
| d20889aef1 | |||
| 50c8302f4a | |||
| d8195d300d | |||
| a8c1387d5a | |||
| ff1e8f260b | |||
| d4329981e7 | |||
| 0003454311 | |||
| 8c6b2234ec | |||
| aad4b8a44c | |||
| 7cab133127 | |||
| 640ac85de4 | |||
| b8d7658626 | |||
| 2503bb3b2c | |||
| e5dd448fe7 | |||
| 4770bb6a93 | |||
| c0bac696dc | |||
| 95f7c33419 | |||
| 535d8876d3 | |||
| 845e433221 | |||
| 5169a607cf | |||
| 8f03af99a7 | |||
| ee63a4a1e4 | |||
| ac29f7a0f2 | |||
| 89ae226b1d | |||
| 477834ac04 | |||
| 97b707b61c | |||
| e86180e842 | |||
| 035ba8810f | |||
| f1c2113dd3 | |||
| 56b79f414d | |||
| 844656d557 | |||
| 849aceb86d | |||
| eef51a6d2b | |||
| c84b85102c | |||
| 3fe62464c3 | |||
| db55fc722f | |||
| 2094450898 | |||
| 889bec04b1 | |||
| ac1e34d4cd | |||
| 55ed75f44d | |||
| 2751872c59 | |||
| 2a3cd35cc4 | |||
| b66f459f75 | |||
| 3910f4e77c | |||
| c0e96216ae | |||
| f9512d72e8 | |||
| b7f2c169ec | |||
| 1e5057d6e6 | |||
| c6255e3224 | |||
| 02230ef619 | |||
| 9b6b60e4d1 | |||
| b9a26ab61e | |||
| a521887ddd | |||
| 5ca7e2f226 | |||
| 125a235dd1 | |||
| 91a7129f8f | |||
| df48a232ec | |||
| ab11b885e6 | |||
| 36fc25fb7e | |||
| 4803cca334 | |||
| 6bd74611cd | |||
| c3f9cf9a64 | |||
| 646ab1283f | |||
| 74cf055610 | |||
| 0d8ba1b154 | |||
| 20edbb7f38 | |||
| 6febc7cc73 | |||
| b94d6b5061 | |||
| b3952cabbc | |||
| 2ffc11b04e | |||
| 96cace2cbb | |||
| 472f5702bd | |||
| c0ac4345d3 | |||
| fbebf4ef83 | |||
| 20513f7749 | |||
| 25a7873ea2 | |||
| d0a32e247e | |||
| 03d4a5736e | |||
| a2e41e6527 | |||
| 40a7caff90 | |||
| 26fc5565e8 | |||
| 388541ce32 | |||
| 6c194667b9 | |||
| 62d0579f40 | |||
| 202595b2a6 | |||
| cb21ff3f04 | |||
| 2a8e3c2dc4 | |||
| 998066d377 | |||
| fefb876fe7 | |||
| 5979e9885e | |||
| a17abe4639 | |||
| d62f913855 | |||
| 12bb7475fc | |||
| df2c7e2b67 | |||
| 713aec887b | |||
| 3089cd7afc | |||
| 00638bc812 | |||
| e002109829 | |||
| b4798fd2ab | |||
| 3c804bf62a | |||
| d39d552bd9 | |||
| b7202a2b0d | |||
| 4e27a4c1f5 | |||
| 4ef31762d0 | |||
| 8b22a8f339 | |||
| d45ff05bcd | |||
| 671dd86206 | |||
| 0abadc1850 | |||
| 4e068d628c | |||
| 4461f99fa4 | |||
| cd1f4bdaa3 | |||
| 4728699585 | |||
| 105a1e5559 | |||
| 1bc18e34a8 | |||
| fb8d295fcb | |||
| 8459d3baea | |||
| 804d78e116 | |||
| 5351e9aa0a | |||
| b5954f15c5 | |||
| 5dce9dd377 | |||
| 0570f76236 | |||
| e22b658a67 | |||
| 56b9cb6ebf | |||
| eaa9a2415e | |||
| 95256a9a0d | |||
| 2286238abc | |||
| 13f0bf57e4 | |||
| 8eb1ac215b | |||
| e132f2fd1b | |||
| 12f6b22c8b | |||
| 6c858e0c4e | |||
| c6b58f7c63 | |||
| a22aafaf96 | |||
| 6298ac3a21 | |||
| cd63afacfe | |||
| 2859183742 | |||
| 8d04af691e | |||
| 055165974e | |||
| be51838775 | |||
| 1207dadee8 | |||
| 109e1898cc | |||
| a24bf7ffb9 | |||
| 046834c2b9 | |||
| f840240aac | |||
| cfa91d3d39 | |||
| f7a7a66a6a | |||
| 5145595d57 | |||
| f01d303381 | |||
| 098c8cb844 | |||
| 04ad0f0264 | |||
| 695e7a4561 | |||
| 7d53028faf | |||
| 6c34198f58 | |||
| 7e3e046109 | |||
| f63c58169f | |||
| e40b11246d | |||
| 161194c8b2 | |||
| 48603ea2c5 | |||
| e2f2a17315 | |||
| e8a0ce88c5 | |||
| 82e2ea747f | |||
| ff666eda9b | |||
| 0d8b82ba49 | |||
| 5598dfdd87 | |||
| 6ef462adcc | |||
| 9511cb5719 | |||
| 1cc1d561e2 | |||
| d15a0df7da | |||
| e1282b6bae | |||
| 5fe7c14ccb | |||
| 42165ba2d6 | |||
| 1af4da43ad | |||
| 4fa879a09e | |||
| fd8f1a29c6 | |||
| 9fda2763ba | |||
| cda23ac4af | |||
| c36b244dd3 | |||
| 335d278f5e | |||
| f987b02c65 | |||
| 3c056276c1 | |||
| 87e2fdefcf | |||
| 672b92b363 | |||
| 762a6517b2 | |||
| d141154a45 | |||
| 6170647c0c | |||
| 48e45c7dd6 | |||
| 5d3d9229b7 | |||
| d54e93d836 | |||
| 830f8fe3e4 | |||
| 7b638538aa | |||
| 2016f6e605 | |||
| 240effd305 | |||
| 6bc629e02c | |||
| f6f2acd67b | |||
| 0146d38405 | |||
| 75d8e7bb89 | |||
| 6b53eaf6b1 | |||
| 16c32273ac | |||
| 1567a6e29d | |||
| 89d543bcbc | |||
| d68e64931b | |||
| 1cbc576286 | |||
| 500b93562c | |||
| 800ca85176 | |||
| cc466a9f1d | |||
| 9d1155843e | |||
| a2139c09b2 | |||
| a3e5f27ab8 | |||
| 643f95ec80 | |||
| 6924147686 | |||
| 6e2b4fa7b4 | |||
| 4e5c749918 | |||
| 66229de77f | |||
| 7eb37c5318 | |||
| 7a21b20711 | |||
| 894be237f2 | |||
| 92e9d9cbfc | |||
| b29b9a9b3a | |||
| 721f844214 | |||
| a3d6a58cc8 | |||
| e598e7fe27 | |||
| ba9e720f9f | |||
| 8e816a261f | |||
| 5b9929ab3d | |||
| ceb54b3f1b | |||
| 8764444758 | |||
| ce9a0b1fdb | |||
| f7a468ea1e | |||
| 861d177a27 | |||
| 3936756b36 | |||
| 3e78ec3fe5 | |||
| 3c3d53b40c | |||
| 151d7c5736 | |||
| 4e4d8d2c3f | |||
| 03d1fd2857 | |||
| 6701decc91 | |||
| 6cff526647 | |||
| dd50bd0249 | |||
| 55a1660242 | |||
| ed365dfef5 | |||
| 23a09e4a13 | |||
| b69e7ebb98 | |||
| 418d6e3f22 | |||
| c44d8678cb | |||
| eb4cd7106d | |||
| d259770f32 | |||
| 80bad608f7 | |||
| 2bce9a2baf | |||
| 791b7746f3 | |||
| 842e3587fd | |||
| 318e79004b | |||
| 9f338a7429 | |||
| 645e48af7b | |||
| ef92c8df13 | |||
| 849d50be8e | |||
| 845092f114 | |||
| 75819a1797 | |||
| d66da85753 | |||
| 98ddb08abd | |||
| 8d1701b0bb | |||
| 1048e522fd | |||
| ee59da4aa3 | |||
| 1ba64cb5d8 | |||
| 462bebf6dd | |||
| e3f84c4e75 | |||
| 6837a0556d | |||
| ede2c8ca37 | |||
| f50367f7d5 | |||
| e758e03d2b | |||
| 835e3270ce | |||
| 480dd5ece4 | |||
| dba6bb5800 | |||
| 40a456e54a | |||
| bf5be00c12 | |||
| dc7c2559d6 | |||
| a75c4a11d3 | |||
| 347a165762 | |||
| fd64bfae13 | |||
| aaeec20ac9 | |||
| 37030f9c11 | |||
| 462f2bca4c | |||
| dc72500b98 | |||
| 962fe8bc22 | |||
| 305eb62647 | |||
| 4754359a21 | |||
| dc07f3d58b | |||
| fcdcfd10d1 | |||
| b74f6a7ace | |||
| ac7e5be187 | |||
| ed910c0beb | |||
| 345fb03857 | |||
| 9881253f2a | |||
| 96d27eecd1 | |||
| 28ebe93b77 | |||
| e849e7a3dd | |||
| e6777b0ad7 | |||
| c488c336de | |||
| 003f97201f | |||
| d85a10af84 | |||
| ff05d860c4 | |||
| 7679403742 | |||
| c51a45e1ba | |||
| a6e24ff2b6 | |||
| e0ec9e0c5f | |||
| 9a42a9b9d9 | |||
| 03a05c511e | |||
| bd91137d27 | |||
| 161640fa11 | |||
| 2b7d12945e | |||
| e42126c956 | |||
| 36942cca18 | |||
| b14f1d5000 | |||
| 1bf4f246c2 | |||
| edda8e010e | |||
| 3308b4dd72 | |||
| 27f4703a9a | |||
| 6af00d9a2e | |||
| 86b9f9316e | |||
| a0ed1b3f62 | |||
| 8dad624b21 | |||
| dc6605fd48 | |||
| c78d3cf638 | |||
| cee4f65d4a | |||
| cd3eeeef14 | |||
| 287d42f2b9 | |||
| dbbaaa46b9 | |||
| 9b8a8c4e46 | |||
| e44fa288fd | |||
| e13c6e812b | |||
| cb55b31afa | |||
| ab3f9e1627 | |||
| 8f25ef96ff | |||
| e13eebaf0b | |||
| 114f5c6685 | |||
| df44fe235b | |||
| 72f4db3d5e | |||
| 8a9ff971a1 | |||
| 5a8da59df1 | |||
| afa3a13d41 | |||
| 6522cf8a43 | |||
| f772e48b36 | |||
| 13bfe88195 | |||
| 5025475414 | |||
| 3c7652efc2 | |||
| 941bc71348 | |||
| bfe890ae00 | |||
| ab5bc1adb6 | |||
| abf7548ab5 | |||
| e2682b5ef7 | |||
| 792ad41499 | |||
| e4ae23e114 | |||
| 67187d5ec5 | |||
| 3271a37115 | |||
| ea9f50de8d | |||
| ea3c5e03fb | |||
| c8c4177d60 | |||
| 76b540e3b8 | |||
| 2062748676 | |||
| 135f0e4ce8 | |||
| cb16687641 | |||
| cb3ef0e79d | |||
| 0a62d90065 | |||
| ba7e3929e9 | |||
| 36c4022b56 | |||
| e22b25e54c | |||
| c6efabaa1d | |||
| 1f6fefdb68 | |||
| 1e34f91ebd | |||
| 35cb2ece9f | |||
| 66cd5c4a7e | |||
| 0daf938f76 | |||
| b90ab27a65 | |||
| c711f4358e | |||
| 84cb03d807 | |||
| 945a55f94a | |||
| 2173b12c67 | |||
| aa970b1fc0 | |||
| 6ad79b305c | 
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| sample_project text eol=lf | ||||
| @@ -4,7 +4,7 @@ on: [push] | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: nostalgia | ||||
|     runs-on: olympic | ||||
|     steps: | ||||
|       - name: Check out repository code | ||||
|         uses: actions/checkout@v3 | ||||
| @@ -17,3 +17,10 @@ jobs: | ||||
|       - run: make purge configure-release | ||||
|       - run: make build | ||||
|       - run: make test | ||||
|       - run: make install | ||||
|       - run: mv dist/linux-x86_64-release nostalgia-linux-x86_64 | ||||
|       - run: tar cf nostalgia-linux-x86_64.tar nostalgia-linux-x86_64 | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         with: | ||||
|           name: nostalgia-linux-x86_64 | ||||
|           path: nostalgia-linux-x86_64.tar | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -6,12 +6,14 @@ | ||||
| .mypy_cache | ||||
| .stfolder | ||||
| .stignore | ||||
| scripts/__pycache__ | ||||
| .vs | ||||
| util/scripts/__pycache__ | ||||
| pyenv | ||||
| CMakeLists.txt.user | ||||
| ROM.oxfs | ||||
| Session.vim | ||||
| build | ||||
| cmake-build-* | ||||
| compile_commands.json | ||||
| dist | ||||
| graph_info.json | ||||
|   | ||||
| @@ -2,4 +2,4 @@ | ||||
| source: | ||||
| - src | ||||
| copyright_notice: |- | ||||
|   Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. | ||||
|   Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. | ||||
|   | ||||
| @@ -1,44 +0,0 @@ | ||||
| { | ||||
|   "version": "0.2.1", | ||||
|   "defaults": {}, | ||||
|   "configurations": [ | ||||
|     { | ||||
|       "type": "default", | ||||
|       "project": "CMakeLists.txt", | ||||
|       "projectTarget": "nostalgia.exe (Install)", | ||||
|       "name": "nostalgia.exe (Install)", | ||||
|       "args": [ | ||||
|         "${projectDir}/sample_project" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "default", | ||||
|       "project": "CMakeLists.txt", | ||||
|       "projectTarget": "nostalgia.exe", | ||||
|       "name": "nostalgia.exe", | ||||
|       "args": [ | ||||
|         "${projectDir}/sample_project" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "default", | ||||
|       "project": "CMakeLists.txt", | ||||
|       "projectTarget": "nostalgia-studio.exe (Install)", | ||||
|       "name": "nostalgia-studio.exe (Install)", | ||||
|       "args": [ | ||||
|         "-profile", | ||||
|         "${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "default", | ||||
|       "project": "CMakeLists.txt", | ||||
|       "projectTarget": "nostalgia-studio.exe", | ||||
|       "name": "nostalgia-studio.exe", | ||||
|       "args": [ | ||||
|         "-profile", | ||||
|         "${projectDir}/src/nostalgia/studio/nostalgia-studio-dev.json" | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										77
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,35 +1,68 @@ | ||||
| BC_VAR_PROJECT_NAME=nostalgia | ||||
| BC_VAR_PROJECT_NAME_CAP=Nostalgia | ||||
| BC_VAR_DEVENV_ROOT=util | ||||
| BUILDCORE_PATH=deps/buildcore | ||||
| include ${BUILDCORE_PATH}/base.mk | ||||
|  | ||||
| ifeq ($(BC_VAR_OS),darwin) | ||||
| 	NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio | ||||
| 	PROJECT_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio | ||||
| 	MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA | ||||
| else | ||||
| 	NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio | ||||
| 	PROJECT_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio | ||||
| 	MGBA=mgba-qt | ||||
| endif | ||||
| PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP} | ||||
|  | ||||
| .PHONY: pkg-gba | ||||
| pkg-gba: build | ||||
| 	${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME} | ||||
| pkg-gba: build-pack build-gba-player | ||||
| 	${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP} | ||||
|  | ||||
| .PHONY: pkg-mac | ||||
| pkg-mac: install | ||||
| 	${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-dmg.py NostalgiaStudio | ||||
|  | ||||
| .PHONY: generate-studio-rsrc | ||||
| generate-studio-rsrc: | ||||
| 	${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/olympic/studio/applib/src/rsrc.json | ||||
| 	${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json | ||||
|  | ||||
| .PHONY: build-gba-player | ||||
| build-gba-player: | ||||
| 	cmake --build ./build/gba-* | ||||
|  | ||||
| .PHONY: build-player | ||||
| build-player: | ||||
| 	${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME_CAP} | ||||
|  | ||||
| .PHONY: build-pack | ||||
| build-pack: | ||||
| 	cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME}-pack | ||||
|  | ||||
|  | ||||
| .PHONY: run | ||||
| run: build | ||||
| 	./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project | ||||
| run: build-player | ||||
| 	${PROJECT_PLAYER} sample_project | ||||
|  | ||||
| .PHONY: build-studio | ||||
| build-studio: | ||||
| 	cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME_CAP}Studio | ||||
|  | ||||
| .PHONY: run-studio | ||||
| run-studio: build | ||||
| 	${NOSTALGIA_STUDIO} | ||||
| run-studio: build-studio | ||||
| 	${PROJECT_STUDIO} | ||||
|  | ||||
| .PHONY: gba-run | ||||
| gba-run: pkg-gba | ||||
| 	${MGBA} ${BC_VAR_PROJECT_NAME}.gba | ||||
| 	${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba | ||||
|  | ||||
| .PHONY: debug | ||||
| debug: build | ||||
| 	${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project | ||||
| 	${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project | ||||
|  | ||||
| .PHONY: debug-studio | ||||
| debug-studio: build | ||||
| 	${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO} | ||||
| 	${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO} | ||||
|  | ||||
|  | ||||
| .PHONY: configure-gba | ||||
| configure-gba: | ||||
| @@ -38,3 +71,25 @@ configure-gba: | ||||
| .PHONY: configure-gba-debug | ||||
| configure-gba-debug: | ||||
| 	${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH} | ||||
|  | ||||
| .PHONY: loc | ||||
| loc: | ||||
| 	${BC_PY3} util/scripts/loc.py \ | ||||
| 		--search-dirs \ | ||||
| 			src \ | ||||
| 			deps/ox/src \ | ||||
| 			deps/buildcore \ | ||||
| 			deps/gbabuildcore \ | ||||
| 			deps/glutils \ | ||||
| 			deps/teagba \ | ||||
| 		--include-exts \ | ||||
| 			.cpp \ | ||||
| 			.hpp \ | ||||
| 			.py \ | ||||
| 			.s \ | ||||
| 			.cmake \ | ||||
| 		--exclude-paths \ | ||||
| 			deps/teagba/src/gba_crt0.s \ | ||||
| 			src/olympic/studio/applib/src/font.cpp \ | ||||
| 			src/olympic/studio/applib/src/font.hpp \ | ||||
| 			src/nostalgia/studio/icondata.cpp | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/buildcore/base.mk
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/buildcore/base.mk
									
									
									
									
										vendored
									
									
								
							| @@ -93,7 +93,7 @@ purge: | ||||
| 	${BC_CMD_RM_RF} compile_commands.json | ||||
| .PHONY: test | ||||
| test: build | ||||
| 	${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS} | ||||
| 	${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS} | ||||
| 	${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test | ||||
| .PHONY: test-verbose | ||||
| test-verbose: build | ||||
|   | ||||
							
								
								
									
										7
									
								
								deps/buildcore/scripts/pybb.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								deps/buildcore/scripts/pybb.py
									
									
									
									
										vendored
									
									
								
							| @@ -11,6 +11,7 @@ | ||||
| # "Python Busy Box" - adds cross-platform equivalents to Unix commands that | ||||
| #                     don't translate well to that other operating system | ||||
|  | ||||
| import multiprocessing | ||||
| import os | ||||
| import platform | ||||
| import shutil | ||||
| @@ -57,7 +58,11 @@ def cmake_build(base_path: str, target: Optional[str]) -> int: | ||||
|         path = os.path.join(base_path, d) | ||||
|         if not os.path.isdir(path): | ||||
|             continue | ||||
|         args = ['cmake', '--build', path] | ||||
|         args = ['cmake', '--build', path, f'-j{multiprocessing.cpu_count()}'] | ||||
|         if path.endswith('release'): | ||||
|             args.append('--config=release') | ||||
|         elif path.endswith('debug'): | ||||
|             args.append('--config=debug') | ||||
|         if target is not None: | ||||
|             args.extend(['--target', target]) | ||||
|         err = subprocess.run(args).returncode | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/buildcore/scripts/util.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/buildcore/scripts/util.py
									
									
									
									
										vendored
									
									
								
							| @@ -35,4 +35,6 @@ def get_arch() -> str: | ||||
|     arch = platform.machine().lower() | ||||
|     if arch == 'amd64': | ||||
|         arch = 'x86_64' | ||||
|     elif arch == 'aarch64': | ||||
|         arch = 'arm64' | ||||
|     return arch | ||||
|   | ||||
							
								
								
									
										4
									
								
								deps/gbabuildcore/base.cmake
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								deps/gbabuildcore/base.cmake
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") | ||||
| #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables") | ||||
| #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork") | ||||
|   | ||||
							
								
								
									
										13
									
								
								deps/glad/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								deps/glad/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +1,11 @@ | ||||
| add_library(glad OBJECT src/glad.c) | ||||
| target_include_directories(glad PUBLIC include) | ||||
| add_library(glad src/glad.c) | ||||
|  | ||||
| target_include_directories(glad PUBLIC include) | ||||
|  | ||||
| install( | ||||
| 	TARGETS | ||||
| 		glad | ||||
| 	DESTINATION | ||||
| 		LIBRARY DESTINATION lib | ||||
| 		ARCHIVE DESTINATION lib | ||||
| ) | ||||
|   | ||||
							
								
								
									
										46
									
								
								deps/glutils/include/glutils/glutils.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								deps/glutils/include/glutils/glutils.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -89,7 +89,7 @@ struct GLObject: public Base { | ||||
| 		return id; | ||||
| 	} | ||||
|  | ||||
| 	constexpr operator const GLuint&() const noexcept { | ||||
| 	constexpr operator GLuint const&() const noexcept { | ||||
| 		return id; | ||||
| 	} | ||||
|  | ||||
| @@ -135,7 +135,7 @@ struct FrameBuffer { | ||||
| 		return fbo.id; | ||||
| 	} | ||||
|  | ||||
| 	constexpr operator const GLuint&() const noexcept { | ||||
| 	constexpr operator GLuint const&() const noexcept { | ||||
| 		return fbo.id; | ||||
| 	} | ||||
|  | ||||
| @@ -158,14 +158,14 @@ struct FrameBuffer { | ||||
|  | ||||
| class FrameBufferBind { | ||||
| 	private: | ||||
| 		static const FrameBuffer *s_activeFb; | ||||
| 		const FrameBuffer *m_restoreFb = nullptr; | ||||
| 		static FrameBuffer const *s_activeFb; | ||||
| 		FrameBuffer const *m_restoreFb = nullptr; | ||||
| 	public: | ||||
| 		explicit FrameBufferBind(const FrameBuffer &fb) noexcept; | ||||
| 		explicit FrameBufferBind(FrameBuffer const &fb) noexcept; | ||||
| 		~FrameBufferBind() noexcept; | ||||
| }; | ||||
|  | ||||
| void bind(const FrameBuffer &fb) noexcept; | ||||
| void bind(FrameBuffer const &fb) noexcept; | ||||
|  | ||||
| struct ShaderVarSet { | ||||
| 	GLsizei len{}; | ||||
| @@ -176,7 +176,7 @@ struct ProgramSource { | ||||
| 	ox::Vector<glutils::ShaderVarSet> const shaderParams; | ||||
| 	GLsizei const rowLen = [this] { | ||||
| 		GLsizei len{}; | ||||
| 		for (auto const&v : shaderParams) { | ||||
| 		for (auto const &v : shaderParams) { | ||||
| 			len += v.len; | ||||
| 		} | ||||
| 		return len; | ||||
| @@ -187,23 +187,23 @@ struct ProgramSource { | ||||
| 	ox::String const geomShader{}; | ||||
| }; | ||||
|  | ||||
| ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept; | ||||
| ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept; | ||||
|  | ||||
| ox::Result<GLProgram> buildShaderProgram( | ||||
| 		ox::CStringView const&vert, | ||||
| 		ox::CStringView const&frag, | ||||
| 		ox::CStringView const&geo = "") noexcept; | ||||
| 		ox::CStringView const &vert, | ||||
| 		ox::CStringView const &frag, | ||||
| 		ox::CStringView const &geo = "") noexcept; | ||||
|  | ||||
| void setupShaderParams( | ||||
| 		GLProgram const&shader, | ||||
| 		ox::Vector<ShaderVarSet> const&vars, | ||||
| 		GLProgram const &shader, | ||||
| 		ox::Vector<ShaderVarSet> const &vars, | ||||
| 		GLsizei vertexRowLen) noexcept; | ||||
|  | ||||
| void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept; | ||||
| void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept; | ||||
|  | ||||
| glutils::GLVertexArray generateVertexArrayObject() noexcept; | ||||
| GLVertexArray generateVertexArrayObject() noexcept; | ||||
|  | ||||
| glutils::GLBuffer generateBuffer() noexcept; | ||||
| GLBuffer generateBuffer() noexcept; | ||||
|  | ||||
| [[nodiscard]] | ||||
| FrameBuffer generateFrameBuffer(int width, int height) noexcept; | ||||
| @@ -215,20 +215,20 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept; | ||||
|  */ | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept; | ||||
|  | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept; | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept; | ||||
|  | ||||
| struct BufferSet { | ||||
| 	glutils::GLVertexArray vao; | ||||
| 	glutils::GLBuffer vbo; | ||||
| 	glutils::GLBuffer ebo; | ||||
| 	glutils::GLTexture tex; | ||||
| 	GLVertexArray vao; | ||||
| 	GLBuffer vbo; | ||||
| 	GLBuffer ebo; | ||||
| 	GLTexture tex; | ||||
| 	ox::Vector<float> vertices; | ||||
| 	ox::Vector<GLuint> elements; | ||||
| }; | ||||
|  | ||||
| void sendVbo(BufferSet const&bs) noexcept; | ||||
| void sendVbo(BufferSet const &bs) noexcept; | ||||
|  | ||||
| void sendEbo(BufferSet const&bs) noexcept; | ||||
| void sendEbo(BufferSet const &bs) noexcept; | ||||
|  | ||||
| void clearScreen() noexcept; | ||||
|  | ||||
|   | ||||
							
								
								
									
										81
									
								
								deps/glutils/src/glutils.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										81
									
								
								deps/glutils/src/glutils.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -46,9 +46,9 @@ template struct GLObject<deleteVertexArray>; | ||||
| template struct GLObject<deleteProgram>; | ||||
| template struct GLObject<deleteShader>; | ||||
|  | ||||
| const FrameBuffer *FrameBufferBind::s_activeFb = nullptr; | ||||
| FrameBuffer const *FrameBufferBind::s_activeFb = nullptr; | ||||
|  | ||||
| FrameBufferBind::FrameBufferBind(const FrameBuffer &fb) noexcept: m_restoreFb(s_activeFb) { | ||||
| FrameBufferBind::FrameBufferBind(FrameBuffer const &fb) noexcept: m_restoreFb(s_activeFb) { | ||||
| 	s_activeFb = &fb; | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, fb); | ||||
| 	glViewport(0, 0, fb.width, fb.height); | ||||
| @@ -64,15 +64,15 @@ FrameBufferBind::~FrameBufferBind() noexcept { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void bind(const FrameBuffer &fb) noexcept { | ||||
| void bind(FrameBuffer const &fb) noexcept { | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, fb); | ||||
| 	glViewport(0, 0, fb.width, fb.height); | ||||
| } | ||||
|  | ||||
|  | ||||
| static ox::Result<GLShader> buildShader( | ||||
| 		GLuint shaderType, | ||||
| 		const GLchar *src, | ||||
| 		GLuint const shaderType, | ||||
| 		GLchar const *src, | ||||
| 		ox::StringViewCR shaderName) noexcept { | ||||
| 	GLShader shader(glCreateShader(shaderType)); | ||||
| 	glShaderSource(shader, 1, &src, nullptr); | ||||
| @@ -83,13 +83,13 @@ static ox::Result<GLShader> buildShader( | ||||
| 		ox::Vector<char> errMsg(ox::units::KB); | ||||
| 		glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data()); | ||||
| 		oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data()); | ||||
| 		return OxError(1, "shader compile error"); | ||||
| 		return ox::Error(1, "shader compile error"); | ||||
| 	} | ||||
| 	return shader; | ||||
| } | ||||
|  | ||||
| ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { | ||||
| 	oxRequireM(program, buildShaderProgram( | ||||
| ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept { | ||||
| 	OX_REQUIRE_M(program, buildShaderProgram( | ||||
| 			src.vertShader, | ||||
| 			src.fragShader, | ||||
| 			src.geomShader)); | ||||
| @@ -98,11 +98,11 @@ ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { | ||||
| } | ||||
|  | ||||
| void setupShaderParams( | ||||
| 		GLProgram const&shader, | ||||
| 		ox::Vector<ShaderVarSet> const&vars, | ||||
| 		GLProgram const &shader, | ||||
| 		ox::Vector<ShaderVarSet> const &vars, | ||||
| 		GLsizei vertexRowLen) noexcept { | ||||
| 	// setup vars | ||||
| 	for (size_t lenWritten = 0; auto const&v : vars) { | ||||
| 	for (size_t lenWritten = 0; auto const &v : vars) { | ||||
| 		auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str())); | ||||
| 		glEnableVertexAttribArray(attr); | ||||
| 		glVertexAttribPointer( | ||||
| @@ -113,27 +113,27 @@ void setupShaderParams( | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept { | ||||
| void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept { | ||||
| 	// get row len | ||||
| 	GLsizei vertexRowLen{}; | ||||
| 	for (auto const&v : vars) { | ||||
| 	for (auto const &v : vars) { | ||||
| 		vertexRowLen += v.len; | ||||
| 	} | ||||
| 	setupShaderParams(shader, vars, vertexRowLen); | ||||
| } | ||||
|  | ||||
| ox::Result<GLProgram> buildShaderProgram( | ||||
| 		ox::CStringView const&vert, | ||||
| 		ox::CStringView const&frag, | ||||
| 		ox::CStringView const&geo) noexcept { | ||||
| 		ox::CStringView const &vert, | ||||
| 		ox::CStringView const &frag, | ||||
| 		ox::CStringView const &geo) noexcept { | ||||
| 	GLProgram prgm(glCreateProgram()); | ||||
| 	oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); | ||||
| 	OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); | ||||
| 	glAttachShader(prgm, vs); | ||||
| 	if (geo.c_str() && geo.bytes() != 0) { | ||||
| 		oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad")); | ||||
| 		OX_REQUIRE(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad")); | ||||
| 		glAttachShader(prgm, gs); | ||||
| 	} | ||||
| 	oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad")); | ||||
| 	OX_REQUIRE(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad")); | ||||
| 	glAttachShader(prgm, fs); | ||||
| 	glLinkProgram(prgm); | ||||
| 	return prgm; | ||||
| @@ -162,16 +162,30 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept { | ||||
| 	// color texture | ||||
| 	glGenTextures(1, &fb.color.id); | ||||
| 	glBindTexture(GL_TEXTURE_2D, fb.color); | ||||
| 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); | ||||
| 	glTexImage2D( | ||||
| 		GL_TEXTURE_2D, | ||||
| 		0, | ||||
| 		GL_RGB, | ||||
| 		width, | ||||
| 		height, | ||||
| 		0, | ||||
| 		GL_RGB, | ||||
| 		GL_UNSIGNED_BYTE, | ||||
| 		nullptr); | ||||
| 	glGenerateMipmap(GL_TEXTURE_2D); | ||||
| 	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 | ||||
| 	glGenRenderbuffers(1, &fb.depth.id); | ||||
| 	glBindRenderbuffer(GL_RENDERBUFFER, fb.depth); | ||||
| 	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); | ||||
| 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth); | ||||
| 	glFramebufferRenderbuffer( | ||||
| 		GL_FRAMEBUFFER, | ||||
| 		GL_DEPTH_STENCIL_ATTACHMENT, | ||||
| 		GL_RENDERBUFFER, | ||||
| 		fb.depth); | ||||
| 	// verify FBO | ||||
| 	oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete"); | ||||
| 	// restore primary FB | ||||
| @@ -189,7 +203,16 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept { | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, fb); | ||||
| 	// color texture | ||||
| 	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 | ||||
| @@ -201,7 +224,7 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept { | ||||
| 	glBindRenderbuffer(GL_RENDERBUFFER, 0); | ||||
| } | ||||
|  | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept { | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, int const width, int const height) noexcept { | ||||
| 	if (!fb) { | ||||
| 		fb = generateFrameBuffer(width, height); | ||||
| 		return; | ||||
| @@ -209,18 +232,18 @@ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept { | ||||
| 	resizeFrameBuffer(fb, width, height); | ||||
| } | ||||
|  | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept { | ||||
| void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept { | ||||
| 	resizeInitFrameBuffer(fb, sz.width, sz.height); | ||||
| } | ||||
|  | ||||
| void sendVbo(BufferSet const&bs) noexcept { | ||||
| 	const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size()); | ||||
| void sendVbo(BufferSet const &bs) noexcept { | ||||
| 	auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size()); | ||||
| 	glBindBuffer(GL_ARRAY_BUFFER, bs.vbo); | ||||
| 	glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW); | ||||
| } | ||||
|  | ||||
| void sendEbo(BufferSet const&bs) noexcept { | ||||
| 	const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size()); | ||||
| void sendEbo(BufferSet const &bs) noexcept { | ||||
| 	auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size()); | ||||
| 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo); | ||||
| 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW); | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								deps/imgui/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								deps/imgui/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -6,7 +6,7 @@ endif() | ||||
| # DrinkingTea: end | ||||
|  | ||||
| add_library( | ||||
| 	imgui OBJECT | ||||
| 	imgui | ||||
| 		imgui.cpp | ||||
| 		imgui_demo.cpp | ||||
| 		imgui_draw.cpp | ||||
| @@ -19,4 +19,12 @@ add_library( | ||||
| target_include_directories( | ||||
| 	imgui SYSTEM PUBLIC | ||||
| 		. | ||||
| ) | ||||
| ) | ||||
|  | ||||
| install( | ||||
| 	TARGETS | ||||
| 		imgui | ||||
| 	DESTINATION | ||||
| 		LIBRARY DESTINATION lib | ||||
| 		ARCHIVE DESTINATION lib | ||||
| ) | ||||
|   | ||||
							
								
								
									
										16
									
								
								deps/nfde/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								deps/nfde/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| cmake_minimum_required(VERSION 3.5) | ||||
| cmake_minimum_required(VERSION 3.19) | ||||
| project(nativefiledialog-extended VERSION 1.1.1) | ||||
|  | ||||
| set(nfd_ROOT_PROJECT OFF) | ||||
| @@ -10,7 +10,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS) | ||||
| 	option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF) | ||||
| endif() | ||||
| option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT}) | ||||
| option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT}) | ||||
| # DrinkingTea: begin | ||||
| if(NOT DEFINED NFD_INSTALL) | ||||
| 	option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT}) | ||||
| endif() | ||||
| # DrinkingTea: end | ||||
|  | ||||
| set(nfd_PLATFORM Undefined) | ||||
| if(WIN32) | ||||
| @@ -21,7 +25,9 @@ elseif(UNIX AND NOT APPLE) | ||||
|   set(nfd_PLATFORM PLATFORM_UNIX) | ||||
| endif() | ||||
|  | ||||
| message("nfd Platform: ${nfd_PLATFORM}") | ||||
| # DrinkingTea: begin | ||||
| #message("nfd Platform: ${nfd_PLATFORM}") | ||||
| # DrinkingTea: end | ||||
|  | ||||
| set(nfd_COMPILER Undefined) | ||||
| if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") | ||||
| @@ -33,7 +39,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C | ||||
|   set(nfd_COMPILER COMPILER_GNU) | ||||
| endif() | ||||
|  | ||||
| message("nfd Compiler: ${nfd_COMPILER}") | ||||
| # DrinkingTea: begin | ||||
| #message("nfd Compiler: ${nfd_COMPILER}") | ||||
| # DrinkingTea: end | ||||
|  | ||||
| # Use latest C++ by default (should be the best one), but let user override it | ||||
| if(NOT DEFINED CMAKE_CXX_STANDARD) | ||||
|   | ||||
							
								
								
									
										6
									
								
								deps/nfde/src/nfd_win.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								deps/nfde/src/nfd_win.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -201,7 +201,7 @@ nfdresult_t SetDefaultExtension(::IFileDialog* fileOpenDialog, | ||||
|     } | ||||
|     if (*p_spec) { | ||||
|         // multiple file extensions for this type (need to allocate memory) | ||||
|         size_t numChars = p_spec - filterList[0].spec; | ||||
|         size_t numChars = static_cast<size_t>(p_spec - filterList[0].spec); | ||||
|         // allocate one more char space for the '\0' | ||||
|         nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1)); | ||||
|         if (!extnBuf) { | ||||
| @@ -710,7 +710,7 @@ nfdresult_t CopyCharToWChar(const nfdu8char_t* inStr, nfdnchar_t*& outStr) { | ||||
|     int charsNeeded = MultiByteToWideChar(CP_UTF8, 0, inStr, -1, nullptr, 0); | ||||
|     assert(charsNeeded); | ||||
|  | ||||
|     nfdnchar_t* tmp_outStr = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * charsNeeded); | ||||
|     nfdnchar_t* tmp_outStr = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * static_cast<size_t>(charsNeeded)); | ||||
|     if (!tmp_outStr) { | ||||
|         return NFD_ERROR; | ||||
|     } | ||||
| @@ -727,7 +727,7 @@ nfdresult_t CopyWCharToNFDChar(const nfdnchar_t* inStr, nfdu8char_t*& outStr) { | ||||
|     int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, inStr, -1, nullptr, 0, nullptr, nullptr); | ||||
|     assert(bytesNeeded); | ||||
|  | ||||
|     nfdu8char_t* tmp_outStr = NFDi_Malloc<nfdu8char_t>(sizeof(nfdu8char_t) * bytesNeeded); | ||||
|     nfdu8char_t* tmp_outStr = NFDi_Malloc<nfdu8char_t>(sizeof(nfdu8char_t) * static_cast<size_t>(bytesNeeded)); | ||||
|     if (!tmp_outStr) { | ||||
|         return NFD_ERROR; | ||||
|     } | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/.liccor.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/.liccor.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
| source: | ||||
| - src | ||||
| copyright_notice: |- | ||||
|   Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|   Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  | ||||
|   This Source Code Form is subject to the terms of the Mozilla Public | ||||
|   License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										10
									
								
								deps/ox/deps/cityhash/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								deps/ox/deps/cityhash/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -9,9 +9,6 @@ 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) | ||||
| @@ -28,3 +25,10 @@ endif() | ||||
|  | ||||
| add_library(CityHash INTERFACE) | ||||
| target_include_directories(CityHash INTERFACE include) | ||||
|  | ||||
| install( | ||||
|     DIRECTORY | ||||
|         include/cityhash | ||||
|     DESTINATION | ||||
|         include | ||||
| ) | ||||
|   | ||||
| @@ -104,6 +104,11 @@ using size_t = decltype(alignof(int)); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" | ||||
| #endif | ||||
|  | ||||
| namespace cityhash::detail { | ||||
|  | ||||
| template<typename T> | ||||
| @@ -671,4 +676,8 @@ constexpr uint128 CityHash128(const char *s, size_t len) noexcept { | ||||
|  | ||||
| } | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #endif  // CITY_HASH_H_ | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/deps/jsoncpp/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/deps/jsoncpp/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -12,7 +12,7 @@ | ||||
| # CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will | ||||
| # continue to generate policy warnings "CMake Warning (dev)...Policy CMP0XXX is not set:" | ||||
| # | ||||
| set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.8.0") | ||||
| set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.13.2") | ||||
| set(JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION "3.13.2") | ||||
| cmake_minimum_required(VERSION ${JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION}) | ||||
| if("${CMAKE_VERSION}" VERSION_LESS "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}") | ||||
|   | ||||
							
								
								
									
										478
									
								
								deps/ox/ox-docs.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										478
									
								
								deps/ox/ox-docs.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,478 @@ | ||||
|  | ||||
| # Ox Docs | ||||
|  | ||||
| ## Project Structure | ||||
|  | ||||
| All components have a platform indicator next to them: | ||||
|  | ||||
|     (OB) - OS, Bare Metal | ||||
|     (-B) - Bare Metal | ||||
|     (O-) - OS | ||||
|  | ||||
| * Ox - Library of things useful for portable bare metal and userland code. Not really that external... | ||||
|     * clargs - Command Line Args processing (OB) | ||||
|     * claw - Reads and writes Metal or Organic Claw with header to indicate which | ||||
|     * event - Qt-like signal system (OB) | ||||
|     * fs - file system (OB) | ||||
|         * logconn - connects logging to Bullock (O-) | ||||
|     * mc - Metal Claw serialization, builds on model (OB) | ||||
|     * oc - Organic Claw serialization (wrapper around JsonCpp), builds on model (O-) | ||||
|     * model - Data structure modelling (OB) | ||||
|         * preloader - library for handling preloading of data (OB) | ||||
|     * std - Standard-ish Library with a lot missing and some things added (OB) | ||||
|  | ||||
| ## Systems | ||||
|  | ||||
| ### Error Handling | ||||
|  | ||||
| Ox provides ```ox::Error``` to report errors. | ||||
| ```ox::Error``` is a struct that has overloaded operators to behave like an | ||||
| integer error code, plus some extra fields to enhance debuggability. | ||||
| If instantiated through the ```OxError(x)``` macro, it will also include the | ||||
| file and line of the error. | ||||
| The ```OxError(x)``` macro should only be used for the initial instantiation of | ||||
| an ```ox::Error```. | ||||
|  | ||||
| In addition to ```ox::Error``` there is also the template ```ox::Result<T>```. | ||||
| ```ox::Result``` simply wraps the type T value in a struct that also includes | ||||
| error information, which allows the returning of a value and an error without | ||||
| resorting to output parameters. | ||||
|  | ||||
| If a function returns an ```ox::Error``` or ```ox::Result``` it should be | ||||
| declared as ```noexcept``` and all exceptions should be translated to an | ||||
| ```ox::Error```. | ||||
|  | ||||
| ```ox::Result``` can be used as follows: | ||||
|  | ||||
| ```cpp | ||||
| ox::Result<int> foo(int i) noexcept { | ||||
| 	if (i < 10) { | ||||
| 		return i + 1; // implicitly calls ox::Result<T>::Result(T) | ||||
| 	} | ||||
| 	return OxError(1); // implicitly calls ox::Result<T>::Result(ox::Error) | ||||
| } | ||||
|  | ||||
| int caller1() { | ||||
| 	auto v = foo(argc); | ||||
| 	if (v.error) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	std::cout << v.value << '\n'; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int caller2() { | ||||
| 	// it is also possible to capture the value and error in their own variables | ||||
| 	auto [val, err] = foo(argc); | ||||
| 	if (err) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	std::cout << val << '\n'; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| ox::Error caller3(int &i) { | ||||
|     return foo(i).moveTo(i); | ||||
| } | ||||
|  | ||||
| ox::Error caller4(int &i) { | ||||
|     return foo(i).copyTo(i); | ||||
| } | ||||
|  | ||||
| int caller5(int i) { | ||||
|     return foo(i).unwrap(); // unwrap will kill the program if there is an error | ||||
| } | ||||
|  | ||||
| int caller6(int i) { | ||||
|     return foo(i).unwrapThrow(); // unwrap will throw if there is an error | ||||
| } | ||||
|  | ||||
| int caller7(int i) { | ||||
|     return foo(i).or_value(0); // will return 0 if foo returned an error | ||||
| } | ||||
|  | ||||
| ox::Result<uint64_t> caller8(int i) { | ||||
|     return foo(i).to<uint64_t>(); // will convert the result of foo to uint64_t | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Lastly, there are a few macros available to help in passing ```ox::Error```s | ||||
| back up the call stack, ```OX_RETURN_ERROR```, ```OX_THROW_ERROR```, and | ||||
| ```OX_REQUIRE```. | ||||
|  | ||||
| ```OX_RETURN_ERROR``` is by far the more helpful of the two. | ||||
| ```OX_RETURN_ERROR``` will return an ```ox::Error``` if it is not 0 and | ||||
| ```OX_THROW_ERROR``` will throw an ```ox::Error``` if it is not 0. | ||||
|  | ||||
| Since ```ox::Error``` is always nodiscard, you must do something with them. | ||||
| In rare cases, you may not have anything you can do with them or you may know | ||||
| the code will never fail in that particular instance. | ||||
| This should be used sparingly. | ||||
|  | ||||
|  | ||||
| ```cpp | ||||
| void studioCode() { | ||||
| 	auto [val, err] = foo(1); | ||||
| 	OX_THROW_ERROR(err); | ||||
| 	doStuff(val); | ||||
| } | ||||
|  | ||||
| ox::Error engineCode() noexcept { | ||||
| 	auto [val, err] = foo(1); | ||||
| 	OX_RETURN_ERROR(err); | ||||
| 	doStuff(val); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| void anyCode() { | ||||
|     auto [val, err] = foo(1); | ||||
|     std::ignore = err; | ||||
|     doStuff(val); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Both macros will also take the ```ox::Result``` directly: | ||||
|  | ||||
| ```cpp | ||||
| void studioCode() { | ||||
| 	auto valerr = foo(1); | ||||
| 	OX_THROW_ERROR(valerr); | ||||
| 	doStuff(valerr.value); | ||||
| } | ||||
|  | ||||
| ox::Error engineCode() noexcept { | ||||
| 	auto valerr = foo(1); | ||||
| 	OX_RETURN_ERROR(valerr); | ||||
| 	doStuff(valerr.value); | ||||
| 	return {}; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Ox also has the ```OX_REQUIRE``` macro, which will initialize a value if there is no error, and return if there is. | ||||
| It aims to somewhat emulate the ```?``` operator in Rust and Swift. | ||||
|  | ||||
| Rust ```?``` operator: | ||||
| ```rust | ||||
| fn f() -> Result<i32, i32> { | ||||
|   // do stuff | ||||
| } | ||||
|  | ||||
| fn f2() -> Result<i32, i32> { | ||||
|   let i = f()?; | ||||
|   Ok(i + 4) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```OX_REQUIRE```: | ||||
| ```cpp | ||||
| ox::Result<int> f() noexcept { | ||||
| 	// do stuff | ||||
| } | ||||
|  | ||||
| ox::Result<int> f2() noexcept { | ||||
| 	OX_REQUIRE(i, f()); // const auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__)) | ||||
| 	return i + 4; | ||||
| } | ||||
| ``` | ||||
| ```OX_REQUIRE``` is not quite as versatile, but it should still cleanup a lot of otherwise less ideal code. | ||||
|  | ||||
| ```OX_REQUIRE``` by default creates a const, but there is also an ```OX_REQUIRE_M``` (OX_REQUIRE Mutable) | ||||
| variant for creating a non-const value. | ||||
|  | ||||
| * ```OX_REQUIRE_M``` - OX_REQUIRE Mutable | ||||
|  | ||||
| ### Logging and Output | ||||
|  | ||||
| Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros. | ||||
| Each of these also provides a format variation. | ||||
|  | ||||
| Ox also provide ```oxOut``` and ```oxErr``` for printing to stdout and stderr. | ||||
| These are intended for permanent messages and always go to stdout and stderr. | ||||
|  | ||||
| Tracing functions do not go to stdout unless the OXTRACE environment variable is set. | ||||
| They also print with the channel that they are on, along with file and line. | ||||
|  | ||||
| Debug statements go to stdout and go to the logger on the "debug" channel. | ||||
| Where trace statements are intended to be written with thoughtfulness, | ||||
| debug statements are intended to be quick and temporary insertions. | ||||
| Debug statements trigger compilation failures if OX_NODEBUG is enabled when CMake is run, | ||||
| as it is on Jenkins builds, so ```oxDebug``` statements should never be checked in. | ||||
| This makes ```oxDebug``` preferable to other forms of logging, as temporary prints should | ||||
| never be checked in. | ||||
|  | ||||
| ```oxError``` always prints. | ||||
| It includes file and line, and is prefixed with a red "ERROR:". | ||||
| It should generally be used conservatively. | ||||
| It should be used only when there is an error that is not technically fatal, but | ||||
| the user almost certainly wants to know about it. | ||||
|  | ||||
| ```oxTrace``` and ```oxTracef```: | ||||
| ```cpp | ||||
| void f(int x, int y) { // x = 9, y = 4 | ||||
| 	oxTrace("nostalgia.core.sdl.gfx") << "f:" << x << y; // Output: "f: 9 4" | ||||
| 	oxTracef("nostalgia.core.sdl.gfx", "f: {}, {}", x, y); // Output: "f: 9, 4" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```oxDebug``` and ```oxDebugf```: | ||||
| ```cpp | ||||
| void f(int x, int y) { // x = 9, y = 4 | ||||
| 	oxDebug() << "f:" << x << y; // Output: "f: 9 4" | ||||
| 	oxDebugf("f: {}, {}", x, y); // Output: "f: 9, 4" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```oxError``` and ```oxErrorf```: | ||||
| ```cpp | ||||
| void f(int x, int y) { // x = 9, y = 4 | ||||
| 	oxError() << "f:" << x << y; // Output: "ERROR: (<file>:<line>): f: 9 4" | ||||
| 	oxErrorf("f: {}, {}", x, y); // Output: "ERROR: (<file>:<line>): f: 9, 4" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Model System | ||||
|  | ||||
| Ox has a model system that provides a sort of manual reflection mechanism. | ||||
|  | ||||
| Models require a model function for the type that you want to model. | ||||
| It is also good to provide a type name and type version number, though that is not required. | ||||
|  | ||||
| The model function takes an instance of the type it is modelling and a template | ||||
| parameter type. | ||||
| The template parameter type must implement the API used in the models, but it | ||||
| can do anything with the data provided to it. | ||||
|  | ||||
| Here is an example from the Nostalgia/Core package: | ||||
|  | ||||
| ```cpp | ||||
| struct NostalgiaPalette { | ||||
| 	static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette"; | ||||
| 	static constexpr auto TypeVersion = 1; | ||||
| 	ox::Vector<Color16> colors; | ||||
| }; | ||||
|  | ||||
| struct NostalgiaGraphic { | ||||
| 	static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic"; | ||||
| 	static constexpr auto TypeVersion = 1; | ||||
| 	int8_t bpp = 0; | ||||
| 	// rows and columns are really only used by TileSheetEditor | ||||
| 	int rows = 1; | ||||
| 	int columns = 1; | ||||
| 	ox::FileAddress defaultPalette; | ||||
| 	NostalgiaPalette pal; | ||||
| 	ox::Vector<uint8_t> pixels; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaPalette> auto *pal) noexcept { | ||||
| 	h->template setTypeInfo<NostalgiaPalette>(); | ||||
| 	// it is also possible to provide the type name and type version as function arguments | ||||
| 	//h->setTypeInfo("net.drinkingtea.nostalgia.core.NostalgiaPalette", 1); | ||||
| 	OX_RETURN_ERROR(h->field("colors", &pal->colors)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *h, ox::CommonPtrWith<NostalgiaGraphic> auto *ng) noexcept { | ||||
| 	h->template setTypeInfo<NostalgiaGraphic>(); | ||||
| 	OX_RETURN_ERROR(h->field("bpp", &ng->bpp)); | ||||
| 	OX_RETURN_ERROR(h->field("rows", &ng->rows)); | ||||
| 	OX_RETURN_ERROR(h->field("columns", &ng->columns)); | ||||
| 	OX_RETURN_ERROR(h->field("defaultPalette", &ng->defaultPalette)); | ||||
| 	OX_RETURN_ERROR(h->field("pal", &ng->pal)); | ||||
| 	OX_RETURN_ERROR(h->field("pixels", &ng->pixels)); | ||||
| 	return {}; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| The model system also provides for unions: | ||||
|  | ||||
| ```cpp | ||||
|  | ||||
| #include <ox/model/types.hpp> | ||||
|  | ||||
| class FileAddress { | ||||
|  | ||||
| 	template<typename T> | ||||
| 	friend constexpr Error model(T*, ox::CommonPtrWith<FileAddress> auto*) noexcept; | ||||
|  | ||||
| 	public: | ||||
| 		static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress"; | ||||
|  | ||||
| 		union Data { | ||||
| 			static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress.Data"; | ||||
| 			char *path; | ||||
| 			const char *constPath; | ||||
| 			uint64_t inode; | ||||
| 		}; | ||||
|  | ||||
| 	protected: | ||||
| 		FileAddressType m_type = FileAddressType::None; | ||||
| 		Data m_data; | ||||
|  | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *h, ox::CommonPtrWith<FileAddress::Data> auto *obj) noexcept { | ||||
| 	h->template setTypeInfo<FileAddress::Data>(); | ||||
| 	OX_RETURN_ERROR(h->fieldCString("path", &obj->path)); | ||||
| 	OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path)); | ||||
| 	OX_RETURN_ERROR(h->field("inode", &obj->inode)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *io, ox::CommonPtrWith<FileAddress> auto *fa) noexcept { | ||||
| 	io->template setTypeInfo<FileAddress>(); | ||||
| 	// cannot read from object in Reflect operation | ||||
| 	if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { | ||||
| 		int8_t type = 0; | ||||
| 		OX_RETURN_ERROR(io->field("type", &type)); | ||||
| 		OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, 0))); | ||||
| 	} else { | ||||
| 		auto type = static_cast<int8_t>(fa->m_type); | ||||
| 		OX_RETURN_ERROR(io->field("type", &type)); | ||||
| 		fa->m_type = static_cast<FileAddressType>(type); | ||||
| 		OX_RETURN_ERROR(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); | ||||
| 	} | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| ``` | ||||
|  | ||||
| There are also macros in ```<ox/model/def.hpp>``` for simplifying the declaration of models: | ||||
|  | ||||
| ```cpp | ||||
| OX_MODEL_BEGIN(NostalgiaGraphic) | ||||
| 	OX_MODEL_FIELD(bpp) | ||||
| 	OX_MODEL_FIELD(rows) | ||||
| 	OX_MODEL_FIELD(columns) | ||||
| 	OX_MODEL_FIELD(defaultPalette) | ||||
| 	OX_MODEL_FIELD(pal) | ||||
| 	OX_MODEL_FIELD(pixels) | ||||
| oxModelEnd() | ||||
| ``` | ||||
|  | ||||
| ### Serialization | ||||
|  | ||||
| Using the model system, Ox provides for serialization. | ||||
| Ox has MetalClaw and OrganicClaw as its serialization format options. | ||||
| MetalClaw is a custom binary format designed for minimal size. | ||||
| OrganicClaw is a wrapper around JsonCpp, chosen because it technically | ||||
| implements a superset of JSON. | ||||
| OrganicClaw requires support for 64 bit integers, whereas normal JSON | ||||
| technically does not. | ||||
|  | ||||
| These formats do not currently support floats. | ||||
|  | ||||
| There is also a wrapper format called Claw that provides a header at the | ||||
| beginning of the file and can dynamically switch between the two depending on | ||||
| what the header says is present. | ||||
| The Claw header also includes information about the type and type version of | ||||
| the data. | ||||
|  | ||||
| Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;``` | ||||
|  | ||||
| That reads: | ||||
|  | ||||
| * Format is Metal Claw, version 1 | ||||
| * Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette | ||||
| * Type version is 1 | ||||
|  | ||||
| #### Metal Claw Example | ||||
|  | ||||
| ##### Read | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/mc/read.hpp> | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept { | ||||
| 	return ox::readMC<NostalgiaPalette>(buff); | ||||
| } | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { | ||||
| 	NostalgiaPalette pal; | ||||
| 	OX_RETURN_ERROR(ox::readMC(buff, pal)); | ||||
| 	return pal; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ##### Write | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/mc/write.hpp> | ||||
|  | ||||
| ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { | ||||
| 	ox::Buffer buffer(ox::units::MB); | ||||
| 	std::size_t sz = 0; | ||||
| 	OX_RETURN_ERROR(ox::writeMC(buffer.data(), buffer.size(), pal, &sz)); | ||||
| 	buffer.resize(sz); | ||||
| 	return buffer; | ||||
| } | ||||
|  | ||||
| ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette const&pal) noexcept { | ||||
| 	return ox::writeMC(pal); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| #### Organic Claw Example | ||||
|  | ||||
| ##### Read | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/oc/read.hpp> | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept { | ||||
| 	return ox::readOC<NostalgiaPalette>(buff); | ||||
| } | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { | ||||
| 	NostalgiaPalette pal; | ||||
| 	OX_RETURN_ERROR(ox::readOC(buff, &pal)); | ||||
| 	return pal; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ##### Write | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/oc/write.hpp> | ||||
|  | ||||
| ox::Result<ox::Buffer> writeSpritePalette1(NostalgiaPalette const&pal) noexcept { | ||||
| 	ox::Buffer buffer(ox::units::MB); | ||||
| 	OX_RETURN_ERROR(ox::writeOC(buffer.data(), buffer.size(), pal)); | ||||
| 	return buffer; | ||||
| } | ||||
|  | ||||
| ox::Result<ox::Buffer> writeSpritePalette2(NostalgiaPalette const&pal) noexcept { | ||||
| 	return ox::writeOC(pal); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| #### Claw Example | ||||
|  | ||||
| ##### Read | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/claw/read.hpp> | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette1(ox::BufferView const&buff) noexcept { | ||||
| 	return ox::readClaw<NostalgiaPalette>(buff); | ||||
| } | ||||
|  | ||||
| ox::Result<NostalgiaPalette> loadPalette2(ox::BufferView const&buff) noexcept { | ||||
| 	NostalgiaPalette pal; | ||||
| 	OX_RETURN_ERROR(ox::readClaw(buff, pal)); | ||||
| 	return pal; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ##### Write | ||||
|  | ||||
| ```cpp | ||||
| #include <ox/claw/write.hpp> | ||||
|  | ||||
| ox::Result<ox::Buffer> writeSpritePalette(NostalgiaPalette const&pal) noexcept { | ||||
| 	return ox::writeClaw(pal); | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										7
									
								
								deps/ox/src/ox/clargs/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								deps/ox/src/ox/clargs/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,9 @@ | ||||
| cmake_minimum_required(VERSION 3.10) | ||||
|  | ||||
| if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") | ||||
| 	# enable warnings | ||||
| 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") | ||||
| endif() | ||||
|  | ||||
|  | ||||
| add_library( | ||||
| 	OxClArgs | ||||
|   | ||||
							
								
								
									
										34
									
								
								deps/ox/src/ox/clargs/clargs.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								deps/ox/src/ox/clargs/clargs.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -11,23 +11,25 @@ | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| ClArgs::ClArgs(int argc, const char **args) noexcept { | ||||
| 	for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) { | ||||
| 		auto arg = String(args[i]); | ||||
| ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<size_t>(argc)}) {} | ||||
|  | ||||
| ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept { | ||||
| 	for (auto i = 0u; i < args.size(); ++i) { | ||||
| 		auto arg = StringView{args[i]}; | ||||
| 		if (arg[0] == '-') { | ||||
| 			while (arg[0] == '-' && arg.len()) { | ||||
| 				arg = arg.substr(1); | ||||
| 			while (arg[0] == '-' && arg.size()) { | ||||
| 				arg = substr(arg, 1); | ||||
| 			} | ||||
| 			m_bools[arg] = true; | ||||
| 			// parse additional arguments | ||||
| 			if (i < static_cast<unsigned>(argc) && args[i + 1]) { | ||||
| 				auto val = String(args[i + 1]); | ||||
| 				if (val.len() && val[i] != '-') { | ||||
| 			if (i < args.size() && args[i + 1]) { | ||||
| 				auto const val = StringView{args[i + 1]}; | ||||
| 				if (val.size() && val[0] != '-') { | ||||
| 					if (val == "false") { | ||||
| 						m_bools[arg] = false; | ||||
| 					} | ||||
| 					m_strings[arg] = val; | ||||
| 					if (auto r = ox::atoi(val.c_str()); r.error == 0) { | ||||
| 					if (auto r = ox::strToInt(val); r.error == 0) { | ||||
| 						m_ints[arg] = r.value; | ||||
| 					} | ||||
| 					++i; | ||||
| @@ -38,32 +40,32 @@ ClArgs::ClArgs(int argc, const char **args) noexcept { | ||||
| } | ||||
|  | ||||
| bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept { | ||||
| 	auto [value, err] = m_ints.at(arg); | ||||
| 	auto const [value, err] = m_bools.at(arg); | ||||
| 	return !err ? *value : defaultValue; | ||||
| } | ||||
|  | ||||
| String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept { | ||||
| 	auto [value, err] = m_strings.at(arg); | ||||
| 	auto const [value, err] = m_strings.at(arg); | ||||
| 	return !err ? ox::String(*value) : ox::String(defaultValue); | ||||
| } | ||||
|  | ||||
| int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept { | ||||
| 	auto [value, err] = m_ints.at(arg); | ||||
| 	auto const [value, err] = m_ints.at(arg); | ||||
| 	return !err ? *value : defaultValue; | ||||
| } | ||||
|  | ||||
| Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept { | ||||
| 	oxRequire(out, m_bools.at(arg)); | ||||
| 	OX_REQUIRE(out, m_bools.at(arg)); | ||||
| 	return *out; | ||||
| } | ||||
|  | ||||
| Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept { | ||||
| 	oxRequire(out, m_strings.at(argName)); | ||||
| 	OX_REQUIRE(out, m_strings.at(argName)); | ||||
| 	return *out; | ||||
| } | ||||
|  | ||||
| Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept { | ||||
| 	oxRequire(out, m_ints.at(arg)); | ||||
| 	OX_REQUIRE(out, m_ints.at(arg)); | ||||
| 	return *out; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										5
									
								
								deps/ox/src/ox/clargs/clargs.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								deps/ox/src/ox/clargs/clargs.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -9,6 +9,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <ox/std/hashmap.hpp> | ||||
| #include <ox/std/span.hpp> | ||||
| #include <ox/std/string.hpp> | ||||
|  | ||||
| namespace ox { | ||||
| @@ -22,6 +23,8 @@ class ClArgs { | ||||
| 	public: | ||||
| 		ClArgs(int argc, const char **args) noexcept; | ||||
|  | ||||
| 		ClArgs(ox::SpanView<const char*> args) noexcept; | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept; | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/claw/claw.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/claw/claw.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/claw/format.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/claw/format.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										34
									
								
								deps/ox/src/ox/claw/read.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								deps/ox/src/ox/claw/read.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -18,7 +18,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept { | ||||
| 	size_t outSz{}; | ||||
| 	const auto s1End = ox::strchr(buffRaw, ';', buffLen); | ||||
| 	if (!s1End) { | ||||
| 		return OxError(1, "Could not read Claw header"); | ||||
| 		return ox::Error(1, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1; | ||||
| 	buffRaw += fmtSz; | ||||
| @@ -26,7 +26,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept { | ||||
| 	outSz += fmtSz; | ||||
| 	auto const s2End = ox::strchr(buffRaw, ';', buffLen); | ||||
| 	if (!s2End) { | ||||
| 		return OxError(2, "Could not read Claw header"); | ||||
| 		return ox::Error(2, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1; | ||||
| 	buffRaw += s2Size; | ||||
| @@ -34,7 +34,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept { | ||||
| 	outSz += s2Size; | ||||
| 	auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1; | ||||
| 	if (!s3End) { | ||||
| 		return OxError(3, "Could not read Claw header"); | ||||
| 		return ox::Error(3, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); | ||||
| 	buffRaw += s3Size; | ||||
| @@ -48,7 +48,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept { | ||||
| 	auto buffLen = buff.size(); | ||||
| 	const auto s1End = ox::strchr(buffRaw, ';', buffLen); | ||||
| 	if (!s1End) { | ||||
| 		return OxError(1, "Could not read Claw header"); | ||||
| 		return ox::Error(1, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const s1Size = static_cast<std::size_t>(s1End - buffRaw); | ||||
| 	StringView const fmt(buffRaw, s1Size); | ||||
| @@ -57,7 +57,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept { | ||||
|  | ||||
| 	auto const s2End = ox::strchr(buffRaw, ';', buffLen); | ||||
| 	if (!s2End) { | ||||
| 		return OxError(2, "Could not read Claw header"); | ||||
| 		return ox::Error(2, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const s2Size = static_cast<std::size_t>(s2End - buffRaw); | ||||
| 	StringView const typeName(buffRaw, s2Size); | ||||
| @@ -66,7 +66,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept { | ||||
|  | ||||
| 	auto const s3End = ox::strchr(buffRaw, ';', buffLen); | ||||
| 	if (!s3End) { | ||||
| 		return OxError(3, "Could not read Claw header"); | ||||
| 		return ox::Error(3, "Could not read Claw header"); | ||||
| 	} | ||||
| 	auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); | ||||
| 	StringView const versionStr(buffRaw, s3Size); | ||||
| @@ -78,36 +78,36 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept { | ||||
| 	} else if (fmt == "O1") { | ||||
| 		hdr.fmt = ClawFormat::Organic; | ||||
| 	} else { | ||||
| 		return OxError(4, "Claw format does not match any supported format/version combo"); | ||||
| 		return ox::Error(4, "Claw format does not match any supported format/version combo"); | ||||
| 	} | ||||
| 	hdr.typeName = typeName; | ||||
| 	std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion); | ||||
| 	std::ignore = ox::strToInt(versionStr).copyTo(hdr.typeVersion); | ||||
| 	hdr.data = buffRaw; | ||||
| 	hdr.dataSize = buffLen; | ||||
| 	return hdr; | ||||
| } | ||||
|  | ||||
| Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept { | ||||
| 	oxRequire(header, readClawHeader(buff)); | ||||
| 	OX_REQUIRE(header, readClawHeader(buff)); | ||||
| 	return {{header.data, header.dataSize}}; | ||||
| } | ||||
|  | ||||
| Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept { | ||||
| 	oxRequire(header, readClawHeader(buff)); | ||||
| 	OX_REQUIRE(header, readClawHeader(buff)); | ||||
| 	auto const [t, tdErr] = ts.getLoad( | ||||
| 			header.typeName, header.typeVersion, header.typeParams); | ||||
| 	if (tdErr) { | ||||
| 		return OxError(3, "Could not load type descriptor"); | ||||
| 		return ox::Error(3, "Could not load type descriptor"); | ||||
| 	} | ||||
| 	ModelObject obj; | ||||
| 	oxReturnError(obj.setType(t)); | ||||
| 	OX_RETURN_ERROR(obj.setType(t)); | ||||
| 	switch (header.fmt) { | ||||
| 		case ClawFormat::Metal: | ||||
| 		{ | ||||
| 			ox::BufferReader br({header.data, header.dataSize}); | ||||
| 			MetalClawReader reader(br); | ||||
| 			ModelHandlerInterface handler(&reader); | ||||
| 			oxReturnError(model(&handler, &obj)); | ||||
| 			OX_RETURN_ERROR(model(&handler, &obj)); | ||||
| 			return obj; | ||||
| 		} | ||||
| 		case ClawFormat::Organic: | ||||
| @@ -115,16 +115,16 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept { | ||||
| #ifdef OX_USE_STDLIB | ||||
| 			OrganicClawReader reader({header.data, header.dataSize}); | ||||
| 			ModelHandlerInterface handler(&reader); | ||||
| 			oxReturnError(model(&handler, &obj)); | ||||
| 			OX_RETURN_ERROR(model(&handler, &obj)); | ||||
| 			return obj; | ||||
| #else | ||||
| 			break; | ||||
| #endif | ||||
| 		} | ||||
| 		case ClawFormat::None: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										14
									
								
								deps/ox/src/ox/claw/read.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								deps/ox/src/ox/claw/read.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -40,12 +40,12 @@ Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept; | ||||
|  | ||||
| template<typename T> | ||||
| Error readClaw(ox::BufferView buff, T &val) { | ||||
| 	oxRequire(header, readClawHeader(buff)); | ||||
| 	OX_REQUIRE(header, readClawHeader(buff)); | ||||
| 	if (header.typeName != getModelTypeName<T>()) { | ||||
| 		return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); | ||||
| 		return ox::Error(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); | ||||
| 	} | ||||
| 	if (header.typeVersion != getModelTypeVersion<T>()) { | ||||
| 		return OxError(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch"); | ||||
| 		return ox::Error(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch"); | ||||
| 	} | ||||
| 	switch (header.fmt) { | ||||
| 		case ClawFormat::Metal: | ||||
| @@ -65,15 +65,15 @@ Error readClaw(ox::BufferView buff, T &val) { | ||||
| #endif | ||||
| 		} | ||||
| 		case ClawFormat::None: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| Result<T> readClaw(ox::BufferView buff) { | ||||
| 	Result<T> val; | ||||
| 	oxReturnError(readClaw(buff, val.value)); | ||||
| 	OX_RETURN_ERROR(readClaw(buff, val.value)); | ||||
| 	return val; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/claw/readclaw.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/claw/readclaw.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										72
									
								
								deps/ox/src/ox/claw/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								deps/ox/src/ox/claw/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -62,45 +62,45 @@ struct TestStruct { | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) { | ||||
| 	oxReturnError(io->template setTypeInfo<TestUnion>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->fieldCString("String", &obj->String)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->fieldCString("String", &obj->String)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) { | ||||
| 	oxReturnError(io->template setTypeInfo<TestStructNest>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->field("String", &obj->String)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->field("String", &obj->String)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) { | ||||
| 	oxReturnError(io->template setTypeInfo<TestStruct>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->field("Int1", &obj->Int1)); | ||||
| 	oxReturnError(io->field("Int2", &obj->Int2)); | ||||
| 	oxReturnError(io->field("Int3", &obj->Int3)); | ||||
| 	oxReturnError(io->field("Int4", &obj->Int4)); | ||||
| 	oxReturnError(io->field("Int5", &obj->Int5)); | ||||
| 	oxReturnError(io->field("Int6", &obj->Int6)); | ||||
| 	oxReturnError(io->field("Int7", &obj->Int7)); | ||||
| 	oxReturnError(io->field("Int8", &obj->Int8)); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->field("Int1", &obj->Int1)); | ||||
| 	OX_RETURN_ERROR(io->field("Int2", &obj->Int2)); | ||||
| 	OX_RETURN_ERROR(io->field("Int3", &obj->Int3)); | ||||
| 	OX_RETURN_ERROR(io->field("Int4", &obj->Int4)); | ||||
| 	OX_RETURN_ERROR(io->field("Int5", &obj->Int5)); | ||||
| 	OX_RETURN_ERROR(io->field("Int6", &obj->Int6)); | ||||
| 	OX_RETURN_ERROR(io->field("Int7", &obj->Int7)); | ||||
| 	OX_RETURN_ERROR(io->field("Int8", &obj->Int8)); | ||||
| 	int unionIdx = 0; | ||||
| 	if constexpr(T::opType() != ox::OpType::Reflect) { | ||||
| 		unionIdx = obj->unionIdx; | ||||
| 	} | ||||
| 	oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx})); | ||||
| 	oxReturnError(io->field("String", &obj->String)); | ||||
| 	oxReturnError(io->field("List", obj->List, 4)); | ||||
| 	oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	oxReturnError(io->field("Struct", &obj->Struct)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, unionIdx})); | ||||
| 	OX_RETURN_ERROR(io->field("String", &obj->String)); | ||||
| 	OX_RETURN_ERROR(io->field("List", obj->List, 4)); | ||||
| 	OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	OX_RETURN_ERROR(io->field("Struct", &obj->Struct)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| static std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| @@ -109,24 +109,24 @@ static std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 			"ClawHeaderReader", | ||||
| 			[] { | ||||
| 				constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;"); | ||||
| 				auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1}); | ||||
| 				auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1}); | ||||
| 				oxAssert(err, "Error parsing header"); | ||||
| 				oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong"); | ||||
| 				oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong"); | ||||
| 				oxAssert(ch.typeVersion == 2, "Type version wrong"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"ClawHeaderReader2", | ||||
| 			[] { | ||||
| 				constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;"); | ||||
| 				auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1}); | ||||
| 				auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1}); | ||||
| 				oxAssert(err, "Error parsing header"); | ||||
| 				oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong"); | ||||
| 				oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong"); | ||||
| 				oxAssert(ch.typeVersion == 3, "Type version wrong"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -134,7 +134,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 			[] { | ||||
| 				constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf"); | ||||
| 				constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3"); | ||||
| 				oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1})); | ||||
| 				OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.size() + 1})); | ||||
| 				oxExpect(actual, expected); | ||||
| 				return ox::Error{}; | ||||
| 			} | ||||
| @@ -145,8 +145,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				// This test doesn't confirm much, but it does show that the writer | ||||
| 				// doesn't segfault | ||||
| 				TestStruct ts; | ||||
| 				oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal)); | ||||
| 				return OxError(0); | ||||
| 				OX_RETURN_ERROR(ox::writeClaw(ts, ox::ClawFormat::Metal)); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -191,7 +191,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(testIn.Struct.String      == testOut.Struct.String, "Struct.String value mismatch"); | ||||
| 				oxAssert(testIn.Struct.Bool        == testOut.Struct.Bool, "Struct.Bool value mismatch"); | ||||
|  | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/claw/write.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/claw/write.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										30
									
								
								deps/ox/src/ox/claw/write.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								deps/ox/src/ox/claw/write.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -39,7 +39,7 @@ struct TypeInfoCatcher { | ||||
| 	} | ||||
|  | ||||
| 	constexpr Error field(...) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	static constexpr auto opType() { | ||||
| @@ -76,21 +76,21 @@ template<typename T> | ||||
| ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept { | ||||
| 	switch (fmt) { | ||||
| 		case ClawFormat::Metal: | ||||
| 			oxReturnError(write(writer, "M2;")); | ||||
| 			OX_RETURN_ERROR(write(writer, "M2;")); | ||||
| 			break; | ||||
| 		case ClawFormat::Organic: | ||||
| 			oxReturnError(write(writer, "O1;")); | ||||
| 			OX_RETURN_ERROR(write(writer, "O1;")); | ||||
| 			break; | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| 	oxReturnError(write(writer, detail::getTypeName(t))); | ||||
| 	oxReturnError(writer.put(';')); | ||||
| 	OX_RETURN_ERROR(write(writer, detail::getTypeName(t))); | ||||
| 	OX_RETURN_ERROR(writer.put(';')); | ||||
| 	const auto tn = detail::getTypeVersion(t); | ||||
| 	if (tn > -1) { | ||||
| 		oxReturnError(ox::writeItoa(tn, writer)); | ||||
| 		OX_RETURN_ERROR(ox::writeItoa(tn, writer)); | ||||
| 	} | ||||
| 	oxReturnError(writer.put(';')); | ||||
| 	OX_RETURN_ERROR(writer.put(';')); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| @@ -102,19 +102,19 @@ Result<Buffer> writeClaw( | ||||
| 		std::size_t buffReserveSz = 2 * units::KB) noexcept { | ||||
| 	Buffer out(buffReserveSz); | ||||
| 	BufferWriter bw(&out, 0); | ||||
| 	oxReturnError(detail::writeClawHeader(bw, &t, fmt)); | ||||
| 	OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt)); | ||||
| #ifdef OX_USE_STDLIB | ||||
| 	if (fmt == ClawFormat::Metal) { | ||||
| 		oxReturnError(writeMC(bw, t)); | ||||
| 		OX_RETURN_ERROR(writeMC(bw, t)); | ||||
| 	} else if (fmt == ClawFormat::Organic) { | ||||
| 		oxRequire(data, writeOC(t)); | ||||
| 		oxReturnError(bw.write(data.data(), data.size())); | ||||
| 		OX_REQUIRE(data, writeOC(t)); | ||||
| 		OX_RETURN_ERROR(bw.write(data.data(), data.size())); | ||||
| 	} | ||||
| #else | ||||
| 	if (fmt != ClawFormat::Metal) { | ||||
| 		return OxError(1, "OC is not supported in this build"); | ||||
| 		return ox::Error(1, "OC is not supported in this build"); | ||||
| 	} | ||||
| 	oxReturnError(writeMC(bw, t)); | ||||
| 	OX_RETURN_ERROR(writeMC(bw, t)); | ||||
| #endif | ||||
| 	out.resize(bw.tellp()); | ||||
| 	return out; | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/event/event.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/event/event.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/event/signal.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/event/signal.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										34
									
								
								deps/ox/src/ox/event/signal.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								deps/ox/src/ox/event/signal.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -57,7 +57,7 @@ class Signal { | ||||
|  | ||||
| 			void call(Args... args) final { | ||||
| 				if constexpr(detail::isError<decltype(f(args...))>::value) { | ||||
| 					oxThrowError(f(args...)); | ||||
| 					OX_THROW_ERROR(f(args...)); | ||||
| 				} else { | ||||
| 					f(args...); | ||||
| 				} | ||||
| @@ -76,7 +76,7 @@ class Signal { | ||||
|  | ||||
| 			void call(Args... args) final { | ||||
| 				if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { | ||||
| 					oxThrowError((m_receiver->*(m_methodPtr))(args...)); | ||||
| 					OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...)); | ||||
| 				} else { | ||||
| 					f(args...); | ||||
| 				} | ||||
| @@ -107,7 +107,7 @@ class Signal { | ||||
|  | ||||
| 			void call(Args... args) final { | ||||
| 				if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { | ||||
| 					oxThrowError((m_receiver->*(m_methodPtr))(args...)); | ||||
| 					OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...)); | ||||
| 				} else { | ||||
| 					(m_receiver->*(m_methodPtr))(args...); | ||||
| 				} | ||||
| @@ -143,6 +143,11 @@ class Signal { | ||||
|  | ||||
| 		Error disconnectObject(const void *receiver) const noexcept; | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		size_t connectionCnt() const noexcept { | ||||
| 			return m_slots.size(); | ||||
| 		} | ||||
|  | ||||
| 		void emit(Args... args) const; | ||||
|  | ||||
| 		Error emitCheckError(Args... args) const noexcept; | ||||
| @@ -193,11 +198,11 @@ Error Signal<Args...>::disconnectObject(const void *receiver) const noexcept { | ||||
| 	for (auto i = 0u; i < m_slots.size(); ++i) { | ||||
| 		const auto &slot = m_slots[i]; | ||||
| 		if (slot->receiver() == receiver) { | ||||
| 			oxReturnError(m_slots.erase(i)); | ||||
| 			OX_RETURN_ERROR(m_slots.erase(i)); | ||||
| 			--i; | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); | ||||
| 	return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); | ||||
| } | ||||
|  | ||||
| template<class... Args> | ||||
| @@ -213,9 +218,9 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept { | ||||
| 		for (auto &f : m_slots) { | ||||
| 			f->call(args...); | ||||
| 		} | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} catch (const ox::Exception &ex) { | ||||
| 		return ox::Error(ex.file, ex.line, ex.errCode, ex.msg); | ||||
| 		return ox::Error(ex.errCode, ex.msg, ex.src); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -319,6 +324,11 @@ class Signal<Error(Args...)> { | ||||
|  | ||||
| 		Error disconnectObject(const void *receiver) const noexcept; | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		size_t connectionCnt() const noexcept { | ||||
| 			return m_slots.size(); | ||||
| 		} | ||||
|  | ||||
| 		void emit(Args... args) const noexcept; | ||||
|  | ||||
| 		Error emitCheckError(Args... args) const noexcept; | ||||
| @@ -381,11 +391,11 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc | ||||
| 	for (auto i = 0u; i < m_slots.size(); ++i) { | ||||
| 		const auto &slot = m_slots[i]; | ||||
| 		if (slot->receiver() == receiver) { | ||||
| 			oxReturnError(m_slots.erase(i)); | ||||
| 			OX_RETURN_ERROR(m_slots.erase(i)); | ||||
| 			--i; | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); | ||||
| 	return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); | ||||
| } | ||||
|  | ||||
| template<class... Args> | ||||
| @@ -398,9 +408,9 @@ void Signal<Error(Args...)>::emit(Args... args) const noexcept { | ||||
| template<class... Args> | ||||
| Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept { | ||||
| 	for (auto &f : m_slots) { | ||||
| 		oxReturnError(f->call(ox::forward<Args>(args)...)); | ||||
| 		OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								deps/ox/src/ox/event/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								deps/ox/src/ox/event/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -17,7 +17,7 @@ struct TestStruct: public ox::SignalHandler { | ||||
| 	int value = 0; | ||||
| 	ox::Error method(int i) noexcept { | ||||
| 		value = i; | ||||
| 		return OxError(0); | ||||
| 		return ox::Error(0); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| @@ -27,13 +27,13 @@ std::map<ox::StringView, std::function<ox::Error()>> tests = { | ||||
| 		[] { | ||||
| 			ox::Signal<ox::Error(int)> signal; | ||||
| 			signal.connect([](int i) -> ox::Error { | ||||
| 				return OxError(i != 5); | ||||
| 				return ox::Error(i != 5); | ||||
| 			}); | ||||
| 			TestStruct ts; | ||||
| 			signal.connect(&ts, &TestStruct::method); | ||||
| 			oxReturnError(signal.emitCheckError(5)); | ||||
| 			oxReturnError(OxError(ts.value != 5)); | ||||
| 			return OxError(0); | ||||
| 			OX_RETURN_ERROR(signal.emitCheckError(5)); | ||||
| 			OX_RETURN_ERROR(ox::Error(ts.value != 5)); | ||||
| 			return ox::Error(0); | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
|   | ||||
							
								
								
									
										4
									
								
								deps/ox/src/ox/fs/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								deps/ox/src/ox/fs/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,7 @@ | ||||
| if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") | ||||
| 	# enable warnings | ||||
| 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage") | ||||
| endif() | ||||
|  | ||||
| add_library( | ||||
| 	OxFS | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										112
									
								
								deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										112
									
								
								deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -10,6 +10,8 @@ | ||||
|  | ||||
| #include <ox/fs/ptrarith/nodebuffer.hpp> | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| using InodeId_t = uint64_t; | ||||
| @@ -205,12 +207,12 @@ Error FileStoreTemplate<size_t>::format(void *buffer, std::size_t bufferSize) { | ||||
| 	auto fsData = nb->malloc(sizeof(FileStoreData)).value; | ||||
| 	if (!fsData.valid()) { | ||||
| 		oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); | ||||
| 		return OxError(1, "Could not read data section of FileStoreData"); | ||||
| 		return ox::Error(1, "Could not read data section of FileStoreData"); | ||||
| 	} | ||||
| 	auto data = nb->template dataOf<FileStoreData>(fsData); | ||||
| 	if (!data.valid()) { | ||||
| 		oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); | ||||
| 		return OxError(1, "Could not read data section of FileStoreData"); | ||||
| 		return ox::Error(1, "Could not read data section of FileStoreData"); | ||||
| 	} | ||||
| 	new (data) FileStoreData; | ||||
| 	return {}; | ||||
| @@ -221,24 +223,24 @@ Error FileStoreTemplate<size_t>::setSize(std::size_t size) { | ||||
| 	if (m_buffSize >= size) { | ||||
| 		return m_buffer->setSize(static_cast<size_t>(size)); | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::incLinks(uint64_t id) { | ||||
| 	oxRequireM(item, find(static_cast<size_t>(id)).validate()); | ||||
| 	OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate()); | ||||
| 	++item->links; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::decLinks(uint64_t id) { | ||||
| 	oxRequireM(item, find(static_cast<size_t>(id)).validate()); | ||||
| 	OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate()); | ||||
| 	--item->links; | ||||
| 	if (item->links == 0) { | ||||
| 		oxReturnError(remove(item)); | ||||
| 		OX_RETURN_ERROR(remove(item)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| @@ -247,7 +249,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t | ||||
| 	oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id); | ||||
| 	auto existing = find(id); | ||||
| 	if (!canWrite(existing, dataSize)) { | ||||
| 		oxReturnError(compact()); | ||||
| 		OX_RETURN_ERROR(compact()); | ||||
| 		existing = find(id); | ||||
| 	} | ||||
|  | ||||
| @@ -267,7 +269,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t | ||||
| 		// if first malloc failed, compact and try again | ||||
| 		if (!dest.valid()) { | ||||
| 			oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting"); | ||||
| 			oxReturnError(compact()); | ||||
| 			OX_RETURN_ERROR(compact()); | ||||
| 			dest = m_buffer->malloc(dataSize).value; | ||||
| 		} | ||||
| 		if (dest.valid()) { | ||||
| @@ -296,16 +298,16 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t | ||||
| 						        dest->id.get(), dest.offset(), destData.size()); | ||||
| 						fsData->rootNode = dest.offset(); | ||||
| 						oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); | ||||
| 						return OxError(0); | ||||
| 						return {}; | ||||
| 					} | ||||
| 				} else { | ||||
| 					oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		oxReturnError(m_buffer->free(dest)); | ||||
| 		OX_RETURN_ERROR(m_buffer->free(dest)); | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| @@ -320,7 +322,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, | ||||
| 	// error check | ||||
| 	if (!src.valid()) { | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); | ||||
| 		return OxError(1, "Could not find requested item"); | ||||
| 		return ox::Error(1, "Could not find requested item"); | ||||
| 	} | ||||
|  | ||||
| 	auto srcData = m_buffer->template dataOf<uint8_t>(src); | ||||
| @@ -333,7 +335,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", | ||||
| 		         "Item data section size: {}, Expected size: {}", srcData.size(), outSize); | ||||
| 		return OxError(1, "Invalid inode"); | ||||
| 		return ox::Error(1, "Invalid inode"); | ||||
| 	} | ||||
|  | ||||
| 	ox::memcpy(out, srcData, srcData.size()); | ||||
| @@ -351,7 +353,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t | ||||
| 	// error check | ||||
| 	if (!src.valid()) { | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
|  | ||||
| 	auto srcData = m_buffer->template dataOf<uint8_t>(src); | ||||
| @@ -364,7 +366,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", | ||||
| 		         "Item data section size: {}, Expected size: {}", srcData.size(), readSize); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
|  | ||||
| 	ox::memcpy(out, srcData.get() + readStart, readSize); | ||||
| @@ -384,7 +386,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, | ||||
| 	// error check | ||||
| 	if (!src.valid()) { | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
|  | ||||
| 	auto srcData = m_buffer->template dataOf<uint8_t>(src); | ||||
| @@ -397,7 +399,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id); | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.read.fail", | ||||
| 		         "Item data section size: {}, Expected size: {}", srcData.size(), readSize); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
|  | ||||
| 	ox::memcpy(out, srcData.get() + readStart, readSize); | ||||
| @@ -420,30 +422,30 @@ ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(uint64_t id) | ||||
|  | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::resize() { | ||||
| 	oxReturnError(compact()); | ||||
| 	OX_RETURN_ERROR(compact()); | ||||
| 	const auto newSize = static_cast<std::size_t>(size() - available()); | ||||
| 	oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); | ||||
| 	oxReturnError(m_buffer->setSize(newSize)); | ||||
| 	OX_RETURN_ERROR(m_buffer->setSize(newSize)); | ||||
| 	oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { | ||||
| 	if (m_buffer->size() > size) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error{1, "new buffer is too small for existing data"}; | ||||
| 	} | ||||
| 	m_buffSize = static_cast<size_t>(size); | ||||
| 	if (newBuff) { | ||||
| 		m_buffer = reinterpret_cast<Buffer*>(newBuff); | ||||
| 		oxReturnError(m_buffer->setSize(static_cast<size_t>(size))); | ||||
| 		m_buffer = static_cast<Buffer*>(newBuff); | ||||
| 		OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size))); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const { | ||||
| 	oxRequire(inode, find(static_cast<size_t>(id)).validate()); | ||||
| 	OX_REQUIRE(inode, find(static_cast<size_t>(id)).validate()); | ||||
| 	return StatInfo { | ||||
| 		id, | ||||
| 		inode->links, | ||||
| @@ -475,16 +477,16 @@ char *FileStoreTemplate<size_t>::buff() { | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { | ||||
| 	for (auto i = m_buffer->iterator(); i.valid(); i.next()) { | ||||
| 		oxReturnError(cb(i->fileType, i.ptr().offset(), i.ptr().end())); | ||||
| 		OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end())); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() { | ||||
| 	auto fsData = fileStoreData(); | ||||
| 	if (!fsData) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	for (auto i = 0; i < 100; i++) { | ||||
| 		auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>); | ||||
| @@ -492,7 +494,7 @@ Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>: | ||||
| 			return inode; | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(2); | ||||
| 	return ox::Error(2); | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| @@ -501,10 +503,10 @@ Error FileStoreTemplate<size_t>::compact() { | ||||
| 	return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { | ||||
| 		if (isFirstItem) { | ||||
| 			isFirstItem = false; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
| 		if (!item.valid()) { | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset()); | ||||
| 		// update rootInode if this is it | ||||
| @@ -522,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() { | ||||
| 				parent->right = item; | ||||
| 			} | ||||
| 		} | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| @@ -542,15 +544,15 @@ template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) { | ||||
| 	auto fsData = fileStoreData(); | ||||
| 	if (!fsData) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); | ||||
| 	OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate()); | ||||
| 	if (root->id == item->id) { | ||||
| 		fsData->rootNode = item; | ||||
| 		item->left = root->left; | ||||
| 		item->right = root->right; | ||||
| 		oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} else { | ||||
| 		return placeItem(root, item); | ||||
| 	} | ||||
| @@ -560,7 +562,7 @@ template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) { | ||||
| 	if (depth > 5000) { | ||||
| 		oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow."); | ||||
| 		return OxError(2); | ||||
| 		return ox::Error(2); | ||||
| 	} | ||||
| 	if (item->id > root->id) { | ||||
| 		auto right = m_buffer->ptr(root->right); | ||||
| @@ -571,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth | ||||
| 				item->right = right->right; | ||||
| 			} | ||||
| 			oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} else { | ||||
| 			return placeItem(right, item, depth + 1); | ||||
| 		} | ||||
| @@ -584,13 +586,13 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth | ||||
| 				item->right = left->right; | ||||
| 			} | ||||
| 			oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} else { | ||||
| 			return placeItem(left, item, depth + 1); | ||||
| 		} | ||||
| 	} else { | ||||
| 		oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself."); | ||||
| 		return OxError(1, "Cannot insert an item on itself."); | ||||
| 		return ox::Error(1, "Cannot insert an item on itself."); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -598,9 +600,9 @@ template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) { | ||||
| 	auto fsData = fileStoreData(); | ||||
| 	if (!fsData) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); | ||||
| 	OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate()); | ||||
| 	if (root->id == item->id) { | ||||
| 		item->left = root->left; | ||||
| 		item->right = root->right; | ||||
| @@ -622,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) { | ||||
| 		} else { | ||||
| 			fsData->rootNode = 0; | ||||
| 		} | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} else { | ||||
| 		return unplaceItem(root, item); | ||||
| 	} | ||||
| @@ -632,7 +634,7 @@ template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) { | ||||
| 	if (depth >= 5000) { | ||||
| 		oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow."); | ||||
| 		return OxError(1, "Excessive recursion depth, stopping before stack overflow."); | ||||
| 		return ox::Error(1, "Excessive recursion depth, stopping before stack overflow."); | ||||
| 	} | ||||
| 	if (item->id > root->id) { | ||||
| 		auto right = m_buffer->ptr(root->right); | ||||
| @@ -651,25 +653,25 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep | ||||
| 			return unplaceItem(left, item, depth + 1); | ||||
| 		} | ||||
| 	} else { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	if (item->right) { | ||||
| 		oxReturnError(placeItem(m_buffer->ptr(item->right))); | ||||
| 		OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->right))); | ||||
| 	} | ||||
| 	if (item->left) { | ||||
| 		oxReturnError(placeItem(m_buffer->ptr(item->left))); | ||||
| 		OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left))); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| Error FileStoreTemplate<size_t>::remove(ItemPtr item) { | ||||
| 	if (item.valid()) { | ||||
| 		oxReturnError(unplaceItem(item)); | ||||
| 		oxReturnError(m_buffer->free(item)); | ||||
| 		return OxError(0); | ||||
| 		OX_RETURN_ERROR(unplaceItem(item)); | ||||
| 		OX_RETURN_ERROR(m_buffer->free(item)); | ||||
| 		return {}; | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename size_t> | ||||
| @@ -771,3 +773,5 @@ using FileStore16 = FileStoreTemplate<uint16_t>; | ||||
| using FileStore32 = FileStoreTemplate<uint32_t>; | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/fs/filesystem/directory.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/fs/filesystem/directory.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										64
									
								
								deps/ox/src/ox/fs/filesystem/directory.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								deps/ox/src/ox/fs/filesystem/directory.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -15,6 +15,8 @@ | ||||
|  | ||||
| #include "types.hpp" | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| template<typename InodeId_t> | ||||
| @@ -50,10 +52,10 @@ struct OX_PACKED DirectoryEntry { | ||||
| 			if (d.valid()) { | ||||
| 				d->inode = inode; | ||||
| 				auto const maxStrSz = bufferSize - 1 - sizeof(*this); | ||||
| 				ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len())); | ||||
| 				ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.size())); | ||||
| 				return {}; | ||||
| 			} | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
|  | ||||
| 		ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept { | ||||
| @@ -139,11 +141,11 @@ template<typename FileStore, typename InodeId_t> | ||||
| Error Directory<FileStore, InodeId_t>::init() noexcept { | ||||
| 	constexpr auto Size = sizeof(Buffer); | ||||
| 	oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId); | ||||
| 	oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory))); | ||||
| 	OX_RETURN_ERROR(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory))); | ||||
| 	auto buff = m_fs.read(m_inodeId).template to<Buffer>(); | ||||
| 	if (!buff.valid()) { | ||||
| 		m_size = 0; | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	new (buff) Buffer(Size); | ||||
| 	m_size = Size; | ||||
| @@ -156,21 +158,21 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) { | ||||
| 		oxTrace("ox.fs.Directory.mkdir", path.fullPath()); | ||||
| 		// determine if already exists | ||||
| 		ox::StringView name; | ||||
| 		oxReturnError(path.get(name)); | ||||
| 		OX_RETURN_ERROR(path.get(name)); | ||||
| 		auto childInode = find(PathIterator(name)); | ||||
| 		if (!childInode.ok()) { | ||||
| 			// if this is not the last item in the path and parents is disabled, | ||||
| 			// return an error | ||||
| 			if (!parents && path.hasNext()) { | ||||
| 				return OxError(1); | ||||
| 				return ox::Error(1); | ||||
| 			} | ||||
| 			childInode = m_fs.generateInodeId(); | ||||
| 			oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value); | ||||
| 			oxLogError(childInode.error); | ||||
| 			oxReturnError(childInode.error); | ||||
| 			OX_RETURN_ERROR(childInode.error); | ||||
| 			// initialize the directory | ||||
| 			Directory<FileStore, InodeId_t> child(m_fs, childInode.value); | ||||
| 			oxReturnError(child.init()); | ||||
| 			OX_RETURN_ERROR(child.init()); | ||||
| 			auto err = write(PathIterator(name), childInode.value); | ||||
| 			if (err) { | ||||
| 				oxLogError(err); | ||||
| @@ -181,7 +183,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) { | ||||
| 		} | ||||
| 		Directory<FileStore, InodeId_t> child(m_fs, childInode.value); | ||||
| 		if (path.hasNext()) { | ||||
| 			oxReturnError(child.mkdir(path.next(), parents)); | ||||
| 			OX_RETURN_ERROR(child.mkdir(path.next(), parents)); | ||||
| 		} | ||||
| 	} | ||||
| 	return {}; | ||||
| @@ -194,45 +196,45 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64 | ||||
| 	if (path.next().hasNext()) { // not yet at target directory, recurse to next one | ||||
| 		oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}", | ||||
| 		         name, path.fullPath()); | ||||
| 		oxReturnError(path.get(name)); | ||||
| 		oxRequire(nextChild, findEntry(name)); | ||||
| 		OX_RETURN_ERROR(path.get(name)); | ||||
| 		OX_REQUIRE(nextChild, findEntry(name)); | ||||
| 		oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild); | ||||
| 		if (nextChild) { | ||||
| 			return Directory(m_fs, nextChild).write(path.next(), inode); | ||||
| 		} else { | ||||
| 			oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name); | ||||
| 			return OxError(1, "File not found and not allowed to create it."); | ||||
| 			return ox::Error(1, "File not found and not allowed to create it."); | ||||
| 		} | ||||
| 	} else { | ||||
| 		oxTrace("ox.fs.Directory.write", path.fullPath()); | ||||
| 		oxReturnError(path.next(name)); | ||||
| 		OX_RETURN_ERROR(path.next(name)); | ||||
| 		// insert the new entry on this directory | ||||
| 		// get the name | ||||
| 		// find existing version of directory | ||||
| 		oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId); | ||||
| 		oxRequire(oldStat, m_fs.stat(m_inodeId)); | ||||
| 		OX_REQUIRE(oldStat, m_fs.stat(m_inodeId)); | ||||
| 		oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size); | ||||
| 		auto old = m_fs.read(m_inodeId).template to<Buffer>(); | ||||
| 		if (!old.valid()) { | ||||
| 			oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); | ||||
| 			return OxError(1, "Could not read existing version of Directory"); | ||||
| 			return ox::Error(1, "Could not read existing version of Directory"); | ||||
| 		} | ||||
| 		const auto pathSize = name.len() + 1; | ||||
| 		const auto pathSize = name.size() + 1; | ||||
| 		const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize); | ||||
| 		const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize); | ||||
| 		auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size); | ||||
| 		if (cpy == nullptr) { | ||||
| 			oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory"); | ||||
| 			return OxError(1, "Could not allocate memory for copy of Directory"); | ||||
| 			return ox::Error(1, "Could not allocate memory for copy of Directory"); | ||||
| 		} | ||||
| 		oxReturnError(cpy->setSize(newSize)); | ||||
| 		OX_RETURN_ERROR(cpy->setSize(newSize)); | ||||
| 		auto val = cpy->malloc(entryDataSize).value; | ||||
| 		if (!val.valid()) { | ||||
| 			oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry"); | ||||
| 			return OxError(1, "Could not allocate memory for new directory entry"); | ||||
| 			return ox::Error(1, "Could not allocate memory for new directory entry"); | ||||
| 		} | ||||
| 		oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name); | ||||
| 		oxReturnError(val->init(inode, name, val.size())); | ||||
| 		OX_RETURN_ERROR(val->init(inode, name, val.size())); | ||||
| 		return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory)); | ||||
| 	} | ||||
| } | ||||
| @@ -240,7 +242,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64 | ||||
| template<typename FileStore, typename InodeId_t> | ||||
| Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { | ||||
| 	ox::StringView name; | ||||
| 	oxReturnError(path.get(name)); | ||||
| 	OX_RETURN_ERROR(path.get(name)); | ||||
| 	oxTrace("ox.fs.Directory.remove", name); | ||||
| 	auto buff = m_fs.read(m_inodeId).template to<Buffer>(); | ||||
| 	if (buff.valid()) { | ||||
| @@ -249,7 +251,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { | ||||
| 			auto data = i->data(); | ||||
| 			if (data.valid()) { | ||||
| 				if (name == data->name) { | ||||
| 					oxReturnError(buff->free(i)); | ||||
| 					OX_RETURN_ERROR(buff->free(i)); | ||||
| 				} | ||||
| 			} else { | ||||
| 				oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY"); | ||||
| @@ -257,7 +259,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { | ||||
| 		} | ||||
| 	} else { | ||||
| 		oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer"); | ||||
| 		return OxError(1, "Could not find directory buffer"); | ||||
| 		return ox::Error(1, "Could not find directory buffer"); | ||||
| 	} | ||||
| 	return {}; | ||||
| } | ||||
| @@ -269,13 +271,13 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept { | ||||
| 	auto buff = m_fs.read(m_inodeId).template to<Buffer>(); | ||||
| 	if (!buff.valid()) { | ||||
| 		oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer"); | ||||
| 		return OxError(1, "Could not directory buffer"); | ||||
| 		return ox::Error(1, "Could not directory buffer"); | ||||
| 	} | ||||
| 	oxTrace("ox.fs.Directory.ls", "Found directory buffer."); | ||||
| 	for (auto i = buff->iterator(); i.valid(); i.next()) { | ||||
| 		auto data = i->data(); | ||||
| 		if (data.valid()) { | ||||
| 			oxReturnError(cb(data->name, data->inode)); | ||||
| 			OX_RETURN_ERROR(cb(data->name, data->inode)); | ||||
| 		} else { | ||||
| 			oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY"); | ||||
| 		} | ||||
| @@ -289,7 +291,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry | ||||
| 	auto buff = m_fs.read(m_inodeId).template to<Buffer>(); | ||||
| 	if (!buff.valid()) { | ||||
| 		oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer"); | ||||
| 		return OxError(2, "Could not findEntry directory buffer"); | ||||
| 		return ox::Error(2, "Could not findEntry directory buffer"); | ||||
| 	} | ||||
| 	oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size()); | ||||
| 	for (auto i = buff->iterator(); i.valid(); i.next()) { | ||||
| @@ -305,15 +307,15 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry | ||||
| 		} | ||||
| 	} | ||||
| 	oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present"); | ||||
| 	return OxError(1, "Entry not present"); | ||||
| 	return ox::Error(1, "Entry not present"); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename InodeId_t> | ||||
| Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept { | ||||
| 	// determine if already exists | ||||
| 	ox::StringView name; | ||||
| 	oxReturnError(path.get(name)); | ||||
| 	oxRequire(v, findEntry(name)); | ||||
| 	OX_RETURN_ERROR(path.get(name)); | ||||
| 	OX_REQUIRE(v, findEntry(name)); | ||||
| 	// recurse if not at end of path | ||||
| 	if (auto p = path.next(); p.valid()) { | ||||
| 		Directory dir(m_fs, v); | ||||
| @@ -333,3 +335,5 @@ using Directory16 = Directory<FileStore16, uint16_t>; | ||||
| using Directory32 = Directory<FileStore32, uint32_t>; | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -31,8 +31,10 @@ FileAddress::FileAddress(uint64_t inode) noexcept { | ||||
| FileAddress::FileAddress(ox::StringViewCR path) noexcept { | ||||
| 	auto pathSize = path.bytes(); | ||||
| 	m_data.path = new char[pathSize + 1]; | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 	memcpy(m_data.path, path.data(), pathSize); | ||||
| 	m_data.path[pathSize] = 0; | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	m_type = FileAddressType::Path; | ||||
| } | ||||
|  | ||||
| @@ -46,9 +48,11 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept { | ||||
| 		case FileAddressType::Path: | ||||
| 		{ | ||||
| 			if (other.m_data.path) { | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 				auto strSize = ox::strlen(other.m_data.path) + 1; | ||||
| 				m_data.path = new char[strSize]; | ||||
| 				ox::memcpy(m_data.path, other.m_data.path, strSize); | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			} else { | ||||
| 				m_data.constPath = ""; | ||||
| 				m_type = FileAddressType::ConstPath; | ||||
|   | ||||
							
								
								
									
										35
									
								
								deps/ox/src/ox/fs/filesystem/filelocation.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								deps/ox/src/ox/fs/filesystem/filelocation.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -13,6 +13,8 @@ | ||||
| #include <ox/model/typenamecatcher.hpp> | ||||
| #include <ox/model/types.hpp> | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| enum class FileAddressType: int8_t { | ||||
| @@ -22,9 +24,6 @@ enum class FileAddressType: int8_t { | ||||
| 	Inode, | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept; | ||||
|  | ||||
| class FileAddress { | ||||
|  | ||||
| 	template<typename T> | ||||
| @@ -87,7 +86,7 @@ class FileAddress { | ||||
| 				case FileAddressType::Inode: | ||||
| 					return m_data.inode; | ||||
| 				default: | ||||
| 					return OxError(1); | ||||
| 					return ox::Error(1); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -98,7 +97,7 @@ class FileAddress { | ||||
| 				case FileAddressType::ConstPath: | ||||
| 					return ox::CStringView(m_data.constPath); | ||||
| 				default: | ||||
| 					return OxError(1); | ||||
| 					return ox::Error(1); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -152,31 +151,33 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept { | ||||
|  | ||||
| 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)); | ||||
| 	OX_RETURN_ERROR(h->template setTypeInfo<FileAddress::Data>()); | ||||
| 	OX_RETURN_ERROR(h->fieldCString("path", &obj->path)); | ||||
| 	OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path)); | ||||
| 	OX_RETURN_ERROR(h->field("inode", &obj->inode)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept { | ||||
| 	oxReturnError(h->template setTypeInfo<FileAddress>()); | ||||
| 	OX_RETURN_ERROR(h->template setTypeInfo<FileAddress>()); | ||||
| 	if constexpr(T::opType() == OpType::Reflect) { | ||||
| 		int8_t type = -1; | ||||
| 		oxReturnError(h->field("type", &type)); | ||||
| 		oxReturnError(h->field("data", UnionView(&fa->m_data, type))); | ||||
| 		OX_RETURN_ERROR(h->field("type", &type)); | ||||
| 		OX_RETURN_ERROR(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)); | ||||
| 		OX_RETURN_ERROR(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)))); | ||||
| 		OX_RETURN_ERROR(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)))); | ||||
| 		OX_RETURN_ERROR(h->field("type", &type)); | ||||
| 		OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); | ||||
| 	} | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
							
								
								
									
										73
									
								
								deps/ox/src/ox/fs/filesystem/filesystem.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								deps/ox/src/ox/fs/filesystem/filesystem.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -21,7 +21,7 @@ Result<const char*> MemFS::directAccess(const FileAddress &addr) const noexcept | ||||
| 		case FileAddressType::Path: | ||||
| 			return directAccess(StringView(addr.getPath().value)); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -33,46 +33,73 @@ Error FileSystem::read(const FileAddress &addr, void *buffer, std::size_t size) | ||||
| 		case FileAddressType::Path: | ||||
| 			return readFilePath(StringView(addr.getPath().value), buffer, size); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Result<Buffer> FileSystem::read(FileAddress const &addr, size_t const size) noexcept { | ||||
| 	Result<Buffer> out; | ||||
| 	out.value.resize(size); | ||||
| 	switch (addr.type()) { | ||||
| 		case FileAddressType::Inode: | ||||
| 			OX_RETURN_ERROR(readFileInode(addr.getInode().value, out.value.data(), size)); | ||||
| 			break; | ||||
| 		case FileAddressType::ConstPath: | ||||
| 		case FileAddressType::Path: | ||||
| 			OX_RETURN_ERROR(readFilePath(StringView{addr.getPath().value}, out.value.data(), size)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			return ox::Error{1}; | ||||
| 	} | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| Result<Buffer> FileSystem::read(StringViewCR path, size_t const size) noexcept { | ||||
| 	Result<Buffer> out; | ||||
| 	out.value.resize(size); | ||||
| 	OX_RETURN_ERROR(readFilePath(path, out.value.data(), size)); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept { | ||||
| 	oxRequire(s, stat(addr)); | ||||
| 	OX_REQUIRE(s, stat(addr)); | ||||
| 	Buffer buff(static_cast<std::size_t>(s.size)); | ||||
| 	oxReturnError(read(addr, buff.data(), buff.size())); | ||||
| 	OX_RETURN_ERROR(read(addr, buff.data(), buff.size())); | ||||
| 	return buff; | ||||
| } | ||||
|  | ||||
| Result<Buffer> FileSystem::read(StringViewCR path) noexcept { | ||||
| 	oxRequire(s, statPath(path)); | ||||
| 	OX_REQUIRE(s, statPath(path)); | ||||
| 	Buffer buff(static_cast<std::size_t>(s.size)); | ||||
| 	oxReturnError(readFilePath(path, buff.data(), buff.size())); | ||||
| 	OX_RETURN_ERROR(readFilePath(path, buff.data(), buff.size())); | ||||
| 	return buff; | ||||
| } | ||||
|  | ||||
| Error FileSystem::read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept { | ||||
| Error FileSystem::read( | ||||
| 		FileAddress const &addr, | ||||
| 		std::size_t const readStart, | ||||
| 		std::size_t const readSize, | ||||
| 		void *buffer, | ||||
| 		std::size_t *size) noexcept { | ||||
| 	switch (addr.type()) { | ||||
| 		case FileAddressType::Inode: | ||||
| 			return read(addr.getInode().value, readStart, readSize, buffer, size); | ||||
| 			return readFileInodeRange(addr.getInode().value, readStart, readSize, buffer, size); | ||||
| 		case FileAddressType::ConstPath: | ||||
| 		case FileAddressType::Path: | ||||
| 			return OxError(2, "Unsupported for path lookups"); | ||||
| 			return readFilePathRange(addr.getPath().value, readStart, readSize, buffer, size); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Error FileSystem::remove(const FileAddress &addr, bool recursive) noexcept { | ||||
| 	switch (addr.type()) { | ||||
| 		case FileAddressType::Inode: | ||||
| 			return remove(addr.getInode().value, recursive); | ||||
| 		case FileAddressType::ConstPath: | ||||
| 		case FileAddressType::Path: | ||||
| 			return remove(StringView(addr.getPath().value), recursive); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 	} | ||||
| Result<size_t> FileSystem::read( | ||||
| 		StringViewCR path, | ||||
| 		std::size_t const readStart, | ||||
| 		std::size_t const readSize, | ||||
| 		Span<char> buff) noexcept { | ||||
| 	size_t szOut{buff.size()}; | ||||
| 	OX_RETURN_ERROR(readFilePathRange(path, readStart, readSize, buff.data(), &szOut)); | ||||
| 	return szOut; | ||||
| } | ||||
|  | ||||
| Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| @@ -83,7 +110,7 @@ Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t si | ||||
| 		case FileAddressType::Path: | ||||
| 			return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -95,7 +122,7 @@ Result<FileStat> FileSystem::stat(const FileAddress &addr) const noexcept { | ||||
| 		case FileAddressType::Path: | ||||
| 			return statPath(StringView(addr.getPath().value)); | ||||
| 		default: | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										201
									
								
								deps/ox/src/ox/fs/filesystem/filesystem.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										201
									
								
								deps/ox/src/ox/fs/filesystem/filesystem.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -20,7 +20,7 @@ | ||||
| namespace ox { | ||||
|  | ||||
| namespace detail { | ||||
| static inline void fsBuffFree(char *buff) noexcept { | ||||
| inline void fsBuffFree(char *buff) noexcept { | ||||
| 	safeDelete(buff); | ||||
| } | ||||
| } | ||||
| @@ -41,25 +41,45 @@ class FileSystem { | ||||
|  | ||||
| 		Error read(const FileAddress &addr, void *buffer, std::size_t size) noexcept; | ||||
|  | ||||
| 		Result<Buffer> read(FileAddress const &addr, size_t size) noexcept; | ||||
|  | ||||
| 		Result<Buffer> read(StringViewCR path, size_t size) noexcept; | ||||
|  | ||||
| 		Result<Buffer> read(const FileAddress &addr) noexcept; | ||||
|  | ||||
| 		Result<Buffer> read(StringViewCR path) noexcept; | ||||
|  | ||||
| 		inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { | ||||
| 		Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { | ||||
| 			return readFilePath(path, buffer, buffSize); | ||||
| 		} | ||||
|  | ||||
| 		inline Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { | ||||
| 		Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { | ||||
| 			return readFileInode(inode, buffer, buffSize); | ||||
| 		} | ||||
|  | ||||
| 		Error read(const FileAddress &addr, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept; | ||||
| 		Error read( | ||||
| 			FileAddress const &addr, | ||||
| 			size_t readStart, | ||||
| 			size_t readSize, | ||||
| 			void *buffer, | ||||
| 			size_t *size) noexcept; | ||||
|  | ||||
| 		/** | ||||
| 		 * | ||||
| 		 * @param path | ||||
| 		 * @param readStart | ||||
| 		 * @param readSize | ||||
| 		 * @param buff | ||||
| 		 * @return error or number of bytes read | ||||
| 		 */ | ||||
| 		Result<size_t> read( | ||||
| 			StringViewCR path, size_t readStart, size_t readSize, ox::Span<char> buff) noexcept; | ||||
|  | ||||
| 		virtual Result<Vector<String>> ls(StringViewCR dir) const noexcept = 0; | ||||
|  | ||||
| 		virtual Error remove(StringViewCR path, bool recursive) noexcept = 0; | ||||
|  | ||||
| 		Error remove(const FileAddress &addr, bool recursive = false) noexcept; | ||||
| 		Error remove(StringViewCR path, bool recursive = false) noexcept { | ||||
| 			return removePath(path, recursive); | ||||
| 		} | ||||
|  | ||||
| 		virtual Error resize(uint64_t size, void *buffer) noexcept = 0; | ||||
|  | ||||
| @@ -67,7 +87,7 @@ class FileSystem { | ||||
| 			return writeFilePath(path, buffer, size, FileType::NormalFile); | ||||
| 		} | ||||
|  | ||||
| 		Error write(StringViewCR path, ox::Span<char> const&buff) noexcept { | ||||
| 		Error write(StringViewCR path, ox::SpanView<char> const&buff) noexcept { | ||||
| 			return write(path, buff.data(), buff.size(), FileType::NormalFile); | ||||
| 		} | ||||
|  | ||||
| @@ -75,42 +95,42 @@ class FileSystem { | ||||
| 			return write(inode, buffer, size, FileType::NormalFile); | ||||
| 		} | ||||
|  | ||||
| 		Error write(uint64_t inode, ox::Span<char> const&buff) noexcept { | ||||
| 		Error write(uint64_t inode, ox::SpanView<char> const&buff) noexcept { | ||||
| 			return write(inode, buff.data(), buff.size(), FileType::NormalFile); | ||||
| 		} | ||||
|  | ||||
| 		Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; | ||||
|  | ||||
| 		inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| 		Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| 			return writeFilePath(path, buffer, size, fileType); | ||||
| 		} | ||||
|  | ||||
| 		inline Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| 		Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| 			return writeFileInode(inode, buffer, size, fileType); | ||||
| 		} | ||||
|  | ||||
| 		inline Result<FileStat> stat(uint64_t inode) const noexcept { | ||||
| 		Result<FileStat> stat(uint64_t inode) const noexcept { | ||||
| 			return statInode(inode); | ||||
| 		} | ||||
|  | ||||
| 		inline Result<FileStat> stat(StringViewCR path) const noexcept { | ||||
| 		Result<FileStat> stat(StringViewCR path) const noexcept { | ||||
| 			return statPath(path); | ||||
| 		} | ||||
|  | ||||
| 		Result<FileStat> stat(const FileAddress &addr) const noexcept; | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		inline bool exists(uint64_t inode) const noexcept { | ||||
| 		bool exists(uint64_t inode) const noexcept { | ||||
| 			return statInode(inode).ok(); | ||||
| 		} | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		inline bool exists(ox::StringView path) const noexcept { | ||||
| 		bool exists(ox::StringView path) const noexcept { | ||||
| 			return statPath(path).ok(); | ||||
| 		} | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		inline bool exists(FileAddress const&addr) const noexcept { | ||||
| 		bool exists(FileAddress const&addr) const noexcept { | ||||
| 			return stat(addr).ok(); | ||||
| 		} | ||||
|  | ||||
| @@ -140,7 +160,12 @@ class FileSystem { | ||||
|  | ||||
| 		virtual Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept = 0; | ||||
|  | ||||
| 		virtual Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept = 0; | ||||
| 		virtual Error readFilePathRange( | ||||
| 			StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept = 0; | ||||
|  | ||||
| 		virtual Error readFileInodeRange(uint64_t inode, size_t readStart, size_t readSize, void *buffer, size_t *size) noexcept = 0; | ||||
|  | ||||
| 		virtual Error removePath(StringViewCR path, bool recursive) noexcept = 0; | ||||
|  | ||||
| 		virtual Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept = 0; | ||||
|  | ||||
| @@ -152,11 +177,11 @@ class MemFS: public FileSystem { | ||||
| 	public: | ||||
| 		Result<const char*> directAccess(const FileAddress &addr) const noexcept; | ||||
|  | ||||
| 		inline Result<const char*> directAccess(StringViewCR path) const noexcept { | ||||
| 		Result<const char*> directAccess(StringViewCR path) const noexcept { | ||||
| 			return directAccessPath(path); | ||||
| 		} | ||||
|  | ||||
| 		inline Result<const char*> directAccess(uint64_t inode) const noexcept { | ||||
| 		Result<const char*> directAccess(uint64_t inode) const noexcept { | ||||
| 			return directAccessInode(inode); | ||||
| 		} | ||||
|  | ||||
| @@ -209,6 +234,11 @@ class FileSystemTemplate: public MemFS { | ||||
|  | ||||
| 		Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override; | ||||
|  | ||||
| 		Error readFilePathRange( | ||||
| 			StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept override; | ||||
|  | ||||
| 		Error removePath(StringViewCR path, bool recursive) noexcept override; | ||||
|  | ||||
| 		Result<const char*> directAccessInode(uint64_t) const noexcept override; | ||||
|  | ||||
| 		Result<Vector<String>> ls(StringViewCR dir) const noexcept override; | ||||
| @@ -216,8 +246,6 @@ class FileSystemTemplate: public MemFS { | ||||
| 		template<typename F> | ||||
| 		Error ls(StringViewCR path, F cb) const; | ||||
|  | ||||
| 		Error remove(StringViewCR path, bool recursive) noexcept override; | ||||
|  | ||||
| 		/** | ||||
| 		 * Resizes FileSystem to minimum possible size. | ||||
| 		 */ | ||||
| @@ -284,69 +312,69 @@ FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() noexcept { | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept { | ||||
| 	oxReturnError(FileStore::format(buff, static_cast<size_t>(buffSize))); | ||||
| 	OX_RETURN_ERROR(FileStore::format(buff, static_cast<size_t>(buffSize))); | ||||
| 	FileStore fs(buff, static_cast<size_t>(buffSize)); | ||||
|  | ||||
| 	constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2; | ||||
| 	Directory rootDir(fs, rootDirInode); | ||||
| 	oxReturnError(rootDir.init()); | ||||
| 	OX_RETURN_ERROR(rootDir.init()); | ||||
|  | ||||
| 	FileSystemData fd; | ||||
| 	fd.rootDirInode = rootDirInode; | ||||
| 	oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get()); | ||||
| 	oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd))); | ||||
| 	OX_RETURN_ERROR(fs.write(InodeFsData, &fd, sizeof(fd))); | ||||
|  | ||||
| 	if (!fs.read(fd.rootDirInode).valid()) { | ||||
| 		oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory"); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
|  | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept { | ||||
| 	oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive); | ||||
| 	oxRequireM(rootDir, this->rootDir()); | ||||
| 	OX_REQUIRE_M(rootDir, this->rootDir()); | ||||
| 	return rootDir.mkdir(path, recursive); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept { | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	Directory rootDir(m_fs, fd.rootDirInode); | ||||
| 	oxRequireM(inode, rootDir.find(src)); | ||||
| 	oxReturnError(rootDir.write(dest, inode)); | ||||
| 	oxReturnError(rootDir.remove(src)); | ||||
| 	return OxError(0); | ||||
| 	OX_REQUIRE_M(inode, rootDir.find(src)); | ||||
| 	OX_RETURN_ERROR(rootDir.write(dest, inode)); | ||||
| 	OX_RETURN_ERROR(rootDir.remove(src)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { | ||||
| 	oxTrace("ox.fs.FileSystemTemplate.readFilePath", path); | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	Directory rootDir(m_fs, fd.rootDirInode); | ||||
| 	oxRequire(s, stat(path)); | ||||
| 	OX_REQUIRE(s, stat(path)); | ||||
| 	if (s.size > buffSize) { | ||||
| 		return OxError(1, "Buffer to small to load file"); | ||||
| 		return ox::Error(1, "Buffer to small to load file"); | ||||
| 	} | ||||
| 	return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept { | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	Directory rootDir(m_fs, fd.rootDirInode); | ||||
| 	oxRequire(inode, rootDir.find(path)); | ||||
| 	OX_REQUIRE(inode, rootDir.find(path)); | ||||
| 	return directAccessInode(inode); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { | ||||
| 	oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode); | ||||
| 	oxRequire(s, stat(inode)); | ||||
| 	OX_REQUIRE(s, stat(inode)); | ||||
| 	if (s.size > buffSize) { | ||||
| 		return OxError(1, "Buffer to small to load file"); | ||||
| 		return ox::Error(1, "Buffer to small to load file"); | ||||
| 	} | ||||
| 	return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); | ||||
| } | ||||
| @@ -357,39 +385,18 @@ Error FileSystemTemplate<FileStore, Directory>::readFileInodeRange(uint64_t inod | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept { | ||||
| 	auto data = m_fs.read(inode); | ||||
| 	if (!data.valid()) { | ||||
| 		return OxError(1, "Data not valid"); | ||||
| 	} | ||||
| 	return reinterpret_cast<char*>(data.get()); | ||||
| Error FileSystemTemplate<FileStore, Directory>::readFilePathRange( | ||||
| 	StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept { | ||||
| 	OX_REQUIRE(s, stat(path)); | ||||
| 	return readFileInodeRange(s.inode, readStart, readSize, buffer, buffSize); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept { | ||||
| 	Vector<String> out; | ||||
| 	oxReturnError(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) { | ||||
| 		out.emplace_back(name); | ||||
| 		return OxError(0); | ||||
| 	})); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| template<typename F> | ||||
| Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const { | ||||
| 	oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path); | ||||
| 	oxRequire(s, stat(path)); | ||||
| 	Directory dir(m_fs, s.inode); | ||||
| 	return dir.ls(cb); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept { | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| Error FileSystemTemplate<FileStore, Directory>::removePath(StringViewCR path, bool recursive) noexcept { | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	Directory rootDir(m_fs, fd.rootDirInode); | ||||
| 	oxRequire(inode, rootDir.find(path)); | ||||
| 	oxRequire(st, statInode(inode)); | ||||
| 	OX_REQUIRE(inode, rootDir.find(path)); | ||||
| 	OX_REQUIRE(st, statInode(inode)); | ||||
| 	if (st.fileType == FileType::NormalFile || recursive) { | ||||
| 		if (auto err = rootDir.remove(path)) { | ||||
| 			// removal failed, try putting the index back | ||||
| @@ -398,9 +405,37 @@ Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool r | ||||
| 		} | ||||
| 	} else { | ||||
| 		oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept { | ||||
| 	auto data = m_fs.read(inode); | ||||
| 	if (!data.valid()) { | ||||
| 		return ox::Error(1, "Data not valid"); | ||||
| 	} | ||||
| 	return reinterpret_cast<char*>(data.get()); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept { | ||||
| 	Vector<String> out; | ||||
| 	OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) { | ||||
| 		out.emplace_back(name); | ||||
| 		return ox::Error{}; | ||||
| 	})); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| template<typename F> | ||||
| Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const { | ||||
| 	oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path); | ||||
| 	OX_REQUIRE(s, stat(path)); | ||||
| 	Directory dir(m_fs, s.inode); | ||||
| 	return dir.ls(cb); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| @@ -410,7 +445,7 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept { | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept { | ||||
| 	oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer)); | ||||
| 	OX_RETURN_ERROR(m_fs.resize(static_cast<size_t>(size), buffer)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| @@ -423,23 +458,23 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath( | ||||
| 	oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path); | ||||
| 	auto [inode, err] = find(path); | ||||
| 	if (err) { | ||||
| 		oxReturnError(m_fs.generateInodeId().moveTo(inode)); | ||||
| 		oxRequireM(rootDir, this->rootDir()); | ||||
| 		oxReturnError(rootDir.write(path, inode)); | ||||
| 		OX_RETURN_ERROR(m_fs.generateInodeId().moveTo(inode)); | ||||
| 		OX_REQUIRE_M(rootDir, this->rootDir()); | ||||
| 		OX_RETURN_ERROR(rootDir.write(path, inode)); | ||||
| 	} | ||||
| 	oxReturnError(writeFileInode(inode, buffer, size, fileType)); | ||||
| 	OX_RETURN_ERROR(writeFileInode(inode, buffer, size, fileType)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { | ||||
| 	oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::itoa(inode)); | ||||
| 	oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::intToStr(inode)); | ||||
| 	return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType)); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept { | ||||
| 	oxRequire(s, m_fs.stat(inode)); | ||||
| 	OX_REQUIRE(s, m_fs.stat(inode)); | ||||
| 	FileStat out; | ||||
| 	out.inode = s.inode; | ||||
| 	out.links = s.links; | ||||
| @@ -450,7 +485,7 @@ Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t in | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept { | ||||
| 	oxRequire(inode, find(path)); | ||||
| 	OX_REQUIRE(inode, find(path)); | ||||
| 	return stat(inode); | ||||
| } | ||||
|  | ||||
| @@ -487,25 +522,25 @@ bool FileSystemTemplate<FileStore, Directory>::valid() const noexcept { | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept { | ||||
| 	FileSystemData fd; | ||||
| 	oxReturnError(m_fs.read(InodeFsData, &fd, sizeof(fd))); | ||||
| 	OX_RETURN_ERROR(m_fs.read(InodeFsData, &fd, sizeof(fd))); | ||||
| 	return fd; | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept { | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	// return root as a special case | ||||
| 	if (path == "/") { | ||||
| 		return static_cast<uint64_t>(fd.rootDirInode); | ||||
| 	} | ||||
| 	Directory rootDir(m_fs, fd.rootDirInode); | ||||
| 	oxRequire(out, rootDir.find(path)); | ||||
| 	OX_REQUIRE(out, rootDir.find(path)); | ||||
| 	return static_cast<uint64_t>(out); | ||||
| } | ||||
|  | ||||
| template<typename FileStore, typename Directory> | ||||
| Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept { | ||||
| 	oxRequire(fd, fileSystemData()); | ||||
| 	OX_REQUIRE(fd, fileSystemData()); | ||||
| 	return Directory(m_fs, fd.rootDirInode); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										82
									
								
								deps/ox/src/ox/fs/filesystem/passthroughfs.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								deps/ox/src/ox/fs/filesystem/passthroughfs.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept { | ||||
| 			success = true; | ||||
| 		} else { | ||||
| 			success = std::filesystem::create_directories(p, ec); | ||||
| 			oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); | ||||
| 			OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); | ||||
| 		} | ||||
| 	} else { | ||||
| 		std::error_code ec; | ||||
| @@ -48,26 +48,26 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept { | ||||
| 			success = true; | ||||
| 		} else { | ||||
| 			success = std::filesystem::create_directory(p, ec); | ||||
| 			oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); | ||||
| 			OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(success ? 0 : 1); | ||||
| 	return ox::Error(success ? 0 : 1); | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept { | ||||
| 	std::error_code ec; | ||||
| 	std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec); | ||||
| 	if (ec.value()) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { | ||||
| 	Vector<String> out; | ||||
| 	std::error_code ec; | ||||
| 	const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); | ||||
| 	OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); | ||||
| 	for (const auto &p : di) { | ||||
| 		const auto u8p = p.path().filename().u8string(); | ||||
| 		out.emplace_back(reinterpret_cast<const char*>(u8p.c_str())); | ||||
| @@ -75,22 +75,14 @@ Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept { | ||||
| 	if (recursive) { | ||||
| 		return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0); | ||||
| 	} else { | ||||
| 		return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::resize(uint64_t, void*) noexcept { | ||||
| 	// unsupported | ||||
| 	return OxError(1, "resize is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "resize is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept { | ||||
| 	// unsupported | ||||
| 	return OxError(1, "statInode(uint64_t) is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "statInode(uint64_t) is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept { | ||||
| @@ -101,7 +93,9 @@ Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept { | ||||
| 	oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path); | ||||
| 	const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec); | ||||
| 	oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed")); | ||||
| 	if (auto err = ec.value()) { | ||||
| 		return ox::Error{static_cast<ox::ErrorCode>(err), "PassThroughFS: stat failed"}; | ||||
| 	} | ||||
| 	return FileStat{0, 0, size, type}; | ||||
| } | ||||
|  | ||||
| @@ -112,14 +106,14 @@ uint64_t PassThroughFS::spaceNeeded(uint64_t size) const noexcept { | ||||
| Result<uint64_t> PassThroughFS::available() const noexcept { | ||||
| 	std::error_code ec; | ||||
| 	const auto s = std::filesystem::space(m_path, ec); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); | ||||
| 	OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); | ||||
| 	return s.available; | ||||
| } | ||||
|  | ||||
| Result<uint64_t> PassThroughFS::size() const noexcept { | ||||
| 	std::error_code ec; | ||||
| 	const auto s = std::filesystem::space(m_path, ec); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); | ||||
| 	OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); | ||||
| 	return s.capacity; | ||||
| } | ||||
|  | ||||
| @@ -128,7 +122,7 @@ char *PassThroughFS::buff() noexcept { | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept { | ||||
| 	return OxError(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| bool PassThroughFS::valid() const noexcept { | ||||
| @@ -147,24 +141,51 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b | ||||
| 		file.seekg(0, std::ios::beg); | ||||
| 		if (size > buffSize) { | ||||
| 			oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path); | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 		file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize)); | ||||
| 	} catch (const std::fstream::failure &f) { | ||||
| 		oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); | ||||
| 		return OxError(2); | ||||
| 		return ox::Error(2); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { | ||||
| 	// unsupported | ||||
| 	return OxError(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::readFilePathRange( | ||||
| 	StringViewCR path, size_t const readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept { | ||||
| 	try { | ||||
| 		std::ifstream file(m_path / stripSlash(path), std::ios::binary | std::ios::ate); | ||||
| 		auto const size = static_cast<size_t>(file.tellg()); | ||||
| 		readSize = ox::min(readSize, size); | ||||
| 		file.seekg(static_cast<off_t>(readStart), std::ios::beg); | ||||
| 		if (readSize > *buffSize) { | ||||
| 			oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path); | ||||
| 			return ox::Error{1}; | ||||
| 		} | ||||
| 		file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(readSize)); | ||||
| 		return {}; | ||||
| 	} catch (std::fstream::failure const &f) { | ||||
| 		oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); | ||||
| 		return ox::Error{2}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept { | ||||
| 	// unsupported | ||||
| 	return OxError(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::removePath(StringViewCR path, bool const recursive) noexcept { | ||||
| 	if (recursive) { | ||||
| 		return ox::Error{std::filesystem::remove_all(m_path / stripSlash(path)) == 0}; | ||||
| 	} else { | ||||
| 		return ox::Error{!std::filesystem::remove(m_path / stripSlash(path))}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept { | ||||
| @@ -174,19 +195,18 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64 | ||||
| 		f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size)); | ||||
| 	} catch (const std::fstream::failure &f) { | ||||
| 		oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { | ||||
| 	// unsupported | ||||
| 	return OxError(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS"); | ||||
| 	return ox::Error(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS"); | ||||
| } | ||||
|  | ||||
| std::string_view PassThroughFS::stripSlash(StringView path) noexcept { | ||||
| 	const auto pathLen = ox::strlen(path); | ||||
| 	for (auto i = 0u; i < pathLen && path[0] == '/'; i++) { | ||||
| 	for (auto i = 0u; i < path.size() && path[0] == '/'; i++) { | ||||
| 		path = substr(path, 1); | ||||
| 	} | ||||
| 	return {path.data(), path.bytes()}; | ||||
|   | ||||
							
								
								
									
										15
									
								
								deps/ox/src/ox/fs/filesystem/passthroughfs.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								deps/ox/src/ox/fs/filesystem/passthroughfs.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -45,8 +45,6 @@ class PassThroughFS: public FileSystem { | ||||
| 		template<typename F> | ||||
| 		Error ls(StringViewCR dir, F cb) const noexcept; | ||||
|  | ||||
| 		Error remove(StringViewCR path, bool recursive) noexcept override; | ||||
|  | ||||
| 		Error resize(uint64_t size, void *buffer) noexcept override; | ||||
|  | ||||
| 		Result<FileStat> statInode(uint64_t inode) const noexcept override; | ||||
| @@ -73,8 +71,13 @@ class PassThroughFS: public FileSystem { | ||||
|  | ||||
| 		Error readFileInode(uint64_t inode, void *buffer, std::size_t size) noexcept override; | ||||
|  | ||||
| 		Error readFilePathRange( | ||||
| 			StringViewCR path, size_t readStart, size_t readSize, void *buffer, size_t *buffSize) noexcept override; | ||||
|  | ||||
| 		Error readFileInodeRange(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) noexcept override; | ||||
|  | ||||
| 		Error removePath(StringViewCR path, bool recursive) noexcept override; | ||||
|  | ||||
| 		Error writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept override; | ||||
|  | ||||
| 		Error writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept override; | ||||
| @@ -92,11 +95,11 @@ template<typename F> | ||||
| Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept { | ||||
| 	std::error_code ec; | ||||
| 	const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); | ||||
| 	OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); | ||||
| 	for (auto &p : di) { | ||||
| 		oxReturnError(cb(p.path().filename().c_str(), 0)); | ||||
| 		OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										34
									
								
								deps/ox/src/ox/fs/filesystem/pathiterator.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								deps/ox/src/ox/fs/filesystem/pathiterator.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -11,6 +11,8 @@ | ||||
| #include <ox/std/trace.hpp> | ||||
| #include "pathiterator.hpp" | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) { | ||||
| @@ -30,13 +32,13 @@ PathIterator::PathIterator(StringViewCR path): PathIterator(path.data(), path.by | ||||
|  */ | ||||
| Error PathIterator::dirPath(char *out, std::size_t outSize) { | ||||
| 	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) { | ||||
| 		ox::memcpy(out, m_path, size); | ||||
| 		out[size] = 0; | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} else { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -45,11 +47,11 @@ Error PathIterator::get(StringView &fileName) { | ||||
| 	std::size_t size = 0; | ||||
| 	if (m_iterator >= m_maxSize) { | ||||
| 		oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	if (!ox::strlen(&m_path[m_iterator])) { | ||||
| 		oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])"); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	auto start = m_iterator; | ||||
| 	if (m_path[start] == '/') { | ||||
| @@ -65,14 +67,14 @@ Error PathIterator::get(StringView &fileName) { | ||||
| 	size = end - start; | ||||
| 	// cannot fit the output in the output parameter | ||||
| 	if (size >= MaxFileNameLength || size == 0) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	fileName = ox::substr(m_path, start, start + size); | ||||
| 	// truncate trailing / | ||||
| 	if (size && fileName[size - 1] == '/') { | ||||
| 		fileName = ox::substr(m_path, start, start + size - 1); | ||||
| 	} | ||||
| 	oxAssert(fileName[fileName.len()-1] != '/', "name ends in /"); | ||||
| 	oxAssert(fileName[fileName.size()-1] != '/', "name ends in /"); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| @@ -81,9 +83,9 @@ Error PathIterator::get(StringView &fileName) { | ||||
|  */ | ||||
| Error PathIterator::next(StringView &fileName) { | ||||
| 	std::size_t size = 0; | ||||
| 	auto retval = OxError(1); | ||||
| 	auto retval = ox::Error(1); | ||||
| 	if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { | ||||
| 		retval = OxError(0); | ||||
| 		retval = {}; | ||||
| 		if (m_path[m_iterator] == '/') { | ||||
| 			m_iterator++; | ||||
| 		} | ||||
| @@ -98,25 +100,25 @@ Error PathIterator::next(StringView &fileName) { | ||||
| 		size = end - start; | ||||
| 		// cannot fit the output in the output parameter | ||||
| 		if (size >= MaxFileNameLength) { | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 		fileName = ox::substr(m_path, start, start + size); | ||||
| 		// truncate trailing / | ||||
| 		while (fileName.len() && fileName[fileName.len() - 1] == '/') { | ||||
| 		while (fileName.size() && fileName[fileName.size() - 1] == '/') { | ||||
| 			fileName = ox::substr(m_path, start, start + size); | ||||
| 		} | ||||
| 		m_iterator += size; | ||||
| 		oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /"); | ||||
| 		oxAssert(fileName.size() == 0 || fileName[fileName.size()-1] != '/', "name ends in /"); | ||||
| 	} | ||||
| 	return retval; | ||||
| } | ||||
|  | ||||
| Result<std::size_t> PathIterator::nextSize() const { | ||||
| 	std::size_t size = 0; | ||||
| 	auto retval = OxError(1); | ||||
| 	auto retval = ox::Error(1); | ||||
| 	auto it = m_iterator; | ||||
| 	if (it < m_maxSize && ox::strlen(&m_path[it])) { | ||||
| 		retval = OxError(0); | ||||
| 		retval = {}; | ||||
| 		if (m_path[it] == '/') { | ||||
| 			it++; | ||||
| 		} | ||||
| @@ -183,3 +185,5 @@ const char *PathIterator::fullPath() const { | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/fs/filesystem/types.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/fs/filesystem/types.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/fs/fs.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/fs/fs.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										34
									
								
								deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -13,6 +13,8 @@ | ||||
|  | ||||
| #include "ptr.hpp" | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox::ptrarith { | ||||
|  | ||||
| template<typename size_t, typename Item> | ||||
| @@ -282,14 +284,14 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal | ||||
| 				addr = m_header.firstItem; | ||||
| 			} else { | ||||
| 				oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state."); | ||||
| 				return OxError(1, "NodeBuffer is in invalid state."); | ||||
| 				return ox::Error(1, "NodeBuffer is in invalid state."); | ||||
| 			} | ||||
| 		} | ||||
| 		oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize); | ||||
| 		auto out = ItemPtr(this, m_header.size, addr, fullSize); | ||||
| 		if (!out.valid()) { | ||||
| 			oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown"); | ||||
| 			return OxError(1, "NodeBuffer::malloc: unknown failure"); | ||||
| 			return ox::Error(1, "NodeBuffer::malloc: unknown failure"); | ||||
| 		} | ||||
| 		ox::memset(out, 0, fullSize); | ||||
| 		new (out) Item; | ||||
| @@ -302,7 +304,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal | ||||
| 			first->prev = out.offset(); | ||||
| 		} else { | ||||
| 			oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer."); | ||||
| 			return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer."); | ||||
| 			return ox::Error(1, "NodeBuffer malloc failed due to invalid first element pointer."); | ||||
| 		} | ||||
|  | ||||
| 		if (oldLast.valid()) { | ||||
| @@ -312,7 +314,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal | ||||
| 			if (out.offset() != first.offset()) { | ||||
| 				// if this is not the first allocation, there should be an oldLast | ||||
| 				oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer."); | ||||
| 				return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer."); | ||||
| 				return ox::Error(1, "NodeBuffer malloc failed due to invalid last element pointer."); | ||||
| 			} | ||||
| 			out->prev = out.offset(); | ||||
| 		} | ||||
| @@ -321,7 +323,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal | ||||
| 		return out; | ||||
| 	} | ||||
| 	oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available()); | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename size_t, typename Item> | ||||
| @@ -344,15 +346,15 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept { | ||||
| 	} else { | ||||
| 		if (!prev.valid()) { | ||||
| 			oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset()); | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 		if (!next.valid()) { | ||||
| 			oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset()); | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 	} | ||||
| 	m_header.bytesUsed -= item.size(); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t, typename Item> | ||||
| @@ -363,12 +365,12 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept { | ||||
| 	oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end); | ||||
| 	if (end > size) { | ||||
| 		// resizing to less than buffer size | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} else { | ||||
| 		m_header.size = static_cast<size_t>(size); | ||||
| 		auto data = reinterpret_cast<uint8_t*>(this) + end; | ||||
| 		ox::memset(data, 0, size - end); | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -399,14 +401,14 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept { | ||||
| 	auto dest = ptr(sizeof(*this)); | ||||
| 	while (dest.offset() <= src.offset()) { | ||||
| 		if (!src.valid()) { | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
| 		if (!dest.valid()) { | ||||
| 			return OxError(2); | ||||
| 			return ox::Error(2); | ||||
| 		} | ||||
| 		// move node | ||||
| 		ox::memcpy(dest, src, src->fullSize()); | ||||
| 		oxReturnError(cb(src, dest)); | ||||
| 		OX_RETURN_ERROR(cb(src, dest)); | ||||
| 		// update surrounding nodes | ||||
| 		auto prev = ptr(dest->prev); | ||||
| 		if (prev.valid()) { | ||||
| @@ -420,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept { | ||||
| 		src = ptr(dest->next); | ||||
| 		dest = uninitializedPtr(dest.offset() + dest->fullSize()); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename size_t, typename Item> | ||||
| @@ -449,3 +451,5 @@ struct OX_PACKED Item { | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
							
								
								
									
										8
									
								
								deps/ox/src/ox/fs/ptrarith/ptr.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								deps/ox/src/ox/fs/ptrarith/ptr.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -10,6 +10,8 @@ | ||||
|  | ||||
| #include <ox/std/std.hpp> | ||||
|  | ||||
| OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) | ||||
|  | ||||
| namespace ox::ptrarith { | ||||
|  | ||||
| template<typename T, typename size_t, size_t minOffset = 1> | ||||
| @@ -252,7 +254,9 @@ constexpr Result<Ptr<T, size_t, minOffset>> Ptr<T, size_t, minOffset>::validate( | ||||
| 	 if (valid()) { | ||||
| 	 	return *this; | ||||
| 	 } | ||||
| 	 return OxError(1); | ||||
| 	 return ox::Error(1); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| OX_CLANG_NOWARN_END | ||||
|   | ||||
							
								
								
									
										51
									
								
								deps/ox/src/ox/fs/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								deps/ox/src/ox/fs/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -52,19 +52,19 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				oxAssert(buffer->free(a1), "Free failed."); | ||||
| 				oxAssert(buffer->free(a2), "Free failed."); | ||||
| 				oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed."); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"PathIterator::next1", | ||||
| 			[](ox::StringView) { | ||||
| 				auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); | ||||
| 				ox::PathIterator it(path.c_str(), path.len()); | ||||
| 				ox::PathIterator it(path.c_str(), path.size()); | ||||
| 				ox::StringView buff; | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -77,17 +77,17 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				oxExpect(buff, "usr"); | ||||
| 				oxAssert(it.next(buff), "PathIterator::next returned error"); | ||||
| 				oxExpect(buff, "share"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"PathIterator::next3", | ||||
| 			[](ox::StringView) { | ||||
| 				auto const path = ox::String("/"); | ||||
| 				ox::PathIterator it(path.c_str(), path.len()); | ||||
| 				ox::PathIterator it(path.c_str(), path.size()); | ||||
| 				ox::StringView buff; | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -99,38 +99,42 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"PathIterator::next5", | ||||
| 			[](ox::StringView) { | ||||
| 				auto const path = ox::String("usr/share/"); | ||||
| 				ox::PathIterator it(path.c_str(), path.len()); | ||||
| 				ox::PathIterator it(path.c_str(), path.size()); | ||||
| 				ox::StringView buff; | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); | ||||
| 				oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"PathIterator::dirPath", | ||||
| 			[] (ox::StringView) { | ||||
| 				auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); | ||||
| 				ox::PathIterator it(path.c_str(), path.len()); | ||||
| 				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"); | ||||
| 				return OxError(0); | ||||
| 				ox::PathIterator it(path.c_str(), path.size()); | ||||
| 				auto buff = static_cast<char*>(ox_alloca(path.size() + 1)); | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 				oxAssert(it.dirPath(buff, path.size()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"PathIterator::hasNext", | ||||
| 			[](ox::StringView) { | ||||
| 				const auto path = "/file1"; | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 				ox::PathIterator it(path, ox::strlen(path)); | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 				oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext"); | ||||
| 				oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -142,7 +146,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
|  | ||||
| 				auto subPtr = p.subPtr<uint64_t>(50); | ||||
| 				oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid."); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -155,7 +159,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				auto first = list->firstItem(); | ||||
| 				oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item"); | ||||
| 				oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -163,9 +167,11 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 			[](ox::StringView) { | ||||
| 				constexpr auto buffLen = 5000; | ||||
| 				constexpr auto str1 = "Hello, World!"; | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 				constexpr auto str1Len = ox::strlen(str1) + 1; | ||||
| 				constexpr auto str2 = "Hello, Moon!"; | ||||
| 				constexpr auto str2Len = ox::strlen(str2) + 1; | ||||
| 				OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 				auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen); | ||||
| 				oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed."); | ||||
| 				ox::FileStore32 fileStore(list, buffLen); | ||||
| @@ -176,7 +182,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				size_t str1ReadSize = 0; | ||||
| 				oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed."); | ||||
|  | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -203,7 +209,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				oxTrace("ox.fs.test.Directory") << "write 3"; | ||||
| 				oxAssert(dir.write("/file2", 2), "Directory write of file2 failed"); | ||||
|  | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -220,19 +226,20 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = | ||||
| 				oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed"); | ||||
| 				oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed"); | ||||
| 				oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| int main(int argc, const char **args) { | ||||
| int main(int argc, const char **argv) { | ||||
| 	if (argc < 2) { | ||||
| 		oxError("Must specify test to run"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	auto const args = ox::Span{argv, static_cast<size_t>(argc)}; | ||||
| 	ox::StringView const testName = args[1]; | ||||
| 	ox::StringView const testArg = args[2] ? args[2] : nullptr; | ||||
| 	ox::StringView const testArg = argc >= 3 ? args[2] : nullptr; | ||||
| 	auto const func = tests.find(testName); | ||||
| 	if (func != tests.end()) { | ||||
| 		oxAssert(func->second(testArg), "Test returned Error"); | ||||
|   | ||||
							
								
								
									
										47
									
								
								deps/ox/src/ox/fs/tool.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								deps/ox/src/ox/fs/tool.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -20,7 +20,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept { | ||||
| 	std::ifstream file(path, std::ios::binary | std::ios::ate); | ||||
| 	if (!file.good()) { | ||||
| 		oxErrorf("Could not find OxFS file: {}", path); | ||||
| 		return OxError(1, "Could not find OxFS file"); | ||||
| 		return ox::Error(1, "Could not find OxFS file"); | ||||
| 	} | ||||
| 	try { | ||||
| 		const auto size = static_cast<std::size_t>(file.tellg()); | ||||
| @@ -30,51 +30,54 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept { | ||||
| 		return Buff{buff, size}; | ||||
| 	} catch (const std::ios_base::failure &e) { | ||||
| 		oxErrorf("Could not read OxFS file: {}", e.what()); | ||||
| 		return OxError(2, "Could not read OxFS file"); | ||||
| 		return ox::Error(2, "Could not read OxFS file"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept { | ||||
| 	oxRequire(buff, loadFsBuff(path)); | ||||
| 	OX_REQUIRE(buff, loadFsBuff(path)); | ||||
| 	return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; | ||||
| } | ||||
|  | ||||
| static ox::Error runLs(ox::FileSystem *fs, int argc, const char **argv) noexcept { | ||||
| 	if (argc < 2) { | ||||
| static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept { | ||||
| 	if (args.size() < 2) { | ||||
| 		oxErr("Must provide a directory to ls\n"); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	oxRequire(files, fs->ls(argv[1])); | ||||
| 	OX_REQUIRE(files, fs->ls(args[1])); | ||||
| 	for (const auto &file : files) { | ||||
| 		oxOutf("{}\n", file); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexcept { | ||||
| 	if (argc < 2) { | ||||
| static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept { | ||||
| 	if (args.size() < 2) { | ||||
| 		oxErr("Must provide a path to a file to read\n"); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	oxRequire(buff, fs->read(ox::StringView(argv[1]))); | ||||
| 	fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); | ||||
| 	return OxError(0); | ||||
| 	OX_REQUIRE(buff, fs->read(ox::StringView(args[1]))); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 	std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| static ox::Error run(int argc, const char **argv) noexcept { | ||||
| 	if (argc < 3) { | ||||
| 		oxErr("OxFS file and subcommand arguments are required\n"); | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	const auto fsPath = argv[1]; | ||||
| 	ox::String subCmd(argv[2]); | ||||
| 	oxRequire(fs, loadFs(fsPath)); | ||||
| 	auto const args = ox::Span{argv, static_cast<size_t>(argc)}; | ||||
| 	auto const fsPath = args[1]; | ||||
| 	ox::String subCmd(args[2]); | ||||
| 	OX_REQUIRE(fs, loadFs(fsPath)); | ||||
| 	if (subCmd == "ls") { | ||||
| 		return runLs(fs.get(), argc - 2, argv + 2); | ||||
| 		return runLs(fs.get(), args + 2); | ||||
| 	} else if (subCmd == "read") { | ||||
| 		return runRead(fs.get(), argc - 2, argv + 2); | ||||
| 		return runRead(fs.get(), args + 2); | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| int main(int argc, const char **argv) { | ||||
|   | ||||
							
								
								
									
										14
									
								
								deps/ox/src/ox/logconn/circularbuff.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								deps/ox/src/ox/logconn/circularbuff.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -34,7 +34,7 @@ class CirculerBuffer { | ||||
| 		constexpr ox::Error put(char v) noexcept { | ||||
| 			return write(&v, 1); | ||||
| 			if (1 > avail()) { | ||||
| 				return OxError(1, "Insufficient space in buffer"); | ||||
| 				return ox::Error(1, "Insufficient space in buffer"); | ||||
| 			} | ||||
| 			m_buff[m_writePt] = v; | ||||
| 			++m_writePt; | ||||
| @@ -43,8 +43,9 @@ class CirculerBuffer { | ||||
|  | ||||
| 		constexpr ox::Error write(const char *buff, std::size_t sz) noexcept { | ||||
| 			if (sz > avail()) { | ||||
| 				return OxError(1, "Insufficient space in buffer"); | ||||
| 				return ox::Error(1, "Insufficient space in buffer"); | ||||
| 			} | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			// write seg 1 | ||||
| 			const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt); | ||||
| 			ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz); | ||||
| @@ -56,12 +57,13 @@ class CirculerBuffer { | ||||
| 				ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz); | ||||
| 				oxAssert(m_buff[0] == buff[seg1Sz], "break"); | ||||
| 			} | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		constexpr ox::Error seekp(std::size_t bytesFwd) noexcept { | ||||
| 			if (bytesFwd > avail()) { | ||||
| 				return OxError(1, "Insufficient space in buffer to seek that far ahead"); | ||||
| 				return ox::Error(1, "Insufficient space in buffer to seek that far ahead"); | ||||
| 			} | ||||
| 			m_writePt += bytesFwd; | ||||
| 			if (m_writePt > m_buff.size()) { | ||||
| @@ -71,7 +73,7 @@ class CirculerBuffer { | ||||
| 		} | ||||
|  | ||||
| 		constexpr ox::Error seekp(int, ios_base::seekdir) noexcept { | ||||
| 			return OxError(1, "Unimplemented"); | ||||
| 			return ox::Error(1, "Unimplemented"); | ||||
| 		} | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| @@ -90,7 +92,9 @@ class CirculerBuffer { | ||||
| 				m_readPt -= m_buff.size(); | ||||
| 				// read seg 2 | ||||
| 				const auto seg2Sz = bytesRead - seg1Sz; | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 				ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			} | ||||
| 			return bytesRead; | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										4
									
								
								deps/ox/src/ox/logconn/def.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								deps/ox/src/ox/logconn/def.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -14,7 +14,7 @@ | ||||
|     { \ | ||||
| 		const auto loggerErr = (loggerName).initConn(appName); \ | ||||
| 		if (loggerErr) { \ | ||||
| 			oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line); \ | ||||
| 			oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.src.file_name(), loggerErr.src.line()); \ | ||||
| 		} else { \ | ||||
| 			ox::trace::setLogger(&(loggerName)); \ | ||||
| 		} \ | ||||
|   | ||||
							
								
								
									
										57
									
								
								deps/ox/src/ox/logconn/logconn.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								deps/ox/src/ox/logconn/logconn.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -9,8 +9,8 @@ | ||||
| #ifdef OX_USE_STDLIB | ||||
| #include <cstdio> | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #ifndef _WIN32 | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <netinet/in.h> | ||||
| @@ -25,15 +25,22 @@ | ||||
|  | ||||
| #include "logconn.hpp" | ||||
|  | ||||
| #include <ox/std/bit.hpp> | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| using Socket = SOCKET; | ||||
| using LenType = int; | ||||
| #else | ||||
| using Socket = int; | ||||
| using LenType = size_t; | ||||
| #endif | ||||
|  | ||||
| using namespace trace; | ||||
|  | ||||
| void closeSock(auto s) noexcept { | ||||
| static void closeSock(auto s) noexcept { | ||||
| #ifdef _WIN32 | ||||
| 	closesocket(s); | ||||
| 	closesocket(static_cast<Socket>(s)); | ||||
| #else | ||||
| 	close(s); | ||||
| #endif | ||||
| @@ -56,8 +63,8 @@ ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept { | ||||
| 	addr.sin_family = AF_INET; | ||||
| 	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | ||||
| 	addr.sin_port = htons(5590); | ||||
| 	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||||
| 	oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); | ||||
| 	m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); | ||||
| 	OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(connect(static_cast<Socket>(m_socket), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); | ||||
| 	return sendInit({.appName = ox::BasicString<128>(appName)}); | ||||
| } | ||||
|  | ||||
| @@ -65,10 +72,10 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept { | ||||
| 	std::size_t totalSent = 0; | ||||
| 	while (totalSent < len) { | ||||
| 		//std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket); | ||||
| 		const auto sent = ::send(m_socket, buff, len, 0); | ||||
| 		const auto sent = ::send(static_cast<Socket>(m_socket), buff, static_cast<LenType>(len), 0); | ||||
| 		if (sent < 0) { | ||||
| 			std::fprintf(stderr, "Could not send msg\n"); | ||||
| 			return OxError(1, "Could not send msg"); | ||||
| 			std::ignore = std::fprintf(stderr, "Could not send msg\n"); | ||||
| 			return ox::Error(1, "Could not send msg"); | ||||
| 		} | ||||
| 		totalSent += static_cast<std::size_t>(sent); | ||||
| 	} | ||||
| @@ -84,22 +91,28 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept { | ||||
| } | ||||
|  | ||||
| void LoggerConn::msgSend() noexcept { | ||||
| 	while (true) { | ||||
| 		std::unique_lock lk(m_waitMut); | ||||
| 		m_waitCond.wait(lk); | ||||
| 		if (!m_running) { | ||||
| 			break; | ||||
| 		} | ||||
| 		std::lock_guard buffLk(m_buffMut); | ||||
| 	try { | ||||
| 		while (true) { | ||||
| 			ox::Array<char, ox::units::KB> tmp; | ||||
| 			const auto read = m_buff.read(tmp.data(), tmp.size()); | ||||
| 			if (!read) { | ||||
| 			std::unique_lock lk(m_waitMut); | ||||
| 			m_waitCond.wait(lk); | ||||
| 			if (!m_running) { | ||||
| 				break; | ||||
| 			} | ||||
| 			//std::printf("LoggerConn: sending %lu bytes\n", read); | ||||
| 			std::ignore = send(tmp.data(), read); | ||||
| 			std::lock_guard const buffLk(m_buffMut); | ||||
| 			while (true) { | ||||
| 				Array<char, units::KB> tmp; | ||||
| 				const auto read = m_buff.read(tmp.data(), tmp.size()); | ||||
| 				if (!read) { | ||||
| 					break; | ||||
| 				} | ||||
| 				oxAssert(read <= tmp.size(), "logger trying to read too much data"); | ||||
| 				//std::printf("LoggerConn: sending %lu bytes\n", read); | ||||
| 				std::ignore = send(tmp.data(), read); | ||||
| 			} | ||||
| 		} | ||||
| 	} catch (std::exception const &e) { | ||||
| 		oxErrf("Exception in logger thread: {}\n", e.what()); | ||||
| 		oxAssert(false, "logger thread exception"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										12
									
								
								deps/ox/src/ox/logconn/logconn.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								deps/ox/src/ox/logconn/logconn.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -45,13 +45,13 @@ class LoggerConn: public trace::Logger { | ||||
| 		ox::Error send(trace::MsgId msgId, const auto &msg) noexcept { | ||||
| 			ox::Array<char, 10 * ox::units::KB> buff; | ||||
| 			std::size_t sz = 0; | ||||
| 			oxReturnError(ox::writeMC(&buff[0], buff.size(), msg, &sz)); | ||||
| 			OX_RETURN_ERROR(ox::writeMC(&buff[0], buff.size(), msg, &sz)); | ||||
| 			//std::printf("sz: %lu\n", sz); | ||||
| 			oxRequire(szBuff, serialize(static_cast<uint32_t>(sz))); | ||||
| 			OX_REQUIRE(szBuff, serialize(static_cast<uint32_t>(sz))); | ||||
| 			std::unique_lock buffLk(m_buffMut); | ||||
| 			oxReturnError(m_buff.put(static_cast<char>(msgId))); | ||||
| 			oxReturnError(m_buff.write(szBuff.data(), szBuff.size())); | ||||
| 			oxReturnError(m_buff.write(buff.data(), sz)); | ||||
| 			OX_RETURN_ERROR(m_buff.put(static_cast<char>(msgId))); | ||||
| 			OX_RETURN_ERROR(m_buff.write(szBuff.data(), szBuff.size())); | ||||
| 			OX_RETURN_ERROR(m_buff.write(buff.data(), sz)); | ||||
| 			buffLk.unlock(); | ||||
| 			m_waitCond.notify_one(); | ||||
| 			return {}; | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/err.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/err.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										82
									
								
								deps/ox/src/ox/mc/intops.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								deps/ox/src/ox/mc/intops.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -57,7 +57,7 @@ static_assert(highestBit(uint64_t(1) << 31) == 31); | ||||
| static_assert(highestBit(uint64_t(1) << 63) == 63); | ||||
|  | ||||
| struct McInt { | ||||
| 	uint8_t data[9] = {}; | ||||
| 	ox::Array<uint8_t, 9> data{}; | ||||
| 	// length of integer in bytes | ||||
| 	std::size_t length = 0; | ||||
| }; | ||||
| @@ -71,7 +71,9 @@ constexpr McInt encodeInteger(I pInput) noexcept { | ||||
| 	// move input to uint64_t to allow consistent bit manipulation, and to avoid | ||||
| 	// overflow concerns | ||||
| 	uint64_t val = 0; | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 	ox::memcpy(&val, &input, sizeof(input)); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	if (val) { | ||||
| 		// bits needed to represent number factoring in space possibly | ||||
| 		// needed for signed bit | ||||
| @@ -94,7 +96,9 @@ constexpr McInt encodeInteger(I pInput) noexcept { | ||||
| 		} | ||||
| 		if (bytes == 9) { | ||||
| 			out.data[0] = bytesIndicator; | ||||
| 			OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			ox::memcpy(&out.data[1], &leVal, 8); | ||||
| 			OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			if (inputNegative) { | ||||
| 				out.data[1] |= 0b1000'0000; | ||||
| 			} | ||||
| @@ -104,7 +108,9 @@ constexpr McInt encodeInteger(I pInput) noexcept { | ||||
| 			auto intermediate = | ||||
| 				static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | | ||||
| 				static_cast<uint64_t>(bytesIndicator); | ||||
| 			ox::memcpy(out.data, &intermediate, sizeof(intermediate)); | ||||
| 			OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate)); | ||||
| 			OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 		} | ||||
| 		out.length = bytes; | ||||
| 	} | ||||
| @@ -135,49 +141,53 @@ static_assert(countBytes(0b1111'1111) == 9); | ||||
| template<typename I> | ||||
| constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept { | ||||
| 	uint8_t firstByte = 0; | ||||
| 	oxReturnError(rdr.read(&firstByte, 1)); | ||||
| 	oxReturnError(rdr.seekg(-1, ox::ios_base::cur)); | ||||
| 	OX_RETURN_ERROR(rdr.read(&firstByte, 1)); | ||||
| 	OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur)); | ||||
| 	const auto bytes = countBytes(firstByte); | ||||
| 	if (bytes == 9) { | ||||
| 		*bytesRead = bytes; | ||||
| 		I out = 0; | ||||
| 		oxReturnError(rdr.seekg(1, ox::ios_base::cur)); | ||||
| 		oxReturnError(rdr.read(&out, sizeof(I))); | ||||
| 		OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur)); | ||||
| 		OX_RETURN_ERROR(rdr.read(&out, sizeof(I))); | ||||
| 		return fromLittleEndian<I>(out); | ||||
| 	} | ||||
| 	*bytesRead = bytes; | ||||
| 	uint64_t decoded = 0; | ||||
| 	oxReturnError(rdr.read(&decoded, bytes)); | ||||
| 	OX_RETURN_ERROR(rdr.read(&decoded, bytes)); | ||||
| 	decoded >>= bytes; | ||||
| 	// move sign bit | ||||
| 	if constexpr(is_signed_v<I>) { | ||||
| 		 const auto negBit = bytes * 8 - bytes - 1; | ||||
| 		 // move sign | ||||
| 		 const auto negative = (decoded >> negBit) == 1; | ||||
| 		 if (negative) { | ||||
| 			 // 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 | ||||
| 			 ox::Array<uint32_t, 2> d = {}; | ||||
| 			 //d[0] = decoded & 0xffff'ffff; | ||||
| 			 //d[1] = decoded >> 32; | ||||
| 			 ox::memcpy(d.data(), &decoded, sizeof(decoded)); | ||||
| 			 auto bit = negBit; | ||||
| 			 for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { | ||||
| 				 d[0] |= 1 << bit; | ||||
| 			 } | ||||
| 			 bit -= 32; | ||||
| 			 for (; bit < Bits<I>; ++bit) { | ||||
| 				 d[1] |= 1 << bit; | ||||
| 			 } | ||||
| 			 I out = 0; | ||||
| 			 if constexpr(ox::defines::BigEndian) { | ||||
| 				 const auto d0Tmp = d[0]; | ||||
| 				 d[0] = d[1]; | ||||
| 				 d[1] = d0Tmp; | ||||
| 			 } | ||||
| 			 ox::memcpy(&out, d.data(), sizeof(out)); | ||||
| 			 return out; | ||||
| 		 } | ||||
| 		const auto negBit = bytes * 8 - bytes - 1; | ||||
| 		// move sign | ||||
| 		const auto negative = (decoded >> negBit) == 1; | ||||
| 		if (negative) { | ||||
| 			// 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 | ||||
| 			ox::Array<uint32_t, 2> d = {}; | ||||
| 			//d[0] = decoded & 0xffff'ffff; | ||||
| 			//d[1] = decoded >> 32; | ||||
| 		 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			ox::memcpy(&d[0], &decoded, sizeof(decoded)); | ||||
| 		 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			auto bit = negBit; | ||||
| 			for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { | ||||
| 				d[0] |= 1 << bit; | ||||
| 			} | ||||
| 			bit -= 32; | ||||
| 			for (; bit < Bits<I>; ++bit) { | ||||
| 				d[1] |= 1 << bit; | ||||
| 			} | ||||
| 			I out = 0; | ||||
| 			if constexpr(ox::defines::BigEndian) { | ||||
| 				const auto d0Tmp = d[0]; | ||||
| 				d[0] = d[1]; | ||||
| 				d[1] = d0Tmp; | ||||
| 			} | ||||
| 		 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			ox::memcpy(&out, &d[0], sizeof(out)); | ||||
| 			OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			return out; | ||||
| 		} | ||||
| 	} | ||||
| 	return static_cast<I>(decoded); | ||||
| } | ||||
| @@ -185,7 +195,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe | ||||
| template<typename I> | ||||
| Result<I> decodeInteger(McInt m) noexcept { | ||||
| 	std::size_t bytesRead{}; | ||||
| 	BufferReader br({reinterpret_cast<const char*>(m.data), 9}); | ||||
| 	BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9}); | ||||
| 	return decodeInteger<I>(br, &bytesRead); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/mc.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/mc.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/presenceindicator.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/presenceindicator.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										18
									
								
								deps/ox/src/ox/mc/presenceindicator.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								deps/ox/src/ox/mc/presenceindicator.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -47,7 +47,7 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe | ||||
| 	constexpr auto blockBits = sizeof(m_mapBlock); | ||||
| 	auto const blockIdx = idx / blockBits; | ||||
| 	if (m_mapBlockIdx != blockIdx) [[unlikely]] { | ||||
| 		oxReturnError(loadMapBlock(blockIdx)); | ||||
| 		OX_RETURN_ERROR(loadMapBlock(blockIdx)); | ||||
| 	} | ||||
| 	idx %= blockBits; | ||||
| 	return (m_mapBlock >> idx) & 1; | ||||
| @@ -55,12 +55,12 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| 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_REQUIRE(g, m_reader.tellg()); | ||||
| 	OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg)); | ||||
| 	ox::Array<char, sizeof(m_mapBlock)> mapBlock{}; | ||||
| 	oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); | ||||
| 	OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); | ||||
| 	// Warning: narrow-conv | ||||
| 	oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); | ||||
| 	OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); | ||||
| 	m_mapBlock = 0; | ||||
| 	for (auto i = 0ull; auto b : mapBlock) { | ||||
| 		m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i; | ||||
| @@ -110,7 +110,7 @@ constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexce | ||||
| 	if (i / 8 < m_mapLen) { | ||||
| 		return (m_map[i / 8] >> (i % 8)) & 1; | ||||
| 	} else { | ||||
| 		return OxError(McPresenceMapOverflow); | ||||
| 		return ox::Error(McPresenceMapOverflow); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -147,14 +147,16 @@ constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept: | ||||
|  | ||||
| constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept { | ||||
| 	if (i / 8 < m_mapLen) { | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 		if (on) { | ||||
| 			m_map[i / 8] |= 1 << (i % 8); | ||||
| 		} else { | ||||
| 			m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8)); | ||||
| 		} | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 		return {}; | ||||
| 	} else { | ||||
| 		return OxError(McPresenceMapOverflow); | ||||
| 		return ox::Error(McPresenceMapOverflow); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/read.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/read.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										108
									
								
								deps/ox/src/ox/mc/read.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										108
									
								
								deps/ox/src/ox/mc/read.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -194,10 +194,10 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n | ||||
| 	if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { | ||||
| 		auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field)); | ||||
| 		*val = result.value; | ||||
| 		oxReturnError(result); | ||||
| 		OX_RETURN_ERROR(result); | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| // array handler | ||||
| @@ -207,18 +207,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *v | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			// read the length | ||||
| 			std::size_t bytesRead = 0; | ||||
| 			oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			// read the list | ||||
| 			if (valLen >= len) { | ||||
| 				auto reader = child({}); | ||||
| 				auto &handler = *reader.interface(); | ||||
| 				oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 				OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 				for (std::size_t i = 0; i < len; ++i) { | ||||
| 					oxReturnError(handler.field({}, &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 					OX_RETURN_ERROR(handler.field({}, &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 				} | ||||
| 			} else { | ||||
| 				oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen); | ||||
| 				return OxError(McOutputBuffEnded); | ||||
| 				return ox::Error(McOutputBuffEnded); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -232,29 +234,29 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri | ||||
| 	if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			// read the length | ||||
| 			oxRequire(g, m_reader.tellg()); | ||||
| 			OX_REQUIRE(g, m_reader.tellg()); | ||||
| 			std::size_t bytesRead = 0; | ||||
| 			oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			oxReturnError(m_reader.seekg(g)); | ||||
| 			OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			OX_RETURN_ERROR(m_reader.seekg(g)); | ||||
| 			// read the list | ||||
| 			auto reader = child(""); | ||||
| 			auto &handler = *reader.interface(); | ||||
| 			oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 			OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 			// this loop body needs to be in a lambda because of the potential alloca call | ||||
| 			constexpr auto loopBody = [](auto &handler, auto &val) { | ||||
| 				oxRequire(keyLen, handler.stringLength(nullptr)); | ||||
| 				OX_REQUIRE(keyLen, handler.stringLength(nullptr)); | ||||
| 				auto wkey = ox_malloca(keyLen + 1, char, 0); | ||||
| 				auto wkeyPtr = wkey.get(); | ||||
| 				oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1)); | ||||
| 				OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1)); | ||||
| 				return handler.field("", &val[wkeyPtr]); | ||||
| 			}; | ||||
| 			for (std::size_t i = 0; i < len; ++i) { | ||||
| 				oxReturnError(loopBody(handler, *val)); | ||||
| 				OX_RETURN_ERROR(loopBody(handler, *val)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -264,11 +266,11 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) | ||||
| 		if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { | ||||
| 			// 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))) { | ||||
| 				oxRequire(len, arrayLength(name, false)); | ||||
| 				oxReturnError(ox::resizeVector(*val, len)); | ||||
| 				OX_REQUIRE(len, arrayLength(name, false)); | ||||
| 				OX_RETURN_ERROR(ox::resizeVector(*val, len)); | ||||
| 				return field(name, val->data(), val->size()); | ||||
| 			} | ||||
| 			oxReturnError(ox::resizeVector(*val, 0)); | ||||
| 			OX_RETURN_ERROR(ox::resizeVector(*val, 0)); | ||||
| 		} | ||||
| 		++m_field; | ||||
| 		return {}; | ||||
| @@ -276,9 +278,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) | ||||
| 		if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { | ||||
| 			// 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))) { | ||||
| 				oxRequire(len, arrayLength(name, false)); | ||||
| 				OX_REQUIRE(len, arrayLength(name, false)); | ||||
| 				if (len > val->size()) { | ||||
| 					return OxError(1, "Input array is too long"); | ||||
| 					return ox::Error(1, "Input array is too long"); | ||||
| 				} | ||||
| 			} | ||||
| 			return field(name, val->data(), val->size()); | ||||
| @@ -289,7 +291,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) | ||||
| 		if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) { | ||||
| 			if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 				auto reader = child(""); | ||||
| 				oxReturnError(model(reader.interface(), val)); | ||||
| 				OX_RETURN_ERROR(model(reader.interface(), val)); | ||||
| 			} | ||||
| 		} | ||||
| 		++m_field; | ||||
| @@ -303,7 +305,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, | ||||
| 	if ((!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) { | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			auto reader = child("", ox::Optional<int>(ox::in_place, val.idx())); | ||||
| 			oxReturnError(model(reader.interface(), val.get())); | ||||
| 			OX_RETURN_ERROR(model(reader.interface(), val.get())); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| @@ -317,18 +319,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString< | ||||
| 		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)); | ||||
| 			OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); | ||||
| 			const auto cap = size; | ||||
| 			*val = BasicString<SmallStringSize>(cap); | ||||
| 			auto data = val->data(); | ||||
| 			// read the string | ||||
| 			oxReturnError(m_reader.read(data, size)); | ||||
| 			OX_RETURN_ERROR(m_reader.read(data, size)); | ||||
| 		} else { | ||||
| 			*val = ""; | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -338,12 +340,12 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> * | ||||
| 		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)); | ||||
| 			OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); | ||||
| 			*val = IString<L>(); | ||||
| 			oxReturnError(val->resize(size)); | ||||
| 			OX_RETURN_ERROR(val->resize(size)); | ||||
| 			auto const data = val->data(); | ||||
| 			// read the string | ||||
| 			oxReturnError(m_reader.read(data, size)); | ||||
| 			OX_RETURN_ERROR(m_reader.read(data, size)); | ||||
| 		} else { | ||||
| 			*val = ""; | ||||
| 		} | ||||
| @@ -357,18 +359,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char | ||||
| 	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)); | ||||
| 		OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); | ||||
| 		if (size > buffLen) { | ||||
| 			return OxError(McOutputBuffEnded); | ||||
| 			return ox::Error(McOutputBuffEnded); | ||||
| 		} | ||||
| 		// re-allocate in case too small | ||||
| 		auto data = val; | ||||
| 		// read the string | ||||
| 		oxReturnError(m_reader.read(data, size)); | ||||
| 		OX_RETURN_ERROR(m_reader.read(data, size)); | ||||
| 		data[size] = 0; | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -376,17 +378,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char | ||||
| 	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)); | ||||
| 		OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); | ||||
| 		// re-allocate in case too small | ||||
| 		safeDelete(*val); | ||||
| 		*val = new char[size + 1]; | ||||
| 		auto data = *val; | ||||
| 		auto data = ox::Span{*val, size + 1}; | ||||
| 		// read the string | ||||
| 		oxReturnError(m_reader.read(data, size)); | ||||
| 		OX_RETURN_ERROR(m_reader.read(data.data(), size)); | ||||
| 		data[size] = 0; | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -395,16 +397,16 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char | ||||
| 		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)); | ||||
| 			OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); | ||||
| 			// re-allocate if too small | ||||
| 			if (buffLen < size + 1) { | ||||
| 				safeDelete(*val); | ||||
| 				*val = new char[size + 1]; | ||||
| 				buffLen = size + 1; | ||||
| 			} | ||||
| 			auto data = *val; | ||||
| 			auto data = ox::Span{*val, size + 1}; | ||||
| 			// read the string | ||||
| 			oxReturnError(m_reader.read(data, size)); | ||||
| 			OX_RETURN_ERROR(m_reader.read(data.data(), size)); | ||||
| 			data[size] = 0; | ||||
| 		} else { | ||||
| 			auto data = *val; | ||||
| @@ -414,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -423,15 +425,15 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			// read the length | ||||
| 			std::size_t bytesRead = 0; | ||||
| 			oxRequire(g, m_reader.tellg()); | ||||
| 			oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			OX_REQUIRE(g, m_reader.tellg()); | ||||
| 			OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			if (!pass) { | ||||
| 				oxReturnError(m_reader.seekg(g)); | ||||
| 				OX_RETURN_ERROR(m_reader.seekg(g)); | ||||
| 			} | ||||
| 			return out; | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -441,7 +443,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con | ||||
| 			// 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)); | ||||
| 			OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur)); | ||||
| 			return len; | ||||
| 		} | ||||
| 	} | ||||
| @@ -455,14 +457,14 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept { | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			std::size_t bytesRead = 0; | ||||
| 			auto const result = mc::decodeInteger<I>(m_reader, &bytesRead); | ||||
| 			oxReturnError(result); | ||||
| 			OX_RETURN_ERROR(result); | ||||
| 			*val = result.value; | ||||
| 		} else { | ||||
| 			*val = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -472,20 +474,20 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc | ||||
| 		if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { | ||||
| 			// read the length | ||||
| 			std::size_t bytesRead = 0; | ||||
| 			oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); | ||||
| 			// read the list | ||||
| 			auto reader = child(""); | ||||
| 			auto &handler = *reader.interface(); | ||||
| 			oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 			OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 			for (std::size_t i = 0; i < len; ++i) { | ||||
| 				T val; | ||||
| 				oxReturnError(handler.field("", &val)); | ||||
| 				oxReturnError(cb(i, &val)); | ||||
| 				OX_RETURN_ERROR(handler.field("", &val)); | ||||
| 				OX_RETURN_ERROR(cb(i, &val)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Reader_c Reader> | ||||
| @@ -546,7 +548,7 @@ Error readMC(ox::BufferView buff, T &val) noexcept { | ||||
| template<typename T> | ||||
| Result<T> readMC(ox::BufferView buff) noexcept { | ||||
| 	Result<T> val; | ||||
| 	oxReturnError(readMC(buff, val.value)); | ||||
| 	OX_RETURN_ERROR(readMC(buff, val.value)); | ||||
| 	return val; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										113
									
								
								deps/ox/src/ox/mc/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								deps/ox/src/ox/mc/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -62,47 +62,47 @@ struct TestStruct { | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<TestUnion>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->fieldCString("CString", &obj->CString)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->fieldCString("CString", &obj->CString)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| oxModelBegin(TestStructNest) | ||||
| 	oxModelField(Bool) | ||||
| 	oxModelField(Int) | ||||
| 	oxModelField(IString) | ||||
| oxModelEnd() | ||||
| OX_MODEL_BEGIN(TestStructNest) | ||||
| 	OX_MODEL_FIELD(Bool) | ||||
| 	OX_MODEL_FIELD(Int) | ||||
| 	OX_MODEL_FIELD(IString) | ||||
| OX_MODEL_END() | ||||
|  | ||||
| template<typename T> | ||||
| constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<TestStruct>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->field("Int1", &obj->Int1)); | ||||
| 	oxReturnError(io->field("Int2", &obj->Int2)); | ||||
| 	oxReturnError(io->field("Int3", &obj->Int3)); | ||||
| 	oxReturnError(io->field("Int4", &obj->Int4)); | ||||
| 	oxReturnError(io->field("Int5", &obj->Int5)); | ||||
| 	oxReturnError(io->field("Int6", &obj->Int6)); | ||||
| 	oxReturnError(io->field("Int7", &obj->Int7)); | ||||
| 	oxReturnError(io->field("Int8", &obj->Int8)); | ||||
| 	oxReturnError(io->field("unionIdx", &obj->unionIdx)); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->field("Int1", &obj->Int1)); | ||||
| 	OX_RETURN_ERROR(io->field("Int2", &obj->Int2)); | ||||
| 	OX_RETURN_ERROR(io->field("Int3", &obj->Int3)); | ||||
| 	OX_RETURN_ERROR(io->field("Int4", &obj->Int4)); | ||||
| 	OX_RETURN_ERROR(io->field("Int5", &obj->Int5)); | ||||
| 	OX_RETURN_ERROR(io->field("Int6", &obj->Int6)); | ||||
| 	OX_RETURN_ERROR(io->field("Int7", &obj->Int7)); | ||||
| 	OX_RETURN_ERROR(io->field("Int8", &obj->Int8)); | ||||
| 	OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx)); | ||||
| 	if constexpr(T::opType() == ox::OpType::Reflect) { | ||||
| 		oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); | ||||
| 		OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0})); | ||||
| 	} else { | ||||
| 		oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); | ||||
| 		OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); | ||||
| 	} | ||||
| 	oxReturnError(io->field("String", &obj->String)); | ||||
| 	oxReturnError(io->field("IString", &obj->IString)); | ||||
| 	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("Struct", &obj->Struct)); | ||||
| 	oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("String", &obj->String)); | ||||
| 	OX_RETURN_ERROR(io->field("IString", &obj->IString)); | ||||
| 	OX_RETURN_ERROR(io->field("List", obj->List, 4)); | ||||
| 	OX_RETURN_ERROR(io->field("Vector", &obj->Vector)); | ||||
| 	OX_RETURN_ERROR(io->field("Vector2", &obj->Vector2)); | ||||
| 	OX_RETURN_ERROR(io->field("Map", &obj->Map)); | ||||
| 	OX_RETURN_ERROR(io->field("Struct", &obj->Struct)); | ||||
| 	OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| @@ -114,9 +114,9 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				// doesn't segfault | ||||
| 				ox::Array<char, 1024> buff; | ||||
| 				TestStruct ts; | ||||
| 				oxReturnError(ox::writeMC(buff.data(), buff.size(), ts)); | ||||
| 				oxReturnError(ox::writeMC(ts)); | ||||
| 				return OxError(0); | ||||
| 				OX_RETURN_ERROR(ox::writeMC(buff.data(), buff.size(), ts)); | ||||
| 				OX_RETURN_ERROR(ox::writeMC(ts)); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -157,7 +157,6 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(testIn.Int8                == testOut.Int8,                "Int8 value mismatch"); | ||||
| 				oxAssert(testIn.Union.Int           == testOut.Union.Int,           "Union.Int value mismatch"); | ||||
| 				oxAssert(testIn.String              == testOut.String,              "String 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[1]             == testOut.List[1],             "List[1] value mismatch"); | ||||
| @@ -176,7 +175,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(testIn.Struct.Int          == testOut.Struct.Int,          "Struct.Int value mismatch"); | ||||
| 				oxAssert(testIn.Struct.IString      == testOut.Struct.IString,      "Struct.IString value mismatch"); | ||||
| 				oxAssert(testIn.Struct.Bool         == testOut.Struct.Bool,         "Struct.Bool value mismatch"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -189,28 +188,28 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) { | ||||
| 					if (val.length != expected.size()) { | ||||
| 						std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n'; | ||||
| 						return OxError(1); | ||||
| 						return ox::Error(1); | ||||
| 					} | ||||
| 					for (std::size_t i = 0; i < expected.size(); i++) { | ||||
| 						if (expected[i] != val.data[i]) { | ||||
| 							std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n'; | ||||
| 							std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n'; | ||||
| 							return OxError(1); | ||||
| 							return ox::Error(1); | ||||
| 						} | ||||
| 					} | ||||
| 					return OxError(0); | ||||
| 					return ox::Error(0); | ||||
| 				}; | ||||
| 				constexpr auto check64 = [](McInt val, auto expected) { | ||||
| 					if (val.length != 9) { | ||||
| 						std::cout << "val.length: " << val.length << '\n'; | ||||
| 						return OxError(1); | ||||
| 						return ox::Error(1); | ||||
| 					} | ||||
| 					ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]); | ||||
| 					if (expected != decoded) { | ||||
| 						std::cout << "decoded: " << decoded << ", expected: " << expected << '\n'; | ||||
| 						return OxError(1); | ||||
| 						return ox::Error(1); | ||||
| 					} | ||||
| 					return OxError(0); | ||||
| 					return ox::Error(0); | ||||
| 				}; | ||||
| 				// signed positive | ||||
| 				oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail"); | ||||
| @@ -247,7 +246,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				// code deduplication | ||||
| 				oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail"); | ||||
| 				oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -260,12 +259,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				using ox::mc::decodeInteger; | ||||
| 				static constexpr auto check = [](auto val) { | ||||
| 					auto result = decodeInteger<decltype(val)>(encodeInteger(val)); | ||||
| 					oxReturnError(result.error); | ||||
| 					OX_RETURN_ERROR(result.error); | ||||
| 					if (result.value != val) { | ||||
| 						std::cout << "Bad value: " << result.value << ", expected: " << val << '\n'; | ||||
| 						return OxError(1); | ||||
| 						return ox::Error(1); | ||||
| 					} | ||||
| 					return OxError(0); | ||||
| 					return ox::Error(0); | ||||
| 				}; | ||||
| 				oxAssert(check(uint32_t(14)), "Decode of 14 failed."); | ||||
| 				oxAssert(check(int8_t(-1)), "Decode of -1 failed."); | ||||
| @@ -291,7 +290,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(check(0xffffffff), "Decode of 0xffffffff failed."); | ||||
| 				oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed."); | ||||
| 				oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed."); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -316,10 +315,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				testIn.Union.Int = 93; | ||||
| 				oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), testIn), "Data generation failed"); | ||||
| 				ox::TypeStore typeStore; | ||||
| 				const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn); | ||||
| 				const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); | ||||
| 				oxAssert(typeErr, "Descriptor write failed"); | ||||
| 				ox::ModelObject testOut; | ||||
| 				oxReturnError(testOut.setType(type)); | ||||
| 				OX_RETURN_ERROR(testOut.setType(type)); | ||||
| 				oxAssert(ox::readMC(dataBuff, testOut), "Data read failed"); | ||||
| 				oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); | ||||
| 				oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); | ||||
| @@ -344,7 +343,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed"); | ||||
| 				oxAssert(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"); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -368,10 +367,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				 testIn.Struct.IString = "Test String 2"; | ||||
| 				 oxAssert(ox::writeMC(dataBuff, dataBuffLen, testIn), "Data generation failed"); | ||||
| 				 ox::TypeStore typeStore; | ||||
| 				 const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn); | ||||
| 				 const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); | ||||
| 				 oxAssert(typeErr, "Descriptor write failed"); | ||||
| 				 ox::BufferReader br({dataBuff, dataBuffLen}); | ||||
| 				 oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br, | ||||
| 				 OX_RETURN_ERROR(ox::walkModel<ox::MetalClawReader>(type, br, | ||||
| 					[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { | ||||
| 						//std::cout << f.fieldName.c_str() << '\n'; | ||||
| 						auto fieldName = f.fieldName.c_str(); | ||||
| @@ -454,10 +453,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 							case ox::PrimitiveType::Union: | ||||
| 								break; | ||||
| 						} | ||||
| 						return OxError(0); | ||||
| 						return ox::Error(0); | ||||
| 					} | ||||
| 				)); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/types.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/types.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/mc/write.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/mc/write.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										109
									
								
								deps/ox/src/ox/mc/write.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								deps/ox/src/ox/mc/write.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -117,12 +117,12 @@ class MetalClawWriter { | ||||
| 			bool fieldSet = false; | ||||
| 			if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 				auto mi = mc::encodeInteger(val); | ||||
| 				oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length)); | ||||
| 				OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length)); | ||||
| 				fieldSet = true; | ||||
| 			} | ||||
| 			oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 			OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 			++m_field; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| }; | ||||
| @@ -181,50 +181,55 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) | ||||
| template<Writer_c Writer> | ||||
| constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { | ||||
| 	if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { | ||||
| 		oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); | ||||
| 		OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); | ||||
| 	} | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| template<std::size_t SmallStringSize> | ||||
| constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept { | ||||
| 	bool fieldSet = false; | ||||
| 	if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 	if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 		// write the length | ||||
| 		const auto strLen = mc::encodeInteger(val->len()); | ||||
| 		oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length)); | ||||
| 		const auto strLen = mc::encodeInteger(val->size()); | ||||
| 		OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length)); | ||||
| 		// write the string | ||||
| 		oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len()))); | ||||
| 		OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->size()))); | ||||
| 		fieldSet = true; | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| template<std::size_t L> | ||||
| constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept { | ||||
| 	return fieldCString(name, val->data(), val->len()); | ||||
| 	return fieldCString(name, val->data(), val->size()); | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept { | ||||
| 	bool fieldSet = false; | ||||
| 	if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { | ||||
| 		OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 		// this strlen is tolerated because sometimes 0 gets passed to | ||||
| 		// the size param, which is a lie | ||||
| 		// this code should be cleaned up at some point... | ||||
| 		const auto strLen = *val ? ox::strlen(*val) : 0; | ||||
| 		OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 		// write the length | ||||
| 		const auto strLenBuff = mc::encodeInteger(strLen); | ||||
| 		oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); | ||||
| 		OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); | ||||
| 		// write the string | ||||
| 		oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen))); | ||||
| 		OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen))); | ||||
| 		fieldSet = true; | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| @@ -243,14 +248,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v | ||||
| 	if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 		// write the length | ||||
| 		const auto strLenBuff = mc::encodeInteger(strLen); | ||||
| 		oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); | ||||
| 		OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); | ||||
| 		// write the string | ||||
| 		oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen))); | ||||
| 		OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen))); | ||||
| 		fieldSet = true; | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| @@ -264,11 +269,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce | ||||
| 			auto const writeIdx = m_writer.tellp(); | ||||
| 			MetalClawWriter<Writer> writer(m_writer); | ||||
| 			ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer}; | ||||
| 			oxReturnError(model(&handler, val)); | ||||
| 			oxReturnError(writer.finalize()); | ||||
| 			OX_RETURN_ERROR(model(&handler, val)); | ||||
| 			OX_RETURN_ERROR(writer.finalize()); | ||||
| 			fieldSet = writeIdx != m_writer.tellp(); | ||||
| 		} | ||||
| 		oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 		OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 		++m_field; | ||||
| 		return {}; | ||||
| 	} | ||||
| @@ -282,11 +287,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> | ||||
| 		auto const writeIdx = m_writer.tellp(); | ||||
| 		MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); | ||||
| 		ModelHandlerInterface handler{&writer}; | ||||
| 		oxReturnError(model(&handler, val.get())); | ||||
| 		oxReturnError(writer.finalize()); | ||||
| 		OX_RETURN_ERROR(model(&handler, val.get())); | ||||
| 		OX_RETURN_ERROR(writer.finalize()); | ||||
| 		fieldSet = writeIdx != m_writer.tellp(); | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return {}; | ||||
| } | ||||
| @@ -298,21 +303,23 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::s | ||||
| 	if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 		// write the length | ||||
| 		const auto arrLen = mc::encodeInteger(len); | ||||
| 		oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); | ||||
| 		OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); | ||||
| 		auto const writeIdx = m_writer.tellp(); | ||||
| 		MetalClawWriter<Writer> writer(m_writer); | ||||
| 		ModelHandlerInterface handler{&writer}; | ||||
| 		oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 		OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); | ||||
| 		// write the array | ||||
| 		for (std::size_t i = 0; i < len; ++i) { | ||||
| 			oxReturnError(handler.field("", &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			OX_RETURN_ERROR(handler.field("", &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 		} | ||||
| 		oxReturnError(writer.finalize()); | ||||
| 		OX_RETURN_ERROR(writer.finalize()); | ||||
| 		fieldSet = writeIdx != m_writer.tellp(); | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| @@ -324,32 +331,32 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String | ||||
| 	if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { | ||||
| 		// write the length | ||||
| 		const auto arrLen = mc::encodeInteger(len); | ||||
| 		oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); | ||||
| 		OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); | ||||
| 		// write map | ||||
| 		MetalClawWriter<Writer> writer(m_writer); | ||||
| 		ModelHandlerInterface handler{&writer}; | ||||
| 		// double len for both key and value | ||||
| 		oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2)); | ||||
| 		OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2)); | ||||
| 		// this loop body needs to be in a lambda because of the potential alloca call | ||||
| 		constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error { | ||||
| 			const auto keyLen = key.len(); | ||||
| 			const auto keyLen = key.size(); | ||||
| 			auto wkey = ox_malloca(keyLen + 1, char, 0); | ||||
| 			memcpy(wkey.get(), key.c_str(), keyLen + 1); | ||||
| 			oxReturnError(handler.fieldCString("", wkey.get(), keyLen)); | ||||
| 			oxRequireM(value, val.at(key)); | ||||
| 			OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen)); | ||||
| 			OX_REQUIRE_M(value, val.at(key)); | ||||
| 			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)); | ||||
| 			OX_RETURN_ERROR(loopBody(handler, key, *val)); | ||||
| 		} | ||||
| 		oxReturnError(writer.finalize()); | ||||
| 		OX_RETURN_ERROR(writer.finalize()); | ||||
| 		fieldSet = true; | ||||
| 	} | ||||
| 	oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); | ||||
| 	++m_field; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<Writer_c Writer> | ||||
| @@ -360,7 +367,7 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo( | ||||
| 		const Vector<String>&, | ||||
| 		std::size_t fields) noexcept { | ||||
| 	const auto fieldPresenceLen = (fields - 1) / 8 + 1; | ||||
| 	oxReturnError(m_writer.write(nullptr, fieldPresenceLen)); | ||||
| 	OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen)); | ||||
| 	m_presenceMapBuff.resize(fieldPresenceLen); | ||||
| 	m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); | ||||
| 	m_fieldPresence.setFields(static_cast<int>(fields)); | ||||
| @@ -370,33 +377,33 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo( | ||||
| template<Writer_c Writer> | ||||
| ox::Error MetalClawWriter<Writer>::finalize() noexcept { | ||||
| 	const auto end = m_writer.tellp(); | ||||
| 	oxReturnError(m_writer.seekp(m_writerBeginP)); | ||||
| 	oxReturnError(m_writer.write( | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP)); | ||||
| 	OX_RETURN_ERROR(m_writer.write( | ||||
| 			reinterpret_cast<const char*>(m_presenceMapBuff.data()), | ||||
| 			m_presenceMapBuff.size())); | ||||
| 	oxReturnError(m_writer.seekp(end)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(end)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { | ||||
| 	MetalClawWriter mcWriter(writer); | ||||
| 	ModelHandlerInterface handler{&mcWriter}; | ||||
| 	oxReturnError(model(&handler, &val)); | ||||
| 	oxReturnError(mcWriter.finalize()); | ||||
| 	OX_RETURN_ERROR(model(&handler, &val)); | ||||
| 	OX_RETURN_ERROR(mcWriter.finalize()); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { | ||||
| 	Buffer buff(buffReserveSz); | ||||
| 	BufferWriter bw(&buff, 0); | ||||
| 	oxReturnError(writeMC(bw, val)); | ||||
| 	OX_RETURN_ERROR(writeMC(bw, val)); | ||||
| 	buff.resize(bw.tellp()); | ||||
| 	return buff; | ||||
| } | ||||
|  | ||||
| Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { | ||||
| 	CharBuffWriter bw(buff, buffLen); | ||||
| 	oxReturnError(writeMC(bw, val)); | ||||
| 	CharBuffWriter bw{{buff, buffLen}}; | ||||
| 	OX_RETURN_ERROR(writeMC(bw, val)); | ||||
| 	if (sizeOut) { | ||||
| 		*sizeOut = bw.tellp(); | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										14
									
								
								deps/ox/src/ox/model/def.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								deps/ox/src/ox/model/def.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -11,9 +11,9 @@ | ||||
| #include <ox/std/concepts.hpp> | ||||
|  | ||||
| // oxModelFwdDecl is necessary because Apple-Clang is broken... | ||||
| #define oxModelFwdDecl(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept | ||||
| #define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>()); | ||||
| #define oxModelEnd() return OxError(0); } | ||||
| #define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName)); | ||||
| #define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); | ||||
| #define oxModelFriend(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept | ||||
| #define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept | ||||
| #define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>()); | ||||
| #define OX_MODEL_END() return {}; } | ||||
| #define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName)); | ||||
| #define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName)); | ||||
| #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/descread.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/descread.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/desctypes.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/desctypes.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										57
									
								
								deps/ox/src/ox/model/desctypes.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								deps/ox/src/ox/model/desctypes.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -43,7 +43,7 @@ static constexpr auto buildTypeId( | ||||
| 		for (const auto &p : typeParams) { | ||||
| 			tp += p + ","; | ||||
| 		} | ||||
| 		tp.resize(tp.len() - 1); | ||||
| 		tp.resize(tp.size() - 1); | ||||
| 		tp += "#"; | ||||
| 	} | ||||
| 	return ox::sfmt("{}{};{}", name, tp, version); | ||||
| @@ -76,21 +76,21 @@ struct Subscript { | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<Subscript>()); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<Subscript>()); | ||||
| 	if constexpr(T::opType() == OpType::Reflect) { | ||||
| 		uint32_t st = 0; | ||||
| 		oxReturnError(io->field("subscriptType", &st)); | ||||
| 		OX_RETURN_ERROR(io->field("subscriptType", &st)); | ||||
| 	} else if constexpr(T::opType() == OpType::Write) { | ||||
| 		auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0; | ||||
| 		oxReturnError(io->field("subscriptType", &pt)); | ||||
| 		OX_RETURN_ERROR(io->field("subscriptType", &pt)); | ||||
| 	} else { | ||||
| 		auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0; | ||||
| 		oxReturnError(io->field("subscriptType", &pt)); | ||||
| 		OX_RETURN_ERROR(io->field("subscriptType", &pt)); | ||||
| 		type->subscriptType = static_cast<Subscript::SubscriptType>(pt); | ||||
| 	} | ||||
| 	oxReturnError(io->field("length", &type->length)); | ||||
| 	oxReturnError(io->field("smallSzLen", &type->smallSzLen)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("length", &type->length)); | ||||
| 	OX_RETURN_ERROR(io->field("smallSzLen", &type->smallSzLen)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| using SubscriptStack = Vector<Subscript, 3>; | ||||
| @@ -119,6 +119,7 @@ struct DescriptorField { | ||||
| 		subscriptLevels(pSubscriptLevels), | ||||
| 		subscriptStack(std::move(pSubscriptType)), | ||||
| 		typeId(std::move(pTypeId)) { | ||||
| 		oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "Subscript level mismatch"); | ||||
| 	} | ||||
|  | ||||
| 	constexpr DescriptorField(const DescriptorField &other) noexcept: | ||||
| @@ -184,38 +185,38 @@ constexpr auto buildTypeId(const DescriptorType &t) noexcept { | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<DescriptorType>()); | ||||
| 	oxReturnError(io->field("typeName", &type->typeName)); | ||||
| 	oxReturnError(io->field("typeVersion", &type->typeVersion)); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<DescriptorType>()); | ||||
| 	OX_RETURN_ERROR(io->field("typeName", &type->typeName)); | ||||
| 	OX_RETURN_ERROR(io->field("typeVersion", &type->typeVersion)); | ||||
| 	if constexpr(T::opType() == OpType::Reflect) { | ||||
| 		uint8_t pt = 0; | ||||
| 		oxReturnError(io->field("primitiveType", &pt)); | ||||
| 		OX_RETURN_ERROR(io->field("primitiveType", &pt)); | ||||
| 	} else if constexpr(T::opType() == OpType::Write) { | ||||
| 		auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; | ||||
| 		oxReturnError(io->field("primitiveType", &pt)); | ||||
| 		OX_RETURN_ERROR(io->field("primitiveType", &pt)); | ||||
| 	} else { | ||||
| 		auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; | ||||
| 		oxReturnError(io->field("primitiveType", &pt)); | ||||
| 		OX_RETURN_ERROR(io->field("primitiveType", &pt)); | ||||
| 		type->primitiveType = static_cast<PrimitiveType>(pt); | ||||
| 	} | ||||
| 	oxReturnError(io->field("typeParams", &type->typeParams)); | ||||
| 	oxReturnError(io->field("fieldList", &type->fieldList)); | ||||
| 	oxReturnError(io->field("length", &type->length)); | ||||
| 	oxReturnError(io->field("preloadable", &type->preloadable)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("typeParams", &type->typeParams)); | ||||
| 	OX_RETURN_ERROR(io->field("fieldList", &type->fieldList)); | ||||
| 	OX_RETURN_ERROR(io->field("length", &type->length)); | ||||
| 	OX_RETURN_ERROR(io->field("preloadable", &type->preloadable)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<DescriptorField>()); | ||||
| 	oxReturnError(io->field("typeId", &field->typeId)); | ||||
| 	oxReturnError(io->field("fieldName", &field->fieldName)); | ||||
| 	oxReturnError(io->field("subscriptLevels", &field->subscriptLevels)); | ||||
| 	oxReturnError(io->field("subscriptStack", &field->subscriptStack)); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<DescriptorField>()); | ||||
| 	OX_RETURN_ERROR(io->field("typeId", &field->typeId)); | ||||
| 	OX_RETURN_ERROR(io->field("fieldName", &field->fieldName)); | ||||
| 	OX_RETURN_ERROR(io->field("subscriptLevels", &field->subscriptLevels)); | ||||
| 	OX_RETURN_ERROR(io->field("subscriptStack", &field->subscriptStack)); | ||||
| 	// defaultValue is unused now, but leave placeholder for backwards compatibility | ||||
| 	int defaultValue = 0; | ||||
| 	oxReturnError(io->field("defaultValue", &defaultValue)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("defaultValue", &defaultValue)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename ReaderBase> | ||||
| @@ -243,7 +244,7 @@ constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto | ||||
| 	// defaultValue is unused now, but placeholder for backwards compatibility | ||||
| 	int defaultValue = 0; | ||||
| 	oxReturnError(io->field("defaultValue", &defaultValue)); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/descwrite.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/descwrite.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										53
									
								
								deps/ox/src/ox/model/descwrite.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								deps/ox/src/ox/model/descwrite.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -97,8 +97,14 @@ class TypeDescWriter { | ||||
| 		                                std::size_t fields = ModelFieldCount_v<T>) noexcept; | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr Error field(StringViewCR name, const T *val, std::size_t valLen, | ||||
| 		                      const SubscriptStack &subscriptStack = {}) noexcept; | ||||
| 		constexpr Error field( | ||||
| 				StringViewCR name, | ||||
| 				T const*val, | ||||
| 				std::size_t valLen, | ||||
| 				SubscriptStack const&subscriptStack) noexcept; | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept; | ||||
|  | ||||
| 		template<typename T, bool force> | ||||
| 		constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept; | ||||
| @@ -193,15 +199,30 @@ constexpr ox::Error TypeDescWriter::setTypeInfo( | ||||
|  | ||||
| // array handler | ||||
| template<typename T> | ||||
| constexpr Error TypeDescWriter::field(StringViewCR name, const T*, std::size_t, const SubscriptStack &subscriptStack) noexcept { | ||||
| constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t, SubscriptStack const&subscriptStack) noexcept { | ||||
| 	if (m_type) { | ||||
| 		constexpr typename remove_pointer<T>::type *p = nullptr; | ||||
| 		const auto t = type(p); | ||||
| 		oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); | ||||
| 		m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t)); | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| // array handler | ||||
| template<typename T> | ||||
| constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t) noexcept { | ||||
| 	if (m_type) { | ||||
| 		constexpr typename remove_pointer<T>::type *p = nullptr; | ||||
| 		const auto t = type(p); | ||||
| 		oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); | ||||
| 		auto const lvls = detail::indirectionLevels_v<T> + 1; | ||||
| 		SubscriptStack subscriptStack{lvls}; | ||||
| 		m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t)); | ||||
| 		return {}; | ||||
| 	} | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename T, bool force> | ||||
| @@ -210,9 +231,9 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val | ||||
| 		const auto t = type(val); | ||||
| 		oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); | ||||
| 		m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| @@ -233,7 +254,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept | ||||
| 			return {}; | ||||
| 		} | ||||
| 	} | ||||
| 	return OxError(1); | ||||
| 	return ox::Error(1); | ||||
| } | ||||
|  | ||||
| template<typename ...Args> | ||||
| @@ -357,26 +378,26 @@ constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typ | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept { | ||||
| 	TypeDescWriter writer(typeStore); | ||||
| constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept { | ||||
| 	TypeDescWriter writer(&typeStore); | ||||
| 	ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); | ||||
| 	if (std::is_constant_evaluated()) { | ||||
| 		std::allocator<T> a; | ||||
| 		T *t = a.allocate(1); | ||||
| 		oxReturnError(model(&handler, t)); | ||||
| 		OX_RETURN_ERROR(model(&handler, t)); | ||||
| 		a.deallocate(t, 1); | ||||
| 	} else { | ||||
| 		auto t = ox_malloca(sizeof(T), T); | ||||
| 		oxReturnError(model(&handler, t.get())); | ||||
| 		OX_RETURN_ERROR(model(&handler, t.get())); | ||||
| 	} | ||||
| 	return writer.definition(); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept { | ||||
| 	TypeDescWriter writer(typeStore); | ||||
| constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept { | ||||
| 	TypeDescWriter writer(&typeStore); | ||||
| 	ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); | ||||
| 	oxReturnError(model(&handler, val)); | ||||
| 	OX_RETURN_ERROR(model(&handler, &val)); | ||||
| 	return writer.definition(); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										10
									
								
								deps/ox/src/ox/model/fieldcounter.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								deps/ox/src/ox/model/fieldcounter.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -31,25 +31,25 @@ class FieldCounter { | ||||
| 		template<typename U> | ||||
| 		constexpr ox::Error field(StringViewCR, U) noexcept { | ||||
| 			++fields; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U> | ||||
| 		constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept { | ||||
| 			++fields; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U, typename Handler> | ||||
| 		constexpr Error field(StringViewCR, Handler) { | ||||
| 			++fields; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename ...Args> | ||||
| 		constexpr Error fieldCString(Args&&...) noexcept { | ||||
| 			++fields; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		static constexpr auto opType() noexcept { | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/metadata.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/metadata.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/model.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/model.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										6
									
								
								deps/ox/src/ox/model/modelhandleradaptor.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								deps/ox/src/ox/model/modelhandleradaptor.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -135,8 +135,8 @@ class ModelHandlerInterface { | ||||
| 					return m_handler->field(name, &v->template get<ModelValueArray>()); | ||||
| 			} | ||||
| 			oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type())); | ||||
| 			oxPanic(OxError(1), "invalid type"); | ||||
| 			return OxError(1, "invalid type"); | ||||
| 			oxPanic(ox::Error(1), "invalid type"); | ||||
| 			return ox::Error(1, "invalid type"); | ||||
| 		} | ||||
|  | ||||
| 		// array handler, with callback to allow handling individual elements | ||||
|   | ||||
							
								
								
									
										32
									
								
								deps/ox/src/ox/model/modelops.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								deps/ox/src/ox/model/modelops.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -56,19 +56,19 @@ class MemberList { | ||||
| 		template<typename T> | ||||
| 		constexpr Error field(const char*, T *v) noexcept { | ||||
| 			vars[m_i++] = static_cast<void*>(v); | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr Error field(const char*, T *v, int) noexcept { | ||||
| 			vars[m_i++] = static_cast<void*>(v); | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U, bool force = false> | ||||
| 		constexpr Error field(const char*, UnionView<U, force> u) noexcept { | ||||
| 			vars[m_i++] = static_cast<void*>(u.get()); | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename T> | ||||
| @@ -107,7 +107,7 @@ class Copier { | ||||
| 				auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]); | ||||
| 				dst = src; | ||||
| 				++m_i; | ||||
| 				return OxError(0); | ||||
| 				return {}; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -119,7 +119,7 @@ class Copier { | ||||
| 				dst = src; | ||||
| 			} | ||||
| 			++m_i; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U, bool force = false> | ||||
| @@ -128,7 +128,7 @@ class Copier { | ||||
| 			auto &src = *u.get(); | ||||
| 			dst = src; | ||||
| 			++m_i; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename T = void> | ||||
| @@ -168,7 +168,7 @@ class Mover { | ||||
| 				dst = std::move(src); | ||||
| 				src = FT{}; | ||||
| 				++m_i; | ||||
| 				return OxError(0); | ||||
| 				return {}; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -181,7 +181,7 @@ class Mover { | ||||
| 				src = FT{}; | ||||
| 			} | ||||
| 			++m_i; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U, bool force = false> | ||||
| @@ -190,7 +190,7 @@ class Mover { | ||||
| 			auto &src = *u.get(); | ||||
| 			dst = std::move(src); | ||||
| 			++m_i; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename T = void> | ||||
| @@ -228,10 +228,10 @@ class Equals { | ||||
| 			const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]); | ||||
| 			++m_i; | ||||
| 			if (dst == src) { | ||||
| 				return OxError(0); | ||||
| 				return {}; | ||||
| 			} else { | ||||
| 				this->value = false; | ||||
| 				return OxError(1); | ||||
| 				return ox::Error(1); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -242,11 +242,11 @@ class Equals { | ||||
| 				const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i]; | ||||
| 				if (!(dst == src)) { | ||||
| 					this->value = false; | ||||
| 					return OxError(1); | ||||
| 					return ox::Error(1); | ||||
| 				} | ||||
| 			} | ||||
| 			++m_i; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		template<typename U, bool force = false> | ||||
| @@ -255,10 +255,10 @@ class Equals { | ||||
| 			const auto &src = *u.get(); | ||||
| 			++m_i; | ||||
| 			if (dst == src) { | ||||
| 				return OxError(0); | ||||
| 				return {}; | ||||
| 			} else { | ||||
| 				this->value = false; | ||||
| 				return OxError(1); | ||||
| 				return ox::Error(1); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|   | ||||
							
								
								
									
										8
									
								
								deps/ox/src/ox/model/modelvalue.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								deps/ox/src/ox/model/modelvalue.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -12,12 +12,12 @@ namespace ox { | ||||
|  | ||||
| static_assert([]() -> ox::Error { | ||||
| 	ox::ModelValue v; | ||||
| 	oxReturnError(v.setType<int32_t>()); | ||||
| 	OX_RETURN_ERROR(v.setType<int32_t>()); | ||||
| 	if (v.type() != ModelValue::Type::SignedInteger32) { | ||||
| 		return OxError(1, "type is wrong"); | ||||
| 		return ox::Error(1, "type is wrong"); | ||||
| 	} | ||||
| 	//oxReturnError(v.set<int32_t>(5)); | ||||
| 	return {}; | ||||
| }() == OxError(0)); | ||||
| }() == ox::Error{}); | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										107
									
								
								deps/ox/src/ox/model/modelvalue.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										107
									
								
								deps/ox/src/ox/model/modelvalue.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -168,7 +168,7 @@ class ModelValue { | ||||
| 		constexpr const auto &get() const noexcept { | ||||
| 			constexpr auto type = getType<T>(); | ||||
| 			if (m_type != type) [[unlikely]] { | ||||
| 				oxPanic(OxError(1), "invalid cast"); | ||||
| 				oxPanic(ox::Error(1), "invalid cast"); | ||||
| 			} | ||||
| 			return getValue<type>(*this); | ||||
| 		} | ||||
| @@ -178,7 +178,7 @@ class ModelValue { | ||||
| 		constexpr auto &get() noexcept { | ||||
| 			constexpr auto type = getType<T>(); | ||||
| 			if (m_type != type) [[unlikely]] { | ||||
| 				oxPanic(OxError(1), "invalid cast"); | ||||
| 				oxPanic(ox::Error(1), "invalid cast"); | ||||
| 			} | ||||
| 			return getValue<type>(*this); | ||||
| 		} | ||||
| @@ -188,8 +188,8 @@ class ModelValue { | ||||
|  | ||||
| 		constexpr Error setType( | ||||
| 				DescriptorType const*type, | ||||
| 				int subscriptLevels = 0, | ||||
| 				SubscriptStack const& = {}) noexcept; | ||||
| 				SubscriptStack const& = {}, | ||||
| 				int subscriptLevels = 0) noexcept; | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr Error setType() noexcept; | ||||
| @@ -242,7 +242,7 @@ class ModelValueArray { | ||||
| 			m_vec.resize(sz); | ||||
| 			if (sz > oldSz) { | ||||
| 				for (auto i = oldSz; i < sz; ++i) { | ||||
| 					oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels)); | ||||
| 					OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); | ||||
| 				} | ||||
| 			} | ||||
| 			return {}; | ||||
| @@ -276,8 +276,9 @@ class ModelValueArray { | ||||
|  | ||||
| 		constexpr Error setType( | ||||
| 				DescriptorType const*type, | ||||
| 				int subscriptLevels, | ||||
| 				SubscriptStack subscriptStack) noexcept { | ||||
| 				SubscriptStack subscriptStack, | ||||
| 				int subscriptLevels) noexcept { | ||||
| 			oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch"); | ||||
| 			m_type = type; | ||||
| 			m_typeSubscriptLevels = subscriptLevels; | ||||
| 			m_subscriptStack = std::move(subscriptStack); | ||||
| @@ -400,7 +401,7 @@ class ModelValueVector { | ||||
| 			m_vec.resize(sz); | ||||
| 			if (sz > oldSz) { | ||||
| 				for (auto i = oldSz; i < sz; ++i) { | ||||
| 					oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack)); | ||||
| 					OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels)); | ||||
| 				} | ||||
| 			} | ||||
| 			return {}; | ||||
| @@ -418,8 +419,9 @@ class ModelValueVector { | ||||
|  | ||||
| 		constexpr Error setType( | ||||
| 				DescriptorType const*type, | ||||
| 				int subscriptLevels, | ||||
| 				SubscriptStack subscriptStack) noexcept { | ||||
| 				SubscriptStack subscriptStack, | ||||
| 				int subscriptLevels) noexcept { | ||||
| 			oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch"); | ||||
| 			m_type = type; | ||||
| 			m_typeSubscriptLevels = subscriptLevels; | ||||
| 			m_subscriptStack = std::move(subscriptStack); | ||||
| @@ -517,7 +519,7 @@ class ModelObject { | ||||
| 			ModelValue value; | ||||
| 		}; | ||||
| 	protected: | ||||
| 		oxModelFriend(ModelObject); | ||||
| 		OX_MODEL_FRIEND(ModelObject); | ||||
| 		friend ModelValue; | ||||
| 		Vector<UniquePtr<Field>> m_fieldsOrder; | ||||
| 		HashMap<String, ModelValue*> m_fields; | ||||
| @@ -632,18 +634,18 @@ class ModelObject { | ||||
| 			if (m_fields.contains(k)) { | ||||
| 				return *m_fields.at(k).value; | ||||
| 			} | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr Error set(const String &k, T &&val) noexcept { | ||||
| 			oxRequire(t, m_fields.at(k)); | ||||
| 			OX_REQUIRE(t, m_fields.at(k)); | ||||
| 			*t = ox::forward<T>(val); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { | ||||
| 			oxRequire(v, m_fields.at(k)); | ||||
| 			OX_REQUIRE(v, m_fields.at(k)); | ||||
| 			return *v; | ||||
| 		} | ||||
|  | ||||
| @@ -668,17 +670,17 @@ class ModelObject { | ||||
|  | ||||
| 		constexpr Error setType(const DescriptorType *type) noexcept { | ||||
| 			if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { | ||||
| 				return OxError(1, "Cannot load a non-struct type to ModelObject"); | ||||
| 				return ox::Error(1, "Cannot load a non-struct type to ModelObject"); | ||||
| 			} | ||||
| 			m_type = type; | ||||
| 			for (const auto &f : type->fieldList) { | ||||
| 				auto field = make_unique<Field>(); | ||||
| 				field->name = f.fieldName; | ||||
| 				oxReturnError(field->value.setType(f.type, f.subscriptLevels, f.subscriptStack)); | ||||
| 				OX_RETURN_ERROR(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels)); | ||||
| 				m_fields[field->name] = &field->value; | ||||
| 				m_fieldsOrder.emplace_back(std::move(field)); | ||||
| 			} | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| }; | ||||
| @@ -720,7 +722,7 @@ class ModelUnion { | ||||
|  | ||||
| 		static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept { | ||||
| 			UniquePtr<ModelUnion> out(new ModelUnion); | ||||
| 			oxReturnError(out->setType(type)); | ||||
| 			OX_RETURN_ERROR(out->setType(type)); | ||||
| 			return out; | ||||
| 		} | ||||
|  | ||||
| @@ -729,7 +731,7 @@ class ModelUnion { | ||||
| 		} | ||||
|  | ||||
| 		constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { | ||||
| 			oxRequire(v, m_fields.at(k)); | ||||
| 			OX_REQUIRE(v, m_fields.at(k)); | ||||
| 			return &(*v)->value; | ||||
| 		} | ||||
|  | ||||
| @@ -761,7 +763,7 @@ class ModelUnion { | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| 		constexpr Result<const ModelValue*> get(StringView const&k) const noexcept { | ||||
| 			oxRequire(t, m_fields.at(k)); | ||||
| 			OX_REQUIRE(t, m_fields.at(k)); | ||||
| 			return &(*t)->value; | ||||
| 		} | ||||
|  | ||||
| @@ -788,7 +790,7 @@ class ModelUnion { | ||||
|  | ||||
| 		constexpr Error setType(const DescriptorType *type) noexcept { | ||||
| 			if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { | ||||
| 				return OxError(1, "Cannot load a non-struct type to ModelUnion"); | ||||
| 				return ox::Error(1, "Cannot load a non-struct type to ModelUnion"); | ||||
| 			} | ||||
| 			m_fields.clear(); | ||||
| 			m_fieldsOrder.clear(); | ||||
| @@ -797,12 +799,12 @@ class ModelUnion { | ||||
| 				auto field = make_unique<Field>(); | ||||
| 				field->name = f.fieldName; | ||||
| 				field->idx = i; | ||||
| 				oxReturnError(field->value.setType(f.type, f.subscriptLevels)); | ||||
| 				OX_RETURN_ERROR(field->value.setType(f.type, SubscriptStack{static_cast<size_t>(f.subscriptLevels)}, f.subscriptLevels)); | ||||
| 				m_fields[field->name] = field.get(); | ||||
| 				m_fieldsOrder.emplace_back(std::move(field)); | ||||
| 				++i; | ||||
| 			} | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		[[nodiscard]] | ||||
| @@ -965,21 +967,21 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept { | ||||
| } | ||||
|  | ||||
| constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept { | ||||
| 	oxReturnError(h->template setTypeInfo<ModelObject>( | ||||
| 	OX_RETURN_ERROR(h->template setTypeInfo<ModelObject>( | ||||
| 			obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); | ||||
| 	for (auto &f : obj->m_fieldsOrder) { | ||||
| 		oxReturnError(h->field(f->name.c_str(), &f->value)); | ||||
| 		OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept { | ||||
| 	oxReturnError(h->template setTypeInfo<ModelUnion>( | ||||
| 	OX_RETURN_ERROR(h->template setTypeInfo<ModelUnion>( | ||||
| 			obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); | ||||
| 	for (auto &f : obj->m_fieldsOrder) { | ||||
| 		oxReturnError(h->field(f->name.c_str(), &f->value)); | ||||
| 		OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { | ||||
| @@ -995,7 +997,7 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { | ||||
| 		case Type::SignedInteger16: | ||||
| 		case Type::SignedInteger32: | ||||
| 		case Type::SignedInteger64: | ||||
| 			ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); | ||||
| 			m_data = other.m_data; | ||||
| 			break; | ||||
| 		case Type::String: | ||||
| 			m_data.str = new String(other.get<String>()); | ||||
| @@ -1028,8 +1030,8 @@ constexpr ModelValue::ModelValue(ModelValue &&other) noexcept { | ||||
| 		case Type::SignedInteger16: | ||||
| 		case Type::SignedInteger32: | ||||
| 		case Type::SignedInteger64: | ||||
| 			ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); | ||||
| 			ox::memset(&other.m_data, 0, sizeof(m_data)); | ||||
| 			m_data = other.m_data; | ||||
| 			other.m_data.ui64 = 0; | ||||
| 			break; | ||||
| 		case Type::String: | ||||
| 			m_data.str = other.m_data.str; | ||||
| @@ -1076,20 +1078,21 @@ constexpr ModelValue::Type ModelValue::type() const noexcept { | ||||
|  | ||||
| constexpr Error ModelValue::setType( | ||||
| 		const DescriptorType *type, | ||||
| 		int subscriptLevels, | ||||
| 		SubscriptStack const&subscriptStack) noexcept { | ||||
| 		SubscriptStack const&subscriptStack, | ||||
| 		int subscriptLevels) noexcept { | ||||
| 	freeResources(); | ||||
| 	oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch"); | ||||
| 	if (subscriptLevels) { | ||||
| 		auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)]; | ||||
| 		if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) { | ||||
| 			m_type = Type::InlineArray; | ||||
| 			m_data.array = new ModelValueArray; | ||||
| 			oxReturnError(m_data.array->setType(type, subscriptLevels - 1, subscriptStack)); | ||||
| 			oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length))); | ||||
| 			OX_RETURN_ERROR(m_data.array->setType(type, subscriptStack, subscriptLevels - 1)); | ||||
| 			OX_RETURN_ERROR(m_data.array->setSize(static_cast<size_t>(subscript.length))); | ||||
| 		} else { | ||||
| 			m_type = Type::Vector; | ||||
| 			m_data.vec = new ModelValueVector; | ||||
| 			oxReturnError(m_data.vec->setType(type, subscriptLevels - 1, subscriptStack)); | ||||
| 			OX_RETURN_ERROR(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1)); | ||||
| 		} | ||||
| 		return {}; | ||||
| 	} else if (type->typeName == types::Bool) { | ||||
| @@ -1118,15 +1121,15 @@ constexpr Error ModelValue::setType( | ||||
| 	} else if (type->primitiveType == PrimitiveType::Struct) { | ||||
| 		m_type = Type::Object; | ||||
| 		m_data.obj = new ModelObject; | ||||
| 		oxReturnError(m_data.obj->setType(type)); | ||||
| 		OX_RETURN_ERROR(m_data.obj->setType(type)); | ||||
| 	} else if (type->primitiveType == PrimitiveType::Union) { | ||||
| 		m_type = Type::Union; | ||||
| 		oxRequireM(u, ModelUnion::make(type)); | ||||
| 		OX_REQUIRE_M(u, ModelUnion::make(type)); | ||||
| 		m_data.uni = u.release(); | ||||
| 		oxReturnError(m_data.uni->setType(type)); | ||||
| 		OX_RETURN_ERROR(m_data.uni->setType(type)); | ||||
| 	} | ||||
| 	oxAssert(m_type != Type::Undefined, "No type set"); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| @@ -1138,11 +1141,11 @@ constexpr Error ModelValue::setType() noexcept { | ||||
| 	//             rather than using getValue<type>() | ||||
| 	if constexpr(type == Type::Object) { | ||||
| 		m_data.obj = new ModelObject; | ||||
| 		oxReturnError(m_data.obj->setType(type)); | ||||
| 		OX_RETURN_ERROR(m_data.obj->setType(type)); | ||||
| 	} else if constexpr(type == Type::Union) { | ||||
| 		oxRequireM(u, ModelUnion::make(type)); | ||||
| 		OX_REQUIRE_M(u, ModelUnion::make(type)); | ||||
| 		m_data.uni = u.release(); | ||||
| 		oxReturnError(m_data.uni->setType(type)); | ||||
| 		OX_RETURN_ERROR(m_data.uni->setType(type)); | ||||
| 	} else if constexpr(type == Type::String) { | ||||
| 		m_data.str = new String; | ||||
| 	} else if constexpr(type == Type::Vector) { | ||||
| @@ -1173,7 +1176,7 @@ template<typename T> | ||||
| constexpr Error ModelValue::set(const T &v) noexcept { | ||||
| 	constexpr auto type = getType<T>(); | ||||
| 	if (m_type != type) [[unlikely]] { | ||||
| 		return OxError(1, "type mismatch"); | ||||
| 		return ox::Error(1, "type mismatch"); | ||||
| 	} | ||||
| 	auto &value = getValue<type>(*this); | ||||
| 	if constexpr(type == Type::Vector || type == Type::Object || | ||||
| @@ -1181,14 +1184,14 @@ constexpr Error ModelValue::set(const T &v) noexcept { | ||||
| 		safeDelete(&value); | ||||
| 	} | ||||
| 	value = v; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| constexpr Error ModelValue::set(T &&v) noexcept { | ||||
| 	constexpr auto type = getType<T>(); | ||||
| 	if (m_type != type) [[unlikely]] { | ||||
| 		return OxError(1, "type mismatch"); | ||||
| 		return ox::Error(1, "type mismatch"); | ||||
| 	} | ||||
| 	auto &value = getValue<type>(*this); | ||||
| 	if constexpr(type == Type::Vector || type == Type::Object || | ||||
| @@ -1196,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept { | ||||
| 		safeDelete(&value); | ||||
| 	} | ||||
| 	value = std::move(v); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept { | ||||
| @@ -1220,7 +1223,7 @@ constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept { | ||||
| 		case Type::SignedInteger16: | ||||
| 		case Type::SignedInteger32: | ||||
| 		case Type::SignedInteger64: | ||||
| 			ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); | ||||
| 			m_data = other.m_data; | ||||
| 			break; | ||||
| 		case Type::String: | ||||
| 			m_data.str = new String(other.get<String>()); | ||||
| @@ -1258,8 +1261,8 @@ constexpr ModelValue &ModelValue::operator=(ModelValue &&other) noexcept { | ||||
| 		case Type::SignedInteger16: | ||||
| 		case Type::SignedInteger32: | ||||
| 		case Type::SignedInteger64: | ||||
| 			ox::memcpy(&m_data, &other.m_data, sizeof(m_data)); | ||||
| 			ox::memset(&other.m_data, 0, sizeof(m_data)); | ||||
| 			m_data = other.m_data; | ||||
| 			other.m_data = {}; | ||||
| 			break; | ||||
| 		case Type::String: | ||||
| 			m_data.str = other.m_data.str; | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/optype.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/optype.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										12
									
								
								deps/ox/src/ox/model/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								deps/ox/src/ox/model/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -17,8 +17,8 @@ struct TestType { | ||||
| 	static constexpr auto TypeVersion = 1; | ||||
| }; | ||||
|  | ||||
| oxModelBegin(TestType) | ||||
| oxModelEnd() | ||||
| OX_MODEL_BEGIN(TestType) | ||||
| OX_MODEL_END() | ||||
|  | ||||
| struct TestType2 { | ||||
| }; | ||||
| @@ -38,12 +38,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 			"ModelValue", | ||||
| 			[] { | ||||
| 				ox::ModelValue v; | ||||
| 				oxReturnError(v.setType<int32_t>()); | ||||
| 				OX_RETURN_ERROR(v.setType<int32_t>()); | ||||
| 				//v.m_type = ox::ModelValue::getType<int32_t>(); | ||||
| 				if (v.type() != ox::ModelValue::Type::SignedInteger32) { | ||||
| 					return OxError(1, "type is wrong"); | ||||
| 					return ox::Error(1, "type is wrong"); | ||||
| 				} | ||||
| 				oxReturnError(v.set<int32_t>(5)); | ||||
| 				OX_RETURN_ERROR(v.set<int32_t>(5)); | ||||
| 				return ox::Error{}; | ||||
| 			} | ||||
| 		}, | ||||
|   | ||||
							
								
								
									
										24
									
								
								deps/ox/src/ox/model/typenamecatcher.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								deps/ox/src/ox/model/typenamecatcher.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -38,17 +38,17 @@ struct TypeNameCatcher { | ||||
|  | ||||
| 	template<typename T> | ||||
| 	constexpr Error field(const char*, T*, std::size_t) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T> | ||||
| 	constexpr Error field(const char*, T) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	template<typename ...Args> | ||||
| 	constexpr Error fieldCString(Args&&...) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	static constexpr auto opType() noexcept { | ||||
| @@ -77,17 +77,17 @@ struct TypeInfoCatcher { | ||||
|  | ||||
| 	template<typename T> | ||||
| 	constexpr Error field(const char*, T*, std::size_t) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T> | ||||
| 	constexpr Error field(const char*, T) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T> | ||||
| 	constexpr Error fieldCString(const char*, T) noexcept { | ||||
| 		return OxError(0); | ||||
| 		return {}; | ||||
| 	} | ||||
|  | ||||
| 	static constexpr auto opType() noexcept { | ||||
| @@ -140,16 +140,16 @@ constexpr Str getModelTypeName() noexcept { | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| template<typename T, typename Str = const char*> | ||||
| [[nodiscard]] | ||||
| consteval auto requireModelTypeName() noexcept { | ||||
| 	constexpr auto name = getModelTypeName<T>(); | ||||
| 	static_assert(ox::StringView{name}.len(), "Type lacks required TypeName"); | ||||
| 	constexpr auto name = getModelTypeName<T, Str>(); | ||||
| 	static_assert(ox::StringView{name}.size(), "Type lacks required TypeName"); | ||||
| 	return name; | ||||
| } | ||||
|  | ||||
| template<typename T, typename Str = const char*> | ||||
| constexpr auto ModelTypeName_v = getModelTypeName<T, Str>(); | ||||
| constexpr auto ModelTypeName_v = requireModelTypeName<T, Str>(); | ||||
|  | ||||
| template<typename T, typename Str = const char*> | ||||
| constexpr auto ModelTypeVersion_v = requireModelTypeVersion<T>(); | ||||
| @@ -159,7 +159,7 @@ constexpr auto ModelTypeId_v = [] { | ||||
| 	constexpr auto name = ModelTypeName_v<T, ox::StringView>; | ||||
| 	constexpr auto version = ModelTypeVersion_v<T>; | ||||
| 	constexpr auto versionStr = ox::sfmt<ox::IString<19>>("{}", version); | ||||
| 	return ox::sfmt<ox::IString<name.len() + versionStr.len() + 1>>("{};{}", name, versionStr); | ||||
| 	return ox::sfmt<ox::IString<name.size() + versionStr.size() + 1>>("{};{}", name, versionStr); | ||||
| }(); | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/model/types.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/model/types.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										18
									
								
								deps/ox/src/ox/model/typestore.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								deps/ox/src/ox/model/typestore.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -31,7 +31,7 @@ class TypeStore { | ||||
| 		constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion, | ||||
| 		                                            const TypeParamPack &typeParams) const noexcept { | ||||
| 			const auto typeId = buildTypeId(name, typeVersion, typeParams); | ||||
| 			oxRequire(out, m_cache.at(typeId)); | ||||
| 			OX_REQUIRE(out, m_cache.at(typeId)); | ||||
| 			return out->get(); | ||||
| 		} | ||||
|  | ||||
| @@ -40,7 +40,7 @@ class TypeStore { | ||||
| 			constexpr auto typeName = ModelTypeName_v<T>; | ||||
| 			constexpr auto typeVersion = ModelTypeVersion_v<T>; | ||||
| 			const auto typeId = buildTypeId(typeName, typeVersion, {}); | ||||
| 			oxRequire(out, m_cache.at(typeId)); | ||||
| 			OX_REQUIRE(out, m_cache.at(typeId)); | ||||
| 			return out->get(); | ||||
| 		} | ||||
|  | ||||
| @@ -56,15 +56,19 @@ class TypeStore { | ||||
| 			auto [val, err] = m_cache.at(typeId); | ||||
| 			if (err) { | ||||
| 				if (!std::is_constant_evaluated()) { | ||||
| 					oxRequireM(dt, loadDescriptor(typeId)); | ||||
| 					OX_REQUIRE_M(dt, loadDescriptor(typeId)); | ||||
| 					for (auto &f : dt->fieldList) { | ||||
| 						oxReturnError(this->getLoad(f.typeId).moveTo(f.type)); | ||||
| 						if (typeId == f.typeId) { | ||||
| 							f.type = dt.get(); | ||||
| 						} else { | ||||
| 							OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type)); | ||||
| 						} | ||||
| 					} | ||||
| 					auto &out = m_cache[typeId]; | ||||
| 					out = std::move(dt); | ||||
| 					return out.get(); | ||||
| 				} else { | ||||
| 					return OxError(1, "Type not available"); | ||||
| 					return ox::Error(1, "Type not available"); | ||||
| 				} | ||||
| 			} | ||||
| 			return val->get(); | ||||
| @@ -102,7 +106,7 @@ class TypeStore { | ||||
|  | ||||
| 	protected: | ||||
| 		virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept { | ||||
| 			return OxError(1); | ||||
| 			return ox::Error(1); | ||||
| 		} | ||||
|  | ||||
| 		Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version, | ||||
|   | ||||
							
								
								
									
										26
									
								
								deps/ox/src/ox/model/walk.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								deps/ox/src/ox/model/walk.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -50,7 +50,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler | ||||
|  | ||||
| template<typename Reader, typename T> | ||||
| constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept { | ||||
| 	oxRequire(out, m_typeStack.back()); | ||||
| 	OX_REQUIRE(out, m_typeStack.back()); | ||||
| 	return *out; | ||||
| } | ||||
|  | ||||
| @@ -87,9 +87,9 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat | ||||
| 	walker->pushNamePath(field.fieldName); | ||||
| 	if (field.subscriptLevels) { | ||||
| 		// add array handling | ||||
| 		oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); | ||||
| 		OX_REQUIRE(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); | ||||
| 		auto child = rdr->child(field.fieldName.c_str()); | ||||
| 		oxReturnError(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen)); | ||||
| 		OX_RETURN_ERROR(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen)); | ||||
| 		DescriptorField f(field); // create mutable copy | ||||
| 		--f.subscriptLevels; | ||||
| 		String subscript; | ||||
| @@ -98,7 +98,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat | ||||
| 			subscript += static_cast<uint64_t>(i); | ||||
| 			subscript += "]"; | ||||
| 			walker->pushNamePath(subscript); | ||||
| 			oxReturnError(parseField(f, &child, walker)); | ||||
| 			OX_RETURN_ERROR(parseField(f, &child, walker)); | ||||
| 			walker->popNamePath(); | ||||
| 		} | ||||
| 		rdr->nextField(); | ||||
| @@ -108,40 +108,40 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat | ||||
| 			case PrimitiveType::SignedInteger: | ||||
| 			case PrimitiveType::Bool: | ||||
| 			case PrimitiveType::String: | ||||
| 				oxReturnError(walker->read(field, rdr)); | ||||
| 				OX_RETURN_ERROR(walker->read(field, rdr)); | ||||
| 				break; | ||||
| 			case PrimitiveType::Struct: | ||||
| 			case PrimitiveType::Union: | ||||
| 				if (rdr->fieldPresent(field.fieldName.c_str())) { | ||||
| 					auto child = rdr->child(field.fieldName.c_str()); | ||||
| 					walker->pushType(field.type); | ||||
| 					oxReturnError(model(&child, walker)); | ||||
| 					OX_RETURN_ERROR(model(&child, walker)); | ||||
| 					walker->popType(); | ||||
| 					rdr->nextField(); | ||||
| 				} else { | ||||
| 					// skip and discard absent field | ||||
| 					int discard; | ||||
| 					oxReturnError(rdr->field(field.fieldName.c_str(), &discard)); | ||||
| 					OX_RETURN_ERROR(rdr->field(field.fieldName.c_str(), &discard)); | ||||
| 				} | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| 	walker->popNamePath(); | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename Reader, typename FH> | ||||
| constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept { | ||||
| 	oxRequire(type, walker->type()); | ||||
| 	OX_REQUIRE(type, walker->type()); | ||||
| 	auto typeName = type->typeName.c_str(); | ||||
| 	auto typeVersion = type->typeVersion; | ||||
| 	auto typeParams = type->typeParams; | ||||
| 	auto &fields = type->fieldList; | ||||
| 	oxReturnError(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size())); | ||||
| 	OX_RETURN_ERROR(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size())); | ||||
| 	for (const auto &field : fields) { | ||||
| 		oxReturnError(parseField(field, rdr, walker)); | ||||
| 		OX_RETURN_ERROR(parseField(field, rdr, walker)); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename Reader, typename Handler> | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/oc/oc.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/oc/oc.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										32
									
								
								deps/ox/src/ox/oc/read.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								deps/ox/src/ox/oc/read.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -15,11 +15,11 @@ namespace ox { | ||||
|  | ||||
| OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { | ||||
| 	auto json = reinterpret_cast<const char*>(buff); | ||||
| 	auto jsonLen = ox::strnlen(json, buffSize); | ||||
| 	auto jsonLen = ox::strnlen_s(json, buffSize); | ||||
| 	Json::CharReaderBuilder parserBuilder; | ||||
| 	auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); | ||||
| 	if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { | ||||
| 		throw OxException(1, "Could not parse JSON"); | ||||
| 		throw ox::Exception(1, "Could not parse JSON"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -27,7 +27,7 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) { | ||||
| 	Json::CharReaderBuilder parserBuilder; | ||||
| 	auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); | ||||
| 	if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { | ||||
| 		throw OxException(1, "Could not parse JSON"); | ||||
| 		throw ox::Exception(1, "Could not parse JSON"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept: | ||||
| } | ||||
|  | ||||
| Error OrganicClawReader::field(const char *key, bool *val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	if (targetValid()) { | ||||
| 		const auto &jv = value(key); | ||||
| 		if (jv.empty()) { | ||||
| @@ -45,7 +45,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept { | ||||
| 		} else if (jv.isBool()) { | ||||
| 			*val = jv.asBool(); | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept { | ||||
| } | ||||
|  | ||||
| Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	const char *begin = nullptr, *end = nullptr; | ||||
| 	const auto &jv = value(key); | ||||
| 	if (targetValid()) { | ||||
| @@ -67,13 +67,13 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu | ||||
| 			const auto strSize = static_cast<std::size_t>(end - begin); | ||||
| 			auto data = val; | ||||
| 			if (strSize >= buffLen) { | ||||
| 				err = OxError(2, "String size exceeds capacity of destination"); | ||||
| 				err = ox::Error(2, "String size exceeds capacity of destination"); | ||||
| 			} else { | ||||
| 				ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); | ||||
| 				data[strSize] = 0; | ||||
| 			} | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu | ||||
| } | ||||
|  | ||||
| Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	const char *begin = nullptr, *end = nullptr; | ||||
| 	const auto &jv = value(key); | ||||
| 	auto &data = *val; | ||||
| @@ -98,7 +98,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { | ||||
| 			ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); | ||||
| 			data[strSize] = 0; | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { | ||||
| } | ||||
|  | ||||
| Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	const char *begin = nullptr, *end = nullptr; | ||||
| 	const auto &jv = value(key); | ||||
| 	if (targetValid()) { | ||||
| @@ -126,7 +126,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b | ||||
| 			ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); | ||||
| 			data[strSize] = nullptr; | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -135,7 +135,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b | ||||
|  | ||||
| Error OrganicClawReader::field(const char *key, UUID *val) noexcept { | ||||
| 	UUIDStr str; | ||||
| 	oxReturnError(field(key, &str)); | ||||
| 	OX_RETURN_ERROR(field(key, &str)); | ||||
| 	return UUID::fromString(str).moveTo(*val); | ||||
| } | ||||
|  | ||||
| @@ -147,7 +147,7 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce | ||||
| 	if (jv.isArray()) { | ||||
| 		return jv.size(); | ||||
| 	} | ||||
| 	return OxError(1, "Type mismatch"); | ||||
| 	return ox::Error(1, "Type mismatch"); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] | ||||
| @@ -161,7 +161,7 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept { | ||||
| 		jv.getString(&begin, &end); | ||||
| 		return static_cast<std::size_t>(end - begin); | ||||
| 	} | ||||
| 	return OxError(1, "Type mismatch"); | ||||
| 	return ox::Error(1, "Type mismatch"); | ||||
| } | ||||
|  | ||||
| OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept { | ||||
|   | ||||
							
								
								
									
										64
									
								
								deps/ox/src/ox/oc/read.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								deps/ox/src/ox/oc/read.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -8,7 +8,11 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ox/std/def.hpp> | ||||
|  | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| #include <json/json.h> | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
|  | ||||
| #include <ox/model/fieldcounter.hpp> | ||||
| #include <ox/model/modelhandleradaptor.hpp> | ||||
| @@ -133,7 +137,7 @@ class OrganicClawReader { | ||||
|  | ||||
| template<typename T> | ||||
| Error OrganicClawReader::field(const char *key, T *val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	try { | ||||
| 		if constexpr (is_integer_v<T>) { | ||||
| 			if (targetValid()) { | ||||
| @@ -144,21 +148,25 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept { | ||||
| 				if (jv.empty()) { | ||||
| 					*val = 0; | ||||
| 				} else if (rightType) { | ||||
| 					*val = static_cast<T>(jv.asUInt()); | ||||
| 					if constexpr(ox::is_signed_v<T>) { | ||||
| 						*val = static_cast<T>(jv.asInt64()); | ||||
| 					} else { | ||||
| 						*val = static_cast<T>(jv.asUInt64()); | ||||
| 					} | ||||
| 				} else { | ||||
| 					err = OxError(1, "Type mismatch"); | ||||
| 					err = ox::Error(1, "Type mismatch"); | ||||
| 				} | ||||
| 			} | ||||
| 		} else if constexpr (isVector_v<T>) { | ||||
| 			const auto&srcVal = value(key); | ||||
| 			const auto srcSize = srcVal.size(); | ||||
| 			oxReturnError(ox::resizeVector(*val, srcSize)); | ||||
| 			OX_RETURN_ERROR(ox::resizeVector(*val, srcSize)); | ||||
| 			err = field(key, val->data(), val->size()); | ||||
| 		} else if constexpr (isArray_v<T>) { | ||||
| 			const auto&srcVal = value(key); | ||||
| 			const auto srcSize = srcVal.size(); | ||||
| 			if (srcSize > val->size()) { | ||||
| 				err = OxError(1, "Input array is too long"); | ||||
| 				err = ox::Error(1, "Input array is too long"); | ||||
| 			} else { | ||||
| 				err = field(key, val->data(), val->size()); | ||||
| 			} | ||||
| @@ -169,11 +177,11 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept { | ||||
| 				ModelHandlerInterface handler(&reader); | ||||
| 				err = model(&handler, val); | ||||
| 			} else { | ||||
| 				err = OxError(1, "Type mismatch"); | ||||
| 				err = ox::Error(1, "Type mismatch"); | ||||
| 			} | ||||
| 		} | ||||
| 	} catch (Json::LogicError const&) { | ||||
| 		err = OxError(1, "error reading JSON data"); | ||||
| 	} catch (Json::LogicError const&e) { | ||||
| 		err = ox::Error(1, "error reading JSON data"); | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| 	return err; | ||||
| @@ -181,7 +189,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept { | ||||
|  | ||||
| template<typename U, bool force> | ||||
| Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	if (targetValid()) { | ||||
| 		const auto &jv = value(key); | ||||
| 		if (jv.empty() || jv.isObject()) { | ||||
| @@ -189,7 +197,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep | ||||
| 			ModelHandlerInterface handler(&reader); | ||||
| 			err = model(&handler, val.get()); | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -198,7 +206,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep | ||||
|  | ||||
| template<std::size_t L> | ||||
| Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	if (targetValid()) { | ||||
| 		const auto &jv = value(key); | ||||
| 		if (jv.empty()) { | ||||
| @@ -206,7 +214,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { | ||||
| 		} else if (jv.isString()) { | ||||
| 			*val = jv.asString().c_str(); | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -215,7 +223,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { | ||||
|  | ||||
| template<std::size_t L> | ||||
| Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { | ||||
| 	auto err = OxError(0); | ||||
| 	ox::Error err{}; | ||||
| 	if (targetValid()) { | ||||
| 		const auto &jv = value(key); | ||||
| 		if (jv.empty()) { | ||||
| @@ -223,7 +231,7 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { | ||||
| 		} else if (jv.isString()) { | ||||
| 			*val = jv.asString().c_str(); | ||||
| 		} else { | ||||
| 			err = OxError(1, "Type mismatch"); | ||||
| 			err = ox::Error(1, "Type mismatch"); | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| @@ -235,25 +243,27 @@ template<typename T> | ||||
| Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept { | ||||
| 	const auto &srcVal = value(key); | ||||
| 	if (!srcVal.isNull() && !srcVal.isArray()) { | ||||
| 		return OxError(1, "Type mismatch"); | ||||
| 		return ox::Error(1, "Type mismatch"); | ||||
| 	} | ||||
| 	auto srcSize = srcVal.size(); | ||||
| 	if (srcSize > valLen) { | ||||
| 		return OxError(1); | ||||
| 		return ox::Error(1); | ||||
| 	} | ||||
| 	OrganicClawReader r(srcVal); | ||||
| 	ModelHandlerInterface handler{&r}; | ||||
| 	for (decltype(srcSize) i = 0; i < srcSize; ++i) { | ||||
| 		oxReturnError(handler.field("", &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 		OX_RETURN_ERROR(handler.field("", &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept { | ||||
| 	const auto &srcVal = value(key); | ||||
| 	if (!srcVal.isObject()) { | ||||
| 		return OxError(1, "Type mismatch"); | ||||
| 		return ox::Error(1, "Type mismatch"); | ||||
| 	} | ||||
| 	auto keys = srcVal.getMemberNames(); | ||||
| 	auto srcSize = srcVal.size(); | ||||
| @@ -261,9 +271,9 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep | ||||
| 	ModelHandlerInterface handler{&r}; | ||||
| 	for (decltype(srcSize) i = 0; i < srcSize; ++i) { | ||||
| 		const auto k = keys[i].c_str(); | ||||
| 		oxReturnError(handler.field(k, &val->operator[](k))); | ||||
| 		OX_RETURN_ERROR(handler.field(k, &val->operator[](k))); | ||||
| 	} | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Error readOC(BufferView buff, auto &val) noexcept { | ||||
| @@ -272,8 +282,10 @@ Error readOC(BufferView buff, auto &val) noexcept { | ||||
| 		Json::Value doc; | ||||
| 		Json::CharReaderBuilder parserBuilder; | ||||
| 		auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader()); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 		if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) { | ||||
| 			return OxError(1, "Could not parse JSON"); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 			return ox::Error(1, "Could not parse JSON"); | ||||
| 		} | ||||
| 		OrganicClawReader reader(buff.data(), buff.size()); | ||||
| 		ModelHandlerInterface handler(&reader); | ||||
| @@ -281,20 +293,20 @@ Error readOC(BufferView buff, auto &val) noexcept { | ||||
| 	} catch (const Error &err) { | ||||
| 		return err; | ||||
| 	} catch (...) { | ||||
| 		return OxError(1, "Unknown Error"); | ||||
| 		return ox::Error(1, "Unknown Error"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| Result<T> readOC(BufferView buff) noexcept { | ||||
| 	Result<T> val; | ||||
| 	oxReturnError(readOC(buff, val.value)); | ||||
| 	OX_RETURN_ERROR(readOC(buff, val.value)); | ||||
| 	return val; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| Result<T> readOC(ox::StringView json) noexcept { | ||||
| 	return readOC<T>(ox::BufferView{json.data(), json.len()}); | ||||
| 	return readOC<T>(ox::BufferView{json.data(), json.size()}); | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										78
									
								
								deps/ox/src/ox/oc/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										78
									
								
								deps/ox/src/ox/oc/test/tests.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -74,45 +74,45 @@ struct TestStruct { | ||||
| }; | ||||
|  | ||||
| constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<TestUnion>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->fieldCString("String", &obj->String)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->fieldCString("String", &obj->String)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<TestStructNest>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->field("String", &obj->String)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->field("String", &obj->String)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { | ||||
| 	oxReturnError(io->template setTypeInfo<TestStruct>()); | ||||
| 	oxReturnError(io->field("Bool", &obj->Bool)); | ||||
| 	oxReturnError(io->field("Int", &obj->Int)); | ||||
| 	oxReturnError(io->field("Int1", &obj->Int1)); | ||||
| 	oxReturnError(io->field("Int2", &obj->Int2)); | ||||
| 	oxReturnError(io->field("Int3", &obj->Int3)); | ||||
| 	oxReturnError(io->field("Int4", &obj->Int4)); | ||||
| 	oxReturnError(io->field("Int5", &obj->Int5)); | ||||
| 	oxReturnError(io->field("Int6", &obj->Int6)); | ||||
| 	oxReturnError(io->field("Int7", &obj->Int7)); | ||||
| 	oxReturnError(io->field("Int8", &obj->Int8)); | ||||
| 	oxReturnError(io->field("unionIdx", &obj->unionIdx)); | ||||
| 	OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>()); | ||||
| 	OX_RETURN_ERROR(io->field("Bool", &obj->Bool)); | ||||
| 	OX_RETURN_ERROR(io->field("Int", &obj->Int)); | ||||
| 	OX_RETURN_ERROR(io->field("Int1", &obj->Int1)); | ||||
| 	OX_RETURN_ERROR(io->field("Int2", &obj->Int2)); | ||||
| 	OX_RETURN_ERROR(io->field("Int3", &obj->Int3)); | ||||
| 	OX_RETURN_ERROR(io->field("Int4", &obj->Int4)); | ||||
| 	OX_RETURN_ERROR(io->field("Int5", &obj->Int5)); | ||||
| 	OX_RETURN_ERROR(io->field("Int6", &obj->Int6)); | ||||
| 	OX_RETURN_ERROR(io->field("Int7", &obj->Int7)); | ||||
| 	OX_RETURN_ERROR(io->field("Int8", &obj->Int8)); | ||||
| 	OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx)); | ||||
| 	if (io->opType() == ox::OpType::Reflect) { | ||||
| 		oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); | ||||
| 		OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0})); | ||||
| 	} else { | ||||
| 		oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); | ||||
| 		OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); | ||||
| 	} | ||||
| 	oxReturnError(io->field("String", &obj->String)); | ||||
| 	oxReturnError(io->field("List", obj->List, 4)); | ||||
| 	oxReturnError(io->field("Map", &obj->Map)); | ||||
| 	oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	oxReturnError(io->field("Struct", &obj->Struct)); | ||||
| 	return OxError(0); | ||||
| 	OX_RETURN_ERROR(io->field("String", &obj->String)); | ||||
| 	OX_RETURN_ERROR(io->field("List", obj->List, 4)); | ||||
| 	OX_RETURN_ERROR(io->field("Map", &obj->Map)); | ||||
| 	OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct)); | ||||
| 	OX_RETURN_ERROR(io->field("Struct", &obj->Struct)); | ||||
| 	return ox::Error(0); | ||||
| } | ||||
|  | ||||
| TestStruct::TestStruct(TestStruct &&other) noexcept { | ||||
| @@ -184,7 +184,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				oxAssert(testIn.Struct.String      == testOut.Struct.String, "Struct.String value mismatch"); | ||||
| 				oxAssert(testIn.Struct.Bool        == testOut.Struct.Bool, "Struct.Bool value mismatch"); | ||||
|  | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @@ -207,10 +207,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 		   testIn.Union.Int = 93; | ||||
| 		   oxAssert(ox::writeOC(testIn).moveTo(dataBuff), "Data generation failed"); | ||||
| 		   ox::TypeStore typeStore; | ||||
| 		   auto type = ox::buildTypeDef(&typeStore, &testIn); | ||||
| 		   auto type = ox::buildTypeDef(typeStore, testIn); | ||||
| 		   oxAssert(type.error, "Descriptor write failed"); | ||||
| 		   ox::ModelObject testOut; | ||||
| 		   oxReturnError(testOut.setType(type.value)); | ||||
| 		   OX_RETURN_ERROR(testOut.setType(type.value)); | ||||
| 		   oxAssert(ox::readOC(dataBuff, testOut), "Data read failed"); | ||||
| 		   oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); | ||||
| 		   oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); | ||||
| @@ -234,7 +234,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 		   oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); | ||||
| 		   oxAssert(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"); | ||||
| 		   return OxError(0); | ||||
| 		   return ox::Error(0); | ||||
| 		   } | ||||
| 		}, | ||||
|  | ||||
| @@ -257,9 +257,9 @@ const std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 				auto [oc, ocErr] = ox::writeOC(testIn); | ||||
| 				oxAssert(ocErr, "Data generation failed"); | ||||
| 				ox::TypeStore typeStore; | ||||
| 				auto type = ox::buildTypeDef(&typeStore, &testIn); | ||||
| 				auto type = ox::buildTypeDef(typeStore, testIn); | ||||
| 				oxAssert(type.error, "Descriptor write failed"); | ||||
| 				oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(), | ||||
| 				OX_RETURN_ERROR(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(), | ||||
| 					[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, | ||||
| 					   ox::OrganicClawReader *rdr) -> ox::Error { | ||||
| 						auto fieldName = f.fieldName.c_str(); | ||||
| @@ -341,10 +341,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = { | ||||
| 							case ox::PrimitiveType::Union: | ||||
| 								break; | ||||
| 						} | ||||
| 						return OxError(0); | ||||
| 						return ox::Error(0); | ||||
| 					} | ||||
| 				)); | ||||
| 				return OxError(0); | ||||
| 				return ox::Error(0); | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										6
									
								
								deps/ox/src/ox/oc/write.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								deps/ox/src/ox/oc/write.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in | ||||
| 		value(key) = *val; | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { | ||||
| @@ -32,7 +32,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) no | ||||
|  | ||||
| Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept { | ||||
| 	const auto uuidStr = uuid->toString(); | ||||
| 	if (targetValid() && uuidStr.len()) { | ||||
| 	if (targetValid() && uuidStr.size()) { | ||||
| 		value(key) = uuidStr.c_str(); | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
|   | ||||
							
								
								
									
										54
									
								
								deps/ox/src/ox/oc/write.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								deps/ox/src/ox/oc/write.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -8,7 +8,11 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ox/std/def.hpp> | ||||
|  | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| #include <json/json.h> | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
|  | ||||
| #include <ox/model/fieldcounter.hpp> | ||||
| #include <ox/model/modelhandleradaptor.hpp> | ||||
| @@ -42,7 +46,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const int16_t *val) noexcept { | ||||
| @@ -50,7 +54,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const int32_t *val) noexcept { | ||||
| @@ -58,7 +62,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const int64_t *val) noexcept { | ||||
| @@ -66,7 +70,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @@ -75,7 +79,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const uint16_t *val) noexcept { | ||||
| @@ -83,7 +87,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const uint32_t *val) noexcept { | ||||
| @@ -91,7 +95,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(const char *key, const uint64_t *val) noexcept { | ||||
| @@ -99,7 +103,7 @@ class OrganicClawWriter { | ||||
| 				value(key) = *val; | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error field(char const*key, bool const*val) noexcept { | ||||
| @@ -122,8 +126,8 @@ class OrganicClawWriter { | ||||
| 				for (std::size_t i = 0; i < keys.size(); ++i) { | ||||
| 					const auto k = keys[i].c_str(); | ||||
| 					if (k) [[likely]] { | ||||
| 						oxRequireM(value, val->at(k)); | ||||
| 						oxReturnError(handler.field(k, value)); | ||||
| 						OX_REQUIRE_M(value, val->at(k)); | ||||
| 						OX_RETURN_ERROR(handler.field(k, value)); | ||||
| 					} | ||||
| 				} | ||||
| 				value(key) = w.m_json; | ||||
| @@ -134,7 +138,7 @@ class OrganicClawWriter { | ||||
|  | ||||
| 		template<std::size_t L> | ||||
| 		Error field(char const*key, IString<L> const*val) noexcept { | ||||
| 			if (targetValid() && val->len()) { | ||||
| 			if (targetValid() && val->size()) { | ||||
| 				value(key) = val->c_str(); | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| @@ -143,11 +147,11 @@ class OrganicClawWriter { | ||||
|  | ||||
| 		template<std::size_t L> | ||||
| 		Error field(char const*key, BasicString<L> const*val) noexcept { | ||||
| 			if (targetValid() && val->len()) { | ||||
| 			if (targetValid() && val->size()) { | ||||
| 				value(key) = val->c_str(); | ||||
| 			} | ||||
| 			++m_fieldIt; | ||||
| 			return OxError(0); | ||||
| 			return {}; | ||||
| 		} | ||||
|  | ||||
| 		Error fieldCString(const char*, const char *const*val, int len) noexcept; | ||||
| @@ -200,12 +204,14 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n | ||||
| 		OrganicClawWriter w((Json::Value(Json::arrayValue))); | ||||
| 		ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; | ||||
| 		for (std::size_t i = 0; i < len; ++i) { | ||||
| 			oxReturnError(handler.field({}, &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 			OX_RETURN_ERROR(handler.field({}, &val[i])); | ||||
| OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 		} | ||||
| 		value(key) = w.m_json; | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| @@ -225,13 +231,13 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept { | ||||
| 	} else if (val && targetValid()) { | ||||
| 		OrganicClawWriter w; | ||||
| 		ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; | ||||
| 		oxReturnError(model(&handler, val)); | ||||
| 		OX_RETURN_ERROR(model(&handler, val)); | ||||
| 		if (!w.m_json.empty() || m_json.isArray()) { | ||||
| 			value(key) = w.m_json; | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename U, bool force> | ||||
| @@ -239,36 +245,40 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep | ||||
| 	if (targetValid()) { | ||||
| 		OrganicClawWriter w(val.idx()); | ||||
| 		ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; | ||||
| 		oxReturnError(model(&handler, val.get())); | ||||
| 		OX_RETURN_ERROR(model(&handler, val.get())); | ||||
| 		if (!w.m_json.isNull()) { | ||||
| 			value(key) = w.m_json; | ||||
| 		} | ||||
| 	} | ||||
| 	++m_fieldIt; | ||||
| 	return OxError(0); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| Result<ox::Buffer> writeOC(const auto &val) noexcept { | ||||
| 	OrganicClawWriter writer; | ||||
| 	ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); | ||||
| 	oxReturnError(model(&handler, &val)); | ||||
| 	OX_RETURN_ERROR(model(&handler, &val)); | ||||
| 	Json::StreamWriterBuilder const jsonBuilder; | ||||
| 	const auto str = Json::writeString(jsonBuilder, writer.m_json); | ||||
| 	Result<Buffer> buff; | ||||
| 	buff.value.resize(str.size() + 1); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 	memcpy(buff.value.data(), str.data(), str.size() + 1); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	return buff; | ||||
| } | ||||
|  | ||||
| Result<ox::String> writeOCString(const auto &val) noexcept { | ||||
| 	OrganicClawWriter writer; | ||||
| 	ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); | ||||
| 	oxReturnError(model(&handler, &val)); | ||||
| 	OX_RETURN_ERROR(model(&handler, &val)); | ||||
| 	Json::StreamWriterBuilder const jsonBuilder; | ||||
| 	const auto str = Json::writeString(jsonBuilder, writer.m_json); | ||||
| 	Result<ox::String> buff; | ||||
| 	buff.value.resize(str.size()); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_BEGIN | ||||
| 	memcpy(buff.value.data(), str.data(), str.size() + 1); | ||||
| 	OX_ALLOW_UNSAFE_BUFFERS_END | ||||
| 	return buff; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -63,7 +63,7 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT | ||||
| 	template<typename T> | ||||
| 	constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept { | ||||
| 		for (std::size_t i = 0; i < cnt; ++i) { | ||||
| 			oxReturnError(field(nullptr, &val[i])); | ||||
| 			OX_RETURN_ERROR(field(nullptr, &val[i])); | ||||
| 		} | ||||
| 		return {}; | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/preloader/platspecs.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/preloader/platspecs.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										2
									
								
								deps/ox/src/ox/preloader/preloader.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/ox/src/ox/preloader/preloader.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|   | ||||
							
								
								
									
										70
									
								
								deps/ox/src/ox/preloader/preloader.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								deps/ox/src/ox/preloader/preloader.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -162,7 +162,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::UnionView | ||||
| 	if (!unionCheckAndIt()) { | ||||
| 		return {}; | ||||
| 	} | ||||
| 	oxReturnError(pad(val.get())); | ||||
| 	OX_RETURN_ERROR(pad(val.get())); | ||||
| 	m_unionIdx.emplace_back(val.idx()); | ||||
| 	const auto err = preload<PlatSpec, U>(this, val.get()); | ||||
| 	m_unionIdx.pop_back(); | ||||
| @@ -175,13 +175,13 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const T *val) | ||||
| 	if (!unionCheckAndIt()) { | ||||
| 		return {}; | ||||
| 	} | ||||
| 	oxReturnError(pad(val)); | ||||
| 	OX_RETURN_ERROR(pad(val)); | ||||
| 	if constexpr(ox::is_integral_v<T>) { | ||||
| 		return ox::serialize(m_writer, PlatSpec::correctEndianness(*val)); | ||||
| 	} else if constexpr(ox::is_pointer_v<T>) { | ||||
| 		const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart; | ||||
| 		oxReturnError(field(name, *val)); | ||||
| 		oxReturnError(endAlloc()); | ||||
| 		OX_RETURN_ERROR(field(name, *val)); | ||||
| 		OX_RETURN_ERROR(endAlloc()); | ||||
| 		return ox::serialize(m_writer, PlatSpec::correctEndianness(a)); | ||||
| 	} else if constexpr(ox::isVector_v<T>) { | ||||
| 		return fieldVector(name, val); | ||||
| @@ -211,19 +211,19 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::BasicStri | ||||
| 		.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), | ||||
| 		.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), | ||||
| 	}; | ||||
| 	oxReturnError(pad(&vecVal)); | ||||
| 	OX_RETURN_ERROR(pad(&vecVal)); | ||||
| 	const auto restore = m_writer.tellp(); | ||||
| 	std::size_t a = 0; | ||||
| 	if (sz && sz >= SmallStringSize) { | ||||
| 		oxReturnError(ox::allocate(m_writer, sz).moveTo(a)); | ||||
| 		OX_RETURN_ERROR(ox::allocate(m_writer, sz).moveTo(a)); | ||||
| 	} else { | ||||
| 		a = restore; | ||||
| 	} | ||||
| 	vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart); | ||||
| 	oxReturnError(m_writer.seekp(a)); | ||||
| 	oxReturnError(m_writer.write(val->data(), sz)); | ||||
| 	oxReturnError(m_writer.seekp(restore)); | ||||
| 	oxReturnError(serialize(m_writer, vecVal)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(a)); | ||||
| 	OX_RETURN_ERROR(m_writer.write(val->data(), sz)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(restore)); | ||||
| 	OX_RETURN_ERROR(serialize(m_writer, vecVal)); | ||||
| 	m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items); | ||||
| 	return {}; | ||||
| } | ||||
| @@ -234,12 +234,12 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const ox::Arra | ||||
| 	if (!unionCheckAndIt()) { | ||||
| 		return {}; | ||||
| 	} | ||||
| 	oxReturnError(pad(&(*val)[0])); | ||||
| 	OX_RETURN_ERROR(pad(&(*val)[0])); | ||||
| 	// serialize the Array elements | ||||
| 	if constexpr(sz) { | ||||
| 		m_unionIdx.emplace_back(-1); | ||||
| 		for (std::size_t i = 0; i < val->size(); ++i) { | ||||
| 			oxReturnError(this->interface()->field(name, &(*val)[i])); | ||||
| 			OX_RETURN_ERROR(this->interface()->field(name, &(*val)[i])); | ||||
| 		} | ||||
| 		m_unionIdx.pop_back(); | ||||
| 	} | ||||
| @@ -253,11 +253,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std: | ||||
| 		return {}; | ||||
| 	} | ||||
| 	if (cnt) { | ||||
| 		oxReturnError(pad(*val)); | ||||
| 		OX_RETURN_ERROR(pad(*val)); | ||||
| 		// serialize the array | ||||
| 		m_unionIdx.emplace_back(-1); | ||||
| 		for (std::size_t i = 0; i < cnt; ++i) { | ||||
| 			oxReturnError(this->interface()->field(nullptr, &val[i])); | ||||
| 			OX_RETURN_ERROR(this->interface()->field(nullptr, &val[i])); | ||||
| 		} | ||||
| 		m_unionIdx.pop_back(); | ||||
| 	} | ||||
| @@ -267,11 +267,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std: | ||||
| template<typename PlatSpec> | ||||
| constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept { | ||||
| 	m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp())); | ||||
| 	oxReturnError(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	auto const padding = calcPadding(align); | ||||
| 	oxRequireM(a, ox::allocate(m_writer, sz + padding)); | ||||
| 	OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding)); | ||||
| 	a += padding; | ||||
| 	oxReturnError(m_writer.seekp(a)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(a)); | ||||
| 	m_allocStart.push_back(a); | ||||
| 	return a; | ||||
| } | ||||
| @@ -280,11 +280,11 @@ template<typename PlatSpec> | ||||
| constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc( | ||||
| 		std::size_t sz, size_t align, std::size_t restore) noexcept { | ||||
| 	m_allocStack.emplace_back(restore, ox::ios_base::beg); | ||||
| 	oxReturnError(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	auto const padding = calcPadding(align); | ||||
| 	oxRequireM(a, ox::allocate(m_writer, sz + padding)); | ||||
| 	OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding)); | ||||
| 	a += padding; | ||||
| 	oxReturnError(m_writer.seekp(a)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(a)); | ||||
| 	m_allocStart.push_back(a); | ||||
| 	return a; | ||||
| } | ||||
| @@ -295,7 +295,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept { | ||||
| 		return m_writer.seekp(0, ox::ios_base::end); | ||||
| 	} | ||||
| 	const auto &si = *m_allocStack.back().unwrap(); | ||||
| 	oxReturnError(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir)); | ||||
| 	m_allocStack.pop_back(); | ||||
| 	m_allocStart.pop_back(); | ||||
| 	return {}; | ||||
| @@ -304,12 +304,12 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept { | ||||
| template<typename PlatSpec> | ||||
| constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept { | ||||
| 	for (const auto &p : m_ptrs) { | ||||
| 		oxReturnError(m_writer.seekp(p.loc)); | ||||
| 		OX_RETURN_ERROR(m_writer.seekp(p.loc)); | ||||
| 		const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>( | ||||
| 				static_cast<typename PlatSpec::PtrType>(p.value + offset)); | ||||
| 		oxReturnError(ox::serialize(m_writer, val)); | ||||
| 		OX_RETURN_ERROR(ox::serialize(m_writer, val)); | ||||
| 	} | ||||
| 	oxReturnError(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| @@ -354,39 +354,39 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector( | ||||
| template<typename PlatSpec> | ||||
| constexpr ox::Error Preloader<PlatSpec>::fieldVector( | ||||
| 		StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept { | ||||
| 	oxReturnError(pad(&vecVal)); | ||||
| 	OX_RETURN_ERROR(pad(&vecVal)); | ||||
| 	const auto vecValPt = m_writer.tellp(); | ||||
| 	// serialize the Vector elements | ||||
| 	if (val->size()) { | ||||
| 		const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size(); | ||||
| 		const auto align = alignOf<PlatSpec>((*val)[0]); | ||||
| 		oxReturnError(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 		OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end)); | ||||
| 		auto const padding = calcPadding(align); | ||||
| 		oxRequireM(p, ox::allocate(m_writer, sz + padding)); | ||||
| 		OX_REQUIRE_M(p, ox::allocate(m_writer, sz + padding)); | ||||
| 		p += padding; | ||||
| 		oxReturnError(m_writer.seekp(p)); | ||||
| 		OX_RETURN_ERROR(m_writer.seekp(p)); | ||||
| 		m_unionIdx.emplace_back(-1); | ||||
| 		for (std::size_t i = 0; i < val->size(); ++i) { | ||||
| 			oxReturnError(this->interface()->field(nullptr, &val->operator[](i))); | ||||
| 			OX_RETURN_ERROR(this->interface()->field(nullptr, &val->operator[](i))); | ||||
| 		} | ||||
| 		m_unionIdx.pop_back(); | ||||
| 		vecVal.items = PlatSpec::correctEndianness( | ||||
| 				static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart)); | ||||
| 		oxReturnError(m_writer.seekp(vecValPt)); | ||||
| 		OX_RETURN_ERROR(m_writer.seekp(vecValPt)); | ||||
| 	} else { | ||||
| 		vecVal.items = 0; | ||||
| 	} | ||||
| 	// serialize the Vector | ||||
| 	oxReturnError(serialize(m_writer, vecVal)); | ||||
| 	OX_RETURN_ERROR(serialize(m_writer, vecVal)); | ||||
| 	m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items); | ||||
| 	return {}; | ||||
| } | ||||
|  | ||||
| template<typename PlatSpec> | ||||
| constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept { | ||||
| 	oxReturnError(pad(&(*val)[0])); | ||||
| 	OX_RETURN_ERROR(pad(&(*val)[0])); | ||||
| 	for (auto const&v : *val) { | ||||
| 		oxReturnError(this->interface()->field({}, &v)); | ||||
| 		OX_RETURN_ERROR(this->interface()->field({}, &v)); | ||||
| 	} | ||||
| 	return {}; | ||||
| } | ||||
| @@ -405,7 +405,7 @@ constexpr size_t Preloader<PlatSpec>::calcPadding(size_t align) const noexcept { | ||||
|  | ||||
| template<typename PlatSpec, typename T> | ||||
| constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept { | ||||
| 	oxReturnError(model(pl->interface(), obj)); | ||||
| 	OX_RETURN_ERROR(model(pl->interface(), obj)); | ||||
| 	return pl->pad(obj); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										6
									
								
								deps/ox/src/ox/preloader/sizecatcher.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								deps/ox/src/ox/preloader/sizecatcher.hpp
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright 2015 - 2024 gary@drinkingtea.net | ||||
|  * Copyright 2015 - 2025 gary@drinkingtea.net | ||||
|  * | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
| @@ -74,7 +74,7 @@ template<typename T, bool force> | ||||
| constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept { | ||||
| 	pad(val.get()); | ||||
| 	UnionSizeCatcher<PlatSpec> sc; | ||||
| 	oxReturnError(model(sc.interface(), val.get())); | ||||
| 	OX_RETURN_ERROR(model(sc.interface(), val.get())); | ||||
| 	m_size += sc.size(); | ||||
| 	return {}; | ||||
| } | ||||
| @@ -91,7 +91,7 @@ template<typename PlatSpec> | ||||
| template<typename T> | ||||
| constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept { | ||||
| 	for (std::size_t i = 0; i < cnt; ++i) { | ||||
| 		oxReturnError(field("", &val[i])); | ||||
| 		OX_RETURN_ERROR(field("", &val[i])); | ||||
| 	} | ||||
| 	return {}; | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user