From da9a720c3fc2d69e35f393fbb96a716599ac0a6f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 3 Sep 2015 17:33:06 -0700 Subject: Hash table bug fix, and add copy constructor and assignment operator for principle of least surprise. --- node/Hashtable.hpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 6 deletions(-) (limited to 'node') diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index c997d54f..5076751d 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -29,6 +29,7 @@ #include #include +#include namespace ZeroTier { @@ -47,9 +48,11 @@ private: { _Bucket(const K &k,const V &v) : k(k),v(v) {} _Bucket(const K &k) : k(k),v() {} + _Bucket(const _Bucket &b) : k(b.k),v(b.v) {} + inline _Bucket &operator=(const _Bucket &b) { k = b.k; v = b.v; return *this; } K k; V v; - _Bucket *next; + _Bucket *next; // must be set manually for each _Bucket }; public: @@ -115,12 +118,47 @@ public: _t[i] = (_Bucket *)0; } + Hashtable(const Hashtable &ht) : + _t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))), + _bc(ht._bc), + _s(ht._s) + { + if (!_t) + throw std::bad_alloc(); + for(unsigned long i=0;i<_bc;++i) + _t[i] = (_Bucket *)0; + for(unsigned long i=0;i<_bc;++i) { + const _Bucket *b = ht._t[i]; + while (b) { + _Bucket *nb = new _Bucket(*b); + nb->next = _t[i]; + _t[i] = nb; + b = b->next; + } + } + } + ~Hashtable() { - clear(); + this->clear(); ::free(_t); } + inline Hashtable &operator=(const Hashtable &ht) + { + this->clear(); + if (ht._s) { + for(unsigned long i=0;iset(b->k,b->v); + b = b->next; + } + } + } + return *this; + } + /** * Erase all entries */ @@ -140,6 +178,24 @@ public: } } + /** + * @return Vector of all keys + */ + inline typename std::vector keys() + { + typename std::vector k; + if (_s) { + for(unsigned long i=0;i<_bc;++i) { + _Bucket *b = _t[i]; + while (b) { + k.push_back(b->k); + b = b->next; + } + } + } + return k; + } + /** * @param k Key * @return Pointer to value or NULL if not found @@ -187,7 +243,8 @@ public: */ inline V &set(const K &k,const V &v) { - const unsigned long bidx = _hc(k) % _bc; + const unsigned long h = _hc(k); + unsigned long bidx = h % _bc; _Bucket *b = _t[bidx]; while (b) { @@ -198,8 +255,10 @@ public: b = b->next; } - if (_s >= _bc) + if (_s >= _bc) { _grow(); + bidx = h % _bc; + } b = new _Bucket(k,v); b->next = _t[bidx]; @@ -215,7 +274,8 @@ public: */ inline V &operator[](const K &k) { - const unsigned long bidx = _hc(k) % _bc; + const unsigned long h = _hc(k); + unsigned long bidx = h % _bc; _Bucket *b = _t[bidx]; while (b) { @@ -224,8 +284,10 @@ public: b = b->next; } - if (_s >= _bc) + if (_s >= _bc) { _grow(); + bidx = h % _bc; + } b = new _Bucket(k); b->next = _t[bidx]; -- cgit v1.2.3