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