1
#ifndef CHILON_VECTOR_HASH_MAP_HPP
2
#define CHILON_VECTOR_HASH_MAP_HPP
3
4
#include <chilon/detail/vector_hash_map.hpp>
5
#include <chilon/key_value.hpp>
6
#include <chilon/meta/return.hpp>
7
#include <chilon/safe_iterator.hpp>
8
#include <chilon/append.hpp>
9
10
#include <unordered_map>
11
#include <vector>
12
13
namespace chilon {
14
15
template <class T, class H = std::hash<typename T::first_type>>
16
class vector_hash_map;
17
18
template <class K, class V, class C, class H>
19
class vector_hash_map< key_value<K, V, C>, H>
20
  : public detail::vector_hash_map
21
{
22
    typedef vector_hash_map<key_value<K, V, C>, H> self;
23
    typedef detail::vector_hash_index<C>           collision_t;
24
25
  public:
26
    // store key indexes
27
    typedef std::unordered_map<K, int, H>       unordered_map;
28
    typedef typename unordered_map::value_type  hash_value_type;
29
30
    typedef std::vector<key_value<K, V, C>>  vector;
31
    typedef typename vector::value_type      value_type;
32
    typedef typename vector::reference       reference;
33
    typedef typename vector::iterator        iterator;
34
    typedef typename vector::const_iterator  const_iterator;
35
    typedef std::pair<iterator, bool>        insert_type;
36
37
  private:
38
    vector         vector_;
39
    unordered_map  hash_;
40
41
  public:
42
    // these return an iterator that is safe after insert
43
    safe_iterator<vector const> safe_ordered_begin() const {
44
        return safe_iterator<vector const>(vector_);
45
    }
46
47
    safe_iterator<vector> safe_ordered_begin() {
48
        return safe_iterator<vector>(vector_);
49
    }
50
51
    const_iterator find(K const& k) const {
52
        auto it = hash_.find(k);
53
        if (it == hash_.end()) return vector_.end();
54
        else return vector_.begin() + it->second;
55
    }
56
57
    iterator find(K const& k) {
58
        auto it = hash_.find(k);
59
        if (it == hash_.end()) return vector_.end();
60
        else return vector_.begin() + it->second;
61
    }
62
63
    const_iterator begin() const { return vector_.begin(); }
64
    const_iterator end()   const { return vector_.end(); }
65
    iterator       begin()       { return vector_.begin(); }
66
    iterator       end()         { return vector_.end(); }
67
68
    auto empty() const CHILON_RETURN(vector_.empty())
69
    auto size()  const CHILON_RETURN(vector_.size())
70
71
    auto count(K const& k) const CHILON_RETURN(hash_.count(k))
72
73
    insert_type insert(value_type const& value) {
74
        auto mapIt = hash_.insert(hash_value_type(value.first, vector_.size()));
75
76
        if (mapIt.second) {
77
            vector_.push_back(value);
78
            return insert_type(vector_.end() - 1, true);
79
        }
80
        else return
81
            collision_t::insert(begin() + mapIt.first->second, value);
82
    }
83
84
    insert_type emplace(value_type&& value) {
85
        auto mapIt = hash_.insert(hash_value_type(value.first, vector_.size()));
86
87
        if (mapIt.second) {
88
            vector_.push_back(std::move(value));
89
            return insert_type(vector_.end() - 1, true);
90
        }
91
        else return
92
            collision_t::insert(begin() + mapIt.first->second, std::move(value));
93
    }
94
};
95
96
template <class U, class T, class H>
97
static inline void append(vector_hash_map<T, H>& t, U const& u) {
98
    append_map(t, u);
99
}
100
101
template <class U, class T, class H>
102
static inline void append(vector_hash_map<T, H>& t, U&& u) {
103
    append_map(t, u);
104
}
105
106
}
107
#endif