forked from OctaForge/libostd
initial range interface for hashtables
parent
c9e3ebd773
commit
fa7bf1d3db
|
@ -11,9 +11,12 @@
|
||||||
#include "octa/types.h"
|
#include "octa/types.h"
|
||||||
#include "octa/utility.h"
|
#include "octa/utility.h"
|
||||||
#include "octa/memory.h"
|
#include "octa/memory.h"
|
||||||
|
#include "octa/range.h"
|
||||||
|
|
||||||
namespace octa {
|
namespace octa {
|
||||||
|
|
||||||
|
template<typename T> struct HashRange;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename B, /* contains methods specific to each ht type */
|
typename B, /* contains methods specific to each ht type */
|
||||||
|
@ -49,6 +52,9 @@ namespace detail {
|
||||||
using FAPair = octa::detail::CompressedPair<AllocPair, FuncPair>;
|
using FAPair = octa::detail::CompressedPair<AllocPair, FuncPair>;
|
||||||
using DataPair = octa::detail::CompressedPair<Chain **, FAPair>;
|
using DataPair = octa::detail::CompressedPair<Chain **, FAPair>;
|
||||||
|
|
||||||
|
using Range = octa::HashRange<E>;
|
||||||
|
using ConstRange = octa::HashRange<const E>;
|
||||||
|
|
||||||
DataPair p_data;
|
DataPair p_data;
|
||||||
|
|
||||||
float p_maxlf;
|
float p_maxlf;
|
||||||
|
@ -170,6 +176,16 @@ namespace detail {
|
||||||
octa::Size bucket_count() const { return p_size; }
|
octa::Size bucket_count() const { return p_size; }
|
||||||
octa::Size max_bucket_count() const { return Size(~0) / sizeof(Chain); }
|
octa::Size max_bucket_count() const { return Size(~0) / sizeof(Chain); }
|
||||||
|
|
||||||
|
Range each() {
|
||||||
|
return Range(p_data.first(), bucket_count());
|
||||||
|
}
|
||||||
|
ConstRange each() const {
|
||||||
|
return ConstRange(p_data.first(), bucket_count());
|
||||||
|
}
|
||||||
|
ConstRange ceach() const {
|
||||||
|
return ConstRange(p_data.first(), bucket_count());
|
||||||
|
}
|
||||||
|
|
||||||
void swap(Hashtable &h) {
|
void swap(Hashtable &h) {
|
||||||
octa::swap(p_size, h.p_size);
|
octa::swap(p_size, h.p_size);
|
||||||
octa::swap(p_len, h.p_len);
|
octa::swap(p_len, h.p_len);
|
||||||
|
@ -180,6 +196,66 @@ namespace detail {
|
||||||
};
|
};
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct HashRange: octa::InputRange<HashRange<T>, octa::ForwardRangeTag, T> {
|
||||||
|
private:
|
||||||
|
struct Chain {
|
||||||
|
T value;
|
||||||
|
Chain *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
Chain **p_chains;
|
||||||
|
Chain *p_node;
|
||||||
|
octa::Size p_num;
|
||||||
|
|
||||||
|
void advance() {
|
||||||
|
while (p_num > 0 && !p_chains[0]) {
|
||||||
|
--p_num;
|
||||||
|
++p_chains;
|
||||||
|
}
|
||||||
|
if (p_num > 0) {
|
||||||
|
p_node = p_chains[0];
|
||||||
|
--p_num;
|
||||||
|
++p_chains;
|
||||||
|
} else {
|
||||||
|
p_node = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
HashRange(): p_chains(), p_num(0) {}
|
||||||
|
HashRange(void *ch, octa::Size n): p_chains((Chain **)ch), p_num(n) {
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
HashRange(const HashRange &v): p_chains(v.p_chains), p_node(v.p_node),
|
||||||
|
p_num(v.p_num) {}
|
||||||
|
|
||||||
|
HashRange &operator=(const HashRange &v) {
|
||||||
|
p_chains = v.p_chains;
|
||||||
|
p_node = v.p_node;
|
||||||
|
p_num = v.p_num;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const { return !p_node && p_num <= 0; }
|
||||||
|
|
||||||
|
bool pop_front() {
|
||||||
|
if (empty()) return false;
|
||||||
|
if (p_node->next) {
|
||||||
|
p_node = p_node->next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p_node = nullptr;
|
||||||
|
advance();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equals_front(const HashRange &v) const {
|
||||||
|
return p_node == v.p_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &front() const { return p_node->value; }
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace octa */
|
} /* namespace octa */
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -17,7 +17,7 @@ namespace octa {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename K, typename T> struct MapBase {
|
template<typename K, typename T> struct MapBase {
|
||||||
typedef octa::Pair<const K, T> Element;
|
using Element = octa::Pair<const K, T>;
|
||||||
|
|
||||||
static inline const K &get_key(Element &e) {
|
static inline const K &get_key(Element &e) {
|
||||||
return e.first;
|
return e.first;
|
||||||
|
@ -56,6 +56,8 @@ public:
|
||||||
using Reference = Value &;
|
using Reference = Value &;
|
||||||
using Pointer = octa::AllocatorPointer<A>;
|
using Pointer = octa::AllocatorPointer<A>;
|
||||||
using ConstPointer = octa::AllocatorConstPointer<A>;
|
using ConstPointer = octa::AllocatorConstPointer<A>;
|
||||||
|
using Range = octa::HashRange<octa::Pair<const K, T>>;
|
||||||
|
using ConstRange = octa::HashRange<const octa::Pair<const K, T>>;
|
||||||
using Allocator = A;
|
using Allocator = A;
|
||||||
|
|
||||||
Map(octa::Size size = 1 << 10, const H &hf = H(), const C &eqf = C(),
|
Map(octa::Size size = 1 << 10, const H &hf = H(), const C &eqf = C(),
|
||||||
|
@ -103,6 +105,10 @@ public:
|
||||||
float max_load_factor() const { return p_table.max_load_factor(); }
|
float max_load_factor() const { return p_table.max_load_factor(); }
|
||||||
void max_load_factor(float lf) { p_table.max_load_factor(lf); }
|
void max_load_factor(float lf) { p_table.max_load_factor(lf); }
|
||||||
|
|
||||||
|
Range each() { return p_table.each(); }
|
||||||
|
ConstRange each() const { return p_table.each(); }
|
||||||
|
ConstRange ceach() const { return p_table.ceach(); }
|
||||||
|
|
||||||
void swap(Map &v) {
|
void swap(Map &v) {
|
||||||
octa::swap(p_table, v.p_table);
|
octa::swap(p_table, v.p_table);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue