diff --git a/cxxmph/hollow_iterator.h b/cxxmph/hollow_iterator.h index 35a18db..54fba74 100644 --- a/cxxmph/hollow_iterator.h +++ b/cxxmph/hollow_iterator.h @@ -30,11 +30,13 @@ struct hollow_iterator_base typedef self_type& self_reference; typedef typename iterator::reference reference; typedef typename iterator::pointer pointer; - hollow_iterator_base() : it_(), empty_() { } - hollow_iterator_base(iterator it, is_empty empty) : it_(it), empty_(empty) { - advance(); - } - hollow_iterator_base(const self_type& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; } + inline hollow_iterator_base() : it_(), empty_() { } + inline hollow_iterator_base(iterator it, is_empty empty, bool solid) : it_(it), empty_(empty) { + if (!solid) advance(); + } + // Same as above, assumes solid==true. + inline hollow_iterator_base(iterator it, is_empty empty) : it_(it), empty_(empty) {} + inline hollow_iterator_base(const self_type& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; } template hollow_iterator_base(const hollow_iterator_base& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; } @@ -58,13 +60,22 @@ struct hollow_iterator_base } }; -template auto make_hollow( +template +inline auto make_solid( container_type* v, const vector* p, iterator it) -> hollow_iterator_base> { return hollow_iterator_base>( it, is_empty(v, p)); } +template +inline auto make_hollow( + container_type* v, const vector* p, iterator it) -> + hollow_iterator_base> { + return hollow_iterator_base>( + it, is_empty(v, p), false); +} + } // namespace cxxmph #endif // __CXXMPH_HOLLOW_ITERATOR_H__ diff --git a/cxxmph/mph_map.h b/cxxmph/mph_map.h index 1d58e32..4d0276f 100644 --- a/cxxmph/mph_map.h +++ b/cxxmph/mph_map.h @@ -23,6 +23,7 @@ #include "mph_bits.h" #include "mph_index.h" +#include "hollow_iterator.h" namespace cxxmph { @@ -46,14 +47,15 @@ class mph_map { typedef HashFcn hasher; typedef EqualKey key_equal; - typedef typename std::vector::pointer pointer; - typedef typename std::vector::reference reference; - typedef typename std::vector::const_reference const_reference; - typedef typename std::vector::size_type size_type; - typedef typename std::vector::difference_type difference_type; + typedef typename vector::pointer pointer; + typedef typename vector::reference reference; + typedef typename vector::const_reference const_reference; + typedef typename vector::size_type size_type; + typedef typename vector::difference_type difference_type; - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; + typedef is_empty> is_empty_type; + typedef hollow_iterator_base::iterator, is_empty_type> iterator; + typedef hollow_iterator_base::const_iterator, is_empty_type> const_iterator; // For making macros simpler. typedef void void_type; @@ -80,7 +82,7 @@ class mph_map { data_type& operator[](const key_type &k); const data_type& operator[](const key_type &k) const; - size_type bucket_count() const { return index_.minimal_perfect_hash_size() + slack_.bucket_count(); } + size_type bucket_count() const { return index_.perfect_hash_size() + slack_.bucket_count(); } void rehash(size_type nbuckets /*ignored*/); protected: // mimicking STL implementation @@ -101,8 +103,8 @@ class mph_map { } void pack(); - std::vector values_; - std::vector present_; + vector values_; + vector present_; SimpleMPHIndex::hash_function> index_; // TODO(davi) optimize slack to use hash from index rather than calculate its own typedef unordered_map slack_type; @@ -151,13 +153,13 @@ MPH_MAP_METHOD_DECL(void_type, pack)() { make_iterator_first(begin()), make_iterator_first(end()), size_); if (!success) { exit(-1); } - std::vector new_values(index_.minimal_perfect_hash_size()); + vector new_values(index_.perfect_hash_size()); new_values.reserve(new_values.size() * 2); - std::vector new_present(index_.minimal_perfect_hash_size(), false); + vector new_present(index_.perfect_hash_size(), false); new_present.reserve(new_present.size() * 2); for (iterator it = begin(), it_end = end(); it != it_end; ++it) { - size_type id = index_.minimal_perfect_hash(it->first); - assert(id < index_.minimal_perfect_hash_size()); + size_type id = index_.perfect_hash(it->first); + assert(id < index_.perfect_hash_size()); assert(id < new_values.size()); new_values[id] = *it; new_present[id] = true; @@ -168,10 +170,10 @@ MPH_MAP_METHOD_DECL(void_type, pack)() { slack_type().swap(slack_); } -MPH_MAP_METHOD_DECL(iterator, begin)() { return values_.begin(); } -MPH_MAP_METHOD_DECL(iterator, end)() { return values_.end(); } -MPH_MAP_METHOD_DECL(const_iterator, begin)() const { return values_.begin(); } -MPH_MAP_METHOD_DECL(const_iterator, end)() const { return values_.end(); } +MPH_MAP_METHOD_DECL(iterator, begin)() { return make_hollow(&values_, &present_, values_.begin()); } +MPH_MAP_METHOD_DECL(iterator, end)() { return make_solid(&values_, &present_, values_.end()); } +MPH_MAP_METHOD_DECL(const_iterator, begin)() const { return make_hollow(&values_, &present_, values_.begin()); } +MPH_MAP_METHOD_DECL(const_iterator, end)() const { return make_solid(&values_, &present_, values_.end()); } MPH_MAP_METHOD_DECL(bool_type, empty)() const { return size_ == 0; } MPH_MAP_METHOD_DECL(size_type, size)() const { return size_; } @@ -184,7 +186,7 @@ MPH_MAP_METHOD_DECL(void_type, clear)() { } MPH_MAP_METHOD_DECL(void_type, erase)(iterator pos) { - present_[pos - begin] = false; + present_[pos.it_ - begin().it_] = false; *pos = value_type(); --size_; } @@ -196,16 +198,16 @@ MPH_MAP_METHOD_DECL(void_type, erase)(const key_type& k) { MPH_MAP_INLINE_METHOD_DECL(const_iterator, find)(const key_type& k) const { auto idx = index(k); - auto it = begin() + idx; - if (idx == -1 || it->first != k) return end(); - return it; + typename vector::const_iterator vit = values_.begin() + idx; + if (idx == -1 || vit->first != k) return end(); + return make_solid(&values_, &present_, vit);; } MPH_MAP_INLINE_METHOD_DECL(iterator, find)(const key_type& k) { auto idx = index(k); - auto it = begin() + idx; - if (idx == -1 || it->first != k) return end(); - return it; + typename vector::iterator vit = values_.begin() + idx; + if (idx == -1 || vit->first != k) return end(); + return make_solid(&values_, &present_, vit);; } MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const { @@ -213,10 +215,10 @@ MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const { auto sit = slack_.find(hasher128_.hash128(k, 0)); if (sit != slack_.end()) return sit->second; } - if (__builtin_expect(index_.minimal_perfect_hash_size(), 1)) { - auto minimal_perfect_hash = index_.minimal_perfect_hash(k); - if (__builtin_expect(present_[minimal_perfect_hash], true)) { - return minimal_perfect_hash; + if (__builtin_expect(index_.perfect_hash_size(), 1)) { + auto perfect_hash = index_.perfect_hash(k); + if (__builtin_expect(present_[perfect_hash], true)) { + return perfect_hash; } } return -1;