[ox/std] Add support for integral types as keys in HashMap
This commit is contained in:
parent
28960dd680
commit
714d9fe433
28
deps/ox/src/ox/std/hashmap.hpp
vendored
28
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -76,7 +76,7 @@ class HashMap {
|
|||||||
/**
|
/**
|
||||||
* K is assumed to be a null terminated string.
|
* K is assumed to be a null terminated string.
|
||||||
*/
|
*/
|
||||||
constexpr static uint64_t hash(K, int len = 0xFFFF) noexcept;
|
constexpr static uint64_t hash(auto) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* K is assumed to be a null terminated string.
|
* K is assumed to be a null terminated string.
|
||||||
@ -182,16 +182,13 @@ constexpr void HashMap<K, T>::erase(const K &k) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto h = hash(k) % m_pairs.size();
|
auto h = hash(k) % m_pairs.size();
|
||||||
char hashStr[sizeof(h) + 1];
|
|
||||||
ox_memcpy(hashStr, &h, sizeof(h));
|
|
||||||
hashStr[sizeof(h)] = 0;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const auto &p = m_pairs[h];
|
const auto &p = m_pairs[h];
|
||||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||||
oxIgnoreError(m_pairs.erase(h));
|
oxIgnoreError(m_pairs.erase(h));
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
h = hash(hashStr, 8) % m_pairs.size();
|
h = hash(h) % m_pairs.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oxIgnoreError(m_keys.erase(ox::find(m_keys.begin(), m_keys.end(), k)));
|
oxIgnoreError(m_keys.erase(ox::find(m_keys.begin(), m_keys.end(), k)));
|
||||||
@ -232,11 +229,19 @@ constexpr void HashMap<K, T>::expand() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename T>
|
template<typename K, typename T>
|
||||||
constexpr uint64_t HashMap<K, T>::hash(K k, int len) noexcept {
|
constexpr uint64_t HashMap<K, T>::hash(auto k) noexcept {
|
||||||
uint64_t sum = 1;
|
uint64_t sum = 1;
|
||||||
for (auto i = 0u; i < static_cast<uint64_t>(len) && k[i]; ++i) {
|
if constexpr(is_integral_v<decltype(k)>) {
|
||||||
|
for (auto i = 0u; i < sizeof(K); ++i) {
|
||||||
|
const auto shift = i * 8;
|
||||||
|
const auto v = static_cast<uint64_t>(k >> shift & 0xff);
|
||||||
|
sum += (sum + v) * 7 * sum;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto i = 0u; k[i]; ++i) {
|
||||||
sum += ((sum + static_cast<uint64_t>(k[i])) * 7) * sum;
|
sum += ((sum + static_cast<uint64_t>(k[i])) * 7) * sum;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +263,14 @@ constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pa
|
|||||||
auto h = hash(k) % pairs.size();
|
auto h = hash(k) % pairs.size();
|
||||||
while (true) {
|
while (true) {
|
||||||
auto &p = pairs[h];
|
auto &p = pairs[h];
|
||||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
bool matches = [&] {
|
||||||
|
if constexpr (is_integral_v<K>) {
|
||||||
|
return p == nullptr || k == p->key;
|
||||||
|
} else {
|
||||||
|
return p == nullptr || ox_strcmp(p->key, k) == 0;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
if (matches) {
|
||||||
return p;
|
return p;
|
||||||
} else {
|
} else {
|
||||||
h = (h + 1) % pairs.size();
|
h = (h + 1) % pairs.size();
|
||||||
|
15
deps/ox/src/ox/std/test/tests.cpp
vendored
15
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -109,11 +109,16 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
{
|
{
|
||||||
"HashMap",
|
"HashMap",
|
||||||
[] {
|
[] {
|
||||||
ox::HashMap<const char*, int> v;
|
ox::HashMap<const char*, int> si;
|
||||||
v["asdf"] = 42;
|
si["asdf"] = 42;
|
||||||
v["aoeu"] = 100;
|
si["aoeu"] = 100;
|
||||||
oxAssert(v["asdf"] == 42, "asdf != 42");
|
oxAssert(si["asdf"] == 42, "asdf != 42");
|
||||||
oxAssert(v["aoeu"] == 100, "aoeu != 100");
|
oxAssert(si["aoeu"] == 100, "aoeu != 100");
|
||||||
|
ox::HashMap<int, int> ii;
|
||||||
|
ii[4] = 42;
|
||||||
|
ii[5] = 100;
|
||||||
|
oxAssert(ii[4] == 42, "4 != 42");
|
||||||
|
oxAssert(ii[5] == 100, "5 != 100");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user