From eca4310caf3d20ba2d87a74e37d48d3a7173a9fe Mon Sep 17 00:00:00 2001 From: q66 Date: Tue, 16 Jun 2015 20:44:32 +0100 Subject: [PATCH] support for hashtable assignment ops --- octa/internal/hashtable.h | 70 ++++++++++++++++++++++++++++++++------- octa/map.h | 30 +++++++++++++++++ 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/octa/internal/hashtable.h b/octa/internal/hashtable.h index e5edfcf..2d3cadc 100644 --- a/octa/internal/hashtable.h +++ b/octa/internal/hashtable.h @@ -152,8 +152,16 @@ namespace detail { A &get_alloc() { return p_data.second().first().first(); } const A &get_alloc() const { return p_data.second().first().first(); } + CPA &get_cpalloc() { return p_data.second().first().second().first(); } + const CPA &get_cpalloc() const { + return p_data.second().first().second().first(); + } + CHA &get_challoc() { return p_data.second().first().second().second(); } + const CHA &get_challoc() const { + return p_data.second().first().second().second(); + } Hashtable(octa::Size size, const H &hf, const C &eqf, const A &alloc): p_size(size), p_len(0), p_chunks(nullptr), p_unused(nullptr), @@ -230,6 +238,38 @@ namespace detail { delete_chunks(p_chunks); } + Hashtable &operator=(const Hashtable &ht) { + clear(); + if (octa::AllocatorPropagateOnContainerCopyAssignment::value) { + if ((get_cpalloc() != ht.get_cpalloc()) && p_size) { + octa::allocator_deallocate(get_cpalloc(), + p_data.first(), p_size); + p_data.first() = octa::allocator_allocate(get_cpalloc(), + p_size); + memset(p_data.first(), 0, p_size * sizeof(Chain *)); + } + get_alloc() = ht.get_alloc(); + get_cpalloc() = ht.get_cpalloc(); + get_challoc() = ht.get_challoc(); + } + for (ConstRange range = ht.each(); !range.empty(); range.pop_front()) + emplace(range.front()); + return *this; + } + + Hashtable &operator=(Hashtable &&ht) { + clear(); + octa::swap(p_size, ht.p_size); + octa::swap(p_len, ht.p_len); + octa::swap(p_chunks, ht.p_chunks); + octa::swap(p_unused, ht.p_unused); + octa::swap(p_data.first(), ht.p_data.first()); + octa::swap(p_data.second().second(), ht.p_data.second().second()); + if (octa::AllocatorPropagateOnContainerMoveAssignment::value) + octa::swap(p_data.second().first(), ht.p_data.second().first()); + return *this; + } + bool empty() const { return p_len == 0; } octa::Size size() const { return p_len; } Size max_size() const { return Size(~0) / sizeof(E); } @@ -403,10 +443,14 @@ namespace detail { return Range(p_data.first(), p_data.first() + bucket_count()); } ConstRange each() const { - return ConstRange(p_data.first(), p_data.first() + bucket_count()); + using Chain = octa::detail::HashChain; + return ConstRange((Chain **)p_data.first(), + (Chain **)(p_data.first() + bucket_count())); } ConstRange ceach() const { - return ConstRange(p_data.first(), p_data.first() + bucket_count()); + using Chain = octa::detail::HashChain; + return ConstRange((Chain **)p_data.first(), + (Chain **)(p_data.first() + bucket_count())); } LocalRange each(octa::Size n) { @@ -414,23 +458,25 @@ namespace detail { return LocalRange(p_data.first()[n]); } ConstLocalRange each(octa::Size n) const { + using Chain = octa::detail::HashChain; if (n >= p_size) return ConstLocalRange(); - return ConstLocalRange(p_data.first()[n]); + return ConstLocalRange((Chain *)p_data.first()[n]); } ConstLocalRange ceach(octa::Size n) const { + using Chain = octa::detail::HashChain; if (n >= p_size) return ConstLocalRange(); - return ConstLocalRange(p_data.first()[n]); + return ConstLocalRange((Chain *)p_data.first()[n]); } - void swap(Hashtable &h) { - octa::swap(p_size, h.p_size); - octa::swap(p_len, h.p_len); - octa::swap(p_chunks, h.p_chunks); - octa::swap(p_unused, h.p_unused); - octa::swap(p_data.first(), h.p_data.first()); - octa::swap(p_data.second().second(), h.p_data.second().second()); + void swap(Hashtable &ht) { + octa::swap(p_size, ht.p_size); + octa::swap(p_len, ht.p_len); + octa::swap(p_chunks, ht.p_chunks); + octa::swap(p_unused, ht.p_unused); + octa::swap(p_data.first(), ht.p_data.first()); + octa::swap(p_data.second().second(), ht.p_data.second().second()); if (octa::AllocatorPropagateOnContainerSwap::value) - octa::swap(p_data.second().first(), h.p_data.second().first()); + octa::swap(p_data.second().first(), ht.p_data.second().first()); } }; } /* namespace detail */ diff --git a/octa/map.h b/octa/map.h index 007877b..ba40cdd 100644 --- a/octa/map.h +++ b/octa/map.h @@ -118,6 +118,36 @@ public: const A &alloc ): Map(octa::each(init), size, hf, C(), alloc) {} + Map &operator=(const Map &m) { + p_table = m.p_table; + return *this; + } + + Map &operator=(Map &&m) { + p_table = octa::move(m.p_table); + return *this; + } + + template + octa::EnableIf< + octa::IsInputRange::value && + octa::IsConvertible, Value>::value, + Map & + > operator=(R range) { + clear(); + for (; !range.empty(); range.pop_front()) + emplace(range.front()); + return *this; + } + + Map &operator=(InitializerList il) { + Value *beg = il.begin(), *end = il.end(); + clear(); + while (beg != end) + emplace(*beg++); + return *this; + } + bool empty() const { return p_table.empty(); } octa::Size size() const { return p_table.size(); } octa::Size max_size() const { return p_table.max_size(); }