1
#ifndef CHILON_VARIANT_VECTOR_HASH_MAP_HPP
2
#define CHILON_VARIANT_VECTOR_HASH_MAP_HPP
3
4
#include <chilon/detail/variant_vector_hash_map.hpp>
5
#include <chilon/detail/vector_hash_index.hpp>
6
#include <chilon/meta/return.hpp>
7
#include <chilon/meta/map.hpp>
8
#include <chilon/meta/remove.hpp>
9
#include <chilon/meta/switch_template.hpp>
10
#include <chilon/variant.hpp>
11
#include <chilon/key_value.hpp>
12
#include <chilon/tuple_set.hpp>
13
#include <chilon/safe_iterator.hpp>
14
#include <chilon/append.hpp>
15
16
#include <unordered_map>
17
#include <vector>
18
19
namespace chilon {
20
21
template <class T, template <class> class H = std::hash>
22
class variant_vector_hash_map : public detail::variant_vector_hash_map {
23
    typedef variant_vector_hash_map<T, H> self;
24
25
    template <class K>
26
    struct index {
27
        std::unordered_map<K, int, H<K>> hash_;
28
    };
29
30
    template <class U>
31
    struct key_type : meta::type_<void> {};
32
33
    template <class K, class V, class A>
34
    struct key_type< key_value<K, V, A> > : meta::type_<index<K>> {};
35
36
    typedef typename meta::switch_template<tuple_set, T>::type  tmp_tpl_set;
37
38
    typedef typename meta::remove<
39
        meta::same<void>::type,
40
        typename meta::map<key_type, tmp_tpl_set>::type>::type   indexes_t;
41
42
  public:
43
    typedef std::vector<T>                   vector;
44
    typedef typename vector::value_type      value_type;
45
    typedef typename vector::reference       reference;
46
    typedef typename vector::iterator        iterator;
47
    typedef typename vector::const_iterator  const_iterator;
48
    typedef std::pair<iterator, bool>        insert_type;
49
50
  private:
51
    vector     vector_;
52
    indexes_t  indexes_;
53
54
  public:
55
    // these return an iterator that is safe after insert
56
    safe_iterator<vector const> safe_ordered_begin() const {
57
        return safe_iterator<vector const>(vector_);
58
    }
59
60
    safe_iterator<vector> safe_ordered_begin() {
61
        return safe_iterator<vector>(vector_);
62
    }
63
64
    template <class K>
65
    const_iterator find(K const& k) const {
66
#if 0
67
        auto it = hash_.find(k);
68
        if (it == hash_.end()) return vector_.end();
69
        else return vector_.begin() + it->second;
70
#endif
71
        return vector_.end();
72
    }
73
74
    template <class K>
75
    iterator find(K const& k) {
76
#if 0
77
        auto it = hash_.find(k);
78
        if (it == hash_.end()) return vector_.end();
79
        else return vector_.begin() + it->second;
80
#endif
81
        return vector_.end();
82
    }
83
84
    const_iterator begin() const { return vector_.begin(); }
85
    const_iterator end()   const { return vector_.end(); }
86
    iterator       begin()       { return vector_.begin(); }
87
    iterator       end()         { return vector_.end(); }
88
89
    auto empty() const CHILON_RETURN(vector_.empty())
90
    auto size()  const CHILON_RETURN(vector_.size())
91
92
    // auto count(K const& k) const CHILON_RETURN(hash_.count(k))
93
94
    insert_type emplace(value_type&& value) {
95
        return variant_apply(value, emplacer(*this, value));
96
    }
97
98
    insert_type insert(value_type const& value) {
99
        return variant_apply(value, inserter(*this));
100
    }
101
102
  private:
103
    struct emplacer {
104
        template <class U>
105
        insert_type operator()(U& v) const {
106
            dest_.vector_.push_back(std::move(src_));
107
            return insert_type(dest_.vector_.end() - 1, true);
108
        }
109
110
        template <class K, class V, class A>
111
        insert_type operator()(key_value<K, V, A>& v) const {
112
            auto& idx = dest_.indexes_.template at< index<K> >();
113
            auto mapIt = idx.hash_.insert(
114
                std::make_pair(v.first, dest_.size()));
115
116
            if (mapIt.second) {
117
                dest_.vector_.push_back(std::move(src_));
118
                return insert_type(dest_.end() - 1, true);
119
            }
120
            else {
121
                typedef key_value<K, V, A> key_value_t;
122
                return detail::vector_hash_index<A>::template insert<key_value_t>(
123
                    dest_.begin() + mapIt.first->second, std::move(v));
124
            }
125
        }
126
127
        emplacer(self& dest, value_type& src) : dest_(dest), src_(src) {}
128
      protected:
129
        self&       dest_;
130
        value_type& src_;
131
    };
132
133
    struct inserter {
134
        template <class U>
135
        insert_type operator()(U const& v) const {
136
            dest_.vector_.push_back(T(v));
137
            return insert_type(dest_.vector_.end() - 1, true);
138
        }
139
140
        template <class K, class V, class A>
141
        insert_type operator()(key_value<K, V, A> const& v) const {
142
            auto& idx = dest_.indexes_.template at< index<K> >();
143
            auto mapIt = idx.hash_.insert(
144
                std::make_pair(v.first, dest_.size()));
145
146
            if (mapIt.second) {
147
                dest_.vector_.push_back(T(v));
148
                return insert_type(dest_.end() - 1, true);
149
            }
150
            else {
151
                typedef key_value<K, V, A> key_value_t;
152
                return detail::vector_hash_index<A>::template insert<key_value_t>(
153
                    dest_.begin() + mapIt.first->second, v);
154
            }
155
        }
156
157
        inserter(self& dest) : dest_(dest) {}
158
      protected:
159
        self&  dest_;
160
    };
161
};
162
163
template <class U, class T, template <class> class H>
164
static inline void append(variant_vector_hash_map<T, H>& t, U const& u) {
165
    append_map(t, u);
166
}
167
168
template <class U, class T, template <class> class H>
169
static inline void append(variant_vector_hash_map<T, H>& t, U&& u) {
170
    append_map(t, u);
171
}
172
173
}
174
#endif