#ifndef CHILON_VECTOR_HASH_MAP_HPP
#define CHILON_VECTOR_HASH_MAP_HPP
#include <chilon/detail/vector_hash_map.hpp>
#include <chilon/key_value.hpp>
#include <chilon/meta/return.hpp>
#include <chilon/safe_iterator.hpp>
#include <chilon/append.hpp>
#include <unordered_map>
#include <vector>
namespace chilon {
template <class T, class H = std::hash<typename T::first_type>>
class vector_hash_map;
template <class K, class V, class C, class H>
class vector_hash_map< key_value<K, V, C>, H>
: public detail::vector_hash_map
{
typedef vector_hash_map<key_value<K, V, C>, H> self;
typedef detail::vector_hash_index<C> collision_t;
public:
// store key indexes
typedef std::unordered_map<K, int, H> unordered_map;
typedef typename unordered_map::value_type hash_value_type;
typedef std::vector<key_value<K, V, C>> vector;
typedef typename vector::value_type value_type;
typedef typename vector::reference reference;
typedef typename vector::iterator iterator;
typedef typename vector::const_iterator const_iterator;
typedef std::pair<iterator, bool> insert_type;
private:
vector vector_;
unordered_map hash_;
public:
// these return an iterator that is safe after insert
safe_iterator<vector const> safe_ordered_begin() const {
return safe_iterator<vector const>(vector_);
}
safe_iterator<vector> safe_ordered_begin() {
return safe_iterator<vector>(vector_);
}
const_iterator find(K const& k) const {
auto it = hash_.find(k);
if (it == hash_.end()) return vector_.end();
else return vector_.begin() + it->second;
}
iterator find(K const& k) {
auto it = hash_.find(k);
if (it == hash_.end()) return vector_.end();
else return vector_.begin() + it->second;
}
const_iterator begin() const { return vector_.begin(); }
const_iterator end() const { return vector_.end(); }
iterator begin() { return vector_.begin(); }
iterator end() { return vector_.end(); }
auto empty() const CHILON_RETURN(vector_.empty())
auto size() const CHILON_RETURN(vector_.size())
auto count(K const& k) const CHILON_RETURN(hash_.count(k))
insert_type insert(value_type const& value) {
auto mapIt = hash_.insert(hash_value_type(value.first, vector_.size()));
if (mapIt.second) {
vector_.push_back(value);
return insert_type(vector_.end() - 1, true);
}
else return
collision_t::insert(begin() + mapIt.first->second, value);
}
insert_type emplace(value_type&& value) {
auto mapIt = hash_.insert(hash_value_type(value.first, vector_.size()));
if (mapIt.second) {
vector_.push_back(std::move(value));
return insert_type(vector_.end() - 1, true);
}
else return
collision_t::insert(begin() + mapIt.first->second, std::move(value));
}
};
template <class U, class T, class H>
static inline void append(vector_hash_map<T, H>& t, U const& u) {
append_map(t, u);
}
template <class U, class T, class H>
static inline void append(vector_hash_map<T, H>& t, U&& u) {
append_map(t, u);
}
}
#endif