From c4f6ee0026452b1ad8dc7edda010ec7dd786de74 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 19:50:48 -0500 Subject: [PATCH 01/11] [nostalgia,olympic] Make performPackTransforms update type id when needed --- .../modules/core/src/keel/keelmodule.cpp | 18 ++++++++++-------- src/olympic/keel/include/keel/context.hpp | 2 +- src/olympic/keel/include/keel/typeconv.hpp | 5 +++-- src/olympic/keel/src/media.cpp | 8 ++++++-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/nostalgia/modules/core/src/keel/keelmodule.cpp b/src/nostalgia/modules/core/src/keel/keelmodule.cpp index 43221940..140dfa71 100644 --- a/src/nostalgia/modules/core/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/core/src/keel/keelmodule.cpp @@ -58,23 +58,25 @@ static class: public keel::Module { ox::Vector 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 { if (typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v) { - return keel::convertBuffToBuff( - ctx, buff, ox::ClawFormat::Metal).moveTo(buff); + oxReturnError(keel::convertBuffToBuff( + 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 { if (typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v) { - return keel::convertBuffToBuff( - ctx, buff, ox::ClawFormat::Metal).moveTo(buff); + oxReturnError(keel::convertBuffToBuff( + ctx, buff, ox::ClawFormat::Metal).moveTo(buff)); + return true; } - return {}; + return false; }, }; } diff --git a/src/olympic/keel/include/keel/context.hpp b/src/olympic/keel/include/keel/context.hpp index 30847cb6..a34d8a18 100644 --- a/src/olympic/keel/include/keel/context.hpp +++ b/src/olympic/keel/include/keel/context.hpp @@ -12,7 +12,7 @@ namespace keel { class Context; -using PackTransform = ox::Error(*)(Context&, ox::Buffer &clawData, ox::StringView); +using PackTransform = ox::Result(*)(Context&, ox::Buffer &clawData, ox::StringView); class Context { public: diff --git a/src/olympic/keel/include/keel/typeconv.hpp b/src/olympic/keel/include/keel/typeconv.hpp index 2ece88c1..b2c51a65 100644 --- a/src/olympic/keel/include/keel/typeconv.hpp +++ b/src/olympic/keel/include/keel/typeconv.hpp @@ -162,11 +162,12 @@ ox::Result convertBuffToBuff( } template -auto transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept -> ox::Error { +ox::Result transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept { if (typeId == ox::ModelTypeId_v) { oxReturnError(keel::convertBuffToBuff(ctx, buff, fmt).moveTo(buff)); + return true; } - return {}; + return false; }; diff --git a/src/olympic/keel/src/media.cpp b/src/olympic/keel/src/media.cpp index 682f34a4..29572f1f 100644 --- a/src/olympic/keel/src/media.cpp +++ b/src/olympic/keel/src/media.cpp @@ -102,9 +102,13 @@ ox::Result uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept { } ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept { - oxRequire(typeId, readAssetTypeId(clawData).to()); + 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 {}; } From d1845448c3f54f2b0003ac396422a3c826e95724 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 22:10:14 -0500 Subject: [PATCH 02/11] [ox/std] Add == and != operators to UUID --- deps/ox/src/ox/std/uuid.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/deps/ox/src/ox/std/uuid.hpp b/deps/ox/src/ox/std/uuid.hpp index d2d783b4..f4a7a899 100644 --- a/deps/ox/src/ox/std/uuid.hpp +++ b/deps/ox/src/ox/std/uuid.hpp @@ -146,6 +146,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; From cd60c4abaf8955400fb93ed417ab10b545d046e0 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 22:10:34 -0500 Subject: [PATCH 03/11] [ox/std] Fix bugs in HashMap and SmallMap --- deps/ox/src/ox/std/hashmap.hpp | 17 +++++----- deps/ox/src/ox/std/smallmap.hpp | 57 +++++++++++++-------------------- 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/deps/ox/src/ox/std/hashmap.hpp b/deps/ox/src/ox/std/hashmap.hpp index 2475359d..d38e2c8f 100644 --- a/deps/ox/src/ox/std/hashmap.hpp +++ b/deps/ox/src/ox/std/hashmap.hpp @@ -133,17 +133,18 @@ constexpr HashMap &HashMap::operator=(HashMap &&other) noexcep template constexpr T &HashMap::operator[](MaybeView_t const&k) { - auto &p = access(m_pairs, k); - if (p == nullptr) { + auto p = &access(m_pairs, k); + if (*p == nullptr) { if (static_cast(m_pairs.size()) * 0.7 < static_cast(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 @@ -208,7 +209,7 @@ constexpr void HashMap::clear() { template constexpr void HashMap::expand() { - Vector r; + Vector 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 constexpr typename HashMap::Pair *const&HashMap::access(Vector const&pairs, KK const&k) const { auto h = static_cast(ox::hash{}(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 constexpr typename HashMap::Pair *&HashMap::access(Vector &pairs, KK const&k) { auto h = static_cast(ox::hash{}(k) % pairs.size()); while (true) { - auto &p = pairs[h]; + auto &p = *pairs.at(h).unwrap(); if (p == nullptr || p->key == k) { return p; } else { diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index 76ad9370..db2fa3eb 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -67,13 +67,11 @@ class SmallMap { constexpr void clear(); private: - constexpr void expand(); + template + constexpr Pair const&access(Vector const&pairs, KK const&key, bool &isNew) const; template - constexpr Pair *const&access(Vector const&pairs, KK const&key) const; - - template - constexpr Pair *&access(Vector &pairs, KK const&key); + constexpr Pair &access(Vector &pairs, KK const&key, bool &isNew); }; @@ -133,15 +131,10 @@ constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noex template constexpr T &SmallMap::operator[](MaybeView_t const&k) { - auto &p = access(m_pairs, k); - if (p == nullptr) { - if (static_cast(m_pairs.size()) * 0.7 < - static_cast(m_keys.size())) { - expand(); - } - p = new Pair; + bool isNew{}; + auto p = &access(m_pairs, k, isNew); + if (isNew) { p->key = k; - m_keys.emplace_back(k); } return p->value; } @@ -194,45 +187,41 @@ constexpr Vector const&SmallMap::keys() const noexcept { template constexpr void SmallMap::clear() { - for (std::size_t i = 0; i < m_pairs.size(); i++) { - delete m_pairs[i]; - } m_pairs.clear(); m_pairs.resize(127); } -template -constexpr void SmallMap::expand() { - Vector 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 template -constexpr typename SmallMap::Pair *const&SmallMap::access( - Vector const&pairs, KK const&k) const { +constexpr typename SmallMap::Pair const&SmallMap::access( + Vector 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; + m_keys.emplace_back(K(k)); + return pairs.emplace_back(); } template template -constexpr typename SmallMap::Pair *&SmallMap::access( - Vector &pairs, KK const&k) { +constexpr typename SmallMap::Pair &SmallMap::access( + Vector &pairs, KK const&k, bool &isNew) { for (auto &p : pairs) { if (p.key == k) { - return &p; + isNew = false; + return p; } } - return nullptr; + isNew = true; + if (static_cast(m_pairs.size()) * 0.7 < + static_cast(m_keys.size())) { + } + m_keys.emplace_back(K(k)); + return pairs.emplace_back(); } } From b089bf460b08af7ec482773366d65c422da66866 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 23:54:22 -0500 Subject: [PATCH 04/11] [ox/std] Optimize Array compare --- deps/ox/src/ox/std/array.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/deps/ox/src/ox/std/array.hpp b/deps/ox/src/ox/std/array.hpp index d20a6180..242010f1 100644 --- a/deps/ox/src/ox/std/array.hpp +++ b/deps/ox/src/ox/std/array.hpp @@ -137,12 +137,16 @@ constexpr Array::Array(Array &&other) noexcept { template constexpr bool Array::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 From b66f61c21795d0acd49cba0ff03883d2a3714694 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 23:55:41 -0500 Subject: [PATCH 05/11] [ox/std] Add hash function for UUID --- deps/ox/src/ox/std/uuid.hpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/deps/ox/src/ox/std/uuid.hpp b/deps/ox/src/ox/std/uuid.hpp index f4a7a899..80b66f1b 100644 --- a/deps/ox/src/ox/std/uuid.hpp +++ b/deps/ox/src/ox/std/uuid.hpp @@ -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 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; } } @@ -192,6 +194,24 @@ class UUID { } }; + +template<> +struct hash { + [[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(v.value()[i]) << (i * 8); + } + } else { + memcpy(&out, &v, sizeof(out)); + } + return out; + } +}; + + template constexpr Error model(T *io, ox::CommonPtrWith auto *obj) noexcept { oxReturnError(io->template setTypeInfo()); From aeb1ef3b125921e814ad83722a728ff02aebf94e Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 23:58:07 -0500 Subject: [PATCH 06/11] [ox/std] Cleanup SmallMap, make it easier to make potential changes --- deps/ox/src/ox/std/smallmap.hpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index db2fa3eb..f8b58c4d 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -29,11 +29,12 @@ class SmallMap { K key = {}; T value{}; }; + using PairVector = Vector; Vector m_keys; - Vector m_pairs; + PairVector m_pairs; public: - explicit constexpr SmallMap(std::size_t size = 127); + constexpr SmallMap() = default; constexpr SmallMap(SmallMap const&other); @@ -68,17 +69,13 @@ class SmallMap { private: template - constexpr Pair const&access(Vector const&pairs, KK const&key, bool &isNew) const; + constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const; template - constexpr Pair &access(Vector &pairs, KK const&key, bool &isNew); + constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew); }; -template -constexpr SmallMap::SmallMap(std::size_t size): m_pairs(size) { -} - template constexpr SmallMap::SmallMap(SmallMap const&other) { m_pairs = other.m_pairs; @@ -188,13 +185,12 @@ constexpr Vector const&SmallMap::keys() const noexcept { template constexpr void SmallMap::clear() { m_pairs.clear(); - m_pairs.resize(127); } template template constexpr typename SmallMap::Pair const&SmallMap::access( - Vector const&pairs, KK const&k, bool &isNew) const { + PairVector const&pairs, KK const&k, bool &isNew) const { for (auto const&p : pairs) { if (p.key == k) { isNew = false; @@ -209,7 +205,7 @@ constexpr typename SmallMap::Pair const&SmallMap::access( template template constexpr typename SmallMap::Pair &SmallMap::access( - Vector &pairs, KK const&k, bool &isNew) { + PairVector &pairs, KK const&k, bool &isNew) { for (auto &p : pairs) { if (p.key == k) { isNew = false; From 09d840cfd03b14d3fe6b174cd5d98c8b800cde3a Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 10 May 2024 23:58:35 -0500 Subject: [PATCH 07/11] [ox/std] Add some functions for comparing HashMap and SmallMap --- deps/ox/src/ox/std/test/CMakeLists.txt | 4 +- deps/ox/src/ox/std/test/tests.cpp | 156 ++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 5 deletions(-) diff --git a/deps/ox/src/ox/std/test/CMakeLists.txt b/deps/ox/src/ox/std/test/CMakeLists.txt index d0c7da23..9c395b9c 100644 --- a/deps/ox/src/ox/std/test/CMakeLists.txt +++ b/deps/ox/src/ox/std/test/CMakeLists.txt @@ -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) diff --git a/deps/ox/src/ox/std/test/tests.cpp b/deps/ox/src/ox/std/test/tests.cpp index 83454091..69808814 100644 --- a/deps/ox/src/ox/std/test/tests.cpp +++ b/deps/ox/src/ox/std/test/tests.cpp @@ -6,13 +6,111 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#include "ox/std/def.hpp" +#if __has_include() +#include +#endif + +#include #undef NDEBUG #include #include #include +[[nodiscard]] +static uint64_t nowMs() { +#if __has_include() + using namespace std::chrono; + return static_cast( + duration_cast( + system_clock::now().time_since_epoch()).count()); +#else + return 0; +#endif +} + +template> +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]; + } + return nowMs() - startTime; +} + +template> +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>(elemCnt, lookupCnt, seed); + hashTime = timeMapStrToUuid>(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>(elemCnt, lookupCnt, seed); + hashTime = timeMapStrToUuid>(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>(elemCnt, lookupCnt, seed); + hashTime = timeMapUuidToStr>(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 tests = { { "malloc", @@ -23,6 +121,8 @@ static std::map tests = { auto a2 = static_cast(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 +167,14 @@ static std::map 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"); @@ -134,10 +234,38 @@ static std::map tests = { return OxError(0); } }, + { + "SmallMap", + [] { + ox::SmallMap 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 si; + si["asdf"] = 42; + si["aoeu"] = 100; + oxAssert(si["asdf"] == 42, "asdf != 42"); + oxAssert(si["aoeu"] == 100, "aoeu != 100"); + ox::SmallMap 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 si; + ox::HashMap si; si["asdf"] = 42; si["aoeu"] = 100; oxAssert(si["asdf"] == 42, "asdf != 42"); @@ -150,6 +278,26 @@ static std::map tests = { return OxError(0); } }, + { + "TimeSmallMapMillion", + [] { + timeMapStrToUuid>(1'000, 1'000'000); + return ox::Error{}; + } + }, + { + "TimeHashMapMillion", + [] { + timeMapStrToUuid>(1'000, 1'000'000); + return ox::Error{}; + } + }, + { + "CompareMaps", + [] { + return compareMaps(); + } + }, { "Serialize-Int", [] { From d054528e4913df6ee4968cd2e9f626819a7b5071 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 11 May 2024 00:24:37 -0500 Subject: [PATCH 08/11] [ox/std] Remove empty if from SmallMap --- deps/ox/src/ox/std/smallmap.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index f8b58c4d..f2f20223 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -213,9 +213,6 @@ constexpr typename SmallMap::Pair &SmallMap::access( } } isNew = true; - if (static_cast(m_pairs.size()) * 0.7 < - static_cast(m_keys.size())) { - } m_keys.emplace_back(K(k)); return pairs.emplace_back(); } From e8041121d02c237e47f7e3da8c8fb63e060c4be6 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 11 May 2024 00:26:57 -0500 Subject: [PATCH 09/11] [ox/std] Add missing oxExpect to timeMapStrToUuid --- deps/ox/src/ox/std/test/tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/deps/ox/src/ox/std/test/tests.cpp b/deps/ox/src/ox/std/test/tests.cpp index 69808814..e0ad7165 100644 --- a/deps/ox/src/ox/std/test/tests.cpp +++ b/deps/ox/src/ox/std/test/tests.cpp @@ -45,6 +45,7 @@ uint64_t timeMapStrToUuid(int elemCnt, int lookups, uint64_t seed = 4321) noexce 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; } From 30797c710b8a8e836a4b564ed47a1a1377187825 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 11 May 2024 00:53:31 -0500 Subject: [PATCH 10/11] [ox/std] Add small sz option to SmallMap --- deps/ox/src/ox/std/smallmap.hpp | 68 ++++++++++++++++----------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index f2f20223..78502faf 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -17,7 +17,7 @@ namespace ox { -template +template class SmallMap { public: @@ -29,7 +29,7 @@ class SmallMap { K key = {}; T value{}; }; - using PairVector = Vector; + using PairVector = Vector; Vector m_keys; PairVector m_pairs; @@ -76,24 +76,24 @@ class SmallMap { }; -template -constexpr SmallMap::SmallMap(SmallMap const&other) { +template +constexpr SmallMap::SmallMap(SmallMap const&other) { m_pairs = other.m_pairs; } -template -constexpr SmallMap::SmallMap(SmallMap &&other) noexcept { +template +constexpr SmallMap::SmallMap(SmallMap &&other) noexcept { m_keys = std::move(other.m_keys); m_pairs = std::move(other.m_pairs); } -template -constexpr SmallMap::~SmallMap() { +template +constexpr SmallMap::~SmallMap() { clear(); } -template -constexpr bool SmallMap::operator==(SmallMap const&other) const { +template +constexpr bool SmallMap::operator==(SmallMap const&other) const { if (m_keys != other.m_keys) { return false; } @@ -106,8 +106,8 @@ constexpr bool SmallMap::operator==(SmallMap const&other) const { return true; } -template -constexpr SmallMap &SmallMap::operator=(SmallMap const&other) { +template +constexpr SmallMap &SmallMap::operator=(SmallMap const&other) { if (this != &other) { clear(); m_keys = other.m_keys; @@ -116,8 +116,8 @@ constexpr SmallMap &SmallMap::operator=(SmallMap const&other) return *this; } -template -constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noexcept { +template +constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noexcept { if (this != &other) { clear(); m_keys = std::move(other.m_keys); @@ -126,8 +126,8 @@ constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noex return *this; } -template -constexpr T &SmallMap::operator[](MaybeView_t const&k) { +template +constexpr T &SmallMap::operator[](MaybeView_t const&k) { bool isNew{}; auto p = &access(m_pairs, k, isNew); if (isNew) { @@ -136,8 +136,8 @@ constexpr T &SmallMap::operator[](MaybeView_t const&k) { return p->value; } -template -constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { +template +constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { auto p = access(m_pairs, k); if (!p) { return {nullptr, OxError(1, "value not found for given key")}; @@ -145,8 +145,8 @@ constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { return &p->value; } -template -constexpr Result SmallMap::at(MaybeView_t const&k) const noexcept { +template +constexpr Result SmallMap::at(MaybeView_t const&k) const noexcept { auto p = access(m_pairs, k); if (!p) { return {nullptr, OxError(1, "value not found for given key")}; @@ -154,8 +154,8 @@ constexpr Result SmallMap::at(MaybeView_t const&k) const noex return &p->value; } -template -constexpr void SmallMap::erase(MaybeView_t const&k) { +template +constexpr void SmallMap::erase(MaybeView_t const&k) { size_t i{}; for (auto const&p : m_pairs) { if (k == p.key) { @@ -167,29 +167,29 @@ constexpr void SmallMap::erase(MaybeView_t const&k) { std::ignore = m_keys.erase(i); } -template -constexpr bool SmallMap::contains(MaybeView_t const&k) const noexcept { +template +constexpr bool SmallMap::contains(MaybeView_t const&k) const noexcept { return access(m_pairs, k) != nullptr; } -template -constexpr std::size_t SmallMap::size() const noexcept { +template +constexpr std::size_t SmallMap::size() const noexcept { return m_keys.size(); } -template -constexpr Vector const&SmallMap::keys() const noexcept { +template +constexpr Vector const&SmallMap::keys() const noexcept { return m_keys; } -template -constexpr void SmallMap::clear() { +template +constexpr void SmallMap::clear() { m_pairs.clear(); } -template +template template -constexpr typename SmallMap::Pair const&SmallMap::access( +constexpr typename SmallMap::Pair const&SmallMap::access( PairVector const&pairs, KK const&k, bool &isNew) const { for (auto const&p : pairs) { if (p.key == k) { @@ -202,9 +202,9 @@ constexpr typename SmallMap::Pair const&SmallMap::access( return pairs.emplace_back(); } -template +template template -constexpr typename SmallMap::Pair &SmallMap::access( +constexpr typename SmallMap::Pair &SmallMap::access( PairVector &pairs, KK const&k, bool &isNew) { for (auto &p : pairs) { if (p.key == k) { From 7233da75eaaea055ed0486895fc85606db86d0f4 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 11 May 2024 01:59:40 -0500 Subject: [PATCH 11/11] [ox/std] Remove dedicated keys array from SmallMap --- deps/ox/src/ox/std/smallmap.hpp | 75 +++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index 78502faf..28f2d43e 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -23,14 +23,13 @@ class SmallMap { public: using key_t = K; using value_t = T; - - private: struct Pair { K key = {}; T value{}; }; + + private: using PairVector = Vector; - Vector m_keys; PairVector m_pairs; public: @@ -63,7 +62,22 @@ class SmallMap { constexpr std::size_t size() const noexcept; [[nodiscard]] - constexpr Vector const&keys() const noexcept; + constexpr Vector 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(); @@ -83,7 +97,6 @@ constexpr SmallMap::SmallMap(SmallMap const&other) template constexpr SmallMap::SmallMap(SmallMap &&other) noexcept { - m_keys = std::move(other.m_keys); m_pairs = std::move(other.m_pairs); } @@ -94,23 +107,13 @@ constexpr SmallMap::~SmallMap() { template constexpr bool SmallMap::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; + return m_pairs == other.m_pairs; } template constexpr SmallMap &SmallMap::operator=(SmallMap const&other) { if (this != &other) { clear(); - m_keys = other.m_keys; m_pairs = other.m_pairs; } return *this; @@ -120,7 +123,6 @@ template constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noexcept { if (this != &other) { clear(); - m_keys = std::move(other.m_keys); m_pairs = std::move(other.m_pairs); } return *this; @@ -164,7 +166,6 @@ constexpr void SmallMap::erase(MaybeView_t const&k) { ++i; } std::ignore = m_pairs.erase(i); - std::ignore = m_keys.erase(i); } template @@ -174,12 +175,42 @@ constexpr bool SmallMap::contains(MaybeView_t const&k) const n template constexpr std::size_t SmallMap::size() const noexcept { - return m_keys.size(); + return m_pairs.size(); } template -constexpr Vector const&SmallMap::keys() const noexcept { - return m_keys; +constexpr Vector SmallMap::keys() const noexcept { + ox::Vector keys; + keys.reserve(m_pairs.size()); + for (auto const&p : m_pairs) { + keys.emplace_back(p.key); + } + return keys; +} + +template +constexpr K const&SmallMap::key(size_t i) const noexcept { + return m_pairs[i].key; +} + +template +constexpr T const&SmallMap::value(size_t i) const noexcept { + return m_pairs[i].value; +} + +template +constexpr T &SmallMap::value(size_t i) noexcept { + return m_pairs[i].value; +} + +template +constexpr SmallMap::Pair const&SmallMap::get(size_t i) const noexcept { + return m_pairs[i]; +} + +template +constexpr SmallMap::Pair &SmallMap::get(size_t i) noexcept { + return m_pairs[i]; } template @@ -198,7 +229,6 @@ constexpr typename SmallMap::Pair const&SmallMap:: } } isNew = true; - m_keys.emplace_back(K(k)); return pairs.emplace_back(); } @@ -213,7 +243,6 @@ constexpr typename SmallMap::Pair &SmallMap::acces } } isNew = true; - m_keys.emplace_back(K(k)); return pairs.emplace_back(); }