Compare commits

..

84 Commits

Author SHA1 Message Date
a863bfc181 [nostalgia/studio] Update version to d2024.12.0
All checks were successful
Build / build (push) Successful in 3m20s
2024-12-21 19:27:00 -06:00
a75c4a11d3 [nfde] Address CMake warning, remove unwanted logging
All checks were successful
Build / build (push) Successful in 2m45s
2024-12-21 17:07:23 -06:00
347a165762 [sample_project] Update type descriptors
All checks were successful
Build / build (push) Successful in 2m55s
2024-12-21 02:45:24 -06:00
fd64bfae13 [keel] Fix a use after free, cleanup
Some checks are pending
Build / build (push) Waiting to run
2024-12-21 02:42:19 -06:00
aaeec20ac9 [nostalgia/player] Fix build 2024-12-21 02:42:05 -06:00
37030f9c11 [keel] Cleanup pack tool 2024-12-21 02:41:56 -06:00
462f2bca4c [nostalgia,olympic] Change macro names to comply with broader conventions 2024-12-21 02:41:19 -06:00
dc72500b98 [glutils] Change macro names to comply with broader conventions 2024-12-18 22:04:39 -06:00
962fe8bc22 [ox] Change macro names to comply with broader conventions 2024-12-18 22:04:25 -06:00
305eb62647 [studio] Fix build
Some checks are pending
Build / build (push) Waiting to run
2024-12-18 21:41:15 -06:00
4754359a21 [ox/std] Cleanup Vec2
Some checks failed
Build / build (push) Has been cancelled
2024-12-15 01:26:41 -06:00
dc07f3d58b [studio] Change FilePicker consturctor to take StringParams 2024-12-15 01:20:29 -06:00
fcdcfd10d1 [ox/std] Run liccor
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-14 14:33:43 -06:00
b74f6a7ace [studio,turbine] Run liccor 2024-12-14 14:33:06 -06:00
ac7e5be187 [ox] Remove OxException
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-14 00:40:05 -06:00
ed910c0beb [nostalgia/core/studio/tilesheeteditor] Fix access overflow on out of bounds Fill command
All checks were successful
Build / build (push) Successful in 2m51s
2024-12-13 22:24:58 -06:00
345fb03857 [ox] Remove OxError 2024-12-13 22:06:47 -06:00
9881253f2a [glutils] Cleanup OxError 2024-12-13 22:06:26 -06:00
96d27eecd1 [nostalgia,olympic] Cleanup 2024-12-13 22:00:03 -06:00
28ebe93b77 [ox/std] Make source_location::current only init if valid
All checks were successful
Build / build (push) Successful in 2m52s
2024-12-12 23:13:39 -06:00
e849e7a3dd [ox/std] Add source_location
Some checks failed
Build / build (push) Has been cancelled
2024-12-12 23:09:01 -06:00
e6777b0ad7 [cityhash] Add install rule 2024-12-12 22:36:09 -06:00
c488c336de [turbine/glfw] Fix mandatoryRefreshPeriodEnd tracking
All checks were successful
Build / build (push) Successful in 2m54s
2024-12-11 22:13:28 -06:00
003f97201f [turbine/glfw] Move MandatoryRefreshPeriod to config.hpp
All checks were successful
Build / build (push) Successful in 2m45s
2024-12-10 23:29:50 -06:00
d85a10af84 [nostalgia/core/studio] Cleanup 2024-12-10 23:29:21 -06:00
ff05d860c4 [turbine/glfw] Replace uninterruptedRefreshes with mandatoryRefreshPeriodEnd
Some checks failed
Build / build (push) Has been cancelled
2024-12-10 01:49:20 -06:00
7679403742 [turbine] Add init wrapper that takes FS path 2024-12-06 23:20:30 -06:00
c51a45e1ba [olympic] Cleanup 2024-12-06 00:22:33 -06:00
a6e24ff2b6 [ox/std] Add CString type alias 2024-12-06 00:20:03 -06:00
e0ec9e0c5f [nostalgia,olympic] Move olympic::run to global namespace
All checks were successful
Build / build (push) Successful in 2m34s
2024-12-06 00:13:10 -06:00
9a42a9b9d9 [nfde] Fix Windows warnings 2024-12-06 00:12:38 -06:00
03a05c511e Merge commit '4ccdfc3a6e5bd501968903a01f7d8141b6f88375'
All checks were successful
Build / build (push) Successful in 2m31s
2024-12-04 19:55:17 -06:00
bd91137d27 [nostalgia,olympic] Fix pack tool build for Windows 2024-12-02 21:10:52 -06:00
161640fa11 [nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 2m46s
2024-12-02 19:58:05 -06:00
2b7d12945e [nostalgia/core/studio] Fix MSVC build 2024-12-01 19:42:29 -06:00
e42126c956 [nostalgia/core] Improve TileSheet validation, add repair
All checks were successful
Build / build (push) Successful in 2m40s
2024-12-01 15:47:49 -06:00
36942cca18 [nostalgia,olympic] Replace SpanView with Span<const T>
All checks were successful
Build / build (push) Successful in 2m36s
2024-12-01 08:41:20 -06:00
b14f1d5000 [ox] Replace SpanView with Span<const T> 2024-12-01 08:41:08 -06:00
1bf4f246c2 [applib] Make run take args as a SpanView 2024-11-28 00:51:42 -06:00
edda8e010e [ox/clargs] Add constructor that takes a SpanView 2024-11-28 00:51:02 -06:00
3308b4dd72 [ox/std] Add missing + and += operators to Span
All checks were successful
Build / build (push) Successful in 2m38s
2024-11-27 00:17:37 -06:00
27f4703a9a [teagba] Suppress warnings for unsafe buffers 2024-11-27 00:15:59 -06:00
6af00d9a2e [nostalgia] Enable warnings for unsafe buffers 2024-11-27 00:14:57 -06:00
86b9f9316e [olympic] Enable warnings for unsafe buffers 2024-11-26 23:58:11 -06:00
a0ed1b3f62 [ox/std] Fix Span raw array constructor 2024-11-26 23:57:41 -06:00
8dad624b21 [studio/applib] Cleanup 2024-11-26 23:32:32 -06:00
dc6605fd48 [keel] Add missing error checking to pack 2024-11-26 23:32:15 -06:00
c78d3cf638 [ox] Add more unsafe buffer exceptions 2024-11-26 23:31:34 -06:00
cee4f65d4a [ox/std] Replace an unsafe buffer
All checks were successful
Build / build (push) Successful in 2m38s
2024-11-26 22:31:20 -06:00
cd3eeeef14 [ox/fs] Suppress unsafe buffer warnings 2024-11-26 22:30:57 -06:00
287d42f2b9 [ox/clargs] Cleanup
All checks were successful
Build / build (push) Successful in 2m41s
2024-11-26 22:08:36 -06:00
dbbaaa46b9 [ox/clargs] Enable unsafe buffer warnings
Some checks failed
Build / build (push) Has been cancelled
2024-11-26 22:06:50 -06:00
9b8a8c4e46 [ox/std] Enable unsafe buffer warnings 2024-11-26 21:59:26 -06:00
e44fa288fd [cityhash] Add pragmas to ignore unsafe buffer warnings 2024-11-26 21:58:39 -06:00
e13c6e812b [ox/std] Remove raw char* CharBufferWriter constructor 2024-11-26 20:48:13 -06:00
cb55b31afa [ox/std] Cleanup 2024-11-26 20:43:43 -06:00
ab3f9e1627 [ox/std] Make Span access check message consistent with other messages 2024-11-26 20:43:20 -06:00
8f25ef96ff [ox/std] Make CharBufferWriter constructor take a Span 2024-11-26 20:42:33 -06:00
e13eebaf0b [ox/std] Cleanup an unsafe buffer 2024-11-26 20:38:00 -06:00
114f5c6685 [ox/std] Add overflow checking to SpanIterator
All checks were successful
Build / build (push) Successful in 2m36s
2024-11-19 01:09:48 -06:00
df44fe235b [keel] Cleanup
All checks were successful
Build / build (push) Successful in 2m42s
2024-11-15 19:59:42 -06:00
72f4db3d5e [nostalgia/core/studio] Fix paste command to never paste beyond target dimensions
All checks were successful
Build / build (push) Successful in 2m40s
2024-11-15 01:39:57 -06:00
8a9ff971a1 [nostalgia/core] Fix resizeSubsheet to work for both growing and shrinking 2024-11-15 01:09:48 -06:00
5a8da59df1 [keel] Fix readAsset to actually return asset 2024-11-15 01:01:31 -06:00
afa3a13d41 [keel] Cleanup 2024-11-14 21:23:42 -06:00
6522cf8a43 [keel] Add ensureValid call to readAsset 2024-11-14 21:17:41 -06:00
f772e48b36 [ox] Add Vector/Array/Span overflow checking 2024-11-14 21:08:38 -06:00
13bfe88195 [nostalgia/core] Fix resizeSubsheet array overflow 2024-11-14 19:59:58 -06:00
5025475414 Merge commit '9e11019b87ba27d1dac9e097dc212a126e404218' 2024-11-01 22:23:08 -05:00
3c7652efc2 [nostalgia/core/studio] Fix PaletteEditor to handle Palettes with 0 pages
All checks were successful
Build / build (push) Successful in 2m55s
2024-10-28 20:57:34 -05:00
941bc71348 [studio] Fix NewMenu name input 2024-10-28 20:57:34 -05:00
bfe890ae00 [ox] Fix typo in docs 2024-10-08 23:04:49 -05:00
ab5bc1adb6 [ox/std] Remove oxRequireT and oxRequireMT 2024-10-06 06:16:14 -05:00
abf7548ab5 [nostalgia/core] Add missing include 2024-10-04 21:36:26 -05:00
e2682b5ef7 [studio/modlib] Add missing include 2024-10-04 21:35:08 -05:00
792ad41499 [nostalgia] Remove .vs dir 2024-10-04 18:51:36 -05:00
e4ae23e114 [olympic/developer-handbook] Remove Ox submodules from project structure
All checks were successful
Build / build (push) Successful in 2m31s
2024-10-04 01:22:21 -05:00
67187d5ec5 [olympic/developer-handbook] Elaborate more on exception usage 2024-10-04 01:18:25 -05:00
3271a37115 [ox] Add Project Structure section to docs
All checks were successful
Build / build (push) Successful in 2m36s
2024-10-04 01:15:17 -05:00
ea9f50de8d [olympic] Add error handling back to developer-handbook.md 2024-10-04 01:13:45 -05:00
ea3c5e03fb [olympic] Remove Ox from developer-handbook.md 2024-10-04 01:00:02 -05:00
c8c4177d60 [ox] Add ox-docs.md 2024-10-04 00:59:23 -05:00
76b540e3b8 [nostalgia/core] Cleanup, add missing FileAddress wrapper function
All checks were successful
Build / build (push) Successful in 2m32s
2024-10-03 22:48:26 -05:00
2062748676 [keel] Cleanup 2024-10-03 22:39:48 -05:00
238 changed files with 3789 additions and 3344 deletions

View File

@ -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"
]
}
]
}

View File

@ -83,13 +83,13 @@ static ox::Result<GLShader> buildShader(
ox::Vector<char> errMsg(ox::units::KB); ox::Vector<char> errMsg(ox::units::KB);
glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data()); glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data());
oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data()); oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data());
return OxError(1, "shader compile error"); return ox::Error(1, "shader compile error");
} }
return shader; return shader;
} }
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept { ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
oxRequireM(program, buildShaderProgram( OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader, src.vertShader,
src.fragShader, src.fragShader,
src.geomShader)); src.geomShader));
@ -127,13 +127,13 @@ ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&frag, ox::CStringView const&frag,
ox::CStringView const&geo) noexcept { ox::CStringView const&geo) noexcept {
GLProgram prgm(glCreateProgram()); GLProgram prgm(glCreateProgram());
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad")); OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs); glAttachShader(prgm, vs);
if (geo.c_str() && geo.bytes() != 0) { if (geo.c_str() && geo.bytes() != 0) {
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad")); OX_REQUIRE(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
glAttachShader(prgm, gs); glAttachShader(prgm, gs);
} }
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad")); OX_REQUIRE(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
glAttachShader(prgm, fs); glAttachShader(prgm, fs);
glLinkProgram(prgm); glLinkProgram(prgm);
return prgm; return prgm;

View File

@ -10,7 +10,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF) option(BUILD_SHARED_LIBS "Build a shared library instead of static" OFF)
endif() endif()
option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT}) option(NFD_BUILD_TESTS "Build tests for nfd" ${nfd_ROOT_PROJECT})
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT}) # DrinkingTea: begin
if(NOT DEFINED NFD_INSTALL)
option(NFD_INSTALL "Generate install target for nfd" ${nfd_ROOT_PROJECT})
endif()
# DrinkingTea: end
set(nfd_PLATFORM Undefined) set(nfd_PLATFORM Undefined)
if(WIN32) if(WIN32)
@ -21,7 +25,9 @@ elseif(UNIX AND NOT APPLE)
set(nfd_PLATFORM PLATFORM_UNIX) set(nfd_PLATFORM PLATFORM_UNIX)
endif() endif()
message("nfd Platform: ${nfd_PLATFORM}") # DrinkingTea: begin
#message("nfd Platform: ${nfd_PLATFORM}")
# DrinkingTea: end
set(nfd_COMPILER Undefined) set(nfd_COMPILER Undefined)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
@ -33,7 +39,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C
set(nfd_COMPILER COMPILER_GNU) set(nfd_COMPILER COMPILER_GNU)
endif() endif()
message("nfd Compiler: ${nfd_COMPILER}") # DrinkingTea: begin
#message("nfd Compiler: ${nfd_COMPILER}")
# DrinkingTea: end
# Use latest C++ by default (should be the best one), but let user override it # Use latest C++ by default (should be the best one), but let user override it
if(NOT DEFINED CMAKE_CXX_STANDARD) if(NOT DEFINED CMAKE_CXX_STANDARD)

View File

@ -201,7 +201,7 @@ nfdresult_t SetDefaultExtension(::IFileDialog* fileOpenDialog,
} }
if (*p_spec) { if (*p_spec) {
// multiple file extensions for this type (need to allocate memory) // 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' // allocate one more char space for the '\0'
nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1)); nfdnchar_t* extnBuf = NFDi_Malloc<nfdnchar_t>(sizeof(nfdnchar_t) * (numChars + 1));
if (!extnBuf) { 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); int charsNeeded = MultiByteToWideChar(CP_UTF8, 0, inStr, -1, nullptr, 0);
assert(charsNeeded); 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) { if (!tmp_outStr) {
return NFD_ERROR; 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); int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, inStr, -1, nullptr, 0, nullptr, nullptr);
assert(bytesNeeded); 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) { if (!tmp_outStr) {
return NFD_ERROR; return NFD_ERROR;
} }

View File

@ -9,9 +9,6 @@ set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON) 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_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@ -28,3 +25,10 @@ endif()
add_library(CityHash INTERFACE) add_library(CityHash INTERFACE)
target_include_directories(CityHash INTERFACE include) target_include_directories(CityHash INTERFACE include)
install(
DIRECTORY
include/cityhash
DESTINATION
include
)

View File

