Hashtable.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  4. *
  5. * (c) ZeroTier, Inc.
  6. * https://www.zerotier.com/
  7. */
  8. #ifndef ZT_HASHTABLE_HPP
  9. #define ZT_HASHTABLE_HPP
  10. #include "Constants.hpp"
  11. #include <stdint.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <utility>
  15. #include <vector>
  16. namespace ZeroTier {
  17. /**
  18. * A minimal hash table implementation for the ZeroTier core
  19. */
  20. template <typename K, typename V> class Hashtable {
  21. private:
  22. struct _Bucket {
  23. _Bucket(const K& k, const V& v) : k(k), v(v)
  24. {
  25. }
  26. _Bucket(const K& k) : k(k), v()
  27. {
  28. }
  29. _Bucket(const _Bucket& b) : k(b.k), v(b.v)
  30. {
  31. }
  32. inline _Bucket& operator=(const _Bucket& b)
  33. {
  34. k = b.k;
  35. v = b.v;
  36. return *this;
  37. }
  38. K k;
  39. V v;
  40. _Bucket* next; // must be set manually for each _Bucket
  41. };
  42. public:
  43. /**
  44. * A simple forward iterator (different from STL)
  45. *
  46. * It's safe to erase the last key, but not others. Don't use set() since that
  47. * may rehash and invalidate the iterator. Note the erasing the key will destroy
  48. * the targets of the pointers returned by next().
  49. */
  50. class Iterator {
  51. public:
  52. /**
  53. * @param ht Hash table to iterate over
  54. */
  55. Iterator(Hashtable& ht) : _idx(0), _ht(&ht), _b(ht._t[0])
  56. {
  57. }
  58. /**
  59. * @param kptr Pointer to set to point to next key
  60. * @param vptr Pointer to set to point to next value
  61. * @return True if kptr and vptr are set, false if no more entries
  62. */
  63. inline bool next(K*& kptr, V*& vptr)
  64. {
  65. for (;;) {
  66. if (_b) {
  67. kptr = &(_b->k);
  68. vptr = &(_b->v);
  69. _b = _b->next;
  70. return true;
  71. }
  72. ++_idx;
  73. if (_idx >= _ht->_bc) {
  74. return false;
  75. }
  76. _b = _ht->_t[_idx];
  77. }
  78. }
  79. private:
  80. unsigned long _idx;
  81. Hashtable* _ht;
  82. _Bucket* _b;
  83. };
  84. // friend class Hashtable<K,V>::Iterator;
  85. /**
  86. * @param bc Initial capacity in buckets (default: 64, must be nonzero)
  87. */
  88. Hashtable(unsigned long bc = 64) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * bc))), _bc(bc), _s(0)
  89. {
  90. if (! _t) {
  91. throw ZT_EXCEPTION_OUT_OF_MEMORY;
  92. }
  93. for (unsigned long i = 0; i < bc; ++i) {
  94. _t[i] = (_Bucket*)0;
  95. }
  96. }
  97. Hashtable(const Hashtable<K, V>& ht) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * ht._bc))), _bc(ht._bc), _s(ht._s)
  98. {
  99. if (! _t) {
  100. throw ZT_EXCEPTION_OUT_OF_MEMORY;
  101. }
  102. for (unsigned long i = 0; i < _bc; ++i) {
  103. _t[i] = (_Bucket*)0;
  104. }
  105. for (unsigned long i = 0; i < _bc; ++i) {
  106. const _Bucket* b = ht._t[i];
  107. while (b) {
  108. _Bucket* nb = new _Bucket(*b);
  109. nb->next = _t[i];
  110. _t[i] = nb;
  111. b = b->next;
  112. }
  113. }
  114. }
  115. ~Hashtable()
  116. {
  117. this->clear();
  118. ::free(_t);
  119. }
  120. inline Hashtable& operator=(const Hashtable<K, V>& ht)
  121. {
  122. this->clear();
  123. if (ht._s) {
  124. for (unsigned long i = 0; i < ht._bc; ++i) {
  125. const _Bucket* b = ht._t[i];
  126. while (b) {
  127. this->set(b->k, b->v);
  128. b = b->next;
  129. }
  130. }
  131. }
  132. return *this;
  133. }
  134. /**
  135. * Erase all entries
  136. */
  137. inline void clear()
  138. {
  139. if (_s) {
  140. for (unsigned long i = 0; i < _bc; ++i) {
  141. _Bucket* b = _t[i];
  142. while (b) {
  143. _Bucket* const nb = b->next;
  144. delete b;
  145. b = nb;
  146. }
  147. _t[i] = (_Bucket*)0;
  148. }
  149. _s = 0;
  150. }
  151. }
  152. /**
  153. * @return Vector of all keys
  154. */
  155. inline typename std::vector<K> keys() const
  156. {
  157. typename std::vector<K> k;
  158. if (_s) {
  159. k.reserve(_s);
  160. for (unsigned long i = 0; i < _bc; ++i) {
  161. _Bucket* b = _t[i];
  162. while (b) {
  163. k.push_back(b->k);
  164. b = b->next;
  165. }
  166. }
  167. }
  168. return k;
  169. }
  170. /**
  171. * Append all keys (in unspecified order) to the supplied vector or list
  172. *
  173. * @param v Vector, list, or other compliant container
  174. * @tparam Type of V (generally inferred)
  175. */
  176. template <typename C> inline void appendKeys(C& v) const
  177. {
  178. if (_s) {
  179. for (unsigned long i = 0; i < _bc; ++i) {
  180. _Bucket* b = _t[i];
  181. while (b) {
  182. v.push_back(b->k);
  183. b = b->next;
  184. }
  185. }
  186. }
  187. }
  188. /**
  189. * @return Vector of all entries (pairs of K,V)
  190. */
  191. inline typename std::vector<std::pair<K, V> > entries() const
  192. {
  193. typename std::vector<std::pair<K, V> > k;
  194. if (_s) {
  195. k.reserve(_s);
  196. for (unsigned long i = 0; i < _bc; ++i) {
  197. _Bucket* b = _t[i];
  198. while (b) {
  199. k.push_back(std::pair<K, V>(b->k, b->v));
  200. b = b->next;
  201. }
  202. }
  203. }
  204. return k;
  205. }
  206. /**
  207. * @param k Key
  208. * @return Pointer to value or NULL if not found
  209. */
  210. inline V* get(const K& k)
  211. {
  212. _Bucket* b = _t[_hc(k) % _bc];
  213. while (b) {
  214. if (b->k == k) {
  215. return &(b->v);
  216. }
  217. b = b->next;
  218. }
  219. return (V*)0;
  220. }
  221. inline const V* get(const K& k) const
  222. {
  223. return const_cast<Hashtable*>(this)->get(k);
  224. }
  225. /**
  226. * @param k Key
  227. * @param v Value to fill with result
  228. * @return True if value was found and set (if false, v is not modified)
  229. */
  230. inline bool get(const K& k, V& v) const
  231. {
  232. _Bucket* b = _t[_hc(k) % _bc];
  233. while (b) {
  234. if (b->k == k) {
  235. v = b->v;
  236. return true;
  237. }
  238. b = b->next;
  239. }
  240. return false;
  241. }
  242. /**
  243. * @param k Key to check
  244. * @return True if key is present
  245. */
  246. inline bool contains(const K& k) const
  247. {
  248. _Bucket* b = _t[_hc(k) % _bc];
  249. while (b) {
  250. if (b->k == k) {
  251. return true;
  252. }
  253. b = b->next;
  254. }
  255. return false;
  256. }
  257. /**
  258. * @param k Key
  259. * @return True if value was present
  260. */
  261. inline bool erase(const K& k)
  262. {
  263. const unsigned long bidx = _hc(k) % _bc;
  264. _Bucket* lastb = (_Bucket*)0;
  265. _Bucket* b = _t[bidx];
  266. while (b) {
  267. if (b->k == k) {
  268. if (lastb) {
  269. lastb->next = b->next;
  270. }
  271. else {
  272. _t[bidx] = b->next;
  273. }
  274. delete b;
  275. --_s;
  276. return true;
  277. }
  278. lastb = b;
  279. b = b->next;
  280. }
  281. return false;
  282. }
  283. /**
  284. * @param k Key
  285. * @param v Value
  286. * @return Reference to value in table
  287. */
  288. inline V& set(const K& k, const V& v)
  289. {
  290. const unsigned long h = _hc(k);
  291. unsigned long bidx = h % _bc;
  292. _Bucket* b = _t[bidx];
  293. while (b) {
  294. if (b->k == k) {
  295. b->v = v;
  296. return b->v;
  297. }
  298. b = b->next;
  299. }
  300. if (_s >= _bc) {
  301. _grow();
  302. bidx = h % _bc;
  303. }
  304. b = new _Bucket(k, v);
  305. b->next = _t[bidx];
  306. _t[bidx] = b;
  307. ++_s;
  308. return b->v;
  309. }
  310. /**
  311. * @param k Key
  312. * @return Value, possibly newly created
  313. */
  314. inline V& operator[](const K& k)
  315. {
  316. const unsigned long h = _hc(k);
  317. unsigned long bidx = h % _bc;
  318. _Bucket* b = _t[bidx];
  319. while (b) {
  320. if (b->k == k) {
  321. return b->v;
  322. }
  323. b = b->next;
  324. }
  325. if (_s >= _bc) {
  326. _grow();
  327. bidx = h % _bc;
  328. }
  329. b = new _Bucket(k);
  330. b->next = _t[bidx];
  331. _t[bidx] = b;
  332. ++_s;
  333. return b->v;
  334. }
  335. /**
  336. * @return Number of entries
  337. */
  338. inline unsigned long size() const
  339. {
  340. return _s;
  341. }
  342. /**
  343. * @return True if table is empty
  344. */
  345. inline bool empty() const
  346. {
  347. return (_s == 0);
  348. }
  349. private:
  350. template <typename O> static inline unsigned long _hc(const O& obj)
  351. {
  352. return (unsigned long)obj.hashCode();
  353. }
  354. static inline unsigned long _hc(const uint64_t i)
  355. {
  356. return (unsigned long)(i ^ (i >> 32)); // good for network IDs and addresses
  357. }
  358. static inline unsigned long _hc(const uint32_t i)
  359. {
  360. return ((unsigned long)i * (unsigned long)0x9e3779b1);
  361. }
  362. static inline unsigned long _hc(const uint16_t i)
  363. {
  364. return ((unsigned long)i * (unsigned long)0x9e3779b1);
  365. }
  366. static inline unsigned long _hc(const int i)
  367. {
  368. return ((unsigned long)i * (unsigned long)0x9e3379b1);
  369. }
  370. inline void _grow()
  371. {
  372. const unsigned long nc = _bc * 2;
  373. _Bucket** nt = reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * nc));
  374. if (nt) {
  375. for (unsigned long i = 0; i < nc; ++i) {
  376. nt[i] = (_Bucket*)0;
  377. }
  378. for (unsigned long i = 0; i < _bc; ++i) {
  379. _Bucket* b = _t[i];
  380. while (b) {
  381. _Bucket* const nb = b->next;
  382. const unsigned long nidx = _hc(b->k) % nc;
  383. b->next = nt[nidx];
  384. nt[nidx] = b;
  385. b = nb;
  386. }
  387. }
  388. ::free(_t);
  389. _t = nt;
  390. _bc = nc;
  391. }
  392. }
  393. _Bucket** _t;
  394. unsigned long _bc;
  395. unsigned long _s;
  396. };
  397. } // namespace ZeroTier
  398. #endif