Compare commits

...

24 Commits

Author SHA1 Message Date
889fe04255 [nostalgia/studio] Set version to 2024.05.0
All checks were successful
Build / build (push) Successful in 2m29s
2024-05-23 22:11:52 -05:00
eed115b287 [keel] Fix a GCC break
All checks were successful
Build / build (push) Successful in 2m39s
2024-05-17 21:13:15 -05:00
7233da75ea [ox/std] Remove dedicated keys array from SmallMap
All checks were successful
Build / build (push) Successful in 2m31s
2024-05-11 01:59:40 -05:00
30797c710b [ox/std] Add small sz option to SmallMap 2024-05-11 00:53:31 -05:00
e8041121d0 [ox/std] Add missing oxExpect to timeMapStrToUuid
All checks were successful
Build / build (push) Successful in 2m32s
2024-05-11 00:26:57 -05:00
d054528e49 [ox/std] Remove empty if from SmallMap
Some checks failed
Build / build (push) Has been cancelled
2024-05-11 00:24:37 -05:00
09d840cfd0 [ox/std] Add some functions for comparing HashMap and SmallMap
All checks were successful
Build / build (push) Successful in 2m31s
2024-05-10 23:58:35 -05:00
aeb1ef3b12 [ox/std] Cleanup SmallMap, make it easier to make potential changes 2024-05-10 23:58:22 -05:00
b66f61c217 [ox/std] Add hash function for UUID 2024-05-10 23:55:41 -05:00
b089bf460b [ox/std] Optimize Array compare 2024-05-10 23:54:22 -05:00
cd60c4abaf [ox/std] Fix bugs in HashMap and SmallMap
All checks were successful
Build / build (push) Successful in 2m30s
2024-05-10 22:10:34 -05:00
d1845448c3 [ox/std] Add == and != operators to UUID 2024-05-10 22:10:14 -05:00
c4f6ee0026 [nostalgia,olympic] Make performPackTransforms update type id when needed 2024-05-10 19:51:03 -05:00
17f28d43d1 [ox/clargs] Replace C string with StringView
All checks were successful
Build / build (push) Successful in 2m27s
2024-05-10 01:30:54 -05:00
043df533b7 [ox] Cleanup string len handling
Some checks failed
Build / build (push) Has been cancelled
Remove UTF-8 parsing. It is a rare enough need that it should have a specialized call when needed.
Better to have a more optimal length fetch for typical case.
2024-05-10 01:29:13 -05:00
bec75d2eba [ox/std] Fix memory leak in Vector 2024-05-09 23:12:36 -05:00
f624c720f9 [studio] Fix broken readClaw call
All checks were successful
Build / build (push) Successful in 2m29s
2024-05-08 23:54:06 -05:00
204e5bbff4 [ox/std] Add SmallMap
All checks were successful
Build / build (push) Successful in 2m28s
2024-05-08 23:46:12 -05:00
1ecf197a9e [nostalgia] Remove .idea directory 2024-05-08 23:44:05 -05:00
74a8a7d751 [ox/std] Remove incomplete writeF32toa
All checks were successful
Build / build (push) Successful in 2m28s
2024-05-08 23:43:12 -05:00
331f721292 [olympic,nostalgia] Cleanup
All checks were successful
Build / build (push) Successful in 2m31s
2024-05-08 23:35:34 -05:00
63486c23d4 [ox] Cleanup 2024-05-08 23:35:05 -05:00
47a6a410c4 [ox/std] Update Vector memory map for preloader
All checks were successful
Build / build (push) Successful in 2m31s
2024-05-03 23:41:16 -05:00
d82c082256 [buildcore] Add error message to pybb debug for missing debugger
All checks were successful
Build / build (push) Successful in 2m29s
2024-05-03 22:58:36 -05:00
62 changed files with 857 additions and 509 deletions

8
.idea/.gitignore generated vendored
View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -1,22 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C>
<option name="INDENT_NAMESPACE_MEMBERS" value="0" />
<option name="INDENT_CLASS_MEMBERS" value="8" />
<option name="INDENT_VISIBILITY_KEYWORDS" value="4" />
</Objective-C>
<Objective-C-extensions>
<extensions>
<pair source="cpp" header="hpp" fileNamingConvention="LOWERCASE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
<pair source="cu" header="cuh" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
<codeStyleSettings language="ObjectiveC">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="DrinkingTea" />
</state>
</component>

View File

