/* */ #ifndef __TMPL_PAIRLIST__ #define __TMPL_PAIRLIST__ #include "data/array_list.h" #include "platform_config.h" // template class ntPairList; /* @short Pair item. @author Emmanuel Julien (ejulien@gsworks.fr) */ template class ntPairItem : public nArrayEntry { protected: int hash; public: TYPE *a, *b; ///< Object pair. void *pair_data; ///< Pair associated data block. /// Compute pair hash value. static int ComputeHash(TYPE *_a, TYPE *_b) { int hash = (((uintptr_t)_a) & 0xf0f0f0f0) | (((uintptr_t)_b) & 0x0f0f0f0f); hash = (hash + 0x7ed55d16) + (hash << 12); hash = (hash ^ 0xc761c23c) ^ (hash >> 19); hash = (hash + 0x165667b1) + (hash << 5); hash = (hash + 0xd3a2646c) ^ (hash << 9); hash = (hash + 0xfd7046c5) + (hash << 3); hash = (hash ^ 0xb55a4f09) ^ (hash >> 16); return hash; } /// Get pair hash. int Hash() const { return hash; } ntPairItem(TYPE *_a, TYPE *_b) { a = _a; b = _b; hash = ComputeHash(a, b); } }; /* */ struct ntPairListPool { uint bucket, entry; void Reset() { bucket = entry = 0; } ntPairListPool() { Reset(); } }; /* @short Pair list. @author Emmanuel Julien (ejulien@gsworks.fr) */ template class ntPairList { #define PairListBucketCount 64 #define OrderPairItems(_A_, _B_) { if (_A_ > _B_) { TYPE *t = _A_; _A_ = _B_; _B_ = t; } } protected: uint count; nArrayList bucket[PairListBucketCount]; public: /// Get item count in list. uint GetCount() const { return count; } /// Pool list. PAIR *Pool(ntPairListPool &pool) const { while (pool.bucket < PairListBucketCount) { if (pool.entry < bucket[pool.bucket].GetCount()) break; pool.entry = 0; pool.bucket++; } if (pool.bucket == PairListBucketCount) return 0; return (PAIR *)bucket[pool.bucket][pool.entry++]; } /// Add a pair. PAIR *Add(TYPE *a, TYPE *b) { OrderPairItems(a, b); PAIR *pair = new PAIR(a, b); if (pair && !bucket[pair->Hash() & (PairListBucketCount - 1)].Add(pair)) _safe_delete(pair); else count++; return pair; } /// Find a pair. PAIR *Find(TYPE *a, TYPE *b) { OrderPairItems(a, b); int hash = PAIR::ComputeHash(a, b); nArrayList &h_bucket = bucket[hash & (PairListBucketCount - 1)]; for (uint n = 0; n < h_bucket.GetCount(); ++n) { PAIR *pair = (PAIR *)h_bucket[n]; if ((pair->a == a) && (pair->b == b)) return pair; } return 0; } /// Remove pair. bool Remove(PAIR *pair) { if (bucket[pair->Hash() & (PairListBucketCount - 1)].Delete(pair)) { count--; return false; } return true; } /// Delete all pair. void DeleteAll(bool freedata = true) { for (int n = 0; n < PairListBucketCount; ++n) bucket[n].DeleteAll(freedata); count = 0; } ntPairList() { count = 0; } }; #endif // __TMPL_PAIRLIST__