forked from OctaForge/libostd
cleaner multihash handling
parent
e0ce128d13
commit
7cf50febd9
|
@ -140,7 +140,8 @@ namespace detail {
|
||||||
typename T, /* value type */
|
typename T, /* value type */
|
||||||
typename H, /* hash func */
|
typename H, /* hash func */
|
||||||
typename C, /* equality check */
|
typename C, /* equality check */
|
||||||
typename A /* allocator */
|
typename A, /* allocator */
|
||||||
|
bool Multihash
|
||||||
> struct Hashtable {
|
> struct Hashtable {
|
||||||
static constexpr octa::Size CHUNKSIZE = 64;
|
static constexpr octa::Size CHUNKSIZE = 64;
|
||||||
|
|
||||||
|
@ -328,7 +329,6 @@ namespace detail {
|
||||||
return B::get_data(c->value);
|
return B::get_data(c->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool multi>
|
|
||||||
octa::Size remove(const K &key) {
|
octa::Size remove(const K &key) {
|
||||||
if (!p_len) return 0;
|
if (!p_len) return 0;
|
||||||
octa::Size olen = p_len;
|
octa::Size olen = p_len;
|
||||||
|
@ -342,7 +342,7 @@ namespace detail {
|
||||||
p_unused = c;
|
p_unused = c;
|
||||||
octa::allocator_destroy(get_alloc(), &c->value);
|
octa::allocator_destroy(get_alloc(), &c->value);
|
||||||
octa::allocator_construct(get_alloc(), &c->value);
|
octa::allocator_construct(get_alloc(), &c->value);
|
||||||
if (!multi) return 1;
|
if (!Multihash) return 1;
|
||||||
} else {
|
} else {
|
||||||
p = &c->next;
|
p = &c->next;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,6 @@ namespace detail {
|
||||||
return olen - p_len;
|
return olen - p_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool multi>
|
|
||||||
octa::Size count(const K &key) {
|
octa::Size count(const K &key) {
|
||||||
if (!p_len) return 0;
|
if (!p_len) return 0;
|
||||||
octa::Size h = get_hash()(key) & (p_size - 1);
|
octa::Size h = get_hash()(key) & (p_size - 1);
|
||||||
|
@ -359,7 +358,7 @@ namespace detail {
|
||||||
for (Chain *c = p_data.first()[h]; c; c = c->next)
|
for (Chain *c = p_data.first()[h]; c; c = c->next)
|
||||||
if (get_eq()(key, B::get_key(c->value))) {
|
if (get_eq()(key, B::get_key(c->value))) {
|
||||||
++ret;
|
++ret;
|
||||||
if (!multi) break;
|
if (!Multihash) break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +406,14 @@ namespace detail {
|
||||||
rehash_ahead(1);
|
rehash_ahead(1);
|
||||||
E elem(octa::forward<Args>(args)...);
|
E elem(octa::forward<Args>(args)...);
|
||||||
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
|
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
|
||||||
|
if (Multihash) {
|
||||||
|
/* multihash: always insert */
|
||||||
|
Chain *ch = insert(h);
|
||||||
|
B::swap_elem(ch->value, elem);
|
||||||
|
Chain **hch = p_data.first();
|
||||||
|
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
|
||||||
|
ch), true);
|
||||||
|
}
|
||||||
Chain *found = nullptr;
|
Chain *found = nullptr;
|
||||||
bool ins = true;
|
bool ins = true;
|
||||||
for (Chain *c = p_data.first()[h]; c; c = c->next) {
|
for (Chain *c = p_data.first()[h]; c; c = c->next) {
|
||||||
|
@ -425,18 +432,6 @@ namespace detail {
|
||||||
found), ins);
|
found), ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...Args>
|
|
||||||
octa::Pair<Range, bool> emplace_multi(Args &&...args) {
|
|
||||||
rehash_ahead(1);
|
|
||||||
E elem(octa::forward<Args>(args)...);
|
|
||||||
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
|
|
||||||
Chain *ch = insert(h);
|
|
||||||
B::swap_elem(ch->value, elem);
|
|
||||||
Chain **hch = p_data.first();
|
|
||||||
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
|
|
||||||
ch), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool find(const K &key, octa::Size &h, Chain *&oc) const {
|
bool find(const K &key, octa::Size &h, Chain *&oc) const {
|
||||||
if (!p_size) return false;
|
if (!p_size) return false;
|
||||||
h = get_hash()(key) & (p_size - 1);
|
h = get_hash()(key) & (p_size - 1);
|
||||||
|
|
15
octa/map.h
15
octa/map.h
|
@ -47,7 +47,8 @@ template<
|
||||||
> struct Map {
|
> struct Map {
|
||||||
private:
|
private:
|
||||||
using Base = octa::detail::Hashtable<
|
using Base = octa::detail::Hashtable<
|
||||||
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>, K, T, H, C, A
|
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
|
||||||
|
K, T, H, C, A, false
|
||||||
>;
|
>;
|
||||||
Base p_table;
|
Base p_table;
|
||||||
|
|
||||||
|
@ -197,11 +198,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size erase(const K &key) {
|
octa::Size erase(const K &key) {
|
||||||
return p_table.remove<false>(key);
|
return p_table.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size count(const K &key) {
|
octa::Size count(const K &key) {
|
||||||
return p_table.count<false>(key);
|
return p_table.count(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range find(const K &key) { return p_table.find(key); }
|
Range find(const K &key) { return p_table.find(key); }
|
||||||
|
@ -241,7 +242,7 @@ template<
|
||||||
private:
|
private:
|
||||||
using Base = octa::detail::Hashtable<
|
using Base = octa::detail::Hashtable<
|
||||||
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
|
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
|
||||||
K, T, H, C, A
|
K, T, H, C, A, true
|
||||||
>;
|
>;
|
||||||
Base p_table;
|
Base p_table;
|
||||||
|
|
||||||
|
@ -368,15 +369,15 @@ public:
|
||||||
|
|
||||||
template<typename ...Args>
|
template<typename ...Args>
|
||||||
octa::Pair<Range, bool> emplace(Args &&...args) {
|
octa::Pair<Range, bool> emplace(Args &&...args) {
|
||||||
return p_table.emplace_multi(octa::forward<Args>(args)...);
|
return p_table.emplace(octa::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size erase(const K &key) {
|
octa::Size erase(const K &key) {
|
||||||
return p_table.remove<true>(key);
|
return p_table.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size count(const K &key) {
|
octa::Size count(const K &key) {
|
||||||
return p_table.count<true>(key);
|
return p_table.count(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range find(const K &key) { return p_table.find(key); }
|
Range find(const K &key) { return p_table.find(key); }
|
||||||
|
|
14
octa/set.h
14
octa/set.h
|
@ -38,7 +38,7 @@ template<
|
||||||
> struct Set {
|
> struct Set {
|
||||||
private:
|
private:
|
||||||
using Base = octa::detail::Hashtable<
|
using Base = octa::detail::Hashtable<
|
||||||
octa::detail::SetBase<T, A>, T, T, T, H, C, A
|
octa::detail::SetBase<T, A>, T, T, T, H, C, A, false
|
||||||
>;
|
>;
|
||||||
Base p_table;
|
Base p_table;
|
||||||
|
|
||||||
|
@ -165,11 +165,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size erase(const T &key) {
|
octa::Size erase(const T &key) {
|
||||||
return p_table.remove<false>(key);
|
return p_table.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size count(const T &key) {
|
octa::Size count(const T &key) {
|
||||||
return p_table.count<false>(key);
|
return p_table.count(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range find(const Key &key) { return p_table.find(key); }
|
Range find(const Key &key) { return p_table.find(key); }
|
||||||
|
@ -208,7 +208,7 @@ template<
|
||||||
> struct Multiset {
|
> struct Multiset {
|
||||||
private:
|
private:
|
||||||
using Base = octa::detail::Hashtable<
|
using Base = octa::detail::Hashtable<
|
||||||
octa::detail::SetBase<T, A>, T, T, T, H, C, A
|
octa::detail::SetBase<T, A>, T, T, T, H, C, A, true
|
||||||
>;
|
>;
|
||||||
Base p_table;
|
Base p_table;
|
||||||
|
|
||||||
|
@ -334,15 +334,15 @@ public:
|
||||||
|
|
||||||
template<typename ...Args>
|
template<typename ...Args>
|
||||||
octa::Pair<Range, bool> emplace(Args &&...args) {
|
octa::Pair<Range, bool> emplace(Args &&...args) {
|
||||||
return p_table.emplace_multi(octa::forward<Args>(args)...);
|
return p_table.emplace(octa::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size erase(const T &key) {
|
octa::Size erase(const T &key) {
|
||||||
return p_table.remove<true>(key);
|
return p_table.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
octa::Size count(const T &key) {
|
octa::Size count(const T &key) {
|
||||||
return p_table.count<true>(key);
|
return p_table.count(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range find(const T &key) { return p_table.find(key); }
|
Range find(const T &key) { return p_table.find(key); }
|
||||||
|
|
Loading…
Reference in New Issue