[ox] Improve hasing and MaybeView
All checks were successful
Build / build (push) Successful in 2m29s
All checks were successful
Build / build (push) Successful in 2m29s
* Add CityHash dep * Use CityHash for HashMap * Make MaybeView more versatile * Cleanup some inappropriate MaybeView uses
This commit is contained in:
2
deps/ox/src/ox/model/walk.hpp
vendored
2
deps/ox/src/ox/model/walk.hpp
vendored
@ -64,7 +64,7 @@ constexpr Error DataWalker<Reader, T>::read(const DescriptorField &f, Reader *rd
|
||||
|
||||
template<typename Reader, typename T>
|
||||
constexpr void DataWalker<Reader, T>::pushNamePath(const FieldName &fn) noexcept {
|
||||
m_path.push_back(fn);
|
||||
m_path.emplace_back(fn);
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
|
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -81,6 +81,7 @@ target_link_libraries(
|
||||
OxStd PUBLIC
|
||||
$<$<CXX_COMPILER_ID:GNU>:gcc>
|
||||
OxTraceHook
|
||||
CityHash
|
||||
)
|
||||
|
||||
install(
|
||||
|
170
deps/ox/src/ox/std/hash.hpp
vendored
Normal file
170
deps/ox/src/ox/std/hash.hpp
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#if __has_include(<functional>)
|
||||
#include <functional>
|
||||
#else
|
||||
namespace std {
|
||||
template<typename T>
|
||||
struct hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <cityhash/city.h>
|
||||
|
||||
#include "istring.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T>
|
||||
struct hash {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(T const&v) const noexcept {
|
||||
return std::hash<T>{}(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<bool> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(bool v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<char> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(char v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<short> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(short v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<int> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(int v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<long> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(long v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<long long> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(long long v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
struct hash<unsigned char> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(unsigned char v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<unsigned short> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(unsigned short v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<unsigned int> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(unsigned int v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<unsigned long> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(unsigned long v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<unsigned long long> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(unsigned long long v) const noexcept {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto hashString(ox::StringView const&v) noexcept {
|
||||
if constexpr(sizeof(void*) == 8) {
|
||||
return cityhash::CityHash64(v.data(), v.bytes());
|
||||
} else {
|
||||
return cityhash::CityHash32(v.data(), v.bytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
struct hash<ox::StringView> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(ox::StringView v) const noexcept {
|
||||
return hashString(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<ox::String> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(ox::StringView v) const noexcept {
|
||||
return hashString(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t sz>
|
||||
struct hash<ox::IString<sz>> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(ox::StringView v) const noexcept {
|
||||
return hashString(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<const char*> {
|
||||
[[nodiscard]]
|
||||
constexpr size_t operator()(ox::StringView v) const noexcept {
|
||||
return hashString(v);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
37
deps/ox/src/ox/std/hashmap.hpp
vendored
37
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "algorithm.hpp"
|
||||
#include "hash.hpp"
|
||||
#include "ignore.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strops.hpp"
|
||||
@ -32,7 +33,7 @@ class HashMap {
|
||||
Vector<Pair*> m_pairs;
|
||||
|
||||
public:
|
||||
explicit constexpr HashMap(std::size_t size = 100);
|
||||
explicit constexpr HashMap(std::size_t size = 127);
|
||||
|
||||
constexpr HashMap(HashMap const&other);
|
||||
|
||||
@ -68,10 +69,6 @@ class HashMap {
|
||||
private:
|
||||
constexpr void expand();
|
||||
|
||||
constexpr static uint64_t hash(Integral_c auto) noexcept;
|
||||
|
||||
constexpr static uint64_t hash(StringView const&) noexcept;
|
||||
|
||||
template<typename KK>
|
||||
constexpr Pair *const&access(Vector<Pair*> const&pairs, KK const&key) const;
|
||||
|
||||
@ -172,14 +169,14 @@ constexpr void HashMap<K, T>::erase(MaybeView_t<K> const&k) {
|
||||
if (!contains(k)) {
|
||||
return;
|
||||
}
|
||||
auto h = hash(k) % m_pairs.size();
|
||||
auto h = ox::hash<MaybeView_t<K>>{}(k) % m_pairs.size();
|
||||
while (true) {
|
||||
const auto &p = m_pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
std::ignore = m_pairs.erase(h);
|
||||
break;
|
||||
} else {
|
||||
h = hash(h) % m_pairs.size();
|
||||
h = ox::hash<MaybeView_t<K>>{}(k) % m_pairs.size();
|
||||
}
|
||||
}
|
||||
std::ignore = m_keys.erase(ox::find(m_keys.begin(), m_keys.end(), k));
|
||||
@ -206,7 +203,7 @@ constexpr void HashMap<K, T>::clear() {
|
||||
delete m_pairs[i];
|
||||
}
|
||||
m_pairs.clear();
|
||||
m_pairs.resize(100);
|
||||
m_pairs.resize(127);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
@ -219,30 +216,10 @@ constexpr void HashMap<K, T>::expand() {
|
||||
m_pairs = std::move(r);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr uint64_t HashMap<K, T>::hash(Integral_c auto k) noexcept {
|
||||
uint64_t sum = 1;
|
||||
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;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr uint64_t HashMap<K, T>::hash(StringView const&k) noexcept {
|
||||
uint64_t sum = 1;
|
||||
for (auto i = 0u; i < k.len(); ++i) {
|
||||
sum += ((sum + static_cast<uint64_t>(k[i])) * 7) * sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
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>(hash(k) % pairs.size());
|
||||
auto h = static_cast<std::size_t>(ox::hash<KK>{}(k) % pairs.size());
|
||||
while (true) {
|
||||
const auto &p = pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
@ -256,7 +233,7 @@ constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*
|
||||
template<typename K, typename T>
|
||||
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>(hash(k) % pairs.size());
|
||||
auto h = static_cast<std::size_t>(ox::hash<KK>{}(k) % pairs.size());
|
||||
while (true) {
|
||||
auto &p = pairs[h];
|
||||
if (p == nullptr || p->key == k) {
|
||||
|
5
deps/ox/src/ox/std/istring.hpp
vendored
5
deps/ox/src/ox/std/istring.hpp
vendored
@ -282,4 +282,9 @@ constexpr std::size_t IString<buffLen>::cap() const noexcept {
|
||||
return buffLen;
|
||||
}
|
||||
|
||||
template<size_t sz>
|
||||
struct MaybeView<ox::IString<sz>> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
|
||||
}
|
||||
|
2
deps/ox/src/ox/std/maybeview.hpp
vendored
2
deps/ox/src/ox/std/maybeview.hpp
vendored
@ -15,7 +15,7 @@ namespace ox {
|
||||
// Maybe StringView. If T is a string type, MaybeType::type/MaybeView_t is a
|
||||
// StringView. This avoids creating unnecessary Strings when taking a
|
||||
// StringView or C string as a function argument.
|
||||
template<typename T, bool isStr = isOxString_v<T>>
|
||||
template<typename T>
|
||||
struct MaybeView {
|
||||
using type = T;
|
||||
};
|
||||
|
5
deps/ox/src/ox/std/string.hpp
vendored
5
deps/ox/src/ox/std/string.hpp
vendored
@ -589,4 +589,9 @@ constexpr auto alignOf(const ox::BasicString<SmallStringSize_v>&) noexcept {
|
||||
return alignOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<size_t sz>
|
||||
struct MaybeView<ox::BasicString<sz>> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
|
||||
}
|
||||
|
5
deps/ox/src/ox/std/stringview.hpp
vendored
5
deps/ox/src/ox/std/stringview.hpp
vendored
@ -98,11 +98,6 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct MaybeView<T, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
|
||||
constexpr ox::Result<int> atoi(ox::CRStringView str) noexcept {
|
||||
int total = 0;
|
||||
int multiplier = 1;
|
||||
|
31
deps/ox/src/ox/std/utility.hpp
vendored
31
deps/ox/src/ox/std/utility.hpp
vendored
@ -8,7 +8,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include(<utility>)
|
||||
#include <utility>
|
||||
#include "typetraits.hpp"
|
||||
#else
|
||||
#include "typetraits.hpp"
|
||||
namespace std {
|
||||
|
||||
template<typename T>
|
||||
constexpr typename ox::remove_reference<T>::type &&move(T &&t) noexcept {
|
||||
return static_cast<typename ox::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void swap(T &a, T &b) noexcept {
|
||||
auto temp = std::move(a);
|
||||
a = std::move(b);
|
||||
b = std::move(temp);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -30,14 +50,3 @@ constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if __has_include(<utility>)
|
||||
#include <utility>
|
||||
#else
|
||||
namespace std {
|
||||
template<typename T>
|
||||
constexpr typename ox::remove_reference<T>::type &&move(T &&t) noexcept {
|
||||
return static_cast<typename ox::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
39
deps/ox/src/ox/std/vector.hpp
vendored
39
deps/ox/src/ox/std/vector.hpp
vendored
@ -272,9 +272,9 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
constexpr bool contains(MaybeView_t<T> const&) const noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(
|
||||
std::size_t pos, std::size_t cnt, MaybeView_t<T> const&val) noexcept(useNoexcept);
|
||||
std::size_t pos, std::size_t cnt, T val) noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, MaybeView_t<T> const&val) noexcept(useNoexcept);
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, T val) noexcept(useNoexcept);
|
||||
|
||||
template<typename... Args>
|
||||
constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept);
|
||||
@ -282,9 +282,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
template<typename... Args>
|
||||
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(T &&item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(MaybeView_t<T> const&item) noexcept(useNoexcept);
|
||||
constexpr void push_back(T item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void pop_back() noexcept(useNoexcept);
|
||||
|
||||
@ -534,14 +532,14 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> co
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
std::size_t pos, std::size_t cnt, MaybeView_t<T> const&val) noexcept(useNoexcept) {
|
||||
std::size_t pos, std::size_t cnt, T val) noexcept(useNoexcept) {
|
||||
if (m_size + cnt > m_cap) {
|
||||
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
|
||||
if (pos < m_size) {
|
||||
m_items[pos] = val;
|
||||
m_items[pos] = std::move(val);
|
||||
} else {
|
||||
for (auto i = 0u; i < cnt; ++i) {
|
||||
std::construct_at(&m_items[pos + i], val);
|
||||
std::construct_at(&m_items[pos + i], m_items[pos]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -549,10 +547,10 @@ Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
for (auto i = m_size + cnt - 1; i > pos; --i) {
|
||||
std::construct_at(&m_items[i], std::move(m_items[i - cnt]));
|
||||
}
|
||||
m_items[pos] = val;
|
||||
m_items[pos] = std::move(val);
|
||||
} else {
|
||||
for (auto i = 0u; i < cnt; ++i) {
|
||||
std::construct_at(&m_items[pos + i], val);
|
||||
std::construct_at(&m_items[pos + i], m_items[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,22 +560,22 @@ Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, MaybeView_t<T> const&val) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, T val) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
|
||||
if (pos < m_size) {
|
||||
m_items[pos] = val;
|
||||
m_items[pos] = std::move(val);
|
||||
} else {
|
||||
std::construct_at(&m_items[pos], val);
|
||||
std::construct_at(&m_items[pos], m_items[pos]);
|
||||
}
|
||||
} else {
|
||||
if (pos < m_size) {
|
||||
for (auto i = m_size; i > pos; --i) {
|
||||
std::construct_at(&m_items[i], std::move(m_items[i - 1]));
|
||||
}
|
||||
m_items[pos] = val;
|
||||
m_items[pos] = std::move(val);
|
||||
} else {
|
||||
std::construct_at(&m_items[pos], val);
|
||||
std::construct_at(&m_items[pos], m_items[pos]);
|
||||
}
|
||||
}
|
||||
++m_size;
|
||||
@ -619,7 +617,7 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
@ -627,15 +625,6 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexce
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(MaybeView_t<T> const&item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
std::construct_at(&m_items[m_size], item);
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::pop_back() noexcept(useNoexcept) {
|
||||
--m_size;
|
||||
|
Reference in New Issue
Block a user