diff --git a/qse/include/qse/cmn/HashList.hpp b/qse/include/qse/cmn/HashList.hpp index c55282bd..6e5d406a 100644 --- a/qse/include/qse/cmn/HashList.hpp +++ b/qse/include/qse/cmn/HashList.hpp @@ -289,6 +289,32 @@ protected: return QSE_NULL; } + template + Node* heterofind_node (const MT& datum, qse_size_t hc) const + { + MCOMPARATOR is_equal; + + qse_size_t head, tail; + Node* np; + + head = hc << 1; tail = head + 1; + + np = this->nodes[head]; + if (np) + { + do + { + T& t = np->value; + if (is_equal(datum, t)) return np; + if (np == this->nodes[tail]) break; + np = np->getNextNode (); + } + while (1); + } + + return QSE_NULL; + } + Node* insert_value (const T& datum, bool overwrite = true) { qse_size_t hc, head, tail; @@ -330,7 +356,7 @@ protected: } else { - this->nodes[head] = datum_list->insert (this->nodes[head], datum); + this->nodes[head] = this->datum_list->insert (this->nodes[head], datum); } return this->nodes[head]; @@ -361,6 +387,22 @@ public: return &b->value; } + template + Node* heterofindNode (const MT& datum) + { + MHASHER hash; + return this->heterofind_node (datum, hash(datum) % this->node_capacity); + } + + template + Node* heterofindValue(const MT& datum) + { + MHASHER hash; + Node* b = this->heterofind_node (datum, hash(datum) % this->node_capacity); + if (!b) return QSE_NULL; + return &b->value; + } + /// The search() function returns the pointer to the existing node /// containing the equal value to \a datum. If no node is found, it /// return #QSE_NULL. @@ -437,6 +479,40 @@ public: return -1; } + template + int heteroremove (const MT& datum) + { + MHASHER hash; + qse_size_t hc = hash(datum) % this->node_capacity; + + Node* np = this->heterofind_node (datum, hc); + if (np) + { + qse_size_t head, tail; + + head = hc << 1; tail = head + 1; + + if (this->nodes[head] == this->nodes[tail]) + { + QSE_ASSERT (np == this->nodes[head]); + this->nodes[head] = this->nodes[tail] = QSE_NULL; + } + else if (np == this->nodes[head]) + { + this->nodes[head] = np->getNextNode(); + } + else if (np == this->nodes[tail]) + { + this->nodes[tail] = np->getPrevNode(); + } + + this->datum_list->remove (np); + return 0; + } + + return -1; + } + void clear () { for (qse_size_t i = 0; i < (this->node_capacity << 1); i++) diff --git a/qse/include/qse/cmn/HashTable.hpp b/qse/include/qse/cmn/HashTable.hpp index a73b5473..b70acd61 100644 --- a/qse/include/qse/cmn/HashTable.hpp +++ b/qse/include/qse/cmn/HashTable.hpp @@ -83,7 +83,6 @@ public: typedef HashTableComparator DefaultComparator; typedef HashTableResizer DefaultResizer; - struct PairHasher { qse_size_t operator() (const Pair& p) @@ -102,6 +101,15 @@ public: } }; + struct PairHeteroComparator + { + qse_size_t operator() (const K& p1, const Pair& p2) + { + COMPARATOR is_equal; + return is_equal (p1, p2.key); + } + }; + typedef HashList PairList; typedef typename PairList::Node PairNode; @@ -114,7 +122,11 @@ public: MIN_LOAD_FACTOR = PairList::MIN_LOAD_FACTOR }; - HashTable (Mmgr* mmgr, qse_size_t capacity = DEFAULT_CAPACITY, qse_size_t load_factor = DEFAULT_LOAD_FACTOR, qse_size_t mpb_size = 0): Mmged(mmgr), pair_list (mmgr, capacity, load_factor, mpb_size) + HashTable (Mmgr* mmgr = QSE_NULL, + qse_size_t capacity = DEFAULT_CAPACITY, + qse_size_t load_factor = DEFAULT_LOAD_FACTOR, + qse_size_t mpb_size = 0): + Mmged(mmgr), pair_list (mmgr, capacity, load_factor, mpb_size) { } @@ -151,19 +163,18 @@ public: Pair* search (const K& key) { - // TODO: find with custom... - PairNode* node = this->pair_list.update (Pair(key)); + //PairNode* node = this->pair_list.update (Pair(key)); + PairNode* node = this->pair_list.template heterofindNode (key); if (!node) return QSE_NULL; return &node->value; } int remove (const K& key) { - // TODO: use removeWithCustom.... - return this->pair_list.remove (Pair(key)); + //return this->pair_list.remove (Pair(key)); + return this->pair_list.template heteroremove (key); } - void clear () { // TODO: accept new capacity.