Compare commits
295 Commits
release-d2
...
54d7c706eb
| Author | SHA1 | Date | |
|---|---|---|---|
| 54d7c706eb | |||
| c9cb186462 | |||
| f204d01a3d | |||
| 62337bd29e | |||
| 7b24b33849 | |||
| 86c2c26d8d | |||
| f8b2700ea7 | |||
| 7848cbbbff | |||
| 96c5223e44 | |||
| d19b848427 | |||
| c812051ec0 | |||
| 3c07eb2df7 | |||
| ca851e1059 | |||
| 11e75cb6ca | |||
| 8c4add57e4 | |||
| 5e1698a321 | |||
| 3e95bc0842 | |||
| 58e19fad48 | |||
| a3a56b24e8 | |||
| 7681830ca6 | |||
| 46a7331754 | |||
| 56c19ad2a6 | |||
| c6ecadf9a8 | |||
| 2ed469f2dd | |||
| 53aea9731d | |||
| 0e028ff653 | |||
| 07688a2c29 | |||
| 9ce4d3f8c7 | |||
| 4aa8255c55 | |||
| bfdfc10425 | |||
| cdd574d873 | |||
| bc05bd12e5 | |||
| b754c66cf5 | |||
| 6a42303239 | |||
| 7477ede222 | |||
| 65e3153dda | |||
| 53a224cf8f | |||
| 592e641ba9 | |||
| 689da4a019 | |||
| bdf7755ee2 | |||
| 63f627377d | |||
| ff9002ad9a | |||
| 4d0da022cf | |||
| 02332d99b5 | |||
| a566ed2a8b | |||
| 815c3d19bf | |||
| 522bb14f18 | |||
| f40d5515f9 | |||
| 941d1d90dc | |||
| 3e880dcdcc | |||
| 03328ac10f | |||
| 63d0abaa3c | |||
| ef2a8cda77 | |||
| 671fa54f6f | |||
| 517432679b | |||
| b31c01f724 | |||
| f41213f13f | |||
| 28be7c4650 | |||
| 2f340b13b2 | |||
| 312c818866 | |||
| 0d69d0c4a2 | |||
| 81a0b8c820 | |||
| 172b5aee90 | |||
| 2b5338a9df | |||
| 8a430faf4c | |||
| e59382dd60 | |||
| 3006e77ef3 | |||
| 59c112a69c | |||
| 31b39982c5 | |||
| 5476417be2 | |||
| e03be694c2 | |||
| 490c0368bc | |||
| a24fc407c5 | |||
| e38b85b4f4 | |||
| f7c3c02c4c | |||
| 8f0f1fea39 | |||
| 2f36a3f6f0 | |||
| 07e5bf9054 | |||
| aacff3daf9 | |||
| e27eee50f0 | |||
| fd610454d6 | |||
| e61d4647b5 | |||
| c275c5f5e6 | |||
| fbf49ba511 | |||
| 92f74b27d1 | |||
| 934f0c9232 | |||
| ee9a3e1152 | |||
| 16886cdf1c | |||
| 08b9508d83 | |||
| 69bd968f98 | |||
| 4e7dc66610 | |||
| bea0cf5a0c | |||
| c7bc2a954f | |||
| 7372036a0a | |||
| 7461d832b6 | |||
| 6052798fea | |||
| fae1e73e54 | |||
| 51f2905c9c | |||
| 0c866d1b96 | |||
| fdf39d1a25 | |||
| a523a75e4b | |||
| cdaa64ed3f | |||
| 801d35c823 | |||
| 37b5fcc0f7 | |||
| f5f2c3bee6 | |||
| f6ef2b5acb | |||
| bf958a4a6e | |||
| 6a70e478a6 | |||
| 671b8edaad | |||
| 952637a1ea | |||
| 7569698e95 | |||
| 21713ba945 | |||
| 73273b6fa7 | |||
| 9f040392c7 | |||
| f4f7e5d053 | |||
| f847289bd4 | |||
| 94b0020d15 | |||
| c54c0bad38 | |||
| b9ffae0269 | |||
| 003f3e01c6 | |||
| 9028e74af0 | |||
| f5ccab5f2c | |||
| c27726a4a9 | |||
| 37cfa927d1 | |||
| 0efed70b57 | |||
| baf5fa3199 | |||
| bd24a775b2 | |||
| 857587c18b | |||
| eb3d53c955 | |||
| 14d58f3f5b | |||
| 5f2397903a | |||
| 58e0ecb469 | |||
| 8838bf420e | |||
| bddc544d7c | |||
| a9437191bf | |||
| 9d8da7ccda | |||
| 394b568e72 | |||
| 78e9f70db6 | |||
| 12e5623fe6 | |||
| cfdfb0a8c9 | |||
| 56e665301f | |||
| 7415ce4bd9 | |||
| 05f42150a1 | |||
| 8ea2bc6934 | |||
| c780924122 | |||
| 8c538560ca | |||
| c3e75bdb55 | |||
| 4419dff299 | |||
| e78c405046 | |||
| 6b7c5d896e | |||
| a33a73d73a | |||
| 536999c070 | |||
| e1cfcc8b5f | |||
| 514cb97835 | |||
| 4b5218c4f1 | |||
| 2ca77173d3 | |||
| cce5f52f96 | |||
| b55993294a | |||
| d8f847d707 | |||
| a5535ef59a | |||
| 8419b137e5 | |||
| ed1160ec74 | |||
| 1e21778059 | |||
| 78379f58c8 | |||
| 4322f720ba | |||
| 26f1a6051f | |||
| c4c1d4777b | |||
| fab012d3e7 | |||
| a90380f377 | |||
| 312097a799 | |||
| a40198ab8d | |||
| 52d8c0bdc8 | |||
| c19d7f4ea3 | |||
| 159b7e7ee7 | |||
| c93eec4f05 | |||
| e7e7a22390 | |||
| 26d5048e67 | |||
| 3b8f97cc41 | |||
| f1e68e0a04 | |||
| d6e4ab7a24 | |||
| 2000b2deee | |||
| 7d92400f6d | |||
| cb304ecf28 | |||
| ea17377700 | |||
| c424bde06d | |||
| ee7d5c6d51 | |||
| 99247cee32 | |||
| 7b8ddc189a | |||
| a6814030ee | |||
| 9937a01042 | |||
| abcf2adc56 | |||
| 05f9023550 | |||
| 5ba0bcf963 | |||
| 3ccadba2f5 | |||
| 00e52b6491 | |||
| ae40487990 | |||
| 84b612c693 | |||
| 3c2a6b047e | |||
| 626da322d9 | |||
| 0de428a2e5 | |||
| 8a52df4f76 | |||
| efec6eb3c8 | |||
| 56eeb24900 | |||
| ae81f6b3de | |||
| c1108301c0 | |||
| 83fbe6ac74 | |||
| 80b452833f | |||
| 0fa394333b | |||
| cae7535034 | |||
| df87832324 | |||
| d585794cbe | |||
| 209658549c | |||
| 02383a4aed | |||
| 185a76282a | |||
| b722b4f701 | |||
| 459ab5aad9 | |||
| 565f621cfc | |||
| 9589ca9148 | |||
| 164db5007b | |||
| cbfb167d29 | |||
| e7b83be867 | |||
| 649da5fca8 | |||
| aa095f7680 | |||
| bb99c99f01 | |||
| 7f0dcdd280 | |||
| 6029ad5d47 | |||
| 26fe266b09 | |||
| 091eda7b44 | |||
| 9676ea5978 | |||
| de8ac10653 | |||
| 88a6cd59f3 | |||
| cd43fb7f38 | |||
| 136f422401 | |||
| e773d6f0ee | |||
| 7da2f68d30 | |||
| d20889aef1 | |||
| 50c8302f4a | |||
| d8195d300d | |||
| a8c1387d5a | |||
| ff1e8f260b | |||
| d4329981e7 | |||
| 0003454311 | |||
| 8c6b2234ec | |||
| aad4b8a44c | |||
| 7cab133127 | |||
| 640ac85de4 | |||
| b8d7658626 | |||
| 2503bb3b2c | |||
| e5dd448fe7 | |||
| 4770bb6a93 | |||
| c0bac696dc | |||
| 95f7c33419 | |||
| 535d8876d3 | |||
| 845e433221 | |||
| 5169a607cf | |||
| 8f03af99a7 | |||
| ee63a4a1e4 | |||
| ac29f7a0f2 | |||
| 89ae226b1d | |||
| 477834ac04 | |||
| 97b707b61c | |||
| e86180e842 | |||
| 035ba8810f | |||
| f1c2113dd3 | |||
| 56b79f414d | |||
| 844656d557 | |||
| 849aceb86d | |||
| eef51a6d2b | |||
| c84b85102c | |||
| 3fe62464c3 | |||
| db55fc722f | |||
| 2094450898 | |||
| 889bec04b1 | |||
| ac1e34d4cd | |||
| 55ed75f44d | |||
| 2751872c59 | |||
| 2a3cd35cc4 | |||
| b66f459f75 | |||
| 3910f4e77c | |||
| c0e96216ae | |||
| f9512d72e8 | |||
| b7f2c169ec | |||
| 1e5057d6e6 | |||
| c6255e3224 | |||
| 02230ef619 | |||
| 9b6b60e4d1 | |||
| b9a26ab61e | |||
| a521887ddd | |||
| 5ca7e2f226 | |||
| 125a235dd1 | |||
| 91a7129f8f | |||
| df48a232ec | |||
| ab11b885e6 | |||
| 36fc25fb7e | |||
| 4803cca334 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
sample_project text eol=lf
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,12 +6,14 @@
|
||||
.mypy_cache
|
||||
.stfolder
|
||||
.stignore
|
||||
.vs
|
||||
util/scripts/__pycache__
|
||||
pyenv
|
||||
CMakeLists.txt.user
|
||||
ROM.oxfs
|
||||
Session.vim
|
||||
build
|
||||
cmake-build-*
|
||||
compile_commands.json
|
||||
dist
|
||||
graph_info.json
|
||||
|
||||
60
Makefile
60
Makefile
@@ -14,28 +14,56 @@ endif
|
||||
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
|
||||
|
||||
.PHONY: pkg-gba
|
||||
pkg-gba: build
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
pkg-gba: build-pack build-gba-player
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
|
||||
|
||||
.PHONY: pkg-mac
|
||||
pkg-mac: install
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-dmg.py NostalgiaStudio
|
||||
|
||||
.PHONY: generate-studio-rsrc
|
||||
generate-studio-rsrc:
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/olympic/studio/applib/src/rsrc.json
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json
|
||||
|
||||
.PHONY: build-gba-player
|
||||
build-gba-player:
|
||||
cmake --build ./build/gba-*
|
||||
|
||||
.PHONY: build-player
|
||||
build-player:
|
||||
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME_CAP}
|
||||
|
||||
.PHONY: build-pack
|
||||
build-pack:
|
||||
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME}-pack
|
||||
|
||||
|
||||
.PHONY: run
|
||||
run: build-player
|
||||
${PROJECT_PLAYER} sample_project
|
||||
|
||||
.PHONY: build-studio
|
||||
build-studio:
|
||||
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME_CAP}Studio
|
||||
|
||||
.PHONY: run-studio
|
||||
run-studio: build
|
||||
run-studio: build-studio
|
||||
${PROJECT_STUDIO}
|
||||
|
||||
.PHONY: gba-run
|
||||
gba-run: pkg-gba
|
||||
${MGBA} ${BC_VAR_PROJECT_NAME}.gba
|
||||
${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba
|
||||
|
||||
.PHONY: debug
|
||||
debug: build
|
||||
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project
|
||||
|
||||
.PHONY: debug-studio
|
||||
debug-studio: build
|
||||
${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}
|
||||
|
||||
|
||||
.PHONY: configure-gba
|
||||
configure-gba:
|
||||
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=release --build_root=${BC_VAR_BUILD_PATH}
|
||||
@@ -43,3 +71,25 @@ configure-gba:
|
||||
.PHONY: configure-gba-debug
|
||||
configure-gba-debug:
|
||||
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
|
||||
|
||||
.PHONY: loc
|
||||
loc:
|
||||
${BC_PY3} util/scripts/loc.py \
|
||||
--search-dirs \
|
||||
src \
|
||||
deps/ox/src \
|
||||
deps/buildcore \
|
||||
deps/gbabuildcore \
|
||||
deps/glutils \
|
||||
deps/teagba \
|
||||
--include-exts \
|
||||
.cpp \
|
||||
.hpp \
|
||||
.py \
|
||||
.s \
|
||||
.cmake \
|
||||
--exclude-paths \
|
||||
deps/teagba/src/gba_crt0.s \
|
||||
src/olympic/studio/applib/src/font.cpp \
|
||||
src/olympic/studio/applib/src/font.hpp \
|
||||
src/nostalgia/studio/icondata.cpp
|
||||
|
||||
7
deps/buildcore/scripts/pybb.py
vendored
7
deps/buildcore/scripts/pybb.py
vendored
@@ -11,6 +11,7 @@
|
||||
# "Python Busy Box" - adds cross-platform equivalents to Unix commands that
|
||||
# don't translate well to that other operating system
|
||||
|
||||
import multiprocessing
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
@@ -57,7 +58,11 @@ def cmake_build(base_path: str, target: Optional[str]) -> int:
|
||||
path = os.path.join(base_path, d)
|
||||
if not os.path.isdir(path):
|
||||
continue
|
||||
args = ['cmake', '--build', path]
|
||||
args = ['cmake', '--build', path, f'-j{multiprocessing.cpu_count()}']
|
||||
if path.endswith('release'):
|
||||
args.append('--config=release')
|
||||
elif path.endswith('debug'):
|
||||
args.append('--config=debug')
|
||||
if target is not None:
|
||||
args.extend(['--target', target])
|
||||
err = subprocess.run(args).returncode
|
||||
|
||||
46
deps/glutils/include/glutils/glutils.hpp
vendored
46
deps/glutils/include/glutils/glutils.hpp
vendored
@@ -89,7 +89,7 @@ struct GLObject: public Base {
|
||||
return id;
|
||||
}
|
||||
|
||||
constexpr operator const GLuint&() const noexcept {
|
||||
constexpr operator GLuint const&() const noexcept {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ struct FrameBuffer {
|
||||
return fbo.id;
|
||||
}
|
||||
|
||||
constexpr operator const GLuint&() const noexcept {
|
||||
constexpr operator GLuint const&() const noexcept {
|
||||
return fbo.id;
|
||||
}
|
||||
|
||||
@@ -158,14 +158,14 @@ struct FrameBuffer {
|
||||
|
||||
class FrameBufferBind {
|
||||
private:
|
||||
static const FrameBuffer *s_activeFb;
|
||||
const FrameBuffer *m_restoreFb = nullptr;
|
||||
static FrameBuffer const *s_activeFb;
|
||||
FrameBuffer const *m_restoreFb = nullptr;
|
||||
public:
|
||||
explicit FrameBufferBind(const FrameBuffer &fb) noexcept;
|
||||
explicit FrameBufferBind(FrameBuffer const &fb) noexcept;
|
||||
~FrameBufferBind() noexcept;
|
||||
};
|
||||
|
||||
void bind(const FrameBuffer &fb) noexcept;
|
||||
void bind(FrameBuffer const &fb) noexcept;
|
||||
|
||||
struct ShaderVarSet {
|
||||
GLsizei len{};
|
||||
@@ -176,7 +176,7 @@ struct ProgramSource {
|
||||
ox::Vector<glutils::ShaderVarSet> const shaderParams;
|
||||
GLsizei const rowLen = [this] {
|
||||
GLsizei len{};
|
||||
for (auto const&v : shaderParams) {
|
||||
for (auto const &v : shaderParams) {
|
||||
len += v.len;
|
||||
}
|
||||
return len;
|
||||
@@ -187,23 +187,23 @@ struct ProgramSource {
|
||||
ox::String const geomShader{};
|
||||
};
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept;
|
||||
ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept;
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
ox::CStringView const&vert,
|
||||
ox::CStringView const&frag,
|
||||
ox::CStringView const&geo = "") noexcept;
|
||||
ox::CStringView const &vert,
|
||||
ox::CStringView const &frag,
|
||||
ox::CStringView const &geo = "") noexcept;
|
||||
|
||||
void setupShaderParams(
|
||||
GLProgram const&shader,
|
||||
ox::Vector<ShaderVarSet> const&vars,
|
||||
GLProgram const &shader,
|
||||
ox::Vector<ShaderVarSet> const &vars,
|
||||
GLsizei vertexRowLen) noexcept;
|
||||
|
||||
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept;
|
||||
void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept;
|
||||
|
||||
glutils::GLVertexArray generateVertexArrayObject() noexcept;
|
||||
GLVertexArray generateVertexArrayObject() noexcept;
|
||||
|
||||
glutils::GLBuffer generateBuffer() noexcept;
|
||||
GLBuffer generateBuffer() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
FrameBuffer generateFrameBuffer(int width, int height) noexcept;
|
||||
@@ -215,20 +215,20 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||
*/
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept;
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept;
|
||||
|
||||
struct BufferSet {
|
||||
glutils::GLVertexArray vao;
|
||||
glutils::GLBuffer vbo;
|
||||
glutils::GLBuffer ebo;
|
||||
glutils::GLTexture tex;
|
||||
GLVertexArray vao;
|
||||
GLBuffer vbo;
|
||||
GLBuffer ebo;
|
||||
GLTexture tex;
|
||||
ox::Vector<float> vertices;
|
||||
ox::Vector<GLuint> elements;
|
||||
};
|
||||
|
||||
void sendVbo(BufferSet const&bs) noexcept;
|
||||
void sendVbo(BufferSet const &bs) noexcept;
|
||||
|
||||
void sendEbo(BufferSet const&bs) noexcept;
|
||||
void sendEbo(BufferSet const &bs) noexcept;
|
||||
|
||||
void clearScreen() noexcept;
|
||||
|
||||
|
||||
71
deps/glutils/src/glutils.cpp
vendored
71
deps/glutils/src/glutils.cpp
vendored
@@ -46,9 +46,9 @@ template struct GLObject<deleteVertexArray>;
|
||||
template struct GLObject<deleteProgram>;
|
||||
template struct GLObject<deleteShader>;
|
||||
|
||||
const FrameBuffer *FrameBufferBind::s_activeFb = nullptr;
|
||||
FrameBuffer const *FrameBufferBind::s_activeFb = nullptr;
|
||||
|
||||
FrameBufferBind::FrameBufferBind(const FrameBuffer &fb) noexcept: m_restoreFb(s_activeFb) {
|
||||
FrameBufferBind::FrameBufferBind(FrameBuffer const &fb) noexcept: m_restoreFb(s_activeFb) {
|
||||
s_activeFb = &fb;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glViewport(0, 0, fb.width, fb.height);
|
||||
@@ -64,15 +64,15 @@ FrameBufferBind::~FrameBufferBind() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void bind(const FrameBuffer &fb) noexcept {
|
||||
void bind(FrameBuffer const &fb) noexcept {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glViewport(0, 0, fb.width, fb.height);
|
||||
}
|
||||
|
||||
|
||||
static ox::Result<GLShader> buildShader(
|
||||
GLuint shaderType,
|
||||
const GLchar *src,
|
||||
GLuint const shaderType,
|
||||
GLchar const *src,
|
||||
ox::StringViewCR shaderName) noexcept {
|
||||
GLShader shader(glCreateShader(shaderType));
|
||||
glShaderSource(shader, 1, &src, nullptr);
|
||||
@@ -88,7 +88,7 @@ static ox::Result<GLShader> buildShader(
|
||||
return shader;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
|
||||
ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept {
|
||||
OX_REQUIRE_M(program, buildShaderProgram(
|
||||
src.vertShader,
|
||||
src.fragShader,
|
||||
@@ -98,11 +98,11 @@ ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
|
||||
}
|
||||
|
||||
void setupShaderParams(
|
||||
GLProgram const&shader,
|
||||
ox::Vector<ShaderVarSet> const&vars,
|
||||
GLProgram const &shader,
|
||||
ox::Vector<ShaderVarSet> const &vars,
|
||||
GLsizei vertexRowLen) noexcept {
|
||||
// setup vars
|
||||
for (size_t lenWritten = 0; auto const&v : vars) {
|
||||
for (size_t lenWritten = 0; auto const &v : vars) {
|
||||
auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str()));
|
||||
glEnableVertexAttribArray(attr);
|
||||
glVertexAttribPointer(
|
||||
@@ -113,19 +113,19 @@ void setupShaderParams(
|
||||
}
|
||||
}
|
||||
|
||||
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept {
|
||||
void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept {
|
||||
// get row len
|
||||
GLsizei vertexRowLen{};
|
||||
for (auto const&v : vars) {
|
||||
for (auto const &v : vars) {
|
||||
vertexRowLen += v.len;
|
||||
}
|
||||
setupShaderParams(shader, vars, vertexRowLen);
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
ox::CStringView const&vert,
|
||||
ox::CStringView const&frag,
|
||||
ox::CStringView const&geo) noexcept {
|
||||
ox::CStringView const &vert,
|
||||
ox::CStringView const &frag,
|
||||
ox::CStringView const &geo) noexcept {
|
||||
GLProgram prgm(glCreateProgram());
|
||||
OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
|
||||
glAttachShader(prgm, vs);
|
||||
@@ -162,16 +162,30 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
// color texture
|
||||
glGenTextures(1, &fb.color.id);
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGB,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
||||
// depth texture
|
||||
glGenRenderbuffers(1, &fb.depth.id);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth);
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER,
|
||||
GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER,
|
||||
fb.depth);
|
||||
// verify FBO
|
||||
oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete");
|
||||
// restore primary FB
|
||||
@@ -189,7 +203,16 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
// color texture
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGB,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// depth texture
|
||||
@@ -201,7 +224,7 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int const width, int const height) noexcept {
|
||||
if (!fb) {
|
||||
fb = generateFrameBuffer(width, height);
|
||||
return;
|
||||
@@ -209,18 +232,18 @@ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
|
||||
resizeFrameBuffer(fb, width, height);
|
||||
}
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept {
|
||||
resizeInitFrameBuffer(fb, sz.width, sz.height);
|
||||
}
|
||||
|
||||
void sendVbo(BufferSet const&bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
||||
void sendVbo(BufferSet const &bs) noexcept {
|
||||
auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
void sendEbo(BufferSet const&bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
||||
void sendEbo(BufferSet const &bs) noexcept {
|
||||
auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
217
deps/ox/ox-docs.md
vendored
217
deps/ox/ox-docs.md
vendored
@@ -28,10 +28,7 @@ All components have a platform indicator next to them:
|
||||
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```.
|
||||
```ox::Error```s will also include the file and line of the 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
|
||||
@@ -49,7 +46,7 @@ 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)
|
||||
return ox::Error(1); // implicitly calls ox::Result<T>::Result(ox::Error)
|
||||
}
|
||||
|
||||
int caller1() {
|
||||
@@ -181,6 +178,216 @@ variant for creating a non-const value.
|
||||
|
||||
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
|
||||
|
||||
### Ox String Types
|
||||
|
||||
Ox has six different major string types.
|
||||
These types are divided into two categories: store types and view types.
|
||||
|
||||
String stores maintain a copy of the string data, whereas view types only
|
||||
maintain a reference to the data.
|
||||
Views should be used where you otherwise might use a const reference to a
|
||||
string store type.
|
||||
|
||||
Having all of these different string types may sound like an interoperability
|
||||
nightmare, but taking string view types extensively where applicable makes the
|
||||
imagined interoperability issues virtually non-existent.
|
||||
|
||||
#### String Store Types
|
||||
|
||||
##### String / BasicString
|
||||
|
||||
```ox::String```, or really ```ox::BasicString```, is Ox's version of
|
||||
```std::string```.
|
||||
Like ```std::string```, ```String``` allocates to store the string data.
|
||||
Also like ```std::string```, ```String``` allows for small string
|
||||
optimization for strings under 8 bytes.
|
||||
Unlike ```std::string```, the template that ```String``` is based on,
|
||||
```BasicString```, takes a parameter that allows adjusting to different size
|
||||
small string buffers.
|
||||
```ox::String``` is an alias to ```ox::BasicString<8>```.
|
||||
|
||||
```cpp
|
||||
// s can hold up to 100 bytes, plus one for a null terminator before allocating
|
||||
ox::BasicString<100> s;
|
||||
```
|
||||
Also unlike ```std::string```, ```ox::String``` has an explicit C-string conversion
|
||||
constructor.
|
||||
This prevents accidental instantiations of ```String```.
|
||||
|
||||
Consider the following:
|
||||
|
||||
```cpp
|
||||
void fStd(std::string const&);
|
||||
void fOx(ox::String const&);
|
||||
|
||||
int main() {
|
||||
// implicit and silent instantiation of std::string, which includes an
|
||||
// allocation
|
||||
fStd("123456789");
|
||||
// Will fail to compile:
|
||||
fOx("123456789");
|
||||
// But explicit String instantiation will work:
|
||||
fOx(ox::String{"123456789"});
|
||||
}
|
||||
```
|
||||
|
||||
##### IString
|
||||
|
||||
```IString```, or "inline string", is like ```BasicString```, but it will cut
|
||||
off strings that exceed that limit.
|
||||
|
||||
```cpp
|
||||
ox::IString<5> s; // s can hold up to 5 characters, plus a null terminator
|
||||
s = "12345"; // valid
|
||||
s = "123456"; // will compile and run, but will get cut off at '5'
|
||||
```
|
||||
|
||||
This is useful for certain string categories that have fixed lengths, like UUID
|
||||
strings or for numbers.
|
||||
|
||||
Ox makes use of ```IString``` in the following ways:
|
||||
|
||||
```cpp
|
||||
using UUIDStr = ox::IString<36>;
|
||||
|
||||
// and
|
||||
|
||||
template<Integer_c Integer>
|
||||
[[nodiscard]]
|
||||
constexpr auto intToStr(Integer v) noexcept {
|
||||
constexpr auto Cap = [] {
|
||||
auto out = 0;
|
||||
switch (sizeof(Integer)) {
|
||||
case 1:
|
||||
out = 3;
|
||||
break;
|
||||
case 2:
|
||||
out = 5;
|
||||
break;
|
||||
case 4:
|
||||
out = 10;
|
||||
break;
|
||||
case 8:
|
||||
out = 21;
|
||||
break;
|
||||
}
|
||||
return out + ox::is_signed_v<Integer>;
|
||||
}();
|
||||
ox::IString<Cap> out;
|
||||
std::ignore = out.resize(out.cap());
|
||||
ox::CharBuffWriter w{{out.data(), out.cap()}};
|
||||
std::ignore = writeItoa(v, w);
|
||||
std::ignore = out.resize(w.tellp());
|
||||
return out;
|
||||
}
|
||||
```
|
||||
|
||||
##### StringParam
|
||||
|
||||
```StringParam``` is a weird type.
|
||||
Because ```String::String(const char*)``` is explicit, it becomes a pain for
|
||||
functions to take ```String```s.
|
||||
|
||||
```cpp
|
||||
struct Type {
|
||||
ox::String m_s;
|
||||
explicit Type(ox::String p): m_s(std::move(p)) {
|
||||
}
|
||||
};
|
||||
|
||||
void f() {
|
||||
ox::String s{"asdf"};
|
||||
Type t1{"asdf"}; // invalid - will not compile
|
||||
Type t2{s}; // invalid - will not compile
|
||||
Type t3{std::move(s)}; // valid
|
||||
Type t4{ox::String{"asdf"}}; // valid
|
||||
}
|
||||
```
|
||||
|
||||
```StringParam``` has implicit conversion constructors, and will appropriately
|
||||
move from r-value ```String```s or create a ```String``` if not passed
|
||||
ownership of an existing ```String```.
|
||||
Think of ```StringParam``` as a way to opt-in to implicit instantiation with
|
||||
strings.
|
||||
|
||||
```StringParam``` can access the string as a view through the ```view()```
|
||||
function, and the ```String``` inside can be accessed by moving from the
|
||||
```StringParam```.
|
||||
|
||||
```cpp
|
||||
struct Type {
|
||||
ox::String m_s;
|
||||
explicit Type(ox::StringParam p): m_s(std::move(p)) {
|
||||
}
|
||||
};
|
||||
|
||||
void f() {
|
||||
ox::String s{"asdf"};
|
||||
Type t1{"asdf"}; // valid
|
||||
Type t2{s}; // valid
|
||||
Type t3{std::move(s)}; // valid
|
||||
Type t4{ox::String{"asdf"}}; // valid
|
||||
}
|
||||
```
|
||||
|
||||
#### String View Types
|
||||
|
||||
##### StringView
|
||||
|
||||
```ox::StringView``` is Ox's version of ```std::string_view```.
|
||||
```StringView``` contains a pointer to a string, along with its size.
|
||||
|
||||
This should be the normal type taken when a function needs a string that will
|
||||
exist until it returns.
|
||||
|
||||
##### CStringView
|
||||
|
||||
```CStringView``` is like ```StringView```, but it comes with the promise that
|
||||
the string ends with a null terminator.
|
||||
Accordingly, it has a ```c_str()``` function in addition to the ```data()```
|
||||
function that ```StringView``` has.
|
||||
|
||||
```CStringView``` should be used when wrapping a C API that only takes C
|
||||
strings.
|
||||
|
||||
##### StringLiteral
|
||||
|
||||
```StringLiteral``` is a string view type, but it kind of straddles the line
|
||||
between view and store types.
|
||||
Creating a ```StringLiteral``` is a promise that you are passing a string
|
||||
literal into the constructor.
|
||||
This means you can treat it like a store, that can be safely used as a copy of
|
||||
the data.
|
||||
Functions that take ```StringLiteral```s are allowed to assume that the data
|
||||
will have no lifetime concerns and hold onto it without any need to make a
|
||||
copy.
|
||||
It has a consteval constructor to enforce the promise that it is a compile time
|
||||
string.
|
||||
|
||||
```cpp
|
||||
void f(ox::StringLiteral const&);
|
||||
|
||||
int main() {
|
||||
f("123456789"); // valid
|
||||
f(ox::String{"123456789"}.c_str()); // invalid - will not compile
|
||||
}
|
||||
```
|
||||
|
||||
#### Other Variants
|
||||
|
||||
There are a few convenience aliases as well.
|
||||
|
||||
* StringCR = String const&
|
||||
* StringViewCR = StringView const&
|
||||
* CStringViewCR = CStringView const&
|
||||
* CString = const char*
|
||||
|
||||
String views do not generally need const references, but it does make debugging
|
||||
easier, as we can skip the constructor call if a string view already exists.
|
||||
|
||||
These kind of aliases probably should not exist for most types, but strings are
|
||||
fundamental and ease of use is desirable.
|
||||
|
||||
### Logging and Output
|
||||
|
||||
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.
|
||||
|
||||
16
deps/ox/src/ox/clargs/clargs.cpp
vendored
16
deps/ox/src/ox/clargs/clargs.cpp
vendored
@@ -15,21 +15,21 @@ ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<
|
||||
|
||||
ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
|
||||
for (auto i = 0u; i < args.size(); ++i) {
|
||||
auto arg = StringView(args[i]);
|
||||
auto arg = StringView{args[i]};
|
||||
if (arg[0] == '-') {
|
||||
while (arg[0] == '-' && arg.len()) {
|
||||
while (arg[0] == '-' && arg.size()) {
|
||||
arg = substr(arg, 1);
|
||||
}
|
||||
m_bools[arg] = true;
|
||||
// parse additional arguments
|
||||
if (i < args.size() && args[i + 1]) {
|
||||
auto val = String(args[i + 1]);
|
||||
if (val.len() && val[i] != '-') {
|
||||
auto const val = StringView{args[i + 1]};
|
||||
if (val.size() && val[0] != '-') {
|
||||
if (val == "false") {
|
||||
m_bools[arg] = false;
|
||||
}
|
||||
m_strings[arg] = val;
|
||||
if (auto r = ox::atoi(val.c_str()); r.error == 0) {
|
||||
if (auto r = ox::strToInt(val); r.error == 0) {
|
||||
m_ints[arg] = r.value;
|
||||
}
|
||||
++i;
|
||||
@@ -40,17 +40,17 @@ ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
|
||||
}
|
||||
|
||||
bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
auto const [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept {
|
||||
auto [value, err] = m_strings.at(arg);
|
||||
auto const [value, err] = m_strings.at(arg);
|
||||
return !err ? ox::String(*value) : ox::String(defaultValue);
|
||||
}
|
||||
|
||||
int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
auto const [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
|
||||
7
deps/ox/src/ox/claw/read.cpp
vendored
7
deps/ox/src/ox/claw/read.cpp
vendored
@@ -81,7 +81,7 @@ Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
|
||||
return ox::Error(4, "Claw format does not match any supported format/version combo");
|
||||
}
|
||||
hdr.typeName = typeName;
|
||||
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
|
||||
std::ignore = ox::strToInt(versionStr).copyTo(hdr.typeVersion);
|
||||
hdr.data = buffRaw;
|
||||
hdr.dataSize = buffLen;
|
||||
return hdr;
|
||||
@@ -106,15 +106,14 @@ Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
|
||||
{
|
||||
ox::BufferReader br({header.data, header.dataSize});
|
||||
MetalClawReader reader(br);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
OX_RETURN_ERROR(model(&handler, &obj));
|
||||
OX_RETURN_ERROR(model(reader.interface(), &obj));
|
||||
return obj;
|
||||
}
|
||||
case ClawFormat::Organic:
|
||||
{
|
||||
#ifdef OX_USE_STDLIB
|
||||
OrganicClawReader reader({header.data, header.dataSize});
|
||||
ModelHandlerInterface handler(&reader);
|
||||
ModelHandlerInterface handler(reader);
|
||||
OX_RETURN_ERROR(model(&handler, &obj));
|
||||
return obj;
|
||||
#else
|
||||
|
||||
3
deps/ox/src/ox/claw/read.hpp
vendored
3
deps/ox/src/ox/claw/read.hpp
vendored
@@ -52,8 +52,7 @@ Error readClaw(ox::BufferView buff, T &val) {
|
||||
{
|
||||
ox::BufferReader br({header.data, header.dataSize});
|
||||
MetalClawReader reader(br);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
return model(&handler, &val);
|
||||
return model(reader.interface(), &val);
|
||||
}
|
||||
case ClawFormat::Organic:
|
||||
{
|
||||
|
||||
8
deps/ox/src/ox/claw/test/tests.cpp
vendored
8
deps/ox/src/ox/claw/test/tests.cpp
vendored
@@ -109,7 +109,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
"ClawHeaderReader",
|
||||
[] {
|
||||
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
|
||||
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
|
||||
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
|
||||
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
|
||||
@@ -121,7 +121,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
"ClawHeaderReader2",
|
||||
[] {
|
||||
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
|
||||
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
|
||||
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
|
||||
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
|
||||
@@ -134,8 +134,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
[] {
|
||||
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
|
||||
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
|
||||
OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
|
||||
oxExpect(actual, expected);
|
||||
OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.size() + 1}));
|
||||
ox::expect(actual, expected);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
|
||||
2
deps/ox/src/ox/claw/write.hpp
vendored
2
deps/ox/src/ox/claw/write.hpp
vendored
@@ -39,7 +39,7 @@ struct TypeInfoCatcher {
|
||||
}
|
||||
|
||||
constexpr Error field(...) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr auto opType() {
|
||||
|
||||
4
deps/ox/src/ox/event/signal.hpp
vendored
4
deps/ox/src/ox/event/signal.hpp
vendored
@@ -218,7 +218,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
|
||||
for (auto &f : m_slots) {
|
||||
f->call(args...);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} catch (const ox::Exception &ex) {
|
||||
return ox::Error(ex.errCode, ex.msg, ex.src);
|
||||
}
|
||||
@@ -410,7 +410,7 @@ Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
|
||||
for (auto &f : m_slots) {
|
||||
OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ template<typename size_t>
|
||||
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
|
||||
OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
|
||||
++item->links;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
@@ -240,7 +240,7 @@ Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
|
||||
if (item->links == 0) {
|
||||
OX_RETURN_ERROR(remove(item));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
@@ -298,7 +298,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
|
||||
dest->id.get(), dest.offset(), destData.size());
|
||||
fsData->rootNode = dest.offset();
|
||||
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
|
||||
@@ -427,20 +427,20 @@ Error FileStoreTemplate<size_t>::resize() {
|
||||
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
|
||||
OX_RETURN_ERROR(m_buffer->setSize(newSize));
|
||||
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
|
||||
if (m_buffer->size() > size) {
|
||||
return ox::Error(1);
|
||||
return ox::Error{1, "new buffer is too small for existing data"};
|
||||
}
|
||||
m_buffSize = static_cast<size_t>(size);
|
||||
if (newBuff) {
|
||||
m_buffer = reinterpret_cast<Buffer*>(newBuff);
|
||||
m_buffer = static_cast<Buffer*>(newBuff);
|
||||
OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
@@ -479,7 +479,7 @@ Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
|
||||
for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
|
||||
OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
@@ -503,7 +503,7 @@ Error FileStoreTemplate<size_t>::compact() {
|
||||
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
|
||||
if (isFirstItem) {
|
||||
isFirstItem = false;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
if (!item.valid()) {
|
||||
return ox::Error(1);
|
||||
@@ -524,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
|
||||
parent->right = item;
|
||||
}
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
|
||||
item->left = root->left;
|
||||
item->right = root->right;
|
||||
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
return placeItem(root, item);
|
||||
}
|
||||
@@ -573,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
|
||||
item->right = right->right;
|
||||
}
|
||||
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
return placeItem(right, item, depth + 1);
|
||||
}
|
||||
@@ -586,7 +586,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
|
||||
item->right = left->right;
|
||||
}
|
||||
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
return placeItem(left, item, depth + 1);
|
||||
}
|
||||
@@ -624,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
|
||||
} else {
|
||||
fsData->rootNode = 0;
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
return unplaceItem(root, item);
|
||||
}
|
||||
@@ -661,7 +661,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
|
||||
if (item->left) {
|
||||
OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t>
|
||||
@@ -669,7 +669,7 @@ Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
|
||||
if (item.valid()) {
|
||||
OX_RETURN_ERROR(unplaceItem(item));
|
||||
OX_RETURN_ERROR(m_buffer->free(item));
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
return ox::Error(1);
|
||||
}
|
||||
|
||||
4
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
4
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
@@ -52,7 +52,7 @@ struct OX_PACKED DirectoryEntry {
|
||||
if (d.valid()) {
|
||||
d->inode = inode;
|
||||
auto const maxStrSz = bufferSize - 1 - sizeof(*this);
|
||||
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
|
||||
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.size()));
|
||||
return {};
|
||||
}
|
||||
return ox::Error(1);
|
||||
@@ -219,7 +219,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
|
||||
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
|
||||
return ox::Error(1, "Could not read existing version of Directory");
|
||||
}
|
||||
const auto pathSize = name.len() + 1;
|
||||
const auto pathSize = name.size() + 1;
|
||||
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
|
||||
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
|
||||
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
|
||||
|
||||
@@ -31,10 +31,10 @@ FileAddress::FileAddress(uint64_t inode) noexcept {
|
||||
FileAddress::FileAddress(ox::StringViewCR path) noexcept {
|
||||
auto pathSize = path.bytes();
|
||||
m_data.path = new char[pathSize + 1];
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
memcpy(m_data.path, path.data(), pathSize);
|
||||
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
m_data.path[pathSize] = 0;
|
||||
OX_CLANG_NOWARN_END
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,11 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
||||
case FileAddressType::Path:
|
||||
{
|
||||
if (other.m_data.path) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
auto strSize = ox::strlen(other.m_data.path) + 1;
|
||||
m_data.path = new char[strSize];
|
||||
ox::memcpy(m_data.path, other.m_data.path, strSize);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
} else {
|
||||
m_data.constPath = "";
|
||||
m_type = FileAddressType::ConstPath;
|
||||
|
||||
@@ -24,9 +24,6 @@ enum class FileAddressType: int8_t {
|
||||
Inode,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept;
|
||||
|
||||
class FileAddress {
|
||||
|
||||
template<typename T>
|
||||
|
||||
41
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
41
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@@ -20,7 +20,7 @@
|
||||
namespace ox {
|
||||
|
||||
namespace detail {
|
||||
static inline void fsBuffFree(char *buff) noexcept {
|
||||
inline void fsBuffFree(char *buff) noexcept {
|
||||
safeDelete(buff);
|
||||
}
|
||||
}
|
||||
@@ -49,11 +49,11 @@ class FileSystem {
|
||||
|
||||
Result<Buffer> read(StringViewCR path) noexcept;
|
||||
|
||||
inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
|
||||
Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
|
||||
return readFilePath(path, buffer, buffSize);
|
||||
}
|
||||
|
||||
inline Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
||||
Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
||||
return readFileInode(inode, buffer, buffSize);
|
||||
}
|
||||
|
||||
@@ -69,8 +69,7 @@ class FileSystem {
|
||||
* @param path
|
||||
* @param readStart
|
||||
* @param readSize
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param buff
|
||||
* @return error or number of bytes read
|
||||
*/
|
||||
Result<size_t> read(
|
||||
@@ -88,7 +87,7 @@ class FileSystem {
|
||||
return writeFilePath(path, buffer, size, FileType::NormalFile);
|
||||
}
|
||||
|
||||
Error write(StringViewCR path, ox::Span<char> const&buff) noexcept {
|
||||
Error write(StringViewCR path, ox::SpanView<char> const&buff) noexcept {
|
||||
return write(path, buff.data(), buff.size(), FileType::NormalFile);
|
||||
}
|
||||
|
||||
@@ -96,42 +95,42 @@ class FileSystem {
|
||||
return write(inode, buffer, size, FileType::NormalFile);
|
||||
}
|
||||
|
||||
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept {
|
||||
Error write(uint64_t inode, ox::SpanView<char> const&buff) noexcept {
|
||||
return write(inode, buff.data(), buff.size(), FileType::NormalFile);
|
||||
}
|
||||
|
||||
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
||||
|
||||
inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||
Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||
return writeFilePath(path, buffer, size, fileType);
|
||||
}
|
||||
|
||||
inline Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||
Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||
return writeFileInode(inode, buffer, size, fileType);
|
||||
}
|
||||
|
||||
inline Result<FileStat> stat(uint64_t inode) const noexcept {
|
||||
Result<FileStat> stat(uint64_t inode) const noexcept {
|
||||
return statInode(inode);
|
||||
}
|
||||
|
||||
inline Result<FileStat> stat(StringViewCR path) const noexcept {
|
||||
Result<FileStat> stat(StringViewCR path) const noexcept {
|
||||
return statPath(path);
|
||||
}
|
||||
|
||||
Result<FileStat> stat(const FileAddress &addr) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool exists(uint64_t inode) const noexcept {
|
||||
bool exists(uint64_t inode) const noexcept {
|
||||
return statInode(inode).ok();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool exists(ox::StringView path) const noexcept {
|
||||
bool exists(ox::StringView path) const noexcept {
|
||||
return statPath(path).ok();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool exists(FileAddress const&addr) const noexcept {
|
||||
bool exists(FileAddress const&addr) const noexcept {
|
||||
return stat(addr).ok();
|
||||
}
|
||||
|
||||
@@ -178,11 +177,11 @@ class MemFS: public FileSystem {
|
||||
public:
|
||||
Result<const char*> directAccess(const FileAddress &addr) const noexcept;
|
||||
|
||||
inline Result<const char*> directAccess(StringViewCR path) const noexcept {
|
||||
Result<const char*> directAccess(StringViewCR path) const noexcept {
|
||||
return directAccessPath(path);
|
||||
}
|
||||
|
||||
inline Result<const char*> directAccess(uint64_t inode) const noexcept {
|
||||
Result<const char*> directAccess(uint64_t inode) const noexcept {
|
||||
return directAccessInode(inode);
|
||||
}
|
||||
|
||||
@@ -330,7 +329,7 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
|
||||
return ox::Error(1);
|
||||
}
|
||||
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename FileStore, typename Directory>
|
||||
@@ -347,7 +346,7 @@ Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringVie
|
||||
OX_REQUIRE_M(inode, rootDir.find(src));
|
||||
OX_RETURN_ERROR(rootDir.write(dest, inode));
|
||||
OX_RETURN_ERROR(rootDir.remove(src));
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename FileStore, typename Directory>
|
||||
@@ -408,7 +407,7 @@ Error FileSystemTemplate<FileStore, Directory>::removePath(StringViewCR path, bo
|
||||
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
|
||||
return ox::Error(1);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename FileStore, typename Directory>
|
||||
@@ -425,7 +424,7 @@ Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR
|
||||
Vector<String> out;
|
||||
OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
|
||||
out.emplace_back(name);
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}));
|
||||
return out;
|
||||
}
|
||||
@@ -469,7 +468,7 @@ Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
|
||||
|
||||
template<typename FileStore, typename Directory>
|
||||
Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||
oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::itoa(inode));
|
||||
oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::intToStr(inode));
|
||||
return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType));
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
|
||||
if (ec.value()) {
|
||||
return ox::Error(1);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
|
||||
@@ -148,7 +148,7 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
|
||||
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
|
||||
return ox::Error(2);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
|
||||
@@ -197,7 +197,7 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
|
||||
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
|
||||
return ox::Error(1);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
|
||||
@@ -206,7 +206,7 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
|
||||
}
|
||||
|
||||
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
|
||||
for (auto i = 0u; i < path.len() && path[0] == '/'; i++) {
|
||||
for (auto i = 0u; i < path.size() && path[0] == '/'; i++) {
|
||||
path = substr(path, 1);
|
||||
}
|
||||
return {path.data(), path.bytes()};
|
||||
|
||||
@@ -99,7 +99,7 @@ Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
|
||||
for (auto &p : di) {
|
||||
OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
12
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
@@ -36,7 +36,7 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) {
|
||||
if (idx >= 0 && size < outSize) {
|
||||
ox::memcpy(out, m_path, size);
|
||||
out[size] = 0;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
return ox::Error(1);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ Error PathIterator::get(StringView &fileName) {
|
||||
if (size && fileName[size - 1] == '/') {
|
||||
fileName = ox::substr(m_path, start, start + size - 1);
|
||||
}
|
||||
oxAssert(fileName[fileName.len()-1] != '/', "name ends in /");
|
||||
oxAssert(fileName[fileName.size()-1] != '/', "name ends in /");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ Error PathIterator::next(StringView &fileName) {
|
||||
std::size_t size = 0;
|
||||
auto retval = ox::Error(1);
|
||||
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
|
||||
retval = ox::Error(0);
|
||||
retval = {};
|
||||
if (m_path[m_iterator] == '/') {
|
||||
m_iterator++;
|
||||
}
|
||||
@@ -104,11 +104,11 @@ Error PathIterator::next(StringView &fileName) {
|
||||
}
|
||||
fileName = ox::substr(m_path, start, start + size);
|
||||
// truncate trailing /
|
||||
while (fileName.len() && fileName[fileName.len() - 1] == '/') {
|
||||
while (fileName.size() && fileName[fileName.size() - 1] == '/') {
|
||||
fileName = ox::substr(m_path, start, start + size);
|
||||
}
|
||||
m_iterator += size;
|
||||
oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /");
|
||||
oxAssert(fileName.size() == 0 || fileName[fileName.size()-1] != '/', "name ends in /");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ Result<std::size_t> PathIterator::nextSize() const {
|
||||
auto retval = ox::Error(1);
|
||||
auto it = m_iterator;
|
||||
if (it < m_maxSize && ox::strlen(&m_path[it])) {
|
||||
retval = ox::Error(0);
|
||||
retval = {};
|
||||
if (m_path[it] == '/') {
|
||||
it++;
|
||||
}
|
||||
|
||||
6
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
6
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
@@ -354,7 +354,7 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
|
||||
}
|
||||
}
|
||||
m_header.bytesUsed -= item.size();
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t, typename Item>
|
||||
@@ -370,7 +370,7 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
|
||||
m_header.size = static_cast<size_t>(size);
|
||||
auto data = reinterpret_cast<uint8_t*>(this) + end;
|
||||
ox::memset(data, 0, size - end);
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
|
||||
src = ptr(dest->next);
|
||||
dest = uninitializedPtr(dest.offset() + dest->fullSize());
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename size_t, typename Item>
|
||||
|
||||
26
deps/ox/src/ox/fs/test/tests.cpp
vendored
26
deps/ox/src/ox/fs/test/tests.cpp
vendored
@@ -59,7 +59,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
"PathIterator::next1",
|
||||
[](ox::StringView) {
|
||||
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
ox::PathIterator it(path.c_str(), path.size());
|
||||
ox::StringView buff;
|
||||
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
||||
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
||||
@@ -74,9 +74,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
ox::PathIterator it(path);
|
||||
ox::StringView buff;
|
||||
oxAssert(it.next(buff), "PathIterator::next returned error");
|
||||
oxExpect(buff, "usr");
|
||||
ox::expect(buff, "usr");
|
||||
oxAssert(it.next(buff), "PathIterator::next returned error");
|
||||
oxExpect(buff, "share");
|
||||
ox::expect(buff, "share");
|
||||
return ox::Error(0);
|
||||
}
|
||||
},
|
||||
@@ -84,7 +84,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
"PathIterator::next3",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
ox::PathIterator it(path.c_str(), path.size());
|
||||
ox::StringView buff;
|
||||
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
|
||||
return ox::Error(0);
|
||||
@@ -106,7 +106,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
"PathIterator::next5",
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("usr/share/");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
ox::PathIterator it(path.c_str(), path.size());
|
||||
ox::StringView buff;
|
||||
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
||||
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
||||
@@ -117,9 +117,11 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
"PathIterator::dirPath",
|
||||
[] (ox::StringView) {
|
||||
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||
ox::PathIterator it(path.c_str(), path.size());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
oxAssert(it.dirPath(buff, path.size()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return ox::Error(0);
|
||||
}
|
||||
},
|
||||
@@ -127,7 +129,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
"PathIterator::hasNext",
|
||||
[](ox::StringView) {
|
||||
const auto path = "/file1";
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
ox::PathIterator it(path, ox::strlen(path));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
|
||||
oxAssert(!it.next().hasNext(), "PathIterator shows incorrect hasNext");
|
||||
return ox::Error(0);
|
||||
@@ -163,14 +167,16 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
[](ox::StringView) {
|
||||
constexpr auto buffLen = 5000;
|
||||
constexpr auto str1 = "Hello, World!";
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
constexpr auto str1Len = ox::strlen(str1) + 1;
|
||||
constexpr auto str2 = "Hello, Moon!";
|
||||
constexpr auto str2Len = ox::strlen(str2) + 1;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
||||
oxAssert(ox::FileStore32::format(list, buffLen), "FileStore::format failed.");
|
||||
ox::FileStore32 fileStore(list, buffLen);
|
||||
oxAssert(fileStore.write(4, const_cast<char*>(str1), str1Len, 1), "FileStore::write 1 failed.");
|
||||
oxAssert(fileStore.write(5, const_cast<char*>(str2), str2Len, 1), "FileStore::write 2 failed.");
|
||||
oxAssert(fileStore.write(4, str1, str1Len, 1), "FileStore::write 1 failed.");
|
||||
oxAssert(fileStore.write(5, str2, str2Len, 1), "FileStore::write 2 failed.");
|
||||
|
||||
char str1Read[str1Len];
|
||||
size_t str1ReadSize = 0;
|
||||
|
||||
6
deps/ox/src/ox/fs/tool.cpp
vendored
6
deps/ox/src/ox/fs/tool.cpp
vendored
@@ -48,7 +48,7 @@ static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept
|
||||
for (const auto &file : files) {
|
||||
oxOutf("{}\n", file);
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
|
||||
@@ -57,8 +57,10 @@ static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcep
|
||||
return ox::Error(1);
|
||||
}
|
||||
OX_REQUIRE(buff, fs->read(ox::StringView(args[1])));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
|
||||
return ox::Error(0);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error run(int argc, const char **argv) noexcept {
|
||||
|
||||
31
deps/ox/src/ox/logconn/logconn.cpp
vendored
31
deps/ox/src/ox/logconn/logconn.cpp
vendored
@@ -91,23 +91,28 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
|
||||
}
|
||||
|
||||
void LoggerConn::msgSend() noexcept {
|
||||
while (true) {
|
||||
std::unique_lock lk(m_waitMut);
|
||||
m_waitCond.wait(lk);
|
||||
if (!m_running) {
|
||||
break;
|
||||
}
|
||||
std::lock_guard const buffLk(m_buffMut);
|
||||
try {
|
||||
while (true) {
|
||||
Array<char, units::KB> tmp;
|
||||
const auto read = m_buff.read(tmp.data(), tmp.size());
|
||||
if (!read) {
|
||||
std::unique_lock lk(m_waitMut);
|
||||
m_waitCond.wait(lk);
|
||||
if (!m_running) {
|
||||
break;
|
||||
}
|
||||
oxAssert(read <= tmp.size(), "logger trying to read too much data");
|
||||
//std::printf("LoggerConn: sending %lu bytes\n", read);
|
||||
std::ignore = send(tmp.data(), read);
|
||||
std::lock_guard const buffLk(m_buffMut);
|
||||
while (true) {
|
||||
Array<char, units::KB> tmp;
|
||||
const auto read = m_buff.read(tmp.data(), tmp.size());
|
||||
if (!read) {
|
||||
break;
|
||||
}
|
||||
oxAssert(read <= tmp.size(), "logger trying to read too much data");
|
||||
//std::printf("LoggerConn: sending %lu bytes\n", read);
|
||||
std::ignore = send(tmp.data(), read);
|
||||
}
|
||||
}
|
||||
} catch (std::exception const &e) {
|
||||
oxErrf("Exception in logger thread: {}\n", e.what());
|
||||
oxAssert(false, "logger thread exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
deps/ox/src/ox/mc/CMakeLists.txt
vendored
1
deps/ox/src/ox/mc/CMakeLists.txt
vendored
@@ -1,6 +1,5 @@
|
||||
add_library(
|
||||
OxMetalClaw
|
||||
presenceindicator.cpp
|
||||
read.cpp
|
||||
write.cpp
|
||||
)
|
||||
|
||||
137
deps/ox/src/ox/mc/intops.hpp
vendored
137
deps/ox/src/ox/mc/intops.hpp
vendored
@@ -18,25 +18,25 @@
|
||||
|
||||
namespace ox::mc {
|
||||
|
||||
template<typename T>
|
||||
template<Integer_c T>
|
||||
static constexpr auto Bits = sizeof(T) << 3;
|
||||
|
||||
/**
|
||||
* Returns highest bit other than possible signed bit.
|
||||
* Bit numbering starts at 0.
|
||||
*/
|
||||
template<typename I>
|
||||
template<Integer_c I>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t highestBit(I val) noexcept {
|
||||
constexpr size_t highestBit(I const val) noexcept {
|
||||
unsigned shiftStart = sizeof(I) * 8 - 1;
|
||||
// find most significant non-sign indicator bit
|
||||
std::size_t highestBit = 0;
|
||||
// find the most significant non-sign indicator bit
|
||||
size_t highestBit = 0;
|
||||
// start at one bit lower if signed
|
||||
if constexpr(is_signed_v<I>) {
|
||||
--shiftStart;
|
||||
}
|
||||
for (auto i = shiftStart; i > 0; --i) {
|
||||
const auto bitValue = (val >> i) & 1;
|
||||
auto const bitValue = (val >> i) & 1;
|
||||
if (bitValue) {
|
||||
highestBit = i;
|
||||
break;
|
||||
@@ -45,7 +45,7 @@ constexpr std::size_t highestBit(I val) noexcept {
|
||||
return highestBit;
|
||||
}
|
||||
|
||||
static_assert(highestBit(int8_t(0b10000000)) == 0);
|
||||
static_assert(highestBit(static_cast<int8_t>(0b10000000)) == 0);
|
||||
static_assert(highestBit(~static_cast<int8_t>(-1)) == 0);
|
||||
static_assert(highestBit(~static_cast<int8_t>(-2)) == 0);
|
||||
static_assert(highestBit(~static_cast<int8_t>(-3)) == 1);
|
||||
@@ -53,40 +53,39 @@ static_assert(highestBit(1) == 0);
|
||||
static_assert(highestBit(2) == 1);
|
||||
static_assert(highestBit(4) == 2);
|
||||
static_assert(highestBit(8) == 3);
|
||||
static_assert(highestBit(uint64_t(1) << 31) == 31);
|
||||
static_assert(highestBit(uint64_t(1) << 63) == 63);
|
||||
static_assert(highestBit(static_cast<uint64_t>(1) << 31) == 31);
|
||||
static_assert(highestBit(static_cast<uint64_t>(1) << 63) == 63);
|
||||
|
||||
struct McInt {
|
||||
ox::Array<uint8_t, 9> data{};
|
||||
Array<uint8_t, 9> data{};
|
||||
// length of integer in bytes
|
||||
std::size_t length = 0;
|
||||
size_t length = 0;
|
||||
};
|
||||
|
||||
template<typename I>
|
||||
template<Integer_c I>
|
||||
[[nodiscard]]
|
||||
constexpr McInt encodeInteger(I pInput) noexcept {
|
||||
auto const input = ox::ResizedInt_t<I, 64>{pInput};
|
||||
constexpr McInt encodeInteger(I const pInput) noexcept {
|
||||
auto const input = ResizedInt_t<I, 64>{pInput};
|
||||
McInt out;
|
||||
const auto inputNegative = is_signed_v<I> && input < 0;
|
||||
// move input to uint64_t to allow consistent bit manipulation, and to avoid
|
||||
auto const inputNegative = is_signed_v<I> && input < 0;
|
||||
// move input to uint64_t to allow consistent bit manipulation and to avoid
|
||||
// overflow concerns
|
||||
uint64_t val = 0;
|
||||
ox::memcpy(&val, &input, sizeof(input));
|
||||
auto const val = std::bit_cast<uint64_t>(input);
|
||||
if (val) {
|
||||
// bits needed to represent number factoring in space possibly
|
||||
// needed for signed bit
|
||||
const auto highBit = inputNegative ? highestBit(~val) : highestBit(val);
|
||||
const auto bits = highBit + 1 + (is_signed_v<I> ? 1 : 0);
|
||||
auto const highBit = inputNegative ? highestBit(~val) : highestBit(val);
|
||||
auto const bits = highBit + 1 + (is_signed_v<I> ? 1 : 0);
|
||||
// bytes needed to store value
|
||||
std::size_t bytes = bits / 8 + (bits % 8 != 0);
|
||||
const auto bitsAvailable = bytes * 8; // bits available to integer value
|
||||
const auto bitsNeeded = bits + bytes;
|
||||
size_t bytes = bits / 8 + (bits % 8 != 0);
|
||||
auto const bitsAvailable = bytes * 8; // bits available to integer value
|
||||
auto const bitsNeeded = bits + bytes;
|
||||
// factor in bits needed for bytesIndicator (does not affect bytesIndicator)
|
||||
// bits for integer + bits needed to represent bytes > bits available
|
||||
if (bitsNeeded > bitsAvailable && bytes != 9) {
|
||||
++bytes;
|
||||
}
|
||||
const auto bytesIndicator = onMask<uint8_t>(bytes - 1);
|
||||
auto const bytesIndicator = onMask<uint8_t>(bytes - 1);
|
||||
// ensure we are copying from little endian representation
|
||||
LittleEndian<uint64_t> leVal = val;
|
||||
if (inputNegative) {
|
||||
@@ -94,17 +93,21 @@ constexpr McInt encodeInteger(I pInput) noexcept {
|
||||
}
|
||||
if (bytes == 9) {
|
||||
out.data[0] = bytesIndicator;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
ox::memcpy(&out.data[1], &leVal, 8);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
if (inputNegative) {
|
||||
out.data[1] |= 0b1000'0000;
|
||||
}
|
||||
} else {
|
||||
const auto valBits = bytes * 8;
|
||||
uint64_t negBit = inputNegative ? 1 : 0;
|
||||
auto intermediate =
|
||||
auto const valBits = bytes * 8;
|
||||
uint64_t const negBit = inputNegative ? 1 : 0;
|
||||
auto const intermediate =
|
||||
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
|
||||
static_cast<uint64_t>(bytesIndicator);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
ox::memcpy(&out.data[0], &intermediate, sizeof(intermediate));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}
|
||||
out.length = bytes;
|
||||
}
|
||||
@@ -116,8 +119,8 @@ constexpr McInt encodeInteger(I pInput) noexcept {
|
||||
* length integer.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t countBytes(unsigned b) noexcept {
|
||||
std::size_t i = 0;
|
||||
constexpr size_t countBytes(unsigned const b) noexcept {
|
||||
size_t i = 0;
|
||||
while ((b >> i) & 1) ++i;
|
||||
return i + 1;
|
||||
}
|
||||
@@ -132,61 +135,65 @@ static_assert(countBytes(0b0011'1111) == 7);
|
||||
static_assert(countBytes(0b0111'1111) == 8);
|
||||
static_assert(countBytes(0b1111'1111) == 9);
|
||||
|
||||
template<typename I>
|
||||
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
|
||||
template<Integer_c I>
|
||||
constexpr Result<I> decodeInteger(Reader_c auto &rdr, size_t &bytesRead) noexcept {
|
||||
uint8_t firstByte = 0;
|
||||
OX_RETURN_ERROR(rdr.read(&firstByte, 1));
|
||||
OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
|
||||
const auto bytes = countBytes(firstByte);
|
||||
auto const bytes = countBytes(firstByte);
|
||||
if (bytes == 9) {
|
||||
*bytesRead = bytes;
|
||||
bytesRead = bytes;
|
||||
I out = 0;
|
||||
OX_RETURN_ERROR(rdr.seekg(1, ox::ios_base::cur));
|
||||
OX_RETURN_ERROR(rdr.read(&out, sizeof(I)));
|
||||
return fromLittleEndian<I>(out);
|
||||
}
|
||||
*bytesRead = bytes;
|
||||
bytesRead = bytes;
|
||||
uint64_t decoded = 0;
|
||||
OX_RETURN_ERROR(rdr.read(&decoded, bytes));
|
||||
decoded >>= bytes;
|
||||
// move sign bit
|
||||
if constexpr(is_signed_v<I>) {
|
||||
const auto negBit = bytes * 8 - bytes - 1;
|
||||
// move sign
|
||||
const auto negative = (decoded >> negBit) == 1;
|
||||
if (negative) {
|
||||
// fill in all bits between encoded sign and real sign with 1s
|
||||
// split it up because the 32-bit ARM can't shift more than 32 bits
|
||||
ox::Array<uint32_t, 2> d = {};
|
||||
//d[0] = decoded & 0xffff'ffff;
|
||||
//d[1] = decoded >> 32;
|
||||
ox::memcpy(&d[0], &decoded, sizeof(decoded));
|
||||
auto bit = negBit;
|
||||
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
|
||||
d[0] |= 1 << bit;
|
||||
}
|
||||
bit -= 32;
|
||||
for (; bit < Bits<I>; ++bit) {
|
||||
d[1] |= 1 << bit;
|
||||
}
|
||||
I out = 0;
|
||||
if constexpr(ox::defines::BigEndian) {
|
||||
const auto d0Tmp = d[0];
|
||||
d[0] = d[1];
|
||||
d[1] = d0Tmp;
|
||||
}
|
||||
ox::memcpy(&out, &d[0], sizeof(out));
|
||||
return out;
|
||||
}
|
||||
auto const negBit = bytes * 8 - bytes - 1;
|
||||
// move sign
|
||||
auto const negative = (decoded >> negBit) == 1;
|
||||
if (negative) {
|
||||
// fill in all bits between encoded sign and real sign with 1s
|
||||
// split it up because the 32-bit ARM can't shift more than 32 bits
|
||||
Array<uint32_t, 2> d = {};
|
||||
//d[0] = decoded & 0xffff'ffff;
|
||||
//d[1] = decoded >> 32;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
ox::memcpy(&d[0], &decoded, sizeof(decoded));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
auto bit = negBit;
|
||||
for (; bit < ox::min<size_t>(Bits<I>, 32); ++bit) {
|
||||
d[0] |= 1 << bit;
|
||||
}
|
||||
bit -= 32;
|
||||
for (; bit < Bits<I>; ++bit) {
|
||||
d[1] |= 1 << bit;
|
||||
}
|
||||
I out = 0;
|
||||
if constexpr(ox::defines::BigEndian) {
|
||||
auto const d0Tmp = d[0];
|
||||
d[0] = d[1];
|
||||
d[1] = d0Tmp;
|
||||
}
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
ox::memcpy(&out, &d[0], sizeof(out));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return out;
|
||||
}
|
||||
}
|
||||
return static_cast<I>(decoded);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
Result<I> decodeInteger(McInt m) noexcept {
|
||||
std::size_t bytesRead{};
|
||||
template<Integer_c I>
|
||||
Result<I> decodeInteger(McInt const &m) noexcept {
|
||||
size_t bytesRead{};
|
||||
BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9});
|
||||
return decodeInteger<I>(br, &bytesRead);
|
||||
return decodeInteger<I>(br, bytesRead);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
17
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
17
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2025 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "err.hpp"
|
||||
#include "presenceindicator.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template class FieldBitmapWriterBase<uint8_t*>;
|
||||
template class FieldBitmapWriterBase<const uint8_t*>;
|
||||
|
||||
}
|
||||
221
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
221
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
@@ -11,6 +11,7 @@
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/bit.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/span.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/reader.hpp>
|
||||
|
||||
@@ -21,143 +22,101 @@ namespace ox {
|
||||
template<Reader_c Reader>
|
||||
class FieldBitmapReader {
|
||||
protected:
|
||||
mutable std::size_t m_mapBlockIdx = ~std::size_t{0};
|
||||
mutable uint64_t m_mapBlock = 0;
|
||||
std::size_t m_mapStart = 0;
|
||||
mutable size_t m_mapBlockIdx = ~size_t{};
|
||||
mutable uint64_t m_mapBlock{};
|
||||
size_t m_mapStart{};
|
||||
Reader &m_reader;
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
|
||||
explicit constexpr FieldBitmapReader(Reader &reader) noexcept:
|
||||
m_mapStart(reader.tellg()),
|
||||
m_reader(reader) {
|
||||
}
|
||||
|
||||
constexpr Result<bool> get(std::size_t i) const noexcept;
|
||||
constexpr Result<bool> get(size_t idx) const noexcept {
|
||||
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||
auto const blockIdx = idx / blockBits;
|
||||
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||
OX_RETURN_ERROR(loadMapBlock(blockIdx));
|
||||
}
|
||||
idx %= blockBits;
|
||||
return (m_mapBlock >> idx) & 1;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
|
||||
m_mapStart(reader.tellg()),
|
||||
m_reader(reader) {
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept {
|
||||
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||
auto const blockIdx = idx / blockBits;
|
||||
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||
OX_RETURN_ERROR(loadMapBlock(blockIdx));
|
||||
}
|
||||
idx %= blockBits;
|
||||
return (m_mapBlock >> idx) & 1;
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||
// Warning: narrow-conv
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||
m_mapBlock = 0;
|
||||
for (auto i = 0ull; auto b : mapBlock) {
|
||||
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||
i += 8;
|
||||
}
|
||||
m_mapBlockIdx = idx;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class FieldBitmapWriterBase {
|
||||
protected:
|
||||
T m_map = nullptr;
|
||||
std::size_t m_mapLen = 0;
|
||||
|
||||
public:
|
||||
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept;
|
||||
|
||||
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
|
||||
|
||||
constexpr Result<bool> get(std::size_t i) const noexcept;
|
||||
|
||||
constexpr void setFields(int) noexcept;
|
||||
|
||||
constexpr void setMaxLen(int) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int64_t getMaxLen() const noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept {
|
||||
m_map = map;
|
||||
m_mapLen = maxLen;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept {
|
||||
m_map = map;
|
||||
m_mapLen = maxLen;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
return (m_map[i / 8] >> (i % 8)) & 1;
|
||||
} else {
|
||||
return ox::Error(McPresenceMapOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept {
|
||||
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept {
|
||||
m_mapLen = static_cast<std::size_t>(maxLen);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
|
||||
return static_cast<int64_t>(m_mapLen);
|
||||
}
|
||||
|
||||
extern template class FieldBitmapWriterBase<uint8_t*>;
|
||||
extern template class FieldBitmapWriterBase<const uint8_t*>;
|
||||
|
||||
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> {
|
||||
|
||||
public:
|
||||
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
|
||||
|
||||
constexpr Error set(std::size_t i, bool on) noexcept;
|
||||
|
||||
};
|
||||
|
||||
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
|
||||
FieldBitmapWriterBase<uint8_t*>(map, maxLen) {
|
||||
}
|
||||
|
||||
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
if (on) {
|
||||
m_map[i / 8] |= 1 << (i % 8);
|
||||
} else {
|
||||
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
|
||||
constexpr Error loadMapBlock(size_t const idx) const noexcept {
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||
Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||
// Warning: narrow-conv
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||
m_mapBlock = 0;
|
||||
for (uint64_t i{}; auto b : mapBlock) {
|
||||
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||
i += 8;
|
||||
}
|
||||
m_mapBlockIdx = idx;
|
||||
return {};
|
||||
}
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return {};
|
||||
} else {
|
||||
return ox::Error(McPresenceMapOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FieldBitmapWriter {
|
||||
protected:
|
||||
Span<char> m_map;
|
||||
size_t m_mapLen{};
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmapWriter(Span<char> const &map) noexcept:
|
||||
m_map(map),
|
||||
m_mapLen(m_map.size()) {
|
||||
}
|
||||
|
||||
constexpr auto setBuffer(Span<char> const &map) noexcept {
|
||||
m_map = map;
|
||||
m_mapLen = map.size();
|
||||
}
|
||||
|
||||
constexpr Result<bool> get(size_t const i) const noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
return (std::bit_cast<uint8_t>(m_map[i / 8]) >> (i % 8)) & 1;
|
||||
}
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
|
||||
constexpr Error setFields(int const fields) noexcept {
|
||||
m_mapLen = static_cast<size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
if (m_mapLen > m_map.size()) [[unlikely]] {
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr void setMaxLen(int const maxLen) noexcept {
|
||||
m_mapLen = static_cast<size_t>(maxLen);
|
||||
}
|
||||
|
||||
constexpr int64_t getMaxLen() const noexcept {
|
||||
return static_cast<int64_t>(m_mapLen);
|
||||
}
|
||||
|
||||
constexpr Error set(size_t const i, bool const on) noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
char &actual = m_map[i / 8];
|
||||
uint8_t v = std::bit_cast<uint8_t>(actual);
|
||||
if (on) {
|
||||
v |= 1 << (i % 8);
|
||||
} else {
|
||||
v &= ~static_cast<uint8_t>(1 << (i % 8));
|
||||
}
|
||||
actual = std::bit_cast<char>(v);
|
||||
return {};
|
||||
}
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
281
deps/ox/src/ox/mc/read.hpp
vendored
281
deps/ox/src/ox/mc/read.hpp
vendored
@@ -32,58 +32,58 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
|
||||
|
||||
private:
|
||||
FieldBitmapReader<Reader> m_fieldPresence;
|
||||
std::size_t m_fields = 0;
|
||||
std::size_t m_field = 0;
|
||||
ox::Optional<int> m_unionIdx;
|
||||
size_t m_fields{};
|
||||
size_t m_field{};
|
||||
Optional<int> const m_unionIdx{};
|
||||
Reader &m_reader;
|
||||
|
||||
public:
|
||||
explicit constexpr MetalClawReaderTemplate(
|
||||
Reader &reader,
|
||||
ox::Optional<int> const&unionIdx = {}) noexcept;
|
||||
Optional<int> const &unionIdx = {}) noexcept;
|
||||
|
||||
constexpr ~MetalClawReaderTemplate() noexcept;
|
||||
|
||||
constexpr Error field(const char*, int8_t *val) noexcept;
|
||||
constexpr Error field(const char*, int16_t *val) noexcept;
|
||||
constexpr Error field(const char*, int32_t *val) noexcept;
|
||||
constexpr Error field(const char*, int64_t *val) noexcept;
|
||||
constexpr Error field(CString, int8_t *val) noexcept;
|
||||
constexpr Error field(CString, int16_t *val) noexcept;
|
||||
constexpr Error field(CString, int32_t *val) noexcept;
|
||||
constexpr Error field(CString, int64_t *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, uint8_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint16_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint32_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint64_t *val) noexcept;
|
||||
constexpr Error field(CString, uint8_t *val) noexcept;
|
||||
constexpr Error field(CString, uint16_t *val) noexcept;
|
||||
constexpr Error field(CString, uint32_t *val) noexcept;
|
||||
constexpr Error field(CString, uint64_t *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, bool *val) noexcept;
|
||||
constexpr Error field(CString, bool *val) noexcept;
|
||||
|
||||
// array handler
|
||||
constexpr Error field(const char*, auto *val, std::size_t len) noexcept;
|
||||
constexpr Error field(CString, auto *val, size_t valLen) noexcept;
|
||||
|
||||
// map handler
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
constexpr Error field(CString, HashMap<String, T> *val) noexcept;
|
||||
|
||||
// array handler, with callback to allow handling individual elements
|
||||
template<typename T, typename CB>
|
||||
constexpr Error field(const char*, CB cb) noexcept;
|
||||
constexpr Error field(CString, CB cb) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *val) noexcept;
|
||||
constexpr Error field(CString, T *val) noexcept;
|
||||
|
||||
template<typename U, bool force>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
constexpr Error field(CString, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
template<size_t SmallStringSize>
|
||||
constexpr Error field(CString, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, IString<L> *val) noexcept;
|
||||
template<size_t L>
|
||||
constexpr Error field(CString, IString<L> *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char*, char *val, std::size_t buffLen) noexcept;
|
||||
constexpr Error fieldCString(CString, char *val, size_t buffLen) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char*, char **val) noexcept;
|
||||
constexpr Error fieldCString(CString, char **val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char*, char **val, std::size_t buffLen) noexcept;
|
||||
constexpr Error fieldCString(CString, char **val, size_t buffLen) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
@@ -101,13 +101,13 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
|
||||
const char *name = T::TypeName,
|
||||
int version = T::TypeVersion,
|
||||
const Vector<String>& = {},
|
||||
std::size_t fields = ModelFieldCount_v<T>) noexcept;
|
||||
size_t fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
/**
|
||||
* Returns a MetalClawReader to parse a child object.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr MetalClawReaderTemplate<Reader> child(const char *name, ox::Optional<int> unionIdx = {}) noexcept;
|
||||
constexpr MetalClawReaderTemplate<Reader> child(const char *name, Optional<int> unionIdx = {}) noexcept;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the next field to be read is present.
|
||||
@@ -122,20 +122,20 @@ class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<R
|
||||
constexpr bool fieldPresent(int fieldNo) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int whichFieldPresent(const char *name, const ModelUnion&) const noexcept;
|
||||
constexpr int whichFieldPresent(const char *name, ModelUnion const&) const noexcept;
|
||||
|
||||
constexpr void nextField() noexcept;
|
||||
|
||||
private:
|
||||
template<typename I>
|
||||
constexpr Error readInteger(I *val) noexcept;
|
||||
constexpr Error readInteger(I &val) noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate(
|
||||
Reader &reader,
|
||||
ox::Optional<int> const&unionIdx) noexcept:
|
||||
Optional<int> const &unionIdx) noexcept:
|
||||
m_fieldPresence(reader),
|
||||
m_unionIdx(unionIdx),
|
||||
m_reader(reader) {
|
||||
@@ -149,71 +149,72 @@ constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept {
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int8_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int16_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int32_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, int64_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint8_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint16_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint32_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, uint64_t *val) noexcept {
|
||||
return readInteger(*val);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept {
|
||||
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));
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, bool *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
auto const result = m_fieldPresence.get(static_cast<size_t>(m_field));
|
||||
*val = result.value;
|
||||
OX_RETURN_ERROR(result);
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
// array handler
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(
|
||||
const char *name, auto *val, size_t const valLen) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
|
||||
// read the list
|
||||
if (valLen >= len) {
|
||||
auto reader = child({});
|
||||
auto &handler = *reader.interface();
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
OX_RETURN_ERROR(handler.field({}, &val[i]));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
@@ -230,18 +231,18 @@ OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, HashMap<String, T> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
|
||||
OX_RETURN_ERROR(m_reader.seekg(g));
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
auto &handler = *reader.interface();
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
|
||||
// this loop body needs to be in a lambda because of the potential alloca call
|
||||
constexpr auto loopBody = [](auto &handler, auto &val) {
|
||||
OX_REQUIRE(keyLen, handler.stringLength(nullptr));
|
||||
@@ -250,22 +251,22 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
|
||||
OX_RETURN_ERROR(handler.fieldCString("", &wkeyPtr, keyLen + 1));
|
||||
return handler.field("", &val[wkeyPtr]);
|
||||
};
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
OX_RETURN_ERROR(loopBody(handler, *val));
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept {
|
||||
if constexpr(isVector_v<T>) {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
// set size of val if the field is present, don't worry about it if not
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
OX_REQUIRE(len, arrayLength(name, false));
|
||||
OX_RETURN_ERROR(ox::resizeVector(*val, len));
|
||||
return field(name, val->data(), val->size());
|
||||
@@ -275,9 +276,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
|
||||
++m_field;
|
||||
return {};
|
||||
} else if constexpr(isArray_v<T>) {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
// set size of val if the field is present, don't worry about it if not
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
OX_REQUIRE(len, arrayLength(name, false));
|
||||
if (len > val->size()) {
|
||||
return ox::Error(1, "Input array is too long");
|
||||
@@ -288,8 +289,8 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
|
||||
++m_field;
|
||||
return {};
|
||||
} else {
|
||||
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_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) && val) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
auto reader = child("");
|
||||
OX_RETURN_ERROR(model(reader.interface(), val));
|
||||
}
|
||||
@@ -301,9 +302,9 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename U, bool force>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept {
|
||||
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))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, UnionView<U, force> val) noexcept {
|
||||
if ((!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) && val.get()) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
auto reader = child("", ox::Optional<int>(ox::in_place, val.idx()));
|
||||
OX_RETURN_ERROR(model(reader.interface(), val.get()));
|
||||
}
|
||||
@@ -313,13 +314,13 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U,
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
template<size_t SmallStringSize>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, BasicString<SmallStringSize> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
|
||||
const auto cap = size;
|
||||
*val = BasicString<SmallStringSize>(cap);
|
||||
auto data = val->data();
|
||||
@@ -330,17 +331,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<std::size_t L>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
template<size_t L>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, IString<L> *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
|
||||
*val = IString<L>();
|
||||
OX_RETURN_ERROR(val->resize(size));
|
||||
auto const data = val->data();
|
||||
@@ -355,11 +356,12 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, IString<L> *
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(
|
||||
CString, char *val, size_t const buffLen) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
|
||||
if (size > buffLen) {
|
||||
return ox::Error(McOutputBuffEnded);
|
||||
}
|
||||
@@ -370,15 +372,15 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
|
||||
data[size] = 0;
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(CString, char **val) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
|
||||
// re-allocate in case too small
|
||||
safeDelete(*val);
|
||||
*val = new char[size + 1];
|
||||
@@ -388,16 +390,16 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
|
||||
data[size] = 0;
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(CString, char **val, size_t buffLen) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(size, mc::decodeInteger<StringLength>(m_reader, bytesRead));
|
||||
// re-allocate if too small
|
||||
if (buffLen < size + 1) {
|
||||
safeDelete(*val);
|
||||
@@ -416,17 +418,17 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(CString, bool const pass) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||
OX_REQUIRE(out, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
|
||||
if (!pass) {
|
||||
OX_RETURN_ERROR(m_reader.seekg(g));
|
||||
}
|
||||
@@ -437,12 +439,12 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(CString) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
|
||||
size_t bytesRead = 0;
|
||||
auto len = mc::decodeInteger<StringLength>(m_reader, bytesRead);
|
||||
OX_RETURN_ERROR(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
|
||||
return len;
|
||||
}
|
||||
@@ -452,34 +454,34 @@ constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(con
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename I>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
std::size_t bytesRead = 0;
|
||||
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I &val) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
size_t bytesRead = 0;
|
||||
auto const result = mc::decodeInteger<I>(m_reader, bytesRead);
|
||||
OX_RETURN_ERROR(result);
|
||||
*val = result.value;
|
||||
val = result.value;
|
||||
} else {
|
||||
*val = 0;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename T, typename CB>
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<std::size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
constexpr Error MetalClawReaderTemplate<Reader>::field(CString, CB cb) noexcept {
|
||||
if (!m_unionIdx.has_value() || static_cast<size_t>(*m_unionIdx) == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<size_t>(m_field))) {
|
||||
// read the length
|
||||
std::size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||
size_t bytesRead = 0;
|
||||
OX_REQUIRE(len, mc::decodeInteger<ArrayLength>(m_reader, bytesRead));
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
auto &handler = *reader.interface();
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("List", 0, {}, static_cast<size_t>(len)));
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
T val;
|
||||
OX_RETURN_ERROR(handler.field("", &val));
|
||||
OX_RETURN_ERROR(cb(i, &val));
|
||||
@@ -487,13 +489,13 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
template<typename T>
|
||||
constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
|
||||
const char*, int, const Vector<String>&, std::size_t fields) noexcept {
|
||||
CString, int, const Vector<String>&, size_t const fields) noexcept {
|
||||
m_fields = fields;
|
||||
// Warning: narrow-conv
|
||||
return m_reader.seekg(
|
||||
@@ -503,24 +505,24 @@ constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(
|
||||
const char*,
|
||||
ox::Optional<int> unionIdx) noexcept {
|
||||
CString,
|
||||
Optional<int> const unionIdx) noexcept {
|
||||
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx);
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(const char*) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
||||
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(CString) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<size_t>(m_field)).value;
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int fieldNo) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
||||
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int const fieldNo) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<size_t>(fieldNo)).value;
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
[[nodiscard]]
|
||||
constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
||||
constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(CString, ModelUnion const &u) const noexcept {
|
||||
FieldBitmapReader<Reader> p(m_reader);
|
||||
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
||||
if (p.get(i)) {
|
||||
@@ -538,11 +540,10 @@ constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
|
||||
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
|
||||
|
||||
template<typename T>
|
||||
Error readMC(ox::BufferView buff, T &val) noexcept {
|
||||
Error readMC(ox::BufferView const buff, T &val) noexcept {
|
||||
BufferReader br(buff);
|
||||
MetalClawReader reader(br);
|
||||
ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader);
|
||||
return model(&handler, &val);
|
||||
return model(reader.interface(), &val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
3
deps/ox/src/ox/mc/test/tests.cpp
vendored
3
deps/ox/src/ox/mc/test/tests.cpp
vendored
@@ -157,8 +157,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
||||
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
|
||||
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
||||
oxDebugf("{}", testOut.IString.len());
|
||||
oxExpect(testIn.IString, testOut.IString);
|
||||
ox::expect(testIn.IString, testOut.IString);
|
||||
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||
|
||||
261
deps/ox/src/ox/mc/write.hpp
vendored
261
deps/ox/src/ox/mc/write.hpp
vendored
@@ -29,71 +29,71 @@
|
||||
namespace ox {
|
||||
|
||||
template<Writer_c Writer>
|
||||
class MetalClawWriter {
|
||||
class MetalClawWriter: public ModelHandlerBase<MetalClawWriter<Writer>, OpType::Write> {
|
||||
|
||||
private:
|
||||
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
|
||||
FieldBitmap m_fieldPresence;
|
||||
int m_field = 0;
|
||||
ox::Optional<int> m_unionIdx;
|
||||
std::size_t m_writerBeginP{};
|
||||
Vector<char, 16> m_presenceMapBuff{};
|
||||
FieldBitmapWriter m_fieldPresence{m_presenceMapBuff};
|
||||
int m_field{};
|
||||
Optional<int> m_unionIdx;
|
||||
size_t m_writerBeginP{};
|
||||
Writer &m_writer;
|
||||
|
||||
public:
|
||||
constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept;
|
||||
constexpr explicit MetalClawWriter(Writer &writer, Optional<int> const &unionIdx = {}) noexcept;
|
||||
|
||||
constexpr ~MetalClawWriter() noexcept = default;
|
||||
|
||||
constexpr Error field(const char*, const int8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int64_t *val) noexcept;
|
||||
constexpr Error field(CString, int8_t const *val) noexcept;
|
||||
constexpr Error field(CString, int16_t const *val) noexcept;
|
||||
constexpr Error field(CString, int32_t const *val) noexcept;
|
||||
constexpr Error field(CString, int64_t const *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, const uint8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint64_t *val) noexcept;
|
||||
constexpr Error field(CString, uint8_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint16_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint32_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint64_t const *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, const bool *val) noexcept;
|
||||
constexpr Error field(CString, bool const *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
constexpr Error field(CString, T const *val, size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
||||
constexpr Error field(CString name, HashMap<String, T> const *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
||||
template<size_t SmallStringSize>
|
||||
constexpr Error field(CString, BasicString<SmallStringSize> const *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, const IString<L> *val) noexcept;
|
||||
template<size_t L>
|
||||
constexpr Error field(CString, IString<L> const *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
|
||||
constexpr Error fieldCString(CString name, CString const*val, size_t buffLen) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept;
|
||||
constexpr Error fieldCString(CString name, CString *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *const*val) noexcept;
|
||||
constexpr Error fieldCString(CString name, CString const*val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
||||
constexpr Error fieldCString(CString name, CString val, size_t strLen) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, const T *val) noexcept;
|
||||
constexpr Error field(CString, T const *val) noexcept;
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
constexpr Error field(CString, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
const char *name = T::TypeName,
|
||||
constexpr Error setTypeInfo(
|
||||
CString name = T::TypeName,
|
||||
int version = T::TypeVersion,
|
||||
const Vector<String>& = {},
|
||||
std::size_t fields = ModelFieldCount_v<T>) noexcept;
|
||||
Vector<String> const& = {},
|
||||
size_t fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
/**
|
||||
* stringLength is not implemented in MetalClawWriter
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto stringLength(const char*) noexcept {
|
||||
constexpr auto stringLength(CString) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -101,28 +101,23 @@ class MetalClawWriter {
|
||||
* stringLength is not implemented in MetalClawWriter
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto arrayLength(const char*, bool = true) noexcept {
|
||||
constexpr auto arrayLength(CString, bool = true) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Write;
|
||||
}
|
||||
|
||||
ox::Error finalize() noexcept;
|
||||
constexpr Error finalize() noexcept;
|
||||
|
||||
private:
|
||||
constexpr Error appendInteger(Integer_c auto val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
auto mi = mc::encodeInteger(val);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length));
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(mi.data.data()), mi.length));
|
||||
fieldSet = true;
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
@@ -131,144 +126,147 @@ extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
|
||||
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept:
|
||||
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
|
||||
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept:
|
||||
m_unionIdx(unionIdx),
|
||||
m_writerBeginP(writer.tellp()),
|
||||
m_writer(writer) {
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int8_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int16_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int32_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int64_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint8_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint16_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint32_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint64_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, bool const *val) noexcept {
|
||||
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), *val));
|
||||
}
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
|
||||
template<size_t SmallStringSize>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, BasicString<SmallStringSize> const *val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto strLen = mc::encodeInteger(val->len());
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
|
||||
auto const strLen = mc::encodeInteger(val->size());
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLen.data.data()), strLen.length));
|
||||
// write the string
|
||||
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
|
||||
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<size_t>(val->size())));
|
||||
fieldSet = true;
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<std::size_t L>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->len());
|
||||
template<size_t L>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString name, IString<L> const *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->size());
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const *val, size_t) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
|
||||
const auto strLen = *val ? ox::strlen(*val) : 0;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
// this strlen is tolerated because sometimes 0 gets passed to
|
||||
// the size param, which is a lie
|
||||
// this code should be cleaned up at some point...
|
||||
auto const strLen = *val ? ox::strlen(*val) : 0;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
// write the length
|
||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
|
||||
auto const strLenBuff = mc::encodeInteger(strLen);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
|
||||
// write the string
|
||||
OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen)));
|
||||
OX_RETURN_ERROR(m_writer.write(*val, static_cast<size_t>(strLen)));
|
||||
fieldSet = true;
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString *val) noexcept {
|
||||
return fieldCString(name, val, {});
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString const *val) noexcept {
|
||||
return fieldCString(name, val, {});
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const val, size_t const strLen) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length));
|
||||
auto const strLenBuff = mc::encodeInteger(strLen);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
|
||||
// write the string
|
||||
OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen)));
|
||||
OX_RETURN_ERROR(m_writer.write(val, static_cast<size_t>(strLen)));
|
||||
fieldSet = true;
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, T const *val) noexcept {
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(nullptr, val->data(), val->size());
|
||||
} else {
|
||||
bool fieldSet = false;
|
||||
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
|
||||
OX_RETURN_ERROR(model(&handler, val));
|
||||
MetalClawWriter writer(m_writer);
|
||||
OX_RETURN_ERROR(model(writer.interface(), val));
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = writeIdx != m_writer.tellp();
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return {};
|
||||
}
|
||||
@@ -276,65 +274,62 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename U, bool force>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, UnionView<U, force> val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx()));
|
||||
ModelHandlerInterface handler{&writer};
|
||||
OX_RETURN_ERROR(model(&handler, val.get()));
|
||||
MetalClawWriter writer(m_writer, Optional<int>(in_place, val.idx()));
|
||||
OX_RETURN_ERROR(model(writer.interface(), val.get()));
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = writeIdx != m_writer.tellp();
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, T const *val, size_t const len) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
|
||||
auto const arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)));
|
||||
MetalClawWriter writer(m_writer);
|
||||
OX_RETURN_ERROR(writer.interface()->template setTypeInfo<T>("List", 0, {}, static_cast<size_t>(len)));
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
for (size_t i{}; i < len; ++i) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
OX_RETURN_ERROR(handler.field("", &val[i]));
|
||||
OX_RETURN_ERROR(writer.interface()->field("", &val[i]));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = writeIdx != m_writer.tellp();
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept {
|
||||
const auto &keys = val->keys();
|
||||
const auto len = keys.size();
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, HashMap<String, T> const *val) noexcept {
|
||||
auto const &keys = val->keys();
|
||||
auto const len = keys.size();
|
||||
bool fieldSet = false;
|
||||
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length));
|
||||
auto const arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
|
||||
// write map
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
MetalClawWriter writer(m_writer);
|
||||
// double len for both key and value
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
|
||||
OX_RETURN_ERROR(writer.interface()->setTypeInfo("Map", 0, {}, len * 2));
|
||||
// this loop body needs to be in a lambda because of the potential alloca call
|
||||
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
|
||||
const auto keyLen = key.len();
|
||||
constexpr auto loopBody = [](auto &handler, auto const &key, auto const &val) -> Error {
|
||||
auto const keyLen = key.size();
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
memcpy(wkey.get(), key.c_str(), keyLen + 1);
|
||||
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
|
||||
@@ -342,53 +337,51 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
||||
return handler.field("", value);
|
||||
};
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
auto const&key = keys[i];
|
||||
OX_RETURN_ERROR(loopBody(handler, key, *val));
|
||||
for (size_t i{}; i < len; ++i) {
|
||||
auto const &key = keys[i];
|
||||
OX_RETURN_ERROR(loopBody(*writer.interface(), key, *val));
|
||||
}
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = true;
|
||||
}
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
|
||||
const char*,
|
||||
constexpr Error MetalClawWriter<Writer>::setTypeInfo(
|
||||
CString,
|
||||
int,
|
||||
const Vector<String>&,
|
||||
std::size_t fields) noexcept {
|
||||
const auto fieldPresenceLen = (fields - 1) / 8 + 1;
|
||||
Vector<String> const&,
|
||||
size_t const fields) noexcept {
|
||||
auto const fieldPresenceLen = (fields - 1) / 8 + 1;
|
||||
OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
|
||||
m_presenceMapBuff.resize(fieldPresenceLen);
|
||||
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
|
||||
m_fieldPresence.setFields(static_cast<int>(fields));
|
||||
return {};
|
||||
m_fieldPresence.setBuffer(m_presenceMapBuff);
|
||||
return m_fieldPresence.setFields(static_cast<int>(fields));
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
ox::Error MetalClawWriter<Writer>::finalize() noexcept {
|
||||
const auto end = m_writer.tellp();
|
||||
constexpr Error MetalClawWriter<Writer>::finalize() noexcept {
|
||||
auto const end = m_writer.tellp();
|
||||
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
|
||||
OX_RETURN_ERROR(m_writer.write(
|
||||
reinterpret_cast<const char*>(m_presenceMapBuff.data()),
|
||||
m_presenceMapBuff.size()));
|
||||
m_presenceMapBuff.data(),
|
||||
m_presenceMapBuff.size()));
|
||||
OX_RETURN_ERROR(m_writer.seekp(end));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
|
||||
Result<Buffer> writeMC(Writer_c auto &writer, auto const &val) noexcept {
|
||||
MetalClawWriter mcWriter(writer);
|
||||
ModelHandlerInterface handler{&mcWriter};
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
OX_RETURN_ERROR(model(mcWriter.interface(), &val));
|
||||
OX_RETURN_ERROR(mcWriter.finalize());
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||
Result<Buffer> writeMC(auto const &val, size_t const buffReserveSz = 2 * units::KB) noexcept {
|
||||
Buffer buff(buffReserveSz);
|
||||
BufferWriter bw(&buff, 0);
|
||||
OX_RETURN_ERROR(writeMC(bw, val));
|
||||
@@ -396,7 +389,7 @@ Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB
|
||||
return buff;
|
||||
}
|
||||
|
||||
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
Error writeMC(char *buff, size_t const buffLen, auto const &val, size_t *sizeOut = nullptr) noexcept {
|
||||
CharBuffWriter bw{{buff, buffLen}};
|
||||
OX_RETURN_ERROR(writeMC(bw, val));
|
||||
if (sizeOut) {
|
||||
|
||||
2
deps/ox/src/ox/model/def.hpp
vendored
2
deps/ox/src/ox/model/def.hpp
vendored
@@ -13,7 +13,7 @@
|
||||
// oxModelFwdDecl is necessary because Apple-Clang is broken...
|
||||
#define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
|
||||
#define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>());
|
||||
#define OX_MODEL_END() return ox::Error(0); }
|
||||
#define OX_MODEL_END() return {}; }
|
||||
#define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
|
||||
#define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
|
||||
#define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
|
||||
|
||||
4
deps/ox/src/ox/model/desctypes.hpp
vendored
4
deps/ox/src/ox/model/desctypes.hpp
vendored
@@ -43,7 +43,7 @@ static constexpr auto buildTypeId(
|
||||
for (const auto &p : typeParams) {
|
||||
tp += p + ",";
|
||||
}
|
||||
tp.resize(tp.len() - 1);
|
||||
tp.resize(tp.size() - 1);
|
||||
tp += "#";
|
||||
}
|
||||
return ox::sfmt("{}{};{}", name, tp, version);
|
||||
@@ -244,7 +244,7 @@ constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto
|
||||
// defaultValue is unused now, but placeholder for backwards compatibility
|
||||
int defaultValue = 0;
|
||||
oxReturnError(io->field("defaultValue", &defaultValue));
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
14
deps/ox/src/ox/model/descwrite.hpp
vendored
14
deps/ox/src/ox/model/descwrite.hpp
vendored
@@ -187,7 +187,7 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
|
||||
PrimitiveType pt;
|
||||
if constexpr(is_union_v<T>) {
|
||||
pt = PrimitiveType::Union;
|
||||
} else if constexpr(isBasicString_v<T> || isBString_v<T>) {
|
||||
} else if constexpr(isBasicString_v<T> || isIString_v<T>) {
|
||||
pt = PrimitiveType::String;
|
||||
} else {
|
||||
pt = PrimitiveType::Struct;
|
||||
@@ -205,7 +205,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t,
|
||||
const auto t = type(p);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
return ox::Error(1);
|
||||
}
|
||||
@@ -220,7 +220,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t)
|
||||
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 {};
|
||||
}
|
||||
return ox::Error(1);
|
||||
}
|
||||
@@ -231,7 +231,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
return ox::Error(1);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept
|
||||
template<std::size_t sz>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::BString, 0, PT, 0);
|
||||
return getType(types::IString, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b,
|
||||
@@ -380,7 +380,7 @@ constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typ
|
||||
template<typename T>
|
||||
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
|
||||
TypeDescWriter writer(&typeStore);
|
||||
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
|
||||
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(writer);
|
||||
if (std::is_constant_evaluated()) {
|
||||
std::allocator<T> a;
|
||||
T *t = a.allocate(1);
|
||||
@@ -396,7 +396,7 @@ constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
|
||||
template<typename T>
|
||||
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
|
||||
TypeDescWriter writer(&typeStore);
|
||||
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
|
||||
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(writer);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
return writer.definition();
|
||||
}
|
||||
|
||||
8
deps/ox/src/ox/model/fieldcounter.hpp
vendored
8
deps/ox/src/ox/model/fieldcounter.hpp
vendored
@@ -31,25 +31,25 @@ class FieldCounter {
|
||||
template<typename U>
|
||||
constexpr ox::Error field(StringViewCR, U) noexcept {
|
||||
++fields;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
|
||||
++fields;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, typename Handler>
|
||||
constexpr Error field(StringViewCR, Handler) {
|
||||
++fields;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(Args&&...) noexcept {
|
||||
++fields;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr auto opType() noexcept {
|
||||
|
||||
142
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
142
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
@@ -17,176 +17,177 @@ namespace ox {
|
||||
template<typename Handler, OpType opType_v = Handler::opType()>
|
||||
class ModelHandlerInterface {
|
||||
private:
|
||||
Handler *m_handler = nullptr;
|
||||
Handler &m_handler;
|
||||
|
||||
public:
|
||||
constexpr explicit ModelHandlerInterface(Handler *handler) noexcept: m_handler(handler) {
|
||||
constexpr explicit ModelHandlerInterface(Handler &handler) noexcept: m_handler(handler) {
|
||||
}
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
const char* name = T::TypeName,
|
||||
CString name = T::TypeName,
|
||||
int version = T::TypeVersion,
|
||||
const Vector<String>& typeParams = {}) noexcept {
|
||||
return m_handler->template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>);
|
||||
Vector<String> const &typeParams = {}) noexcept {
|
||||
return m_handler.template setTypeInfo<T>(name, version, typeParams, ModelFieldCount_v<T>);
|
||||
}
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
const char *name,
|
||||
CString name,
|
||||
int version,
|
||||
const Vector<String>& typeParams,
|
||||
std::size_t fields) noexcept {
|
||||
return m_handler->template setTypeInfo<T>(name, version, typeParams, fields);
|
||||
Vector<String> const &typeParams,
|
||||
size_t fields) noexcept {
|
||||
return m_handler.template setTypeInfo<T>(name, version, typeParams, fields);
|
||||
}
|
||||
|
||||
template<std::size_t len>
|
||||
constexpr Error fieldCString(const char *name, char val[len]) noexcept {
|
||||
return m_handler->fieldCString(name, &val[0], len);
|
||||
template<size_t len>
|
||||
constexpr Error fieldCString(CString name, char val[len]) noexcept {
|
||||
return m_handler.fieldCString(name, &val[0], len);
|
||||
}
|
||||
|
||||
template<std::size_t len>
|
||||
constexpr Error fieldCString(const char *name, const char val[len]) noexcept requires(opType_v != OpType::Read) {
|
||||
template<size_t len>
|
||||
constexpr Error fieldCString(CString name, char const val[len]) noexcept requires(opType_v != OpType::Read) {
|
||||
if constexpr(opType_v != OpType::Read) {
|
||||
return m_handler->fieldCString(name, &val[0], len);
|
||||
return m_handler.fieldCString(name, &val[0], len);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
||||
return m_handler->fieldCString(name, val);
|
||||
constexpr Error fieldCString(CString name, char **val) noexcept {
|
||||
return m_handler.fieldCString(name, val);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *const*val) noexcept requires(opType_v != OpType::Read) {
|
||||
constexpr Error fieldCString(CString name, char const *const*val) noexcept requires(opType_v != OpType::Read) {
|
||||
// this check looks pointless, but it's to address a Clang bug
|
||||
if constexpr(opType_v != OpType::Read) {
|
||||
return m_handler->fieldCString(name, val);
|
||||
return m_handler.fieldCString(name, val);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept requires(opType_v != OpType::Read) {
|
||||
constexpr Error fieldCString(CString name, char const **val) noexcept requires(opType_v != OpType::Read) {
|
||||
// this check looks pointless, but it's to address a Clang bug
|
||||
if constexpr(opType_v != OpType::Read) {
|
||||
return m_handler->fieldCString(name, val);
|
||||
return m_handler.fieldCString(name, val);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
constexpr Error fieldCString(CString name, char **val, size_t buffLen) noexcept {
|
||||
return m_handler.fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept requires(opType_v != OpType::Read) {
|
||||
constexpr Error fieldCString(CString name, char const **val, size_t buffLen) noexcept requires(opType_v != OpType::Read) {
|
||||
// this check looks pointless, but it's to address a Clang bug
|
||||
if constexpr(opType_v != OpType::Read) {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
return m_handler.fieldCString(name, val, buffLen);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
constexpr Error fieldCString(CString name, char *val, size_t buffLen) noexcept {
|
||||
return m_handler.fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldModelValue(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept {
|
||||
constexpr Error fieldModelValue(char const *name, CommonPtrWith<ModelValue> auto *v) noexcept {
|
||||
switch (v->type()) {
|
||||
case ModelValue::Type::Undefined:
|
||||
break;
|
||||
case ModelValue::Type::Bool:
|
||||
return m_handler->field(name, &v->template get<bool>());
|
||||
return m_handler.field(name, &v->template get<bool>());
|
||||
case ModelValue::Type::UnsignedInteger8:
|
||||
return m_handler->field(name, &v->template get<uint8_t>());
|
||||
return m_handler.field(name, &v->template get<uint8_t>());
|
||||
case ModelValue::Type::UnsignedInteger16:
|
||||
return m_handler->field(name, &v->template get<uint16_t>());
|
||||
return m_handler.field(name, &v->template get<uint16_t>());
|
||||
case ModelValue::Type::UnsignedInteger32:
|
||||
return m_handler->field(name, &v->template get<uint32_t>());
|
||||
return m_handler.field(name, &v->template get<uint32_t>());
|
||||
case ModelValue::Type::UnsignedInteger64:
|
||||
return m_handler->field(name, &v->template get<uint64_t>());
|
||||
return m_handler.field(name, &v->template get<uint64_t>());
|
||||
case ModelValue::Type::SignedInteger8:
|
||||
return m_handler->field(name, &v->template get<int8_t>());
|
||||
return m_handler.field(name, &v->template get<int8_t>());
|
||||
case ModelValue::Type::SignedInteger16:
|
||||
return m_handler->field(name, &v->template get<int16_t>());
|
||||
return m_handler.field(name, &v->template get<int16_t>());
|
||||
case ModelValue::Type::SignedInteger32:
|
||||
return m_handler->field(name, &v->template get<int32_t>());
|
||||
return m_handler.field(name, &v->template get<int32_t>());
|
||||
case ModelValue::Type::SignedInteger64:
|
||||
return m_handler->field(name, &v->template get<int64_t>());
|
||||
return m_handler.field(name, &v->template get<int64_t>());
|
||||
case ModelValue::Type::String:
|
||||
return m_handler->field(name, &v->template get<String>());
|
||||
return m_handler.field(name, &v->template get<String>());
|
||||
case ModelValue::Type::Object:
|
||||
return m_handler->field(name, &v->template get<ModelObject>());
|
||||
return m_handler.field(name, &v->template get<ModelObject>());
|
||||
case ModelValue::Type::Union:
|
||||
{
|
||||
auto &u = v->template get<ModelUnion>();
|
||||
if constexpr(opType_v == OpType::Read) {
|
||||
u.setActiveField(m_handler->whichFieldPresent(name, u));
|
||||
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
|
||||
u.setActiveField(whichFieldPresent(m_handler, name, u));
|
||||
return m_handler.field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
|
||||
} else {
|
||||
return m_handler->field(name, UnionView<const ModelUnion, true>(&u, u.unionIdx()));
|
||||
return m_handler.field(name, UnionView<ModelUnion const, true>(&u, u.unionIdx()));
|
||||
}
|
||||
}
|
||||
case ModelValue::Type::Vector:
|
||||
return m_handler->field(name, &v->template get<ModelValueVector>());
|
||||
return m_handler.field(name, &v->template get<ModelValueVector>());
|
||||
case ModelValue::Type::InlineArray:
|
||||
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()));
|
||||
oxPanic(ox::Error(1), "invalid type");
|
||||
ox::panic("invalid type");
|
||||
return ox::Error(1, "invalid type");
|
||||
}
|
||||
|
||||
// array handler, with callback to allow handling individual elements
|
||||
template<typename T, typename Callback>
|
||||
constexpr Error field(const char *name, Callback cb) noexcept {
|
||||
return m_handler->template field<T, Callback>(name, cb);
|
||||
constexpr Error field(CString name, Callback cb) noexcept {
|
||||
return m_handler.template field<T, Callback>(name, cb);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const T *v) noexcept {
|
||||
constexpr Error field(CString name, const T *v) noexcept {
|
||||
if constexpr(ox::is_same_v<T, ModelValue>) {
|
||||
return fieldModelValue(name, v);
|
||||
} else {
|
||||
return m_handler->field(name, v);
|
||||
return m_handler.field(name, v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T *v) noexcept {
|
||||
constexpr Error field(CString name, T *v) noexcept {
|
||||
if constexpr(ox::is_same_v<T, ModelValue>) {
|
||||
return fieldModelValue(name, v);
|
||||
} else {
|
||||
return m_handler->field(name, v);
|
||||
return m_handler.field(name, v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char *name, UnionView<U, force> val) noexcept {
|
||||
return m_handler->field(name, val);
|
||||
constexpr Error field(CString name, UnionView<U, force> val) noexcept {
|
||||
return m_handler.field(name, val);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, auto *val, std::size_t len) noexcept {
|
||||
return m_handler->field(name, val, len);
|
||||
constexpr Error field(CString name, auto *val, size_t len) noexcept {
|
||||
return m_handler.field(name, val, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param name
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto arrayLength(const char *name, bool pass = true) noexcept {
|
||||
return m_handler->arrayLength(name, pass);
|
||||
constexpr auto arrayLength(CString name, bool pass = true) noexcept {
|
||||
return m_handler.arrayLength(name, pass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an string length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto stringLength(const char *name) noexcept {
|
||||
return m_handler->stringLength(name);
|
||||
constexpr auto stringLength(CString name) noexcept {
|
||||
return m_handler.stringLength(name);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -198,22 +199,33 @@ class ModelHandlerInterface {
|
||||
constexpr auto handler() noexcept {
|
||||
return m_handler;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename H>
|
||||
static constexpr int whichFieldPresent(H &h, CString name, ModelUnion const &u) noexcept
|
||||
requires(H::opType() == OpType::Read) {
|
||||
return h.whichFieldPresent(name, u);
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
static constexpr int whichFieldPresent(H&, CString, ModelUnion const&) noexcept
|
||||
requires(H::opType() != OpType::Read) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename Handler, ox::OpType opType_v = Handler::opType()>
|
||||
template<typename Handler, OpType opType_v = Handler::opType()>
|
||||
class ModelHandlerBase {
|
||||
private:
|
||||
ModelHandlerInterface<Handler, opType_v> m_interface;
|
||||
ModelHandlerInterface<Handler, opType_v> m_interface{*static_cast<Handler*>(this)};
|
||||
public:
|
||||
constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
constexpr ModelHandlerBase(ModelHandlerBase&&) noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
[[nodiscard]]
|
||||
constexpr auto interface() noexcept {
|
||||
return &m_interface;
|
||||
}
|
||||
[[nodiscard]]
|
||||
static constexpr ox::OpType opType() noexcept {
|
||||
static constexpr OpType opType() noexcept {
|
||||
return opType_v;
|
||||
}
|
||||
};
|
||||
|
||||
24
deps/ox/src/ox/model/modelops.hpp
vendored
24
deps/ox/src/ox/model/modelops.hpp
vendored
@@ -56,19 +56,19 @@ class MemberList {
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *v) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(v);
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *v, int) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(v);
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(u.get());
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -107,7 +107,7 @@ class Copier {
|
||||
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
|
||||
dst = src;
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ class Copier {
|
||||
dst = src;
|
||||
}
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
@@ -128,7 +128,7 @@ class Copier {
|
||||
auto &src = *u.get();
|
||||
dst = src;
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
@@ -168,7 +168,7 @@ class Mover {
|
||||
dst = std::move(src);
|
||||
src = FT{};
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class Mover {
|
||||
src = FT{};
|
||||
}
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
@@ -190,7 +190,7 @@ class Mover {
|
||||
auto &src = *u.get();
|
||||
dst = std::move(src);
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
@@ -228,7 +228,7 @@ class Equals {
|
||||
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
|
||||
++m_i;
|
||||
if (dst == src) {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
this->value = false;
|
||||
return ox::Error(1);
|
||||
@@ -246,7 +246,7 @@ class Equals {
|
||||
}
|
||||
}
|
||||
++m_i;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
@@ -255,7 +255,7 @@ class Equals {
|
||||
const auto &src = *u.get();
|
||||
++m_i;
|
||||
if (dst == src) {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
} else {
|
||||
this->value = false;
|
||||
return ox::Error(1);
|
||||
|
||||
13
deps/ox/src/ox/model/modelvalue.cpp
vendored
13
deps/ox/src/ox/model/modelvalue.cpp
vendored
@@ -6,18 +6,23 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/hashmap.hpp>
|
||||
|
||||
#include "modelvalue.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
static_assert([]() -> ox::Error {
|
||||
ox::ModelValue v;
|
||||
static_assert([]() -> Error {
|
||||
ModelValue v;
|
||||
OX_RETURN_ERROR(v.setType<int32_t>());
|
||||
if (v.type() != ModelValue::Type::SignedInteger32) {
|
||||
return ox::Error(1, "type is wrong");
|
||||
return Error(1, "type is wrong");
|
||||
}
|
||||
//oxReturnError(v.set<int32_t>(5));
|
||||
return {};
|
||||
}() == ox::Error(0));
|
||||
}() == Error{});
|
||||
|
||||
// a dummy function to prevent linker errors in a library that has no other symbols
|
||||
void modelDummyFunc() noexcept {}
|
||||
|
||||
}
|
||||
|
||||
46
deps/ox/src/ox/model/modelvalue.hpp
vendored
46
deps/ox/src/ox/model/modelvalue.hpp
vendored
@@ -100,7 +100,7 @@ class ModelValue {
|
||||
return Type::Union;
|
||||
} else if constexpr(is_same_v<U, ModelObject>) {
|
||||
return Type::Object;
|
||||
} else if constexpr(isBasicString_v<U> || isBString_v<U>) {
|
||||
} else if constexpr(isBasicString_v<U> || isIString_v<U>) {
|
||||
return Type::String;
|
||||
} else if constexpr(is_same_v<U, ModelValueVector>) {
|
||||
return Type::Vector;
|
||||
@@ -168,7 +168,7 @@ class ModelValue {
|
||||
constexpr const auto &get() const noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
oxPanic(ox::Error(1), "invalid cast");
|
||||
ox::panic("invalid cast");
|
||||
}
|
||||
return getValue<type>(*this);
|
||||
}
|
||||
@@ -178,7 +178,7 @@ class ModelValue {
|
||||
constexpr auto &get() noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
oxPanic(ox::Error(1), "invalid cast");
|
||||
ox::panic("invalid cast");
|
||||
}
|
||||
return getValue<type>(*this);
|
||||
}
|
||||
@@ -187,7 +187,7 @@ class ModelValue {
|
||||
constexpr Type type() const noexcept;
|
||||
|
||||
constexpr Error setType(
|
||||
DescriptorType const*type,
|
||||
DescriptorType const *type,
|
||||
SubscriptStack const& = {},
|
||||
int subscriptLevels = 0) noexcept;
|
||||
|
||||
@@ -200,8 +200,6 @@ class ModelValue {
|
||||
template<typename T>
|
||||
constexpr Error set(T &&v) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(const ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &&val) noexcept;
|
||||
@@ -275,7 +273,7 @@ class ModelValueArray {
|
||||
}
|
||||
|
||||
constexpr Error setType(
|
||||
DescriptorType const*type,
|
||||
DescriptorType const *type,
|
||||
SubscriptStack subscriptStack,
|
||||
int subscriptLevels) noexcept {
|
||||
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
|
||||
@@ -418,7 +416,7 @@ class ModelValueVector {
|
||||
}
|
||||
|
||||
constexpr Error setType(
|
||||
DescriptorType const*type,
|
||||
DescriptorType const *type,
|
||||
SubscriptStack subscriptStack,
|
||||
int subscriptLevels) noexcept {
|
||||
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
|
||||
@@ -821,7 +819,7 @@ class ModelUnion {
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(ModelValueArray const*v) noexcept {
|
||||
constexpr std::size_t sizeOf(ModelValueArray const *v) noexcept {
|
||||
return sizeOf<PlatSpec>(&(*v)[0]) * v->size();
|
||||
}
|
||||
|
||||
@@ -972,7 +970,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
@@ -981,7 +979,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
|
||||
@@ -997,7 +995,7 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
m_data = other.m_data;
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = new String(other.get<String>());
|
||||
@@ -1030,8 +1028,8 @@ constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
ox::memset(&other.m_data, 0, sizeof(m_data));
|
||||
m_data = other.m_data;
|
||||
other.m_data.ui64 = 0;
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = other.m_data.str;
|
||||
@@ -1098,7 +1096,7 @@ constexpr Error ModelValue::setType(
|
||||
} else if (type->typeName == types::Bool) {
|
||||
m_type = Type::Bool;
|
||||
} else if (type->typeName == types::BasicString ||
|
||||
type->typeName == types::BString ||
|
||||
type->typeName == types::IString ||
|
||||
type->typeName == types::String) {
|
||||
m_type = Type::String;
|
||||
m_data.str = new String;
|
||||
@@ -1129,7 +1127,7 @@ constexpr Error ModelValue::setType(
|
||||
OX_RETURN_ERROR(m_data.uni->setType(type));
|
||||
}
|
||||
oxAssert(m_type != Type::Undefined, "No type set");
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -1176,7 +1174,7 @@ template<typename T>
|
||||
constexpr Error ModelValue::set(const T &v) noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
return ox::Error(1, "type mismatch");
|
||||
return Error(1, "type mismatch");
|
||||
}
|
||||
auto &value = getValue<type>(*this);
|
||||
if constexpr(type == Type::Vector || type == Type::Object ||
|
||||
@@ -1184,7 +1182,7 @@ constexpr Error ModelValue::set(const T &v) noexcept {
|
||||
safeDelete(&value);
|
||||
}
|
||||
value = v;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -1199,11 +1197,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
|
||||
safeDelete(&value);
|
||||
}
|
||||
value = std::move(v);
|
||||
return ox::Error(0);
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {
|
||||
return this->operator=(const_cast<const ModelValue&>(other));
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
|
||||
@@ -1223,7 +1217,7 @@ constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
m_data = other.m_data;
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = new String(other.get<String>());
|
||||
@@ -1261,8 +1255,8 @@ constexpr ModelValue &ModelValue::operator=(ModelValue &&other) noexcept {
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
ox::memset(&other.m_data, 0, sizeof(m_data));
|
||||
m_data = other.m_data;
|
||||
other.m_data = {};
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = other.m_data.str;
|
||||
|
||||
16
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
16
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
@@ -38,17 +38,17 @@ struct TypeNameCatcher {
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T*, std::size_t) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(Args&&...) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr auto opType() noexcept {
|
||||
@@ -77,17 +77,17 @@ struct TypeInfoCatcher {
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T*, std::size_t) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error fieldCString(const char*, T) noexcept {
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr auto opType() noexcept {
|
||||
@@ -144,7 +144,7 @@ template<typename T, typename Str = const char*>
|
||||
[[nodiscard]]
|
||||
consteval auto requireModelTypeName() noexcept {
|
||||
constexpr auto name = getModelTypeName<T, Str>();
|
||||
static_assert(ox::StringView{name}.len(), "Type lacks required TypeName");
|
||||
static_assert(ox::StringView{name}.size(), "Type lacks required TypeName");
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ constexpr auto ModelTypeId_v = [] {
|
||||
constexpr auto name = ModelTypeName_v<T, ox::StringView>;
|
||||
constexpr auto version = ModelTypeVersion_v<T>;
|
||||
constexpr auto versionStr = ox::sfmt<ox::IString<19>>("{}", version);
|
||||
return ox::sfmt<ox::IString<name.len() + versionStr.len() + 1>>("{};{}", name, versionStr);
|
||||
return ox::sfmt<ox::IString<name.size() + versionStr.size() + 1>>("{};{}", name, versionStr);
|
||||
}();
|
||||
|
||||
}
|
||||
|
||||
34
deps/ox/src/ox/model/types.hpp
vendored
34
deps/ox/src/ox/model/types.hpp
vendored
@@ -31,18 +31,18 @@
|
||||
namespace ox {
|
||||
|
||||
namespace types {
|
||||
constexpr StringView BasicString = "net.drinkingtea.ox.BasicString";
|
||||
constexpr StringView BString = "net.drinkingtea.ox.BString";
|
||||
constexpr StringView String = "B.string";
|
||||
constexpr StringView Bool = "B.bool";
|
||||
constexpr StringView Uint8 = "B.uint8";
|
||||
constexpr StringView Uint16 = "B.uint16";
|
||||
constexpr StringView Uint32 = "B.uint32";
|
||||
constexpr StringView Uint64 = "B.uint64";
|
||||
constexpr StringView Int8 = "B.int8";
|
||||
constexpr StringView Int16 = "B.int16";
|
||||
constexpr StringView Int32 = "B.int32";
|
||||
constexpr StringView Int64 = "B.int64";
|
||||
constexpr StringLiteral BasicString = "net.drinkingtea.ox.BasicString";
|
||||
constexpr StringLiteral IString = "net.drinkingtea.ox.IString";
|
||||
constexpr StringLiteral String = "B.string";
|
||||
constexpr StringLiteral Bool = "B.bool";
|
||||
constexpr StringLiteral Uint8 = "B.uint8";
|
||||
constexpr StringLiteral Uint16 = "B.uint16";
|
||||
constexpr StringLiteral Uint32 = "B.uint32";
|
||||
constexpr StringLiteral Uint64 = "B.uint64";
|
||||
constexpr StringLiteral Int8 = "B.int8";
|
||||
constexpr StringLiteral Int16 = "B.int16";
|
||||
constexpr StringLiteral Int32 = "B.int32";
|
||||
constexpr StringLiteral Int64 = "B.int64";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -63,17 +63,17 @@ static_assert(isBasicString_v<ox::BasicString<8ul>>);
|
||||
static_assert(isBasicString_v<ox::String>);
|
||||
|
||||
template<typename T>
|
||||
consteval bool isBString(const T*) noexcept {
|
||||
consteval bool isIString(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<std::size_t SmallVecSize>
|
||||
consteval bool isBString(const BasicString<SmallVecSize>*) noexcept {
|
||||
consteval bool isIString(const BasicString<SmallVecSize>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isBString_v = isBasicString(static_cast<const T*>(nullptr));
|
||||
constexpr bool isIString_v = isIString(static_cast<const T*>(nullptr));
|
||||
|
||||
static_assert(isBasicString_v<ox::BasicString<0ul>>);
|
||||
static_assert(isBasicString_v<ox::BasicString<8ul>>);
|
||||
@@ -169,12 +169,12 @@ constexpr bool isSmartPtr_v<::std::unique_ptr<T>> = true;
|
||||
#endif
|
||||
|
||||
|
||||
template<typename Union, bool force = false>
|
||||
template<typename Union, bool force = false> requires(force || is_union_v<Union>)
|
||||
class UnionView {
|
||||
|
||||
protected:
|
||||
int m_idx = -1;
|
||||
typename enable_if<is_union_v<Union> || force, Union>::type *m_union = nullptr;
|
||||
Union *m_union = nullptr;
|
||||
|
||||
public:
|
||||
constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {
|
||||
|
||||
4
deps/ox/src/ox/model/walk.hpp
vendored
4
deps/ox/src/ox/model/walk.hpp
vendored
@@ -127,7 +127,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
|
||||
}
|
||||
}
|
||||
walker->popNamePath();
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Reader, typename FH>
|
||||
@@ -141,7 +141,7 @@ constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
|
||||
for (const auto &field : fields) {
|
||||
OX_RETURN_ERROR(parseField(field, rdr, walker));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Reader, typename Handler>
|
||||
|
||||
78
deps/ox/src/ox/oc/read.cpp
vendored
78
deps/ox/src/ox/oc/read.cpp
vendored
@@ -13,31 +13,31 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) {
|
||||
OrganicClawReader::OrganicClawReader(const uint8_t *buff, size_t const buffSize) {
|
||||
auto json = reinterpret_cast<const char*>(buff);
|
||||
auto jsonLen = ox::strnlen(json, buffSize);
|
||||
auto jsonLen = ox::strnlen_s(json, buffSize);
|
||||
Json::CharReaderBuilder parserBuilder;
|
||||
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
||||
throw ox::Exception(1, "Could not parse JSON");
|
||||
throw Exception(1, "Could not parse JSON");
|
||||
}
|
||||
}
|
||||
|
||||
OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
|
||||
OrganicClawReader::OrganicClawReader(CString const json, size_t const jsonLen) {
|
||||
Json::CharReaderBuilder parserBuilder;
|
||||
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
||||
throw ox::Exception(1, "Could not parse JSON");
|
||||
throw Exception(1, "Could not parse JSON");
|
||||
}
|
||||
}
|
||||
|
||||
OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
|
||||
OrganicClawReader::OrganicClawReader(Json::Value json, int const unionIdx) noexcept:
|
||||
m_json(std::move(json)),
|
||||
m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
Error OrganicClawReader::field(const char *key, bool *val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
Error OrganicClawReader::field(CString const key, bool *val) noexcept {
|
||||
Error err{};
|
||||
if (targetValid()) {
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
@@ -45,16 +45,16 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
|
||||
} else if (jv.isBool()) {
|
||||
*val = jv.asBool();
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
Error OrganicClawReader::fieldCString(CString const key, char *val, size_t const buffLen) noexcept {
|
||||
Error err{};
|
||||
CString begin = nullptr, end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
if (targetValid()) {
|
||||
if (jv.empty()) {
|
||||
@@ -64,25 +64,25 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
const auto strSize = static_cast<size_t>(end - begin);
|
||||
auto data = val;
|
||||
if (strSize >= buffLen) {
|
||||
err = ox::Error(2, "String size exceeds capacity of destination");
|
||||
err = Error(2, "String size exceeds capacity of destination");
|
||||
} else {
|
||||
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
memcpy(data, begin, static_cast<size_t>(strSize));
|
||||
data[strSize] = 0;
|
||||
}
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
Error OrganicClawReader::fieldCString(CString const key, char **val) noexcept {
|
||||
Error err{};
|
||||
CString begin = nullptr, end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
auto &data = *val;
|
||||
if (targetValid()) {
|
||||
@@ -92,22 +92,22 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
const auto strSize = static_cast<size_t>(end - begin);
|
||||
safeDelete(*val);
|
||||
*val = new char[strSize + 1];
|
||||
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
memcpy(data, begin, static_cast<size_t>(strSize));
|
||||
data[strSize] = 0;
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
Error OrganicClawReader::fieldCString(CString const key, char **val, size_t const buffLen) noexcept {
|
||||
Error err{};
|
||||
CString begin = nullptr, end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
if (targetValid()) {
|
||||
if (jv.empty()) {
|
||||
@@ -117,29 +117,29 @@ Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t b
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
const auto strSize = static_cast<size_t>(end - begin);
|
||||
auto data = val;
|
||||
if (strSize >= buffLen) {
|
||||
safeDelete(*val);
|
||||
*val = new char[strSize + 1];
|
||||
}
|
||||
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
memcpy(data, begin, static_cast<size_t>(strSize));
|
||||
data[strSize] = nullptr;
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::field(const char *key, UUID *val) noexcept {
|
||||
Error OrganicClawReader::field(CString const key, UUID *val) noexcept {
|
||||
UUIDStr str;
|
||||
OX_RETURN_ERROR(field(key, &str));
|
||||
return UUID::fromString(str).moveTo(*val);
|
||||
}
|
||||
|
||||
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept {
|
||||
Result<size_t> OrganicClawReader::arrayLength(CString const key, bool) noexcept {
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
return 0;
|
||||
@@ -147,32 +147,32 @@ Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexce
|
||||
if (jv.isArray()) {
|
||||
return jv.size();
|
||||
}
|
||||
return ox::Error(1, "Type mismatch");
|
||||
return Error(1, "Type mismatch");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
size_t OrganicClawReader::stringLength(CString const key) noexcept {
|
||||
CString begin = nullptr, end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
return 0;
|
||||
}
|
||||
if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
return static_cast<std::size_t>(end - begin);
|
||||
return static_cast<size_t>(end - begin);
|
||||
}
|
||||
return ox::Error(1, "Type mismatch");
|
||||
return Error(1, "Type mismatch");
|
||||
}
|
||||
|
||||
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {
|
||||
OrganicClawReader OrganicClawReader::child(CString const key, int const unionIdx) noexcept {
|
||||
return OrganicClawReader(value(key), unionIdx);
|
||||
}
|
||||
|
||||
bool OrganicClawReader::fieldPresent(const char *key) noexcept {
|
||||
bool OrganicClawReader::fieldPresent(CString const key) noexcept {
|
||||
return !m_json[key].empty();
|
||||
}
|
||||
|
||||
int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u) const noexcept {
|
||||
int OrganicClawReader::whichFieldPresent(CString const name, ModelUnion const &u) const noexcept {
|
||||
const auto &obj = m_json[name];
|
||||
if (!obj.isObject()) {
|
||||
return -1;
|
||||
@@ -184,7 +184,7 @@ int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u)
|
||||
return u.getKeyIdx(keys.front().c_str());
|
||||
}
|
||||
|
||||
Json::Value &OrganicClawReader::value(const char *key) noexcept {
|
||||
Json::Value &OrganicClawReader::value(CString const key) noexcept {
|
||||
if (m_json.isArray()) {
|
||||
return m_json[m_fieldIt];
|
||||
} else {
|
||||
|
||||
162
deps/ox/src/ox/oc/read.hpp
vendored
162
deps/ox/src/ox/oc/read.hpp
vendored
@@ -8,7 +8,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/def.hpp>
|
||||
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
#include <json/json.h>
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
@@ -30,75 +34,76 @@ class OrganicClawReader {
|
||||
private:
|
||||
Json::Value m_json;
|
||||
Json::ArrayIndex m_fieldIt = 0;
|
||||
int m_unionIdx = -1;
|
||||
int const m_unionIdx = -1;
|
||||
|
||||
public:
|
||||
OrganicClawReader() noexcept = default;
|
||||
|
||||
OrganicClawReader(const uint8_t *buff, std::size_t buffSize);
|
||||
OrganicClawReader(uint8_t const *buff, size_t buffSize);
|
||||
|
||||
OrganicClawReader(const char *json, std::size_t buffSize);
|
||||
OrganicClawReader(CString json, size_t buffSize);
|
||||
|
||||
explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char *key, bool *val) noexcept;
|
||||
Error field(CString key, bool *val) noexcept;
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
Error field(const char *key, T *val, std::size_t len) noexcept;
|
||||
Error field(CString key, T *val, size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
Error field(CString, HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char *key, T *val) noexcept;
|
||||
Error field(CString key, T *val) noexcept;
|
||||
|
||||
template<typename U, bool force = false>
|
||||
Error field(const char *key, UnionView<U, force> val) noexcept;
|
||||
Error field(CString key, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BasicString<L> *val) noexcept;
|
||||
template<size_t L>
|
||||
Error field(CString key, BasicString<L> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, IString<L> *val) noexcept;
|
||||
template<size_t L>
|
||||
Error field(CString key, IString<L> *val) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char *val, std::size_t buffLen) noexcept;
|
||||
Error fieldCString(CString key, char *val, size_t buffLen) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char **val) noexcept;
|
||||
Error fieldCString(CString key, char **val) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char **val, std::size_t buffLen) noexcept;
|
||||
Error fieldCString(CString key, char **val, size_t buffLen) noexcept;
|
||||
|
||||
Error field(const char *key, UUID *val) noexcept;
|
||||
Error field(CString key, UUID *val) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param key
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
*/
|
||||
Result<std::size_t> arrayLength(const char *key, bool pass = true) noexcept;
|
||||
Result<size_t> arrayLength(CString key, bool pass = true) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an string length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::size_t stringLength(const char *name) noexcept;
|
||||
size_t stringLength(CString key) noexcept;
|
||||
|
||||
template<typename T = void>
|
||||
constexpr ox::Error setTypeInfo() noexcept {
|
||||
constexpr Error setTypeInfo() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr ox::Error setTypeInfo(const char*) noexcept {
|
||||
constexpr Error setTypeInfo(CString) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr ox::Error setTypeInfo(const char*, int, const Vector<String>& = {}) noexcept {
|
||||
constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr ox::Error setTypeInfo(const char*, int, const Vector<String>& = {}, std::size_t = {}) noexcept {
|
||||
constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}, size_t = {}) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -106,16 +111,16 @@ class OrganicClawReader {
|
||||
* Returns a OrganicClawReader to parse a child object.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
OrganicClawReader child(const char *key, int unionIdx = -1) noexcept;
|
||||
OrganicClawReader child(CString key, int unionIdx = -1) noexcept;
|
||||
|
||||
// compatibility stub
|
||||
constexpr void nextField() noexcept {}
|
||||
|
||||
[[nodiscard]]
|
||||
bool fieldPresent(const char *key) noexcept;
|
||||
bool fieldPresent(CString key) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int whichFieldPresent(const char *name, const ModelUnion &u) const noexcept;
|
||||
int whichFieldPresent(CString name, const ModelUnion &u) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
@@ -124,7 +129,7 @@ class OrganicClawReader {
|
||||
|
||||
private:
|
||||
[[nodiscard]]
|
||||
Json::Value &value(const char *key) noexcept;
|
||||
Json::Value &value(CString key) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool targetValid() const noexcept;
|
||||
@@ -132,103 +137,102 @@ class OrganicClawReader {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawReader::field(const char *key, T *val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
Error OrganicClawReader::field(CString key, T *val) noexcept {
|
||||
Error err{};
|
||||
try {
|
||||
if constexpr (is_integer_v<T>) {
|
||||
if (targetValid()) {
|
||||
auto const&jv = value(key);
|
||||
auto const &jv = value(key);
|
||||
auto const rightType = sizeof(T) == 8 ?
|
||||
(ox::is_signed_v<T> ? jv.isInt64() : jv.isUInt64()) :
|
||||
(ox::is_signed_v<T> ? jv.isInt() : jv.isUInt());
|
||||
(is_signed_v<T> ? jv.isInt64() : jv.isUInt64()) :
|
||||
(is_signed_v<T> ? jv.isInt() : jv.isUInt());
|
||||
if (jv.empty()) {
|
||||
*val = 0;
|
||||
} else if (rightType) {
|
||||
if constexpr(ox::is_signed_v<T>) {
|
||||
if constexpr(is_signed_v<T>) {
|
||||
*val = static_cast<T>(jv.asInt64());
|
||||
} else {
|
||||
*val = static_cast<T>(jv.asUInt64());
|
||||
}
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error{1, "Type mismatch"};
|
||||
}
|
||||
}
|
||||
} else if constexpr (isVector_v<T>) {
|
||||
const auto&srcVal = value(key);
|
||||
const auto srcSize = srcVal.size();
|
||||
OX_RETURN_ERROR(ox::resizeVector(*val, srcSize));
|
||||
auto const &srcVal = value(key);
|
||||
auto const srcSize = srcVal.size();
|
||||
OX_RETURN_ERROR(resizeVector(*val, srcSize));
|
||||
err = field(key, val->data(), val->size());
|
||||
} else if constexpr (isArray_v<T>) {
|
||||
const auto&srcVal = value(key);
|
||||
const auto srcSize = srcVal.size();
|
||||
auto const &srcVal = value(key);
|
||||
auto const srcSize = srcVal.size();
|
||||
if (srcSize > val->size()) {
|
||||
err = ox::Error(1, "Input array is too long");
|
||||
err = Error{1, "Input array is too long"};
|
||||
} else {
|
||||
err = field(key, val->data(), val->size());
|
||||
}
|
||||
} else if (targetValid()) {
|
||||
const auto&jv = value(key);
|
||||
auto const &jv = value(key);
|
||||
if (jv.empty() || jv.isObject()) {
|
||||
auto reader = child(key);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
ModelHandlerInterface handler(reader);
|
||||
err = model(&handler, val);
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error{1, "Type mismatch"};
|
||||
}
|
||||
}
|
||||
} catch (Json::LogicError const&e) {
|
||||
oxDebugf("JSON error: {}", e.what());
|
||||
err = ox::Error(1, "error reading JSON data");
|
||||
} catch (Json::LogicError const &e) {
|
||||
err = Error{1, "error reading JSON data"};
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename U, bool force>
|
||||
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
Error OrganicClawReader::field(CString const key, UnionView<U, force> val) noexcept {
|
||||
Error err{};
|
||||
if (targetValid()) {
|
||||
const auto &jv = value(key);
|
||||
auto const &jv = value(key);
|
||||
if (jv.empty() || jv.isObject()) {
|
||||
auto reader = child(key, val.idx());
|
||||
ModelHandlerInterface handler(&reader);
|
||||
ModelHandlerInterface handler(reader);
|
||||
err = model(&handler, val.get());
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error{1, "Type mismatch"};
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
template<size_t L>
|
||||
Error OrganicClawReader::field(CString const key, BasicString<L> *val) noexcept {
|
||||
Error err{};
|
||||
if (targetValid()) {
|
||||
const auto &jv = value(key);
|
||||
auto const &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
*val = BasicString<L>{};
|
||||
} else if (jv.isString()) {
|
||||
*val = jv.asString().c_str();
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error{1, "Type mismatch"};
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
|
||||
auto err = ox::Error(0);
|
||||
template<size_t L>
|
||||
Error OrganicClawReader::field(CString const key, IString<L> *val) noexcept {
|
||||
Error err{};
|
||||
if (targetValid()) {
|
||||
const auto &jv = value(key);
|
||||
auto const &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
*val = IString<L>{};
|
||||
} else if (jv.isString()) {
|
||||
*val = jv.asString().c_str();
|
||||
} else {
|
||||
err = ox::Error(1, "Type mismatch");
|
||||
err = Error{1, "Type mismatch"};
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
@@ -237,43 +241,43 @@ Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
|
||||
const auto &srcVal = value(key);
|
||||
Error OrganicClawReader::field(CString const key, T *val, size_t valLen) noexcept {
|
||||
auto const &srcVal = value(key);
|
||||
if (!srcVal.isNull() && !srcVal.isArray()) {
|
||||
return ox::Error(1, "Type mismatch");
|
||||
return Error{1, "Type mismatch"};
|
||||
}
|
||||
auto srcSize = srcVal.size();
|
||||
if (srcSize > valLen) {
|
||||
return ox::Error(1);
|
||||
return Error{1};
|
||||
}
|
||||
OrganicClawReader r(srcVal);
|
||||
ModelHandlerInterface handler{&r};
|
||||
ModelHandlerInterface handler{r};
|
||||
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
OX_RETURN_ERROR(handler.field("", &val[i]));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
const auto &srcVal = value(key);
|
||||
Error OrganicClawReader::field(CString const key, HashMap<String, T> *val) noexcept {
|
||||
auto const &srcVal = value(key);
|
||||
if (!srcVal.isObject()) {
|
||||
return ox::Error(1, "Type mismatch");
|
||||
return Error{1, "Type mismatch"};
|
||||
}
|
||||
auto keys = srcVal.getMemberNames();
|
||||
auto srcSize = srcVal.size();
|
||||
OrganicClawReader r(srcVal);
|
||||
ModelHandlerInterface handler{&r};
|
||||
ModelHandlerInterface handler{r};
|
||||
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
|
||||
const auto k = keys[i].c_str();
|
||||
auto const k = keys[i].c_str();
|
||||
OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
|
||||
}
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error readOC(BufferView buff, auto &val) noexcept {
|
||||
Error readOC(BufferView const buff, auto &val) noexcept {
|
||||
// OrganicClawReader constructor can throw, but readOC should return its errors.
|
||||
try {
|
||||
Json::Value doc;
|
||||
@@ -282,15 +286,15 @@ Error readOC(BufferView buff, auto &val) noexcept {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return ox::Error(1, "Could not parse JSON");
|
||||
return Error{1, "Could not parse JSON"};
|
||||
}
|
||||
OrganicClawReader reader(buff.data(), buff.size());
|
||||
ModelHandlerInterface handler(&reader);
|
||||
ModelHandlerInterface handler(reader);
|
||||
return model(&handler, &val);
|
||||
} catch (const Error &err) {
|
||||
} catch (Error const &err) {
|
||||
return err;
|
||||
} catch (...) {
|
||||
return ox::Error(1, "Unknown Error");
|
||||
return Error{1, "Unknown Error"};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,8 +306,8 @@ Result<T> readOC(BufferView buff) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<T> readOC(ox::StringView json) noexcept {
|
||||
return readOC<T>(ox::BufferView{json.data(), json.len()});
|
||||
Result<T> readOC(StringViewCR json) noexcept {
|
||||
return readOC<T>(BufferView{json.data(), json.size()});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
14
deps/ox/src/ox/oc/write.cpp
vendored
14
deps/ox/src/ox/oc/write.cpp
vendored
@@ -10,29 +10,29 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
OrganicClawWriter::OrganicClawWriter(int unionIdx) noexcept: m_unionIdx(unionIdx) {
|
||||
OrganicClawWriter::OrganicClawWriter(int const unionIdx) noexcept: m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept:
|
||||
OrganicClawWriter::OrganicClawWriter(Json::Value json, int const unionIdx) noexcept:
|
||||
m_json(std::move(json)),
|
||||
m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, int len) noexcept {
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const *val, int const len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const *val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), static_cast<int>(ox::strlen(val)));
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept {
|
||||
Error OrganicClawWriter::field(const char *key, UUID const *uuid) noexcept {
|
||||
const auto uuidStr = uuid->toString();
|
||||
if (targetValid() && uuidStr.len()) {
|
||||
if (targetValid() && uuidStr.size()) {
|
||||
value(key) = uuidStr.c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
|
||||
128
deps/ox/src/ox/oc/write.hpp
vendored
128
deps/ox/src/ox/oc/write.hpp
vendored
@@ -8,7 +8,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/def.hpp>
|
||||
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
#include <json/json.h>
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
@@ -24,85 +28,85 @@ namespace ox {
|
||||
|
||||
class OrganicClawWriter {
|
||||
|
||||
friend Result<ox::Buffer> writeOC(const auto &val) noexcept;
|
||||
friend Result<ox::String> writeOCString(const auto &val) noexcept;
|
||||
friend Result<Buffer> writeOC(const auto &val) noexcept;
|
||||
friend Result<String> writeOCString(const auto &val) noexcept;
|
||||
|
||||
protected:
|
||||
Json::Value m_json{Json::Value(Json::objectValue)};
|
||||
Json::ArrayIndex m_fieldIt = 0;
|
||||
int m_unionIdx = -1;
|
||||
int const m_unionIdx = -1;
|
||||
|
||||
public:
|
||||
explicit OrganicClawWriter(int unionIdx = -1) noexcept;
|
||||
|
||||
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char *key, const int8_t *val) noexcept {
|
||||
Error field(CString const key, int8_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const int16_t *val) noexcept {
|
||||
Error field(CString const key, int16_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const int32_t *val) noexcept {
|
||||
Error field(CString const key, int32_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const int64_t *val) noexcept {
|
||||
Error field(CString const key, int64_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
Error field(const char *key, const uint8_t *val) noexcept {
|
||||
Error field(CString const key, uint8_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint16_t *val) noexcept {
|
||||
Error field(CString const key, uint16_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint32_t *val) noexcept {
|
||||
Error field(CString const key, uint32_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(const char *key, const uint64_t *val) noexcept {
|
||||
Error field(CString const key, uint64_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error field(char const*key, bool const*val) noexcept {
|
||||
Error field(char const*key, bool const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@@ -114,12 +118,12 @@ class OrganicClawWriter {
|
||||
Error field(char const*, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(char const*key, HashMap<String, T> const*val) noexcept {
|
||||
Error field(char const*key, HashMap<String, T> const *val) noexcept {
|
||||
if (targetValid()) {
|
||||
const auto &keys = val->keys();
|
||||
OrganicClawWriter w;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
|
||||
for (std::size_t i = 0; i < keys.size(); ++i) {
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
|
||||
for (size_t i = 0; i < keys.size(); ++i) {
|
||||
const auto k = keys[i].c_str();
|
||||
if (k) [[likely]] {
|
||||
OX_REQUIRE_M(value, val->at(k));
|
||||
@@ -132,49 +136,49 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(char const*key, IString<L> const*val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
template<size_t L>
|
||||
Error field(char const*key, IString<L> const *val) noexcept {
|
||||
if (targetValid() && val->size()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(char const*key, BasicString<L> const*val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
template<size_t L>
|
||||
Error field(char const*key, BasicString<L> const *val) noexcept {
|
||||
if (targetValid() && val->size()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error fieldCString(const char*, const char *const*val, int len) noexcept;
|
||||
Error fieldCString(CString, CString const *val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, const char *const*val) noexcept;
|
||||
Error fieldCString(CString name, CString const*val) noexcept;
|
||||
|
||||
Error field(const char *key, const UUID *uuid) noexcept;
|
||||
Error field(CString key, UUID const *uuid) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
Error field(CString, T const *val, size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, const T *val) noexcept;
|
||||
Error field(CString, T const *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
constexpr Error setTypeInfo(
|
||||
const char* = T::TypeName,
|
||||
int = T::TypeVersion) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
constexpr Error setTypeInfo(
|
||||
const char*,
|
||||
int,
|
||||
const Vector<String>&,
|
||||
std::size_t) noexcept {
|
||||
Vector<String> const&,
|
||||
size_t) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -190,16 +194,16 @@ class OrganicClawWriter {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Json::Value &value(const char *key) noexcept;
|
||||
Json::Value &value(CString key) noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) noexcept {
|
||||
Error OrganicClawWriter::field(CString key, T const *val, size_t const len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
OrganicClawWriter w((Json::Value(Json::arrayValue)));
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
OX_RETURN_ERROR(handler.field({}, &val[i]));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
@@ -207,70 +211,74 @@ OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
|
||||
Error OrganicClawWriter::field(CString key, T const *val) noexcept {
|
||||
if constexpr(is_integer_v<T>) {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
// the int type needs to be normalized because jsoncpp doesn't
|
||||
// factor in every permutation unsigned long, etc.
|
||||
if constexpr(ox::is_signed_v<T>) {
|
||||
value(key) = static_cast<ox::Int<8 * sizeof(*val)>>(*val);
|
||||
if constexpr(is_signed_v<T>) {
|
||||
value(key) = static_cast<Int<8 * sizeof(*val)>>(*val);
|
||||
} else {
|
||||
value(key) = static_cast<ox::Uint<8 * sizeof(*val)>>(*val);
|
||||
value(key) = static_cast<Uint<8 * sizeof(*val)>>(*val);
|
||||
}
|
||||
}
|
||||
} else if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(key, val->data(), val->size());
|
||||
} else if (val && targetValid()) {
|
||||
OrganicClawWriter w;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
|
||||
OX_RETURN_ERROR(model(&handler, val));
|
||||
if (!w.m_json.empty() || m_json.isArray()) {
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename U, bool force>
|
||||
Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept {
|
||||
Error OrganicClawWriter::field(CString key, UnionView<U, force> val) noexcept {
|
||||
if (targetValid()) {
|
||||
OrganicClawWriter w(val.idx());
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{&w};
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler{w};
|
||||
OX_RETURN_ERROR(model(&handler, val.get()));
|
||||
if (!w.m_json.isNull()) {
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<ox::Buffer> writeOC(const auto &val) noexcept {
|
||||
Result<Buffer> writeOC(auto const &val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
Json::StreamWriterBuilder const jsonBuilder;
|
||||
const auto str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
auto const str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
Result<Buffer> buff;
|
||||
buff.value.resize(str.size() + 1);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
memcpy(buff.value.data(), str.data(), str.size() + 1);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return buff;
|
||||
}
|
||||
|
||||
Result<ox::String> writeOCString(const auto &val) noexcept {
|
||||
Result<String> writeOCString(auto const &val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(&writer);
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
Json::StreamWriterBuilder const jsonBuilder;
|
||||
const auto str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
Result<ox::String> buff;
|
||||
auto const str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
Result<String> buff;
|
||||
buff.value.resize(str.size());
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
memcpy(buff.value.data(), str.data(), str.size() + 1);
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@@ -33,6 +33,7 @@ add_library(
|
||||
concepts.cpp
|
||||
fmt.cpp
|
||||
heapmgr.cpp
|
||||
istreamreader.cpp
|
||||
math.cpp
|
||||
memops.cpp
|
||||
random.cpp
|
||||
|
||||
100
deps/ox/src/ox/std/anyptr.hpp
vendored
100
deps/ox/src/ox/std/anyptr.hpp
vendored
@@ -22,7 +22,7 @@ class AnyPtrT {
|
||||
private:
|
||||
struct WrapBase {
|
||||
virtual constexpr ~WrapBase() = default;
|
||||
virtual constexpr WrapBase *copyTo(ox::Span<char> s) noexcept = 0;
|
||||
virtual constexpr WrapBase *copyTo(Span<char> s) const noexcept = 0;
|
||||
virtual constexpr operator bool() const noexcept = 0;
|
||||
virtual void free() noexcept = 0;
|
||||
};
|
||||
@@ -32,7 +32,7 @@ class AnyPtrT {
|
||||
T *data{};
|
||||
explicit constexpr Wrap(T *pData) noexcept: data(pData) {
|
||||
}
|
||||
constexpr WrapBase *copyTo(ox::Span<char> s) noexcept override {
|
||||
constexpr WrapBase *copyTo(Span<char> s) const noexcept override {
|
||||
oxAssert(s.size() >= sizeof(Wrap), "too small buffer");
|
||||
if (std::is_constant_evaluated()) {
|
||||
return new Wrap(data);
|
||||
@@ -49,8 +49,10 @@ class AnyPtrT {
|
||||
}
|
||||
};
|
||||
|
||||
WrapBase *m_wrapPtr{};
|
||||
ox::Array<char, sizeof(Wrap<void*>)> m_wrapData;
|
||||
union {
|
||||
WrapBase *m_wrapPtr{};
|
||||
AllocAlias<Wrap<void*>> m_wrapData;
|
||||
} m_data;
|
||||
|
||||
public:
|
||||
constexpr AnyPtrT() noexcept = default;
|
||||
@@ -58,25 +60,25 @@ class AnyPtrT {
|
||||
template<typename T>
|
||||
constexpr AnyPtrT(T *ptr) noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
m_wrapPtr = new Wrap<T>(ptr);
|
||||
setWrapPtr(new Wrap<T>(ptr));
|
||||
} else {
|
||||
m_wrapPtr = new(m_wrapData.data()) Wrap<T>(ptr);
|
||||
new(m_data.m_wrapData.data()) Wrap<T>(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr AnyPtrT(AnyPtrT const&other) noexcept requires(!unique) {
|
||||
constexpr AnyPtrT(AnyPtrT const &other) noexcept requires(!unique) {
|
||||
if (other) {
|
||||
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
|
||||
setWrapPtr(other.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr AnyPtrT(AnyPtrT &&other) noexcept {
|
||||
if (other) {
|
||||
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
|
||||
setWrapPtr(other.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
|
||||
if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
other.m_wrapPtr = {};
|
||||
m_data.m_wrapData = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +87,7 @@ class AnyPtrT {
|
||||
free();
|
||||
}
|
||||
if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,25 +96,31 @@ class AnyPtrT {
|
||||
if constexpr(unique) {
|
||||
free();
|
||||
} else if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
if (std::is_constant_evaluated()) {
|
||||
m_wrapPtr = new Wrap(ptr);
|
||||
setWrapPtr(new Wrap(ptr));
|
||||
} else {
|
||||
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr);
|
||||
new(m_data.m_wrapData.data()) Wrap(ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr AnyPtrT &operator=(AnyPtrT const&ptr) noexcept requires(!unique) {
|
||||
constexpr AnyPtrT &operator=(AnyPtrT const &ptr) noexcept requires(!unique) {
|
||||
if (this != &ptr) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
if (ptr) {
|
||||
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData);
|
||||
if (std::is_constant_evaluated()) {
|
||||
if (ptr) {
|
||||
ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff);
|
||||
}
|
||||
} else {
|
||||
m_wrapPtr = nullptr;
|
||||
if (ptr) {
|
||||
setWrapPtr(ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
|
||||
} else {
|
||||
setWrapPtr(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@@ -123,43 +131,65 @@ class AnyPtrT {
|
||||
if constexpr(unique) {
|
||||
free();
|
||||
} else if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
if (ptr) {
|
||||
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData);
|
||||
setWrapPtr(ptr.getWrapPtr()->copyTo(m_data.m_wrapData.buff));
|
||||
if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(ptr.m_wrapPtr);
|
||||
ptr.m_wrapPtr = nullptr;
|
||||
ox::safeDelete(ptr.m_data.m_wrapPtr);
|
||||
setWrapPtr(nullptr);
|
||||
}
|
||||
} else {
|
||||
m_wrapPtr = nullptr;
|
||||
m_data = {};
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr operator bool() const noexcept {
|
||||
return m_wrapPtr && *m_wrapPtr;
|
||||
return getWrapPtr() && *getWrapPtr();
|
||||
}
|
||||
|
||||
constexpr void free() noexcept {
|
||||
if (m_wrapPtr) {
|
||||
m_wrapPtr->free();
|
||||
if (auto p = getWrapPtr()) {
|
||||
p->free();
|
||||
}
|
||||
if (std::is_constant_evaluated()) {
|
||||
ox::safeDelete(m_wrapPtr);
|
||||
ox::safeDelete(m_data.m_wrapPtr);
|
||||
}
|
||||
m_wrapPtr = nullptr;
|
||||
m_data.m_wrapData = {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T *get() const noexcept {
|
||||
#ifdef OX_BARE_METAL
|
||||
return static_cast<Wrap<T>*>(m_wrapPtr)->data;
|
||||
#else
|
||||
return dynamic_cast<Wrap<T>*>(m_wrapPtr)->data;
|
||||
#endif
|
||||
if constexpr(defines::HasRTTI) {
|
||||
return dynamic_cast<Wrap<T> const*>(getWrapPtr())->data;
|
||||
}
|
||||
return static_cast<Wrap<T> const*>(getWrapPtr())->data;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void setWrapPtr(WrapBase *ptr) noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
m_data.m_wrapPtr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr WrapBase *getWrapPtr() noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
return m_data.m_wrapPtr;
|
||||
} else {
|
||||
return std::launder(reinterpret_cast<WrapBase*>(m_data.m_wrapData.data()));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr WrapBase const *getWrapPtr() const noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
return m_data.m_wrapPtr;
|
||||
} else {
|
||||
return std::launder(reinterpret_cast<WrapBase const*>(m_data.m_wrapData.data()));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
4
deps/ox/src/ox/std/array.hpp
vendored
4
deps/ox/src/ox/std/array.hpp
vendored
@@ -181,13 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
|
||||
|
||||
template<typename T, std::size_t ArraySize>
|
||||
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
|
||||
boundsCheck(i, size(), "Array access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t ArraySize>
|
||||
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
|
||||
boundsCheck(i, size(), "Array access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
|
||||
58
deps/ox/src/ox/std/assert.cpp
vendored
58
deps/ox/src/ox/std/assert.cpp
vendored
@@ -15,8 +15,8 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept {
|
||||
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
|
||||
void panic(Error const &err, StringViewCR panicMsg, std::source_location const &src) noexcept {
|
||||
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", src.file_name(), src.line(), panicMsg);
|
||||
if (err.msg) {
|
||||
oxErrf("\tError Message:\t{}\n", err.msg);
|
||||
}
|
||||
@@ -26,41 +26,61 @@ void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const
|
||||
}
|
||||
#ifdef OX_USE_STDLIB
|
||||
printStackTrace(2);
|
||||
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << file << ":" << line << ")";
|
||||
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << src.file_name() << ":" << src.line() << ")";
|
||||
std::abort();
|
||||
#else
|
||||
while (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept {
|
||||
panic(StringView{file}, line, StringView{panicMsg}, err);
|
||||
#if __GNUC__ && !_WIN32
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void panic(Error const &err, char const*panicMsg, std::source_location const &src) noexcept {
|
||||
panic(err, StringView{panicMsg}, src);
|
||||
}
|
||||
|
||||
void assertFailFuncRuntime(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
StringViewCR assertTxt,
|
||||
StringViewCR msg) noexcept {
|
||||
StringViewCR msg,
|
||||
std::source_location const &src) noexcept {
|
||||
#ifdef OX_USE_STDLIB
|
||||
auto const st = genStackTrace(2);
|
||||
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st);
|
||||
oxTracef(
|
||||
"assert", "Failed assert: {} ({}) [{}:{}]:\n{}",
|
||||
msg,
|
||||
assertTxt,
|
||||
src.file_name(),
|
||||
src.line(),
|
||||
st);
|
||||
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);
|
||||
oxErrf(
|
||||
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
|
||||
src.file_name(),
|
||||
src.line(),
|
||||
msg);
|
||||
oxTracef(
|
||||
"assert", "Failed assert: {} ({}) [{}:{}]",
|
||||
msg,
|
||||
assertTxt,
|
||||
src.file_name(),
|
||||
src.line());
|
||||
constexprPanic(msg, {}, src);
|
||||
#endif
|
||||
}
|
||||
|
||||
void assertFailFuncRuntime(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
[[maybe_unused]] Error const&err,
|
||||
[[maybe_unused]] Error const &err,
|
||||
StringViewCR,
|
||||
StringViewCR assertMsg) noexcept {
|
||||
StringViewCR assertMsg,
|
||||
std::source_location const &src) noexcept {
|
||||
#if defined(OX_USE_STDLIB)
|
||||
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
|
||||
auto msg = sfmt(
|
||||
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
|
||||
src.file_name(),
|
||||
src.line(),
|
||||
assertMsg);
|
||||
if (err.msg) {
|
||||
msg += sfmt("\tError Message:\t{}\n", err.msg);
|
||||
}
|
||||
@@ -70,10 +90,10 @@ void assertFailFuncRuntime(
|
||||
}
|
||||
msg += genStackTrace(2);
|
||||
oxErr(msg);
|
||||
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
|
||||
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, src.file_name(), src.line());
|
||||
abort();
|
||||
#else
|
||||
constexprPanic(file, line, assertMsg);
|
||||
constexprPanic(assertMsg, {}, src);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
79
deps/ox/src/ox/std/assert.hpp
vendored
79
deps/ox/src/ox/std/assert.hpp
vendored
@@ -8,10 +8,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(OX_USE_STDLIB)
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include "def.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "error.hpp"
|
||||
@@ -23,42 +19,49 @@
|
||||
namespace ox {
|
||||
|
||||
[[noreturn]]
|
||||
void panic(StringViewCR file, int line, StringViewCR panicMsg, Error const&err = {}) noexcept;
|
||||
void panic(
|
||||
Error const&err,
|
||||
StringViewCR panicMsg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept;
|
||||
|
||||
[[noreturn]]
|
||||
inline void panic(
|
||||
StringViewCR panicMsg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
panic(Error{1}, panicMsg, src);
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
constexpr void constexprPanic(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
StringViewCR panicMsg,
|
||||
Error const&err = {}) noexcept {
|
||||
Error const &err = {},
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
panic(file, line, panicMsg, err);
|
||||
panic(err, panicMsg, src);
|
||||
} else {
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void assertFailFuncRuntime(
|
||||
StringViewCR file,
|
||||
int line,
|
||||
StringViewCR assertTxt,
|
||||
StringViewCR msg) noexcept;
|
||||
StringViewCR msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept;
|
||||
|
||||
void assertFailFuncRuntime(
|
||||
StringViewCR file,
|
||||
int line,
|
||||
Error const&err,
|
||||
Error const &err,
|
||||
StringViewCR,
|
||||
StringViewCR assertMsg) noexcept;
|
||||
StringViewCR assertMsg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept;
|
||||
|
||||
constexpr void assertFunc(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
bool const pass,
|
||||
[[maybe_unused]]StringViewCR assertTxt,
|
||||
[[maybe_unused]]StringViewCR msg) noexcept {
|
||||
[[maybe_unused]]StringViewCR msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if (!pass) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
assertFailFuncRuntime(file, line, assertTxt, msg);
|
||||
assertFailFuncRuntime(assertTxt, msg, src);
|
||||
} else {
|
||||
while (true);
|
||||
}
|
||||
@@ -66,14 +69,13 @@ constexpr void assertFunc(
|
||||
}
|
||||
|
||||
constexpr void assertFunc(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
Error const&err,
|
||||
Error const &err,
|
||||
StringViewCR,
|
||||
StringViewCR assertMsg) noexcept {
|
||||
StringViewCR assertMsg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if (err) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
assertFailFuncRuntime(file, line, err, {}, assertMsg);
|
||||
assertFailFuncRuntime(err, {}, assertMsg, src);
|
||||
} else {
|
||||
while (true);
|
||||
}
|
||||
@@ -81,20 +83,31 @@ constexpr void assertFunc(
|
||||
}
|
||||
|
||||
constexpr void expect(
|
||||
StringViewCR file,
|
||||
int const line,
|
||||
auto const&actual,
|
||||
auto const&expected) noexcept {
|
||||
auto const &actual,
|
||||
auto const &expected,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if (actual != expected) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
#if defined(OX_USE_STDLIB)
|
||||
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
|
||||
oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
|
||||
oxErrf(
|
||||
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
|
||||
src.file_name(),
|
||||
src.line(),
|
||||
"Value incorrect");
|
||||
oxErrf(
|
||||
"expected: {}\nactual: {}\n",
|
||||
detail::toStringView<true>(expected),
|
||||
detail::toStringView<true>(actual));
|
||||
printStackTrace(2);
|
||||
oxTracef("assert.expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
|
||||
oxTracef(
|
||||
"assert.expect", "Failed assert: {} == {} [{}:{}]",
|
||||
detail::toStringView<true>(actual),
|
||||
detail::toStringView<true>(expected),
|
||||
src.file_name(),
|
||||
src.line());
|
||||
std::abort();
|
||||
#else
|
||||
constexprPanic(file, line, "Comparison failed");
|
||||
constexprPanic("Comparison failed", {}, src);
|
||||
#endif
|
||||
} else {
|
||||
while (true);
|
||||
|
||||
2
deps/ox/src/ox/std/basestringview.hpp
vendored
2
deps/ox/src/ox/std/basestringview.hpp
vendored
@@ -185,7 +185,7 @@ class BaseStringView {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto len() const noexcept {
|
||||
constexpr auto size() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
|
||||
8
deps/ox/src/ox/std/byteswap.hpp
vendored
8
deps/ox/src/ox/std/byteswap.hpp
vendored
@@ -17,19 +17,19 @@ namespace ox {
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T byteSwap(typename enable_if<sizeof(T) == 1, T>::type i) noexcept {
|
||||
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 1) {
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T byteSwap(typename enable_if<sizeof(T) == 2, T>::type i) noexcept {
|
||||
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 2) {
|
||||
return static_cast<T>(i << 8) | static_cast<T>(i >> 8);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T byteSwap(typename enable_if<sizeof(T) == 4, T>::type i) noexcept {
|
||||
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 4) {
|
||||
return ((i >> 24) & 0x000000ff) |
|
||||
((i >> 8) & 0x0000ff00) |
|
||||
((i << 8) & 0x00ff0000) |
|
||||
@@ -38,7 +38,7 @@ constexpr T byteSwap(typename enable_if<sizeof(T) == 4, T>::type i) noexcept {
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T byteSwap(typename enable_if<sizeof(T) == 8, T>::type i) noexcept {
|
||||
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 8) {
|
||||
return ((i >> 56) & 0x00000000000000ff) |
|
||||
((i >> 40) & 0x000000000000ff00) |
|
||||
((i >> 24) & 0x0000000000ff0000) |
|
||||
|
||||
4
deps/ox/src/ox/std/concepts.hpp
vendored
4
deps/ox/src/ox/std/concepts.hpp
vendored
@@ -32,4 +32,8 @@ concept Integral_c = ox::is_integral_v<T>;
|
||||
|
||||
template<typename T, size_t max>
|
||||
concept IntegerRange_c = ox::is_integer_v<T> && ox::MaxValue<T> >= max;
|
||||
|
||||
template<typename Union>
|
||||
concept Union_c = is_union_v<Union>;
|
||||
|
||||
}
|
||||
|
||||
8
deps/ox/src/ox/std/cstringview.hpp
vendored
8
deps/ox/src/ox/std/cstringview.hpp
vendored
@@ -21,13 +21,13 @@ class CStringView: public detail::BaseStringView {
|
||||
|
||||
constexpr CStringView(CStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.size()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.size()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(IString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
constexpr CStringView(IString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.size()) {}
|
||||
|
||||
constexpr CStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
@@ -37,7 +37,7 @@ class CStringView: public detail::BaseStringView {
|
||||
|
||||
constexpr auto &operator=(CStringView const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
set(other.data(), other.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
9
deps/ox/src/ox/std/cstrops.hpp
vendored
9
deps/ox/src/ox/std/cstrops.hpp
vendored
@@ -30,9 +30,12 @@ constexpr T1 strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
constexpr size_t strnlen_s(const char *str, size_t const maxLen) noexcept {
|
||||
if (!str) [[unlikely]] {
|
||||
return 0;
|
||||
}
|
||||
size_t len = 0;
|
||||
for (; len < maxLen && str[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
5
deps/ox/src/ox/std/def.hpp
vendored
5
deps/ox/src/ox/std/def.hpp
vendored
@@ -48,9 +48,8 @@
|
||||
|
||||
// Asserts
|
||||
|
||||
#define oxPanic(errCode, msg) ox::panic(__FILE__, __LINE__, msg, errCode)
|
||||
#ifndef NDEBUG
|
||||
#define oxAssert(pass, msg) ox::assertFunc(__FILE__, __LINE__, pass, #pass, msg)
|
||||
#define oxAssert(pass, msg) ox::assertFunc(pass, #pass, msg)
|
||||
#else
|
||||
namespace ox {
|
||||
struct [[nodiscard]] Error;
|
||||
@@ -59,8 +58,6 @@ constexpr void oxAssert(bool, const char*) noexcept {}
|
||||
constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
|
||||
#endif
|
||||
|
||||
#define oxExpect(actual, expected) ox::expect(__FILE__, __LINE__, actual, expected)
|
||||
|
||||
// Alloca
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
6
deps/ox/src/ox/std/defines.hpp
vendored
6
deps/ox/src/ox/std/defines.hpp
vendored
@@ -53,6 +53,12 @@ constexpr auto NDebug = true;
|
||||
constexpr auto NDebug = false;
|
||||
#endif
|
||||
|
||||
#if defined(OX_BARE_METAL)
|
||||
constexpr auto HasRTTI = false;
|
||||
#else
|
||||
constexpr auto HasRTTI = true;
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
constexpr auto BigEndian = true;
|
||||
constexpr auto LittleEndian = false;
|
||||
|
||||
106
deps/ox/src/ox/std/error.hpp
vendored
106
deps/ox/src/ox/std/error.hpp
vendored
@@ -17,7 +17,7 @@ class exception {
|
||||
virtual ~exception() = default;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual char const*what() const noexcept {
|
||||
virtual char const *what() const noexcept {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
@@ -37,22 +37,22 @@ using ErrorCode = uint16_t;
|
||||
|
||||
struct [[nodiscard]] Error {
|
||||
std::source_location src;
|
||||
ox::CString msg = nullptr;
|
||||
CString msg = nullptr;
|
||||
ErrorCode errCode = 0;
|
||||
|
||||
constexpr Error() noexcept = default;
|
||||
|
||||
explicit constexpr Error(
|
||||
ErrorCode const errCode,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
std::source_location const &src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
errCode{errCode}
|
||||
{}
|
||||
|
||||
explicit constexpr Error(
|
||||
ErrorCode const errCode,
|
||||
ox::CString msg,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
CString const msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
msg{msg},
|
||||
errCode{errCode}
|
||||
@@ -62,39 +62,51 @@ struct [[nodiscard]] Error {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
constexpr Error reoriginate(
|
||||
ErrorCode const pErrCode,
|
||||
CString const pMsg = nullptr,
|
||||
std::source_location const &pSrc = std::source_location::current()) const noexcept {
|
||||
return Error{pErrCode, pMsg, pSrc};
|
||||
}
|
||||
|
||||
constexpr Error reoriginate(
|
||||
std::source_location const &pSrc = std::source_location::current()) const noexcept {
|
||||
return Error{errCode, msg, pSrc};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto errCode(Error const&err) noexcept {
|
||||
constexpr auto errCode(Error const &err) noexcept {
|
||||
return err.errCode;
|
||||
}
|
||||
|
||||
template<typename T = char const*>
|
||||
[[nodiscard]]
|
||||
constexpr auto toStr(Error const&err) noexcept {
|
||||
constexpr auto toStr(Error const &err) noexcept {
|
||||
return err.msg ? T{err.msg} : "";
|
||||
}
|
||||
|
||||
struct Exception: public std::exception {
|
||||
std::source_location src;
|
||||
ox::CString msg = nullptr;
|
||||
CString msg = nullptr;
|
||||
ErrorCode errCode = 0;
|
||||
|
||||
explicit Exception(
|
||||
ErrorCode const errCode,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
std::source_location const &src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
errCode{errCode} {}
|
||||
|
||||
explicit Exception(
|
||||
ErrorCode const errCode,
|
||||
ox::CString msg,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
CString msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
msg{msg},
|
||||
errCode{errCode} {}
|
||||
|
||||
explicit Exception(Error const&err) noexcept:
|
||||
explicit Exception(Error const &err) noexcept:
|
||||
src{err.src},
|
||||
msg{err.msg ? err.msg : ""},
|
||||
errCode{err.errCode} {}
|
||||
@@ -104,18 +116,21 @@ struct Exception: public std::exception {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
char const*what() const noexcept override {
|
||||
char const *what() const noexcept override {
|
||||
return msg;
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]]
|
||||
void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
|
||||
void panic(
|
||||
Error const &err,
|
||||
CString panicMsg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept;
|
||||
|
||||
template<typename T>
|
||||
struct [[nodiscard]] Result {
|
||||
|
||||
using type = typename remove_reference<T>::type;
|
||||
using type = remove_reference_t<T>;
|
||||
|
||||
T value;
|
||||
Error error;
|
||||
@@ -124,25 +139,25 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Result(Result<U> const&other) noexcept: value(other.value), error(other.error) {
|
||||
constexpr Result(Result<U> const &other) noexcept: value(other.value), error(other.error) {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
|
||||
}
|
||||
|
||||
constexpr Result(Error const&error) noexcept: value(), error(error) {
|
||||
constexpr Result(Error const &error) noexcept: value(), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(type const&value, Error const&error = {}) noexcept: value(value), error(error) {
|
||||
constexpr Result(type const &value, Error const &error = {}) noexcept: value(value), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(type &&value, Error const&error = {}) 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;
|
||||
|
||||
explicit constexpr operator type const&() const noexcept {
|
||||
explicit constexpr operator type const &() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -156,7 +171,7 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error copyTo(U &val) const& noexcept {
|
||||
constexpr Error copyTo(U &val) const & noexcept {
|
||||
if (!error) [[likely]] {
|
||||
val = value;
|
||||
}
|
||||
@@ -182,7 +197,7 @@ struct [[nodiscard]] Result {
|
||||
[[nodiscard]]
|
||||
constexpr T &unwrap() & noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
ox::panic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -190,15 +205,15 @@ struct [[nodiscard]] Result {
|
||||
[[nodiscard]]
|
||||
constexpr T &&unwrap() && noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
ox::panic(error, "Failed unwrap");
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T const&unwrap() const & noexcept {
|
||||
constexpr T const &unwrap() const & noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
ox::panic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -206,7 +221,7 @@ struct [[nodiscard]] Result {
|
||||
[[nodiscard]]
|
||||
constexpr T &unwrapThrow() & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
throw Exception(error);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -214,13 +229,13 @@ struct [[nodiscard]] Result {
|
||||
[[nodiscard]]
|
||||
constexpr T &&unwrapThrow() && {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
throw Exception(error);
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T const&unwrapThrow() const & {
|
||||
constexpr T const &unwrapThrow() const & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
@@ -244,7 +259,7 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
constexpr ox::Result<U> to(auto const&f) & noexcept {
|
||||
constexpr ox::Result<U> to(auto const &f) & noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
return error;
|
||||
}
|
||||
@@ -252,7 +267,7 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
constexpr ox::Result<U> to(auto const&f) && noexcept {
|
||||
constexpr ox::Result<U> to(auto const &f) && noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
return error;
|
||||
}
|
||||
@@ -264,7 +279,7 @@ struct [[nodiscard]] Result {
|
||||
* @param alt
|
||||
* @return value of Result or alt
|
||||
*/
|
||||
constexpr T or_value(T &&alt) const& noexcept {
|
||||
constexpr T or_value(T &&alt) const & noexcept {
|
||||
if (error) {
|
||||
return std::move(alt);
|
||||
}
|
||||
@@ -288,7 +303,7 @@ struct [[nodiscard]] Result {
|
||||
* @param alt
|
||||
* @return value of Result or alt
|
||||
*/
|
||||
constexpr T or_value(T const&alt) const& noexcept {
|
||||
constexpr T or_value(T const &alt) const & noexcept {
|
||||
if (error) {
|
||||
return alt;
|
||||
}
|
||||
@@ -300,45 +315,54 @@ struct [[nodiscard]] Result {
|
||||
* @param alt
|
||||
* @return value of Result or alt
|
||||
*/
|
||||
constexpr T or_value(T const&alt) && noexcept {
|
||||
constexpr T or_value(T const &alt) && noexcept {
|
||||
if (error) {
|
||||
return alt;
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
constexpr Result transformError(ErrorCode const ec, CString const msg) && {
|
||||
if (error) {
|
||||
error = Error{ec, msg};
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr Error toError(Error const&e) noexcept {
|
||||
constexpr Error toError(Error const &e) noexcept {
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error toError(Result<T> const&r) noexcept {
|
||||
constexpr Error toError(Result<T> const &r) noexcept {
|
||||
return r.error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
constexpr void primitiveAssert(char const*file, int line, bool pass, char const*msg) noexcept {
|
||||
constexpr void primitiveAssert(
|
||||
bool const pass,
|
||||
char const *msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if constexpr(ox::defines::Debug) {
|
||||
if (!pass) [[unlikely]] {
|
||||
panic(file, line, msg, ox::Error(1));
|
||||
panic(ox::Error{1}, msg, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void boundsCheck(
|
||||
char const*file,
|
||||
int const line,
|
||||
size_t const i,
|
||||
size_t const sz,
|
||||
char const*msg) noexcept {
|
||||
char const *msg,
|
||||
std::source_location const &src = std::source_location::current()) noexcept {
|
||||
if constexpr(defines::CheckBounds) {
|
||||
if (i >= sz) [[unlikely]] {
|
||||
panic(file, line, msg, ox::Error{1});
|
||||
panic(ox::Error{1}, msg, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
deps/ox/src/ox/std/hashmap.hpp
vendored
15
deps/ox/src/ox/std/hashmap.hpp
vendored
@@ -106,9 +106,12 @@ constexpr bool HashMap<K, T>::operator==(HashMap const &other) const {
|
||||
if (m_keys != other.m_keys) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < m_keys.size(); ++i) {
|
||||
auto &k = m_keys[i];
|
||||
if (at(k) != other.at(k)) {
|
||||
for (auto &k : m_keys) {
|
||||
auto const a = at(k).value;
|
||||
auto const b = other.at(k).value;
|
||||
if (
|
||||
a != b && // handle one being null and other not
|
||||
(a && b && *a != *b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -196,7 +199,7 @@ constexpr std::size_t HashMap<K, T>::size() const noexcept {
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr Vector<K> const&HashMap<K, T>::keys() const noexcept {
|
||||
constexpr Vector<K> const &HashMap<K, T>::keys() const noexcept {
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
@@ -205,8 +208,8 @@ constexpr Vector<T> HashMap<K, T>::values() const noexcept {
|
||||
Vector<T> out;
|
||||
out.reserve(m_keys.size());
|
||||
for (auto const &p : m_pairs) {
|
||||
if (out) {
|
||||
out.emplace_back(p->value);
|
||||
if (p) {
|
||||
out.emplace_back(*p->value);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
4
deps/ox/src/ox/std/heapmgr.cpp
vendored
4
deps/ox/src/ox/std/heapmgr.cpp
vendored
@@ -77,7 +77,7 @@ static HeapSegment *findSegmentFor(std::size_t sz) noexcept {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
oxPanic(ox::Error(1), "malloc: could not find segment");
|
||||
ox::panic("malloc: could not find segment");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ void free(void *ptr) noexcept {
|
||||
} else if (p.segment) {
|
||||
p.segment->inUse = false;
|
||||
} else {
|
||||
oxPanic(ox::Error(1), "Bad heap free");
|
||||
ox::panic("Bad heap free");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
deps/ox/src/ox/std/ignore.hpp
vendored
2
deps/ox/src/ox/std/ignore.hpp
vendored
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace std {
|
||||
|
||||
inline constexpr struct {
|
||||
inline constexpr struct ignore_t {
|
||||
constexpr void operator=(auto&&) const noexcept {}
|
||||
} ignore;
|
||||
|
||||
|
||||
77
deps/ox/src/ox/std/istreamreader.cpp
vendored
Normal file
77
deps/ox/src/ox/std/istreamreader.cpp
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2015 - 2025 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <istream>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "reader.hpp"
|
||||
#include "istreamreader.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::ios_base::seekdir sdMap(ox::ios_base::seekdir in) noexcept {
|
||||
switch (in) {
|
||||
case ox::ios_base::beg:
|
||||
return std::ios_base::beg;
|
||||
case ox::ios_base::end:
|
||||
return std::ios_base::end;
|
||||
case ox::ios_base::cur:
|
||||
return std::ios_base::cur;
|
||||
}
|
||||
return std::ios_base::beg;
|
||||
}
|
||||
|
||||
Result<char> StreamReader::peek() const noexcept {
|
||||
try {
|
||||
if (m_strm.eof()) {
|
||||
return Error{1, "EOF"};
|
||||
}
|
||||
char c{};
|
||||
m_strm.get(c);
|
||||
if (m_strm.unget()) [[unlikely]] {
|
||||
return ox::Error{1, "Unable to unget character"};
|
||||
}
|
||||
return static_cast<char>(c);
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "peek failed");
|
||||
}
|
||||
}
|
||||
|
||||
Result<size_t> StreamReader::read(char *v, size_t cnt) noexcept {
|
||||
return static_cast<size_t>(m_strm.read(v, static_cast<std::streamsize>(cnt)).gcount());
|
||||
}
|
||||
|
||||
Error StreamReader::seekg(size_t p) noexcept {
|
||||
try {
|
||||
m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur);
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "seekg failed");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Error StreamReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
|
||||
try {
|
||||
m_strm.seekg(p, sdMap(sd));
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "seekg failed");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<size_t> StreamReader::tellg() noexcept {
|
||||
const auto sz = m_strm.tellg();
|
||||
return {static_cast<size_t>(sz), ox::Error(sz == -1)};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
33
deps/ox/src/ox/std/istreamreader.hpp
vendored
Normal file
33
deps/ox/src/ox/std/istreamreader.hpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2015 - 2025 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <istream>
|
||||
#endif
|
||||
|
||||
#include "reader.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
class StreamReader: public Reader_v {
|
||||
private:
|
||||
std::istream &m_strm;
|
||||
public:
|
||||
constexpr explicit StreamReader(std::istream &stream) noexcept: m_strm(stream) {}
|
||||
Result<char> peek() const noexcept override;
|
||||
Result<size_t> read(char *v, size_t cnt) noexcept override;
|
||||
Error seekg(size_t p) noexcept override;
|
||||
Error seekg(int64_t p, ios_base::seekdir sd) noexcept override;
|
||||
Result<size_t> tellg() noexcept override;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
12
deps/ox/src/ox/std/istring.hpp
vendored
12
deps/ox/src/ox/std/istring.hpp
vendored
@@ -72,7 +72,7 @@ class IString {
|
||||
* Returns the number of characters in this string.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t len() const noexcept;
|
||||
constexpr std::size_t size() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of bytes used for this string.
|
||||
@@ -121,7 +121,7 @@ constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr IString<size> &IString<size>::operator=(ox::StringViewCR str) noexcept {
|
||||
std::size_t strLen = str.len();
|
||||
std::size_t strLen = str.size();
|
||||
if (cap() < strLen) {
|
||||
strLen = cap();
|
||||
}
|
||||
@@ -171,7 +171,7 @@ constexpr char &IString<StrCap>::operator[](std::size_t i) noexcept {
|
||||
template<std::size_t StrCap>
|
||||
constexpr Error IString<StrCap>::append(const char *str, std::size_t strLen) noexcept {
|
||||
Error err{};
|
||||
auto const currentLen = len();
|
||||
auto const currentLen = size();
|
||||
if (cap() < currentLen + strLen) {
|
||||
strLen = cap() - currentLen;
|
||||
err = ox::Error(1, "Insufficient space for full string");
|
||||
@@ -187,7 +187,7 @@ OX_CLANG_NOWARN_END
|
||||
|
||||
template<std::size_t StrCap>
|
||||
constexpr Error IString<StrCap>::append(ox::StringView str) noexcept {
|
||||
return append(str.data(), str.len());
|
||||
return append(str.data(), str.size());
|
||||
}
|
||||
|
||||
template<std::size_t StrCap>
|
||||
@@ -207,7 +207,7 @@ constexpr const char *IString<StrCap>::c_str() const noexcept {
|
||||
|
||||
|
||||
template<std::size_t StrCap>
|
||||
constexpr std::size_t IString<StrCap>::len() const noexcept {
|
||||
constexpr std::size_t IString<StrCap>::size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ struct MaybeView<ox::IString<sz>> {
|
||||
|
||||
template<Integer_c Integer>
|
||||
[[nodiscard]]
|
||||
constexpr auto itoa(Integer v) noexcept {
|
||||
constexpr auto intToStr(Integer v) noexcept {
|
||||
constexpr auto Cap = [] {
|
||||
auto out = 0;
|
||||
switch (sizeof(Integer)) {
|
||||
|
||||
6
deps/ox/src/ox/std/iterator.hpp
vendored
6
deps/ox/src/ox/std/iterator.hpp
vendored
@@ -133,17 +133,17 @@ struct SpanIterator {
|
||||
}
|
||||
|
||||
constexpr PtrType operator->() const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
|
||||
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
|
||||
return &m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator*() const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
|
||||
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
|
||||
return m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator[](std::size_t s) const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, s, m_max, "SpanIterator access overflow");
|
||||
boundsCheck(s, m_max, "SpanIterator access overflow");
|
||||
return m_t[s];
|
||||
}
|
||||
|
||||
|
||||
3
deps/ox/src/ox/std/memory.hpp
vendored
3
deps/ox/src/ox/std/memory.hpp
vendored
@@ -213,8 +213,7 @@ class UniquePtr {
|
||||
return m_t;
|
||||
}
|
||||
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
|
||||
constexpr void reset(UniquePtr &&other = UniquePtr()) {
|
||||
auto t = m_t;
|
||||
m_t = other.release();
|
||||
Deleter()(t);
|
||||
|
||||
44
deps/ox/src/ox/std/new.hpp
vendored
44
deps/ox/src/ox/std/new.hpp
vendored
@@ -30,22 +30,60 @@ constexpr void *operator new(std::size_t, void *addr) noexcept {
|
||||
constexpr void *operator new[](std::size_t, void *addr) noexcept {
|
||||
return addr;
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr T* launder(T* __p) noexcept {
|
||||
return __builtin_launder(__p);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args, bool noex>
|
||||
void launder(T(*)(Args...) noexcept(noex)) = delete;
|
||||
template<typename T, typename... Args, bool noex>
|
||||
void launder(T(*)(Args......) noexcept(noex)) = delete;
|
||||
void launder(void*) = delete;
|
||||
void launder(void const*) = delete;
|
||||
void launder(volatile void*) = delete;
|
||||
void launder(volatile void const*) = delete;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace ox {
|
||||
|
||||
/**
|
||||
* Aliases type T in size and alignment to allow allocating space for a T
|
||||
* without running the constructor.
|
||||
*/
|
||||
template<typename T, std::size_t sz = sizeof(T)>
|
||||
struct alignas(alignof(T)) AllocAlias {
|
||||
char buff[sz];
|
||||
constexpr AllocAlias() noexcept = default;
|
||||
[[nodiscard]]
|
||||
auto data() noexcept {
|
||||
return reinterpret_cast<T*>(this);
|
||||
}
|
||||
[[nodiscard]]
|
||||
auto data() const noexcept {
|
||||
return reinterpret_cast<T const*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename U = T, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr U *make(Args &&...args) noexcept {
|
||||
#ifdef __cpp_exceptions
|
||||
try {
|
||||
return new T(ox::forward<Args>(args)...);
|
||||
} catch (std::exception const&ex) {
|
||||
oxPanic(ox::Error(1, ex.what()), ex.what());
|
||||
} catch (std::exception const &ex) {
|
||||
ox::panic(ox::Error(1, ex.what()), ex.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
|
||||
ox::panic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
|
||||
67
deps/ox/src/ox/std/reader.cpp
vendored
67
deps/ox/src/ox/std/reader.cpp
vendored
@@ -5,70 +5,3 @@
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <istream>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "reader.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::ios_base::seekdir sdMap(ox::ios_base::seekdir in) noexcept {
|
||||
switch (in) {
|
||||
case ox::ios_base::beg:
|
||||
return std::ios_base::beg;
|
||||
case ox::ios_base::end:
|
||||
return std::ios_base::end;
|
||||
case ox::ios_base::cur:
|
||||
return std::ios_base::cur;
|
||||
}
|
||||
return std::ios_base::beg;
|
||||
}
|
||||
|
||||
ox::Result<char> StreamReader::peek() const noexcept {
|
||||
try {
|
||||
char c{};
|
||||
m_strm.get(c);
|
||||
auto const ok = c != EOF;
|
||||
if (ok && m_strm.unget()) [[unlikely]] {
|
||||
return ox::Error(1, "Unable to unget character");
|
||||
}
|
||||
return {static_cast<char>(c), ox::Error(!ok, "File peek failed")};
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "peek failed");
|
||||
}
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> StreamReader::read(char *v, std::size_t cnt) noexcept {
|
||||
return static_cast<size_t>(m_strm.read(v, static_cast<std::streamsize>(cnt)).gcount());
|
||||
}
|
||||
|
||||
ox::Error StreamReader::seekg(std::size_t p) noexcept {
|
||||
try {
|
||||
m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur);
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "seekg failed");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error StreamReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
|
||||
try {
|
||||
m_strm.seekg(p, sdMap(sd));
|
||||
} catch (std::exception const&) {
|
||||
return ox::Error(1, "seekg failed");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> StreamReader::tellg() noexcept {
|
||||
const auto sz = m_strm.tellg();
|
||||
return {static_cast<std::size_t>(sz), ox::Error(sz == -1)};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
18
deps/ox/src/ox/std/reader.hpp
vendored
18
deps/ox/src/ox/std/reader.hpp
vendored
@@ -8,10 +8,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <istream>
|
||||
#endif
|
||||
|
||||
#include "concepts.hpp"
|
||||
#include "error.hpp"
|
||||
#include "types.hpp"
|
||||
@@ -63,18 +59,4 @@ class ReaderT: public Reader_v {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
class StreamReader: public Reader_v {
|
||||
private:
|
||||
std::istream &m_strm;
|
||||
public:
|
||||
constexpr explicit StreamReader(std::istream &stream) noexcept: m_strm(stream) {}
|
||||
ox::Result<char> peek() const noexcept override;
|
||||
ox::Result<std::size_t> read(char *v, std::size_t cnt) noexcept override;
|
||||
ox::Error seekg(std::size_t p) noexcept override;
|
||||
ox::Error seekg(int64_t p, ios_base::seekdir sd) noexcept override;
|
||||
ox::Result<std::size_t> tellg() noexcept override;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
37
deps/ox/src/ox/std/serialize.hpp
vendored
37
deps/ox/src/ox/std/serialize.hpp
vendored
@@ -18,7 +18,7 @@ namespace ox {
|
||||
|
||||
template<typename PlatSpec>
|
||||
struct VectorMemMap {
|
||||
const std::size_t smallVecSize = 0; // not a map value
|
||||
size_t const smallVecSize = 0; // not a map value
|
||||
typename PlatSpec::size_t size = 0;
|
||||
typename PlatSpec::size_t cap = 0;
|
||||
typename PlatSpec::PtrType items = 0;
|
||||
@@ -26,11 +26,11 @@ struct VectorMemMap {
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const VectorMemMap<PlatSpec> *t) noexcept {
|
||||
constexpr auto padding = [](std::size_t size, std::size_t al) {
|
||||
constexpr auto sizeOf(VectorMemMap<PlatSpec> const *t) noexcept {
|
||||
constexpr auto padding = [](size_t const size, size_t const al) {
|
||||
return size % al;
|
||||
};
|
||||
std::size_t size = 0;
|
||||
size_t size = 0;
|
||||
if (t->smallVecSize) {
|
||||
size += t->smallVecSize;
|
||||
size += padding(size, PlatSpec::alignOf(t->size));
|
||||
@@ -43,17 +43,17 @@ constexpr auto sizeOf(const VectorMemMap<PlatSpec> *t) noexcept {
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallVecSize = 0>
|
||||
template<typename PlatSpec, size_t SmallVecSize = 0>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const VectorMemMap<PlatSpec>&) noexcept {
|
||||
const typename PlatSpec::size_t i = 0;
|
||||
constexpr auto alignOf(VectorMemMap<PlatSpec> const&) noexcept {
|
||||
typename PlatSpec::size_t const i = 0;
|
||||
return PlatSpec::alignOf(i);
|
||||
}
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
constexpr ox::Error pad(Writer_c auto &w, const T *v) noexcept {
|
||||
const auto a = PlatSpec::alignOf(*v);
|
||||
const auto excess = w.tellp() % a;
|
||||
constexpr Error pad(Writer_c auto &w, T const *v) noexcept {
|
||||
auto const a = PlatSpec::alignOf(*v);
|
||||
auto const excess = w.tellp() % a;
|
||||
if (excess) {
|
||||
return w.write(nullptr, a - excess);
|
||||
} else {
|
||||
@@ -62,7 +62,7 @@ constexpr ox::Error pad(Writer_c auto &w, const T *v) noexcept {
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error serialize(Writer_c auto &w, const VectorMemMap<PlatSpec> &vm) noexcept {
|
||||
constexpr Error serialize(Writer_c auto &w, VectorMemMap<PlatSpec> const &vm) noexcept {
|
||||
OX_RETURN_ERROR(w.write(nullptr, vm.smallVecSize));
|
||||
OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.size)));
|
||||
OX_RETURN_ERROR(serialize(w, PlatSpec::correctEndianness(vm.cap)));
|
||||
@@ -70,21 +70,20 @@ constexpr ox::Error serialize(Writer_c auto &w, const VectorMemMap<PlatSpec> &vm
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error serialize(Writer_c auto &w, T val) noexcept requires(is_integer_v<T>) {
|
||||
ox::Array<char, sizeof(T)> tmp;
|
||||
for (auto i = 0u; i < sizeof(T); ++i) {
|
||||
constexpr Error serialize(Writer_c auto &w, Integral_c auto val) noexcept {
|
||||
Array<char, sizeof(val)> tmp;
|
||||
for (auto i = 0u; i < sizeof(val); ++i) {
|
||||
tmp[i] = static_cast<char>((val >> i * 8) & 255);
|
||||
}
|
||||
return w.write(tmp.data(), tmp.size());
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
|
||||
ox::Array<char, sizeof(T)> out = {};
|
||||
constexpr Result<Array<char, sizeof(T)>> serialize(T const &in) noexcept {
|
||||
Array<char, sizeof(T)> out = {};
|
||||
CharBuffWriter w(out);
|
||||
OX_RETURN_ERROR(serialize(w, in));
|
||||
return out;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
53
deps/ox/src/ox/std/span.hpp
vendored
53
deps/ox/src/ox/std/span.hpp
vendored
@@ -8,6 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include(<array>)
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
#include "array.hpp"
|
||||
#include "bit.hpp"
|
||||
#include "def.hpp"
|
||||
@@ -35,6 +39,20 @@ class Span {
|
||||
|
||||
constexpr Span() noexcept = default;
|
||||
|
||||
#if __has_include(<array>)
|
||||
template<std::size_t sz>
|
||||
constexpr Span(std::array<T, sz> &a) noexcept:
|
||||
m_items(a.data()),
|
||||
m_size(a.size()) {
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr Span(std::array<ox::remove_const_t<T>, sz> const &a) noexcept:
|
||||
m_items(a.data()),
|
||||
m_size(a.size()) {
|
||||
}
|
||||
#endif
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr Span(ox::Array<T, sz> &a) noexcept:
|
||||
m_items(a.data()),
|
||||
@@ -42,7 +60,7 @@ class Span {
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const&a) noexcept:
|
||||
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const &a) noexcept:
|
||||
m_items(a.data()),
|
||||
m_size(a.size()) {
|
||||
}
|
||||
@@ -54,7 +72,7 @@ class Span {
|
||||
}
|
||||
|
||||
template<std::size_t sz, typename Allocator>
|
||||
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const&v) noexcept:
|
||||
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const &v) noexcept:
|
||||
m_items(v.data()),
|
||||
m_size(v.size()) {
|
||||
}
|
||||
@@ -128,28 +146,41 @@ class Span {
|
||||
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
|
||||
}
|
||||
|
||||
constexpr T &operator[](std::size_t i) noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
constexpr T const&operator[](std::size_t i) const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
|
||||
constexpr T &operator[](std::size_t i) const noexcept {
|
||||
boundsCheck(i, size(), "Span access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
constexpr Span operator+(size_t i) const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
|
||||
boundsCheck(i, size(), "Span access overflow");
|
||||
return {m_items + i, m_size - i};
|
||||
}
|
||||
|
||||
constexpr Span operator+=(size_t i) noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
|
||||
boundsCheck(i, size(), "Span access overflow");
|
||||
m_items += i;
|
||||
m_size -= i;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Span operator++(int) noexcept {
|
||||
++m_items;
|
||||
--m_size;
|
||||
if (!m_size) [[unlikely]] {
|
||||
m_items = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Span operator++() noexcept {
|
||||
++m_items;
|
||||
--m_size;
|
||||
if (!m_size) [[unlikely]] {
|
||||
m_items = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto data() const noexcept {
|
||||
return m_items;
|
||||
|
||||
58
deps/ox/src/ox/std/strconv.hpp
vendored
58
deps/ox/src/ox/std/strconv.hpp
vendored
@@ -17,35 +17,41 @@
|
||||
namespace ox {
|
||||
|
||||
template<Integer_c Integer>
|
||||
constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
OX_RETURN_ERROR(writer.put('-'));
|
||||
constexpr ox::Error writeItoa(Integer const v, ox::Writer_c auto &writer) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
OX_RETURN_ERROR(writer.put('-'));
|
||||
val = ~val + 1;
|
||||
}
|
||||
if constexpr(sizeof(v) == 8 && !ox::is_signed_v<Integer>) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (digit) {
|
||||
digit -= 10;
|
||||
OX_RETURN_ERROR(writer.put('1'));
|
||||
OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
|
||||
++it;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 0 is a special case
|
||||
OX_RETURN_ERROR(writer.put('0'));
|
||||
}
|
||||
return {};
|
||||
while (mod) {
|
||||
auto const digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 0 is a special case
|
||||
OX_RETURN_ERROR(writer.put('0'));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
60
deps/ox/src/ox/std/string.hpp
vendored
60
deps/ox/src/ox/std/string.hpp
vendored
@@ -28,7 +28,7 @@ OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
namespace ox {
|
||||
|
||||
template<typename Integer>
|
||||
constexpr ox::IString<21> itoa(Integer v) noexcept;
|
||||
constexpr ox::IString<21> intToStr(Integer v) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
class BasicString {
|
||||
@@ -139,7 +139,7 @@ class BasicString {
|
||||
|
||||
constexpr BasicString &operator+=(Integer_c auto i) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(StringView src) noexcept;
|
||||
constexpr BasicString &operator+=(StringViewCR src) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(BasicString const&src) noexcept;
|
||||
|
||||
@@ -176,17 +176,17 @@ class BasicString {
|
||||
constexpr char &operator[](std::size_t i) noexcept;
|
||||
|
||||
constexpr Error append(const char *str, std::size_t strLen) noexcept {
|
||||
auto currentLen = len();
|
||||
auto currentLen = size();
|
||||
m_buff.resize(m_buff.size() + strLen);
|
||||
ox::listcpy(&m_buff[currentLen], str, strLen);
|
||||
// make sure last element is a null terminator
|
||||
m_buff[currentLen + strLen] = 0;
|
||||
// this can't fail, but it returns an Error to match BString::append
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr Error append(ox::StringView sv) noexcept {
|
||||
return append(sv.data(), sv.len());
|
||||
constexpr Error append(StringViewCR sv) noexcept {
|
||||
return append(sv.data(), sv.size());
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -213,22 +213,22 @@ class BasicString {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return static_cast<const char*>(m_buff.data());
|
||||
return m_buff.data();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline explicit operator const char*() const {
|
||||
constexpr explicit operator const char*() const {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
#if __has_include(<string>)
|
||||
[[nodiscard]]
|
||||
inline std::string toStdString() const {
|
||||
std::string toStdString() const {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline explicit operator std::string() const {
|
||||
explicit operator std::string() const {
|
||||
return c_str();
|
||||
}
|
||||
#endif
|
||||
@@ -237,7 +237,7 @@ class BasicString {
|
||||
* Returns the number of characters in this string.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t len() const noexcept;
|
||||
constexpr std::size_t size() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of bytes used for this string.
|
||||
@@ -277,7 +277,7 @@ constexpr BasicString<SmallStringSize_v>::BasicString(const char *str, std::size
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(StringLiteral const&str) noexcept:
|
||||
BasicString(StringView{str.data(), str.len()}) {
|
||||
BasicString(StringView{str.data(), str.size()}) {
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
@@ -317,13 +317,13 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int64_t i) noexcept {
|
||||
set(ox::itoa(i));
|
||||
set(ox::intToStr(i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(uint64_t i) noexcept {
|
||||
set(ox::itoa(i));
|
||||
set(ox::intToStr(i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -371,12 +371,12 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(Integer_c auto i) noexcept {
|
||||
auto const str = ox::itoa(i);
|
||||
auto const str = ox::intToStr(i);
|
||||
return this->operator+=(str.c_str());
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(StringView s) noexcept {
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(StringViewCR s) noexcept {
|
||||
std::size_t strLen = s.bytes();
|
||||
std::ignore = append(s.data(), strLen);
|
||||
return *this;
|
||||
@@ -384,14 +384,14 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(BasicString const&src) noexcept {
|
||||
std::ignore = append(src.c_str(), src.len());
|
||||
std::ignore = append(src.c_str(), src.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const char *str) const noexcept {
|
||||
const std::size_t strLen = ox::strlen(str);
|
||||
const auto currentLen = len();
|
||||
const auto currentLen = size();
|
||||
BasicString<SmallStringSize_v> cpy;
|
||||
cpy.m_buff.resize(m_buff.size() + strLen);
|
||||
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
|
||||
@@ -414,14 +414,14 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(Integer_c auto i) const noexcept {
|
||||
auto const str = ox::itoa(i);
|
||||
auto const str = ox::intToStr(i);
|
||||
return *this + str;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(StringViewCR src) const noexcept {
|
||||
const std::size_t strLen = src.len();
|
||||
const auto currentLen = len();
|
||||
const std::size_t strLen = src.size();
|
||||
const auto currentLen = size();
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
cpy.m_buff.resize(m_buff.size() + strLen);
|
||||
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
|
||||
@@ -432,8 +432,8 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(BasicString const&src) const noexcept {
|
||||
const std::size_t strLen = src.len();
|
||||
const auto currentLen = len();
|
||||
const std::size_t strLen = src.size();
|
||||
const auto currentLen = size();
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
cpy.m_buff.resize(m_buff.size() + strLen);
|
||||
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
|
||||
@@ -456,7 +456,7 @@ constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) con
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(OxString_c auto const&other) const noexcept {
|
||||
return ox::StringView(*this) == ox::StringView(other);
|
||||
return StringView(*this) == StringView(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
@@ -521,7 +521,7 @@ constexpr std::size_t BasicString<SmallStringSize_v>::bytes() const noexcept {
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
|
||||
constexpr std::size_t BasicString<SmallStringSize_v>::size() const noexcept {
|
||||
return m_buff.size() - 1;
|
||||
}
|
||||
|
||||
@@ -548,28 +548,28 @@ using StringCR = String const&;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::String toString(ox::StringViewCR sv) noexcept {
|
||||
constexpr String toString(StringViewCR sv) noexcept {
|
||||
return ox::String(sv);
|
||||
}
|
||||
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
|
||||
constexpr auto sizeOf(BasicString<SmallStringSize_v> const*) noexcept {
|
||||
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
|
||||
return sizeOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const ox::BasicString<SmallStringSize_v>&) noexcept {
|
||||
constexpr auto alignOf(BasicString<SmallStringSize_v> const&) noexcept {
|
||||
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
|
||||
return alignOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<size_t sz>
|
||||
struct MaybeView<ox::BasicString<sz>> {
|
||||
using type = ox::StringView;
|
||||
struct MaybeView<BasicString<sz>> {
|
||||
using type = StringView;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
23
deps/ox/src/ox/std/stringliteral.hpp
vendored
23
deps/ox/src/ox/std/stringliteral.hpp
vendored
@@ -16,33 +16,28 @@ namespace ox {
|
||||
* StringLiteral is used for functions that want to ensure that they are taking
|
||||
* string literals, and not strings outside of the data section of the program
|
||||
* that might get deleted.
|
||||
* This type cannot force you to use it correctly, so don't give it something
|
||||
* that is not a literal.
|
||||
* If you do this:
|
||||
* StringLiteral(str.c_str())
|
||||
* the resulting segfault is on you.
|
||||
*/
|
||||
class StringLiteral: public detail::BaseStringView {
|
||||
public:
|
||||
constexpr StringLiteral() noexcept = default;
|
||||
|
||||
constexpr StringLiteral(StringLiteral const&sv) noexcept = default;
|
||||
constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
|
||||
|
||||
constexpr explicit StringLiteral(std::nullptr_t) noexcept {}
|
||||
consteval StringLiteral(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr explicit StringLiteral(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
|
||||
consteval StringLiteral(char const *str, std::size_t const len) noexcept: BaseStringView{str, len} {}
|
||||
|
||||
constexpr explicit StringLiteral(char const *str) noexcept: StringLiteral(str, ox::strlen(str)) {}
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
consteval StringLiteral(char const *str) noexcept: StringLiteral{str, ox::strlen(str)} {}
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
|
||||
constexpr StringLiteral &operator=(StringLiteral const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
}
|
||||
constexpr StringLiteral &operator=(StringLiteral const &other) noexcept {
|
||||
set(other.data(), other.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
constexpr char const *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
|
||||
3
deps/ox/src/ox/std/stringparam.hpp
vendored
3
deps/ox/src/ox/std/stringparam.hpp
vendored
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cstringview.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
namespace ox {
|
||||
@@ -20,6 +21,8 @@ class StringParam {
|
||||
constexpr StringParam(StringParam &&o) noexcept: m_value{std::move(o.m_value)} {}
|
||||
constexpr StringParam(char const*value) noexcept: m_value{value} {}
|
||||
constexpr StringParam(detail::BaseStringView const&value) noexcept: m_value{value} {}
|
||||
template<size_t sz>
|
||||
constexpr StringParam(ox::IString<sz> const&value) noexcept: m_value{value} {}
|
||||
constexpr StringParam(ox::String const&value) noexcept: m_value{value} {}
|
||||
constexpr StringParam(ox::String &&value) noexcept: m_value{std::move(value)} {}
|
||||
constexpr operator ox::String() && noexcept { return std::move(m_value); }
|
||||
|
||||
31
deps/ox/src/ox/std/stringview.hpp
vendored
31
deps/ox/src/ox/std/stringview.hpp
vendored
@@ -40,10 +40,10 @@ class StringView: public detail::BaseStringView {
|
||||
constexpr StringView(BaseStringView const&str) noexcept: BaseStringView(str.data(), str.bytes()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.size()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr StringView(const IString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
constexpr StringView(const IString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.size()) {}
|
||||
|
||||
constexpr StringView(std::nullptr_t) noexcept {}
|
||||
|
||||
@@ -53,24 +53,24 @@ class StringView: public detail::BaseStringView {
|
||||
|
||||
constexpr auto &operator=(StringView const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
set(other.data(), other.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using StringViewCR = const StringView&;
|
||||
using StringViewCR = StringView const&;
|
||||
|
||||
constexpr auto operator==(StringViewCR s1, StringViewCR s2) noexcept {
|
||||
if (s2.len() != s1.len()) {
|
||||
if (s2.size() != s1.size()) {
|
||||
return false;
|
||||
}
|
||||
return ox::strncmp(s1.data(), s2.data(), s1.len()) == 0;
|
||||
return ox::strncmp(s1.data(), s2.data(), s1.size()) == 0;
|
||||
}
|
||||
|
||||
constexpr auto operator<=>(StringViewCR s1, StringViewCR s2) noexcept {
|
||||
const auto maxLen = ox::min(s1.len(), s2.len());
|
||||
const auto maxLen = ox::min(s1.size(), s2.size());
|
||||
const auto a = &s1.front();
|
||||
const auto b = &s2.front();
|
||||
for (std::size_t i = 0; i < maxLen && (a[i] || b[i]); ++i) {
|
||||
@@ -80,16 +80,16 @@ constexpr auto operator<=>(StringViewCR s1, StringViewCR s2) noexcept {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (s1.len() > s2.len()) {
|
||||
if (s1.size() > s2.size()) {
|
||||
return 1;
|
||||
} else if (s1.len() < s2.len()) {
|
||||
} else if (s1.size() < s2.size()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto write(Writer_c auto &writer, ox::StringViewCR sv) noexcept {
|
||||
constexpr auto write(Writer_c auto &writer, StringViewCR sv) noexcept {
|
||||
return writer.write(sv.data(), sv.bytes());
|
||||
}
|
||||
|
||||
@@ -100,19 +100,24 @@ constexpr auto toStdStringView(StringViewCR sv) noexcept {
|
||||
#endif
|
||||
|
||||
|
||||
constexpr ox::Result<int> atoi(ox::StringViewCR str) noexcept {
|
||||
constexpr ox::Result<int> strToInt(StringViewCR str) noexcept {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
int total = 0;
|
||||
int multiplier = 1;
|
||||
for (auto i = static_cast<int64_t>(str.len()) - 1; i != -1; --i) {
|
||||
if (str.size() == 0) [[unlikely]] {
|
||||
return Error{1, "Empty string passed to strToInt"};
|
||||
}
|
||||
for (auto i = static_cast<int64_t>(str.size()) - 1; i != -1; --i) {
|
||||
auto s = static_cast<std::size_t>(i);
|
||||
if (str[s] >= '0' && str[s] <= '9') {
|
||||
total += (str[s] - '0') * multiplier;
|
||||
multiplier *= 10;
|
||||
} else {
|
||||
return ox::Error(1);
|
||||
return ox::Error{1};
|
||||
}
|
||||
}
|
||||
return total;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
deps/ox/src/ox/std/strops.cpp
vendored
27
deps/ox/src/ox/std/strops.cpp
vendored
@@ -7,8 +7,10 @@
|
||||
*/
|
||||
|
||||
#include "def.hpp"
|
||||
#include "span.hpp"
|
||||
#include "strops.hpp"
|
||||
|
||||
|
||||
static_assert(ox::strcmp("asdf", "hijk") < 0, "asdf < hijk");
|
||||
static_assert(ox::strcmp("hijk", "asdf") > 0, "hijk > asdf");
|
||||
static_assert(ox::strcmp("resize", "read") > 0, "resize > read");
|
||||
@@ -17,27 +19,28 @@ static_assert(ox::strcmp("resize", "resize") == 0, "resize == resize");
|
||||
static_assert(ox::strcmp("", "") == 0, "\"\" == \"\"");
|
||||
|
||||
static_assert([] {
|
||||
auto testStr = "asdf";
|
||||
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
return ox::strchr(testStr, 0, 4) == &testStr[4];
|
||||
OX_CLANG_NOWARN_END
|
||||
auto constexpr testStr = ox::Span{"asdf"};
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
return ox::strchr(testStr.data(), 0, 4) == &testStr[4];
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}(), "ox::strchr 0");
|
||||
|
||||
static_assert([] {
|
||||
int retval = 0;
|
||||
auto testStr = "aaaa";
|
||||
auto constexpr testStr = "aaaa";
|
||||
// test the const and non-const versions of ox::lastIndexOf
|
||||
retval |= !(ox::lastIndexOf(const_cast<char*>(testStr), 'a', ox::strlen(testStr)) == 3);
|
||||
retval |= !(ox::lastIndexOf(testStr, 'a', ox::strlen(testStr)) == 3);
|
||||
return retval == 0;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
return ox::lastIndexOf(testStr, 'a', ox::strlen(testStr)) == 3;
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}(), "ox::lastIndexOf aaaa a");
|
||||
|
||||
#ifndef OX_USE_STDLIB
|
||||
|
||||
extern "C"
|
||||
std::size_t strlen(const char *str) {
|
||||
std::size_t len = 0;
|
||||
for (; str[len]; len++);
|
||||
size_t strlen(const char *str) {
|
||||
size_t len{};
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
while (str[len]) { ++len; }
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
48
deps/ox/src/ox/std/strops.hpp
vendored
48
deps/ox/src/ox/std/strops.hpp
vendored
@@ -21,37 +21,47 @@ OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
namespace ox {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexcept {
|
||||
if (str.len() >= pos) {
|
||||
return {&str[pos], str.len() - pos};
|
||||
constexpr StringView substr(StringViewCR str, std::size_t const pos) noexcept {
|
||||
if (str.size() >= pos) {
|
||||
return {&str[pos], str.size() - pos};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std::size_t end) noexcept {
|
||||
if (str.len() >= start && end >= start) {
|
||||
constexpr StringView substr(StringViewCR str, std::size_t const start, std::size_t const end) noexcept {
|
||||
if (str.size() >= start && end >= start) {
|
||||
return {&str[start], end - start};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(StringViewCR base, char const beginning) noexcept {
|
||||
return base.size() && base[0] == beginning;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(StringViewCR base, char const ending) noexcept {
|
||||
return base.size() && base[base.size() - 1] == ending;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(StringViewCR base, StringViewCR beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox::strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
const auto beginningLen = ox::min(beginning.size(), base.size());
|
||||
return base.size() >= beginning.size() && ox::strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(StringViewCR base, StringViewCR ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return base.len() >= endingLen && ox::strcmp(base.data() + (base.len() - endingLen), ending) == 0;
|
||||
const auto endingLen = ending.size();
|
||||
return base.size() >= endingLen && ox::strcmp(base.data() + (base.size() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t find(StringViewCR str, char search) noexcept {
|
||||
constexpr std::size_t find(StringViewCR str, char const search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
for (; i < str.size(); ++i) {
|
||||
if (str[i] == search) {
|
||||
break;
|
||||
}
|
||||
@@ -62,7 +72,7 @@ constexpr std::size_t find(StringViewCR str, char search) noexcept {
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t find(StringViewCR str, StringViewCR search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
for (; i < str.size(); ++i) {
|
||||
if (beginsWith(substr(str, i), search)) {
|
||||
break;
|
||||
}
|
||||
@@ -72,14 +82,14 @@ constexpr std::size_t find(StringViewCR str, StringViewCR search) noexcept {
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
[[nodiscard]]
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, char del) noexcept {
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, char const del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](StringViewCR current, char del) {
|
||||
return substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
for (auto current = str; current.size(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
if (const auto s = substr(current, 0, next); s.size()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
@@ -92,11 +102,11 @@ template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringViewCR del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](StringViewCR current, StringViewCR del) {
|
||||
return substr(current, find(current, del) + del.len());
|
||||
return substr(current, find(current, del) + del.size());
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
for (auto current = str; current.size(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
if (const auto s = substr(current, 0, next); s.size()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
@@ -105,7 +115,7 @@ constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringView
|
||||
}
|
||||
|
||||
[[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 const character) noexcept {
|
||||
ox::Result<std::size_t> retval = ox::Error(1, "Character not found");
|
||||
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
|
||||
if (str[static_cast<std::size_t>(i)] == character) {
|
||||
|
||||
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@@ -28,3 +28,4 @@ add_test("[ox/std] FromHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "FromHex")
|
||||
add_test("[ox/std] ToHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ToHex")
|
||||
add_test("[ox/std] UUID" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID")
|
||||
add_test("[ox/std] UUID::generate" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID::generate")
|
||||
add_test("[ox/std] intToStr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "intToStr")
|
||||
|
||||
299
deps/ox/src/ox/std/test/tests.cpp
vendored
299
deps/ox/src/ox/std/test/tests.cpp
vendored
@@ -30,7 +30,7 @@ static uint64_t steadyNowMs() {
|
||||
}
|
||||
|
||||
template<typename Map = ox::SmallMap<ox::String, ox::UUID>>
|
||||
uint64_t timeMapStrToUuid(int elemCnt, int lookups, uint64_t seed = 4321) noexcept {
|
||||
uint64_t timeMapStrToUuid(int const elemCnt, int const lookups, uint64_t seed = 4321) noexcept {
|
||||
ox::UUID::seedGenerator({1234, seed});
|
||||
Map map;
|
||||
// setup test map
|
||||
@@ -43,15 +43,16 @@ uint64_t timeMapStrToUuid(int elemCnt, int lookups, uint64_t seed = 4321) noexce
|
||||
// start
|
||||
auto const startTime = steadyNowMs();
|
||||
for (int i = 0; i < lookups; ++i) {
|
||||
auto const&k = keys[rand.gen() % keys.size()];
|
||||
auto const &k = keys[rand.gen() % keys.size()];
|
||||
map[k];
|
||||
oxExpect(map[k], ox::UUID::fromString(k).unwrap());
|
||||
ox::expect(map[k], ox::UUID::fromString(k).unwrap());
|
||||
}
|
||||
return steadyNowMs() - startTime;
|
||||
}
|
||||
|
||||
template<typename Map = ox::SmallMap<ox::UUID, ox::String>>
|
||||
uint64_t timeMapUuidToStr(int elemCnt, int lookups, uint64_t seed = 4321) noexcept {
|
||||
[[nodiscard]]
|
||||
uint64_t timeMapUuidToStr(int const elemCnt, int const lookups, uint64_t seed = 4321) noexcept {
|
||||
ox::UUID::seedGenerator({1234, seed});
|
||||
Map map;
|
||||
// setup test map
|
||||
@@ -64,13 +65,13 @@ uint64_t timeMapUuidToStr(int elemCnt, int lookups, uint64_t seed = 4321) noexce
|
||||
// start
|
||||
auto const startTime = steadyNowMs();
|
||||
for (int i = 0; i < lookups; ++i) {
|
||||
auto const&k = keys[rand.gen() % keys.size()];
|
||||
oxExpect(map[k], k.toString());
|
||||
auto const &k = keys[rand.gen() % keys.size()];
|
||||
ox::expect(map[k], k.toString());
|
||||
}
|
||||
return steadyNowMs() - startTime;
|
||||
}
|
||||
|
||||
static ox::Error compareMaps(int lookupCnt = 1'000'000) {
|
||||
static ox::Error compareMaps(int const lookupCnt = 1'000'000) {
|
||||
auto const seed = steadyNowMs();
|
||||
uint64_t hashTime{};
|
||||
uint64_t smallTime{};
|
||||
@@ -126,7 +127,7 @@ OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
OX_CLANG_NOWARN_END
|
||||
ox::heapmgr::free(a1);
|
||||
ox::heapmgr::free(a2);
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -135,16 +136,17 @@ OX_CLANG_NOWARN_END
|
||||
ox::Array<char, 10> buff;
|
||||
ox::CharBuffWriter bw(buff);
|
||||
oxAssert(ox::writeItoa(5, bw), "ox::writeItoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("5"));
|
||||
ox::expect(ox::StringView(buff.data()), ox::StringView("5"));
|
||||
OX_RETURN_ERROR(bw.seekp(0));
|
||||
oxAssert(ox::writeItoa(50, bw), "ox::writeItoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("50"));
|
||||
ox::expect(ox::StringView(buff.data()), ox::StringView("50"));
|
||||
OX_RETURN_ERROR(bw.seekp(0));
|
||||
oxAssert(ox::writeItoa(500, bw), "ox::writeItoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("500"));
|
||||
ox::expect(ox::StringView(buff.data()), ox::StringView("500"));
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
{
|
||||
"ABCDEFG != HIJKLMN",
|
||||
[]() {
|
||||
@@ -169,6 +171,7 @@ OX_CLANG_NOWARN_END
|
||||
return ox::Error(ox::memcmp("ABCDEFGHI", "ABCDEFG", 7) != 0);
|
||||
}
|
||||
},
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
{
|
||||
"IString",
|
||||
[]() {
|
||||
@@ -181,8 +184,8 @@ OX_CLANG_NOWARN_END
|
||||
s = "asdf";
|
||||
oxAssert(s == "asdf", "String assign broken");
|
||||
oxAssert(s != "aoeu", "String assign broken");
|
||||
oxAssert(s.len() == 4, "String assign broken");
|
||||
return ox::Error(0);
|
||||
oxAssert(s.size() == 4, "String assign broken");
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -212,11 +215,11 @@ OX_CLANG_NOWARN_END
|
||||
oxAssert(ox::StringView("Write") != ox::String(""), "String / StringView comparison broken");
|
||||
oxAssert(ox::String("Write") != ox::StringView(""), "String / StringView comparison broken");
|
||||
oxAssert(ox::String("Write") == ox::StringView("Write"), "String / StringView comparison broken");
|
||||
oxExpect(ox::String("asdf").substr(1, 3), "sd");
|
||||
ox::expect(ox::String("asdf").substr(1, 3), "sd");
|
||||
oxAssert(
|
||||
ox::String(ox::StringView("Write")) == ox::StringView("Write"),
|
||||
"String / StringView comparison broken");
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -225,16 +228,16 @@ OX_CLANG_NOWARN_END
|
||||
ox::Vector<int> v;
|
||||
oxAssert(v.size() == 0, "Initial Vector size not 0");
|
||||
oxAssert(v.empty(), "Vector::empty() is broken");
|
||||
auto insertTest = [&v](int val, std::size_t size) {
|
||||
auto insertTest = [&v](int const val, std::size_t const size) {
|
||||
v.push_back(val);
|
||||
OX_RETURN_ERROR(ox::Error(v.size() != size, "Vector size incorrect"));
|
||||
OX_RETURN_ERROR(ox::Error(v[v.size() - 1] != val, "Vector value wrong"));
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
};
|
||||
oxAssert(insertTest(42, 1), "Vector insertion failed");
|
||||
oxAssert(insertTest(100, 2), "Vector insertion failed");
|
||||
oxAssert(insertTest(102, 3), "Vector insertion failed");
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -247,9 +250,9 @@ OX_CLANG_NOWARN_END
|
||||
v.emplace_back("aoeu");
|
||||
auto const origData = v.data();
|
||||
v.shrink_to_fit();
|
||||
oxExpect(v[0], "asdf");
|
||||
oxExpect(v[1], "aoeu");
|
||||
oxExpect(v.capacity(), 2u);
|
||||
ox::expect(v[0], "asdf");
|
||||
ox::expect(v[1], "aoeu");
|
||||
ox::expect(v.capacity(), 2u);
|
||||
oxAssert(origData != v.data(), "shrink_to_fit did not create a new allocation");
|
||||
}
|
||||
{
|
||||
@@ -259,9 +262,9 @@ OX_CLANG_NOWARN_END
|
||||
v.emplace_back("aoeu");
|
||||
auto const origData = v.data();
|
||||
v.shrink_to_fit();
|
||||
oxExpect(v[0], "asdf");
|
||||
oxExpect(v[1], "aoeu");
|
||||
oxExpect(v.capacity(), 2u);
|
||||
ox::expect(v[0], "asdf");
|
||||
ox::expect(v[1], "aoeu");
|
||||
ox::expect(v.capacity(), 2u);
|
||||
oxAssert(origData == v.data(), "shrink_to_fit inappropriately created a new allocation");
|
||||
}
|
||||
return ox::Error{};
|
||||
@@ -271,13 +274,13 @@ OX_CLANG_NOWARN_END
|
||||
"findIdx",
|
||||
[] {
|
||||
ox::Vector<ox::IString<8>> const v {"zero", "one", "two", "three", "four"};
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "zero").or_value(5), 0u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "one").or_value(5), 1u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "two").or_value(5), 2u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "three").or_value(5), 3u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "four").or_value(5), 4u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "five").or_value(5), 5u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "six").or_value(6), 6u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "zero").or_value(5), 0u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "one").or_value(5), 1u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "two").or_value(5), 2u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "three").or_value(5), 3u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "four").or_value(5), 4u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "five").or_value(5), 5u);
|
||||
ox::expect(ox::findIdx(v.begin(), v.end(), "six").or_value(6), 6u);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
@@ -286,19 +289,19 @@ OX_CLANG_NOWARN_END
|
||||
[] {
|
||||
ox::SmallMap<ox::String, ox::String> map;
|
||||
map["asdf"] = "aoeu";
|
||||
oxExpect(map["asdf"], "aoeu");
|
||||
oxExpect(map.size(), 1u);
|
||||
oxExpect(map["aoeu"], "");
|
||||
oxExpect(map.size(), 2u);
|
||||
ox::expect(map["asdf"], "aoeu");
|
||||
ox::expect(map.size(), 1u);
|
||||
ox::expect(map["aoeu"], "");
|
||||
ox::expect(map.size(), 2u);
|
||||
ox::SmallMap<ox::String, ox::String> cmap;
|
||||
cmap["asdf"] = "aoeu";
|
||||
auto constexpr constTest = [](ox::SmallMap<ox::String, ox::String> const&map) {
|
||||
auto constexpr constTest = [](ox::SmallMap<ox::String, ox::String> const &map) {
|
||||
OX_REQUIRE(asdf, map.at("asdf"));
|
||||
oxExpect(*asdf, "aoeu");
|
||||
oxExpect(map.size(), 1u);
|
||||
ox::expect(*asdf, "aoeu");
|
||||
ox::expect(map.size(), 1u);
|
||||
auto const aoeu = map.at("aoeu");
|
||||
oxExpect(aoeu.ok(), false);
|
||||
oxExpect(map.size(), 1u);
|
||||
ox::expect(aoeu.ok(), false);
|
||||
ox::expect(map.size(), 1u);
|
||||
return ox::Error{};
|
||||
};
|
||||
return constTest(cmap);
|
||||
@@ -317,7 +320,7 @@ OX_CLANG_NOWARN_END
|
||||
ii[5] = 100;
|
||||
oxAssert(ii[4] == 42, "4 != 42");
|
||||
oxAssert(ii[5] == 100, "5 != 100");
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -332,18 +335,17 @@ OX_CLANG_NOWARN_END
|
||||
oxAssert(!si.contains("asdf"), "wrongly contains asdf");
|
||||
oxAssert(si.contains("aoeu"), "does not contains aoeu");
|
||||
oxAssert(!si.at("asdf").ok(), "asdf != 0");
|
||||
oxExpect(si["asdf"], 0);
|
||||
ox::expect(si["asdf"], 0);
|
||||
oxAssert(si["aoeu"] == 100, "aoeu != 100");
|
||||
auto si2 = si;
|
||||
oxDebugf("{}", si2["asdf"]);
|
||||
oxExpect(si2["asdf"], 0);
|
||||
ox::expect(si2["asdf"], 0);
|
||||
oxAssert(si2["aoeu"] == 100, "aoeu != 100");
|
||||
ox::HashMap<int, int> ii;
|
||||
ii[4] = 42;
|
||||
ii[5] = 100;
|
||||
oxAssert(ii[4] == 42, "4 != 42");
|
||||
oxAssert(ii[5] == 100, "5 != 100");
|
||||
return ox::Error(0);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -376,15 +378,15 @@ OX_CLANG_NOWARN_END
|
||||
static_cast<int>(actual[1]),
|
||||
static_cast<int>(actual[2]),
|
||||
static_cast<int>(actual[3]));
|
||||
oxExpect(ox::serialize<int32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
oxExpect(ox::serialize<int32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<int32_t>(257).unwrap(), BA({1, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(257).unwrap(), BA({1, 1, 0, 0}));
|
||||
ox::expect(ox::serialize<int32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
ox::expect(ox::serialize<int32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
ox::expect(ox::serialize<int32_t>(257).unwrap(), BA({1, 1, 0, 0}));
|
||||
ox::expect(ox::serialize<uint32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
ox::expect(ox::serialize<uint32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
ox::expect(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...
|
||||
oxExpect(ox::serialize<uint32_t>(0xffff'ffff).unwrap(), BA({neg1, neg1, neg1, neg1}));
|
||||
return ox::Error(0);
|
||||
ox::expect(ox::serialize<uint32_t>(0xffff'ffff).unwrap(), BA({neg1, neg1, neg1, neg1}));
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -393,58 +395,58 @@ OX_CLANG_NOWARN_END
|
||||
ox::Buffer b;
|
||||
ox::BufferWriter w(&b);
|
||||
oxAssert(w.write("asdf", 4), "write failed");
|
||||
oxExpect(b.size(), 4u);
|
||||
ox::expect(b.size(), 4u);
|
||||
oxAssert(w.write("aoeu", 4), "write failed");
|
||||
oxExpect(b.size(), 8u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu");
|
||||
ox::expect(b.size(), 8u);
|
||||
ox::expect(ox::StringView(b.data(), b.size()), "asdfaoeu");
|
||||
ox::StringView constexpr qwerty = "qwerty";
|
||||
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
|
||||
oxExpect(b.size(), 14u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
|
||||
return ox::Error(0);
|
||||
ox::expect(b.size(), 14u);
|
||||
ox::expect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"FromHex",
|
||||
[] {
|
||||
oxExpect(ox::detail::fromHex("01").unwrap(), 0x01);
|
||||
oxExpect(ox::detail::fromHex("02").unwrap(), 0x02);
|
||||
oxExpect(ox::detail::fromHex("03").unwrap(), 0x03);
|
||||
oxExpect(ox::detail::fromHex("04").unwrap(), 0x04);
|
||||
oxExpect(ox::detail::fromHex("05").unwrap(), 0x05);
|
||||
oxExpect(ox::detail::fromHex("06").unwrap(), 0x06);
|
||||
oxExpect(ox::detail::fromHex("07").unwrap(), 0x07);
|
||||
oxExpect(ox::detail::fromHex("08").unwrap(), 0x08);
|
||||
oxExpect(ox::detail::fromHex("0d").unwrap(), 0x0d);
|
||||
oxExpect(ox::detail::fromHex("0e").unwrap(), 0x0e);
|
||||
oxExpect(ox::detail::fromHex("0f").unwrap(), 0x0f);
|
||||
oxExpect(ox::detail::fromHex("0F").unwrap(), 0x0f);
|
||||
oxExpect(ox::detail::fromHex("fF").unwrap(), 0xff);
|
||||
oxExpect(ox::detail::fromHex("ff").unwrap(), 0xff);
|
||||
oxExpect(ox::detail::fromHex("a0").unwrap(), 0xa0);
|
||||
oxExpect(ox::detail::fromHex("93").unwrap(), 0x93);
|
||||
oxExpect(ox::detail::fromHex("40").unwrap(), 0x40);
|
||||
return ox::Error(0);
|
||||
ox::expect(ox::detail::fromHex("01").unwrap(), 0x01);
|
||||
ox::expect(ox::detail::fromHex("02").unwrap(), 0x02);
|
||||
ox::expect(ox::detail::fromHex("03").unwrap(), 0x03);
|
||||
ox::expect(ox::detail::fromHex("04").unwrap(), 0x04);
|
||||
ox::expect(ox::detail::fromHex("05").unwrap(), 0x05);
|
||||
ox::expect(ox::detail::fromHex("06").unwrap(), 0x06);
|
||||
ox::expect(ox::detail::fromHex("07").unwrap(), 0x07);
|
||||
ox::expect(ox::detail::fromHex("08").unwrap(), 0x08);
|
||||
ox::expect(ox::detail::fromHex("0d").unwrap(), 0x0d);
|
||||
ox::expect(ox::detail::fromHex("0e").unwrap(), 0x0e);
|
||||
ox::expect(ox::detail::fromHex("0f").unwrap(), 0x0f);
|
||||
ox::expect(ox::detail::fromHex("0F").unwrap(), 0x0f);
|
||||
ox::expect(ox::detail::fromHex("fF").unwrap(), 0xff);
|
||||
ox::expect(ox::detail::fromHex("ff").unwrap(), 0xff);
|
||||
ox::expect(ox::detail::fromHex("a0").unwrap(), 0xa0);
|
||||
ox::expect(ox::detail::fromHex("93").unwrap(), 0x93);
|
||||
ox::expect(ox::detail::fromHex("40").unwrap(), 0x40);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"ToHex",
|
||||
[] {
|
||||
oxExpect(ox::detail::toHex(0x01), "01");
|
||||
oxExpect(ox::detail::toHex(0x02), "02");
|
||||
oxExpect(ox::detail::toHex(0x03), "03");
|
||||
oxExpect(ox::detail::toHex(0x04), "04");
|
||||
oxExpect(ox::detail::toHex(0x05), "05");
|
||||
oxExpect(ox::detail::toHex(0x06), "06");
|
||||
oxExpect(ox::detail::toHex(0x07), "07");
|
||||
oxExpect(ox::detail::toHex(0x08), "08");
|
||||
oxExpect(ox::detail::toHex(0x0d), "0d");
|
||||
oxExpect(ox::detail::toHex(0x0e), "0e");
|
||||
oxExpect(ox::detail::toHex(0x0f), "0f");
|
||||
oxExpect(ox::detail::toHex(0x93), "93");
|
||||
oxExpect(ox::detail::toHex(0x40), "40");
|
||||
oxExpect(ox::detail::toHex(0xf0), "f0");
|
||||
return ox::Error(0);
|
||||
ox::expect(ox::detail::toHex(0x01), "01");
|
||||
ox::expect(ox::detail::toHex(0x02), "02");
|
||||
ox::expect(ox::detail::toHex(0x03), "03");
|
||||
ox::expect(ox::detail::toHex(0x04), "04");
|
||||
ox::expect(ox::detail::toHex(0x05), "05");
|
||||
ox::expect(ox::detail::toHex(0x06), "06");
|
||||
ox::expect(ox::detail::toHex(0x07), "07");
|
||||
ox::expect(ox::detail::toHex(0x08), "08");
|
||||
ox::expect(ox::detail::toHex(0x0d), "0d");
|
||||
ox::expect(ox::detail::toHex(0x0e), "0e");
|
||||
ox::expect(ox::detail::toHex(0x0f), "0f");
|
||||
ox::expect(ox::detail::toHex(0x93), "93");
|
||||
ox::expect(ox::detail::toHex(0x40), "40");
|
||||
ox::expect(ox::detail::toHex(0xf0), "f0");
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -452,20 +454,20 @@ OX_CLANG_NOWARN_END
|
||||
[] {
|
||||
constexpr ox::StringView uuidStr = "8d814442-f46e-4cc3-8edc-ca3c01cc86db";
|
||||
OX_REQUIRE(uuid, ox::UUID::fromString(uuidStr));
|
||||
oxExpect(uuid.toString(), uuidStr);
|
||||
oxExpect(ox::UUID{}.isNull(), true);
|
||||
oxExpect(ox::UUID::fromString(uuidStr).value.isNull(), false);
|
||||
return ox::Error(0);
|
||||
ox::expect(uuid.toString(), uuidStr);
|
||||
ox::expect(ox::UUID{}.isNull(), true);
|
||||
ox::expect(ox::UUID::fromString(uuidStr).value.isNull(), false);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"UUID::generate",
|
||||
[] {
|
||||
ox::UUID::seedGenerator({1234, 4321});
|
||||
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(), "7df77910-841c-48ba-ea2e-44521ac47c2e");
|
||||
return ox::Error(0);
|
||||
ox::expect(ox::UUID::generate().unwrap().toString(), "5c3f4b5e-ccbf-4727-7f03-3053dedc8827");
|
||||
ox::expect(ox::UUID::generate().unwrap().toString(), "90d0274a-2774-4afa-88e5-0c1d60ba3abf");
|
||||
ox::expect(ox::UUID::generate().unwrap().toString(), "7df77910-841c-48ba-ea2e-44521ac47c2e");
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -473,71 +475,100 @@ OX_CLANG_NOWARN_END
|
||||
[] {
|
||||
ox::StringView sv = "ab.cd";
|
||||
auto list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = "ab.cd.fg";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 3u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
oxExpect(list[2], "fg");
|
||||
ox::expect(list.size(), 3u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
ox::expect(list[2], "fg");
|
||||
sv = "ab.cd.";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = ".ab.cd.";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = ".";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 0u);
|
||||
ox::expect(list.size(), 0u);
|
||||
sv = ".";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 0u);
|
||||
ox::expect(list.size(), 0u);
|
||||
sv = "";
|
||||
list = ox::split(sv, ".");
|
||||
oxExpect(list.size(), 0u);
|
||||
ox::expect(list.size(), 0u);
|
||||
// split by single char
|
||||
sv = "ab.cd";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = "ab.cd.fg";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 3u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
oxExpect(list[2], "fg");
|
||||
ox::expect(list.size(), 3u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
ox::expect(list[2], "fg");
|
||||
sv = "ab.cd.";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = ".ab.cd.";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 2u);
|
||||
oxExpect(list[0], "ab");
|
||||
oxExpect(list[1], "cd");
|
||||
ox::expect(list.size(), 2u);
|
||||
ox::expect(list[0], "ab");
|
||||
ox::expect(list[1], "cd");
|
||||
sv = ".";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 0u);
|
||||
ox::expect(list.size(), 0u);
|
||||
sv = ".";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 0u);
|
||||
ox::expect(list.size(), 0u);
|
||||
sv = "";
|
||||
list = ox::split(sv, '.');
|
||||
oxExpect(list.size(), 0u);
|
||||
return ox::Error(0);
|
||||
ox::expect(list.size(), 0u);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"intToStr",
|
||||
[] {
|
||||
ox::expect(ox::intToStr<uint8_t>(255u), "255");
|
||||
ox::expect(ox::intToStr<int8_t>(127), "127");
|
||||
ox::expect(ox::intToStr<int8_t>(-128), "-128");
|
||||
ox::expect(ox::intToStr<uint16_t>(65535u), "65535");
|
||||
ox::expect(ox::intToStr<int16_t>(32767), "32767");
|
||||
ox::expect(ox::intToStr<int16_t>(-32768), "-32768");
|
||||
ox::expect(ox::intToStr<uint32_t>(4294967295u), "4294967295");
|
||||
ox::expect(ox::intToStr<int32_t>(2147483647), "2147483647");
|
||||
ox::expect(ox::intToStr<int32_t>(-2147483648), "-2147483648");
|
||||
ox::expect(ox::intToStr<uint64_t>(18446744073709551615u), "18446744073709551615");
|
||||
ox::expect(ox::intToStr<int64_t>(9223372036854775807), "9223372036854775807");
|
||||
ox::expect(ox::intToStr<int64_t>(-9223372036854775807), "-9223372036854775807");
|
||||
ox::expect(ox::intToStr<uint64_t>(0), "0");
|
||||
ox::expect(ox::intToStr<uint64_t>(5), "5");
|
||||
ox::expect(ox::intToStr(0), "0");
|
||||
ox::expect(ox::intToStr(5), "5");
|
||||
ox::expect(ox::intToStr(5000), "5000");
|
||||
ox::expect(ox::intToStr(50000), "50000");
|
||||
ox::expect(ox::intToStr(500000), "500000");
|
||||
ox::expect(ox::intToStr(-5), "-5");
|
||||
ox::expect(ox::intToStr(-5000), "-5000");
|
||||
ox::expect(ox::intToStr(-50000), "-50000");
|
||||
ox::expect(ox::intToStr(-500000), "-500000");
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
int main(int const argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
return -1;
|
||||
|
||||
14
deps/ox/src/ox/std/trace.hpp
vendored
14
deps/ox/src/ox/std/trace.hpp
vendored
@@ -166,7 +166,7 @@ class OutStream {
|
||||
constexpr OutStream &operator<<(Integer_c auto v) noexcept;
|
||||
|
||||
constexpr OutStream &operator<<(char v) noexcept {
|
||||
if (m_msg.msg.len()) {
|
||||
if (m_msg.msg.size()) {
|
||||
m_msg.msg += m_delimiter;
|
||||
}
|
||||
m_msg.msg += v;
|
||||
@@ -174,7 +174,7 @@ class OutStream {
|
||||
}
|
||||
|
||||
constexpr OutStream &operator<<(StringViewCR v) noexcept {
|
||||
if (m_msg.msg.len()) {
|
||||
if (m_msg.msg.size()) {
|
||||
m_msg.msg += m_delimiter;
|
||||
}
|
||||
m_msg.msg += v;
|
||||
@@ -209,7 +209,7 @@ class OutStream {
|
||||
|
||||
private:
|
||||
constexpr OutStream &appendSignedInt(int64_t v) noexcept {
|
||||
if (m_msg.msg.len()) {
|
||||
if (m_msg.msg.size()) {
|
||||
m_msg.msg += m_delimiter;
|
||||
}
|
||||
m_msg.msg += static_cast<int64_t>(v);
|
||||
@@ -217,7 +217,7 @@ class OutStream {
|
||||
}
|
||||
|
||||
constexpr OutStream &appendUnsignedInt(uint64_t v) noexcept {
|
||||
if (m_msg.msg.len()) {
|
||||
if (m_msg.msg.size()) {
|
||||
m_msg.msg += m_delimiter;
|
||||
}
|
||||
m_msg.msg += static_cast<int64_t>(v);
|
||||
@@ -227,7 +227,7 @@ class OutStream {
|
||||
};
|
||||
|
||||
constexpr OutStream &OutStream::operator<<(Integer_c auto v) noexcept {
|
||||
if (m_msg.msg.len()) {
|
||||
if (m_msg.msg.size()) {
|
||||
m_msg.msg += m_delimiter;
|
||||
}
|
||||
m_msg.msg += v;
|
||||
@@ -268,7 +268,7 @@ using TraceStream = NullStream;
|
||||
|
||||
inline void logError(const char *file, int line, const char *fmt, const Error &err) noexcept {
|
||||
if (err) {
|
||||
TraceStream trc(file, line, "ox::error");
|
||||
TraceStream trc(file, line, "ox.error");
|
||||
if (err.src.file_name() != nullptr) {
|
||||
trc << "Error: (" << err.src.file_name() << ":" << err.src.line() << "):";
|
||||
} else {
|
||||
@@ -280,7 +280,7 @@ inline void logError(const char *file, int line, const char *fmt, const Error &e
|
||||
|
||||
inline void logError(const char *file, int line, const Error &err) noexcept {
|
||||
if (err) {
|
||||
TraceStream trc(file, line, "ox::error");
|
||||
TraceStream trc(file, line, "ox.error");
|
||||
trc << "Error:" << err;
|
||||
if (err.src.file_name() != nullptr) {
|
||||
trc << "(" << err.src.file_name() << ":" << err.src.line() << ")";
|
||||
|
||||
4
deps/ox/src/ox/std/tracehook.cpp
vendored
4
deps/ox/src/ox/std/tracehook.cpp
vendored
@@ -39,6 +39,8 @@ enum LogChan {
|
||||
Debug = 4,
|
||||
};
|
||||
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
|
||||
template<LogChan chan>
|
||||
static void log(ox::StringViewCR str) {
|
||||
const auto sz = ox::min<std::size_t>(0x100, str.bytes());
|
||||
@@ -103,5 +105,7 @@ void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
|
||||
#endif
|
||||
}
|
||||
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
|
||||
}
|
||||
|
||||
|
||||
19
deps/ox/src/ox/std/types.hpp
vendored
19
deps/ox/src/ox/std/types.hpp
vendored
@@ -63,25 +63,6 @@ namespace ox {
|
||||
|
||||
using CString = char const*;
|
||||
|
||||
/**
|
||||
* Aliases type T in size and alignment to allow allocating space for a T
|
||||
* without running the constructor.
|
||||
*/
|
||||
template<typename T, std::size_t sz = sizeof(T)>
|
||||
struct alignas(alignof(T)) AllocAlias {
|
||||
char buff[sz];
|
||||
constexpr AllocAlias() noexcept = default;
|
||||
[[nodiscard]]
|
||||
auto data() noexcept {
|
||||
return reinterpret_cast<T*>(this);
|
||||
}
|
||||
[[nodiscard]]
|
||||
auto data() const noexcept {
|
||||
return reinterpret_cast<const T*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<std::size_t sz>
|
||||
struct SignedType {
|
||||
};
|
||||
|
||||
106
deps/ox/src/ox/std/typetraits.hpp
vendored
106
deps/ox/src/ox/std/typetraits.hpp
vendored
@@ -34,6 +34,41 @@ inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
|
||||
|
||||
namespace ox {
|
||||
|
||||
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;
|
||||
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
|
||||
@@ -109,6 +144,12 @@ template<> struct is_integer<int16_t> : true_type {};
|
||||
template<> struct is_integer<uint16_t>: true_type {};
|
||||
template<> struct is_integer<int32_t> : true_type {};
|
||||
template<> struct is_integer<uint32_t>: true_type {};
|
||||
template<> struct is_integer<int8_t const> : true_type {};
|
||||
template<> struct is_integer<uint8_t const> : true_type {};
|
||||
template<> struct is_integer<int16_t const> : true_type {};
|
||||
template<> struct is_integer<uint16_t const>: true_type {};
|
||||
template<> struct is_integer<int32_t const> : true_type {};
|
||||
template<> struct is_integer<uint32_t const>: true_type {};
|
||||
|
||||
// some of these need to be done with the actual language syntax because no one
|
||||
// can agree on what an (u)int64_t is...
|
||||
@@ -116,9 +157,13 @@ template<> struct is_integer<long>: true_type {};
|
||||
template<> struct is_integer<long long>: true_type {};
|
||||
template<> struct is_integer<unsigned long>: true_type {};
|
||||
template<> struct is_integer<unsigned long long>: true_type {};
|
||||
template<> struct is_integer<long const>: true_type {};
|
||||
template<> struct is_integer<long long const>: true_type {};
|
||||
template<> struct is_integer<unsigned long const>: true_type {};
|
||||
template<> struct is_integer<unsigned long long const>: true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_integer_v = is_integral<T>::value;
|
||||
constexpr bool is_integer_v = is_integer<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept Integer_c = is_integer<T>::value;
|
||||
@@ -180,20 +225,6 @@ struct is_same<T, T>: true_type {};
|
||||
template<typename T, typename U>
|
||||
constexpr auto is_same_v = is_same<T, U>::value;
|
||||
|
||||
// enable_if ///////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool B, class T = void>
|
||||
struct enable_if {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct enable_if<true, T> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<bool B, typename T>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct is_pointer {
|
||||
static constexpr bool value = false;
|
||||
@@ -237,6 +268,9 @@ struct remove_pointer<T* const volatile> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct remove_reference {
|
||||
@@ -275,39 +309,23 @@ template<class T>
|
||||
constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0);
|
||||
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct remove_cv {
|
||||
using type = T;
|
||||
};
|
||||
T const &declvalCopy();
|
||||
|
||||
template<typename T, typename = decltype(T(declvalCopy<T>()))>
|
||||
constexpr bool is_copy_constructible(int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct remove_cv<const T> {
|
||||
using type = T;
|
||||
};
|
||||
constexpr bool is_copy_constructible(bool) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
template<class T>
|
||||
constexpr bool is_copy_constructible_v = detail::is_copy_constructible<T>(0);
|
||||
|
||||
|
||||
// is String?
|
||||
|
||||
15
deps/ox/src/ox/std/utility.hpp
vendored
15
deps/ox/src/ox/std/utility.hpp
vendored
@@ -32,9 +32,9 @@ constexpr bool cmp_equal(T const t, U const u) noexcept {
|
||||
if constexpr(ox::is_signed_v<T> == ox::is_signed_v<U>) {
|
||||
return t == u;
|
||||
} else if constexpr(ox::is_signed_v<T>) {
|
||||
return ox::Signed<T>{t} == u;
|
||||
return t >= 0 && static_cast<ox::Unsigned<T>>(t) == u;
|
||||
} else {
|
||||
return t == ox::Signed<U>{u};
|
||||
return u >= 0 && t == static_cast<ox::Unsigned<U>>(u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ constexpr bool cmp_less(T const t, U const u) noexcept {
|
||||
if constexpr(ox::is_signed_v<T> == ox::is_signed_v<U>) {
|
||||
return t < u;
|
||||
} else if constexpr(ox::is_signed_v<T>) {
|
||||
return ox::Signed<T>{t} < u;
|
||||
return t < 0 || static_cast<ox::Unsigned<T>>(t) < u;
|
||||
} else {
|
||||
return t < ox::Signed<U>{u};
|
||||
return u >= 0 && t < static_cast<ox::Unsigned<U>>(u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ constexpr bool cmp_greater_equal(T const t, U const u) noexcept {
|
||||
return !std::cmp_less(t, u);
|
||||
}
|
||||
|
||||
static_assert(cmp_less(-1, 5u));
|
||||
static_assert(!cmp_less(5u, -1));
|
||||
static_assert(cmp_equal(5u, 5));
|
||||
static_assert(cmp_equal(5, 5u));
|
||||
static_assert(!cmp_equal(-5, 5u));
|
||||
static_assert(!cmp_equal(4u, 5u));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
14
deps/ox/src/ox/std/uuid.hpp
vendored
14
deps/ox/src/ox/std/uuid.hpp
vendored
@@ -58,7 +58,7 @@ constexpr ox::Result<uint8_t> fromHex(ox::StringViewCR v) noexcept {
|
||||
if (!detail::isHexChar(v[0]) || !detail::isHexChar(v[1])) {
|
||||
return ox::Error(1, "Invalid UUID");
|
||||
}
|
||||
if (v.len() != 2) {
|
||||
if (v.size() != 2) {
|
||||
return ox::Error(2);
|
||||
}
|
||||
uint8_t out = 0;
|
||||
@@ -105,6 +105,10 @@ class UUID {
|
||||
ox::Array<uint8_t, 16> m_value{};
|
||||
|
||||
public:
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.UUID";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
|
||||
static void seedGenerator(const RandomSeed &seed) noexcept;
|
||||
|
||||
static ox::Result<UUID> generate() noexcept;
|
||||
@@ -129,18 +133,18 @@ class UUID {
|
||||
}
|
||||
|
||||
static constexpr ox::Result<ox::UUID> fromString(ox::StringViewCR s) noexcept {
|
||||
if (s.len() < 36) {
|
||||
if (s.size() < 36) {
|
||||
return ox::Error(1, "Insufficient data to contain a complete UUID");
|
||||
}
|
||||
UUID out;
|
||||
auto valueI = 0u;
|
||||
for (size_t i = 0; i < s.len();) {
|
||||
for (size_t i = 0; i < s.size();) {
|
||||
if (s[i] == '-') {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const auto seg = substr(s, i, i + 2);
|
||||
if (seg.len() != 2) {
|
||||
if (seg.size() != 2) {
|
||||
return ox::Error(1, "Invalid UUID");
|
||||
}
|
||||
OX_REQUIRE(val, detail::fromHex(seg));
|
||||
@@ -170,7 +174,7 @@ class UUID {
|
||||
for (auto i = 0u; i < cnt; ++i) {
|
||||
const auto v = value[valueI];
|
||||
const auto h = detail::toHex(v);
|
||||
std::ignore = writer.write(h.c_str(), h.len());
|
||||
std::ignore = writer.write(h.c_str(), h.size());
|
||||
++valueI;
|
||||
}
|
||||
};
|
||||
|
||||
350
deps/ox/src/ox/std/vector.hpp
vendored
350
deps/ox/src/ox/std/vector.hpp
vendored
@@ -26,7 +26,7 @@ namespace ox {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename Allocator, std::size_t Size = 1>
|
||||
template<typename T, typename Allocator, size_t Size = 1>
|
||||
struct VectorAllocator {
|
||||
static_assert(sizeof(AllocAlias<T>) == sizeof(T));
|
||||
static_assert(alignof(AllocAlias<T>) == alignof(T));
|
||||
@@ -34,10 +34,10 @@ struct VectorAllocator {
|
||||
ox::Array<AllocAlias<T>, Size> m_data = {};
|
||||
protected:
|
||||
constexpr VectorAllocator() noexcept = default;
|
||||
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
||||
constexpr VectorAllocator(VectorAllocator const&) noexcept = default;
|
||||
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
|
||||
|
||||
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
||||
constexpr void allocate(T **items, size_t const cap) noexcept {
|
||||
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
||||
if (std::is_constant_evaluated() || cap > Size) {
|
||||
*items = Allocator{}.allocate(cap);
|
||||
@@ -49,45 +49,31 @@ struct VectorAllocator {
|
||||
constexpr void moveConstructItemsFrom(
|
||||
T **items,
|
||||
VectorAllocator *src,
|
||||
const std::size_t count,
|
||||
const std::size_t cap) noexcept {
|
||||
size_t const count,
|
||||
size_t const cap) noexcept {
|
||||
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
|
||||
// try removing it later
|
||||
if (!std::is_constant_evaluated()) {
|
||||
if (cap <= m_data.size() && count <= m_data.size()) {
|
||||
for (auto i = 0u; i < count; ++i) {
|
||||
const auto dstItem = reinterpret_cast<T *>(&m_data[i]);
|
||||
const auto srcItem = reinterpret_cast<T *>(&src->m_data[i]);
|
||||
std::construct_at<T>(dstItem, std::move(*srcItem));
|
||||
auto const srcItem = std::launder(reinterpret_cast<T*>(&src->m_data[i]));
|
||||
new (&m_data[i]) T(std::move(*srcItem));
|
||||
}
|
||||
if (count) {
|
||||
*items = std::launder(reinterpret_cast<T*>(m_data.data()));
|
||||
} else {
|
||||
*items = reinterpret_cast<T*>(m_data.data());
|
||||
}
|
||||
*items = reinterpret_cast<T*>(m_data.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void moveItemsFrom(
|
||||
T **items,
|
||||
VectorAllocator *src,
|
||||
const std::size_t count,
|
||||
const std::size_t cap) noexcept {
|
||||
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
|
||||
// try removing it later
|
||||
if (!std::is_constant_evaluated()) {
|
||||
if (cap <= m_data.size() && count <= m_data.size()) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto dstItem = reinterpret_cast<T *>(&m_data[i]);
|
||||
const auto srcItem = reinterpret_cast<T *>(&src->m_data[i]);
|
||||
*dstItem = std::move(*srcItem);
|
||||
}
|
||||
*items = reinterpret_cast<T*>(m_data.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void deallocate(T *items, std::size_t cap) noexcept {
|
||||
constexpr void deallocate(T *const items, size_t const cap) noexcept {
|
||||
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
||||
if (std::is_constant_evaluated()) {
|
||||
Allocator{}.deallocate(items, cap);
|
||||
if (items) {
|
||||
Allocator{}.deallocate(items, cap);
|
||||
}
|
||||
} else {
|
||||
if (items && static_cast<void*>(items) != static_cast<void*>(m_data.data())) {
|
||||
Allocator{}.deallocate(items, cap);
|
||||
@@ -101,10 +87,10 @@ template<typename T, typename Allocator>
|
||||
struct VectorAllocator<T, Allocator, 0> {
|
||||
protected:
|
||||
constexpr VectorAllocator() noexcept = default;
|
||||
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
||||
constexpr VectorAllocator(VectorAllocator const&) noexcept = default;
|
||||
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
|
||||
|
||||
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
||||
constexpr void allocate(T **items, size_t const cap) noexcept {
|
||||
*items = Allocator{}.allocate(cap);
|
||||
}
|
||||
|
||||
@@ -112,15 +98,15 @@ struct VectorAllocator<T, Allocator, 0> {
|
||||
constexpr void moveConstructItemsFrom(
|
||||
T**,
|
||||
VectorAllocator*,
|
||||
const std::size_t,
|
||||
const std::size_t) noexcept {
|
||||
size_t const,
|
||||
size_t const) noexcept {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
constexpr void moveItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept {
|
||||
constexpr void moveItemsFrom(T**, VectorAllocator*, size_t const, size_t const) noexcept {
|
||||
}
|
||||
|
||||
constexpr void deallocate(T *items, std::size_t cap) noexcept {
|
||||
constexpr void deallocate(T *const items, size_t const cap) noexcept {
|
||||
if (items) {
|
||||
Allocator{}.deallocate(items, cap);
|
||||
}
|
||||
@@ -130,12 +116,12 @@ struct VectorAllocator<T, Allocator, 0> {
|
||||
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize = 0, typename Allocator = std::allocator<T>>
|
||||
template<typename T, size_t SmallVectorSize = 0, typename Allocator = std::allocator<T>>
|
||||
class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
using size_type = size_t;
|
||||
|
||||
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
|
||||
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
|
||||
@@ -143,18 +129,18 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
private:
|
||||
static constexpr auto initialCap = SmallVectorSize > 0 ? SmallVectorSize : 50;
|
||||
static constexpr auto useNoexcept = ox::is_integral_v<T> || ox::is_pointer_v<T>;
|
||||
std::size_t m_size = 0;
|
||||
std::size_t m_cap = 0;
|
||||
size_t m_size = 0;
|
||||
size_t m_cap = 0;
|
||||
T *m_items = nullptr;
|
||||
|
||||
public:
|
||||
constexpr Vector() noexcept = default;
|
||||
|
||||
explicit constexpr Vector(std::size_t size) noexcept;
|
||||
explicit constexpr Vector(size_t size) noexcept;
|
||||
|
||||
constexpr Vector(std::initializer_list<T> list) noexcept;
|
||||
|
||||
constexpr Vector(const Vector &other) noexcept(useNoexcept);
|
||||
constexpr Vector(Vector const &other) noexcept(useNoexcept);
|
||||
|
||||
constexpr Vector(Vector &&other) noexcept;
|
||||
|
||||
@@ -169,23 +155,23 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const T&, const T*> begin() const noexcept {
|
||||
return iterator<const T&, const T*>(m_items, 0, m_size);
|
||||
constexpr iterator<T const&, T const*> begin() const noexcept {
|
||||
return iterator<T const&, T const*>(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);
|
||||
constexpr iterator<T const&, T const*> end() const noexcept {
|
||||
return iterator<T const&, T const*>(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);
|
||||
constexpr iterator<T const&, T const*> cbegin() const noexcept {
|
||||
return iterator<T const&, T const*>(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);
|
||||
constexpr iterator<T const&, T const*> cend() const noexcept {
|
||||
return iterator<T const&, T const*>(m_items, m_size, m_size);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -199,36 +185,36 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
}
|
||||
|
||||
[[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);
|
||||
constexpr iterator<T const&, T const*, true> crbegin() const noexcept {
|
||||
return iterator<T const&, T const*, 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);
|
||||
constexpr iterator<T const&, T const*, true> crend() const noexcept {
|
||||
return iterator<T const&, T const*, 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);
|
||||
constexpr iterator<T const&, T const*, true> rbegin() const noexcept {
|
||||
return iterator<T const&, T const*, 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 iterator<T const&, T const*, true> rend() const noexcept {
|
||||
return iterator<T const&, T const*, true>(m_items, MaxValue<size_type>, m_size);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Vector &other) const noexcept(useNoexcept);
|
||||
constexpr bool operator==(Vector const &other) const noexcept(useNoexcept);
|
||||
|
||||
constexpr Vector &operator=(const Vector &other) noexcept(useNoexcept);
|
||||
constexpr Vector &operator=(Vector const &other) noexcept(useNoexcept);
|
||||
|
||||
constexpr Vector &operator=(Vector &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T &operator[](std::size_t i) noexcept;
|
||||
constexpr T &operator[](size_t i) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T &operator[](std::size_t i) const noexcept;
|
||||
constexpr T const &operator[](size_t i) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<T*> at(size_t i) noexcept;
|
||||
@@ -240,26 +226,28 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
constexpr Result<T*> front() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<const T*> front() const noexcept;
|
||||
constexpr Result<T const*> front() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<T*> back() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<const T*> back() const noexcept;
|
||||
constexpr Result<T const*> back() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t capacity() const noexcept;
|
||||
constexpr size_t capacity() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept;
|
||||
constexpr size_t size() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool empty() const noexcept;
|
||||
|
||||
constexpr void clear() noexcept(useNoexcept);
|
||||
|
||||
constexpr void resize(std::size_t size) noexcept(useNoexcept);
|
||||
constexpr void resize(size_t size) noexcept(useNoexcept);
|
||||
|
||||
constexpr void reserveResize(size_t size) noexcept(useNoexcept);
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T *data() noexcept {
|
||||
@@ -267,7 +255,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T *data() const noexcept {
|
||||
constexpr T const *data() const noexcept {
|
||||
return m_items;
|
||||
}
|
||||
|
||||
@@ -275,17 +263,19 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
constexpr bool contains(MaybeView_t<T> const&) const noexcept;
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(
|
||||
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept);
|
||||
size_t pos, size_t cnt, T const &val) noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, T val) noexcept(useNoexcept);
|
||||
constexpr iterator<T&, T*, false> insert(size_t pos, T val) noexcept(useNoexcept);
|
||||
|
||||
template<typename... Args>
|
||||
constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept);
|
||||
constexpr iterator<T&, T*, false> emplace(size_t pos, Args&&... args) noexcept(useNoexcept);
|
||||
|
||||
template<typename... Args>
|
||||
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(T item) noexcept(useNoexcept);
|
||||
constexpr void push_back(T const &item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(T &&item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void pop_back() noexcept(useNoexcept);
|
||||
|
||||
@@ -294,14 +284,14 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
* @param pos iterator at the point to remove
|
||||
* @return Error if index is out of bounds
|
||||
*/
|
||||
constexpr Result<iterator<T&, T*, false>> erase(const iterator<> &pos) noexcept(useNoexcept);
|
||||
constexpr Result<iterator<T&, T*, false>> erase(iterator<> const &pos) noexcept(useNoexcept);
|
||||
|
||||
/**
|
||||
* Removes an item from the Vector.
|
||||
* @param pos position of item to remove
|
||||
* @return Error if index is out of bounds
|
||||
*/
|
||||
constexpr Result<iterator<T&, T*, false>> erase(std::size_t pos) noexcept(useNoexcept);
|
||||
constexpr Result<iterator<T&, T*, false>> erase(size_t pos) noexcept(useNoexcept);
|
||||
|
||||
/**
|
||||
* Moves the last item in the Vector to position pos and decrements the
|
||||
@@ -309,59 +299,62 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
* @param pos position of item to remove
|
||||
* @return Error if index is out of bounds
|
||||
*/
|
||||
constexpr Error unordered_erase(std::size_t pos) noexcept(useNoexcept);
|
||||
constexpr Error unordered_erase(size_t pos) noexcept(useNoexcept);
|
||||
|
||||
constexpr Error remove(T const &val);
|
||||
constexpr Error remove(MaybeView_t<T> const &val);
|
||||
|
||||
constexpr void reserve(std::size_t cap) noexcept(useNoexcept);
|
||||
constexpr void reserve(size_t cap) noexcept(useNoexcept);
|
||||
|
||||
constexpr void shrink_to_fit() noexcept(useNoexcept);
|
||||
|
||||
private:
|
||||
constexpr void reserveInsert(
|
||||
std::size_t cap, std::size_t pos, std::size_t offset = 1) noexcept(useNoexcept);
|
||||
size_t cap, size_t pos, size_t offset = 1) noexcept(useNoexcept);
|
||||
|
||||
};
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
|
||||
using VectorIt = typename Vector<T, SmallVectorSize, Allocator>::template iterator<RefType, reverse>;
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
|
||||
constexpr VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> operator+(
|
||||
std::size_t n,
|
||||
const VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> &a) {
|
||||
size_t n,
|
||||
VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> const &a) {
|
||||
return a + n;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::size_t size) noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(size_t const size) noexcept {
|
||||
m_size = size;
|
||||
m_cap = m_size;
|
||||
this->allocate(&m_items, m_cap);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
std::construct_at(&m_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept {
|
||||
reserve(list.size());
|
||||
for (auto &item : list) {
|
||||
emplace_back(std::move(item));
|
||||
m_size = list.size();
|
||||
m_cap = m_size;
|
||||
this->allocate(&m_items, m_cap);
|
||||
for (size_t i{}; auto &item : list) {
|
||||
std::construct_at(&m_items[i], std::move(item));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(const Vector &other) noexcept(useNoexcept) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(Vector const &other) noexcept(useNoexcept) {
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
this->allocate(&m_items, other.m_cap);
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
std::construct_at(&m_items[i], other.m_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(Vector &&other) noexcept {
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
@@ -372,20 +365,20 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(Vector &&other) noexcept
|
||||
other.m_items = nullptr;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::~Vector() {
|
||||
clear();
|
||||
this->deallocate(m_items, m_cap);
|
||||
m_items = nullptr;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::operator==(
|
||||
const Vector &other) const noexcept(useNoexcept) {
|
||||
Vector const &other) const noexcept(useNoexcept) {
|
||||
if (m_size != other.m_size) {
|
||||
return false;
|
||||
}
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
for (size_t i = 0; i < m_size; i++) {
|
||||
if (!(m_items[i] == other.m_items[i])) {
|
||||
return false;
|
||||
}
|
||||
@@ -393,9 +386,9 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::operator==(
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(
|
||||
const Vector &other) noexcept(useNoexcept) {
|
||||
Vector const &other) noexcept(useNoexcept) {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
this->deallocate(m_items, m_cap);
|
||||
@@ -403,14 +396,14 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
this->allocate(&m_items, other.m_cap);
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
for (size_t i = 0; i < m_size; i++) {
|
||||
std::construct_at(&m_items[i], other.m_items[i]);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(
|
||||
Vector &&other) noexcept {
|
||||
if (this != &other) {
|
||||
@@ -419,7 +412,7 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
m_items = other.m_items;
|
||||
this->moveItemsFrom(&m_items, &other, m_size, m_cap);
|
||||
this->moveConstructItemsFrom(&m_items, &other, m_size, m_cap);
|
||||
other.m_size = 0;
|
||||
other.m_cap = 0;
|
||||
other.m_items = nullptr;
|
||||
@@ -427,35 +420,35 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr T &Vector<T, SmallVectorSize, Allocator>::operator[](size_t const i) noexcept {
|
||||
boundsCheck(i, size(), "Vector access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr const T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) const noexcept {
|
||||
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr T const &Vector<T, SmallVectorSize, Allocator>::operator[](size_t const i) const noexcept {
|
||||
boundsCheck(i, size(), "Vector access overflow");
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::at(size_t i) noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::at(size_t const i) noexcept {
|
||||
if (i < size()) [[likely]] {
|
||||
return &operator[](i);
|
||||
}
|
||||
return ox::Error(1, "Vector: Invalid index");
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T const*> Vector<T, SmallVectorSize, Allocator>::at(size_t i) const noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T const*> Vector<T, SmallVectorSize, Allocator>::at(size_t const i) const noexcept {
|
||||
if (i < size()) [[likely]] {
|
||||
return &operator[](i);
|
||||
}
|
||||
return ox::Error(1, "Vector: Invalid index");
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::front() noexcept {
|
||||
if (!m_size) {
|
||||
return {nullptr, ox::Error(1)};
|
||||
@@ -463,15 +456,15 @@ constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::front() noexcept {
|
||||
return &m_items[0];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<const T*> Vector<T, SmallVectorSize, Allocator>::front() const noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T const*> Vector<T, SmallVectorSize, Allocator>::front() const noexcept {
|
||||
if (!m_size) {
|
||||
return {nullptr, ox::Error(1)};
|
||||
}
|
||||
return &m_items[0];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::back() noexcept {
|
||||
if (!m_size) {
|
||||
return {nullptr, ox::Error(1)};
|
||||
@@ -479,59 +472,65 @@ constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::back() noexcept {
|
||||
return &m_items[m_size - 1];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<const T*> Vector<T, SmallVectorSize, Allocator>::back() const noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<T const*> Vector<T, SmallVectorSize, Allocator>::back() const noexcept {
|
||||
if (!m_size) {
|
||||
return {nullptr, ox::Error(1)};
|
||||
}
|
||||
return &m_items[m_size - 1];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr std::size_t Vector<T, SmallVectorSize, Allocator>::capacity() const noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr size_t Vector<T, SmallVectorSize, Allocator>::capacity() const noexcept {
|
||||
return m_cap;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr std::size_t Vector<T, SmallVectorSize, Allocator>::size() const noexcept {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr size_t Vector<T, SmallVectorSize, Allocator>::size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::empty() const noexcept {
|
||||
return !m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::clear() noexcept(useNoexcept) {
|
||||
if constexpr(is_class<T>()) {
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
m_items[i].~T();
|
||||
}
|
||||
}
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) noexcept(useNoexcept) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::resize(size_t const size) noexcept(useNoexcept) {
|
||||
if (m_cap < size) {
|
||||
reserve(size * 2);
|
||||
}
|
||||
if (m_size < size) {
|
||||
for (std::size_t i = m_size; i < size; i++) {
|
||||
for (size_t i = m_size; i < size; i++) {
|
||||
std::construct_at(&m_items[i]);
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = size; i < m_size; i++) {
|
||||
for (size_t i = size; i < m_size; i++) {
|
||||
m_items[i].~T();
|
||||
}
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const&v) const noexcept {
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveResize(size_t const size) noexcept(useNoexcept) {
|
||||
reserve(size);
|
||||
resize(size);
|
||||
}
|
||||
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const &v) const noexcept {
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
if (m_items[i] == v) {
|
||||
return true;
|
||||
}
|
||||
@@ -539,10 +538,10 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> co
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept) {
|
||||
size_t const pos, size_t const cnt, T const &val) noexcept(useNoexcept) {
|
||||
if (m_size + cnt > m_cap) {
|
||||
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
|
||||
}
|
||||
@@ -562,9 +561,9 @@ Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, T val) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(size_t pos, T val) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
|
||||
}
|
||||
@@ -580,10 +579,10 @@ Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, T val) noexcept(u
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
template<typename... Args>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::emplace(size_t pos, Args&&... args) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
|
||||
if (pos < m_size) {
|
||||
@@ -603,7 +602,7 @@ Vector<T, SmallVectorSize, Allocator>::emplace(std::size_t pos, Args&&... args)
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
template<typename... Args>
|
||||
constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
@@ -614,8 +613,17 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
|
||||
return *out;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T item) noexcept(useNoexcept) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T const &item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
std::construct_at(&m_items[m_size], item);
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
@@ -623,21 +631,21 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T item) noexcept
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::pop_back() noexcept(useNoexcept) {
|
||||
--m_size;
|
||||
m_items[m_size].~T();
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>>
|
||||
Vector<T, SmallVectorSize, Allocator>::erase(const iterator<> &pos) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::erase(iterator<> const &pos) noexcept(useNoexcept) {
|
||||
return erase(pos.offset());
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>>
|
||||
Vector<T, SmallVectorSize, Allocator>::erase(std::size_t pos) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::erase(size_t pos) noexcept(useNoexcept) {
|
||||
if (pos >= m_size) {
|
||||
return ox::Error(1, "Vector::erase failed: pos is greater than Vector size");
|
||||
}
|
||||
@@ -649,8 +657,8 @@ Vector<T, SmallVectorSize, Allocator>::erase(std::size_t pos) noexcept(useNoexce
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Error Vector<T, SmallVectorSize, Allocator>::unordered_erase(std::size_t pos)
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Error Vector<T, SmallVectorSize, Allocator>::unordered_erase(size_t pos)
|
||||
noexcept(useNoexcept) {
|
||||
if (pos >= m_size) {
|
||||
return ox::Error(1);
|
||||
@@ -658,11 +666,11 @@ constexpr Error Vector<T, SmallVectorSize, Allocator>::unordered_erase(std::size
|
||||
--m_size;
|
||||
m_items[pos] = std::move(m_items[m_size]);
|
||||
m_items[m_size].~T();
|
||||
return ox::Error(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr ox::Error Vector<T, SmallVectorSize, Allocator>::remove(T const &val) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr ox::Error Vector<T, SmallVectorSize, Allocator>::remove(MaybeView_t<T> const &val) {
|
||||
for (size_t i{}; auto const &v : *this) {
|
||||
if (v == val) {
|
||||
return erase(i).error;
|
||||
@@ -672,18 +680,18 @@ constexpr ox::Error Vector<T, SmallVectorSize, Allocator>::remove(T const &val)
|
||||
return ox::Error{1, "element not found"};
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) noexcept(useNoexcept) {
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(size_t cap) noexcept(useNoexcept) {
|
||||
if (cap <= m_cap) {
|
||||
return;
|
||||
}
|
||||
const auto oldItems = m_items;
|
||||
const auto oldCap = m_cap;
|
||||
auto const oldItems = m_items;
|
||||
auto const oldCap = m_cap;
|
||||
m_cap = cap;
|
||||
this->allocate(&m_items, cap);
|
||||
if (oldItems) { // move over old items
|
||||
const auto itRange = ox::min(cap, m_size);
|
||||
for (std::size_t i = 0; i < itRange; ++i) {
|
||||
auto const itRange = ox::min(cap, m_size);
|
||||
for (size_t i = 0; i < itRange; ++i) {
|
||||
std::construct_at(&m_items[i], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
@@ -691,17 +699,17 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) n
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::shrink_to_fit() noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
return;
|
||||
}
|
||||
const auto oldItems = m_items;
|
||||
const auto oldCap = m_cap;
|
||||
auto const oldItems = m_items;
|
||||
auto const oldCap = m_cap;
|
||||
m_cap = m_size;
|
||||
this->allocate(&m_items, m_size);
|
||||
if (oldItems) { // move over old items
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
std::construct_at(&m_items[i], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
@@ -709,26 +717,26 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::shrink_to_fit() noexcept(u
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename T, size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert(
|
||||
std::size_t cap,
|
||||
std::size_t pos,
|
||||
std::size_t offset) noexcept(useNoexcept) {
|
||||
size_t cap,
|
||||
size_t pos,
|
||||
size_t offset) noexcept(useNoexcept) {
|
||||
if (cap <= m_cap) {
|
||||
return;
|
||||
}
|
||||
const auto oldItems = m_items;
|
||||
const auto oldCap = m_cap;
|
||||
auto const oldItems = m_items;
|
||||
auto const oldCap = m_cap;
|
||||
m_cap = cap;
|
||||
this->allocate(&m_items, cap);
|
||||
if (oldItems) { // move over old items
|
||||
auto itRange = ox::min(m_size, pos);
|
||||
for (std::size_t i = 0; i < itRange; ++i) {
|
||||
for (size_t i = 0; i < itRange; ++i) {
|
||||
std::construct_at(&m_items[i], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
itRange = m_size;
|
||||
for (std::size_t i = pos; i < itRange; ++i) {
|
||||
for (size_t i = pos; i < itRange; ++i) {
|
||||
std::construct_at(&m_items[i + offset], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
@@ -739,8 +747,8 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert(
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const Vector<T>&) noexcept {
|
||||
const typename PlatSpec::size_t i = 0;
|
||||
constexpr auto alignOf(Vector<T> const&) noexcept {
|
||||
typename PlatSpec::size_t const i = 0;
|
||||
return PlatSpec::alignOf(i);
|
||||
}
|
||||
|
||||
|
||||
112
deps/teagba/include/teagba/addresses.hpp
vendored
112
deps/teagba/include/teagba/addresses.hpp
vendored
@@ -5,103 +5,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/units.hpp>
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Interrupt Handler
|
||||
|
||||
using interrupt_handler = void (*)();
|
||||
#define REG_ISR *reinterpret_cast<interrupt_handler*>(0x0300'7FFC)
|
||||
#define REG_IE *reinterpret_cast<volatile uint16_t*>(0x0400'0200)
|
||||
#define REG_IF *reinterpret_cast<volatile uint16_t*>(0x0400'0202)
|
||||
#define REG_IME *reinterpret_cast<volatile uint16_t*>(0x0400'0208)
|
||||
using InterruptHandler = void(*)();
|
||||
#define REG_ISR (*reinterpret_cast<InterruptHandler*>(0x0300'7FFC))
|
||||
#define REG_IE (*reinterpret_cast<volatile uint16_t*>(0x0400'0200))
|
||||
#define REG_IF (*reinterpret_cast<volatile uint16_t*>(0x0400'0202))
|
||||
#define REG_IME (*reinterpret_cast<volatile uint16_t*>(0x0400'0208))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Display Registers
|
||||
|
||||
#define REG_DISPCTL *reinterpret_cast<volatile uint32_t*>(0x0400'0000)
|
||||
#define REG_DISPSTAT *reinterpret_cast<volatile uint32_t*>(0x0400'0004)
|
||||
#define REG_VCOUNT *reinterpret_cast<volatile uint32_t*>(0x0400'0006)
|
||||
#define REG_DISPCTL (*reinterpret_cast<volatile uint32_t*>(0x0400'0000))
|
||||
#define REG_DISPSTAT (*reinterpret_cast<volatile uint32_t*>(0x0400'0004))
|
||||
#define REG_VCOUNT (*reinterpret_cast<volatile uint32_t*>(0x0400'0006))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Timers
|
||||
|
||||
#define REG_TIMER0 *reinterpret_cast<volatile uint16_t*>(0x0400'0100)
|
||||
#define REG_TIMER0CTL *reinterpret_cast<volatile uint16_t*>(0x0400'0102)
|
||||
#define REG_TIMER0 (*reinterpret_cast<volatile uint16_t*>(0x0400'0100))
|
||||
#define REG_TIMER0CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'0102))
|
||||
|
||||
#define REG_TIMER1 *reinterpret_cast<volatile uint16_t*>(0x0400'0104)
|
||||
#define REG_TIMER1CTL *reinterpret_cast<volatile uint16_t*>(0x0400'0106)
|
||||
#define REG_TIMER1 (*reinterpret_cast<volatile uint16_t*>(0x0400'0104))
|
||||
#define REG_TIMER1CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'0106))
|
||||
|
||||
#define REG_TIMER2 *reinterpret_cast<volatile uint16_t*>(0x0400'0108)
|
||||
#define REG_TIMER2CTL *reinterpret_cast<volatile uint16_t*>(0x0400'010a)
|
||||
#define REG_TIMER2 (*reinterpret_cast<volatile uint16_t*>(0x0400'0108))
|
||||
#define REG_TIMER2CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'010a))
|
||||
|
||||
#define REG_TIMER3 *reinterpret_cast<volatile uint16_t*>(0x0400'010c)
|
||||
#define REG_TIMER3CTL *reinterpret_cast<volatile uint16_t*>(0x0400'010e)
|
||||
#define REG_TIMER3 (*reinterpret_cast<volatile uint16_t*>(0x0400'010c))
|
||||
#define REG_TIMER3CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'010e))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// background registers
|
||||
|
||||
// background control registers
|
||||
using BgCtl = uint16_t;
|
||||
#define REG_BG0CTL *reinterpret_cast<volatile BgCtl*>(0x0400'0008)
|
||||
#define REG_BG1CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000a)
|
||||
#define REG_BG2CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000c)
|
||||
#define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e)
|
||||
#define REG_BG0CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'0008))
|
||||
#define REG_BG1CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000a))
|
||||
#define REG_BG2CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000c))
|
||||
#define REG_BG3CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000e))
|
||||
|
||||
[[nodiscard]]
|
||||
inline volatile BgCtl ®BgCtl(uintptr_t bgIdx) noexcept {
|
||||
inline volatile BgCtl ®BgCtl(uintptr_t const bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx);
|
||||
}
|
||||
|
||||
// background horizontal scrolling registers
|
||||
#define REG_BG0HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0010)
|
||||
#define REG_BG1HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0014)
|
||||
#define REG_BG2HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0018)
|
||||
#define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c)
|
||||
#define REG_BG0HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0010))
|
||||
#define REG_BG1HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0014))
|
||||
#define REG_BG2HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0018))
|
||||
#define REG_BG3HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001c))
|
||||
|
||||
[[nodiscard]]
|
||||
inline volatile uint32_t ®BgHofs(auto bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx);
|
||||
volatile int16_t ®BgHofs(auto const bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile int16_t*>(0x0400'0010 + 4 * bgIdx);
|
||||
}
|
||||
|
||||
// background vertical scrolling registers
|
||||
#define REG_BG0VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0012)
|
||||
#define REG_BG1VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0016)
|
||||
#define REG_BG2VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001a)
|
||||
#define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e)
|
||||
#define REG_BG0VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0012))
|
||||
#define REG_BG1VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0016))
|
||||
#define REG_BG2VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001a))
|
||||
#define REG_BG3VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001e))
|
||||
|
||||
[[nodiscard]]
|
||||
inline volatile uint32_t ®BgVofs(auto bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx);
|
||||
volatile int16_t ®BgVofs(auto const bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile int16_t*>(0x0400'0012 + 4 * bgIdx);
|
||||
}
|
||||
|
||||
// background scrolling registers
|
||||
|
||||
struct OffsetPair {
|
||||
int16_t x{}, y{};
|
||||
};
|
||||
|
||||
#define REG_BG0OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0010))
|
||||
#define REG_BG1OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0014))
|
||||
#define REG_BG2OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0018))
|
||||
#define REG_BG3OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'001c))
|
||||
|
||||
[[nodiscard]]
|
||||
volatile OffsetPair ®BgOfs(auto const bgIdx) noexcept {
|
||||
return *reinterpret_cast<volatile OffsetPair*>(0x0400'0010 + sizeof(OffsetPair) * bgIdx);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// User Input
|
||||
|
||||
#define REG_GAMEPAD *reinterpret_cast<volatile uint16_t*>(0x0400'0130)
|
||||
#define REG_GAMEPAD (*reinterpret_cast<volatile uint16_t*>(0x0400'0130))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Memory Addresses
|
||||
|
||||
#define MEM_EWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0200'0000)
|
||||
#define MEM_EWRAM_END reinterpret_cast<uint8_t*>(0x0203'FFFF)
|
||||
#define MEM_EWRAM (*(reinterpret_cast<ox::Array<uint16_t, 0x0203'FFFF - 0x0200'0000>*>(0x0200'0000)))
|
||||
|
||||
#define MEM_IWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0300'0000)
|
||||
#define MEM_IWRAM_END reinterpret_cast<uint8_t*>(0x0300'7FFF)
|
||||
#define MEM_IWRAM (*(reinterpret_cast<ox::Array<uint8_t, 0x0300'7FFF - 0x0300'0000>*>(0x0300'0000)))
|
||||
|
||||
#define REG_BLNDCTL *reinterpret_cast<uint16_t*>(0x0400'0050)
|
||||
#define REG_BLNDCTL (*reinterpret_cast<uint16_t*>(0x0400'0050))
|
||||
|
||||
#define MEM_BG_PALETTE reinterpret_cast<uint16_t*>(0x0500'0000)
|
||||
#define MEM_SPRITE_PALETTE reinterpret_cast<uint16_t*>(0x0500'0200)
|
||||
using Palette = ox::Array<uint16_t, 128>;
|
||||
#define MEM_BG_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0000)))
|
||||
#define MEM_SPRITE_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0200)))
|
||||
|
||||
using BgMapTile = ox::Array<uint16_t, 8192>;
|
||||
#define MEM_BG_TILES reinterpret_cast<BgMapTile*>(0x0600'0000)
|
||||
#define MEM_BG_MAP reinterpret_cast<BgMapTile*>(0x0600'e000)
|
||||
#define MEM_BG_TILES (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'0000)))
|
||||
#define MEM_BG_MAP (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'e000)))
|
||||
|
||||
#define MEM_SPRITE_TILES reinterpret_cast<uint16_t*>(0x0601'0000)
|
||||
#define MEM_OAM reinterpret_cast<uint64_t*>(0x0700'0000)
|
||||
#define MEM_SPRITE_TILES (*(reinterpret_cast<ox::Array<uint16_t, 32 * ox::units::KB>*>(0x0601'0000)))
|
||||
#define MEM_OAM (*(reinterpret_cast<ox::Array<uint64_t, 64>*>(0x0700'0000)))
|
||||
|
||||
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000)
|
||||
#define MEM_ROM (*(reinterpret_cast<ox::Array<char, 32 * ox::units::MB>*>(0x0700'0000)))
|
||||
|
||||
#define MEM_SRAM reinterpret_cast<char*>(0x0e00'0000)
|
||||
#define MEM_SRAM_SIZE 65535
|
||||
#define MEM_SRAM (*(reinterpret_cast<ox::Array<char, 64 * ox::units::KB>*>(0x0e00'0000)))
|
||||
|
||||
4
deps/teagba/include/teagba/gfx.hpp
vendored
4
deps/teagba/include/teagba/gfx.hpp
vendored
@@ -37,8 +37,10 @@ struct OX_ALIGN8 GbaSpriteAttrUpdate {
|
||||
|
||||
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept;
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;
|
||||
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept;
|
||||
|
||||
void applySpriteUpdates() noexcept;
|
||||
|
||||
void setBgOffset(uint16_t bg, int16_t x, int16_t y) noexcept;
|
||||
|
||||
}
|
||||
|
||||
8
deps/teagba/src/cstartup.cpp
vendored
8
deps/teagba/src/cstartup.cpp
vendored
@@ -2,6 +2,8 @@
|
||||
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#include <ox/std/heapmgr.hpp>
|
||||
|
||||
#include <teagba/bios.hpp>
|
||||
@@ -24,7 +26,7 @@ extern void (*__preinit_array_end[]) (void);
|
||||
extern void (*__init_array_start[]) (void);
|
||||
extern void (*__init_array_end[]) (void);
|
||||
|
||||
int main(int argc, const char **argv);
|
||||
int main(int argc, char const **argv);
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -48,7 +50,7 @@ void __libc_init_array() {
|
||||
}
|
||||
|
||||
int c_start() {
|
||||
const char *args[2] = {"", "rom.oxfs"};
|
||||
char const *args[2] = {"", "rom.oxfs"};
|
||||
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
|
||||
mgba::initConsole();
|
||||
#pragma GCC diagnostic push
|
||||
@@ -58,3 +60,5 @@ int c_start() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
12
deps/teagba/src/gfx.cpp
vendored
12
deps/teagba/src/gfx.cpp
vendored
@@ -12,13 +12,13 @@ namespace teagba {
|
||||
|
||||
static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
|
||||
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept {
|
||||
GbaSpriteAttrUpdate &spriteAttr(size_t const i) noexcept {
|
||||
return g_spriteBuffer[i];
|
||||
}
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
|
||||
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept {
|
||||
const auto ie = REG_IE; // disable vblank interrupt handler
|
||||
REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler
|
||||
REG_IE = REG_IE & static_cast<uint16_t>(~Int_vblank); // disable vblank interrupt handler
|
||||
g_spriteBuffer[upd.idx] = upd;
|
||||
REG_IE = ie; // enable vblank interrupt handler
|
||||
}
|
||||
@@ -29,4 +29,10 @@ void applySpriteUpdates() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void setBgOffset(uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
||||
auto &o = regBgOfs(bg);
|
||||
o.x = x;
|
||||
o.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ All components have a platform indicator next to them:
|
||||
* opengl - OpenGL implementation (P-)
|
||||
* studio - studio plugin for core (P-)
|
||||
* keel - keel plugin for core (PG)
|
||||
* scene - defines & processes map data (PG)
|
||||
* studio - studio plugin for scene (P-)
|
||||
* keel - keel plugin for scene (PG)
|
||||
* sound - sound system for Nostalgia (PG)
|
||||
* studio - studio plugin for sound (P-)
|
||||
* keel - keel plugin for sound (PG)
|
||||
* player - plays the games (PG)
|
||||
* studio - makes the games (P-)
|
||||
* tools - command line tools (P-)
|
||||
@@ -48,7 +48,7 @@ All components have a platform indicator next to them:
|
||||
Not really that external... (PG)
|
||||
* GlUtils - OpenGL helpers (P-)
|
||||
* teagba - GBA assembly startup code (mostly pulled from devkitPro under MPL
|
||||
2.0), and custom GBA hardware interop code (-G)
|
||||
2.0), and custom GBA hardware interop code (-G)
|
||||
|
||||
Most GBA code is built on PC because it is small and helps to work on both
|
||||
projects with the same CMake build dir, but GBA code is never linked with any
|
||||
@@ -89,7 +89,8 @@ The GBA has two major resources for learning about its hardware:
|
||||
|
||||
On the surface, it seems like C++ changes the way we do things from C for no
|
||||
reason, but there are reasons for many of these duplications of functionality.
|
||||
The C++ language designers aren't stupid. Question them, but don't ignore them.
|
||||
The C++ language designers aren't stupid.
|
||||
Question them, but don't ignore them.
|
||||
|
||||
#### Casting
|
||||
|
||||
@@ -163,10 +164,11 @@ The Ox way of doing things is the Olympic way of doing things.
|
||||
### Error Handling
|
||||
|
||||
Instead of throwing exceptions, generally try to use
|
||||
[ox::Errors](deps/ox/ox-docs.md#error-handling) for error reporting,
|
||||
but exceptions may be used where they make sense.
|
||||
[ox::Error](deps/ox/ox-docs.md#error-handling) for error reporting.
|
||||
Exceptions may be used where errors-as-values will not work, but catch them and
|
||||
convert them to ```ox::Error``` as soon as possible.
|
||||
|
||||
Exceptions should generally just use ```OxException```, which is bascially an
|
||||
Exceptions should generally just use ```ox::Exception```, which is basically an
|
||||
exception form of ```ox::Error```.
|
||||
|
||||
### File I/O
|
||||
|
||||
@@ -1,4 +1,60 @@
|
||||
# d2025.02
|
||||
# NEXT
|
||||
|
||||
* Add Get Info file dialog option in project explorer
|
||||
|
||||
# d2025.07.0
|
||||
|
||||
* Add sub-command for exporting TileSheets as PNG files.
|
||||
* Add 'Reload Project' menu item under File.
|
||||
* Fix opening a project to mark an unopenable file as closed in the config file on startup.
|
||||
|
||||
# d2025.06.0
|
||||
|
||||
* Add ability to remember recent projects in config
|
||||
* Add navigation support (back and forward)
|
||||
* Fix file deletion to close file even if not active
|
||||
* Fix file copy to work when creating a copy with the name of a previously
|
||||
deleted file
|
||||
* Fix crash that could occur after switching projects
|
||||
* Make file picker popup accept on double click of a file
|
||||
* TileSheetEditor: Fix copy/cut/paste enablement when there is no selection
|
||||
* TileSheetEditor: Fix manual redo of draw actions, fix drawing to pixel 0, 0
|
||||
as first action
|
||||
* TileSheetEditor: Fix draw command to work on same pixel after switching
|
||||
subsheets
|
||||
* PaletteEditor: Add RGB key shortcuts for focusing color channels
|
||||
* PaletteEditor: Add color preview to color editor
|
||||
|
||||
# d2025.05.1
|
||||
|
||||
* TileSheetEditor: Fix overrun errors when switching subsheets, clear selection
|
||||
on switch (261e324acd)
|
||||
* Fix new build error that occurs in MSVC (26d5048e6720c4c2d52508a6ee44c67dd9fe3ee5)
|
||||
|
||||
# d2025.05.0
|
||||
|
||||
* Add app icon for both window and file
|
||||
* Change application font to Roboto Medium
|
||||
* Closing application will now confirm with user if any files have unsaved
|
||||
changes.
|
||||
* UUID duplicates will now be reported when opening a project.
|
||||
* Deleting a directory now closes files in that directory.
|
||||
* Delete key now initiates deletion of selected directory.
|
||||
* Remove ability to re-order tabs. There were bugs associated with that.
|
||||
* Mac: Menu bar shortcuts now say Cmd instead of Ctrl.
|
||||
* TileSheetEditor: Fix selection clearing to work when clicking outside image.
|
||||
* TileSheetEditor: Fix Delete Tile functionality, which was completely broken
|
||||
* TileSheetEditor: Fix Insert Tile functionality, which was completely broken
|
||||
* PaletteEditor: Fix color number key range. Previously, pressing A caused the
|
||||
editor to jump to the last color.
|
||||
* PaletteEditor: Page rename will now take effect upon pressing enter if the
|
||||
text input has focus
|
||||
|
||||
# d2025.02.1
|
||||
|
||||
* Fix closing tab with unsaved changes (a44c5acc4b)
|
||||
|
||||
# d2025.02.0
|
||||
|
||||
* Rename core namespace to gfx.
|
||||
* Add PaletteV5 to accommodate namespace change.
|
||||
|
||||
28
sample_project/Palettes/SC9K_Logo.npal
Normal file
28
sample_project/Palettes/SC9K_Logo.npal
Normal file
@@ -0,0 +1,28 @@
|
||||
K1;3d1a77ec-265f-4905-2061-4f1003ee2189;O1;net.drinkingtea.nostalgia.gfx.Palette;5;{
|
||||
"colorNames" :
|
||||
[
|
||||
"Color 1",
|
||||
"Color 2",
|
||||
"Color 3"
|
||||
],
|
||||
"pages" :
|
||||
[
|
||||
{
|
||||
"colors" :
|
||||
[
|
||||
{
|
||||
"b" : 10,
|
||||
"g" : 5,
|
||||
"r" : 5
|
||||
},
|
||||
{},
|
||||
{
|
||||
"b" : 31,
|
||||
"g" : 31,
|
||||
"r" : 31
|
||||
}
|
||||
],
|
||||
"name" : "Page 1"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
269
sample_project/TileSheets/NS_Logo16.nts
Normal file
269
sample_project/TileSheets/NS_Logo16.nts
Normal file
@@ -0,0 +1,269 @@
|
||||
K1;e7ae945e-d6c5-4444-5738-be95b4e5937a;O1;net.drinkingtea.nostalgia.gfx.TileSheet;5;{
|
||||
"bpp" : 4,
|
||||
"defaultPalette" : "uuid://c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed",
|
||||
"subsheet" :
|
||||
{
|
||||
"columns" : 2,
|
||||
"name" : "Root",
|
||||
"pixels" :
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"rows" : 2
|
||||
}
|
||||
}
|
||||
1039
sample_project/TileSheets/NS_Logo32.nts
Normal file
1039
sample_project/TileSheets/NS_Logo32.nts
Normal file
File diff suppressed because it is too large
Load Diff
4111
sample_project/TileSheets/NS_Logo64.nts
Normal file
4111
sample_project/TileSheets/NS_Logo64.nts
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user