Compare commits
16 Commits
f624c720f9
...
release-d2
| Author | SHA1 | Date | |
|---|---|---|---|
| 889fe04255 | |||
| eed115b287 | |||
| 7233da75ea | |||
| 30797c710b | |||
| e8041121d0 | |||
| d054528e49 | |||
| 09d840cfd0 | |||
| aeb1ef3b12 | |||
| b66f61c217 | |||
| b089bf460b | |||
| cd60c4abaf | |||
| d1845448c3 | |||
| c4f6ee0026 | |||
| 17f28d43d1 | |||
| 043df533b7 | |||
| bec75d2eba |
4
deps/ox/src/ox/clargs/clargs.cpp
vendored
4
deps/ox/src/ox/clargs/clargs.cpp
vendored
@@ -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 {
|
||||
|
||||
2
deps/ox/src/ox/clargs/clargs.hpp
vendored
2
deps/ox/src/ox/clargs/clargs.hpp
vendored
@@ -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;
|
||||
|
||||
10
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
10
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
@@ -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
|
||||
|
||||
43
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
43
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
@@ -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);
|
||||
|
||||
14
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
14
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
@@ -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
|
||||
|
||||
37
deps/ox/src/ox/fs/test/tests.cpp
vendored
37
deps/ox/src/ox/fs/test/tests.cpp
vendored
@@ -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;
|
||||
|
||||
22
deps/ox/src/ox/mc/read.hpp
vendored
22
deps/ox/src/ox/mc/read.hpp
vendored
@@ -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>
|
||||
|
||||
3
deps/ox/src/ox/mc/test/tests.cpp
vendored
3
deps/ox/src/ox/mc/test/tests.cpp
vendored
@@ -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");
|
||||
|
||||
2
deps/ox/src/ox/mc/write.hpp
vendored
2
deps/ox/src/ox/mc/write.hpp
vendored
@@ -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>
|
||||
|
||||
14
deps/ox/src/ox/oc/read.hpp
vendored
14
deps/ox/src/ox/oc/read.hpp
vendored
@@ -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
|
||||
|
||||
2
deps/ox/src/ox/std/CMakeLists.txt
vendored
2
deps/ox/src/ox/std/CMakeLists.txt
vendored
@@ -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})
|
||||
|
||||
12
deps/ox/src/ox/std/array.hpp
vendored
12
deps/ox/src/ox/std/array.hpp
vendored
@@ -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>
|
||||
|
||||
17
deps/ox/src/ox/std/hashmap.hpp
vendored
17
deps/ox/src/ox/std/hashmap.hpp
vendored
@@ -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 {
|
||||
|
||||
56
deps/ox/src/ox/std/istring.hpp
vendored
56
deps/ox/src/ox/std/istring.hpp
vendored
@@ -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;
|
||||
|
||||
2
deps/ox/src/ox/std/memops.hpp
vendored
2
deps/ox/src/ox/std/memops.hpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
197
deps/ox/src/ox/std/smallmap.hpp
vendored
197
deps/ox/src/ox/std/smallmap.hpp
vendored
@@ -17,23 +17,23 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename K, typename T>
|
||||
template<typename K, typename T, size_t SmallSz = 0>
|
||||
class SmallMap {
|
||||
|
||||
public:
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
|
||||
private:
|
||||
struct Pair {
|
||||
K key = {};
|
||||
T value{};
|
||||
};
|
||||
Vector<K> m_keys;
|
||||
Vector<Pair> m_pairs;
|
||||
|
||||
private:
|
||||
using PairVector = Vector<Pair, SmallSz>;
|
||||
PairVector m_pairs;
|
||||
|
||||
public:
|
||||
explicit constexpr SmallMap(std::size_t size = 127);
|
||||
constexpr SmallMap() = default;
|
||||
|
||||
constexpr SmallMap(SmallMap const&other);
|
||||
|
||||
@@ -62,92 +62,84 @@ class SmallMap {
|
||||
constexpr std::size_t size() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Vector<K> const&keys() const noexcept;
|
||||
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:
|
||||
constexpr void expand();
|
||||
template<typename KK>
|
||||
constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const;
|
||||
|
||||
template<typename KK>
|
||||
constexpr Pair *const&access(Vector<Pair> const&pairs, KK const&key) const;
|
||||
|
||||
template<typename KK>
|
||||
constexpr Pair *&access(Vector<Pair> &pairs, KK const&key);
|
||||
constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew);
|
||||
|
||||
};
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr SmallMap<K, T>::SmallMap(std::size_t size): m_pairs(size) {
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr SmallMap<K, T>::SmallMap(SmallMap<K, T> const&other) {
|
||||
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>
|
||||
constexpr SmallMap<K, T>::SmallMap(SmallMap<K, T> &&other) noexcept {
|
||||
m_keys = std::move(other.m_keys);
|
||||
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>
|
||||
constexpr SmallMap<K, T>::~SmallMap() {
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr SmallMap<K, T, SmallSz>::~SmallMap() {
|
||||
clear();
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr bool SmallMap<K, T>::operator==(SmallMap 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)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
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>
|
||||
constexpr SmallMap<K, T> &SmallMap<K, T>::operator=(SmallMap<K, T> const&other) {
|
||||
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_keys = other.m_keys;
|
||||
m_pairs = other.m_pairs;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr SmallMap<K, T> &SmallMap<K, T>::operator=(SmallMap<K, T> &&other) noexcept {
|
||||
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_keys = std::move(other.m_keys);
|
||||
m_pairs = std::move(other.m_pairs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr T &SmallMap<K, T>::operator[](MaybeView_t<K> const&k) {
|
||||
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 = new Pair;
|
||||
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;
|
||||
m_keys.emplace_back(k);
|
||||
}
|
||||
return p->value;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr Result<T*> SmallMap<K, T>::at(MaybeView_t<K> const&k) noexcept {
|
||||
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")};
|
||||
@@ -155,8 +147,8 @@ constexpr Result<T*> SmallMap<K, T>::at(MaybeView_t<K> const&k) noexcept {
|
||||
return &p->value;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr Result<const T*> SmallMap<K, T>::at(MaybeView_t<K> const&k) const noexcept {
|
||||
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")};
|
||||
@@ -164,8 +156,8 @@ constexpr Result<const T*> SmallMap<K, T>::at(MaybeView_t<K> const&k) const noex
|
||||
return &p->value;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void SmallMap<K, T>::erase(MaybeView_t<K> const&k) {
|
||||
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) {
|
||||
@@ -174,65 +166,84 @@ constexpr void SmallMap<K, T>::erase(MaybeView_t<K> const&k) {
|
||||
++i;
|
||||
}
|
||||
std::ignore = m_pairs.erase(i);
|
||||
std::ignore = m_keys.erase(i);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr bool SmallMap<K, T>::contains(MaybeView_t<K> const&k) const noexcept {
|
||||
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>
|
||||
constexpr std::size_t SmallMap<K, T>::size() const noexcept {
|
||||
return m_keys.size();
|
||||
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>
|
||||
constexpr Vector<K> const&SmallMap<K, T>::keys() const noexcept {
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void SmallMap<K, T>::clear() {
|
||||
for (std::size_t i = 0; i < m_pairs.size(); i++) {
|
||||
delete m_pairs[i];
|
||||
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();
|
||||
m_pairs.resize(127);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void SmallMap<K, T>::expand() {
|
||||
Vector<Pair*> r;
|
||||
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));
|
||||
}
|
||||
m_pairs = std::move(r);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
template<typename KK>
|
||||
constexpr typename SmallMap<K, T>::Pair *const&SmallMap<K, T>::access(
|
||||
Vector<Pair> const&pairs, KK const&k) const {
|
||||
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) {
|
||||
return &p;
|
||||
isNew = false;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
isNew = true;
|
||||
return pairs.emplace_back();
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
template<typename KK>
|
||||
constexpr typename SmallMap<K, T>::Pair *&SmallMap<K, T>::access(
|
||||
Vector<Pair> &pairs, KK const&k) {
|
||||
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) {
|
||||
return &p;
|
||||
isNew = false;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
isNew = true;
|
||||
return pairs.emplace_back();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
20
deps/ox/src/ox/std/string.hpp
vendored
20
deps/ox/src/ox/std/string.hpp
vendored
@@ -515,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>
|
||||
@@ -531,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>
|
||||
|
||||
4
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
4
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@@ -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)
|
||||
|
||||
158
deps/ox/src/ox/std/test/tests.cpp
vendored
158
deps/ox/src/ox/std/test/tests.cpp
vendored
@@ -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,6 +210,7 @@ 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");
|
||||
oxExpect(ox::String("asdf").substr(1, 3), "sd");
|
||||
oxAssert(
|
||||
ox::String(ox::StringView("Write")) == ox::StringView("Write"),
|
||||
"String / StringView comparison broken");
|
||||
@@ -133,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");
|
||||
@@ -149,6 +279,26 @@ 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",
|
||||
[] {
|
||||
|
||||
39
deps/ox/src/ox/std/uuid.hpp
vendored
39
deps/ox/src/ox/std/uuid.hpp
vendored
@@ -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>());
|
||||
|
||||
2
deps/ox/src/ox/std/vector.hpp
vendored
2
deps/ox/src/ox/std/vector.hpp
vendored
@@ -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);
|
||||
}
|
||||
|
||||
@@ -58,23 +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::StringView typeId) -> ox::Error {
|
||||
[](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>) {
|
||||
return keel::convertBuffToBuff<CompactTileSheet>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(buff);
|
||||
oxReturnError(keel::convertBuffToBuff<CompactTileSheet>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
return true;
|
||||
}
|
||||
return {};
|
||||
return false;
|
||||
},
|
||||
[](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Error {
|
||||
[](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result<bool> {
|
||||
if (typeId == ox::ModelTypeId_v<NostalgiaPalette> ||
|
||||
typeId == ox::ModelTypeId_v<PaletteV1>) {
|
||||
return keel::convertBuffToBuff<Palette>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(buff);
|
||||
oxReturnError(keel::convertBuffToBuff<Palette>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
return true;
|
||||
}
|
||||
return {};
|
||||
return false;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ target_link_libraries(
|
||||
|
||||
target_compile_definitions(
|
||||
NostalgiaStudio PUBLIC
|
||||
OLYMPIC_APP_VERSION="dev build"
|
||||
OLYMPIC_APP_VERSION="d2024.05.0"
|
||||
)
|
||||
|
||||
install(
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace keel {
|
||||
|
||||
class Context;
|
||||
using PackTransform = ox::Error(*)(Context&, ox::Buffer &clawData, ox::StringView);
|
||||
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringView);
|
||||
|
||||
class Context {
|
||||
public:
|
||||
|
||||
@@ -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)};
|
||||
|
||||
@@ -162,11 +162,12 @@ ox::Result<ox::Buffer> convertBuffToBuff(
|
||||
}
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
auto transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept -> ox::Error {
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -102,9 +102,13 @@ ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
|
||||
}
|
||||
|
||||
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
||||
oxRequire(typeId, readAssetTypeId(clawData).to<ox::String>());
|
||||
oxRequireM(typeId, readAssetTypeId(clawData));
|
||||
for (auto const tr : packTransforms(ctx)) {
|
||||
oxReturnError(tr(ctx, clawData, typeId));
|
||||
bool changed{};
|
||||
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
|
||||
if (changed) {
|
||||
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user