2015-06-14 01:46:46 +00:00
|
|
|
/* Associative array for OctaSTD. Implemented as a hash table.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_MAP_H
|
|
|
|
#define OCTA_MAP_H
|
|
|
|
|
|
|
|
#include "octa/types.h"
|
|
|
|
#include "octa/utility.h"
|
|
|
|
#include "octa/memory.h"
|
|
|
|
#include "octa/functional.h"
|
|
|
|
|
|
|
|
#include "octa/internal/hashtable.h"
|
|
|
|
|
|
|
|
namespace octa {
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename K, typename T> struct MapBase {
|
2015-06-14 03:32:01 +00:00
|
|
|
using Element = octa::Pair<const K, T>;
|
2015-06-14 01:46:46 +00:00
|
|
|
|
|
|
|
static inline const K &get_key(Element &e) {
|
|
|
|
return e.first;
|
|
|
|
}
|
|
|
|
static inline T &get_data(Element &e) {
|
|
|
|
return e.second;
|
|
|
|
}
|
|
|
|
template<typename U>
|
2015-06-14 02:04:03 +00:00
|
|
|
static inline void set_key(Element &e, U &&key) {
|
2015-06-14 01:46:46 +00:00
|
|
|
e.first.~K();
|
2015-06-14 02:04:03 +00:00
|
|
|
new ((K *)&e.first) K(octa::forward<U>(key));
|
2015-06-14 01:46:46 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<
|
|
|
|
typename K, typename T,
|
|
|
|
typename H = octa::ToHash<K>,
|
|
|
|
typename C = octa::Equal<K>,
|
|
|
|
typename A = octa::Allocator<octa::Pair<const K, T>>
|
|
|
|
> struct Map {
|
|
|
|
private:
|
|
|
|
using Base = octa::detail::Hashtable<
|
|
|
|
octa::detail::MapBase<K, T>, octa::Pair<const K, T>, K, T, H, C, A
|
|
|
|
>;
|
|
|
|
Base p_table;
|
|
|
|
public:
|
|
|
|
|
|
|
|
using Key = K;
|
|
|
|
using Mapped = T;
|
|
|
|
using Size = octa::Size;
|
|
|
|
using Difference = octa::Ptrdiff;
|
|
|
|
using Hasher = H;
|
|
|
|
using KeyEqual = C;
|
|
|
|
using Value = octa::Pair<const K, T>;
|
|
|
|
using Reference = Value &;
|
|
|
|
using Pointer = octa::AllocatorPointer<A>;
|
|
|
|
using ConstPointer = octa::AllocatorConstPointer<A>;
|
2015-06-14 03:32:01 +00:00
|
|
|
using Range = octa::HashRange<octa::Pair<const K, T>>;
|
|
|
|
using ConstRange = octa::HashRange<const octa::Pair<const K, T>>;
|
2015-06-14 01:46:46 +00:00
|
|
|
using Allocator = A;
|
|
|
|
|
|
|
|
Map(octa::Size size = 1 << 10, const H &hf = H(), const C &eqf = C(),
|
|
|
|
const A &alloc = A()): p_table(size, hf, eqf, alloc) {}
|
|
|
|
|
2015-06-14 02:38:08 +00:00
|
|
|
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(); }
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-06-14 02:38:08 +00:00
|
|
|
octa::Size bucket_count() const { return p_table.bucket_count(); }
|
|
|
|
octa::Size max_bucket_count() const { return p_table.max_bucket_count(); }
|
2015-06-14 01:46:46 +00:00
|
|
|
|
|
|
|
void clear() { p_table.clear(); }
|
|
|
|
|
|
|
|
A get_allocator() const {
|
|
|
|
return p_table.get_challoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
T &at(const K &key) {
|
|
|
|
return *p_table.access(key);
|
|
|
|
}
|
|
|
|
const T &at(const K &key) const {
|
|
|
|
return *p_table.access(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
T &operator[](const K &key) {
|
|
|
|
octa::Size h;
|
|
|
|
T *v = p_table.access_base(key, h);
|
|
|
|
if (v) return *v;
|
|
|
|
return p_table.insert(h, key);
|
|
|
|
}
|
2015-06-14 02:04:03 +00:00
|
|
|
T &operator[](K &&key) {
|
|
|
|
octa::Size h;
|
|
|
|
T *v = p_table.access_base(key, h);
|
|
|
|
if (v) return *v;
|
|
|
|
return p_table.insert(h, octa::move(key));
|
|
|
|
}
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-06-14 02:38:08 +00:00
|
|
|
octa::Size erase(const K &key) {
|
|
|
|
if (p_table.remove(key)) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float load_factor() const { return p_table.load_factor(); }
|
2015-06-14 02:43:11 +00:00
|
|
|
float max_load_factor() const { return p_table.max_load_factor(); }
|
|
|
|
void max_load_factor(float lf) { p_table.max_load_factor(lf); }
|
2015-06-14 02:38:08 +00:00
|
|
|
|
2015-06-14 03:32:01 +00:00
|
|
|
Range each() { return p_table.each(); }
|
|
|
|
ConstRange each() const { return p_table.each(); }
|
|
|
|
ConstRange ceach() const { return p_table.ceach(); }
|
|
|
|
|
2015-06-14 01:46:46 +00:00
|
|
|
void swap(Map &v) {
|
|
|
|
octa::swap(p_table, v.p_table);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
#endif
|