@ -104,6 +104,11 @@ using size_t = decltype(alignof(int));
#endif #endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
namespace cityhash::detail { namespace cityhash::detail {
template<typename T> 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_ #endif // CITY_HASH_H_

478
deps/ox/ox-docs.md vendored Normal file
View 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);
}
```

View File

@ -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( add_library(
OxClArgs OxClArgs

View File

@ -11,16 +11,18 @@
namespace ox { namespace ox {
ClArgs::ClArgs(int argc, const char **args) noexcept { ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<size_t>(argc)}) {}
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
auto arg = String(args[i]); ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]);
if (arg[0] == '-') { if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) { while (arg[0] == '-' && arg.len()) {
arg = arg.substr(1); arg = substr(arg, 1);
} }
m_bools[arg] = true; m_bools[arg] = true;
// parse additional arguments // parse additional arguments
if (i < static_cast<unsigned>(argc) && args[i + 1]) { if (i < args.size() && args[i + 1]) {
auto val = String(args[i + 1]); auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') { if (val.len() && val[i] != '-') {
if (val == "false") { if (val == "false") {
@ -53,17 +55,17 @@ int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
} }
Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept { Result<bool> ClArgs::getBool(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_bools.at(arg)); OX_REQUIRE(out, m_bools.at(arg));
return *out; return *out;
} }
Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept { Result<String> ClArgs::getString(ox::StringViewCR argName) const noexcept {
oxRequire(out, m_strings.at(argName)); OX_REQUIRE(out, m_strings.at(argName));
return *out; return *out;
} }
Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept { Result<int> ClArgs::getInt(ox::StringViewCR arg) const noexcept {
oxRequire(out, m_ints.at(arg)); OX_REQUIRE(out, m_ints.at(arg));
return *out; return *out;
} }

View File

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <ox/std/hashmap.hpp> #include <ox/std/hashmap.hpp>
#include <ox/std/span.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
namespace ox { namespace ox {
@ -22,6 +23,8 @@ class ClArgs {
public: public:
ClArgs(int argc, const char **args) noexcept; ClArgs(int argc, const char **args) noexcept;
ClArgs(ox::SpanView<const char*> args) noexcept;
[[nodiscard]] [[nodiscard]]
bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept; bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept;

View File

@ -18,7 +18,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
size_t outSz{}; size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1; auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
buffRaw += fmtSz; buffRaw += fmtSz;
@ -26,7 +26,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += fmtSz; outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1; auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
buffRaw += s2Size; buffRaw += s2Size;
@ -34,7 +34,7 @@ ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
outSz += s2Size; outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1; auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
buffRaw += s3Size; buffRaw += s3Size;
@ -48,7 +48,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffLen = buff.size(); auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen); const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return ox::Error(1, "Could not read Claw header");
} }
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw); auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
StringView const fmt(buffRaw, s1Size); StringView const fmt(buffRaw, s1Size);
@ -57,7 +57,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s2End = ox::strchr(buffRaw, ';', buffLen); auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return ox::Error(2, "Could not read Claw header");
} }
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw); auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
StringView const typeName(buffRaw, s2Size); StringView const typeName(buffRaw, s2Size);
@ -66,7 +66,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto const s3End = ox::strchr(buffRaw, ';', buffLen); auto const s3End = ox::strchr(buffRaw, ';', buffLen);
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return ox::Error(3, "Could not read Claw header");
} }
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
StringView const versionStr(buffRaw, s3Size); StringView const versionStr(buffRaw, s3Size);
@ -78,7 +78,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} else if (fmt == "O1") { } else if (fmt == "O1") {
hdr.fmt = ClawFormat::Organic; hdr.fmt = ClawFormat::Organic;
} else { } else {
return OxError(4, "Claw format does not match any supported format/version combo"); return ox::Error(4, "Claw format does not match any supported format/version combo");
} }
hdr.typeName = typeName; hdr.typeName = typeName;
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion); std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
@ -88,26 +88,26 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
} }
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept { Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
return {{header.data, header.dataSize}}; return {{header.data, header.dataSize}};
} }
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept { Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
auto const [t, tdErr] = ts.getLoad( auto const [t, tdErr] = ts.getLoad(
header.typeName, header.typeVersion, header.typeParams); header.typeName, header.typeVersion, header.typeParams);
if (tdErr) { if (tdErr) {
return OxError(3, "Could not load type descriptor"); return ox::Error(3, "Could not load type descriptor");
} }
ModelObject obj; ModelObject obj;
oxReturnError(obj.setType(t)); OX_RETURN_ERROR(obj.setType(t));
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
{ {
ox::BufferReader br({header.data, header.dataSize}); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
} }
case ClawFormat::Organic: case ClawFormat::Organic:
@ -115,16 +115,16 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader({header.data, header.dataSize}); OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); OX_RETURN_ERROR(model(&handler, &obj));
return obj; return obj;
#else #else
break; break;
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -40,12 +40,12 @@ Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
template<typename T> template<typename T>
Error readClaw(ox::BufferView buff, T &val) { Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff)); OX_REQUIRE(header, readClawHeader(buff));
if (header.typeName != getModelTypeName<T>()) { if (header.typeName != getModelTypeName<T>()) {
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); return ox::Error(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
} }
if (header.typeVersion != getModelTypeVersion<T>()) { if (header.typeVersion != getModelTypeVersion<T>()) {
return OxError(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch"); return ox::Error(Error_ClawTypeVersionMismatch, "Claw Read: Type Version mismatch");
} }
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
@ -65,15 +65,15 @@ Error readClaw(ox::BufferView buff, T &val) {
#endif #endif
} }
case ClawFormat::None: case ClawFormat::None:
return OxError(1); return ox::Error(1);
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
Result<T> readClaw(ox::BufferView buff) { Result<T> readClaw(ox::BufferView buff) {
Result<T> val; Result<T> val;
oxReturnError(readClaw(buff, val.value)); OX_RETURN_ERROR(readClaw(buff, val.value));
return val; return val;
} }

View File

@ -62,45 +62,45 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
int unionIdx = 0; int unionIdx = 0;
if constexpr(T::opType() != ox::OpType::Reflect) { if constexpr(T::opType() != ox::OpType::Reflect) {
unionIdx = obj->unionIdx; unionIdx = obj->unionIdx;
} }
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
static std::map<ox::StringView, ox::Error(*)()> tests = { static std::map<ox::StringView, ox::Error(*)()> tests = {
@ -114,7 +114,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
oxAssert(ch.typeVersion == 2, "Type version wrong"); oxAssert(ch.typeVersion == 2, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -126,7 +126,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
oxAssert(ch.typeVersion == 3, "Type version wrong"); oxAssert(ch.typeVersion == 3, "Type version wrong");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -134,7 +134,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3"); constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1})); OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
oxExpect(actual, expected); oxExpect(actual, expected);
return ox::Error{}; return ox::Error{};
} }
@ -145,8 +145,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
// This test doesn't confirm much, but it does show that the writer // This test doesn't confirm much, but it does show that the writer
// doesn't segfault // doesn't segfault
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal)); OX_RETURN_ERROR(ox::writeClaw(ts, ox::ClawFormat::Metal));
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -191,7 +191,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -39,7 +39,7 @@ struct TypeInfoCatcher {
} }
constexpr Error field(...) noexcept { constexpr Error field(...) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() { static constexpr auto opType() {
@ -76,21 +76,21 @@ template<typename T>
ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept { ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept {
switch (fmt) { switch (fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
oxReturnError(write(writer, "M2;")); OX_RETURN_ERROR(write(writer, "M2;"));
break; break;
case ClawFormat::Organic: case ClawFormat::Organic:
oxReturnError(write(writer, "O1;")); OX_RETURN_ERROR(write(writer, "O1;"));
break; break;
default: default:
return OxError(1); return ox::Error(1);
} }
oxReturnError(write(writer, detail::getTypeName(t))); OX_RETURN_ERROR(write(writer, detail::getTypeName(t)));
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
const auto tn = detail::getTypeVersion(t); const auto tn = detail::getTypeVersion(t);
if (tn > -1) { if (tn > -1) {
oxReturnError(ox::writeItoa(tn, writer)); OX_RETURN_ERROR(ox::writeItoa(tn, writer));
} }
oxReturnError(writer.put(';')); OX_RETURN_ERROR(writer.put(';'));
return {}; return {};
} }
@ -102,19 +102,19 @@ Result<Buffer> writeClaw(
std::size_t buffReserveSz = 2 * units::KB) noexcept { std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer out(buffReserveSz); Buffer out(buffReserveSz);
BufferWriter bw(&out, 0); BufferWriter bw(&out, 0);
oxReturnError(detail::writeClawHeader(bw, &t, fmt)); OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt));
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
if (fmt == ClawFormat::Metal) { if (fmt == ClawFormat::Metal) {
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
} else if (fmt == ClawFormat::Organic) { } else if (fmt == ClawFormat::Organic) {
oxRequire(data, writeOC(t)); OX_REQUIRE(data, writeOC(t));
oxReturnError(bw.write(data.data(), data.size())); OX_RETURN_ERROR(bw.write(data.data(), data.size()));
} }
#else #else
if (fmt != ClawFormat::Metal) { if (fmt != ClawFormat::Metal) {
return OxError(1, "OC is not supported in this build"); return ox::Error(1, "OC is not supported in this build");
} }
oxReturnError(writeMC(bw, t)); OX_RETURN_ERROR(writeMC(bw, t));
#endif #endif
out.resize(bw.tellp()); out.resize(bw.tellp());
return out; return out;

View File

@ -57,7 +57,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype(f(args...))>::value) { if constexpr(detail::isError<decltype(f(args...))>::value) {
oxThrowError(f(args...)); OX_THROW_ERROR(f(args...));
} else { } else {
f(args...); f(args...);
} }
@ -76,7 +76,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
f(args...); f(args...);
} }
@ -107,7 +107,7 @@ class Signal {
void call(Args... args) final { void call(Args... args) final {
if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) { if constexpr(detail::isError<decltype((m_receiver->*(m_methodPtr))(args...))>::value) {
oxThrowError((m_receiver->*(m_methodPtr))(args...)); OX_THROW_ERROR((m_receiver->*(m_methodPtr))(args...));
} else { } else {
(m_receiver->*(m_methodPtr))(args...); (m_receiver->*(m_methodPtr))(args...);
} }
@ -193,11 +193,11 @@ Error Signal<Args...>::disconnectObject(const void *receiver) const noexcept {
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@ -213,7 +213,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
f->call(args...); f->call(args...);
} }
return OxError(0); return ox::Error(0);
} catch (const ox::Exception &ex) { } catch (const ox::Exception &ex) {
return ox::Error(ex.file, ex.line, ex.errCode, ex.msg); return ox::Error(ex.file, ex.line, ex.errCode, ex.msg);
} }
@ -381,11 +381,11 @@ Error Signal<Error(Args...)>::disconnectObject(const void *receiver) const noexc
for (auto i = 0u; i < m_slots.size(); ++i) { for (auto i = 0u; i < m_slots.size(); ++i) {
const auto &slot = m_slots[i]; const auto &slot = m_slots[i];
if (slot->receiver() == receiver) { if (slot->receiver() == receiver) {
oxReturnError(m_slots.erase(i)); OX_RETURN_ERROR(m_slots.erase(i));
--i; --i;
} }
} }
return OxError(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots"); return ox::Error(1, "Signal::disconnectObject: Receiver was not found among this Signal's slots");
} }
template<class... Args> template<class... Args>
@ -398,9 +398,9 @@ void Signal<Error(Args...)>::emit(Args... args) const noexcept {
template<class... Args> template<class... Args>
Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept { Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) { for (auto &f : m_slots) {
oxReturnError(f->call(ox::forward<Args>(args)...)); OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
} }
return OxError(0); return ox::Error(0);
} }
} }

View File

@ -17,7 +17,7 @@ struct TestStruct: public ox::SignalHandler {
int value = 0; int value = 0;
ox::Error method(int i) noexcept { ox::Error method(int i) noexcept {
value = i; value = i;
return OxError(0); return ox::Error(0);
} }
}; };
@ -27,13 +27,13 @@ std::map<ox::StringView, std::function<ox::Error()>> tests = {
[] { [] {
ox::Signal<ox::Error(int)> signal; ox::Signal<ox::Error(int)> signal;
signal.connect([](int i) -> ox::Error { signal.connect([](int i) -> ox::Error {
return OxError(i != 5); return ox::Error(i != 5);
}); });
TestStruct ts; TestStruct ts;
signal.connect(&ts, &TestStruct::method); signal.connect(&ts, &TestStruct::method);
oxReturnError(signal.emitCheckError(5)); OX_RETURN_ERROR(signal.emitCheckError(5));
oxReturnError(OxError(ts.value != 5)); OX_RETURN_ERROR(ox::Error(ts.value != 5));
return OxError(0); return ox::Error(0);
} }
}, },
}; };

View File

@ -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( add_library(
OxFS OxFS

View File

@ -10,6 +10,8 @@
#include <ox/fs/ptrarith/nodebuffer.hpp> #include <ox/fs/ptrarith/nodebuffer.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
using InodeId_t = uint64_t; 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; auto fsData = nb->malloc(sizeof(FileStoreData)).value;
if (!fsData.valid()) { if (!fsData.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
auto data = nb->template dataOf<FileStoreData>(fsData); auto data = nb->template dataOf<FileStoreData>(fsData);
if (!data.valid()) { if (!data.valid()) {
oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData"); oxTrace("ox.fs.FileStoreTemplate.format.fail", "Could not read data section of FileStoreData");
return OxError(1, "Could not read data section of FileStoreData"); return ox::Error(1, "Could not read data section of FileStoreData");
} }
new (data) FileStoreData; new (data) FileStoreData;
return {}; return {};
@ -221,24 +223,24 @@ Error FileStoreTemplate<size_t>::setSize(std::size_t size) {
if (m_buffSize >= size) { if (m_buffSize >= size) {
return m_buffer->setSize(static_cast<size_t>(size)); return m_buffer->setSize(static_cast<size_t>(size));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) { Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
++item->links; ++item->links;
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::decLinks(uint64_t id) { Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
oxRequireM(item, find(static_cast<size_t>(id)).validate()); OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
--item->links; --item->links;
if (item->links == 0) { if (item->links == 0) {
oxReturnError(remove(item)); OX_RETURN_ERROR(remove(item));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> 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); oxTracef("ox.fs.FileStoreTemplate.write", "Attempting to write to inode {}", id);
auto existing = find(id); auto existing = find(id);
if (!canWrite(existing, dataSize)) { if (!canWrite(existing, dataSize)) {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
existing = find(id); existing = find(id);
} }
@ -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 first malloc failed, compact and try again
if (!dest.valid()) { if (!dest.valid()) {
oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting"); oxTrace("ox.fs.FileStoreTemplate.write", "Allocation failed, compacting");
oxReturnError(compact()); OX_RETURN_ERROR(compact());
dest = m_buffer->malloc(dataSize).value; dest = m_buffer->malloc(dataSize).value;
} }
if (dest.valid()) { if (dest.valid()) {
@ -296,16 +298,16 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
dest->id.get(), dest.offset(), destData.size()); dest->id.get(), dest.offset(), destData.size());
fsData->rootNode = dest.offset(); fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get()); oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return OxError(0); return ox::Error(0);
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header."); oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
} }
} }
} }
oxReturnError(m_buffer->free(dest)); OX_RETURN_ERROR(m_buffer->free(dest));
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
@ -320,7 +322,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1, "Could not find requested item"); return ox::Error(1, "Could not find requested item");
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -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", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), outSize); "Item data section size: {}, Expected size: {}", srcData.size(), outSize);
return OxError(1, "Invalid inode"); return ox::Error(1, "Invalid inode");
} }
ox::memcpy(out, srcData, srcData.size()); ox::memcpy(out, srcData, srcData.size());
@ -351,7 +353,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -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", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@ -384,7 +386,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
// error check // error check
if (!src.valid()) { if (!src.valid()) {
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id); oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not find requested item: {}", id);
return OxError(1); return ox::Error(1);
} }
auto srcData = m_buffer->template dataOf<uint8_t>(src); auto srcData = m_buffer->template dataOf<uint8_t>(src);
@ -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", "Could not read data section of item: {}", id);
oxTracef("ox.fs.FileStoreTemplate.read.fail", oxTracef("ox.fs.FileStoreTemplate.read.fail",
"Item data section size: {}, Expected size: {}", srcData.size(), readSize); "Item data section size: {}, Expected size: {}", srcData.size(), readSize);
return OxError(1); return ox::Error(1);
} }
ox::memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
@ -420,30 +422,30 @@ ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(uint64_t id)
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize() { Error FileStoreTemplate<size_t>::resize() {
oxReturnError(compact()); OX_RETURN_ERROR(compact());
const auto newSize = static_cast<std::size_t>(size() - available()); const auto newSize = static_cast<std::size_t>(size() - available());
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize); oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
oxReturnError(m_buffer->setSize(newSize)); OX_RETURN_ERROR(m_buffer->setSize(newSize));
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size()); oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) { if (m_buffer->size() > size) {
return OxError(1); return ox::Error(1);
} }
m_buffSize = static_cast<size_t>(size); m_buffSize = static_cast<size_t>(size);
if (newBuff) { if (newBuff) {
m_buffer = reinterpret_cast<Buffer*>(newBuff); m_buffer = reinterpret_cast<Buffer*>(newBuff);
oxReturnError(m_buffer->setSize(static_cast<size_t>(size))); OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const { Result<StatInfo> FileStoreTemplate<size_t>::stat(uint64_t id) const {
oxRequire(inode, find(static_cast<size_t>(id)).validate()); OX_REQUIRE(inode, find(static_cast<size_t>(id)).validate());
return StatInfo { return StatInfo {
id, id,
inode->links, inode->links,
@ -475,16 +477,16 @@ char *FileStoreTemplate<size_t>::buff() {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) { for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
oxReturnError(cb(i->fileType, i.ptr().offset(), i.ptr().end())); OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() { Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>::generateInodeId() {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
for (auto i = 0; i < 100; i++) { for (auto i = 0; i < 100; i++) {
auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>); auto inode = static_cast<typename FileStoreTemplate<size_t>::InodeId_t>(fsData->random.gen() % MaxValue<InodeId_t>);
@ -492,7 +494,7 @@ Result<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>:
return inode; return inode;
} }
} }
return OxError(2); return ox::Error(2);
} }
template<typename size_t> template<typename size_t>
@ -501,10 +503,10 @@ Error FileStoreTemplate<size_t>::compact() {
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error { return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
if (isFirstItem) { if (isFirstItem) {
isFirstItem = false; isFirstItem = false;
return OxError(0); return ox::Error(0);
} }
if (!item.valid()) { if (!item.valid()) {
return OxError(1); return ox::Error(1);
} }
oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset()); oxTracef("ox.fs.FileStoreTemplate.compact.moveItem", "Moving Item: {} from {} to {}", item->id.get(), oldAddr, item.offset());
// update rootInode if this is it // update rootInode if this is it
@ -522,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
parent->right = item; parent->right = item;
} }
} }
return OxError(0); return ox::Error(0);
}); });
} }
@ -542,15 +544,15 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
fsData->rootNode = item; fsData->rootNode = item;
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(root, item); return placeItem(root, item);
} }
@ -560,7 +562,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth > 5000) { if (depth > 5000) {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(2); return ox::Error(2);
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@ -571,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = right->right; item->right = right->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(right, item, depth + 1); 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; item->right = left->right;
} }
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get()); oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return OxError(0); return ox::Error(0);
} else { } else {
return placeItem(left, item, depth + 1); return placeItem(left, item, depth + 1);
} }
} else { } else {
oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself."); oxTrace("ox.fs.FileStoreTemplate.placeItem.fail", "Cannot insert an item on itself.");
return OxError(1, "Cannot insert an item on itself."); return ox::Error(1, "Cannot insert an item on itself.");
} }
} }
@ -598,9 +600,9 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
auto fsData = fileStoreData(); auto fsData = fileStoreData();
if (!fsData) { if (!fsData) {
return OxError(1); return ox::Error(1);
} }
oxRequireM(root, m_buffer->ptr(fsData->rootNode).validate()); OX_REQUIRE_M(root, m_buffer->ptr(fsData->rootNode).validate());
if (root->id == item->id) { if (root->id == item->id) {
item->left = root->left; item->left = root->left;
item->right = root->right; item->right = root->right;
@ -622,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else { } else {
fsData->rootNode = 0; fsData->rootNode = 0;
} }
return OxError(0); return ox::Error(0);
} else { } else {
return unplaceItem(root, item); return unplaceItem(root, item);
} }
@ -632,7 +634,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) { Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth >= 5000) { if (depth >= 5000) {
oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow."); oxTrace("ox.fs.FileStoreTemplate.unplaceItem.fail", "Excessive recursion depth, stopping before stack overflow.");
return OxError(1, "Excessive recursion depth, stopping before stack overflow."); return ox::Error(1, "Excessive recursion depth, stopping before stack overflow.");
} }
if (item->id > root->id) { if (item->id > root->id) {
auto right = m_buffer->ptr(root->right); auto right = m_buffer->ptr(root->right);
@ -651,25 +653,25 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
return unplaceItem(left, item, depth + 1); return unplaceItem(left, item, depth + 1);
} }
} else { } else {
return OxError(1); return ox::Error(1);
} }
if (item->right) { if (item->right) {
oxReturnError(placeItem(m_buffer->ptr(item->right))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->right)));
} }
if (item->left) { if (item->left) {
oxReturnError(placeItem(m_buffer->ptr(item->left))); OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::remove(ItemPtr item) { Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) { if (item.valid()) {
oxReturnError(unplaceItem(item)); OX_RETURN_ERROR(unplaceItem(item));
oxReturnError(m_buffer->free(item)); OX_RETURN_ERROR(m_buffer->free(item));
return OxError(0); return ox::Error(0);
} }
return OxError(1); return ox::Error(1);
} }
template<typename size_t> template<typename size_t>
@ -771,3 +773,5 @@ using FileStore16 = FileStoreTemplate<uint16_t>;
using FileStore32 = FileStoreTemplate<uint32_t>; using FileStore32 = FileStoreTemplate<uint32_t>;
} }
OX_CLANG_NOWARN_END

View File

@ -15,6 +15,8 @@
#include "types.hpp" #include "types.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename InodeId_t> template<typename InodeId_t>
@ -53,7 +55,7 @@ struct OX_PACKED DirectoryEntry {
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len())); ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
return {}; return {};
} }
return OxError(1); return ox::Error(1);
} }
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept { ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() noexcept {
@ -139,11 +141,11 @@ template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::init() noexcept { Error Directory<FileStore, InodeId_t>::init() noexcept {
constexpr auto Size = sizeof(Buffer); constexpr auto Size = sizeof(Buffer);
oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId); oxTracef("ox.fs.Directory.init", "Initializing Directory with Inode ID: {}", m_inodeId);
oxReturnError(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory))); OX_RETURN_ERROR(m_fs.write(m_inodeId, nullptr, Size, static_cast<uint8_t>(FileType::Directory)));
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
m_size = 0; m_size = 0;
return OxError(1); return ox::Error(1);
} }
new (buff) Buffer(Size); new (buff) Buffer(Size);
m_size = Size; m_size = Size;
@ -156,21 +158,21 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
oxTrace("ox.fs.Directory.mkdir", path.fullPath()); oxTrace("ox.fs.Directory.mkdir", path.fullPath());
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
auto childInode = find(PathIterator(name)); auto childInode = find(PathIterator(name));
if (!childInode.ok()) { if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled, // if this is not the last item in the path and parents is disabled,
// return an error // return an error
if (!parents && path.hasNext()) { if (!parents && path.hasNext()) {
return OxError(1); return ox::Error(1);
} }
childInode = m_fs.generateInodeId(); childInode = m_fs.generateInodeId();
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value); oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
oxLogError(childInode.error); oxLogError(childInode.error);
oxReturnError(childInode.error); OX_RETURN_ERROR(childInode.error);
// initialize the directory // initialize the directory
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
oxReturnError(child.init()); OX_RETURN_ERROR(child.init());
auto err = write(PathIterator(name), childInode.value); auto err = write(PathIterator(name), childInode.value);
if (err) { if (err) {
oxLogError(err); oxLogError(err);
@ -181,7 +183,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
} }
Directory<FileStore, InodeId_t> child(m_fs, childInode.value); Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
if (path.hasNext()) { if (path.hasNext()) {
oxReturnError(child.mkdir(path.next(), parents)); OX_RETURN_ERROR(child.mkdir(path.next(), parents));
} }
} }
return {}; return {};
@ -194,28 +196,28 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
if (path.next().hasNext()) { // not yet at target directory, recurse to next one if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}", oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
name, path.fullPath()); name, path.fullPath());
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(nextChild, findEntry(name)); OX_REQUIRE(nextChild, findEntry(name));
oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild); oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild);
if (nextChild) { if (nextChild) {
return Directory(m_fs, nextChild).write(path.next(), inode); return Directory(m_fs, nextChild).write(path.next(), inode);
} else { } else {
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name); oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name);
return OxError(1, "File not found and not allowed to create it."); return ox::Error(1, "File not found and not allowed to create it.");
} }
} else { } else {
oxTrace("ox.fs.Directory.write", path.fullPath()); oxTrace("ox.fs.Directory.write", path.fullPath());
oxReturnError(path.next(name)); OX_RETURN_ERROR(path.next(name));
// insert the new entry on this directory // insert the new entry on this directory
// get the name // get the name
// find existing version of directory // find existing version of directory
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId); oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
oxRequire(oldStat, m_fs.stat(m_inodeId)); OX_REQUIRE(oldStat, m_fs.stat(m_inodeId));
oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size); oxTracef("ox.fs.Directory.write", "Found existing directory of size {}", oldStat.size);
auto old = m_fs.read(m_inodeId).template to<Buffer>(); auto old = m_fs.read(m_inodeId).template to<Buffer>();
if (!old.valid()) { if (!old.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
return OxError(1, "Could not read existing version of Directory"); return ox::Error(1, "Could not read existing version of Directory");
} }
const auto pathSize = name.len() + 1; const auto pathSize = name.len() + 1;
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize); const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
@ -223,16 +225,16 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size); auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
if (cpy == nullptr) { if (cpy == nullptr) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
return OxError(1, "Could not allocate memory for copy of Directory"); return ox::Error(1, "Could not allocate memory for copy of Directory");
} }
oxReturnError(cpy->setSize(newSize)); OX_RETURN_ERROR(cpy->setSize(newSize));
auto val = cpy->malloc(entryDataSize).value; auto val = cpy->malloc(entryDataSize).value;
if (!val.valid()) { if (!val.valid()) {
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry"); oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
return OxError(1, "Could not allocate memory for new directory entry"); return ox::Error(1, "Could not allocate memory for new directory entry");
} }
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name); oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name);
oxReturnError(val->init(inode, name, val.size())); OX_RETURN_ERROR(val->init(inode, name, val.size()));
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory)); return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
} }
} }
@ -240,7 +242,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept { Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxTrace("ox.fs.Directory.remove", name); oxTrace("ox.fs.Directory.remove", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (buff.valid()) { if (buff.valid()) {
@ -249,7 +251,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
if (name == data->name) { if (name == data->name) {
oxReturnError(buff->free(i)); OX_RETURN_ERROR(buff->free(i));
} }
} else { } else {
oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.remove", "INVALID DIRECTORY ENTRY");
@ -257,7 +259,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
} }
} else { } else {
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer"); oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
return OxError(1, "Could not find directory buffer"); return ox::Error(1, "Could not find directory buffer");
} }
return {}; return {};
} }
@ -269,13 +271,13 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer"); oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
return OxError(1, "Could not directory buffer"); return ox::Error(1, "Could not directory buffer");
} }
oxTrace("ox.fs.Directory.ls", "Found directory buffer."); oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data(); auto data = i->data();
if (data.valid()) { if (data.valid()) {
oxReturnError(cb(data->name, data->inode)); OX_RETURN_ERROR(cb(data->name, data->inode));
} else { } else {
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY"); oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
} }
@ -289,7 +291,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
auto buff = m_fs.read(m_inodeId).template to<Buffer>(); auto buff = m_fs.read(m_inodeId).template to<Buffer>();
if (!buff.valid()) { if (!buff.valid()) {
oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer"); oxTrace("ox.fs.Directory.findEntry.fail", "Could not findEntry directory buffer");
return OxError(2, "Could not findEntry directory buffer"); return ox::Error(2, "Could not findEntry directory buffer");
} }
oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size()); oxTracef("ox.fs.Directory.findEntry", "Found directory buffer, size: {}", buff.size());
for (auto i = buff->iterator(); i.valid(); i.next()) { for (auto i = buff->iterator(); i.valid(); i.next()) {
@ -305,15 +307,15 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
} }
} }
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present"); oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
return OxError(1, "Entry not present"); return ox::Error(1, "Entry not present");
} }
template<typename FileStore, typename InodeId_t> template<typename FileStore, typename InodeId_t>
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept { Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept {
// determine if already exists // determine if already exists
ox::StringView name; ox::StringView name;
oxReturnError(path.get(name)); OX_RETURN_ERROR(path.get(name));
oxRequire(v, findEntry(name)); OX_REQUIRE(v, findEntry(name));
// recurse if not at end of path // recurse if not at end of path
if (auto p = path.next(); p.valid()) { if (auto p = path.next(); p.valid()) {
Directory dir(m_fs, v); Directory dir(m_fs, v);
@ -333,3 +335,5 @@ using Directory16 = Directory<FileStore16, uint16_t>;
using Directory32 = Directory<FileStore32, uint32_t>; using Directory32 = Directory<FileStore32, uint32_t>;
} }
OX_CLANG_NOWARN_END

View File

@ -32,7 +32,9 @@ FileAddress::FileAddress(ox::StringViewCR path) noexcept {
auto pathSize = path.bytes(); auto pathSize = path.bytes();
m_data.path = new char[pathSize + 1]; m_data.path = new char[pathSize + 1];
memcpy(m_data.path, path.data(), pathSize); memcpy(m_data.path, path.data(), pathSize);
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
m_data.path[pathSize] = 0; m_data.path[pathSize] = 0;
OX_CLANG_NOWARN_END
m_type = FileAddressType::Path; m_type = FileAddressType::Path;
} }

View File

@ -13,6 +13,8 @@
#include <ox/model/typenamecatcher.hpp> #include <ox/model/typenamecatcher.hpp>
#include <ox/model/types.hpp> #include <ox/model/types.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
enum class FileAddressType: int8_t { enum class FileAddressType: int8_t {
@ -87,7 +89,7 @@ class FileAddress {
case FileAddressType::Inode: case FileAddressType::Inode:
return m_data.inode; return m_data.inode;
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -98,7 +100,7 @@ class FileAddress {
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
return ox::CStringView(m_data.constPath); return ox::CStringView(m_data.constPath);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -152,31 +154,33 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept {
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress::Data>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress::Data>());
oxReturnError(h->fieldCString("path", &obj->path)); OX_RETURN_ERROR(h->fieldCString("path", &obj->path));
oxReturnError(h->fieldCString("constPath", &obj->path)); OX_RETURN_ERROR(h->fieldCString("constPath", &obj->path));
oxReturnError(h->field("inode", &obj->inode)); OX_RETURN_ERROR(h->field("inode", &obj->inode));
return {}; return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept { constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
oxReturnError(h->template setTypeInfo<FileAddress>()); OX_RETURN_ERROR(h->template setTypeInfo<FileAddress>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
int8_t type = -1; int8_t type = -1;
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, type))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, type)));
} else if constexpr(T::opType() == OpType::Read) { } else if constexpr(T::opType() == OpType::Read) {
auto type = static_cast<int8_t>(fa->m_type); auto type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
fa->m_type = static_cast<FileAddressType>(type); fa->m_type = static_cast<FileAddressType>(type);
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto const type = static_cast<int8_t>(fa->m_type); auto const type = static_cast<int8_t>(fa->m_type);
oxReturnError(h->field("type", &type)); OX_RETURN_ERROR(h->field("type", &type));
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type)))); OX_RETURN_ERROR(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
} }
return {}; return {};
} }
} }
OX_CLANG_NOWARN_END

View File

@ -21,7 +21,7 @@ Result<const char*> MemFS::directAccess(const FileAddress &addr) const noexcept
case FileAddressType::Path: case FileAddressType::Path:
return directAccess(StringView(addr.getPath().value)); return directAccess(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -33,21 +33,21 @@ Error FileSystem::read(const FileAddress &addr, void *buffer, std::size_t size)
case FileAddressType::Path: case FileAddressType::Path:
return readFilePath(StringView(addr.getPath().value), buffer, size); return readFilePath(StringView(addr.getPath().value), buffer, size);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept { Result<Buffer> FileSystem::read(const FileAddress &addr) noexcept {
oxRequire(s, stat(addr)); OX_REQUIRE(s, stat(addr));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(read(addr, buff.data(), buff.size())); OX_RETURN_ERROR(read(addr, buff.data(), buff.size()));
return buff; return buff;
} }
Result<Buffer> FileSystem::read(StringViewCR path) noexcept { Result<Buffer> FileSystem::read(StringViewCR path) noexcept {
oxRequire(s, statPath(path)); OX_REQUIRE(s, statPath(path));
Buffer buff(static_cast<std::size_t>(s.size)); Buffer buff(static_cast<std::size_t>(s.size));
oxReturnError(readFilePath(path, buff.data(), buff.size())); OX_RETURN_ERROR(readFilePath(path, buff.data(), buff.size()));
return buff; return buff;
} }
@ -57,9 +57,9 @@ Error FileSystem::read(const FileAddress &addr, std::size_t readStart, std::size
return read(addr.getInode().value, readStart, readSize, buffer, size); return read(addr.getInode().value, readStart, readSize, buffer, size);
case FileAddressType::ConstPath: case FileAddressType::ConstPath:
case FileAddressType::Path: case FileAddressType::Path:
return OxError(2, "Unsupported for path lookups"); return ox::Error(2, "Unsupported for path lookups");
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -71,7 +71,7 @@ Error FileSystem::remove(const FileAddress &addr, bool recursive) noexcept {
case FileAddressType::Path: case FileAddressType::Path:
return remove(StringView(addr.getPath().value), recursive); return remove(StringView(addr.getPath().value), recursive);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -83,7 +83,7 @@ Error FileSystem::write(const FileAddress &addr, const void *buffer, uint64_t si
case FileAddressType::Path: case FileAddressType::Path:
return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType); return writeFilePath(StringView(addr.getPath().value), buffer, size, fileType);
default: default:
return OxError(1); return ox::Error(1);
} }
} }
@ -95,7 +95,7 @@ Result<FileStat> FileSystem::stat(const FileAddress &addr) const noexcept {
case FileAddressType::Path: case FileAddressType::Path:
return statPath(StringView(addr.getPath().value)); return statPath(StringView(addr.getPath().value));
default: default:
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -284,69 +284,69 @@ FileSystemTemplate<FileStore, Directory>::~FileSystemTemplate() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buffSize) noexcept {
oxReturnError(FileStore::format(buff, static_cast<size_t>(buffSize))); OX_RETURN_ERROR(FileStore::format(buff, static_cast<size_t>(buffSize)));
FileStore fs(buff, static_cast<size_t>(buffSize)); FileStore fs(buff, static_cast<size_t>(buffSize));
constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2; constexpr auto rootDirInode = MaxValue<typename FileStore::InodeId_t> / 2;
Directory rootDir(fs, rootDirInode); Directory rootDir(fs, rootDirInode);
oxReturnError(rootDir.init()); OX_RETURN_ERROR(rootDir.init());
FileSystemData fd; FileSystemData fd;
fd.rootDirInode = rootDirInode; fd.rootDirInode = rootDirInode;
oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get()); oxTracef("ox.fs.FileSystemTemplate.format", "rootDirInode: {}", fd.rootDirInode.get());
oxReturnError(fs.write(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(fs.write(InodeFsData, &fd, sizeof(fd)));
if (!fs.read(fd.rootDirInode).valid()) { if (!fs.read(fd.rootDirInode).valid()) {
oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory"); oxTrace("ox.fs.FileSystemTemplate.format.error", "FileSystemTemplate::format did not correctly create root directory");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::mkdir(StringViewCR path, bool recursive) noexcept {
oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive); oxTracef("ox.fs.FileSystemTemplate.mkdir", "path: {}, recursive: {}", path, recursive);
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
return rootDir.mkdir(path, recursive); return rootDir.mkdir(path, recursive);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept { Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringViewCR dest) noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequireM(inode, rootDir.find(src)); OX_REQUIRE_M(inode, rootDir.find(src));
oxReturnError(rootDir.write(dest, inode)); OX_RETURN_ERROR(rootDir.write(dest, inode));
oxReturnError(rootDir.remove(src)); OX_RETURN_ERROR(rootDir.remove(src));
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFilePath(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
oxTrace("ox.fs.FileSystemTemplate.readFilePath", path); oxTrace("ox.fs.FileSystemTemplate.readFilePath", path);
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(s, stat(path)); OX_REQUIRE(s, stat(path));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(s.inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept { Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
return directAccessInode(inode); return directAccessInode(inode);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode); oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode);
oxRequire(s, stat(inode)); OX_REQUIRE(s, stat(inode));
if (s.size > buffSize) { if (s.size > buffSize) {
return OxError(1, "Buffer to small to load file"); return ox::Error(1, "Buffer to small to load file");
} }
return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize); return readFileInodeRange(inode, 0, static_cast<size_t>(s.size), buffer, &buffSize);
} }
@ -360,7 +360,7 @@ template<typename FileStore, typename Directory>
Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept { Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(uint64_t inode) const noexcept {
auto data = m_fs.read(inode); auto data = m_fs.read(inode);
if (!data.valid()) { if (!data.valid()) {
return OxError(1, "Data not valid"); return ox::Error(1, "Data not valid");
} }
return reinterpret_cast<char*>(data.get()); return reinterpret_cast<char*>(data.get());
} }
@ -368,9 +368,9 @@ Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessInode(
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept { Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path) const noexcept {
Vector<String> out; Vector<String> out;
oxReturnError(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) { OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name); out.emplace_back(name);
return OxError(0); return ox::Error(0);
})); }));
return out; return out;
} }
@ -379,17 +379,17 @@ template<typename FileStore, typename Directory>
template<typename F> template<typename F>
Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const { Error FileSystemTemplate<FileStore, Directory>::ls(StringViewCR path, F cb) const {
oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path); oxTracef("ox.fs.FileSystemTemplate.ls", "path: {}", path);
oxRequire(s, stat(path)); OX_REQUIRE(s, stat(path));
Directory dir(m_fs, s.inode); Directory dir(m_fs, s.inode);
return dir.ls(cb); return dir.ls(cb);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept { Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool recursive) noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(inode, rootDir.find(path)); OX_REQUIRE(inode, rootDir.find(path));
oxRequire(st, statInode(inode)); OX_REQUIRE(st, statInode(inode));
if (st.fileType == FileType::NormalFile || recursive) { if (st.fileType == FileType::NormalFile || recursive) {
if (auto err = rootDir.remove(path)) { if (auto err = rootDir.remove(path)) {
// removal failed, try putting the index back // removal failed, try putting the index back
@ -398,9 +398,9 @@ Error FileSystemTemplate<FileStore, Directory>::remove(StringViewCR path, bool r
} }
} else { } else {
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting."); oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
@ -410,7 +410,7 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept { Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer)); OX_RETURN_ERROR(m_fs.resize(static_cast<size_t>(size), buffer));
return {}; return {};
} }
@ -423,11 +423,11 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path); oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path);
auto [inode, err] = find(path); auto [inode, err] = find(path);
if (err) { if (err) {
oxReturnError(m_fs.generateInodeId().moveTo(inode)); OX_RETURN_ERROR(m_fs.generateInodeId().moveTo(inode));
oxRequireM(rootDir, this->rootDir()); OX_REQUIRE_M(rootDir, this->rootDir());
oxReturnError(rootDir.write(path, inode)); OX_RETURN_ERROR(rootDir.write(path, inode));
} }
oxReturnError(writeFileInode(inode, buffer, size, fileType)); OX_RETURN_ERROR(writeFileInode(inode, buffer, size, fileType));
return {}; return {};
} }
@ -439,7 +439,7 @@ Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, c
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t inode) const noexcept {
oxRequire(s, m_fs.stat(inode)); OX_REQUIRE(s, m_fs.stat(inode));
FileStat out; FileStat out;
out.inode = s.inode; out.inode = s.inode;
out.links = s.links; out.links = s.links;
@ -450,7 +450,7 @@ Result<FileStat> FileSystemTemplate<FileStore, Directory>::statInode(uint64_t in
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept { Result<FileStat> FileSystemTemplate<FileStore, Directory>::statPath(StringViewCR path) const noexcept {
oxRequire(inode, find(path)); OX_REQUIRE(inode, find(path));
return stat(inode); return stat(inode);
} }
@ -487,25 +487,25 @@ bool FileSystemTemplate<FileStore, Directory>::valid() const noexcept {
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept { Result<typename FileSystemTemplate<FileStore, Directory>::FileSystemData> FileSystemTemplate<FileStore, Directory>::fileSystemData() const noexcept {
FileSystemData fd; FileSystemData fd;
oxReturnError(m_fs.read(InodeFsData, &fd, sizeof(fd))); OX_RETURN_ERROR(m_fs.read(InodeFsData, &fd, sizeof(fd)));
return fd; return fd;
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept { Result<uint64_t> FileSystemTemplate<FileStore, Directory>::find(StringViewCR path) const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
// return root as a special case // return root as a special case
if (path == "/") { if (path == "/") {
return static_cast<uint64_t>(fd.rootDirInode); return static_cast<uint64_t>(fd.rootDirInode);
} }
Directory rootDir(m_fs, fd.rootDirInode); Directory rootDir(m_fs, fd.rootDirInode);
oxRequire(out, rootDir.find(path)); OX_REQUIRE(out, rootDir.find(path));
return static_cast<uint64_t>(out); return static_cast<uint64_t>(out);
} }
template<typename FileStore, typename Directory> template<typename FileStore, typename Directory>
Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept { Result<Directory> FileSystemTemplate<FileStore, Directory>::rootDir() const noexcept {
oxRequire(fd, fileSystemData()); OX_REQUIRE(fd, fileSystemData());
return Directory(m_fs, fd.rootDirInode); return Directory(m_fs, fd.rootDirInode);
} }

View File

@ -39,7 +39,7 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directories(p, ec); success = std::filesystem::create_directories(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} else { } else {
std::error_code ec; std::error_code ec;
@ -48,26 +48,26 @@ Error PassThroughFS::mkdir(StringViewCR path, bool recursive) noexcept {
success = true; success = true;
} else { } else {
success = std::filesystem::create_directory(p, ec); success = std::filesystem::create_directory(p, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: mkdir failed"));
} }
} }
return OxError(success ? 0 : 1); return ox::Error(success ? 0 : 1);
} }
Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept { Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
std::error_code ec; std::error_code ec;
std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec); std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest), ec);
if (ec.value()) { if (ec.value()) {
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept { Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
Vector<String> out; Vector<String> out;
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (const auto &p : di) { for (const auto &p : di) {
const auto u8p = p.path().filename().u8string(); const auto u8p = p.path().filename().u8string();
out.emplace_back(reinterpret_cast<const char*>(u8p.c_str())); out.emplace_back(reinterpret_cast<const char*>(u8p.c_str()));
@ -77,20 +77,20 @@ Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept { Error PassThroughFS::remove(StringViewCR path, bool recursive) noexcept {
if (recursive) { if (recursive) {
return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0); return ox::Error(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
} else { } else {
return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0); return ox::Error(std::filesystem::remove(m_path / stripSlash(path)) != 0);
} }
} }
Error PassThroughFS::resize(uint64_t, void*) noexcept { Error PassThroughFS::resize(uint64_t, void*) noexcept {
// unsupported // unsupported
return OxError(1, "resize is not supported by PassThroughFS"); return ox::Error(1, "resize is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept { Result<FileStat> PassThroughFS::statInode(uint64_t) const noexcept {
// unsupported // unsupported
return OxError(1, "statInode(uint64_t) is not supported by PassThroughFS"); return ox::Error(1, "statInode(uint64_t) is not supported by PassThroughFS");
} }
Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept { Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
@ -101,7 +101,7 @@ Result<FileStat> PassThroughFS::statPath(StringViewCR path) const noexcept {
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path); oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec); const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size); oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
return FileStat{0, 0, size, type}; return FileStat{0, 0, size, type};
} }
@ -112,14 +112,14 @@ uint64_t PassThroughFS::spaceNeeded(uint64_t size) const noexcept {
Result<uint64_t> PassThroughFS::available() const noexcept { Result<uint64_t> PassThroughFS::available() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.available; return s.available;
} }
Result<uint64_t> PassThroughFS::size() const noexcept { Result<uint64_t> PassThroughFS::size() const noexcept {
std::error_code ec; std::error_code ec;
const auto s = std::filesystem::space(m_path, ec); const auto s = std::filesystem::space(m_path, ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: could not get FS size"));
return s.capacity; return s.capacity;
} }
@ -128,7 +128,7 @@ char *PassThroughFS::buff() noexcept {
} }
Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept { Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) noexcept {
return OxError(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS"); return ox::Error(1, "walk(Error(*)(uint8_t, uint64_t, uint64_t)) is not supported by PassThroughFS");
} }
bool PassThroughFS::valid() const noexcept { bool PassThroughFS::valid() const noexcept {
@ -147,24 +147,24 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
if (size > buffSize) { if (size > buffSize) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path); oxTracef("ox.fs.PassThroughFS.read.error", "Read failed: Buffer too small: {}", path);
return OxError(1); return ox::Error(1);
} }
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize)); file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(buffSize));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return OxError(2); return ox::Error(2);
} }
return OxError(0); return ox::Error(0);
} }
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept { Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
// unsupported // unsupported
return OxError(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS"); return ox::Error(1, "readFileInode(uint64_t, void*, std::size_t) is not supported by PassThroughFS");
} }
Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept { Error PassThroughFS::readFileInodeRange(uint64_t, std::size_t, std::size_t, void*, std::size_t*) noexcept {
// unsupported // unsupported
return OxError(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS"); return ox::Error(1, "read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) is not supported by PassThroughFS");
} }
Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept { Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64_t size, FileType) noexcept {
@ -174,14 +174,14 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size)); f.write(static_cast<const char*>(buffer), static_cast<std::streamsize>(size));
} catch (const std::fstream::failure &f) { } catch (const std::fstream::failure &f) {
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what()); oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
} }
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept { Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
// unsupported // unsupported
return OxError(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS"); return ox::Error(1, "writeFileInode(uint64_t, void*, uint64_t, uint8_t) is not supported by PassThroughFS");
} }
std::string_view PassThroughFS::stripSlash(StringView path) noexcept { std::string_view PassThroughFS::stripSlash(StringView path) noexcept {

View File

@ -92,11 +92,11 @@ template<typename F>
Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept { Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
std::error_code ec; std::error_code ec;
const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec); const auto di = std::filesystem::directory_iterator(m_path / stripSlash(dir), ec);
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed")); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: ls failed"));
for (auto &p : di) { for (auto &p : di) {
oxReturnError(cb(p.path().filename().c_str(), 0)); OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
} }
return OxError(0); return ox::Error(0);
} }
} }

View File

@ -11,6 +11,8 @@
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include "pathiterator.hpp" #include "pathiterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) { 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) { Error PathIterator::dirPath(char *out, std::size_t outSize) {
const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize); const auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
const auto size = static_cast<std::size_t>(idx + 1); const auto size = static_cast<std::size_t>(idx) + 1;
if (idx >= 0 && size < outSize) { if (idx >= 0 && size < outSize) {
ox::memcpy(out, m_path, size); ox::memcpy(out, m_path, size);
out[size] = 0; out[size] = 0;
return OxError(0); return ox::Error(0);
} else { } else {
return OxError(1); return ox::Error(1);
} }
} }
@ -45,11 +47,11 @@ Error PathIterator::get(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
if (m_iterator >= m_maxSize) { if (m_iterator >= m_maxSize) {
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize); oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
return OxError(1); return ox::Error(1);
} }
if (!ox::strlen(&m_path[m_iterator])) { if (!ox::strlen(&m_path[m_iterator])) {
oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])"); oxTrace("ox.fs.PathIterator.get", "!ox::strlen(&m_path[m_iterator])");
return OxError(1); return ox::Error(1);
} }
auto start = m_iterator; auto start = m_iterator;
if (m_path[start] == '/') { if (m_path[start] == '/') {
@ -65,7 +67,7 @@ Error PathIterator::get(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength || size == 0) { if (size >= MaxFileNameLength || size == 0) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
@ -81,9 +83,9 @@ Error PathIterator::get(StringView &fileName) {
*/ */
Error PathIterator::next(StringView &fileName) { Error PathIterator::next(StringView &fileName) {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = OxError(0); retval = ox::Error(0);
if (m_path[m_iterator] == '/') { if (m_path[m_iterator] == '/') {
m_iterator++; m_iterator++;
} }
@ -98,7 +100,7 @@ Error PathIterator::next(StringView &fileName) {
size = end - start; size = end - start;
// cannot fit the output in the output parameter // cannot fit the output in the output parameter
if (size >= MaxFileNameLength) { if (size >= MaxFileNameLength) {
return OxError(1); return ox::Error(1);
} }
fileName = ox::substr(m_path, start, start + size); fileName = ox::substr(m_path, start, start + size);
// truncate trailing / // truncate trailing /
@ -113,10 +115,10 @@ Error PathIterator::next(StringView &fileName) {
Result<std::size_t> PathIterator::nextSize() const { Result<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0; std::size_t size = 0;
auto retval = OxError(1); auto retval = ox::Error(1);
auto it = m_iterator; auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) { if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = OxError(0); retval = ox::Error(0);
if (m_path[it] == '/') { if (m_path[it] == '/') {
it++; it++;
} }
@ -183,3 +185,5 @@ const char *PathIterator::fullPath() const {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -13,6 +13,8 @@
#include "ptr.hpp" #include "ptr.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith { namespace ox::ptrarith {
template<typename size_t, typename Item> 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; addr = m_header.firstItem;
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer is in invalid state.");
return OxError(1, "NodeBuffer is in invalid state."); return ox::Error(1, "NodeBuffer is in invalid state.");
} }
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize); oxTracef("ox.ptrarith.NodeBuffer.malloc", "buffer size: {}; addr: {}; fullSize: {}", m_header.size.get(), addr, fullSize);
auto out = ItemPtr(this, m_header.size, addr, fullSize); auto out = ItemPtr(this, m_header.size, addr, fullSize);
if (!out.valid()) { if (!out.valid()) {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown"); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown");
return OxError(1, "NodeBuffer::malloc: unknown failure"); return ox::Error(1, "NodeBuffer::malloc: unknown failure");
} }
ox::memset(out, 0, fullSize); ox::memset(out, 0, fullSize);
new (out) Item; new (out) Item;
@ -302,7 +304,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
first->prev = out.offset(); first->prev = out.offset();
} else { } else {
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid first element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid first element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid first element pointer.");
} }
if (oldLast.valid()) { if (oldLast.valid()) {
@ -312,7 +314,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
if (out.offset() != first.offset()) { if (out.offset() != first.offset()) {
// if this is not the first allocation, there should be an oldLast // if this is not the first allocation, there should be an oldLast
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer."); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "NodeBuffer malloc failed due to invalid last element pointer.");
return OxError(1, "NodeBuffer malloc failed due to invalid last element pointer."); return ox::Error(1, "NodeBuffer malloc failed due to invalid last element pointer.");
} }
out->prev = out.offset(); out->prev = out.offset();
} }
@ -321,7 +323,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
return out; return out;
} }
oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available()); oxTracef("ox.ptrarith.NodeBuffer.malloc.fail", "Insufficient space: {} needed, {} available", fullSize, available());
return OxError(1); return ox::Error(1);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -344,15 +346,15 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
} else { } else {
if (!prev.valid()) { if (!prev.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid prev element pointer: {}", prev.offset());
return OxError(1); return ox::Error(1);
} }
if (!next.valid()) { if (!next.valid()) {
oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset()); oxTracef("ox.ptrarith.NodeBuffer.free.fail", "NodeBuffer free failed due to invalid next element pointer: {}", next.offset());
return OxError(1); return ox::Error(1);
} }
} }
m_header.bytesUsed -= item.size(); m_header.bytesUsed -= item.size();
return OxError(0); return ox::Error(0);
} }
template<typename size_t, typename Item> 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); oxTracef("ox.ptrarith.NodeBuffer.setSize", "end: {}", end);
if (end > size) { if (end > size) {
// resizing to less than buffer size // resizing to less than buffer size
return OxError(1); return ox::Error(1);
} else { } else {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end; auto data = reinterpret_cast<uint8_t*>(this) + end;
ox::memset(data, 0, size - end); ox::memset(data, 0, size - end);
return OxError(0); return ox::Error(0);
} }
} }
@ -399,14 +401,14 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
auto dest = ptr(sizeof(*this)); auto dest = ptr(sizeof(*this));
while (dest.offset() <= src.offset()) { while (dest.offset() <= src.offset()) {
if (!src.valid()) { if (!src.valid()) {
return OxError(1); return ox::Error(1);
} }
if (!dest.valid()) { if (!dest.valid()) {
return OxError(2); return ox::Error(2);
} }
// move node // move node
ox::memcpy(dest, src, src->fullSize()); ox::memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest)); OX_RETURN_ERROR(cb(src, dest));
// update surrounding nodes // update surrounding nodes
auto prev = ptr(dest->prev); auto prev = ptr(dest->prev);
if (prev.valid()) { if (prev.valid()) {
@ -420,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
src = ptr(dest->next); src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize()); dest = uninitializedPtr(dest.offset() + dest->fullSize());
} }
return OxError(0); return ox::Error(0);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -449,3 +451,5 @@ struct OX_PACKED Item {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,8 @@
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::ptrarith { namespace ox::ptrarith {
template<typename T, typename size_t, size_t minOffset = 1> 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()) { if (valid()) {
return *this; return *this;
} }
return OxError(1); return ox::Error(1);
} }
} }
OX_CLANG_NOWARN_END

View File

@ -52,7 +52,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(buffer->free(a1), "Free failed."); oxAssert(buffer->free(a1), "Free failed.");
oxAssert(buffer->free(a2), "Free failed."); oxAssert(buffer->free(a2), "Free failed.");
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed."); oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -64,7 +64,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -77,7 +77,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxExpect(buff, "usr"); oxExpect(buff, "usr");
oxAssert(it.next(buff), "PathIterator::next returned error"); oxAssert(it.next(buff), "PathIterator::next returned error");
oxExpect(buff, "share"); oxExpect(buff, "share");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -87,7 +87,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -99,7 +99,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -110,7 +110,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::StringView buff; ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -120,7 +120,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path.c_str(), path.len()); ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1)); auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -130,7 +130,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
ox::PathIterator it(path, ox::strlen(path)); ox::PathIterator it(path, ox::strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext"); oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -142,7 +142,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto subPtr = p.subPtr<uint64_t>(50); auto subPtr = p.subPtr<uint64_t>(50);
oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid."); oxAssert(subPtr.valid(), "Ptr::subPtr: Ptr subPtr is invalid.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -155,7 +155,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
auto first = list->firstItem(); auto first = list->firstItem();
oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item"); oxAssert(first.valid(), "NodeBuffer::insert: Could not access first item");
oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid"); oxAssert(first->size() == 50, "NodeBuffer::insert: First item size invalid");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -176,7 +176,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
size_t str1ReadSize = 0; size_t str1ReadSize = 0;
oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed."); oxAssert(fileStore.read(4, reinterpret_cast<void*>(str1Read), str1Len, &str1ReadSize), "FileStore::read 1 failed.");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -203,7 +203,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxTrace("ox.fs.test.Directory") << "write 3"; oxTrace("ox.fs.test.Directory") << "write 3";
oxAssert(dir.write("/file2", 2), "Directory write of file2 failed"); oxAssert(dir.write("/file2", 2), "Directory write of file2 failed");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -220,19 +220,20 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed"); oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
return OxError(0); return ox::Error(0);
} }
}, },
}, },
}; };
int main(int argc, const char **args) { int main(int argc, const char **argv) {
if (argc < 2) { if (argc < 2) {
oxError("Must specify test to run"); oxError("Must specify test to run");
return -1; return -1;
} }
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::StringView const testName = args[1]; 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); auto const func = tests.find(testName);
if (func != tests.end()) { if (func != tests.end()) {
oxAssert(func->second(testArg), "Test returned Error"); oxAssert(func->second(testArg), "Test returned Error");

View File

@ -20,7 +20,7 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
std::ifstream file(path, std::ios::binary | std::ios::ate); std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.good()) { if (!file.good()) {
oxErrorf("Could not find OxFS file: {}", path); oxErrorf("Could not find OxFS file: {}", path);
return OxError(1, "Could not find OxFS file"); return ox::Error(1, "Could not find OxFS file");
} }
try { try {
const auto size = static_cast<std::size_t>(file.tellg()); const auto size = static_cast<std::size_t>(file.tellg());
@ -30,51 +30,52 @@ static ox::Result<Buff> loadFsBuff(const char *path) noexcept {
return Buff{buff, size}; return Buff{buff, size};
} catch (const std::ios_base::failure &e) { } catch (const std::ios_base::failure &e) {
oxErrorf("Could not read OxFS file: {}", e.what()); oxErrorf("Could not read OxFS file: {}", e.what());
return OxError(2, "Could not read OxFS file"); return ox::Error(2, "Could not read OxFS file");
} }
} }
static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept { static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexcept {
oxRequire(buff, loadFsBuff(path)); OX_REQUIRE(buff, loadFsBuff(path));
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
} }
static ox::Error runLs(ox::FileSystem *fs, int argc, const char **argv) noexcept { static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (argc < 2) { if (args.size() < 2) {
oxErr("Must provide a directory to ls\n"); oxErr("Must provide a directory to ls\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(files, fs->ls(argv[1])); OX_REQUIRE(files, fs->ls(args[1]));
for (const auto &file : files) { for (const auto &file : files) {
oxOutf("{}\n", file); oxOutf("{}\n", file);
} }
return OxError(0); return ox::Error(0);
} }
static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexcept { static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (argc < 2) { if (args.size() < 2) {
oxErr("Must provide a path to a file to read\n"); oxErr("Must provide a path to a file to read\n");
return OxError(1); return ox::Error(1);
} }
oxRequire(buff, fs->read(ox::StringView(argv[1]))); OX_REQUIRE(buff, fs->read(ox::StringView(args[1])));
fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout); std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
return OxError(0); return ox::Error(0);
} }
static ox::Error run(int argc, const char **argv) noexcept { static ox::Error run(int argc, const char **argv) noexcept {
if (argc < 3) { if (argc < 3) {
oxErr("OxFS file and subcommand arguments are required\n"); oxErr("OxFS file and subcommand arguments are required\n");
return OxError(1); return ox::Error(1);
} }
const auto fsPath = argv[1]; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::String subCmd(argv[2]); auto const fsPath = args[1];
oxRequire(fs, loadFs(fsPath)); ox::String subCmd(args[2]);
OX_REQUIRE(fs, loadFs(fsPath));
if (subCmd == "ls") { if (subCmd == "ls") {
return runLs(fs.get(), argc - 2, argv + 2); return runLs(fs.get(), args + 2);
} else if (subCmd == "read") { } 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) { int main(int argc, const char **argv) {

View File

@ -34,7 +34,7 @@ class CirculerBuffer {
constexpr ox::Error put(char v) noexcept { constexpr ox::Error put(char v) noexcept {
return write(&v, 1); return write(&v, 1);
if (1 > avail()) { if (1 > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
m_buff[m_writePt] = v; m_buff[m_writePt] = v;
++m_writePt; ++m_writePt;
@ -43,8 +43,9 @@ class CirculerBuffer {
constexpr ox::Error write(const char *buff, std::size_t sz) noexcept { constexpr ox::Error write(const char *buff, std::size_t sz) noexcept {
if (sz > avail()) { if (sz > avail()) {
return OxError(1, "Insufficient space in buffer"); return ox::Error(1, "Insufficient space in buffer");
} }
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// write seg 1 // write seg 1
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt); const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz); ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
@ -56,12 +57,13 @@ class CirculerBuffer {
ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz); ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
oxAssert(m_buff[0] == buff[seg1Sz], "break"); oxAssert(m_buff[0] == buff[seg1Sz], "break");
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} }
constexpr ox::Error seekp(std::size_t bytesFwd) noexcept { constexpr ox::Error seekp(std::size_t bytesFwd) noexcept {
if (bytesFwd > avail()) { if (bytesFwd > avail()) {
return OxError(1, "Insufficient space in buffer to seek that far ahead"); return ox::Error(1, "Insufficient space in buffer to seek that far ahead");
} }
m_writePt += bytesFwd; m_writePt += bytesFwd;
if (m_writePt > m_buff.size()) { if (m_writePt > m_buff.size()) {
@ -71,7 +73,7 @@ class CirculerBuffer {
} }
constexpr ox::Error seekp(int, ios_base::seekdir) noexcept { constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
return OxError(1, "Unimplemented"); return ox::Error(1, "Unimplemented");
} }
[[nodiscard]] [[nodiscard]]
@ -90,7 +92,9 @@ class CirculerBuffer {
m_readPt -= m_buff.size(); m_readPt -= m_buff.size();
// read seg 2 // read seg 2
const auto seg2Sz = bytesRead - seg1Sz; const auto seg2Sz = bytesRead - seg1Sz;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz); ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
OX_ALLOW_UNSAFE_BUFFERS_END
} }
return bytesRead; return bytesRead;
} }

View File

@ -9,8 +9,8 @@
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
#include <cstdio> #include <cstdio>
#include <sys/types.h>
#ifndef _WIN32 #ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -25,15 +25,22 @@
#include "logconn.hpp" #include "logconn.hpp"
#include <ox/std/bit.hpp>
namespace ox { namespace ox {
#ifdef _WIN32
using Socket = SOCKET;
using LenType = int;
#else
using Socket = int;
using LenType = size_t;
#endif
using namespace trace; using namespace trace;
void closeSock(auto s) noexcept { static void closeSock(auto s) noexcept {
#ifdef _WIN32 #ifdef _WIN32
closesocket(s); closesocket(static_cast<Socket>(s));
#else #else
close(s); close(s);
#endif #endif
@ -56,8 +63,8 @@ ox::Error LoggerConn::initConn(ox::StringViewCR appName) noexcept {
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(5590); addr.sin_port = htons(5590);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); m_socket = static_cast<int>(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
oxReturnError(OxError(static_cast<ox::ErrorCode>(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))); OX_RETURN_ERROR(ox::Error(static_cast<ox::ErrorCode>(connect(static_cast<Socket>(m_socket), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))));
return sendInit({.appName = ox::BasicString<128>(appName)}); return sendInit({.appName = ox::BasicString<128>(appName)});
} }
@ -65,10 +72,10 @@ ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
std::size_t totalSent = 0; std::size_t totalSent = 0;
while (totalSent < len) { while (totalSent < len) {
//std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket); //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) { if (sent < 0) {
std::fprintf(stderr, "Could not send msg\n"); std::ignore = std::fprintf(stderr, "Could not send msg\n");
return OxError(1, "Could not send msg"); return ox::Error(1, "Could not send msg");
} }
totalSent += static_cast<std::size_t>(sent); totalSent += static_cast<std::size_t>(sent);
} }
@ -90,13 +97,14 @@ void LoggerConn::msgSend() noexcept {
if (!m_running) { if (!m_running) {
break; break;
} }
std::lock_guard buffLk(m_buffMut); std::lock_guard const buffLk(m_buffMut);
while (true) { while (true) {
ox::Array<char, ox::units::KB> tmp; Array<char, units::KB> tmp;
const auto read = m_buff.read(tmp.data(), tmp.size()); const auto read = m_buff.read(tmp.data(), tmp.size());
if (!read) { if (!read) {
break; break;
} }
oxAssert(read <= tmp.size(), "logger trying to read too much data");
//std::printf("LoggerConn: sending %lu bytes\n", read); //std::printf("LoggerConn: sending %lu bytes\n", read);
std::ignore = send(tmp.data(), read); std::ignore = send(tmp.data(), read);
} }

View File

@ -45,13 +45,13 @@ class LoggerConn: public trace::Logger {
ox::Error send(trace::MsgId msgId, const auto &msg) noexcept { ox::Error send(trace::MsgId msgId, const auto &msg) noexcept {
ox::Array<char, 10 * ox::units::KB> buff; ox::Array<char, 10 * ox::units::KB> buff;
std::size_t sz = 0; std::size_t sz = 0;
oxReturnError(ox::writeMC(&buff[0], buff.size(), msg, &sz)); OX_RETURN_ERROR(ox::writeMC(&buff[0], buff.size(), msg, &sz));
//std::printf("sz: %lu\n", sz); //std::printf("sz: %lu\n", sz);
oxRequire(szBuff, serialize(static_cast<uint32_t>(sz))); OX_REQUIRE(szBuff, serialize(static_cast<uint32_t>(sz)));
std::unique_lock buffLk(m_buffMut); std::unique_lock buffLk(m_buffMut);
oxReturnError(m_buff.put(static_cast<char>(msgId))); OX_RETURN_ERROR(m_buff.put(static_cast<char>(msgId)));
oxReturnError(m_buff.write(szBuff.data(), szBuff.size())); OX_RETURN_ERROR(m_buff.write(szBuff.data(), szBuff.size()));
oxReturnError(m_buff.write(buff.data(), sz)); OX_RETURN_ERROR(m_buff.write(buff.data(), sz));
buffLk.unlock(); buffLk.unlock();
m_waitCond.notify_one(); m_waitCond.notify_one();
return {}; return {};

View File

@ -57,7 +57,7 @@ static_assert(highestBit(uint64_t(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63); static_assert(highestBit(uint64_t(1) << 63) == 63);
struct McInt { struct McInt {
uint8_t data[9] = {}; ox::Array<uint8_t, 9> data{};
// length of integer in bytes // length of integer in bytes
std::size_t length = 0; std::size_t length = 0;
}; };
@ -104,7 +104,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
auto intermediate = auto intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
ox::memcpy(out.data, &intermediate, sizeof(intermediate)); ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate));
} }
out.length = bytes; out.length = bytes;
} }
@ -135,19 +135,19 @@ static_assert(countBytes(0b1111'1111) == 9);
template<typename I> template<typename I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept { constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
uint8_t firstByte = 0; uint8_t firstByte = 0;
oxReturnError(rdr.read(&firstByte, 1)); OX_RETURN_ERROR(rdr.read(&firstByte, 1));
oxReturnError(rdr.seekg(-1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte); const auto bytes = countBytes(firstByte);
if (bytes == 9) { if (bytes == 9) {
*bytesRead = bytes; *bytesRead = bytes;
I out = 0; I out = 0;
oxReturnError(rdr.seekg(1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
oxReturnError(rdr.read(&out, sizeof(I))); OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
return fromLittleEndian<I>(out); return fromLittleEndian<I>(out);
} }
*bytesRead = bytes; *bytesRead = bytes;
uint64_t decoded = 0; uint64_t decoded = 0;
oxReturnError(rdr.read(&decoded, bytes)); OX_RETURN_ERROR(rdr.read(&decoded, bytes));
decoded >>= bytes; decoded >>= bytes;
// move sign bit // move sign bit
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
@ -160,7 +160,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
ox::Array<uint32_t, 2> d = {}; ox::Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
ox::memcpy(d.data(), &decoded, sizeof(decoded)); ox::memcpy(&d[0], &decoded, sizeof(decoded));
auto bit = negBit; auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
d[0] |= 1 << bit; d[0] |= 1 << bit;
@ -175,7 +175,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
d[0] = d[1]; d[0] = d[1];
d[1] = d0Tmp; d[1] = d0Tmp;
} }
ox::memcpy(&out, d.data(), sizeof(out)); ox::memcpy(&out, &d[0], sizeof(out));
return out; return out;
} }
} }
@ -185,7 +185,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
template<typename I> template<typename I>
Result<I> decodeInteger(McInt m) noexcept { Result<I> decodeInteger(McInt m) noexcept {
std::size_t bytesRead{}; 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); return decodeInteger<I>(br, &bytesRead);
} }

View File

@ -47,7 +47,7 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
constexpr auto blockBits = sizeof(m_mapBlock); constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits; auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] { if (m_mapBlockIdx != blockIdx) [[unlikely]] {
oxReturnError(loadMapBlock(blockIdx)); OX_RETURN_ERROR(loadMapBlock(blockIdx));
} }
idx %= blockBits; idx %= blockBits;
return (m_mapBlock >> idx) & 1; return (m_mapBlock >> idx) & 1;
@ -55,12 +55,12 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
template<Reader_c Reader> template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept { constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{}; ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv // Warning: narrow-conv
oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0; m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) { for (auto i = 0ull; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i; m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
@ -110,7 +110,7 @@ constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexce
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1; return (m_map[i / 8] >> (i % 8)) & 1;
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }
@ -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 { constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (on) { if (on) {
m_map[i / 8] |= 1 << (i % 8); m_map[i / 8] |= 1 << (i % 8);
} else { } else {
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8)); m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} else { } else {
return OxError(McPresenceMapOverflow); return ox::Error(McPresenceMapOverflow);
} }
} }

View File

@ -194,10 +194,10 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field)); auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
*val = result.value; *val = result.value;
oxReturnError(result); OX_RETURN_ERROR(result);
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
// array handler // 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
if (valLen >= len) { if (valLen >= len) {
auto reader = child({}); auto reader = child({});
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(handler.field({}, &val[i])); OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field({}, &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
} }
} else { } else {
oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen); oxTracef("ox.mc.read.field(T)", "{}, length: {}", name, valLen);
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
} }
} }
@ -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_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto &val) { constexpr auto loopBody = [](auto &handler, auto &val) {
oxRequire(keyLen, handler.stringLength(nullptr)); OX_REQUIRE(keyLen, handler.stringLength(nullptr));
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
auto wkeyPtr = wkey.get(); auto wkeyPtr = wkey.get();
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1)); OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
return handler.field("", &val[wkeyPtr]); return handler.field("", &val[wkeyPtr]);
}; };
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
oxReturnError(loopBody(handler, *val)); OX_RETURN_ERROR(loopBody(handler, *val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
oxReturnError(ox::resizeVector(*val, len)); OX_RETURN_ERROR(ox::resizeVector(*val, len));
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
} }
oxReturnError(ox::resizeVector(*val, 0)); OX_RETURN_ERROR(ox::resizeVector(*val, 0));
} }
++m_field; ++m_field;
return {}; return {};
@ -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) { if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
// set size of val if the field is present, don't worry about it if not // set size of val if the field is present, don't worry about it if not
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
oxRequire(len, arrayLength(name, false)); OX_REQUIRE(len, arrayLength(name, false));
if (len > val->size()) { if (len > val->size()) {
return OxError(1, "Input array is too long"); return ox::Error(1, "Input array is too long");
} }
} }
return field(name, val->data(), val->size()); return field(name, val->data(), val->size());
@ -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_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child(""); auto reader = child("");
oxReturnError(model(reader.interface(), val)); OX_RETURN_ERROR(model(reader.interface(), val));
} }
} }
++m_field; ++m_field;
@ -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_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) && val.get()) {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx())); auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
oxReturnError(model(reader.interface(), val.get())); OX_RETURN_ERROR(model(reader.interface(), val.get()));
} }
} }
++m_field; ++m_field;
@ -317,18 +319,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
const auto cap = size; const auto cap = size;
*val = BasicString<SmallStringSize>(cap); *val = BasicString<SmallStringSize>(cap);
auto data = val->data(); auto data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
*val = IString<L>(); *val = IString<L>();
oxReturnError(val->resize(size)); OX_RETURN_ERROR(val->resize(size));
auto const data = val->data(); auto const data = val->data();
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
} else { } else {
*val = ""; *val = "";
} }
@ -357,18 +359,18 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
if (size > buffLen) { if (size > buffLen) {
return OxError(McOutputBuffEnded); return ox::Error(McOutputBuffEnded);
} }
// re-allocate in case too small // re-allocate in case too small
auto data = val; auto data = val;
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data, size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate in case too small // re-allocate in case too small
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
auto data = *val; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead)); OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
// re-allocate if too small // re-allocate if too small
if (buffLen < size + 1) { if (buffLen < size + 1) {
safeDelete(*val); safeDelete(*val);
*val = new char[size + 1]; *val = new char[size + 1];
buffLen = size + 1; buffLen = size + 1;
} }
auto data = *val; auto data = ox::Span{*val, size + 1};
// read the string // read the string
oxReturnError(m_reader.read(data, size)); OX_RETURN_ERROR(m_reader.read(data.data(), size));
data[size] = 0; data[size] = 0;
} else { } else {
auto data = *val; auto data = *val;
@ -414,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
if (!pass) { if (!pass) {
oxReturnError(m_reader.seekg(g)); OX_RETURN_ERROR(m_reader.seekg(g));
} }
return out; return out;
} }
} }
return OxError(1); return ox::Error(1);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -441,7 +443,7 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead); auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
oxReturnError(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur)); OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
return len; return len;
} }
} }
@ -455,14 +457,14 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead); auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
oxReturnError(result); OX_RETURN_ERROR(result);
*val = result.value; *val = result.value;
} else { } else {
*val = 0; *val = 0;
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> 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))) { if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
// read the length // read the length
std::size_t bytesRead = 0; std::size_t bytesRead = 0;
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead)); OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
// read the list // read the list
auto reader = child(""); auto reader = child("");
auto &handler = *reader.interface(); auto &handler = *reader.interface();
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
T val; T val;
oxReturnError(handler.field("", &val)); OX_RETURN_ERROR(handler.field("", &val));
oxReturnError(cb(i, &val)); OX_RETURN_ERROR(cb(i, &val));
} }
} }
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Reader_c Reader> template<Reader_c Reader>
@ -546,7 +548,7 @@ Error readMC(ox::BufferView buff, T &val) noexcept {
template<typename T> template<typename T>
Result<T> readMC(ox::BufferView buff) noexcept { Result<T> readMC(ox::BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readMC(buff, val.value)); OX_RETURN_ERROR(readMC(buff, val.value));
return val; return val;
} }

View File

@ -62,47 +62,47 @@ struct TestStruct {
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("CString", &obj->CString)); OX_RETURN_ERROR(io->fieldCString("CString", &obj->CString));
return OxError(0); return ox::Error(0);
} }
oxModelBegin(TestStructNest) OX_MODEL_BEGIN(TestStructNest)
oxModelField(Bool) OX_MODEL_FIELD(Bool)
oxModelField(Int) OX_MODEL_FIELD(Int)
oxModelField(IString) OX_MODEL_FIELD(IString)
oxModelEnd() OX_MODEL_END()
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if constexpr(T::opType() == ox::OpType::Reflect) { if constexpr(T::opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("IString", &obj->IString)); OX_RETURN_ERROR(io->field("IString", &obj->IString));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Vector", &obj->Vector)); OX_RETURN_ERROR(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Vector2", &obj->Vector2)); OX_RETURN_ERROR(io->field("Vector2", &obj->Vector2));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
return OxError(0); return ox::Error(0);
} }
std::map<ox::StringView, ox::Error(*)()> tests = { std::map<ox::StringView, ox::Error(*)()> tests = {
@ -114,9 +114,9 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// doesn't segfault // doesn't segfault
ox::Array<char, 1024> buff; ox::Array<char, 1024> buff;
TestStruct ts; TestStruct ts;
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts)); OX_RETURN_ERROR(ox::writeMC(buff.data(), buff.size(), ts));
oxReturnError(ox::writeMC(ts)); OX_RETURN_ERROR(ox::writeMC(ts));
return OxError(0); return ox::Error(0);
} }
}, },
@ -176,7 +176,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch"); oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch"); oxAssert(testIn.Struct.IString == testOut.Struct.IString, "Struct.IString value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@ -189,28 +189,28 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) { static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) {
if (val.length != expected.size()) { if (val.length != expected.size()) {
std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n'; std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n';
return OxError(1); return ox::Error(1);
} }
for (std::size_t i = 0; i < expected.size(); i++) { for (std::size_t i = 0; i < expected.size(); i++) {
if (expected[i] != val.data[i]) { if (expected[i] != val.data[i]) {
std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n'; std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n';
std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n'; std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
return OxError(1); return ox::Error(1);
} }
} }
return OxError(0); return ox::Error(0);
}; };
constexpr auto check64 = [](McInt val, auto expected) { constexpr auto check64 = [](McInt val, auto expected) {
if (val.length != 9) { if (val.length != 9) {
std::cout << "val.length: " << val.length << '\n'; std::cout << "val.length: " << val.length << '\n';
return OxError(1); return ox::Error(1);
} }
ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]); ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]);
if (expected != decoded) { if (expected != decoded) {
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n'; std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
// signed positive // signed positive
oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail"); oxAssert(check(encodeInteger(int64_t(1)), {0b000'0001'0}), "Encode 1 fail");
@ -247,7 +247,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// code deduplication // code deduplication
oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<int64_t>), MaxValue<int64_t>), "Encode MaxValue<int64_t> fail");
oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail"); oxAssert(check64(encodeInteger(MaxValue<uint64_t>), MaxValue<uint64_t>), "Encode MaxValue<uint64_t> fail");
return OxError(0); return ox::Error(0);
} }
}, },
@ -260,12 +260,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
using ox::mc::decodeInteger; using ox::mc::decodeInteger;
static constexpr auto check = [](auto val) { static constexpr auto check = [](auto val) {
auto result = decodeInteger<decltype(val)>(encodeInteger(val)); auto result = decodeInteger<decltype(val)>(encodeInteger(val));
oxReturnError(result.error); OX_RETURN_ERROR(result.error);
if (result.value != val) { if (result.value != val) {
std::cout << "Bad value: " << result.value << ", expected: " << val << '\n'; std::cout << "Bad value: " << result.value << ", expected: " << val << '\n';
return OxError(1); return ox::Error(1);
} }
return OxError(0); return ox::Error(0);
}; };
oxAssert(check(uint32_t(14)), "Decode of 14 failed."); oxAssert(check(uint32_t(14)), "Decode of 14 failed.");
oxAssert(check(int8_t(-1)), "Decode of -1 failed."); oxAssert(check(int8_t(-1)), "Decode of -1 failed.");
@ -291,7 +291,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(check(0xffffffff), "Decode of 0xffffffff failed."); oxAssert(check(0xffffffff), "Decode of 0xffffffff failed.");
oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed."); oxAssert(check(0xffffffffffff), "Decode of 0xffffffffffff failed.");
oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed."); oxAssert(check(0xffffffffffffffff), "Decode of U64 max failed.");
return OxError(0); return ox::Error(0);
} }
}, },
@ -319,7 +319,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type)); OX_RETURN_ERROR(testOut.setType(type));
oxAssert(ox::readMC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@ -344,7 +344,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed"); oxAssert(testOutStructCopy.at("IString").unwrap()->get<ox::String>() == testIn.Struct.IString.c_str(), "testOut.Struct.IString (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@ -371,7 +371,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn); const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::BufferReader br({dataBuff, dataBuffLen}); ox::BufferReader br({dataBuff, dataBuffLen});
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br, OX_RETURN_ERROR(ox::walkModel<ox::MetalClawReader>(type, br,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n'; //std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@ -454,10 +454,10 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -117,12 +117,12 @@ class MetalClawWriter {
bool fieldSet = false; bool fieldSet = false;
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
}; };
@ -181,10 +181,10 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val)
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
} }
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -194,14 +194,14 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<Sm
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->len()); const auto strLen = mc::encodeInteger(val->len());
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
// write the string // write the string
oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len()))); OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -217,14 +217,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *c
const auto strLen = *val ? ox::strlen(*val) : 0; const auto strLen = *val ? ox::strlen(*val) : 0;
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -243,14 +243,14 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -264,11 +264,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer}; ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@ -282,11 +282,11 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@ -298,21 +298,23 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::s
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
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(); fieldSet = writeIdx != m_writer.tellp();
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -324,32 +326,32 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
// write map // write map
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
// double len for both key and value // double len for both key and value
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2)); OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error { constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.len(); const auto keyLen = key.len();
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1); memcpy(wkey.get(), key.c_str(), keyLen + 1);
oxReturnError(handler.fieldCString("", wkey.get(), keyLen)); OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
oxRequireM(value, val.at(key)); OX_REQUIRE_M(value, val.at(key));
return handler.field("", value); return handler.field("", value);
}; };
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
auto const&key = keys[i]; auto const&key = keys[i];
oxReturnError(loopBody(handler, key, *val)); OX_RETURN_ERROR(loopBody(handler, key, *val));
} }
oxReturnError(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return ox::Error(0);
} }
template<Writer_c Writer> template<Writer_c Writer>
@ -360,7 +362,7 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
const Vector<String>&, const Vector<String>&,
std::size_t fields) noexcept { std::size_t fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1; const auto fieldPresenceLen = (fields - 1) / 8 + 1;
oxReturnError(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields)); m_fieldPresence.setFields(static_cast<int>(fields));
@ -370,33 +372,33 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
template<Writer_c Writer> template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept { ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp(); const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP)); OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write( OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()), reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size())); m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end)); OX_RETURN_ERROR(m_writer.seekp(end));
return {}; return {};
} }
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
MetalClawWriter mcWriter(writer); MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{&mcWriter}; ModelHandlerInterface handler{&mcWriter};
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
oxReturnError(mcWriter.finalize()); OX_RETURN_ERROR(mcWriter.finalize());
return {}; return {};
} }
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz); Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0); BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
buff.resize(bw.tellp()); buff.resize(bw.tellp());
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw(buff, buffLen); CharBuffWriter bw{{buff, buffLen}};
oxReturnError(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {
*sizeOut = bw.tellp(); *sizeOut = bw.tellp();
} }

View File

@ -11,9 +11,9 @@
#include <ox/std/concepts.hpp> #include <ox/std/concepts.hpp>
// oxModelFwdDecl is necessary because Apple-Clang is broken... // oxModelFwdDecl is necessary because Apple-Clang is broken...
#define oxModelFwdDecl(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>()); #define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>());
#define oxModelEnd() return OxError(0); } #define OX_MODEL_END() return ox::Error(0); }
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName)); #define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); #define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept #define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept

View File

@ -76,21 +76,21 @@ struct Subscript {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<Subscript>()); OX_RETURN_ERROR(io->template setTypeInfo<Subscript>());
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint32_t st = 0; uint32_t st = 0;
oxReturnError(io->field("subscriptType", &st)); OX_RETURN_ERROR(io->field("subscriptType", &st));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint8_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
} else { } else {
auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0; auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0;
oxReturnError(io->field("subscriptType", &pt)); OX_RETURN_ERROR(io->field("subscriptType", &pt));
type->subscriptType = static_cast<Subscript::SubscriptType>(pt); type->subscriptType = static_cast<Subscript::SubscriptType>(pt);
} }
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("smallSzLen", &type->smallSzLen)); OX_RETURN_ERROR(io->field("smallSzLen", &type->smallSzLen));
return OxError(0); return {};
} }
using SubscriptStack = Vector<Subscript, 3>; using SubscriptStack = Vector<Subscript, 3>;
@ -119,6 +119,7 @@ struct DescriptorField {
subscriptLevels(pSubscriptLevels), subscriptLevels(pSubscriptLevels),
subscriptStack(std::move(pSubscriptType)), subscriptStack(std::move(pSubscriptType)),
typeId(std::move(pTypeId)) { typeId(std::move(pTypeId)) {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "Subscript level mismatch");
} }
constexpr DescriptorField(const DescriptorField &other) noexcept: constexpr DescriptorField(const DescriptorField &other) noexcept:
@ -184,38 +185,38 @@ constexpr auto buildTypeId(const DescriptorType &t) noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorType>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorType>());
oxReturnError(io->field("typeName", &type->typeName)); OX_RETURN_ERROR(io->field("typeName", &type->typeName));
oxReturnError(io->field("typeVersion", &type->typeVersion)); OX_RETURN_ERROR(io->field("typeVersion", &type->typeVersion));
if constexpr(T::opType() == OpType::Reflect) { if constexpr(T::opType() == OpType::Reflect) {
uint8_t pt = 0; uint8_t pt = 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else if constexpr(T::opType() == OpType::Write) { } else if constexpr(T::opType() == OpType::Write) {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
} else { } else {
auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0; auto pt = type ? static_cast<uint8_t>(type->primitiveType) : 0;
oxReturnError(io->field("primitiveType", &pt)); OX_RETURN_ERROR(io->field("primitiveType", &pt));
type->primitiveType = static_cast<PrimitiveType>(pt); type->primitiveType = static_cast<PrimitiveType>(pt);
} }
oxReturnError(io->field("typeParams", &type->typeParams)); OX_RETURN_ERROR(io->field("typeParams", &type->typeParams));
oxReturnError(io->field("fieldList", &type->fieldList)); OX_RETURN_ERROR(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length)); OX_RETURN_ERROR(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable)); OX_RETURN_ERROR(io->field("preloadable", &type->preloadable));
return OxError(0); return {};
} }
template<typename T> template<typename T>
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept { constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
oxReturnError(io->template setTypeInfo<DescriptorField>()); OX_RETURN_ERROR(io->template setTypeInfo<DescriptorField>());
oxReturnError(io->field("typeId", &field->typeId)); OX_RETURN_ERROR(io->field("typeId", &field->typeId));
oxReturnError(io->field("fieldName", &field->fieldName)); OX_RETURN_ERROR(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels)); OX_RETURN_ERROR(io->field("subscriptLevels", &field->subscriptLevels));
oxReturnError(io->field("subscriptStack", &field->subscriptStack)); OX_RETURN_ERROR(io->field("subscriptStack", &field->subscriptStack));
// defaultValue is unused now, but leave placeholder for backwards compatibility // defaultValue is unused now, but leave placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); OX_RETURN_ERROR(io->field("defaultValue", &defaultValue));
return OxError(0); return {};
} }
template<typename ReaderBase> 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 // defaultValue is unused now, but placeholder for backwards compatibility
int defaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue)); oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0); return ox::Error(0);
} }
#endif #endif

View File

@ -97,8 +97,14 @@ class TypeDescWriter {
std::size_t fields = ModelFieldCount_v<T>) noexcept; std::size_t fields = ModelFieldCount_v<T>) noexcept;
template<typename T> template<typename T>
constexpr Error field(StringViewCR name, const T *val, std::size_t valLen, constexpr Error field(
const SubscriptStack &subscriptStack = {}) noexcept; 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> template<typename T, bool force>
constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept; constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept;
@ -193,15 +199,30 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
// array handler // array handler
template<typename T> 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) { if (m_type) {
constexpr typename remove_pointer<T>::type *p = nullptr; constexpr typename remove_pointer<T>::type *p = nullptr;
const auto t = type(p); const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t)); m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
return OxError(0); return ox::Error(0);
} }
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 ox::Error(0);
}
return ox::Error(1);
} }
template<typename T, bool force> template<typename T, bool force>
@ -210,9 +231,9 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName)); m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return OxError(0); return ox::Error(0);
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
@ -233,7 +254,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept
return {}; return {};
} }
} }
return OxError(1); return ox::Error(1);
} }
template<typename ...Args> template<typename ...Args>
@ -363,11 +384,11 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
std::allocator<T> a; std::allocator<T> a;
T *t = a.allocate(1); T *t = a.allocate(1);
oxReturnError(model(&handler, t)); OX_RETURN_ERROR(model(&handler, t));
a.deallocate(t, 1); a.deallocate(t, 1);
} else { } else {
auto t = ox_malloca(sizeof(T), T); auto t = ox_malloca(sizeof(T), T);
oxReturnError(model(&handler, t.get())); OX_RETURN_ERROR(model(&handler, t.get()));
} }
return writer.definition(); return writer.definition();
} }
@ -376,7 +397,7 @@ template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore); TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer); ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
return writer.definition(); return writer.definition();
} }

View File

@ -31,25 +31,25 @@ class FieldCounter {
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U) noexcept { constexpr ox::Error field(StringViewCR, U) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename U> template<typename U>
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept { constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename U, typename Handler> template<typename U, typename Handler>
constexpr Error field(StringViewCR, Handler) { constexpr Error field(StringViewCR, Handler) {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
++fields; ++fields;
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {

View File

@ -135,8 +135,8 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>()); return m_handler->field(name, &v->template get<ModelValueArray>());
} }
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type())); oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(OxError(1), "invalid type"); oxPanic(ox::Error(1), "invalid type");
return OxError(1, "invalid type"); return ox::Error(1, "invalid type");
} }
// array handler, with callback to allow handling individual elements // array handler, with callback to allow handling individual elements

View File

@ -56,19 +56,19 @@ class MemberList {
template<typename T> template<typename T>
constexpr Error field(const char*, T *v) noexcept { constexpr Error field(const char*, T *v) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T *v, int) noexcept { constexpr Error field(const char*, T *v, int) noexcept {
vars[m_i++] = static_cast<void*>(v); vars[m_i++] = static_cast<void*>(v);
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> u) noexcept { constexpr Error field(const char*, UnionView<U, force> u) noexcept {
vars[m_i++] = static_cast<void*>(u.get()); vars[m_i++] = static_cast<void*>(u.get());
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -107,7 +107,7 @@ class Copier {
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]); auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
dst = src; dst = src;
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
} }
@ -119,7 +119,7 @@ class Copier {
dst = src; dst = src;
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -128,7 +128,7 @@ class Copier {
auto &src = *u.get(); auto &src = *u.get();
dst = src; dst = src;
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename T = void> template<typename T = void>
@ -168,7 +168,7 @@ class Mover {
dst = std::move(src); dst = std::move(src);
src = FT{}; src = FT{};
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
} }
@ -181,7 +181,7 @@ class Mover {
src = FT{}; src = FT{};
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -190,7 +190,7 @@ class Mover {
auto &src = *u.get(); auto &src = *u.get();
dst = std::move(src); dst = std::move(src);
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename T = void> template<typename T = void>
@ -228,10 +228,10 @@ class Equals {
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]); const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return ox::Error(0);
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
@ -242,11 +242,11 @@ class Equals {
const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i]; const auto &dst = cbit_cast<FT*>(m_other->vars[m_i])[i];
if (!(dst == src)) { if (!(dst == src)) {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }
++m_i; ++m_i;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force = false> template<typename U, bool force = false>
@ -255,10 +255,10 @@ class Equals {
const auto &src = *u.get(); const auto &src = *u.get();
++m_i; ++m_i;
if (dst == src) { if (dst == src) {
return OxError(0); return ox::Error(0);
} else { } else {
this->value = false; this->value = false;
return OxError(1); return ox::Error(1);
} }
} }

View File

@ -12,12 +12,12 @@ namespace ox {
static_assert([]() -> ox::Error { static_assert([]() -> ox::Error {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
if (v.type() != ModelValue::Type::SignedInteger32) { if (v.type() != ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
//oxReturnError(v.set<int32_t>(5)); //oxReturnError(v.set<int32_t>(5));
return {}; return {};
}() == OxError(0)); }() == ox::Error(0));
} }

View File

@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept { constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept { constexpr auto &get() noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
oxPanic(OxError(1), "invalid cast"); oxPanic(ox::Error(1), "invalid cast");
} }
return getValue<type>(*this); return getValue<type>(*this);
} }
@ -188,8 +188,8 @@ class ModelValue {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels = 0, SubscriptStack const& = {},
SubscriptStack const& = {}) noexcept; int subscriptLevels = 0) noexcept;
template<typename T> template<typename T>
constexpr Error setType() noexcept; constexpr Error setType() noexcept;
@ -242,7 +242,7 @@ class ModelValueArray {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@ -276,8 +276,9 @@ class ModelValueArray {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels, SubscriptStack subscriptStack,
SubscriptStack subscriptStack) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type; m_type = type;
m_typeSubscriptLevels = subscriptLevels; m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack); m_subscriptStack = std::move(subscriptStack);
@ -400,7 +401,7 @@ class ModelValueVector {
m_vec.resize(sz); m_vec.resize(sz);
if (sz > oldSz) { if (sz > oldSz) {
for (auto i = oldSz; i < sz; ++i) { for (auto i = oldSz; i < sz; ++i) {
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack)); OX_RETURN_ERROR(m_vec[i].setType(m_type, m_subscriptStack, m_typeSubscriptLevels));
} }
} }
return {}; return {};
@ -418,8 +419,9 @@ class ModelValueVector {
constexpr Error setType( constexpr Error setType(
DescriptorType const*type, DescriptorType const*type,
int subscriptLevels, SubscriptStack subscriptStack,
SubscriptStack subscriptStack) noexcept { int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
m_type = type; m_type = type;
m_typeSubscriptLevels = subscriptLevels; m_typeSubscriptLevels = subscriptLevels;
m_subscriptStack = std::move(subscriptStack); m_subscriptStack = std::move(subscriptStack);
@ -517,7 +519,7 @@ class ModelObject {
ModelValue value; ModelValue value;
}; };
protected: protected:
oxModelFriend(ModelObject); OX_MODEL_FRIEND(ModelObject);
friend ModelValue; friend ModelValue;
Vector<UniquePtr<Field>> m_fieldsOrder; Vector<UniquePtr<Field>> m_fieldsOrder;
HashMap<String, ModelValue*> m_fields; HashMap<String, ModelValue*> m_fields;
@ -632,18 +634,18 @@ class ModelObject {
if (m_fields.contains(k)) { if (m_fields.contains(k)) {
return *m_fields.at(k).value; return *m_fields.at(k).value;
} }
return OxError(1); return ox::Error(1);
} }
template<typename T> template<typename T>
constexpr Error set(const String &k, T &&val) noexcept { constexpr Error set(const String &k, T &&val) noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
*t = ox::forward<T>(val); *t = ox::forward<T>(val);
return {}; return {};
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return *v; return *v;
} }
@ -668,17 +670,17 @@ class ModelObject {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelObject"); return ox::Error(1, "Cannot load a non-struct type to ModelObject");
} }
m_type = type; m_type = type;
for (const auto &f : type->fieldList) { for (const auto &f : type->fieldList) {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
oxReturnError(field->value.setType(f.type, f.subscriptLevels, f.subscriptStack)); OX_RETURN_ERROR(field->value.setType(f.type, f.subscriptStack, f.subscriptLevels));
m_fields[field->name] = &field->value; m_fields[field->name] = &field->value;
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
} }
return OxError(0); return {};
} }
}; };
@ -720,7 +722,7 @@ class ModelUnion {
static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept { static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept {
UniquePtr<ModelUnion> out(new ModelUnion); UniquePtr<ModelUnion> out(new ModelUnion);
oxReturnError(out->setType(type)); OX_RETURN_ERROR(out->setType(type));
return out; return out;
} }
@ -729,7 +731,7 @@ class ModelUnion {
} }
constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept { constexpr ox::Result<ModelValue*> at(StringView const&k) noexcept {
oxRequire(v, m_fields.at(k)); OX_REQUIRE(v, m_fields.at(k));
return &(*v)->value; return &(*v)->value;
} }
@ -761,7 +763,7 @@ class ModelUnion {
[[nodiscard]] [[nodiscard]]
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept { constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
oxRequire(t, m_fields.at(k)); OX_REQUIRE(t, m_fields.at(k));
return &(*t)->value; return &(*t)->value;
} }
@ -788,7 +790,7 @@ class ModelUnion {
constexpr Error setType(const DescriptorType *type) noexcept { constexpr Error setType(const DescriptorType *type) noexcept {
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) { if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
return OxError(1, "Cannot load a non-struct type to ModelUnion"); return ox::Error(1, "Cannot load a non-struct type to ModelUnion");
} }
m_fields.clear(); m_fields.clear();
m_fieldsOrder.clear(); m_fieldsOrder.clear();
@ -797,12 +799,12 @@ class ModelUnion {
auto field = make_unique<Field>(); auto field = make_unique<Field>();
field->name = f.fieldName; field->name = f.fieldName;
field->idx = i; field->idx = i;
oxReturnError(field->value.setType(f.type, f.subscriptLevels)); OX_RETURN_ERROR(field->value.setType(f.type, SubscriptStack{static_cast<size_t>(f.subscriptLevels)}, f.subscriptLevels));
m_fields[field->name] = field.get(); m_fields[field->name] = field.get();
m_fieldsOrder.emplace_back(std::move(field)); m_fieldsOrder.emplace_back(std::move(field));
++i; ++i;
} }
return OxError(0); return {};
} }
[[nodiscard]] [[nodiscard]]
@ -965,21 +967,21 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept {
} }
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelObject>( OX_RETURN_ERROR(h->template setTypeInfo<ModelObject>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return ox::Error(0);
} }
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept { constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
oxReturnError(h->template setTypeInfo<ModelUnion>( OX_RETURN_ERROR(h->template setTypeInfo<ModelUnion>(
obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size())); obj->typeName().c_str(), obj->typeVersion(), {}, obj->m_fieldsOrder.size()));
for (auto &f : obj->m_fieldsOrder) { for (auto &f : obj->m_fieldsOrder) {
oxReturnError(h->field(f->name.c_str(), &f->value)); OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
} }
return OxError(0); return ox::Error(0);
} }
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept { constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
@ -1076,20 +1078,21 @@ constexpr ModelValue::Type ModelValue::type() const noexcept {
constexpr Error ModelValue::setType( constexpr Error ModelValue::setType(
const DescriptorType *type, const DescriptorType *type,
int subscriptLevels, SubscriptStack const&subscriptStack,
SubscriptStack const&subscriptStack) noexcept { int subscriptLevels) noexcept {
freeResources(); freeResources();
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
if (subscriptLevels) { if (subscriptLevels) {
auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)]; auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)];
if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) { if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) {
m_type = Type::InlineArray; m_type = Type::InlineArray;
m_data.array = new ModelValueArray; m_data.array = new ModelValueArray;
oxReturnError(m_data.array->setType(type, subscriptLevels - 1, subscriptStack)); OX_RETURN_ERROR(m_data.array->setType(type, subscriptStack, subscriptLevels - 1));
oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length))); OX_RETURN_ERROR(m_data.array->setSize(static_cast<size_t>(subscript.length)));
} else { } else {
m_type = Type::Vector; m_type = Type::Vector;
m_data.vec = new ModelValueVector; m_data.vec = new ModelValueVector;
oxReturnError(m_data.vec->setType(type, subscriptLevels - 1, subscriptStack)); OX_RETURN_ERROR(m_data.vec->setType(type, subscriptStack, subscriptLevels - 1));
} }
return {}; return {};
} else if (type->typeName == types::Bool) { } else if (type->typeName == types::Bool) {
@ -1118,15 +1121,15 @@ constexpr Error ModelValue::setType(
} else if (type->primitiveType == PrimitiveType::Struct) { } else if (type->primitiveType == PrimitiveType::Struct) {
m_type = Type::Object; m_type = Type::Object;
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if (type->primitiveType == PrimitiveType::Union) { } else if (type->primitiveType == PrimitiveType::Union) {
m_type = Type::Union; m_type = Type::Union;
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} }
oxAssert(m_type != Type::Undefined, "No type set"); oxAssert(m_type != Type::Undefined, "No type set");
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -1138,11 +1141,11 @@ constexpr Error ModelValue::setType() noexcept {
// rather than using getValue<type>() // rather than using getValue<type>()
if constexpr(type == Type::Object) { if constexpr(type == Type::Object) {
m_data.obj = new ModelObject; m_data.obj = new ModelObject;
oxReturnError(m_data.obj->setType(type)); OX_RETURN_ERROR(m_data.obj->setType(type));
} else if constexpr(type == Type::Union) { } else if constexpr(type == Type::Union) {
oxRequireM(u, ModelUnion::make(type)); OX_REQUIRE_M(u, ModelUnion::make(type));
m_data.uni = u.release(); m_data.uni = u.release();
oxReturnError(m_data.uni->setType(type)); OX_RETURN_ERROR(m_data.uni->setType(type));
} else if constexpr(type == Type::String) { } else if constexpr(type == Type::String) {
m_data.str = new String; m_data.str = new String;
} else if constexpr(type == Type::Vector) { } else if constexpr(type == Type::Vector) {
@ -1173,7 +1176,7 @@ template<typename T>
constexpr Error ModelValue::set(const T &v) noexcept { constexpr Error ModelValue::set(const T &v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@ -1181,14 +1184,14 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = v; value = v;
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error ModelValue::set(T &&v) noexcept { constexpr Error ModelValue::set(T &&v) noexcept {
constexpr auto type = getType<T>(); constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] { if (m_type != type) [[unlikely]] {
return OxError(1, "type mismatch"); return ox::Error(1, "type mismatch");
} }
auto &value = getValue<type>(*this); auto &value = getValue<type>(*this);
if constexpr(type == Type::Vector || type == Type::Object || if constexpr(type == Type::Vector || type == Type::Object ||
@ -1196,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value); safeDelete(&value);
} }
value = std::move(v); value = std::move(v);
return OxError(0); return ox::Error(0);
} }
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept { constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {

View File

@ -17,8 +17,8 @@ struct TestType {
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
}; };
oxModelBegin(TestType) OX_MODEL_BEGIN(TestType)
oxModelEnd() OX_MODEL_END()
struct TestType2 { struct TestType2 {
}; };
@ -38,12 +38,12 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
"ModelValue", "ModelValue",
[] { [] {
ox::ModelValue v; ox::ModelValue v;
oxReturnError(v.setType<int32_t>()); OX_RETURN_ERROR(v.setType<int32_t>());
//v.m_type = ox::ModelValue::getType<int32_t>(); //v.m_type = ox::ModelValue::getType<int32_t>();
if (v.type() != ox::ModelValue::Type::SignedInteger32) { if (v.type() != ox::ModelValue::Type::SignedInteger32) {
return OxError(1, "type is wrong"); return ox::Error(1, "type is wrong");
} }
oxReturnError(v.set<int32_t>(5)); OX_RETURN_ERROR(v.set<int32_t>(5));
return ox::Error{}; return ox::Error{};
} }
}, },

View File

@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename ...Args> template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept { constexpr Error fieldCString(Args&&...) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
@ -77,17 +77,17 @@ struct TypeInfoCatcher {
template<typename T> template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept { constexpr Error field(const char*, T*, std::size_t) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error field(const char*, T) noexcept { constexpr Error field(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
constexpr Error fieldCString(const char*, T) noexcept { constexpr Error fieldCString(const char*, T) noexcept {
return OxError(0); return ox::Error(0);
} }
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {

View File

@ -31,7 +31,7 @@ class TypeStore {
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion, constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
const TypeParamPack &typeParams) const noexcept { const TypeParamPack &typeParams) const noexcept {
const auto typeId = buildTypeId(name, typeVersion, typeParams); const auto typeId = buildTypeId(name, typeVersion, typeParams);
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@ -40,7 +40,7 @@ class TypeStore {
constexpr auto typeName = ModelTypeName_v<T>; constexpr auto typeName = ModelTypeName_v<T>;
constexpr auto typeVersion = ModelTypeVersion_v<T>; constexpr auto typeVersion = ModelTypeVersion_v<T>;
const auto typeId = buildTypeId(typeName, typeVersion, {}); const auto typeId = buildTypeId(typeName, typeVersion, {});
oxRequire(out, m_cache.at(typeId)); OX_REQUIRE(out, m_cache.at(typeId));
return out->get(); return out->get();
} }
@ -56,15 +56,15 @@ class TypeStore {
auto [val, err] = m_cache.at(typeId); auto [val, err] = m_cache.at(typeId);
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeId)); OX_REQUIRE_M(dt, loadDescriptor(typeId));
for (auto &f : dt->fieldList) { for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeId).moveTo(f.type)); OX_RETURN_ERROR(this->getLoad(f.typeId).moveTo(f.type));
} }
auto &out = m_cache[typeId]; auto &out = m_cache[typeId];
out = std::move(dt); out = std::move(dt);
return out.get(); return out.get();
} else { } else {
return OxError(1, "Type not available"); return ox::Error(1, "Type not available");
} }
} }
return val->get(); return val->get();
@ -102,7 +102,7 @@ class TypeStore {
protected: protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept { virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return OxError(1); return ox::Error(1);
} }
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version, Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringViewCR name, int version,

View File

@ -50,7 +50,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler
template<typename Reader, typename T> template<typename Reader, typename T>
constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept { constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept {
oxRequire(out, m_typeStack.back()); OX_REQUIRE(out, m_typeStack.back());
return *out; return *out;
} }
@ -87,9 +87,9 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
walker->pushNamePath(field.fieldName); walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) { if (field.subscriptLevels) {
// add array handling // add array handling
oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); OX_REQUIRE(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true));
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
oxReturnError(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen)); OX_RETURN_ERROR(child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen));
DescriptorField f(field); // create mutable copy DescriptorField f(field); // create mutable copy
--f.subscriptLevels; --f.subscriptLevels;
String subscript; String subscript;
@ -98,7 +98,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
subscript += static_cast<uint64_t>(i); subscript += static_cast<uint64_t>(i);
subscript += "]"; subscript += "]";
walker->pushNamePath(subscript); walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker)); OX_RETURN_ERROR(parseField(f, &child, walker));
walker->popNamePath(); walker->popNamePath();
} }
rdr->nextField(); rdr->nextField();
@ -108,40 +108,40 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
case PrimitiveType::SignedInteger: case PrimitiveType::SignedInteger:
case PrimitiveType::Bool: case PrimitiveType::Bool:
case PrimitiveType::String: case PrimitiveType::String:
oxReturnError(walker->read(field, rdr)); OX_RETURN_ERROR(walker->read(field, rdr));
break; break;
case PrimitiveType::Struct: case PrimitiveType::Struct:
case PrimitiveType::Union: case PrimitiveType::Union:
if (rdr->fieldPresent(field.fieldName.c_str())) { if (rdr->fieldPresent(field.fieldName.c_str())) {
auto child = rdr->child(field.fieldName.c_str()); auto child = rdr->child(field.fieldName.c_str());
walker->pushType(field.type); walker->pushType(field.type);
oxReturnError(model(&child, walker)); OX_RETURN_ERROR(model(&child, walker));
walker->popType(); walker->popType();
rdr->nextField(); rdr->nextField();
} else { } else {
// skip and discard absent field // skip and discard absent field
int discard; int discard;
oxReturnError(rdr->field(field.fieldName.c_str(), &discard)); OX_RETURN_ERROR(rdr->field(field.fieldName.c_str(), &discard));
} }
break; break;
} }
} }
walker->popNamePath(); walker->popNamePath();
return OxError(0); return ox::Error(0);
} }
template<typename Reader, typename FH> template<typename Reader, typename FH>
constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept { constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
oxRequire(type, walker->type()); OX_REQUIRE(type, walker->type());
auto typeName = type->typeName.c_str(); auto typeName = type->typeName.c_str();
auto typeVersion = type->typeVersion; auto typeVersion = type->typeVersion;
auto typeParams = type->typeParams; auto typeParams = type->typeParams;
auto &fields = type->fieldList; auto &fields = type->fieldList;
oxReturnError(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size())); OX_RETURN_ERROR(rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size()));
for (const auto &field : fields) { for (const auto &field : fields) {
oxReturnError(parseField(field, rdr, walker)); OX_RETURN_ERROR(parseField(field, rdr, walker));
} }
return OxError(0); return ox::Error(0);
} }
template<typename Reader, typename Handler> template<typename Reader, typename Handler>

View File

@ -19,7 +19,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize)
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@ -27,7 +27,7 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxException(1, "Could not parse JSON"); throw ox::Exception(1, "Could not parse JSON");
} }
} }
@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
} }
Error OrganicClawReader::field(const char *key, bool *val) noexcept { Error OrganicClawReader::field(const char *key, bool *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -45,7 +45,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} else if (jv.isBool()) { } else if (jv.isBool()) {
*val = jv.asBool(); *val = jv.asBool();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@ -67,13 +67,13 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
const auto strSize = static_cast<std::size_t>(end - begin); const auto strSize = static_cast<std::size_t>(end - begin);
auto data = val; auto data = val;
if (strSize >= buffLen) { if (strSize >= buffLen) {
err = OxError(2, "String size exceeds capacity of destination"); err = ox::Error(2, "String size exceeds capacity of destination");
} else { } else {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} }
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
} }
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
auto &data = *val; auto &data = *val;
@ -98,7 +98,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0; data[strSize] = 0;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
} }
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept { Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
const char *begin = nullptr, *end = nullptr; const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key); const auto &jv = value(key);
if (targetValid()) { if (targetValid()) {
@ -126,7 +126,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
ox::memcpy(data, begin, static_cast<std::size_t>(strSize)); ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = nullptr; data[strSize] = nullptr;
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -135,7 +135,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
Error OrganicClawReader::field(const char *key, UUID *val) noexcept { Error OrganicClawReader::field(const char *key, UUID *val) noexcept {
UUIDStr str; UUIDStr str;
oxReturnError(field(key, &str)); OX_RETURN_ERROR(field(key, &str));
return UUID::fromString(str).moveTo(*val); return UUID::fromString(str).moveTo(*val);
} }
@ -147,7 +147,7 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
if (jv.isArray()) { if (jv.isArray()) {
return jv.size(); return jv.size();
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
[[nodiscard]] [[nodiscard]]
@ -161,7 +161,7 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
jv.getString(&begin, &end); jv.getString(&begin, &end);
return static_cast<std::size_t>(end - begin); return static_cast<std::size_t>(end - begin);
} }
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept { OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {

View File

@ -133,7 +133,7 @@ class OrganicClawReader {
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept { Error OrganicClawReader::field(const char *key, T *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
try { try {
if constexpr (is_integer_v<T>) { if constexpr (is_integer_v<T>) {
if (targetValid()) { if (targetValid()) {
@ -146,19 +146,19 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
} else if (rightType) { } else if (rightType) {
*val = static_cast<T>(jv.asUInt()); *val = static_cast<T>(jv.asUInt());
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
} else if constexpr (isVector_v<T>) { } else if constexpr (isVector_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
oxReturnError(ox::resizeVector(*val, srcSize)); OX_RETURN_ERROR(ox::resizeVector(*val, srcSize));
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) { } else if constexpr (isArray_v<T>) {
const auto&srcVal = value(key); const auto&srcVal = value(key);
const auto srcSize = srcVal.size(); const auto srcSize = srcVal.size();
if (srcSize > val->size()) { if (srcSize > val->size()) {
err = OxError(1, "Input array is too long"); err = ox::Error(1, "Input array is too long");
} else { } else {
err = field(key, val->data(), val->size()); err = field(key, val->data(), val->size());
} }
@ -169,11 +169,11 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val); err = model(&handler, val);
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
} catch (Json::LogicError const&) { } catch (Json::LogicError const&) {
err = OxError(1, "error reading JSON data"); err = ox::Error(1, "error reading JSON data");
} }
++m_fieldIt; ++m_fieldIt;
return err; return err;
@ -181,7 +181,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
template<typename U, bool force> template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept { Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty() || jv.isObject()) { if (jv.empty() || jv.isObject()) {
@ -189,7 +189,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
err = model(&handler, val.get()); err = model(&handler, val.get());
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -198,7 +198,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -206,7 +206,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -215,7 +215,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L> template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept { Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
auto err = OxError(0); auto err = ox::Error(0);
if (targetValid()) { if (targetValid()) {
const auto &jv = value(key); const auto &jv = value(key);
if (jv.empty()) { if (jv.empty()) {
@ -223,7 +223,7 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
} else if (jv.isString()) { } else if (jv.isString()) {
*val = jv.asString().c_str(); *val = jv.asString().c_str();
} else { } else {
err = OxError(1, "Type mismatch"); err = ox::Error(1, "Type mismatch");
} }
} }
++m_fieldIt; ++m_fieldIt;
@ -235,25 +235,27 @@ template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept { Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) { if (!srcVal.isNull() && !srcVal.isArray()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
if (srcSize > valLen) { if (srcSize > valLen) {
return OxError(1); return ox::Error(1);
} }
OrganicClawReader r(srcVal); OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
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 ox::Error(0);
} }
template<typename T> template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept { Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key); const auto &srcVal = value(key);
if (!srcVal.isObject()) { if (!srcVal.isObject()) {
return OxError(1, "Type mismatch"); return ox::Error(1, "Type mismatch");
} }
auto keys = srcVal.getMemberNames(); auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size(); auto srcSize = srcVal.size();
@ -261,9 +263,9 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
ModelHandlerInterface handler{&r}; ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) { for (decltype(srcSize) i = 0; i < srcSize; ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
oxReturnError(handler.field(k, &val->operator[](k))); OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
} }
return OxError(0); return ox::Error(0);
} }
Error readOC(BufferView buff, auto &val) noexcept { Error readOC(BufferView buff, auto &val) noexcept {
@ -272,8 +274,10 @@ Error readOC(BufferView buff, auto &val) noexcept {
Json::Value doc; Json::Value doc;
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) { if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
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()); OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
@ -281,14 +285,14 @@ Error readOC(BufferView buff, auto &val) noexcept {
} catch (const Error &err) { } catch (const Error &err) {
return err; return err;
} catch (...) { } catch (...) {
return OxError(1, "Unknown Error"); return ox::Error(1, "Unknown Error");
} }
} }
template<typename T> template<typename T>
Result<T> readOC(BufferView buff) noexcept { Result<T> readOC(BufferView buff) noexcept {
Result<T> val; Result<T> val;
oxReturnError(readOC(buff, val.value)); OX_RETURN_ERROR(readOC(buff, val.value));
return val; return val;
} }

View File

@ -74,45 +74,45 @@ struct TestStruct {
}; };
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestUnion>()); OX_RETURN_ERROR(io->template setTypeInfo<TestUnion>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->fieldCString("String", &obj->String)); OX_RETURN_ERROR(io->fieldCString("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStructNest>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStructNest>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
return OxError(0); return ox::Error(0);
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TestStruct>()); OX_RETURN_ERROR(io->template setTypeInfo<TestStruct>());
oxReturnError(io->field("Bool", &obj->Bool)); OX_RETURN_ERROR(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); OX_RETURN_ERROR(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); OX_RETURN_ERROR(io->field("Int1", &obj->Int1));
oxReturnError(io->field("Int2", &obj->Int2)); OX_RETURN_ERROR(io->field("Int2", &obj->Int2));
oxReturnError(io->field("Int3", &obj->Int3)); OX_RETURN_ERROR(io->field("Int3", &obj->Int3));
oxReturnError(io->field("Int4", &obj->Int4)); OX_RETURN_ERROR(io->field("Int4", &obj->Int4));
oxReturnError(io->field("Int5", &obj->Int5)); OX_RETURN_ERROR(io->field("Int5", &obj->Int5));
oxReturnError(io->field("Int6", &obj->Int6)); OX_RETURN_ERROR(io->field("Int6", &obj->Int6));
oxReturnError(io->field("Int7", &obj->Int7)); OX_RETURN_ERROR(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); OX_RETURN_ERROR(io->field("Int8", &obj->Int8));
oxReturnError(io->field("unionIdx", &obj->unionIdx)); OX_RETURN_ERROR(io->field("unionIdx", &obj->unionIdx));
if (io->opType() == ox::OpType::Reflect) { if (io->opType() == ox::OpType::Reflect) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else { } else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx})); OX_RETURN_ERROR(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
} }
oxReturnError(io->field("String", &obj->String)); OX_RETURN_ERROR(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); OX_RETURN_ERROR(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map)); OX_RETURN_ERROR(io->field("Map", &obj->Map));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); OX_RETURN_ERROR(io->field("EmptyStruct", &obj->EmptyStruct));
oxReturnError(io->field("Struct", &obj->Struct)); OX_RETURN_ERROR(io->field("Struct", &obj->Struct));
return OxError(0); return ox::Error(0);
} }
TestStruct::TestStruct(TestStruct &&other) noexcept { TestStruct::TestStruct(TestStruct &&other) noexcept {
@ -184,7 +184,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch"); oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch"); oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
return OxError(0); return ox::Error(0);
} }
}, },
@ -210,7 +210,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value)); OX_RETURN_ERROR(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff, testOut), "Data read failed"); oxAssert(ox::readOC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
@ -234,7 +234,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0); return ox::Error(0);
} }
}, },
@ -259,7 +259,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
ox::TypeStore typeStore; ox::TypeStore typeStore;
auto type = ox::buildTypeDef(typeStore, testIn); auto type = ox::buildTypeDef(typeStore, testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(), OX_RETURN_ERROR(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(),
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f,
ox::OrganicClawReader *rdr) -> ox::Error { ox::OrganicClawReader *rdr) -> ox::Error {
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
@ -341,10 +341,10 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
case ox::PrimitiveType::Union: case ox::PrimitiveType::Union:
break; break;
} }
return OxError(0); return ox::Error(0);
} }
)); ));
return OxError(0); return ox::Error(0);
} }
}, },
} }

View File

@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept { Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {

View File

@ -42,7 +42,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int16_t *val) noexcept { Error field(const char *key, const int16_t *val) noexcept {
@ -50,7 +50,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int32_t *val) noexcept { Error field(const char *key, const int32_t *val) noexcept {
@ -58,7 +58,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const int64_t *val) noexcept { Error field(const char *key, const int64_t *val) noexcept {
@ -66,7 +66,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
@ -75,7 +75,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint16_t *val) noexcept { Error field(const char *key, const uint16_t *val) noexcept {
@ -83,7 +83,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint32_t *val) noexcept { Error field(const char *key, const uint32_t *val) noexcept {
@ -91,7 +91,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(const char *key, const uint64_t *val) noexcept { Error field(const char *key, const uint64_t *val) noexcept {
@ -99,7 +99,7 @@ class OrganicClawWriter {
value(key) = *val; value(key) = *val;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error field(char const*key, bool const*val) noexcept { Error field(char const*key, bool const*val) noexcept {
@ -122,8 +122,8 @@ class OrganicClawWriter {
for (std::size_t i = 0; i < keys.size(); ++i) { for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str(); const auto k = keys[i].c_str();
if (k) [[likely]] { if (k) [[likely]] {
oxRequireM(value, val->at(k)); OX_REQUIRE_M(value, val->at(k));
oxReturnError(handler.field(k, value)); OX_RETURN_ERROR(handler.field(k, value));
} }
} }
value(key) = w.m_json; value(key) = w.m_json;
@ -147,7 +147,7 @@ class OrganicClawWriter {
value(key) = val->c_str(); value(key) = val->c_str();
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Error fieldCString(const char*, const char *const*val, int len) noexcept; Error fieldCString(const char*, const char *const*val, int len) noexcept;
@ -200,12 +200,14 @@ Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) n
OrganicClawWriter w((Json::Value(Json::arrayValue))); OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
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; value(key) = w.m_json;
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
template<typename T> template<typename T>
@ -225,13 +227,13 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
} else if (val && targetValid()) { } else if (val && targetValid()) {
OrganicClawWriter w; OrganicClawWriter w;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val)); OX_RETURN_ERROR(model(&handler, val));
if (!w.m_json.empty() || m_json.isArray()) { if (!w.m_json.empty() || m_json.isArray()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
template<typename U, bool force> template<typename U, bool force>
@ -239,19 +241,19 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
if (targetValid()) { if (targetValid()) {
OrganicClawWriter w(val.idx()); OrganicClawWriter w(val.idx());
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w}; ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
oxReturnError(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
if (!w.m_json.isNull()) { if (!w.m_json.isNull()) {
value(key) = w.m_json; value(key) = w.m_json;
} }
} }
++m_fieldIt; ++m_fieldIt;
return OxError(0); return ox::Error(0);
} }
Result<ox::Buffer> writeOC(const auto &val) noexcept { Result<ox::Buffer> writeOC(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<Buffer> buff; Result<Buffer> buff;
@ -263,7 +265,7 @@ Result<ox::Buffer> writeOC(const auto &val) noexcept {
Result<ox::String> writeOCString(const auto &val) noexcept { Result<ox::String> writeOCString(const auto &val) noexcept {
OrganicClawWriter writer; OrganicClawWriter writer;
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer); ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
oxReturnError(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
Json::StreamWriterBuilder const jsonBuilder; Json::StreamWriterBuilder const jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json); const auto str = Json::writeString(jsonBuilder, writer.m_json);
Result<ox::String> buff; Result<ox::String> buff;

View File

@ -63,7 +63,7 @@ struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpT
template<typename T> template<typename T>
constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept { constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field(nullptr, &val[i])); OX_RETURN_ERROR(field(nullptr, &val[i]));
} }
return {}; return {};
} }

View File

@ -162,7 +162,7 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::UnionView
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val.get())); OX_RETURN_ERROR(pad(val.get()));
m_unionIdx.emplace_back(val.idx()); m_unionIdx.emplace_back(val.idx());
const auto err = preload<PlatSpec, U>(this, val.get()); const auto err = preload<PlatSpec, U>(this, val.get());
m_unionIdx.pop_back(); m_unionIdx.pop_back();
@ -175,13 +175,13 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const T *val)
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(val)); OX_RETURN_ERROR(pad(val));
if constexpr(ox::is_integral_v<T>) { if constexpr(ox::is_integral_v<T>) {
return ox::serialize(m_writer, PlatSpec::correctEndianness(*val)); return ox::serialize(m_writer, PlatSpec::correctEndianness(*val));
} else if constexpr(ox::is_pointer_v<T>) { } else if constexpr(ox::is_pointer_v<T>) {
const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart; const PtrType a = startAlloc(sizeOf<PlatSpec>(val), alignOf<PlatSpec>(*val), m_writer.tellp()) + PlatSpec::RomStart;
oxReturnError(field(name, *val)); OX_RETURN_ERROR(field(name, *val));
oxReturnError(endAlloc()); OX_RETURN_ERROR(endAlloc());
return ox::serialize(m_writer, PlatSpec::correctEndianness(a)); return ox::serialize(m_writer, PlatSpec::correctEndianness(a));
} else if constexpr(ox::isVector_v<T>) { } else if constexpr(ox::isVector_v<T>) {
return fieldVector(name, val); return fieldVector(name, val);
@ -211,19 +211,19 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const ox::BasicStri
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)), .cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
}; };
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto restore = m_writer.tellp(); const auto restore = m_writer.tellp();
std::size_t a = 0; std::size_t a = 0;
if (sz && sz >= SmallStringSize) { if (sz && sz >= SmallStringSize) {
oxReturnError(ox::allocate(m_writer, sz).moveTo(a)); OX_RETURN_ERROR(ox::allocate(m_writer, sz).moveTo(a));
} else { } else {
a = restore; a = restore;
} }
vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart); vecVal.items = PlatSpec::correctEndianness(static_cast<PtrType>(a) + PlatSpec::RomStart);
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
oxReturnError(m_writer.write(val->data(), sz)); OX_RETURN_ERROR(m_writer.write(val->data(), sz));
oxReturnError(m_writer.seekp(restore)); OX_RETURN_ERROR(m_writer.seekp(restore));
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items); m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items);
return {}; return {};
} }
@ -234,12 +234,12 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR name, const ox::Arra
if (!unionCheckAndIt()) { if (!unionCheckAndIt()) {
return {}; return {};
} }
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
// serialize the Array elements // serialize the Array elements
if constexpr(sz) { if constexpr(sz) {
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(name, &(*val)[i])); OX_RETURN_ERROR(this->interface()->field(name, &(*val)[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@ -253,11 +253,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
return {}; return {};
} }
if (cnt) { if (cnt) {
oxReturnError(pad(*val)); OX_RETURN_ERROR(pad(*val));
// serialize the array // serialize the array
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(this->interface()->field(nullptr, &val[i])); OX_RETURN_ERROR(this->interface()->field(nullptr, &val[i]));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
} }
@ -267,11 +267,11 @@ constexpr ox::Error Preloader<PlatSpec>::field(StringViewCR, const T **val, std:
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept { constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(size_t sz, size_t align) noexcept {
m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp())); m_allocStack.emplace_back(static_cast<typename PlatSpec::PtrType>(m_writer.tellp()));
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@ -280,11 +280,11 @@ template<typename PlatSpec>
constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc( constexpr ox::Result<std::size_t> Preloader<PlatSpec>::startAlloc(
std::size_t sz, size_t align, std::size_t restore) noexcept { std::size_t sz, size_t align, std::size_t restore) noexcept {
m_allocStack.emplace_back(restore, ox::ios_base::beg); m_allocStack.emplace_back(restore, ox::ios_base::beg);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(a, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(a, ox::allocate(m_writer, sz + padding));
a += padding; a += padding;
oxReturnError(m_writer.seekp(a)); OX_RETURN_ERROR(m_writer.seekp(a));
m_allocStart.push_back(a); m_allocStart.push_back(a);
return a; return a;
} }
@ -295,7 +295,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
return m_writer.seekp(0, ox::ios_base::end); return m_writer.seekp(0, ox::ios_base::end);
} }
const auto &si = *m_allocStack.back().unwrap(); const auto &si = *m_allocStack.back().unwrap();
oxReturnError(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir)); OX_RETURN_ERROR(m_writer.seekp(static_cast<ox::ssize_t>(si.restore), si.seekdir));
m_allocStack.pop_back(); m_allocStack.pop_back();
m_allocStart.pop_back(); m_allocStart.pop_back();
return {}; return {};
@ -304,12 +304,12 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept { constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept {
for (const auto &p : m_ptrs) { for (const auto &p : m_ptrs) {
oxReturnError(m_writer.seekp(p.loc)); OX_RETURN_ERROR(m_writer.seekp(p.loc));
const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>( const auto val = PlatSpec::template correctEndianness<typename PlatSpec::PtrType>(
static_cast<typename PlatSpec::PtrType>(p.value + offset)); static_cast<typename PlatSpec::PtrType>(p.value + offset));
oxReturnError(ox::serialize(m_writer, val)); OX_RETURN_ERROR(ox::serialize(m_writer, val));
} }
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
return {}; return {};
} }
@ -354,39 +354,39 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldVector( constexpr ox::Error Preloader<PlatSpec>::fieldVector(
StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept { StringViewCR, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
oxReturnError(pad(&vecVal)); OX_RETURN_ERROR(pad(&vecVal));
const auto vecValPt = m_writer.tellp(); const auto vecValPt = m_writer.tellp();
// serialize the Vector elements // serialize the Vector elements
if (val->size()) { if (val->size()) {
const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size(); const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size();
const auto align = alignOf<PlatSpec>((*val)[0]); const auto align = alignOf<PlatSpec>((*val)[0]);
oxReturnError(m_writer.seekp(0, ox::ios_base::end)); OX_RETURN_ERROR(m_writer.seekp(0, ox::ios_base::end));
auto const padding = calcPadding(align); auto const padding = calcPadding(align);
oxRequireM(p, ox::allocate(m_writer, sz + padding)); OX_REQUIRE_M(p, ox::allocate(m_writer, sz + padding));
p += padding; p += padding;
oxReturnError(m_writer.seekp(p)); OX_RETURN_ERROR(m_writer.seekp(p));
m_unionIdx.emplace_back(-1); m_unionIdx.emplace_back(-1);
for (std::size_t i = 0; i < val->size(); ++i) { for (std::size_t i = 0; i < val->size(); ++i) {
oxReturnError(this->interface()->field(nullptr, &val->operator[](i))); OX_RETURN_ERROR(this->interface()->field(nullptr, &val->operator[](i)));
} }
m_unionIdx.pop_back(); m_unionIdx.pop_back();
vecVal.items = PlatSpec::correctEndianness( vecVal.items = PlatSpec::correctEndianness(
static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart)); static_cast<typename PlatSpec::size_t>(p + PlatSpec::RomStart));
oxReturnError(m_writer.seekp(vecValPt)); OX_RETURN_ERROR(m_writer.seekp(vecValPt));
} else { } else {
vecVal.items = 0; vecVal.items = 0;
} }
// serialize the Vector // serialize the Vector
oxReturnError(serialize(m_writer, vecVal)); OX_RETURN_ERROR(serialize(m_writer, vecVal));
m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items); m_ptrs.emplace_back(m_writer.tellp() - PtrSize, vecVal.items);
return {}; return {};
} }
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept { constexpr ox::Error Preloader<PlatSpec>::fieldArray(StringViewCR, ox::ModelValueArray const*val) noexcept {
oxReturnError(pad(&(*val)[0])); OX_RETURN_ERROR(pad(&(*val)[0]));
for (auto const&v : *val) { for (auto const&v : *val) {
oxReturnError(this->interface()->field({}, &v)); OX_RETURN_ERROR(this->interface()->field({}, &v));
} }
return {}; return {};
} }
@ -405,7 +405,7 @@ constexpr size_t Preloader<PlatSpec>::calcPadding(size_t align) const noexcept {
template<typename PlatSpec, typename T> template<typename PlatSpec, typename T>
constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept { constexpr ox::Error preload(Preloader<PlatSpec> *pl, ox::CommonPtrWith<T> auto *obj) noexcept {
oxReturnError(model(pl->interface(), obj)); OX_RETURN_ERROR(model(pl->interface(), obj));
return pl->pad(obj); return pl->pad(obj);
} }

View File

@ -74,7 +74,7 @@ template<typename T, bool force>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept {
pad(val.get()); pad(val.get());
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@ -91,7 +91,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept { constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }

View File

@ -43,7 +43,7 @@ class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>, OpTy
template<typename T, bool force> template<typename T, bool force>
constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept { constexpr ox::Error field(StringViewCR, const UnionView<T, force> val) noexcept {
UnionSizeCatcher<PlatSpec> sc; UnionSizeCatcher<PlatSpec> sc;
oxReturnError(model(sc.interface(), val.get())); OX_RETURN_ERROR(model(sc.interface(), val.get()));
m_size += sc.size(); m_size += sc.size();
return {}; return {};
} }
@ -80,7 +80,7 @@ template<typename PlatSpec>
template<typename T> template<typename T>
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept { constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(StringViewCR, const T **val, std::size_t cnt) noexcept {
for (std::size_t i = 0; i < cnt; ++i) { for (std::size_t i = 0; i < cnt; ++i) {
oxReturnError(field("", &val[i])); OX_RETURN_ERROR(field("", &val[i]));
} }
return {}; return {};
} }

View File

@ -1,3 +1,9 @@
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# enable warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-buffer-usage")
endif()
if(OX_USE_STDLIB AND OX_ENABLE_TRACEHOOK) if(OX_USE_STDLIB AND OX_ENABLE_TRACEHOOK)
add_library( add_library(
OxTraceHook SHARED OxTraceHook SHARED

View File

@ -8,6 +8,10 @@
#pragma once #pragma once
#include "def.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename It, typename T> template<typename It, typename T>
@ -40,4 +44,6 @@ constexpr OutIt copy_n(It in, Size cnt, OutIt out) {
return out; return out;
} }
} }
OX_CLANG_NOWARN_END

View File

@ -9,6 +9,7 @@
#pragma once #pragma once
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "error.hpp" #include "error.hpp"
#include "initializerlist.hpp" #include "initializerlist.hpp"
#include "iterator.hpp" #include "iterator.hpp"
@ -17,6 +18,8 @@
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
@ -35,6 +38,10 @@ class Array {
public: public:
constexpr Array() noexcept = default; constexpr Array() noexcept = default;
template<typename ...Args>
constexpr Array(Args ...list) noexcept: m_items{std::move(list)...} {
}
constexpr Array(std::initializer_list<T> list) noexcept; constexpr Array(std::initializer_list<T> list) noexcept;
constexpr Array(const Array &other); constexpr Array(const Array &other);
@ -174,11 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept { constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
template<typename T, std::size_t ArraySize> template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept { constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Array access overflow");
return m_items[i]; return m_items[i];
} }
@ -198,3 +207,5 @@ constexpr bool Array<T, ArraySize>::contains(const T &v) const {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -6,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include "fmt.hpp"
#include "stacktrace.hpp" #include "stacktrace.hpp"
#include "trace.hpp" #include "trace.hpp"
@ -13,7 +14,7 @@
namespace ox { namespace ox {
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept { void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) { if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
@ -31,4 +32,40 @@ void panic(const char *file, int line, const char *panicMsg, const Error &err) n
#endif #endif
} }
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
}
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
output += genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
}
void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
#if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort();
#else
constexprPanic(file, line, assertMsg);
#endif
}
} }

View File

@ -22,9 +22,9 @@
namespace ox { namespace ox {
void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = OxError(0)) noexcept; void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept;
constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = OxError(0)) noexcept { constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err); panic(file, line, panicMsg, err);
} else { } else {
@ -32,19 +32,13 @@ constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg
} }
} }
void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept;
void assertFailFuncRuntime(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept;
constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept { constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept {
if (!pass) { if (!pass) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#ifdef OX_USE_STDLIB assertFailFuncRuntime(file, line, assertTxt, msg);
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
output += genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
#endif
} else { } else {
while (true); while (true);
} }
@ -54,22 +48,7 @@ constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused
constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept { constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB) assertFailFuncRuntime(file, line, err, {}, assertMsg);
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.file != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
std::abort();
#else
constexprPanic(file, line, assertMsg);
#endif
} else { } else {
while (true); while (true);
} }

View File

@ -9,9 +9,12 @@
#pragma once #pragma once
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "cstrops.hpp" #include "cstrops.hpp"
#include "iterator.hpp" #include "iterator.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::detail { namespace ox::detail {
class BaseStringView { class BaseStringView {
@ -202,7 +205,7 @@ class BaseStringView {
} }
[[nodiscard]] [[nodiscard]]
constexpr auto operator[](std::size_t i) const noexcept { constexpr auto &operator[](std::size_t i) const noexcept {
return m_str[i]; return m_str[i];
} }
@ -215,3 +218,5 @@ class BaseStringView {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -126,11 +126,11 @@ constexpr void Bounds::set(const Point &pt1, const Point &pt2) noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Bounds> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<Bounds> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Bounds>()); OX_RETURN_ERROR(io->template setTypeInfo<Bounds>());
oxReturnError(io->field("x", &obj->x)); OX_RETURN_ERROR(io->field("x", &obj->x));
oxReturnError(io->field("y", &obj->y)); OX_RETURN_ERROR(io->field("y", &obj->y));
oxReturnError(io->field("width", &obj->width)); OX_RETURN_ERROR(io->field("width", &obj->width));
oxReturnError(io->field("height", &obj->height)); OX_RETURN_ERROR(io->field("height", &obj->height));
return {}; return {};
} }

View File

@ -14,12 +14,14 @@
#include "vector.hpp" #include "vector.hpp"
#include "writer.hpp" #include "writer.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
extern template class Vector<char>; extern template class Vector<char>;
using Buffer = Vector<char>; using Buffer = Vector<char>;
using BufferView = SpanView<char>; using BufferView = Span<const char>;
class BufferWriter { class BufferWriter {
private: private:
@ -51,7 +53,7 @@ class BufferWriter {
base = static_cast<ox::Signed<std::size_t>>(m_it); base = static_cast<ox::Signed<std::size_t>>(m_it);
break; break;
default: default:
return OxError(1, "Invalid seekdir"); return ox::Error(1, "Invalid seekdir");
} }
m_it = static_cast<std::size_t>(base + off); m_it = static_cast<std::size_t>(base + off);
return {}; return {};
@ -100,15 +102,11 @@ class CharBuffWriter {
char *m_buff = nullptr; char *m_buff = nullptr;
public: public:
template<std::size_t sz> explicit constexpr CharBuffWriter(ox::Span<char> buff) noexcept:
explicit constexpr CharBuffWriter(ox::Array<char, sz> &buff) noexcept:
m_cap(buff.size()), m_cap(buff.size()),
m_buff(buff.data()) { m_buff(buff.data()) {
} }
explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) {
}
constexpr ox::Error seekp(std::size_t p) noexcept { constexpr ox::Error seekp(std::size_t p) noexcept {
m_it = p; m_it = p;
return {}; return {};
@ -127,7 +125,7 @@ class CharBuffWriter {
base = static_cast<ox::Signed<std::size_t>>(m_it); base = static_cast<ox::Signed<std::size_t>>(m_it);
break; break;
default: default:
return OxError(1, "Invalid seekdir"); return ox::Error(1, "Invalid seekdir");
} }
m_it = static_cast<std::size_t>(base + off); m_it = static_cast<std::size_t>(base + off);
return {}; return {};
@ -140,7 +138,7 @@ class CharBuffWriter {
constexpr ox::Error put(char val) noexcept { constexpr ox::Error put(char val) noexcept {
if (m_it >= m_cap) [[unlikely]] { if (m_it >= m_cap) [[unlikely]] {
return OxError(1, "Buffer overrun"); return ox::Error(1, "Buffer overrun");
} }
m_buff[m_it] = val; m_buff[m_it] = val;
++m_it; ++m_it;
@ -151,7 +149,7 @@ class CharBuffWriter {
constexpr ox::Error write(const char *buff, std::size_t cnt) noexcept { constexpr ox::Error write(const char *buff, std::size_t cnt) noexcept {
const auto end = m_it + cnt; const auto end = m_it + cnt;
if (end > m_cap) [[unlikely]] { if (end > m_cap) [[unlikely]] {
return OxError(1, "Buffer overrun"); return ox::Error(1, "Buffer overrun");
} }
if (buff) { if (buff) {
for (auto i = 0u; i < cnt; ++i) { for (auto i = 0u; i < cnt; ++i) {
@ -181,7 +179,7 @@ class BufferReader {
constexpr ox::Result<char> peek() const noexcept { constexpr ox::Result<char> peek() const noexcept {
if (m_it >= m_size) [[unlikely]] { if (m_it >= m_size) [[unlikely]] {
return OxError(1, "Peek failed: buffer overrun"); return ox::Error(1, "Peek failed: buffer overrun");
} }
return m_buff[m_it]; return m_buff[m_it];
} }
@ -189,7 +187,7 @@ class BufferReader {
constexpr ox::Result<std::size_t> read(void *v, std::size_t sz) noexcept { constexpr ox::Result<std::size_t> read(void *v, std::size_t sz) noexcept {
sz = ox::min(sz, m_size - m_it); sz = ox::min(sz, m_size - m_it);
if (m_it + sz > m_size) [[unlikely]] { if (m_it + sz > m_size) [[unlikely]] {
return OxError(1, "Read failed: Buffer overrun"); return ox::Error(1, "Read failed: Buffer overrun");
} }
ox::memcpy(v, &m_buff[m_it], sz); ox::memcpy(v, &m_buff[m_it], sz);
m_it += sz; m_it += sz;
@ -198,7 +196,7 @@ class BufferReader {
constexpr ox::Error seekg(std::size_t p) noexcept { constexpr ox::Error seekg(std::size_t p) noexcept {
if (p > m_size) [[unlikely]] { if (p > m_size) [[unlikely]] {
return OxError(1, "Seek failed: Buffer overrun"); return ox::Error(1, "Seek failed: Buffer overrun");
} }
m_it = p; m_it = p;
return {}; return {};
@ -217,11 +215,11 @@ class BufferReader {
base = static_cast<ox::Signed<std::size_t>>(m_it); base = static_cast<ox::Signed<std::size_t>>(m_it);
break; break;
default: default:
return OxError(1, "Invalid seekdir"); return ox::Error(1, "Invalid seekdir");
} }
auto const newIt = static_cast<std::size_t>(base + off); auto const newIt = static_cast<std::size_t>(base + off);
if (newIt > m_size) [[unlikely]] { if (newIt > m_size) [[unlikely]] {
return OxError(1, "Seek failed: Buffer overrun"); return ox::Error(1, "Seek failed: Buffer overrun");
} }
m_it = newIt; m_it = newIt;
return {}; return {};
@ -237,3 +235,5 @@ extern template class WriterT<BufferWriter>;
extern template class WriterT<CharBuffWriter>; extern template class WriterT<CharBuffWriter>;
} }
OX_CLANG_NOWARN_END

View File

@ -8,9 +8,12 @@
#pragma once #pragma once
#include "def.hpp"
#include "types.hpp" #include "types.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T1, typename T2> template<typename T1, typename T2>
@ -113,3 +116,5 @@ constexpr int lastIndexOf(const auto &str, int character, std::size_t maxLen = 0
} }
} }
OX_CLANG_NOWARN_END

View File

@ -37,17 +37,13 @@
// Error handling // Error handling
#define oxReturnError(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] return _ox_error; } (void) 0 #define OX_RETURN_ERROR(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] return _ox_error; } (void) 0
#define oxThrowError(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] throw ox::Exception(_ox_error); } (void) 0 #define OX_THROW_ERROR(x) { if (const auto _ox_error = ox::detail::toError(x)) [[unlikely]] throw ox::Exception(_ox_error); } (void) 0
#define oxConcatImpl(a, b) a##b #define OX_CONCAT_IMPL(a, b) a##b
#define oxConcat(a, b) oxConcatImpl(a, b) #define OX_CONCAT(a, b) OX_CONCAT_IMPL(a, b)
// oxRequire Mutable // oxRequire Mutable
#define oxRequireM(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxReturnError(oxConcat(oxRequire_err_, __LINE__)) #define OX_REQUIRE_M(out, x) auto [out, OX_CONCAT(oxRequire_err_, __LINE__)] = x; OX_RETURN_ERROR(OX_CONCAT(oxRequire_err_, __LINE__))
#define oxRequire(out, x) const oxRequireM(out, x) #define OX_REQUIRE(out, x) const OX_REQUIRE_M(out, x)
// oxRequire Mutable Throw
#define oxRequireMT(out, x) auto [out, oxConcat(oxRequire_err_, __LINE__)] = x; oxThrowError(oxConcat(oxRequire_err_, __LINE__))
// oxRequire Throw
#define oxRequireT(out, x) const oxRequireMT(out, x)
// Asserts // Asserts
@ -75,6 +71,21 @@ constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
#define ox_alloca(size) __builtin_alloca(size) #define ox_alloca(size) __builtin_alloca(size)
#endif #endif
#define OX_PRAGMA(x) _Pragma(#x)
#ifdef __clang__
#define OX_CLANG_NOWARN_BEGIN(warnoption) \
OX_PRAGMA(clang diagnostic push) \
OX_PRAGMA(clang diagnostic ignored #warnoption)
#define OX_CLANG_NOWARN_END OX_PRAGMA(clang diagnostic pop)
#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
#define OX_ALLOW_UNSAFE_BUFFERS_END OX_CLANG_NOWARN_END
#else
#define OX_CLANG_NOWARN_BEGIN(warnoption)
#define OX_CLANG_NOWARN_END
#define OX_ALLOW_UNSAFE_BUFFERS_BEGIN
#define OX_ALLOW_UNSAFE_BUFFERS_END
#endif
/** /**
* @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation * @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation
*/ */

View File

@ -31,4 +31,4 @@ class Defer {
} }
#define oxDefer ox::Defer const oxConcat(oxDefer_, __LINE__) = #define OX_DEFER ox::Defer const OX_CONCAT(oxDefer_, __LINE__) =

View File

@ -17,57 +17,59 @@ class exception {
virtual ~exception() = default; virtual ~exception() = default;
[[nodiscard]] [[nodiscard]]
virtual const char *what() const noexcept { virtual char const*what() const noexcept {
return ""; return "";
} }
}; };
} }
#endif #endif
#include "defines.hpp"
#include "def.hpp" #include "def.hpp"
#include "source_location.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
#include "utility.hpp" #include "utility.hpp"
#define OxError(...) ox::Error(__FILE__, __LINE__, __VA_ARGS__)
#define OxException(...) ox::Exception(__FILE__, __LINE__, __VA_ARGS__)
namespace ox { namespace ox {
using ErrorCode = uint16_t; using ErrorCode = uint16_t;
struct [[nodiscard]] Error { struct [[nodiscard]] Error {
const char *msg = nullptr; ox::CString msg = nullptr;
const char *file = nullptr; ox::CString file = nullptr;
uint16_t line = 0; uint16_t line = 0;
ErrorCode errCode = 0; ErrorCode errCode = 0;
constexpr Error() noexcept = default; constexpr Error() noexcept = default;
explicit constexpr Error(ErrorCode ec) noexcept: errCode(ec) { explicit constexpr Error(
} ox::CString file,
uint32_t const line,
ErrorCode const errCode,
ox::CString msg = nullptr) noexcept:
msg{msg},
file{file},
line{static_cast<uint16_t>(line)},
errCode{errCode} {}
explicit constexpr Error(const char *file, uint32_t line, ErrorCode errCode, const char *msg = nullptr) noexcept { explicit constexpr Error(
this->file = file; ErrorCode const errCode,
this->line = static_cast<uint16_t>(line); std::source_location const&src = std::source_location::current()) noexcept:
this->msg = msg; file{src.file_name()},
this->errCode = errCode; line{static_cast<uint16_t>(src.line())},
} errCode{errCode}
{}
constexpr Error(const Error &o) noexcept { explicit constexpr Error(
this->msg = o.msg; ErrorCode const errCode,
this->file = o.file; ox::CString msg,
this->line = o.line; std::source_location const&src = std::source_location::current()) noexcept:
this->errCode = o.errCode; msg{msg},
} file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
constexpr Error &operator=(const Error &o) noexcept { errCode{errCode}
this->msg = o.msg; {}
this->file = o.file;
this->line = o.line;
this->errCode = o.errCode;
return *this;
}
constexpr operator uint64_t() const noexcept { constexpr operator uint64_t() const noexcept {
return errCode; return errCode;
@ -76,51 +78,62 @@ struct [[nodiscard]] Error {
}; };
[[nodiscard]] [[nodiscard]]
constexpr auto errCode(const Error &err) noexcept { constexpr auto errCode(Error const&err) noexcept {
return err.errCode; return err.errCode;
} }
template<typename T=const char*> template<typename T = char const*>
[[nodiscard]] [[nodiscard]]
constexpr auto toStr(const Error &err) noexcept { constexpr auto toStr(Error const&err) noexcept {
return err.msg ? T(err.msg) : ""; return err.msg ? T{err.msg} : "";
} }
struct Exception: public std::exception { struct Exception: public std::exception {
const char *msg = nullptr; ox::CString msg = nullptr;
const char *file = nullptr; ox::CString file = nullptr;
uint16_t line = 0; uint16_t line = 0;
ErrorCode errCode = 0; ErrorCode errCode = 0;
explicit inline Exception(const char *file, uint32_t line, ErrorCode errCode, const char *msg = "") noexcept { explicit inline Exception(ox::CString file, uint32_t line, ErrorCode errCode, char const*msg = "") noexcept {
this->file = file; this->file = file;
this->line = static_cast<uint16_t>(line); this->line = static_cast<uint16_t>(line);
this->msg = msg; this->msg = msg;
this->errCode = errCode; this->errCode = errCode;
} }
explicit inline Exception(const Error &err) { explicit inline Exception(
if (err.msg) { ErrorCode const errCode,
this->msg = err.msg; std::source_location const&src = std::source_location::current()) noexcept:
} else { file{src.file_name()},
this->msg = ""; line{static_cast<uint16_t>(src.line())},
} errCode{errCode} {}
this->file = err.file;
this->line = err.line; explicit inline Exception(
this->errCode = err.errCode; ErrorCode const errCode,
} ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept:
msg{msg},
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} {}
explicit inline Exception(Error const&err) noexcept:
msg{err.msg ? err.msg : ""},
file{err.file},
line{err.line},
errCode{err.errCode} {}
constexpr Error toError() const noexcept { constexpr Error toError() const noexcept {
return Error(file, line, errCode, msg); return Error(file, line, errCode, msg);
} }
[[nodiscard]] [[nodiscard]]
const char *what() const noexcept override { char const*what() const noexcept override {
return msg; return msg;
} }
}; };
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept; void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
template<typename T> template<typename T>
struct [[nodiscard]] Result { struct [[nodiscard]] Result {
@ -134,25 +147,25 @@ struct [[nodiscard]] Result {
} }
template<typename U> template<typename U>
constexpr Result(const Result<U> &other) noexcept: value(other.value), error(other.error) { constexpr Result(Result<U> const&other) noexcept: value(other.value), error(other.error) {
} }
template<typename U> template<typename U>
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) { constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
} }
constexpr Result(const Error &error) noexcept: value(), error(error) { constexpr Result(Error const&error) noexcept: value(), error(error) {
} }
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(value), error(error) { constexpr Result(type const&value, Error const&error = {}) noexcept: value(value), error(error) {
} }
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(std::move(value)), error(error) { constexpr Result(type &&value, Error const&error = {}) noexcept: value(std::move(value)), error(error) {
} }
constexpr ~Result() noexcept = default; constexpr ~Result() noexcept = default;
explicit constexpr operator const type&() const noexcept { explicit constexpr operator type const&() const noexcept {
return value; return value;
} }
@ -321,15 +334,23 @@ struct [[nodiscard]] Result {
namespace detail { namespace detail {
constexpr Error toError(const Error &e) noexcept { constexpr Error toError(Error const&e) noexcept {
return e; return e;
} }
template<typename T> template<typename T>
constexpr Error toError(const Result<T> &r) noexcept { constexpr Error toError(Result<T> const&r) noexcept {
return r.error; return r.error;
} }
} }
constexpr void primitiveAssert(char const*file, int line, bool pass, char const*msg) noexcept {
if constexpr(ox::defines::Debug) {
if (!pass) [[unlikely]] {
panic(file, line, msg, ox::Error(1));
}
}
}
} }

View File

@ -25,6 +25,8 @@
#include "types.hpp" #include "types.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
namespace detail { namespace detail {
@ -81,16 +83,16 @@ class FmtArg {
private: private:
static constexpr auto DataSz = 23; static constexpr auto DataSz = 23;
char dataStr[DataSz] = {}; ox::Array<char, DataSz> dataStr{};
template<typename T> template<typename T>
constexpr StringView sv(const T &v, char *dataStr) noexcept { constexpr StringView sv(const T &v, ox::Span<char> dataStr) noexcept {
if constexpr(is_bool_v<T>) { if constexpr(is_bool_v<T>) {
return v ? "true" : "false"; return v ? "true" : "false";
} else if constexpr(is_integer_v<T>) { } else if constexpr(is_integer_v<T>) {
ox::CharBuffWriter w(dataStr, DataSz); ox::CharBuffWriter w{dataStr};
std::ignore = ox::writeItoa(v, w); std::ignore = ox::writeItoa(v, w);
return dataStr; return dataStr.data();
} else { } else {
return toStringView(v); return toStringView(v);
} }
@ -225,3 +227,5 @@ constexpr Result<T> join(auto const&d, auto const&list) {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -154,7 +154,7 @@ template<typename K, typename T>
constexpr Result<T*> HashMap<K, T>::at(MaybeView_t<K> const&k) noexcept { constexpr Result<T*> HashMap<K, T>::at(MaybeView_t<K> const&k) noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
return &p->value; return &p->value;
} }
@ -163,7 +163,7 @@ template<typename K, typename T>
constexpr Result<const T*> HashMap<K, T>::at(MaybeView_t<K> const&k) const noexcept { constexpr Result<const T*> HashMap<K, T>::at(MaybeView_t<K> const&k) const noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
return &p->value; return &p->value;
} }

View File

@ -8,8 +8,11 @@
#include "assert.hpp" #include "assert.hpp"
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "heapmgr.hpp" #include "heapmgr.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox::heapmgr { namespace ox::heapmgr {
static struct HeapSegment *volatile g_heapBegin = nullptr; static struct HeapSegment *volatile g_heapBegin = nullptr;
@ -74,7 +77,7 @@ static HeapSegment *findSegmentFor(std::size_t sz) noexcept {
return s; return s;
} }
} }
oxPanic(OxError(1), "malloc: could not find segment"); oxPanic(ox::Error(1), "malloc: could not find segment");
return nullptr; return nullptr;
} }
@ -99,7 +102,7 @@ void free(void *ptr) noexcept {
} else if (p.segment) { } else if (p.segment) {
p.segment->inUse = false; p.segment->inUse = false;
} else { } else {
oxPanic(OxError(1), "Bad heap free"); oxPanic(ox::Error(1), "Bad heap free");
} }
} }
@ -142,3 +145,5 @@ void operator delete[](void *ptr, unsigned long int) noexcept {
} }
#endif #endif
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,7 @@
#include "array.hpp" #include "array.hpp"
#include "concepts.hpp" #include "concepts.hpp"
#include "def.hpp"
#include "cstrops.hpp" #include "cstrops.hpp"
#include "memops.hpp" #include "memops.hpp"
#include "error.hpp" #include "error.hpp"
@ -173,9 +174,11 @@ constexpr Error IString<StrCap>::append(const char *str, std::size_t strLen) noe
auto const currentLen = len(); auto const currentLen = len();
if (cap() < currentLen + strLen) { if (cap() < currentLen + strLen) {
strLen = cap() - currentLen; strLen = cap() - currentLen;
err = OxError(1, "Insufficient space for full string"); err = ox::Error(1, "Insufficient space for full string");
} }
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
ox::strncpy(m_buff.data() + currentLen, str, strLen); ox::strncpy(m_buff.data() + currentLen, str, strLen);
OX_CLANG_NOWARN_END
// make sure last element is a null terminator // make sure last element is a null terminator
m_buff[currentLen + strLen] = 0; m_buff[currentLen + strLen] = 0;
m_size += strLen; m_size += strLen;
@ -216,7 +219,7 @@ constexpr std::size_t IString<StrCap>::bytes() const noexcept {
template<std::size_t StrCap> template<std::size_t StrCap>
constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept { constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
if (sz > StrCap) [[unlikely]] { if (sz > StrCap) [[unlikely]] {
return OxError(1, "Trying to extend IString beyond its cap"); return ox::Error(1, "Trying to extend IString beyond its cap");
} }
for (auto i = m_size; i < sz; ++i) { for (auto i = m_size; i < sz; ++i) {
m_buff[i] = 0; m_buff[i] = 0;
@ -228,7 +231,7 @@ constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
template<std::size_t StrCap> template<std::size_t StrCap>
constexpr ox::Error IString<StrCap>::unsafeResize(size_t sz) noexcept { constexpr ox::Error IString<StrCap>::unsafeResize(size_t sz) noexcept {
if (sz > StrCap) [[unlikely]] { if (sz > StrCap) [[unlikely]] {
return OxError(1, "Trying to extend IString beyond its cap"); return ox::Error(1, "Trying to extend IString beyond its cap");
} }
m_size = sz; m_size = sz;
return {}; return {};
@ -263,7 +266,7 @@ constexpr auto itoa(Integer v) noexcept {
}(); }();
ox::IString<Cap> out; ox::IString<Cap> out;
std::ignore = out.resize(out.cap()); std::ignore = out.resize(out.cap());
ox::CharBuffWriter w(out.data(), out.cap()); ox::CharBuffWriter w{{out.data(), out.cap()}};
std::ignore = writeItoa(v, w); std::ignore = writeItoa(v, w);
std::ignore = out.resize(w.tellp()); std::ignore = out.resize(w.tellp());
return out; return out;

View File

@ -8,6 +8,8 @@
#pragma once #pragma once
#include "def.hpp"
#include "error.hpp"
#include "math.hpp" #include "math.hpp"
#if !__has_include(<iterator>) #if !__has_include(<iterator>)
@ -38,6 +40,8 @@ struct contiguous_iterator_tag: public random_access_iterator_tag {
#include <iterator> #include <iterator>
#endif #endif
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename Category, typename T, typename DiffType = std::ptrdiff_t, template<typename Category, typename T, typename DiffType = std::ptrdiff_t,
@ -129,14 +133,17 @@ struct SpanIterator {
} }
constexpr PtrType operator->() const noexcept { constexpr PtrType operator->() const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
return &m_t[m_offset]; return &m_t[m_offset];
} }
constexpr RefType operator*() const noexcept { constexpr RefType operator*() const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
return m_t[m_offset]; return m_t[m_offset];
} }
constexpr RefType operator[](std::size_t s) const noexcept { constexpr RefType operator[](std::size_t s) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, s < m_max, "SpanIterator access overflow");
return m_t[s]; return m_t[s];
} }
@ -167,3 +174,5 @@ struct SpanIterator {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -10,6 +10,8 @@
#include "types.hpp" #include "types.hpp"
#include "memops.hpp" #include "memops.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
#ifndef OX_USE_STDLIB #ifndef OX_USE_STDLIB
#define ox_inhibit_loop_to_libcall __attribute__((__optimize__("-fno-tree-loop-distribute-patterns"))) #define ox_inhibit_loop_to_libcall __attribute__((__optimize__("-fno-tree-loop-distribute-patterns")))
@ -96,3 +98,5 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -8,6 +8,7 @@
#pragma once #pragma once
#include "def.hpp"
#include "types.hpp" #include "types.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
@ -27,6 +28,8 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
} }
#endif #endif
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T1, typename T2> template<typename T1, typename T2>
@ -56,3 +59,5 @@ void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -42,10 +42,10 @@ constexpr U *make(Args &&...args) noexcept {
try { try {
return new T(ox::forward<Args>(args)...); return new T(ox::forward<Args>(args)...);
} catch (std::exception const&ex) { } catch (std::exception const&ex) {
oxPanic(OxError(1, ex.what()), ex.what()); oxPanic(ox::Error(1, ex.what()), ex.what());
return nullptr; return nullptr;
} catch (...) { } catch (...) {
oxPanic(OxError(2, "Allocation or constructor failed"), "Allocation or constructor failed"); oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
return nullptr; return nullptr;
} }
#else #else
@ -62,7 +62,7 @@ constexpr Result<T*> makeCatch(Args &&...args) noexcept {
} catch (const ox::Exception &ex) { } catch (const ox::Exception &ex) {
return ex.toError(); return ex.toError();
} catch (...) { } catch (...) {
return OxError(1, "Allocation or constructor failed"); return ox::Error(1, "Allocation or constructor failed");
} }
#else #else
return new T(ox::forward<Args>(args)...); return new T(ox::forward<Args>(args)...);

View File

@ -8,11 +8,7 @@
#pragma once #pragma once
#include "bit.hpp"
#include "initializerlist.hpp"
#include "iterator.hpp"
#include "memory.hpp" #include "memory.hpp"
#include "new.hpp"
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"

View File

@ -189,9 +189,9 @@ constexpr bool Point::operator!=(const Point &p) const noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Point> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<Point> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Point>()); OX_RETURN_ERROR(io->template setTypeInfo<Point>());
oxReturnError(io->field("x", &obj->x)); OX_RETURN_ERROR(io->field("x", &obj->x));
oxReturnError(io->field("y", &obj->y)); OX_RETURN_ERROR(io->field("y", &obj->y));
return {}; return {};
} }

View File

@ -9,9 +9,12 @@
#pragma once #pragma once
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "stddef.hpp" #include "stddef.hpp"
#include "types.hpp" #include "types.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
using RandomSeed = uint64_t[2]; using RandomSeed = uint64_t[2];
@ -51,3 +54,5 @@ constexpr uint64_t Random::gen() noexcept {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -34,11 +34,11 @@ ox::Result<char> StreamReader::peek() const noexcept {
m_strm.get(c); m_strm.get(c);
auto const ok = c != EOF; auto const ok = c != EOF;
if (ok && m_strm.unget()) [[unlikely]] { if (ok && m_strm.unget()) [[unlikely]] {
return OxError(1, "Unable to unget character"); return ox::Error(1, "Unable to unget character");
} }
return {static_cast<char>(c), OxError(!ok, "File peek failed")}; return {static_cast<char>(c), ox::Error(!ok, "File peek failed")};
} catch (std::exception const&) { } catch (std::exception const&) {
return OxError(1, "peek failed"); return ox::Error(1, "peek failed");
} }
} }
@ -50,7 +50,7 @@ ox::Error StreamReader::seekg(std::size_t p) noexcept {
try { try {
m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur); m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur);
} catch (std::exception const&) { } catch (std::exception const&) {
return OxError(1, "seekg failed"); return ox::Error(1, "seekg failed");
} }
return {}; return {};
} }
@ -59,14 +59,14 @@ ox::Error StreamReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
try { try {
m_strm.seekg(p, sdMap(sd)); m_strm.seekg(p, sdMap(sd));
} catch (std::exception const&) { } catch (std::exception const&) {
return OxError(1, "seekg failed"); return ox::Error(1, "seekg failed");
} }
return {}; return {};
} }
ox::Result<std::size_t> StreamReader::tellg() noexcept { ox::Result<std::size_t> StreamReader::tellg() noexcept {
const auto sz = m_strm.tellg(); const auto sz = m_strm.tellg();
return {static_cast<std::size_t>(sz), OxError(sz == -1)}; return {static_cast<std::size_t>(sz), ox::Error(sz == -1)};
} }
} }

View File

@ -63,10 +63,10 @@ constexpr ox::Error pad(Writer_c auto &w, const T *v) noexcept {
template<typename PlatSpec> template<typename PlatSpec>
constexpr ox::Error serialize(Writer_c auto &w, const VectorMemMap<PlatSpec> &vm) noexcept { constexpr ox::Error serialize(Writer_c auto &w, const VectorMemMap<PlatSpec> &vm) noexcept {
oxReturnError(w.write(nullptr, vm.smallVecSize)); OX_RETURN_ERROR(w.write(nullptr, vm.smallVecSize));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.size))); OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.size)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.cap))); OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.cap)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.items))); OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.items)));
return {}; return {};
} }
@ -83,7 +83,7 @@ template<typename T>
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept { constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
ox::Array<char, sizeof(T)> out = {}; ox::Array<char, sizeof(T)> out = {};
CharBuffWriter w(out); CharBuffWriter w(out);
oxReturnError(serialize(w, in)); OX_RETURN_ERROR(serialize(w, in));
return out; return out;
}; };

View File

@ -190,9 +190,9 @@ constexpr bool Size::operator!=(const Size &p) const noexcept {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Size> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<Size> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<Size>()); OX_RETURN_ERROR(io->template setTypeInfo<Size>());
oxReturnError(io->field("width", &obj->width)); OX_RETURN_ERROR(io->field("width", &obj->width));
oxReturnError(io->field("height", &obj->height)); OX_RETURN_ERROR(io->field("height", &obj->height));
return {}; return {};
} }

View File

@ -140,7 +140,7 @@ template<typename K, typename T, size_t SmallSz>
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept { constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
return &p->value; return &p->value;
} }
@ -149,7 +149,7 @@ template<typename K, typename T, size_t SmallSz>
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept { constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
auto p = access(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, OxError(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
return &p->value; return &p->value;
} }
@ -247,8 +247,8 @@ constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::acces
template<typename T, typename K, typename V, size_t SmallSz> template<typename T, typename K, typename V, size_t SmallSz>
constexpr Error model(T *io, ox::CommonPtrWith<SmallMap<K, V, SmallSz>> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<SmallMap<K, V, SmallSz>> auto *obj) noexcept {
using Map = SmallMap<K, V, SmallSz>; using Map = SmallMap<K, V, SmallSz>;
oxReturnError(io->template setTypeInfo<Map>()); OX_RETURN_ERROR(io->template setTypeInfo<Map>());
oxReturnError(io->field("pairs", &obj->m_pairs)); OX_RETURN_ERROR(io->field("pairs", &obj->m_pairs));
return {}; return {};
} }

68
deps/ox/src/ox/std/source_location.hpp vendored Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#if __has_include(<source_location>)
#include <source_location>
#else
#include "types.hpp"
namespace std {
class source_location {
private:
struct __impl {
char const*_M_file_name{};
char const*_M_function_name{};
uint32_t _M_line{};
uint32_t _M_column{};
};
static constexpr __impl Default{
._M_file_name = "",
._M_function_name = "",
._M_line = {},
._M_column = {},
};
__impl const*m_data{&Default};
using Raw = decltype(__builtin_source_location());
public:
constexpr source_location() noexcept = default;
static consteval source_location current(Raw const pSl = __builtin_source_location()) noexcept {
source_location sl;
if (pSl) {
sl.m_data = static_cast<__impl const*>(pSl);
}
return sl;
}
constexpr uint32_t line() const noexcept {
return m_data->_M_line;
}
constexpr uint32_t column() const noexcept {
return m_data->_M_column;
}
constexpr ox::CString file_name() const noexcept {
return m_data->_M_file_name;
}
constexpr ox::CString function_name() const noexcept {
return m_data->_M_function_name;
}
};
}
#endif

View File

@ -10,135 +10,21 @@
#include "array.hpp" #include "array.hpp"
#include "bit.hpp" #include "bit.hpp"
#include "def.hpp"
#include "iterator.hpp" #include "iterator.hpp"
#include "vector.hpp" #include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T>
class SpanView {
private:
T const*m_items{};
std::size_t m_size{};
public:
using value_type = T;
using size_type = std::size_t;
template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr SpanView() noexcept {}
template<std::size_t sz>
constexpr SpanView(ox::Array<T, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator>
constexpr SpanView(ox::Vector<T, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz>
constexpr SpanView(const T a[sz]) noexcept:
m_items(a),
m_size(sz) {
}
constexpr SpanView(const T *a, std::size_t sz) noexcept:
m_items(a),
m_size(sz) {
}
constexpr iterator<> begin() noexcept {
return iterator<>(m_items, 0, m_size);
}
constexpr iterator<> end() noexcept {
return iterator<>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> begin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> end() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cbegin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cend() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
constexpr const T &operator[](std::size_t i) const noexcept {
return m_items[i];
}
constexpr SpanView operator+(size_t i) const noexcept {
return {m_items + i, m_size - i};
}
constexpr SpanView operator+=(size_t i) noexcept {
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]]
constexpr T const*data() const noexcept {
return m_items;
}
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return m_size;
}
[[nodiscard]]
constexpr bool empty() const noexcept {
return m_size == 0;
}
};
template<typename T> template<typename T>
class Span { class Span {
private: private:
T *m_items{}; T *m_items{};
const std::size_t m_size{}; std::size_t m_size{};
public: public:
using value_type = T; using value_type = T;
@ -147,20 +33,34 @@ class Span {
template<typename RefType = T&, typename PtrType = T*, bool reverse = false> template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>; using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr Span() noexcept = default;
template<std::size_t sz> template<std::size_t sz>
constexpr Span(ox::Array<T, sz> &a) noexcept: constexpr Span(ox::Array<T, sz> &a) noexcept:
m_items(a.data()), m_items(a.data()),
m_size(a.size()) { m_size(a.size()) {
} }
template<std::size_t sz>
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator> template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<T, sz, Allocator> &v) noexcept: constexpr Span(ox::Vector<T, sz, Allocator> &v) noexcept:
m_items(v.data()), m_items(v.data()),
m_size(v.size()) { m_size(v.size()) {
} }
template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz> template<std::size_t sz>
constexpr Span(T a[sz]) noexcept: constexpr Span(T (&a)[sz]) noexcept:
m_items(a), m_items(a),
m_size(sz) { m_size(sz) {
} }
@ -229,13 +129,27 @@ class Span {
} }
constexpr T &operator[](std::size_t i) noexcept { constexpr T &operator[](std::size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i]; return m_items[i];
} }
constexpr const T &operator[](std::size_t i) const noexcept { constexpr const T &operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i]; return m_items[i];
} }
constexpr Span operator+(size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return {m_items + i, m_size - i};
}
constexpr Span operator+=(size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]] [[nodiscard]]
constexpr auto data() const noexcept { constexpr auto data() const noexcept {
return m_items; return m_items;
@ -253,4 +167,9 @@ class Span {
}; };
template<typename T>
using SpanView = Span<const T>;
} }
OX_CLANG_NOWARN_END

View File

@ -18,11 +18,14 @@
#endif #endif
#endif #endif
#include "def.hpp"
#include "defines.hpp" #include "defines.hpp"
#include "string.hpp" #include "string.hpp"
#include "trace.hpp" #include "trace.hpp"
#include "vector.hpp" #include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>) #if defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
@ -100,3 +103,5 @@ void printStackTrace([[maybe_unused]]unsigned shave) noexcept {
} }
} }
OX_CLANG_NOWARN_END

View File

@ -1,3 +1,10 @@
/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once #pragma once
@ -17,7 +24,7 @@ constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
constexpr auto base = 10; constexpr auto base = 10;
auto it = 0; auto it = 0;
if (val < 0) { if (val < 0) {
oxReturnError(writer.put('-')); OX_RETURN_ERROR(writer.put('-'));
++it; ++it;
} }
while (mod) { while (mod) {
@ -30,13 +37,13 @@ constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
start = 'a'; start = 'a';
digit -= 10; digit -= 10;
} }
oxReturnError(writer.put(static_cast<char>(start + digit))); OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
++it; ++it;
} }
} }
} else { } else {
// 0 is a special case // 0 is a special case
oxReturnError(writer.put('0')); OX_RETURN_ERROR(writer.put('0'));
} }
return {}; return {};
} }

View File

@ -13,6 +13,7 @@
#endif #endif
#include "algorithm.hpp" #include "algorithm.hpp"
#include "def.hpp"
#include "ignore.hpp" #include "ignore.hpp"
#include "memops.hpp" #include "memops.hpp"
#include "serialize.hpp" #include "serialize.hpp"
@ -22,6 +23,8 @@
#include "strops.hpp" #include "strops.hpp"
#include "vector.hpp" #include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename Integer> template<typename Integer>
@ -179,7 +182,7 @@ class BasicString {
// make sure last element is a null terminator // make sure last element is a null terminator
m_buff[currentLen + strLen] = 0; m_buff[currentLen + strLen] = 0;
// this can't fail, but it returns an Error to match BString::append // this can't fail, but it returns an Error to match BString::append
return OxError(0); return ox::Error(0);
} }
constexpr Error append(ox::StringView sv) noexcept { constexpr Error append(ox::StringView sv) noexcept {
@ -496,12 +499,12 @@ constexpr char &BasicString<SmallStringSize_v>::operator[](std::size_t i) noexce
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t pos) const noexcept { constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t pos) const noexcept {
return BasicString(m_buff.data() + pos, m_buff.size() - pos - 1); return BasicString(&m_buff[pos], m_buff.size() - pos - 1);
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t begin, std::size_t end) const noexcept { constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t begin, std::size_t end) const noexcept {
const auto src = m_buff.data() + begin; const auto src = &m_buff[begin];
const auto size = end - begin; const auto size = end - begin;
BasicString<SmallStringSize_v> out(size); BasicString<SmallStringSize_v> out(size);
const auto buff = out.data(); const auto buff = out.data();
@ -568,3 +571,5 @@ struct MaybeView<ox::BasicString<sz>> {
}; };
} }
OX_CLANG_NOWARN_END

View File

@ -17,6 +17,8 @@
#include "maybeview.hpp" #include "maybeview.hpp"
#include "writer.hpp" #include "writer.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<std::size_t buffLen> template<std::size_t buffLen>
@ -107,7 +109,7 @@ constexpr ox::Result<int> atoi(ox::StringViewCR str) noexcept {
total += (str[s] - '0') * multiplier; total += (str[s] - '0') * multiplier;
multiplier *= 10; multiplier *= 10;
} else { } else {
return OxError(1); return ox::Error(1);
} }
} }
return total; return total;
@ -116,3 +118,4 @@ constexpr ox::Result<int> atoi(ox::StringViewCR str) noexcept {
} }
OX_CLANG_NOWARN_END

View File

@ -6,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include "def.hpp"
#include "strops.hpp" #include "strops.hpp"
static_assert(ox::strcmp("asdf", "hijk") < 0, "asdf < hijk"); static_assert(ox::strcmp("asdf", "hijk") < 0, "asdf < hijk");
@ -17,7 +18,9 @@ static_assert(ox::strcmp("", "") == 0, "\"\" == \"\"");
static_assert([] { static_assert([] {
auto testStr = "asdf"; auto testStr = "asdf";
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
return ox::strchr(testStr, 0, 4) == &testStr[4]; return ox::strchr(testStr, 0, 4) == &testStr[4];
OX_CLANG_NOWARN_END
}(), "ox::strchr 0"); }(), "ox::strchr 0");
static_assert([] { static_assert([] {

View File

@ -9,18 +9,21 @@
#pragma once #pragma once
#include "cstrops.hpp" #include "cstrops.hpp"
#include "def.hpp"
#include "error.hpp" #include "error.hpp"
#include "math.hpp" #include "math.hpp"
#include "stringview.hpp" #include "stringview.hpp"
#include "types.hpp" #include "types.hpp"
#include "vector.hpp" #include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
[[nodiscard]] [[nodiscard]]
constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexcept { constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexcept {
if (str.len() >= pos) { if (str.len() >= pos) {
return {str.data() + pos, str.len() - pos}; return {&str[pos], str.len() - pos};
} }
return {}; return {};
} }
@ -28,7 +31,7 @@ constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexc
[[nodiscard]] [[nodiscard]]
constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std::size_t end) noexcept { constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std::size_t end) noexcept {
if (str.len() >= start && end >= start) { if (str.len() >= start && end >= start) {
return {str.data() + start, end - start}; return {&str[start], end - start};
} }
return {}; return {};
} }
@ -103,7 +106,7 @@ constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringView
[[nodiscard]] [[nodiscard]]
constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int character) noexcept { constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int character) noexcept {
ox::Result<std::size_t> retval = OxError(1, "Character not found"); ox::Result<std::size_t> retval = ox::Error(1, "Character not found");
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) { for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
if (str[static_cast<std::size_t>(i)] == character) { if (str[static_cast<std::size_t>(i)] == character) {
retval = static_cast<std::size_t>(i); retval = static_cast<std::size_t>(i);
@ -113,3 +116,5 @@ constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int characte
} }
} }
OX_CLANG_NOWARN_END

View File

@ -121,10 +121,12 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
auto a1 = static_cast<char*>(ox::heapmgr::malloc(5)); auto a1 = static_cast<char*>(ox::heapmgr::malloc(5));
auto a2 = static_cast<char*>(ox::heapmgr::malloc(5)); auto a2 = static_cast<char*>(ox::heapmgr::malloc(5));
oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken"); oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken");
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken"); oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken");
OX_CLANG_NOWARN_END
ox::heapmgr::free(a1); ox::heapmgr::free(a1);
ox::heapmgr::free(a2); ox::heapmgr::free(a2);
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -134,10 +136,10 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
ox::CharBuffWriter bw(buff); ox::CharBuffWriter bw(buff);
oxAssert(ox::writeItoa(5, bw), "ox::writeItoa returned Error"); oxAssert(ox::writeItoa(5, bw), "ox::writeItoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("5")); oxExpect(ox::StringView(buff.data()), ox::StringView("5"));
oxReturnError(bw.seekp(0)); OX_RETURN_ERROR(bw.seekp(0));
oxAssert(ox::writeItoa(50, bw), "ox::writeItoa returned Error"); oxAssert(ox::writeItoa(50, bw), "ox::writeItoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("50")); oxExpect(ox::StringView(buff.data()), ox::StringView("50"));
oxReturnError(bw.seekp(0)); OX_RETURN_ERROR(bw.seekp(0));
oxAssert(ox::writeItoa(500, bw), "ox::writeItoa returned Error"); oxAssert(ox::writeItoa(500, bw), "ox::writeItoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("500")); oxExpect(ox::StringView(buff.data()), ox::StringView("500"));
return ox::Error{}; return ox::Error{};
@ -146,41 +148,41 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
"ABCDEFG != HIJKLMN", "ABCDEFG != HIJKLMN",
[]() { []() {
return OxError(ox::memcmp("ABCDEFG", "HIJKLMN", 7) >= 0); return ox::Error(ox::memcmp("ABCDEFG", "HIJKLMN", 7) >= 0);
} }
}, },
{ {
"HIJKLMN != ABCDEFG", "HIJKLMN != ABCDEFG",
[]() { []() {
return OxError(ox::memcmp("HIJKLMN", "ABCDEFG", 7) <= 0); return ox::Error(ox::memcmp("HIJKLMN", "ABCDEFG", 7) <= 0);
} }
}, },
{ {
"ABCDEFG == ABCDEFG", "ABCDEFG == ABCDEFG",
[]() { []() {
return OxError(ox::memcmp("ABCDEFG", "ABCDEFG", 7) != 0); return ox::Error(ox::memcmp("ABCDEFG", "ABCDEFG", 7) != 0);
} }
}, },
{ {
"ABCDEFGHI == ABCDEFG", "ABCDEFGHI == ABCDEFG",
[]() { []() {
return OxError(ox::memcmp("ABCDEFGHI", "ABCDEFG", 7) != 0); return ox::Error(ox::memcmp("ABCDEFGHI", "ABCDEFG", 7) != 0);
} }
}, },
{ {
"IString", "IString",
[]() { []() {
ox::IString<5> s; ox::IString<5> s;
oxReturnError(s.append("A")); OX_RETURN_ERROR(s.append("A"));
oxReturnError(s.append("B")); OX_RETURN_ERROR(s.append("B"));
oxReturnError(s.append("9")); OX_RETURN_ERROR(s.append("9"));
oxReturnError(s.append("C")); OX_RETURN_ERROR(s.append("C"));
oxAssert(s == "AB9C", "IString append broken"); oxAssert(s == "AB9C", "IString append broken");
s = "asdf"; s = "asdf";
oxAssert(s == "asdf", "String assign broken"); oxAssert(s == "asdf", "String assign broken");
oxAssert(s != "aoeu", "String assign broken"); oxAssert(s != "aoeu", "String assign broken");
oxAssert(s.len() == 4, "String assign broken"); oxAssert(s.len() == 4, "String assign broken");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -214,7 +216,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert( oxAssert(
ox::String(ox::StringView("Write")) == ox::StringView("Write"), ox::String(ox::StringView("Write")) == ox::StringView("Write"),
"String / StringView comparison broken"); "String / StringView comparison broken");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -225,14 +227,14 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(v.empty(), "Vector::empty() is broken"); oxAssert(v.empty(), "Vector::empty() is broken");
auto insertTest = [&v](int val, std::size_t size) { auto insertTest = [&v](int val, std::size_t size) {
v.push_back(val); v.push_back(val);
oxReturnError(OxError(v.size() != size, "Vector size incorrect")); OX_RETURN_ERROR(ox::Error(v.size() != size, "Vector size incorrect"));
oxReturnError(OxError(v[v.size() - 1] != val, "Vector value wrong")); OX_RETURN_ERROR(ox::Error(v[v.size() - 1] != val, "Vector value wrong"));
return OxError(0); return ox::Error(0);
}; };
oxAssert(insertTest(42, 1), "Vector insertion failed"); oxAssert(insertTest(42, 1), "Vector insertion failed");
oxAssert(insertTest(100, 2), "Vector insertion failed"); oxAssert(insertTest(100, 2), "Vector insertion failed");
oxAssert(insertTest(102, 3), "Vector insertion failed"); oxAssert(insertTest(102, 3), "Vector insertion failed");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -244,7 +246,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxExpect(map.size(), 1u); oxExpect(map.size(), 1u);
oxExpect(map["aoeu"], ""); oxExpect(map["aoeu"], "");
oxExpect(map.size(), 2u); oxExpect(map.size(), 2u);
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -260,7 +262,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
ii[5] = 100; ii[5] = 100;
oxAssert(ii[4] == 42, "4 != 42"); oxAssert(ii[4] == 42, "4 != 42");
oxAssert(ii[5] == 100, "5 != 100"); oxAssert(ii[5] == 100, "5 != 100");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -276,7 +278,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
ii[5] = 100; ii[5] = 100;
oxAssert(ii[4] == 42, "4 != 42"); oxAssert(ii[4] == 42, "4 != 42");
oxAssert(ii[5] == 100, "5 != 100"); oxAssert(ii[5] == 100, "5 != 100");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -317,7 +319,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxExpect(ox::serialize<uint32_t>(257).unwrap(), BA({1, 1, 0, 0})); oxExpect(ox::serialize<uint32_t>(257).unwrap(), BA({1, 1, 0, 0}));
constexpr auto neg1 = static_cast<char>(-1); // ARM64 Linux assumes -1 literals are ints... constexpr auto neg1 = static_cast<char>(-1); // ARM64 Linux assumes -1 literals are ints...
oxExpect(ox::serialize<uint32_t>(0xffff'ffff).unwrap(), BA({neg1, neg1, neg1, neg1})); oxExpect(ox::serialize<uint32_t>(0xffff'ffff).unwrap(), BA({neg1, neg1, neg1, neg1}));
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -334,7 +336,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed"); oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
oxExpect(b.size(), 14u); oxExpect(b.size(), 14u);
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty"); oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -357,7 +359,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxExpect(ox::detail::fromHex("a0").unwrap(), 0xa0); oxExpect(ox::detail::fromHex("a0").unwrap(), 0xa0);
oxExpect(ox::detail::fromHex("93").unwrap(), 0x93); oxExpect(ox::detail::fromHex("93").unwrap(), 0x93);
oxExpect(ox::detail::fromHex("40").unwrap(), 0x40); oxExpect(ox::detail::fromHex("40").unwrap(), 0x40);
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -377,18 +379,18 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxExpect(ox::detail::toHex(0x93), "93"); oxExpect(ox::detail::toHex(0x93), "93");
oxExpect(ox::detail::toHex(0x40), "40"); oxExpect(ox::detail::toHex(0x40), "40");
oxExpect(ox::detail::toHex(0xf0), "f0"); oxExpect(ox::detail::toHex(0xf0), "f0");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
"UUID", "UUID",
[] { [] {
constexpr ox::StringView uuidStr = "8d814442-f46e-4cc3-8edc-ca3c01cc86db"; constexpr ox::StringView uuidStr = "8d814442-f46e-4cc3-8edc-ca3c01cc86db";
oxRequire(uuid, ox::UUID::fromString(uuidStr)); OX_REQUIRE(uuid, ox::UUID::fromString(uuidStr));
oxExpect(uuid.toString(), uuidStr); oxExpect(uuid.toString(), uuidStr);
oxExpect(ox::UUID{}.isNull(), true); oxExpect(ox::UUID{}.isNull(), true);
oxExpect(ox::UUID::fromString(uuidStr).value.isNull(), false); oxExpect(ox::UUID::fromString(uuidStr).value.isNull(), false);
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -398,7 +400,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxExpect(ox::UUID::generate().unwrap().toString(), "5c3f4b5e-ccbf-4727-7f03-3053dedc8827"); oxExpect(ox::UUID::generate().unwrap().toString(), "5c3f4b5e-ccbf-4727-7f03-3053dedc8827");
oxExpect(ox::UUID::generate().unwrap().toString(), "90d0274a-2774-4afa-88e5-0c1d60ba3abf"); oxExpect(ox::UUID::generate().unwrap().toString(), "90d0274a-2774-4afa-88e5-0c1d60ba3abf");
oxExpect(ox::UUID::generate().unwrap().toString(), "7df77910-841c-48ba-ea2e-44521ac47c2e"); oxExpect(ox::UUID::generate().unwrap().toString(), "7df77910-841c-48ba-ea2e-44521ac47c2e");
return OxError(0); return ox::Error(0);
} }
}, },
{ {
@ -465,15 +467,17 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
sv = ""; sv = "";
list = ox::split(sv, '.'); list = ox::split(sv, '.');
oxExpect(list.size(), 0u); oxExpect(list.size(), 0u);
return OxError(0); return ox::Error(0);
} }
}, },
}; };
int main(int argc, const char **args) { int main(int argc, const char **argv) {
if (argc < 2) { if (argc < 2) {
oxError("Must specify test to run"); oxError("Must specify test to run");
return -1;
} }
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const testName = args[1]; auto const testName = args[1];
auto const func = tests.find(testName); auto const func = tests.find(testName);
if (func != tests.end()) { if (func != tests.end()) {

View File

@ -10,6 +10,17 @@
namespace ox::trace { namespace ox::trace {
static class: public Logger {
public:
ox::Error send(const TraceMsg&) noexcept final {
return {};
}
ox::Error sendInit(const InitTraceMsg&) noexcept final {
return {};
}
} defaultLogger;
static Logger *logger = &defaultLogger;
void init() { void init() {
oxTraceInitHook(); oxTraceInitHook();
} }
@ -19,19 +30,6 @@ void init(Logger *logger) {
setLogger(logger); setLogger(logger);
} }
class NullLogger: public Logger {
public:
ox::Error send(const TraceMsg&) noexcept final {
return {};
}
ox::Error sendInit(const InitTraceMsg&) noexcept final {
return {};
}
};
static NullLogger defaultLogger;
static Logger *logger = &defaultLogger;
void setLogger(Logger *logger) noexcept { void setLogger(Logger *logger) noexcept {
trace::logger = logger; trace::logger = logger;
} }

View File

@ -48,12 +48,12 @@ struct TraceMsgRcv {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<TraceMsgRcv> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<TraceMsgRcv> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TraceMsgRcv>()); OX_RETURN_ERROR(io->template setTypeInfo<TraceMsgRcv>());
oxReturnError(io->field("file", &obj->file)); OX_RETURN_ERROR(io->field("file", &obj->file));
oxReturnError(io->field("line", &obj->line)); OX_RETURN_ERROR(io->field("line", &obj->line));
oxReturnError(io->field("time", &obj->time)); OX_RETURN_ERROR(io->field("time", &obj->time));
oxReturnError(io->field("ch", &obj->ch)); OX_RETURN_ERROR(io->field("ch", &obj->ch));
oxReturnError(io->field("msg", &obj->msg)); OX_RETURN_ERROR(io->field("msg", &obj->msg));
return {}; return {};
} }
@ -69,12 +69,12 @@ struct TraceMsg {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<TraceMsg> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<TraceMsg> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<TraceMsg>()); OX_RETURN_ERROR(io->template setTypeInfo<TraceMsg>());
oxReturnError(io->fieldCString("file", &obj->file)); OX_RETURN_ERROR(io->fieldCString("file", &obj->file));
oxReturnError(io->field("line", &obj->line)); OX_RETURN_ERROR(io->field("line", &obj->line));
oxReturnError(io->field("time", &obj->time)); OX_RETURN_ERROR(io->field("time", &obj->time));
oxReturnError(io->fieldCString("ch", &obj->ch)); OX_RETURN_ERROR(io->fieldCString("ch", &obj->ch));
oxReturnError(io->field("msg", &obj->msg)); OX_RETURN_ERROR(io->field("msg", &obj->msg));
return {}; return {};
} }
@ -87,8 +87,8 @@ struct InitTraceMsgRcv {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<InitTraceMsgRcv> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<InitTraceMsgRcv> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<InitTraceMsgRcv>()); OX_RETURN_ERROR(io->template setTypeInfo<InitTraceMsgRcv>());
oxReturnError(io->field("appName", &obj->appName)); OX_RETURN_ERROR(io->field("appName", &obj->appName));
return {}; return {};
} }
@ -101,8 +101,8 @@ struct InitTraceMsg {
template<typename T> template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<InitTraceMsg> auto *obj) noexcept { constexpr Error model(T *io, ox::CommonPtrWith<InitTraceMsg> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<InitTraceMsg>()); OX_RETURN_ERROR(io->template setTypeInfo<InitTraceMsg>());
oxReturnError(io->field("appName", &obj->appName)); OX_RETURN_ERROR(io->field("appName", &obj->appName));
return {}; return {};
} }
@ -173,7 +173,7 @@ class OutStream {
return *this; return *this;
} }
constexpr OutStream &operator<<(const char *v) noexcept { constexpr OutStream &operator<<(StringViewCR v) noexcept {
if (m_msg.msg.len()) { if (m_msg.msg.len()) {
m_msg.msg += m_delimiter; m_msg.msg += m_delimiter;
} }
@ -181,6 +181,10 @@ class OutStream {
return *this; return *this;
} }
constexpr OutStream &operator<<(const char *v) noexcept {
return operator<<(StringView{v});
}
template<std::size_t sz> template<std::size_t sz>
constexpr OutStream &operator<<(const IString<sz> &v) noexcept { constexpr OutStream &operator<<(const IString<sz> &v) noexcept {
return operator<<(v.c_str()); return operator<<(v.c_str());

View File

@ -61,6 +61,8 @@ using uint_t = unsigned;
namespace ox { namespace ox {
using CString = char const*;
/** /**
* Aliases type T in size and alignment to allow allocating space for a T * Aliases type T in size and alignment to allow allocating space for a T
* without running the constructor. * without running the constructor.

View File

@ -269,6 +269,41 @@ template<class T>
constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0); constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0);
template<typename T>
struct remove_cv {
using type = T;
};
template<typename T>
struct remove_cv<const T> {
using type = T;
};
template<typename T>
struct remove_cv<volatile T> {
using type = T;
};
template<typename T>
struct remove_cv<const volatile T> {
using type = T;
};
template<typename T>
struct remove_const {
using type = T;
};
template<typename T>
struct remove_const<const T> {
using type = T;
};
template<typename T>
using remove_const_t = typename remove_const<T>::type;
// is String? // is String?
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>

View File

@ -21,7 +21,7 @@ void UUID::seedGenerator(const RandomSeed &seed) noexcept {
// UUID v4 // UUID v4
Result<UUID> UUID::generate() noexcept { Result<UUID> UUID::generate() noexcept {
if (!s_seeded) { if (!s_seeded) {
return OxError(1, "UUID generator not seeded."); return ox::Error(1, "UUID generator not seeded.");
} }
UUID out; UUID out;
for (auto &v : out.m_value) { for (auto &v : out.m_value) {

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