diff --git a/octa/internal/hashtable.h b/octa/internal/hashtable.h index 3668845..31db7cd 100644 --- a/octa/internal/hashtable.h +++ b/octa/internal/hashtable.h @@ -117,6 +117,8 @@ namespace detail { using Range = octa::HashRange; using ConstRange = octa::HashRange; + using LocalRange = Range; + using ConstLocalRange = ConstRange; DataPair p_data; @@ -260,6 +262,21 @@ namespace detail { octa::Size bucket_count() const { return p_size; } octa::Size max_bucket_count() const { return Size(~0) / sizeof(Chain); } + template + octa::Size bucket(const U &key) const { + return get_hash()(key) & (p_size - 1); + } + + octa::Size bucket_size(octa::Size n) const { + octa::Size ret = 0; + if (ret >= p_size) return ret; + Chain *c = p_data.first()[n]; + if (!c) return ret; + for (; c; c = c->next) + ++ret; + return ret; + } + void rehash(octa::Size count) { count = octa::max(count, octa::Size(p_len / max_load_factor())); @@ -302,6 +319,19 @@ namespace detail { return ConstRange(p_data.first(), bucket_count()); } + LocalRange each(octa::Size n) { + if (n >= p_size) return LocalRange(); + return LocalRange(nullptr, p_data.first()[n], 0); + } + ConstLocalRange each(octa::Size n) const { + if (n >= p_size) return ConstLocalRange(); + return ConstLocalRange(nullptr, p_data.first()[n], 0); + } + ConstLocalRange ceach(octa::Size n) const { + if (n >= p_size) return ConstLocalRange(); + return ConstLocalRange(nullptr, p_data.first()[n], 0); + } + void swap(Hashtable &h) { octa::swap(p_size, h.p_size); octa::swap(p_len, h.p_len); diff --git a/octa/map.h b/octa/map.h index 171d9e9..f3417ab 100644 --- a/octa/map.h +++ b/octa/map.h @@ -63,6 +63,8 @@ public: using ConstPointer = octa::AllocatorConstPointer; using Range = octa::HashRange>; using ConstRange = octa::HashRange>; + using LocalRange = Range; + using ConstLocalRange = ConstRange; using Allocator = A; explicit Map(octa::Size size, const H &hf = H(), @@ -114,6 +116,9 @@ public: octa::Size bucket_count() const { return p_table.bucket_count(); } octa::Size max_bucket_count() const { return p_table.max_bucket_count(); } + octa::Size bucket(const K &key) const { return p_table.bucket(key); } + octa::Size bucket_size(octa::Size n) const { return p_table.bucket_size(n); } + void clear() { p_table.clear(); } A get_allocator() const { @@ -150,6 +155,13 @@ public: return 0; } + octa::Size count(const K &key) { + octa::Size h; + T *v = p_table.access_base(key, h); + if (v) return 1; + return 0; + } + float load_factor() const { return p_table.load_factor(); } float max_load_factor() const { return p_table.max_load_factor(); } void max_load_factor(float lf) { p_table.max_load_factor(lf); } @@ -166,6 +178,10 @@ public: ConstRange each() const { return p_table.each(); } ConstRange ceach() const { return p_table.ceach(); } + LocalRange each(octa::Size n) { return p_table.each(n); } + ConstLocalRange each(octa::Size n) const { return p_table.each(n); } + ConstLocalRange ceach(octa::Size n) const { return p_table.each(n); } + void swap(Map &v) { octa::swap(p_table, v.p_table); }