forked from OctaForge/libostd
cleaner hash range handling
parent
c287d7e98a
commit
e2d8283eb7
|
@ -15,7 +15,70 @@
|
||||||
|
|
||||||
namespace octa {
|
namespace octa {
|
||||||
|
|
||||||
template<typename T> struct HashRange;
|
namespace detail {
|
||||||
|
template<typename T>
|
||||||
|
struct HashChain {
|
||||||
|
T value;
|
||||||
|
HashChain<T> *next;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct HashRange: octa::InputRange<HashRange<T>, octa::ForwardRangeTag, T> {
|
||||||
|
private:
|
||||||
|
using Chain = octa::detail::HashChain<T>;
|
||||||
|
|
||||||
|
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(Chain **ch, octa::Size n): p_chains(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 detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
|
@ -29,10 +92,8 @@ namespace detail {
|
||||||
> struct Hashtable {
|
> struct Hashtable {
|
||||||
static constexpr octa::Size CHUNKSIZE = 64;
|
static constexpr octa::Size CHUNKSIZE = 64;
|
||||||
|
|
||||||
struct Chain {
|
using Chain = octa::detail::HashChain<E>;
|
||||||
E value;
|
|
||||||
Chain *next;
|
|
||||||
};
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
Chain chains[CHUNKSIZE];
|
Chain chains[CHUNKSIZE];
|
||||||
Chunk *next;
|
Chunk *next;
|
||||||
|
@ -196,66 +257,6 @@ 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
|
|
@ -344,7 +344,7 @@ static inline bool operator!=(const char *lhs, const String &rhs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename F>
|
template<typename T, typename F>
|
||||||
String concat(const T v, const String &sep, F func) {
|
String concat(const T &v, const String &sep, F func) {
|
||||||
String ret;
|
String ret;
|
||||||
auto range = octa::each(v);
|
auto range = octa::each(v);
|
||||||
if (range.empty()) return octa::move(ret);
|
if (range.empty()) return octa::move(ret);
|
||||||
|
|
Loading…
Reference in New Issue