Some hashlib improvements

This commit is contained in:
Clifford Wolf 2015-02-09 20:11:51 +01:00
parent 68979d1395
commit adf4ecbc1f
1 changed files with 37 additions and 9 deletions

View File

@ -178,18 +178,19 @@ class dict
entry_t() { } entry_t() { }
entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { } entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { }
entry_t(std::pair<K, T> &&udata, int next) : udata(std::move(udata)), next(next) { }
}; };
std::vector<int> hashtable; std::vector<int> hashtable;
std::vector<entry_t> entries; std::vector<entry_t> entries;
OPS ops; OPS ops;
#if 0 #ifdef NDEBUG
static inline void do_assert(bool) { }
#else
static inline void do_assert(bool cond) { static inline void do_assert(bool cond) {
if (!cond) throw std::runtime_error("dict<> assert failed."); if (!cond) throw std::runtime_error("dict<> assert failed.");
} }
#else
static inline void do_assert(bool) { }
#endif #endif
int do_hash(const K &key) const int do_hash(const K &key) const
@ -220,6 +221,8 @@ class dict
return 0; return 0;
int k = hashtable[hash]; int k = hashtable[hash];
do_assert(0 <= k && k < int(entries.size()));
if (k == index) { if (k == index) {
hashtable[hash] = entries[index].next; hashtable[hash] = entries[index].next;
} else { } else {
@ -237,6 +240,8 @@ class dict
int back_hash = do_hash(entries[back_idx].udata.first); int back_hash = do_hash(entries[back_idx].udata.first);
k = hashtable[back_hash]; k = hashtable[back_hash];
do_assert(0 <= k && k < int(entries.size()));
if (k == back_idx) { if (k == back_idx) {
hashtable[back_hash] = index; hashtable[back_hash] = index;
} else { } else {
@ -278,6 +283,19 @@ class dict
return index; return index;
} }
int do_insert(const K &key, int &hash)
{
if (hashtable.empty()) {
entries.push_back(entry_t(std::pair<K, T>(key, T()), -1));
do_rehash();
hash = do_hash(key);
} else {
entries.push_back(entry_t(std::pair<K, T>(key, T()), hashtable[hash]));
hashtable[hash] = entries.size() - 1;
}
return entries.size() - 1;
}
int do_insert(const std::pair<K, T> &value, int &hash) int do_insert(const std::pair<K, T> &value, int &hash)
{ {
if (hashtable.empty()) { if (hashtable.empty()) {
@ -375,6 +393,16 @@ public:
insert(*first); insert(*first);
} }
std::pair<iterator, bool> insert(const K &key)
{
int hash = do_hash(key);
int i = do_lookup(key, hash);
if (i >= 0)
return std::pair<iterator, bool>(iterator(this, i), false);
i = do_insert(key, hash);
return std::pair<iterator, bool>(iterator(this, i), true);
}
std::pair<iterator, bool> insert(const std::pair<K, T> &value) std::pair<iterator, bool> insert(const std::pair<K, T> &value)
{ {
int hash = do_hash(value.first); int hash = do_hash(value.first);
@ -476,14 +504,14 @@ public:
return false; return false;
for (auto &it : entries) { for (auto &it : entries) {
auto oit = other.find(it.udata.first); auto oit = other.find(it.udata.first);
if (oit == other.end() || oit->second != it.udata.second) if (oit == other.end() || !(oit->second == it.udata.second))
return false; return false;
} }
return true; return true;
} }
bool operator!=(const dict &other) const { bool operator!=(const dict &other) const {
return !(*this == other); return !operator==(other);
} }
size_t size() const { return entries.size(); } size_t size() const { return entries.size(); }
@ -516,12 +544,12 @@ protected:
std::vector<entry_t> entries; std::vector<entry_t> entries;
OPS ops; OPS ops;
#if 0 #ifdef NDEBUG
static inline void do_assert(bool) { }
#else
static inline void do_assert(bool cond) { static inline void do_assert(bool cond) {
if (!cond) throw std::runtime_error("pool<> assert failed."); if (!cond) throw std::runtime_error("pool<> assert failed.");
} }
#else
static inline void do_assert(bool) { }
#endif #endif
int do_hash(const K &key) const int do_hash(const K &key) const
@ -791,7 +819,7 @@ public:
} }
bool operator!=(const pool &other) const { bool operator!=(const pool &other) const {
return !(*this == other); return !operator==(other);
} }
size_t size() const { return entries.size(); } size_t size() const { return entries.size(); }