@ -1,17 +0,0 @@
/*
* Copyright 2016 - 2021 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#[[#pragma]]# once
${NAMESPACES_OPEN}
class ${NAME} {
};
${NAMESPACES_CLOSE}

View File

@ -1,13 +0,0 @@
/*
* Copyright 2016 - 2021 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#[[#include]]# "${HEADER_FILENAME}"
${NAMESPACES_OPEN}
${NAMESPACES_CLOSE}

View File

@ -1,24 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
<option name="clangTidyChecks" value="-*,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-convert-member-functions-to-static,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-make-member-function-const,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof,cert-*,misc-*,readability-duplicate-include,-misc-non-private-member-variables-in-classes,-misc-no-recursion,bugprone-*,clang-analyzer-*,modernize-*,portability-*,-modernize-use-trailing-return-type,-bugprone-easily-swappable-parameters" />
</inspection_tool>
<inspection_tool class="Clazy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantConditionsOC" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantFunctionResult" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantParameter" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DanglingPointers" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EndlessLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="InfiniteRecursion" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LocalValueEscapesScope" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LoopDoesntUseConditionVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NullDereference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NullDereferences" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnreachableCallsOfFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnreachableCode" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedParameter" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedValue" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

17
.idea/misc.xml generated
View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompDBSettings">
<option name="linkedExternalProjectsSettings">
<CompDBProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</CompDBProjectSettings>
</option>
</component>
<component name="CompDBWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="ExternalStorageConfigurationManager" enabled="true" />
</project>

8
.idea/nostalgia.iml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8" />
</facet>
</component>
</module>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -98,6 +98,9 @@ def debug(paths: List[str]) -> int:
args = ['gdb', '--args']
elif shutil.which('lldb') is not None:
args = ['lldb', '--']
else:
sys.stderr.write('debug: could not find a supported debugger\n')
return 1
args.extend(paths)
return subprocess.run(args).returncode

View File

@ -42,9 +42,9 @@ bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept {
return !err ? *value : defaultValue;
}
String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept {
String ClArgs::getString(ox::CRStringView arg, ox::StringView defaultValue) const noexcept {
auto [value, err] = m_strings.at(arg);
return !err ? ox::String(std::move(*value)) : ox::String(defaultValue);
return !err ? ox::String(*value) : ox::String(defaultValue);
}
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {

View File

@ -26,7 +26,7 @@ class ClArgs {
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
[[nodiscard]]
String getString(ox::CRStringView argName, const char *defaultValue) const noexcept;
String getString(ox::CRStringView argName, ox::StringView defaultValue) const noexcept;
[[nodiscard]]
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;

View File

@ -12,34 +12,66 @@
namespace ox {
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept {
const auto s1End = ox::strchr(buff, ';', buffLen);
ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
auto buffRaw = buff.data();
auto buffLen = buff.size();
size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) {
return OxError(1, "Could not read Claw header");
}
const auto s1Size = static_cast<std::size_t>(s1End - buff);
const String fmt(buff, s1Size);
buff += s1Size + 1;
buffLen -= s1Size + 1;
const auto s2End = ox::strchr(buff, ';', buffLen);
auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
buffRaw += fmtSz;
buffLen -= fmtSz;
outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) {
return OxError(2, "Could not read Claw header");
}
const auto s2Size = static_cast<std::size_t>(s2End - buff);
const String typeName(buff, s2Size);
buff += s2Size + 1;
buffLen -= s2Size + 1;
const auto s3End = ox::strchr(buff, ';', buffLen);
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
buffRaw += s2Size;
buffLen -= s2Size;
outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
if (!s3End) {
return OxError(3, "Could not read Claw header");
}
const auto s3Size = static_cast<std::size_t>(s3End - buff);
const String versionStr(buff, s3Size);
buff += s3Size + 1;
buffLen -= s3Size + 1;
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
buffRaw += s3Size;
buffLen -= s3Size;
outSz += s3Size;
return {{buff.data() + fmtSz, outSz - fmtSz - 1}};
}
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffRaw = buff.data();
auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) {
return OxError(1, "Could not read Claw header");
}
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
StringView const fmt(buffRaw, s1Size);
buffRaw += s1Size + 1;
buffLen -= s1Size + 1;
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) {
return OxError(2, "Could not read Claw header");
}
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
StringView const typeName(buffRaw, s2Size);
buffRaw += s2Size + 1;
buffLen -= s2Size + 1;
auto const s3End = ox::strchr(buffRaw, ';', buffLen);
if (!s3End) {
return OxError(3, "Could not read Claw header");
}
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
StringView const versionStr(buffRaw, s3Size);
buffRaw += s3Size + 1;
buffLen -= s3Size + 1;
ClawHeader hdr;
if (fmt == "M2") {
hdr.fmt = ClawFormat::Metal;
@ -49,32 +81,21 @@ Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcep
return OxError(4, "Claw format does not match any supported format/version combo");
}
hdr.typeName = typeName;
if (auto r = ox::atoi(versionStr.c_str()); r.error == 0) {
hdr.typeVersion = r.value;
}
hdr.data = buff;
std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
hdr.data = buffRaw;
hdr.dataSize = buffLen;
return hdr;
}
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept {
return readClawHeader(buff.data(), buff.size());
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff));
return {{header.data, header.dataSize}};
}
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept {
oxRequire(header, readClawHeader(buff, buffLen));
Buffer out(header.dataSize);
ox::listcpy(out.data(), header.data, out.size());
return out;
}
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
return stripClawHeader(buff.data(), buff.size());
}
Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept {
oxRequire(header, readClawHeader(buff, buffSz));
auto const [t, tdErr] = ts.getLoad(header.typeName, header.typeVersion, header.typeParams);
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff));
auto const [t, tdErr] = ts.getLoad(
header.typeName, header.typeVersion, header.typeParams);
if (tdErr) {
return OxError(3, "Could not load type descriptor");
}
@ -83,7 +104,7 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
switch (header.fmt) {
case ClawFormat::Metal:
{
ox::BufferReader br(header.data, header.dataSize);
ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br);
ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj));
@ -92,7 +113,7 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
case ClawFormat::Organic:
{
#ifdef OX_USE_STDLIB
OrganicClawReader reader(header.data, header.dataSize);
OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj));
return obj;
@ -106,8 +127,4 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
return OxError(1);
}
Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept {
return readClaw(ts, buff.data(), buff.size());
}
}

View File

@ -8,6 +8,7 @@
#pragma once
#include <ox/std/span.hpp>
#include <ox/mc/read.hpp>
#ifdef OX_USE_STDLIB
#include <ox/oc/read.hpp>
@ -31,17 +32,15 @@ struct ClawHeader {
std::size_t dataSize = 0;
};
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept;
ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept;
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept;
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept;
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept;
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept;
Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
template<typename T>
Error readClaw(const char *buff, std::size_t buffLen, T *val) {
oxRequire(header, readClawHeader(buff, buffLen));
Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff));
if (header.typeName != getModelTypeName<T>()) {
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
}
@ -51,16 +50,16 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
switch (header.fmt) {
case ClawFormat::Metal:
{
ox::BufferReader br(header.data, header.dataSize);
ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br);
ModelHandlerInterface handler(&reader);
return model(&handler, val);
return model(&handler, &val);
}
case ClawFormat::Organic:
{
#ifdef OX_USE_STDLIB
OrganicClawReader reader(header.data, header.dataSize);
return model(&reader, val);
return model(&reader, &val);
#else
break;
#endif
@ -72,24 +71,12 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
}
template<typename T>
Result<T> readClaw(const char *buff, std::size_t buffLen) {
T val;
oxReturnError(readClaw(buff, buffLen, &val));
Result<T> readClaw(ox::BufferView buff) {
Result<T> val;
oxReturnError(readClaw(buff, val.value));
return val;
}
template<typename T>
Error readClaw(const Buffer &buff, T *val) {
return readClaw<T>(buff.data(), buff.size(), val);
}
template<typename T>
Result<T> readClaw(const Buffer &buff) {
return readClaw<T>(buff.data(), buff.size());
}
Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept;
Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept;
Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept;
}

View File

@ -10,5 +10,6 @@ target_link_libraries(
add_test("[ox/claw] ClawHeaderReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader)
add_test("[ox/claw] ClawHeaderReader2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader2)
add_test("[ox/claw] ClawHeaderReadTypeId" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReadTypeId)
add_test("[ox/claw] ClawWriter" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawWriter)
add_test("[ox/claw] ClawReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawReader)

View File

@ -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.len() + 1});
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
@ -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.len() + 1});
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
@ -129,6 +129,16 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"ClawHeaderReadTypeId",
[] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
oxExpect(actual, expected);
return ox::Error{};
}
},
{
"ClawWriter",
[] {
@ -156,7 +166,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Struct.String = "Test String 2";
const auto [buff, err] = ox::writeMC(testIn);
oxAssert(err, "writeClaw failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readClaw failed");
oxAssert(ox::readMC(buff, testOut), "readClaw failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");

View File

@ -159,7 +159,7 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, Fi
// determine if already exists
auto name = nameBuff;
oxReturnError(path.get(name));
oxReturnError(path.get(*name));
auto childInode = find(PathIterator(*name));
if (!childInode.ok()) {
// if this is not the last item in the path and parents is disabled,
@ -203,7 +203,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
auto name = nameBuff;
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
oxReturnError(path.get(name));
oxReturnError(path.get(*name));
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
*name, path.fullPath());
oxRequire(nextChild, findEntry(*name));
@ -222,7 +222,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
// insert the new entry on this directory
// get the name
oxReturnError(path.next(name));
oxReturnError(path.next(*name));
// find existing version of directory
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
@ -263,7 +263,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameB
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
}
auto &name = *nameBuff;
oxReturnError(path.get(&name));
oxReturnError(path.get(name));
oxTrace("ox.fs.Directory.remove", name);
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
@ -343,7 +343,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(Path
// determine if already exists
auto name = nameBuff;
oxReturnError(path.get(name));
oxReturnError(path.get(*name));
oxRequire(v, findEntry(*name));
// recurse if not at end of path

View File

@ -61,8 +61,9 @@ Error PathIterator::fileName(char *out, std::size_t outSize) {
}
// Gets the get item in the path
Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
Error PathIterator::get(IString<MaxFileNameLength> &fileName) {
std::size_t size = 0;
std::ignore = fileName.resize(MaxFileNameLength);
if (m_iterator >= m_maxSize) {
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
return OxError(1);
@ -84,22 +85,25 @@ Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
const auto end = static_cast<size_t>(substr - m_path);
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize || size == 0) {
if (size >= MaxFileNameLength || size == 0) {
return OxError(1);
}
ox::memcpy(pathOut, &m_path[start], size);
ox::memcpy(fileName.data(), &m_path[start], size);
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
if (size && fileName[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
return OxError(0);
oxReturnError(fileName.resize(size));
return {};
}
// Gets the get item in the path
Error PathIterator::next(char *pathOut, std::size_t pathOutSize) {
/**
* @return 0 if no error
*/
Error PathIterator::next(IString<MaxFileNameLength> &fileName) {
std::size_t size = 0;
auto retval = OxError(1);
std::ignore = fileName.resize(MaxFileNameLength);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = OxError(0);
if (m_path[m_iterator] == '/') {
@ -115,34 +119,21 @@ Error PathIterator::next(char *pathOut, std::size_t pathOutSize) {
const auto end = static_cast<size_t>(substr - m_path);
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize) {
if (size >= MaxFileNameLength) {
return OxError(1);
}
ox::memcpy(pathOut, &m_path[start], size);
ox::memcpy(fileName.data(), &m_path[start], size);
}
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
if (size && fileName[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
fileName[size] = 0; // end with null terminator
oxReturnError(fileName.resize(size));
m_iterator += size;
return retval;
}
/**
* @return 0 if no error
*/
Error PathIterator::get(IString<MaxFileNameLength> *fileName) {
return get(fileName->data(), fileName->cap());
}
/**
* @return 0 if no error
*/
Error PathIterator::next(IString<MaxFileNameLength> *fileName) {
return next(fileName->data(), fileName->cap());
}
Result<std::size_t> PathIterator::nextSize() const {
std::size_t size = 0;
auto retval = OxError(1);

View File

@ -41,22 +41,12 @@ class PathIterator {
/**
* @return 0 if no error
*/
Error next(char *pathOut, std::size_t pathOutSize);
Error next(FileName &fileName);
/**
* @return 0 if no error
*/
Error get(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error next(FileName *fileName);
/**
* @return 0 if no error
*/
Error get(FileName *fileName);
Error get(FileName &fileName);
/**
* @return 0 if no error

View File

@ -60,10 +60,10 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
ox::FileName buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
return OxError(0);
}
},
@ -72,9 +72,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("/usr/share/");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
return OxError(0);
}
},
@ -83,8 +83,8 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("/");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
return OxError(0);
}
},
@ -93,10 +93,10 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
return OxError(0);
}
},
@ -105,9 +105,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
[](ox::StringView) {
auto const path = ox::String("usr/share/");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff, path.len()) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
ox::FileName buff;
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
return OxError(0);
}
},
@ -237,8 +237,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
};
int main(int argc, const char **args) {
if (argc < 3) {
oxError("Must specify test to run and test argument");
if (argc < 2) {
oxError("Must specify test to run");
return -1;
}
ox::StringView const testName = args[1];
ox::StringView const testArg = args[2] ? args[2] : nullptr;

View File

@ -185,7 +185,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
template<typename I>
Result<I> decodeInteger(McInt m) noexcept {
std::size_t bytesRead{};
BufferReader br(reinterpret_cast<const char*>(m.data), 9);
BufferReader br({reinterpret_cast<const char*>(m.data), 9});
return decodeInteger<I>(br, &bytesRead);
}

View File

@ -322,9 +322,6 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
*val = BasicString<SmallStringSize>(cap);
auto data = val->data();
// read the string
if (static_cast<StringLength>(cap) < size) {
return OxError(McOutputBuffEnded);
}
oxReturnError(m_reader.read(data, size));
} else {
*val = "";
@ -336,8 +333,23 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
template<Reader_c Reader>
template<std::size_t L>
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, IString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap());
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))) {
// read the length
std::size_t bytesRead = 0;
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
*val = IString<L>();
oxReturnError(val->resize(size));
auto const data = val->data();
// read the string
oxReturnError(m_reader.read(data, size));
} else {
*val = "";
}
}
++m_field;
return {};
}
template<Reader_c Reader>
@ -524,25 +536,20 @@ constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
template<typename T>
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
BufferReader br(buff, buffLen);
Error readMC(ox::BufferView buff, T &val) noexcept {
BufferReader br(buff);
MetalClawReader reader(br);
ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader);
return model(&handler, val);
return model(&handler, &val);
}
template<typename T>
Result<T> readMC(const char *buff, std::size_t buffLen) noexcept {
T val;
oxReturnError(readMC(buff, buffLen, &val));
Result<T> readMC(ox::BufferView buff) noexcept {
Result<T> val;
oxReturnError(readMC(buff, val.value));
return val;
}
template<typename T>
Result<T> readMC(const Buffer &buff) noexcept {
return readMC<T>(buff.data(), buff.size());
}
extern template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
}

View File

@ -143,7 +143,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// run tests
const auto [buff, err] = ox::writeMC(testIn);
oxAssert(err, "writeMC failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readMC failed");
oxAssert(ox::readMC(buff, testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
@ -157,7 +157,8 @@ 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");
oxAssert(testIn.IString == testOut.IString, "IString value mismatch");
oxDebugf("{}", testOut.IString.len());
oxExpect(testIn.IString, testOut.IString);
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
@ -319,7 +320,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut;
oxReturnError(testOut.setType(type));
oxAssert(ox::readMC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
oxAssert(testOut.at("IString").unwrap()->get<ox::String>() == testIn.IString.c_str(), "testOut.String failed");
@ -369,7 +370,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
ox::TypeStore typeStore;
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(typeErr, "Descriptor write failed");
ox::BufferReader br(dataBuff, dataBuffLen);
ox::BufferReader br({dataBuff, dataBuffLen});
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n';

View File

@ -207,7 +207,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<Sm
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->cap());
return fieldCString(name, val->data(), val->len());
}
template<Writer_c Writer>

View File

@ -37,12 +37,12 @@ constexpr auto buildTypeId() noexcept {
static constexpr auto buildTypeId(CRStringView name, int version,
const TypeParamPack &typeParams = {}) noexcept {
String tp;
if (typeParams.size()) {
if (!typeParams.empty()) {
tp = "#";
for (const auto &p : typeParams) {
tp += p + ",";
}
tp = tp.substr(0, tp.len() - 1);
tp.resize(tp.len() - 1);
tp += "#";
}
return ox::sfmt("{}{};{}", name, tp, version);

View File

@ -97,6 +97,7 @@ struct TypeInfoCatcher {
};
template<typename T>
[[nodiscard]]
constexpr int getModelTypeVersion(T *val) noexcept {
TypeInfoCatcher nc;
std::ignore = model(&nc, val);
@ -104,6 +105,7 @@ constexpr int getModelTypeVersion(T *val) noexcept {
}
template<typename T>
[[nodiscard]]
constexpr int getModelTypeVersion() noexcept {
std::allocator<T> a;
const auto t = a.allocate(1);
@ -113,6 +115,7 @@ constexpr int getModelTypeVersion() noexcept {
}
template<typename T>
[[nodiscard]]
consteval int requireModelTypeVersion() noexcept {
constexpr auto version = getModelTypeVersion<T>();
static_assert(version != 0, "TypeVersion is required");
@ -120,6 +123,7 @@ consteval int requireModelTypeVersion() noexcept {
}
template<typename T, typename Str = const char*>
[[nodiscard]]
constexpr Str getModelTypeName(T *val) noexcept {
TypeNameCatcher nc;
std::ignore = model(&nc, val);
@ -127,6 +131,7 @@ constexpr Str getModelTypeName(T *val) noexcept {
}
template<typename T, typename Str = const char*>
[[nodiscard]]
constexpr Str getModelTypeName() noexcept {
std::allocator<T> a;
auto t = a.allocate(1);
@ -136,8 +141,10 @@ constexpr Str getModelTypeName() noexcept {
}
template<typename T>
[[nodiscard]]
consteval auto requireModelTypeName() noexcept {
constexpr auto name = getModelTypeName<T>();
static_assert(ox::StringView{name}.len(), "Type lacks required TypeName");
return name;
}

View File

@ -101,7 +101,7 @@ class TypeStore {
}
protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView) noexcept {
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return OxError(1);
}

View File

@ -207,7 +207,19 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
return fieldCString(key, val->data(), val->cap());
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
*val = IString<L>{};
} else if (jv.isString()) {
*val = jv.asString().c_str();
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
// array handler
@ -246,18 +258,18 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
return OxError(0);
}
Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept {
Error readOC(BufferView buff, auto &val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors.
try {
Json::Value doc;
Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(buff, buff + buffSize, &doc, nullptr)) {
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
return OxError(1, "Could not parse JSON");
}
OrganicClawReader reader(buff, buffSize);
OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader);
return model(&handler, val);
return model(&handler, &val);
} catch (const Error &err) {
return err;
} catch (...) {
@ -266,20 +278,15 @@ Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept {
}
template<typename T>
Result<T> readOC(const char *json, std::size_t jsonLen) noexcept {
T val;
oxReturnError(readOC(json, jsonLen, &val));
Result<T> readOC(BufferView buff) noexcept {
Result<T> val;
oxReturnError(readOC(buff, val.value));
return val;
}
template<typename T>
Result<T> readOC(const char *json) noexcept {
return readOC<T>(json, ox::strlen(json));
}
template<typename T>
Result<T> readOC(const Buffer &buff) noexcept {
return readOC<T>(buff.data(), buff.size());
Result<T> readOC(ox::StringView json) noexcept {
return readOC<T>(ox::BufferView{json.data(), json.len()});
}
}

View File

@ -211,7 +211,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
oxAssert(ox::readOC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");

View File

@ -45,7 +45,7 @@ add_library(
if(NOT MSVC)
target_compile_options(OxStd PRIVATE -Wsign-conversion)
target_compile_options(OxStd PRIVATE -Wconversion)
if(${OX_OS_LINUX})
if(${OX_OS_LINUX} AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(OxStd PUBLIC -export-dynamic)
#target_link_options(OxStd PUBLIC -W1,-E)
elseif(${OX_OS_FREEBSD})
@ -117,6 +117,7 @@ install(
ranges.hpp
serialize.hpp
size.hpp
smallmap.hpp
stacktrace.hpp
std.hpp
stddef.hpp

View File

@ -137,12 +137,16 @@ constexpr Array<T, ArraySize>::Array(Array &&other) noexcept {
template<typename T, std::size_t ArraySize>
constexpr bool Array<T, ArraySize>::operator==(const Array &other) const {
for (std::size_t i = 0; i < ArraySize; i++) {
if (!(m_items[i] == other.m_items[i])) {
return false;
if (std::is_constant_evaluated()) {
for (std::size_t i = 0; i < ArraySize; i++) {
if (!(m_items[i] == other.m_items[i])) {
return false;
}
}
return true;
} else {
return memcmp(this, &other, sizeof(*this)) == 0;
}
return true;
}
template<typename T, std::size_t ArraySize>

View File

@ -10,6 +10,7 @@
#include "error.hpp"
#include "reader.hpp"
#include "span.hpp"
#include "vector.hpp"
#include "writer.hpp"
@ -18,6 +19,7 @@ namespace ox {
extern template class Vector<char>;
using Buffer = Vector<char>;
using BufferView = SpanView<char>;
class BufferWriter {
private:
@ -174,10 +176,7 @@ class BufferReader {
char const* m_buff = nullptr;
public:
constexpr explicit BufferReader(char const*buff, std::size_t sz) noexcept:
m_size(sz), m_buff(buff) {}
constexpr explicit BufferReader(ox::Buffer const&buffer) noexcept:
constexpr explicit BufferReader(ox::BufferView buffer) noexcept:
m_size(buffer.size()), m_buff(buffer.data()) {}
constexpr ox::Result<char> peek() const noexcept {

View File

@ -234,6 +234,22 @@ struct [[nodiscard]] Result {
return value;
}
template<typename U = T>
constexpr ox::Result<U> to() & noexcept {
if (error) [[unlikely]] {
return error;
}
return U(value);
}
template<typename U = T>
constexpr ox::Result<U> to() && noexcept {
if (error) [[unlikely]] {
return error;
}
return U(std::move(value));
}
template<typename U = T>
constexpr ox::Result<U> to(auto const&f) & noexcept {
if (error) [[unlikely]] {

View File

@ -40,12 +40,17 @@ constexpr StringView toStringView(const char *s) noexcept {
template<bool force = false, std::size_t size>
constexpr StringView toStringView(const IString<size> &s) noexcept {
return s.c_str();
return s;
}
template<bool force = false>
constexpr StringView toStringView(ox::StringLiteral s) noexcept {
return s;
}
template<bool force = false, std::size_t size>
constexpr StringView toStringView(const BasicString<size> &s) noexcept {
return s.c_str();
return s;
}
#if __has_include(<string>)

View File

@ -133,17 +133,18 @@ constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> &&other) noexcep
template<typename K, typename T>
constexpr T &HashMap<K, T>::operator[](MaybeView_t<K> const&k) {
auto &p = access(m_pairs, k);
if (p == nullptr) {
auto p = &access(m_pairs, k);
if (*p == nullptr) {
if (static_cast<double>(m_pairs.size()) * 0.7 <
static_cast<double>(m_keys.size())) {
expand();
p = &access(m_pairs, k);
}
p = new Pair;
p->key = k;
*p = new Pair;
(*p)->key = k;
m_keys.emplace_back(k);
}
return p->value;
return (*p)->value;
}
template<typename K, typename T>
@ -208,7 +209,7 @@ constexpr void HashMap<K, T>::clear() {
template<typename K, typename T>
constexpr void HashMap<K, T>::expand() {
Vector<Pair*> r;
Vector<Pair*> r(m_pairs.size() * 2);
for (std::size_t i = 0; i < m_keys.size(); ++i) {
auto const&k = m_keys[i];
access(r, k) = std::move(access(m_pairs, k));
@ -221,7 +222,7 @@ template<typename KK>
constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*> const&pairs, KK const&k) const {
auto h = static_cast<std::size_t>(ox::hash<KK>{}(k) % pairs.size());
while (true) {
const auto &p = pairs[h];
auto const&p = *pairs.at(h).unwrap();
if (p == nullptr || p->key == k) {
return p;
} else {
@ -235,7 +236,7 @@ template<typename KK>
constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pairs, KK const&k) {
auto h = static_cast<std::size_t>(ox::hash<KK>{}(k) % pairs.size());
while (true) {
auto &p = pairs[h];
auto &p = *pairs.at(h).unwrap();
if (p == nullptr || p->key == k) {
return p;
} else {

View File

@ -85,7 +85,9 @@ class IString {
* Returns the capacity of bytes for this string.
*/
[[nodiscard]]
constexpr std::size_t cap() const noexcept;
constexpr static std::size_t cap() noexcept {
return StrCap;
}
};
template<std::size_t size>
@ -113,7 +115,7 @@ constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
template<std::size_t size>
constexpr IString<size> &IString<size>::operator=(ox::CRStringView str) noexcept {
std::size_t strLen = str.bytes() + 1;
std::size_t strLen = str.len();
if (cap() < strLen) {
strLen = cap();
}
@ -126,14 +128,7 @@ constexpr IString<size> &IString<size>::operator=(ox::CRStringView str) noexcept
template<std::size_t size>
constexpr IString<size> &IString<size>::operator=(const char *str) noexcept {
std::size_t strLen = ox::strlen(str) + 1;
if (cap() < strLen) {
strLen = cap();
}
m_size = strLen;
ox::listcpy(m_buff.data(), str, strLen);
// make sure last element is a null terminator
m_buff[cap()] = 0;
operator=(ox::StringView{str});
return *this;
}
@ -170,30 +165,21 @@ 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 currentLen = len();
if (cap() < currentLen + strLen + 1) {
auto const currentLen = len();
if (cap() < currentLen + strLen) {
strLen = cap() - currentLen;
err = OxError(1, "Insufficient space for full string");
}
ox::strncpy(m_buff.data() + currentLen, str, strLen);
// make sure last element is a null terminator
m_buff[currentLen + strLen] = 0;
m_size += strLen;
return err;
}
template<std::size_t StrCap>
constexpr Error IString<StrCap>::append(ox::StringView str) noexcept {
auto strLen = str.len();
Error err{};
auto currentLen = len();
if (cap() < currentLen + strLen + 1) {
strLen = cap() - currentLen;
err = OxError(1, "Insufficient space for full string");
}
ox::strncpy(m_buff.data() + currentLen, str, strLen);
// make sure last element is a null terminator
m_buff[currentLen + strLen] = 0;
return err;
return append(str.data(), str.len());
}
template<std::size_t StrCap>
@ -214,27 +200,12 @@ constexpr const char *IString<StrCap>::c_str() const noexcept {
template<std::size_t StrCap>
constexpr std::size_t IString<StrCap>::len() const noexcept {
std::size_t length = 0;
for (std::size_t i = 0; i < StrCap; i++) {
auto const b = static_cast<uint8_t>(m_buff[i]);
if (b) {
const auto asciiChar = (b & 128) == 0;
const auto utf8Char = (b & (256 << 6)) == (256 << 6);
if (asciiChar || utf8Char) {
length++;
}
} else {
break;
}
}
return length;
return m_size;
}
template<std::size_t StrCap>
constexpr std::size_t IString<StrCap>::bytes() const noexcept {
std::size_t i = 0;
for (i = 0; i < StrCap && m_buff[i]; i++);
return i + 1; // add one for null terminator
return m_size + 1;
}
template<std::size_t StrCap>
@ -249,11 +220,6 @@ constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
return {};
}
template<std::size_t StrCap>
constexpr std::size_t IString<StrCap>::cap() const noexcept {
return StrCap;
}
template<size_t sz>
struct MaybeView<ox::IString<sz>> {
using type = ox::StringView;

View File

@ -33,7 +33,7 @@ template<typename T1, typename T2>
constexpr T1 *listcpy(T1 *dest, T2 *src, std::size_t maxLen) noexcept {
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
std::size_t i = 0;
while (i < maxLen && src[i]) {
while (i < maxLen) {
dest[i] = static_cast<T1Type>(src[i]);
++i;
}

View File

@ -19,7 +19,6 @@ namespace ox {
template<typename PlatSpec>
struct VectorMemMap {
const std::size_t smallVecSize = 0; // not a map value
uint8_t allocator = 0;
typename PlatSpec::size_t size = 0;
typename PlatSpec::size_t cap = 0;
typename PlatSpec::PtrType items = 0;
@ -34,10 +33,8 @@ constexpr auto sizeOf(const VectorMemMap<PlatSpec> *t) noexcept {
std::size_t size = 0;
if (t->smallVecSize) {
size += t->smallVecSize;
size += padding(size, PlatSpec::alignOf(t->allocator));
size += padding(size, PlatSpec::alignOf(t->size));
}
size += sizeof(t->allocator);
size += padding(size, PlatSpec::alignOf(t->size));
size += sizeof(t->size);
size += padding(size, PlatSpec::alignOf(t->cap));
size += sizeof(t->cap);
@ -67,8 +64,6 @@ 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 {
oxReturnError(w.write(nullptr, vm.smallVecSize));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.allocator)));
oxReturnError(pad<PlatSpec>(w, &vm.size));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.size)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.cap)));
oxReturnError(serialize(w, PlatSpec::correctEndianness(vm.items)));

249
deps/ox/src/ox/std/smallmap.hpp vendored Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright 2015 - 2024 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "algorithm.hpp"
#include "hash.hpp"
#include "ignore.hpp"
#include "stringview.hpp"
#include "strops.hpp"
#include "vector.hpp"
namespace ox {
template<typename K, typename T, size_t SmallSz = 0>
class SmallMap {
public:
using key_t = K;
using value_t = T;
struct Pair {
K key = {};
T value{};
};
private:
using PairVector = Vector<Pair, SmallSz>;
PairVector m_pairs;
public:
constexpr SmallMap() = default;
constexpr SmallMap(SmallMap const&other);
constexpr SmallMap(SmallMap &&other) noexcept;
constexpr ~SmallMap();
constexpr bool operator==(SmallMap const&other) const;
constexpr SmallMap &operator=(SmallMap const&other);
constexpr SmallMap &operator=(SmallMap &&other) noexcept;
constexpr T &operator[](MaybeView_t<K> const&key);
constexpr Result<T*> at(MaybeView_t<K> const&key) noexcept;
constexpr Result<const T*> at(MaybeView_t<K> const&key) const noexcept;
constexpr void erase(MaybeView_t<K> const&key);
[[nodiscard]]
constexpr bool contains(MaybeView_t<K> const&key) const noexcept;
[[nodiscard]]
constexpr std::size_t size() const noexcept;
[[nodiscard]]
constexpr Vector<K> keys() const noexcept;
[[nodiscard]]
constexpr K const&key(size_t i) const noexcept;
[[nodiscard]]
constexpr T const&value(size_t i) const noexcept;
[[nodiscard]]
constexpr T &value(size_t i) noexcept;
[[nodiscard]]
constexpr Pair const&get(size_t i) const noexcept;
[[nodiscard]]
constexpr Pair &get(size_t i) noexcept;
constexpr void clear();
private:
template<typename KK>
constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const;
template<typename KK>
constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew);
};
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::SmallMap(SmallMap<K, T, SmallSz> const&other) {
m_pairs = other.m_pairs;
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::SmallMap(SmallMap<K, T, SmallSz> &&other) noexcept {
m_pairs = std::move(other.m_pairs);
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::~SmallMap() {
clear();
}
template<typename K, typename T, size_t SmallSz>
constexpr bool SmallMap<K, T, SmallSz>::operator==(SmallMap const&other) const {
return m_pairs == other.m_pairs;
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K, T, SmallSz> const&other) {
if (this != &other) {
clear();
m_pairs = other.m_pairs;
}
return *this;
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K, T, SmallSz> &&other) noexcept {
if (this != &other) {
clear();
m_pairs = std::move(other.m_pairs);
}
return *this;
}
template<typename K, typename T, size_t SmallSz>
constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
bool isNew{};
auto p = &access(m_pairs, k, isNew);
if (isNew) {
p->key = k;
}
return p->value;
}
template<typename K, typename T, size_t SmallSz>
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
}
return &p->value;
}
template<typename K, typename T, size_t SmallSz>
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
auto p = access(m_pairs, k);
if (!p) {
return {nullptr, OxError(1, "value not found for given key")};
}
return &p->value;
}
template<typename K, typename T, size_t SmallSz>
constexpr void SmallMap<K, T, SmallSz>::erase(MaybeView_t<K> const&k) {
size_t i{};
for (auto const&p : m_pairs) {
if (k == p.key) {
break;
}
++i;
}
std::ignore = m_pairs.erase(i);
}
template<typename K, typename T, size_t SmallSz>
constexpr bool SmallMap<K, T, SmallSz>::contains(MaybeView_t<K> const&k) const noexcept {
return access(m_pairs, k) != nullptr;
}
template<typename K, typename T, size_t SmallSz>
constexpr std::size_t SmallMap<K, T, SmallSz>::size() const noexcept {
return m_pairs.size();
}
template<typename K, typename T, size_t SmallSz>
constexpr Vector<K> SmallMap<K, T, SmallSz>::keys() const noexcept {
ox::Vector<K> keys;
keys.reserve(m_pairs.size());
for (auto const&p : m_pairs) {
keys.emplace_back(p.key);
}
return keys;
}
template<typename K, typename T, size_t SmallSz>
constexpr K const&SmallMap<K, T, SmallSz>::key(size_t i) const noexcept {
return m_pairs[i].key;
}
template<typename K, typename T, size_t SmallSz>
constexpr T const&SmallMap<K, T, SmallSz>::value(size_t i) const noexcept {
return m_pairs[i].value;
}
template<typename K, typename T, size_t SmallSz>
constexpr T &SmallMap<K, T, SmallSz>::value(size_t i) noexcept {
return m_pairs[i].value;
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::get(size_t i) const noexcept {
return m_pairs[i];
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::get(size_t i) noexcept {
return m_pairs[i];
}
template<typename K, typename T, size_t SmallSz>
constexpr void SmallMap<K, T, SmallSz>::clear() {
m_pairs.clear();
}
template<typename K, typename T, size_t SmallSz>
template<typename KK>
constexpr typename SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::access(
PairVector const&pairs, KK const&k, bool &isNew) const {
for (auto const&p : pairs) {
if (p.key == k) {
isNew = false;
return p;
}
}
isNew = true;
return pairs.emplace_back();
}
template<typename K, typename T, size_t SmallSz>
template<typename KK>
constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::access(
PairVector &pairs, KK const&k, bool &isNew) {
for (auto &p : pairs) {
if (p.key == k) {
isNew = false;
return p;
}
}
isNew = true;
return pairs.emplace_back();
}
}

View File

@ -19,8 +19,8 @@ template<typename T>
class SpanView {
private:
const T *m_items{};
const std::size_t m_size{};
T const*m_items{};
std::size_t m_size{};
public:
using value_type = T;
@ -106,6 +106,16 @@ class SpanView {
return m_items[i];
}
constexpr SpanView operator+(size_t i) const noexcept {
return {m_items + i, m_size - i};
}
constexpr SpanView operator+=(size_t i) noexcept {
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]]
constexpr T const*data() const noexcept {
return m_items;

View File

@ -39,6 +39,7 @@
#include "realstd.hpp"
#include "serialize.hpp"
#include "size.hpp"
#include "smallmap.hpp"
#include "stacktrace.hpp"
#include "stddef.hpp"
#include "string.hpp"

View File

@ -1,7 +1,9 @@
#pragma once
#include "bit.hpp"
#include "error.hpp"
#include "math.hpp"
#include "types.hpp"
#include "writer.hpp"

View File

@ -192,6 +192,10 @@ class BasicString {
[[nodiscard]]
constexpr BasicString substr(std::size_t begin, std::size_t end) const noexcept;
constexpr void resize(size_t sz) noexcept {
m_buff.resize(sz);
}
[[nodiscard]]
constexpr const char *data() const noexcept {
return m_buff.data();
@ -511,7 +515,7 @@ constexpr char &BasicString<SmallStringSize_v>::operator[](std::size_t i) noexce
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t pos) const noexcept {
return BasicString(m_buff.data() + pos, m_buff.size() - pos);
return BasicString(m_buff.data() + pos, m_buff.size() - pos - 1);
}
template<std::size_t SmallStringSize_v>
@ -527,26 +531,12 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(
template<std::size_t SmallStringSize_v>
constexpr std::size_t BasicString<SmallStringSize_v>::bytes() const noexcept {
std::size_t i;
for (i = 0; i < m_buff.size() && m_buff[i]; ++i);
return i + 1; // add one for null terminator
return m_buff.size();
}
template<std::size_t SmallStringSize_v>
constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
std::size_t length = 0;
for (const auto c : m_buff) {
const auto b = static_cast<uint8_t>(c);
if (b) {
// normal ASCII character or start of UTF-8 character
if ((b & 128) == 0 || (b & (256 << 6)) == (256 << 6)) {
++length;
}
} else {
break;
}
}
return length;
return m_buff.size() - 1;
}
template<std::size_t SmallStringSize_v>

View File

@ -12,8 +12,10 @@ add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTOR
add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFG == ABCDEFG")
add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFGHI == ABCDEFG")
add_test("[ox/std] itoa" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "itoa")
add_test("[ox/std] BString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "BString")
add_test("[ox/std] IString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "IString")
add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String")
add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap")
add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2")
add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector")
add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap")
add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc)

View File

@ -6,13 +6,112 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "ox/std/def.hpp"
#if __has_include(<chrono>)
#include<chrono>
#endif
#include <ox/std/def.hpp>
#undef NDEBUG
#include <map>
#include <ox/std/uuid.hpp>
#include <ox/std/std.hpp>
[[nodiscard]]
static uint64_t nowMs() {
#if __has_include(<chrono>)
using namespace std::chrono;
return static_cast<uint64_t>(
duration_cast<milliseconds>(
system_clock::now().time_since_epoch()).count());
#else
return 0;
#endif
}
template<typename Map = ox::SmallMap<ox::String, ox::UUID>>
uint64_t timeMapStrToUuid(int elemCnt, int lookups, uint64_t seed = 4321) noexcept {
ox::UUID::seedGenerator({1234, seed});
Map map;
// setup test map
for (int i = 0; i < elemCnt; ++i) {
auto const uuid = ox::UUID::generate().unwrap();
map[uuid.toString()] = uuid;
}
auto const keys = map.keys();
ox::Random rand;
// start
auto const startTime = nowMs();
for (int i = 0; i < lookups; ++i) {
auto const&k = keys[rand.gen() % keys.size()];
map[k];
oxExpect(map[k], ox::UUID::fromString(k).unwrap());
}
return nowMs() - startTime;
}
template<typename Map = ox::SmallMap<ox::UUID, ox::String>>
uint64_t timeMapUuidToStr(int elemCnt, int lookups, uint64_t seed = 4321) noexcept {
ox::UUID::seedGenerator({1234, seed});
Map map;
// setup test map
for (int i = 0; i < elemCnt; ++i) {
auto const uuid = ox::UUID::generate().unwrap();
map[uuid] = uuid.toString();
}
auto const keys = map.keys();
ox::Random rand;
// start
auto const startTime = nowMs();
for (int i = 0; i < lookups; ++i) {
auto const&k = keys[rand.gen() % keys.size()];
oxExpect(map[k], k.toString());
}
return nowMs() - startTime;
}
static ox::Error compareMaps(int lookupCnt = 1'000'000) {
auto const seed = nowMs();
uint64_t hashTime{};
uint64_t smallTime{};
int elemCnt = 1;
oxOut("UUIDStr to UUID:\n\n");
while (hashTime >= smallTime) {
smallTime = timeMapStrToUuid<ox::SmallMap<ox::UUIDStr, ox::UUID>>(elemCnt, lookupCnt, seed);
hashTime = timeMapStrToUuid<ox::HashMap<ox::UUIDStr, ox::UUID>>(elemCnt, lookupCnt, seed);
oxOutf(
"UUIDStr to UUID: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n",
elemCnt, lookupCnt, hashTime, smallTime);
++elemCnt;
}
oxOut("\n\nString to UUID:\n\n");
hashTime = 0;
smallTime = 0;
elemCnt = 1;
while (hashTime >= smallTime) {
smallTime = timeMapStrToUuid<ox::SmallMap<ox::String, ox::UUID>>(elemCnt, lookupCnt, seed);
hashTime = timeMapStrToUuid<ox::HashMap<ox::String, ox::UUID>>(elemCnt, lookupCnt, seed);
oxOutf(
"String to UUID: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n",
elemCnt, lookupCnt, hashTime, smallTime);
++elemCnt;
}
oxOut("\n\nUUID to UUIDStr:\n\n");
hashTime = 0;
smallTime = 0;
elemCnt = 1;
while (hashTime >= smallTime) {
smallTime = timeMapUuidToStr<ox::SmallMap<ox::UUID, ox::UUIDStr>>(elemCnt, lookupCnt, seed);
hashTime = timeMapUuidToStr<ox::HashMap<ox::UUID, ox::UUIDStr>>(elemCnt, lookupCnt, seed);
oxOutf(
"UUID to UUIDStr: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n",
elemCnt, lookupCnt, hashTime, smallTime);
++elemCnt;
}
oxOut("\n");
return {};
}
static std::map<ox::StringView, ox::Error(*)()> tests = {
{
"malloc",
@ -23,6 +122,8 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
auto a2 = static_cast<char*>(ox::heapmgr::malloc(5));
oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken");
oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken");
ox::heapmgr::free(a1);
ox::heapmgr::free(a2);
return OxError(0);
}
},
@ -67,14 +168,14 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
}
},
{
"BString",
"IString",
[]() {
ox::IString<5> s;
oxReturnError(s.append("A"));
oxReturnError(s.append("B"));
oxReturnError(s.append("9"));
oxReturnError(s.append("C"));
oxAssert(s == "AB9C", "BString append broken");
oxAssert(s == "AB9C", "IString append broken");
s = "asdf";
oxAssert(s == "asdf", "String assign broken");
oxAssert(s != "aoeu", "String assign broken");
@ -109,7 +210,10 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
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");
oxAssert(ox::String(ox::StringView("Write")) == ox::StringView("Write"), "String / StringView comparison broken");
oxExpect(ox::String("asdf").substr(1, 3), "sd");
oxAssert(
ox::String(ox::StringView("Write")) == ox::StringView("Write"),
"String / StringView comparison broken");
return OxError(0);
}
},
@ -119,7 +223,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
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, [[maybe_unused]] std::size_t size) {
auto insertTest = [&v](int val, std::size_t size) {
v.push_back(val);
oxReturnError(OxError(v.size() != size, "Vector size incorrect"));
oxReturnError(OxError(v[v.size() - 1] != val, "Vector value wrong"));
@ -131,10 +235,38 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"SmallMap",
[] {
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);
return OxError(0);
}
},
{
"SmallMap2",
[] {
ox::SmallMap<ox::String, int> si;
si["asdf"] = 42;
si["aoeu"] = 100;
oxAssert(si["asdf"] == 42, "asdf != 42");
oxAssert(si["aoeu"] == 100, "aoeu != 100");
ox::SmallMap<int, int> ii;
ii[4] = 42;
ii[5] = 100;
oxAssert(ii[4] == 42, "4 != 42");
oxAssert(ii[5] == 100, "5 != 100");
return OxError(0);
}
},
{
"HashMap",
[] {
ox::HashMap<const char*, int> si;
ox::HashMap<ox::String, int> si;
si["asdf"] = 42;
si["aoeu"] = 100;
oxAssert(si["asdf"] == 42, "asdf != 42");
@ -147,12 +279,36 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"TimeSmallMapMillion",
[] {
timeMapStrToUuid<ox::SmallMap<ox::String, ox::UUID>>(1'000, 1'000'000);
return ox::Error{};
}
},
{
"TimeHashMapMillion",
[] {
timeMapStrToUuid<ox::HashMap<ox::String, ox::UUID>>(1'000, 1'000'000);
return ox::Error{};
}
},
{
"CompareMaps",
[] {
return compareMaps();
}
},
{
"Serialize-Int",
[] {
using BA = ox::Array<char, 4>;
const auto actual = ox::serialize<uint32_t>(256).unwrap();
oxOutf("[{}, {}, {}, {}]", static_cast<int>(actual[0]), static_cast<int>(actual[1]), static_cast<int>(actual[2]), static_cast<int>(actual[3]));
oxOutf("[{}, {}, {}, {}]",
static_cast<int>(actual[0]),
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}));

View File

@ -8,9 +8,11 @@
#pragma once
#include "bit.hpp"
#include "ignore.hpp"
#include "istring.hpp"
#include "buffer.hpp"
#include "hash.hpp"
#include "random.hpp"
#include "ranges.hpp"
#include "stringview.hpp"
@ -105,7 +107,7 @@ class UUID {
static ox::Result<UUID> generate() noexcept;
[[nodiscard]]
constexpr auto value() const noexcept {
constexpr auto const&value() const noexcept {
return m_value;
}
@ -118,8 +120,8 @@ class UUID {
return false;
} else {
constexpr uint64_t zero = 0;
return ox::memcmp(&zero, m_value.data() + 0, 8) == 0
&& ox::memcmp(&zero, m_value.data() + 8, 8) == 0;
return memcmp(&zero, m_value.data() + 0, 8) == 0
&& memcmp(&zero, m_value.data() + 8, 8) == 0;
}
}
@ -146,6 +148,14 @@ class UUID {
return out;
}
constexpr bool operator==(UUID const&o) const noexcept {
return m_value == o.m_value;
}
constexpr bool operator!=(UUID const&o) const noexcept {
return !operator==(o);
}
[[nodiscard]]
constexpr ox::Error toString(Writer_c auto &writer) const noexcept {
auto valueI = 0u;
@ -176,13 +186,32 @@ class UUID {
[[nodiscard]]
constexpr UUIDStr toString() const noexcept {
UUIDStr out;
ox::CharBuffWriter bw(out.data(), out.cap());
std::ignore = out.resize(UUIDStr::cap());
ox::CharBuffWriter bw(out.data(), UUIDStr::cap());
std::ignore = toString(bw);
out[out.cap()] = 0;
out[UUIDStr::cap()] = 0;
return out;
}
};
template<>
struct hash<ox::UUID> {
[[nodiscard]]
constexpr size_t operator()(ox::UUID v) const noexcept {
size_t out{};
if (std::is_constant_evaluated()) {
for (auto i = 0u; i < sizeof(out); ++i) {
out |= static_cast<size_t>(v.value()[i]) << (i * 8);
}
} else {
memcpy(&out, &v, sizeof(out));
}
return out;
}
};
template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<UUID> auto *obj) noexcept {
oxReturnError(io->template setTypeInfo<UUID>());

View File

@ -85,6 +85,8 @@ struct VectorAllocator {
constexpr void deallocate(T *items, std::size_t 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);
} else {
if (items && static_cast<void*>(items) != static_cast<void*>(m_data.data())) {
Allocator{}.deallocate(items, cap);
}

View File

@ -196,7 +196,7 @@ static ox::Error loadTileSheetSet(
.targetBpp = static_cast<unsigned>(set.bpp),
.setEntry = &entry,
};
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
tileWriteIdx += target.tileWriteIdx;
}
return {};
@ -215,7 +215,7 @@ ox::Error loadBgTileSheet(
.defaultPalette = {},
.tileMap = MEM_BG_TILES[cbb].data(),
};
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
// update bpp of all bgs with the updated cbb
const auto bpp = ctx.cbbData[cbb].bpp;
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
@ -267,7 +267,7 @@ ox::Error loadSpriteTileSheet(
.defaultPalette = {},
.tileMap = MEM_SPRITE_TILES,
};
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
if (loadDefaultPalette && target.defaultPalette) {
oxReturnError(loadSpritePalette(ctx, target.defaultPalette));
}

View File

@ -58,29 +58,25 @@ static class: public keel::Module {
ox::Vector<keel::PackTransform> packTransforms() const noexcept final {
return {
// convert tilesheets to CompactTileSheets
[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
oxRequire(hdr, keel::readAssetHeader(buff));
auto const typeId = ox::buildTypeId(
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
[](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result<bool> {
if (typeId == ox::ModelTypeId_v<TileSheetV1> ||
typeId == ox::ModelTypeId_v<TileSheetV2> ||
typeId == ox::ModelTypeId_v<TileSheetV3> ||
typeId == ox::ModelTypeId_v<TileSheetV4>) {
oxReturnError(keel::convertBuffToBuff<CompactTileSheet>(
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
return true;
}
return {};
return false;
},
[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
oxRequire(hdr, keel::readAssetHeader(buff));
auto const typeId = ox::buildTypeId(
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
[](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result<bool> {
if (typeId == ox::ModelTypeId_v<NostalgiaPalette> ||
typeId == ox::ModelTypeId_v<PaletteV1>) {
oxReturnError(keel::convertBuffToBuff<Palette>(
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
return true;
}
return {};
return false;
},
};
}

View File

@ -29,11 +29,11 @@ class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, Til
};
class TileSheetV2ToTileSheetV3Converter: public keel::Converter<TileSheetV2, TileSheetV3> {
static void convertSubsheet(
TileSheetV2::SubSheet &src,
TileSheetV3::SubSheet &dst,
SubSheetId &idIt) noexcept;
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
static void convertSubsheet(
TileSheetV2::SubSheet &src,
TileSheetV3::SubSheet &dst,
SubSheetId &idIt) noexcept;
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
};
class TileSheetV3ToTileSheetV4Converter: public keel::Converter<TileSheetV3, TileSheetV4> {
@ -45,7 +45,7 @@ class TileSheetV3ToTileSheetV4Converter: public keel::Converter<TileSheetV3, Til
};
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> {
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
};
}

View File

@ -11,7 +11,7 @@ target_link_libraries(
target_compile_definitions(
NostalgiaStudio PUBLIC
OLYMPIC_APP_VERSION="dev build"
OLYMPIC_APP_VERSION="d2024.05.0"
)
install(

View File

@ -11,9 +11,7 @@ namespace keel {
constexpr auto K1HdrSz = 40;
ox::Result<ox::UUID> readUuidHeader(ox::Buffer const&buff) noexcept;
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept;
ox::Result<ox::UUID> readUuidHeader(ox::BufferView buff) noexcept;
ox::Error writeUuidHeader(ox::Writer_c auto &writer, ox::UUID const&uuid) noexcept {
oxReturnError(write(writer, "K1;"));
@ -22,24 +20,24 @@ ox::Error writeUuidHeader(ox::Writer_c auto &writer, ox::UUID const&uuid) noexce
}
template<typename T>
ox::Result<T> readAsset(ox::Buffer const&buff) noexcept {
ox::Result<T> readAsset(ox::BufferView buff) noexcept {
std::size_t offset = 0;
const auto err = readUuidHeader(buff).error;
if (!err) {
offset = K1HdrSz; // the size of K1 headers
}
return ox::readClaw<T>(buff.data() + offset, buff.size() - offset);
return ox::readClaw<T>(buff + offset);
}
ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::Buffer const&buff) noexcept;
ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::BufferView buff) noexcept;
struct AssetHdr {
ox::UUID uuid;
ox::ClawHeader clawHdr;
};
ox::Result<AssetHdr> readAssetHeader(char const*buff, std::size_t buffLen) noexcept;
ox::Result<ox::StringView> readAssetTypeId(ox::BufferView buff) noexcept;
ox::Result<AssetHdr> readAssetHeader(ox::Buffer const&buff) noexcept;
ox::Result<AssetHdr> readAssetHeader(ox::BufferView buff) noexcept;
}

View File

@ -12,7 +12,7 @@
namespace keel {
class Context;
using PackTransform = ox::Error(*)(Context&, ox::Buffer &clawData);
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringView);
class Context {
public:
@ -36,4 +36,22 @@ class Context {
constexpr virtual ~Context() noexcept = default;
};
constexpr ox::SpanView<PackTransform> packTransforms(
[[maybe_unused]] Context const&ctx) noexcept {
#ifndef OX_BARE_METAL
return ctx.packTransforms;
#else
return {};
#endif
}
constexpr ox::SpanView<class BaseConverter const*> converters(
[[maybe_unused]] Context const&ctx) noexcept {
#ifndef OX_BARE_METAL
return ctx.converters;
#else
return {};
#endif
}
}

View File

@ -94,7 +94,7 @@ ox::Error preloadObj(
oxOutf("preloading {} as a {}\n", path, obj.type()->typeName);
// preload
oxRequire(a, pl.startAlloc(ox::sizeOf<GbaPlatSpec>(&obj), ox::alignOf<GbaPlatSpec>(obj)));
auto const err = ox::preload<GbaPlatSpec, decltype(obj)>(&pl, &obj);
auto const err = ox::preload<GbaPlatSpec, ox::ModelObject>(&pl, &obj);
oxReturnError(pl.endAlloc());
oxReturnError(err);
keel::PreloadPtr const p{.preloadAddr = static_cast<uint32_t>(a)};

View File

@ -40,7 +40,7 @@ class WrapInline: public Wrap {
};
template<typename T, typename... Args>
constexpr auto makeWrap(Args &&...args) noexcept {
constexpr ox::UPtr<Wrap> makeWrap(Args &&...args) noexcept {
return ox::make_unique<WrapInline<T>>(ox::forward<Args>(args)...);
}
@ -65,9 +65,10 @@ class BaseConverter {
[[nodiscard]]
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
virtual ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept = 0;
virtual ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept = 0;
[[nodiscard]]
inline bool matches(
@ -84,12 +85,12 @@ class Converter: public BaseConverter {
public:
[[nodiscard]]
ox::StringView srcTypeName() const noexcept final {
return ox::requireModelTypeName<SrcType>();
return ox::ModelTypeName_v<SrcType>;
}
[[nodiscard]]
int srcTypeVersion() const noexcept final {
return ox::requireModelTypeVersion<SrcType>();
return ox::ModelTypeVersion_v<SrcType>;
}
[[nodiscard]]
@ -97,7 +98,7 @@ class Converter: public BaseConverter {
constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
return pSrcTypeName == SrcTypeName
&& pSrcTypeVersion == SrcTypeVersion;
&& pSrcTypeVersion == SrcTypeVersion;
}
[[nodiscard]]
@ -105,20 +106,22 @@ class Converter: public BaseConverter {
constexpr auto DstTypeName = ox::StringView(ox::requireModelTypeName<DstType>());
constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
return dstTypeName == DstTypeName
&& dstTypeVersion == DstTypeVersion;
&& dstTypeVersion == DstTypeVersion;
}
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept final {
ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(
keel::Context &ctx, Wrap &src) const noexcept final {
auto dst = makeWrap<DstType>();
oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(*dst)));
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
return {std::move(dst)};
}
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept final {
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept final {
oxRequireM(src, readAsset<SrcType>(srcBuff));
auto dst = makeWrap<DstType>();
oxReturnError(convert(ctx, src, wrapCast<DstType>(*dst)));
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
return {std::move(dst)};
}
protected:
@ -126,9 +129,11 @@ class Converter: public BaseConverter {
};
ox::Result<ox::UniquePtr<Wrap>> convert(
keel::Context &ctx, ox::Buffer const&srcBuffer,
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::Buffer const&srcBuffer,
ox::CRStringView dstTypeName,
int dstTypeVersion) noexcept;
template<typename DstType>
ox::Result<DstType> convert(keel::Context &ctx, ox::Buffer const&srcBuffer) noexcept {
@ -148,7 +153,8 @@ ox::Error convert(keel::Context &ctx, ox::Buffer const&buff, DstType *outObj) no
}
template<typename DstType>
ox::Result<ox::Buffer> convertBuffToBuff(keel::Context &ctx, ox::Buffer const&srcBuffer, ox::ClawFormat fmt) noexcept {
ox::Result<ox::Buffer> convertBuffToBuff(
keel::Context &ctx, ox::Buffer const&srcBuffer, ox::ClawFormat fmt) noexcept {
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
@ -156,14 +162,12 @@ ox::Result<ox::Buffer> convertBuffToBuff(keel::Context &ctx, ox::Buffer const&sr
}
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
auto transformRule(keel::Context &ctx, ox::Buffer &buff) noexcept -> ox::Error {
oxRequire(hdr, readAssetHeader(buff));
const auto typeId = ox::buildTypeId(
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept {
if (typeId == ox::ModelTypeId_v<From>) {
oxReturnError(keel::convertBuffToBuff<To>(ctx, buff, fmt).moveTo(buff));
return true;
}
return {};
return false;
};

View File

@ -19,7 +19,7 @@ class TypeStore: public ox::TypeStore {
explicit TypeStore(ox::FileSystem &fs, ox::StringView descPath) noexcept;
protected:
ox::Result<ox::UPtr<ox::DescriptorType>> loadDescriptor(ox::CRStringView typeId) noexcept override;
ox::Result<ox::UPtr<ox::DescriptorType>> loadDescriptor(ox::StringView typeId) noexcept override;
};
}

View File

@ -6,41 +6,45 @@
namespace keel {
ox::Result<ox::UUID> readUuidHeader(ox::Buffer const&buff) noexcept {
return readUuidHeader(buff.data(), buff.size());
}
ox::Result<ox::UUID> readUuidHeader(char const*buff, std::size_t buffLen) noexcept {
if (buffLen < K1HdrSz) {
ox::Result<ox::UUID> readUuidHeader(ox::BufferView buff) noexcept {
if (buff.size() < K1HdrSz) [[unlikely]] {
return OxError(1, "Insufficient data to contain complete Keel header");
}
constexpr ox::StringView k1Hdr = "K1;";
if (k1Hdr != ox::StringView(buff, k1Hdr.bytes())) {
if (k1Hdr != ox::StringView(buff.data(), k1Hdr.bytes())) [[unlikely]] {
return OxError(2, "No Keel asset header data");
}
return ox::UUID::fromString(ox::StringView(buff + k1Hdr.bytes(), 36));
return ox::UUID::fromString(ox::StringView(buff.data() + k1Hdr.bytes(), 36));
}
ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::Buffer const&buff) noexcept {
ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::BufferView buff) noexcept {
std::size_t offset = 0;
if (!readUuidHeader(buff).error) {
offset = K1HdrSz;
}
return ox::readClaw(ts, buff.data() + offset, buff.size() - offset);
buff += offset;
return ox::readClaw(ts, buff);
}
ox::Result<AssetHdr> readAssetHeader(char const*buff, std::size_t buffLen) noexcept {
AssetHdr out;
const auto err = readUuidHeader(buff, buffLen).moveTo(out.uuid);
ox::Result<ox::StringView> readAssetTypeId(ox::BufferView buff) noexcept {
const auto err = readUuidHeader(buff).error;
const auto offset = err ? 0u : K1HdrSz;
buff = buff + offset;
buffLen = buffLen - offset;
oxReturnError(ox::readClawHeader(buff, buffLen).moveTo(out.clawHdr));
if (offset >= buff.size()) [[unlikely]] {
return OxError(1, "Buffer too small for expected data");
}
return ox::readClawTypeId(buff + offset);
}
ox::Result<AssetHdr> readAssetHeader(ox::BufferView buff) noexcept {
ox::Result<AssetHdr> out;
const auto err = readUuidHeader(buff).moveTo(out.value.uuid);
const auto offset = err ? 0u : K1HdrSz;
if (offset >= buff.size()) [[unlikely]] {
return OxError(1, "Buffer too small for expected data");
}
buff += offset;
oxReturnError(ox::readClawHeader(buff).moveTo(out.value.clawHdr));
return out;
}
ox::Result<AssetHdr> readAssetHeader(ox::Buffer const&buff) noexcept {
return readAssetHeader(buff.data(), buff.size());
}
}

View File

@ -102,14 +102,15 @@ ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
}
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
#ifndef OX_BARE_METAL
for (auto tr : ctx.packTransforms) {
oxReturnError(tr(ctx, clawData));
oxRequireM(typeId, readAssetTypeId(clawData));
for (auto const tr : packTransforms(ctx)) {
bool changed{};
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
if (changed) {
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
}
}
return {};
#else
return OxError(1, "Transformations not supported on this platform");
#endif
}
}
@ -153,7 +154,7 @@ ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView path
oxRequire(stat, ctx.rom->stat(path));
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(path));
PreloadPtr p;
oxReturnError(ox::readMC(buff, static_cast<std::size_t>(stat.size), &p));
oxReturnError(ox::readMC({buff, static_cast<std::size_t>(stat.size)}, p));
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
}
@ -161,7 +162,7 @@ ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const
oxRequire(stat, ctx.rom->stat(file));
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(file));
PreloadPtr p;
oxReturnError(ox::readMC(buff, static_cast<std::size_t>(stat.size), &p));
oxReturnError(ox::readMC({buff, static_cast<std::size_t>(stat.size)}, p));
return static_cast<std::size_t>(p.preloadAddr) + ctx.preloadSectionOffset;
}

View File

@ -10,13 +10,13 @@
namespace keel {
[[nodiscard]]
static ox::Result<const BaseConverter*> findConverter(
ox::Vector<const BaseConverter*> const&converters,
static ox::Result<BaseConverter const*> findConverter(
ox::SpanView<BaseConverter const*> const&converters,
ox::CRStringView srcTypeName,
int srcTypeVersion,
ox::CRStringView dstTypeName,
int dstTypeVersion) noexcept {
for (auto &c : converters) {
for (auto const&c : converters) {
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
return c;
}
@ -24,21 +24,22 @@ static ox::Result<const BaseConverter*> findConverter(
return OxError(1, "Could not find converter");
};
static ox::Result<ox::UniquePtr<Wrap>> convert(
[[maybe_unused]] keel::Context &ctx,
ox::Vector<const BaseConverter*> const&converters,
[[maybe_unused]] ox::Buffer const&srcBuffer,
[[maybe_unused]] ox::CRStringView srcTypeName,
[[maybe_unused]] int srcTypeVersion,
[[maybe_unused]] ox::CRStringView dstTypeName,
[[maybe_unused]] int dstTypeVersion) noexcept {
static ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::SpanView<BaseConverter const*> const&converters,
ox::Buffer const&srcBuffer,
ox::CRStringView srcTypeName,
int srcTypeVersion,
ox::CRStringView dstTypeName,
int dstTypeVersion) noexcept {
// look for direct converter
auto [c, err] = findConverter(converters, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
auto [c, err] = findConverter(
converters, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
if (!err) {
return c->convertBuffToPtr(ctx, srcBuffer);
}
// try to chain multiple converters
for (const auto &subConverter : converters) {
for (auto const&subConverter : converters) {
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
continue;
}
@ -52,24 +53,20 @@ static ox::Result<ox::UniquePtr<Wrap>> convert(
return OxError(1, "Could not convert between types");
}
ox::Result<ox::UniquePtr<Wrap>> convert(
[[maybe_unused]] keel::Context &ctx,
[[maybe_unused]] ox::Buffer const&srcBuffer,
[[maybe_unused]] ox::CRStringView dstTypeName,
[[maybe_unused]] int dstTypeVersion) noexcept {
#ifndef OX_BARE_METAL
ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::Buffer const&srcBuffer,
ox::CRStringView dstTypeName,
int dstTypeVersion) noexcept {
oxRequire(hdr, readAssetHeader(srcBuffer));
return convert(
ctx,
ctx.converters,
converters(ctx),
srcBuffer,
hdr.clawHdr.typeName,
hdr.clawHdr.typeVersion,
dstTypeName,
dstTypeVersion);
#else
return OxError(1, "Operation not supported on this platform");
#endif
}
}

View File

@ -11,11 +11,11 @@ TypeStore::TypeStore(ox::FileSystem &fs, ox::StringView descPath) noexcept:
m_descPath(descPath) {
}
ox::Result<ox::UPtr<ox::DescriptorType>> TypeStore::loadDescriptor(ox::CRStringView typeId) noexcept {
auto path = ox::sfmt("{}/{}", m_descPath, typeId);
ox::Result<ox::UPtr<ox::DescriptorType>> TypeStore::loadDescriptor(ox::StringView const typeId) noexcept {
auto const path = ox::sfmt("{}/{}", m_descPath, typeId);
oxRequire(buff, m_fs.read(path));
auto dt = ox::make_unique<ox::DescriptorType>();
oxReturnError(ox::readClaw<ox::DescriptorType>(buff, dt.get()));
oxReturnError(ox::readClaw<ox::DescriptorType>(buff, *dt));
return dt;
}

View File

@ -68,7 +68,7 @@ static ox::Error run(
static_cast<uint64_t>(time << 1)
});
// run app
auto const err = runApp(appName, projectDataDir, ox::UniquePtr<ox::FileSystem>(nullptr));
auto const err = runApp(appName, projectDataDir, ox::UPtr<ox::FileSystem>(nullptr));
oxAssert(err, "Something went wrong...");
return err;
}

View File

@ -29,9 +29,9 @@ ox::Result<T> getDragDropPayload(ox::CStringView name) noexcept {
if (!payload) {
return OxError(1, "No drag/drop payload");
}
return ox::readClaw<T>(
return ox::readClaw<T>({
reinterpret_cast<char const*>(payload->Data),
static_cast<size_t>(payload->DataSize));
static_cast<size_t>(payload->DataSize)});
}
ox::Error setDragDropPayload(ox::CStringView name, auto const &obj) noexcept {