Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

686 lines
15 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // hashtbl.h
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file describes the hash_table template class.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 09/23/1997 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #ifndef _HASHTBL_H_
  19. #define _HASHTBL_H_
  20. #include <algorithm>
  21. #include <functional>
  22. #include <string>
  23. #include <iasapi.h>
  24. #include <nocopy.h>
  25. //////////
  26. // TEMPLATE STRUCT identity
  27. //////////
  28. template<class _Ty>
  29. struct identity : std::unary_function<_Ty, _Ty>
  30. {
  31. _Ty operator()(const _Ty& _X) const
  32. {
  33. return _X;
  34. }
  35. };
  36. ///////////////////////////////////////////////////////////////////////////////
  37. //
  38. // CLASS
  39. //
  40. // Caster<Type1, Type2>
  41. //
  42. // DESCRIPTION
  43. //
  44. // Function class that casts references from Type1 to Type2. Used for
  45. // the hash table default parameters.
  46. //
  47. ///////////////////////////////////////////////////////////////////////////////
  48. template <class Type1, class Type2>
  49. class Caster : public std::unary_function<Type1, const Type2&>
  50. {
  51. public:
  52. Caster() {}
  53. const Type2& operator()(const Type1& X) const
  54. {
  55. return X;
  56. }
  57. };
  58. ///////////////////////////////////////////////////////////////////////////////
  59. //
  60. // CLASS
  61. //
  62. // ExtractFirst<T>
  63. //
  64. // DESCRIPTION
  65. //
  66. // Function class that extracts the first item from a pair. Useful for
  67. // setting up an STL style map where the first item in the pair is the key.
  68. //
  69. ///////////////////////////////////////////////////////////////////////////////
  70. template <class T>
  71. class ExtractFirst : public std::unary_function<T, const typename T::first_type&>
  72. {
  73. public:
  74. const typename T::first_type& operator()(const T& X) const
  75. {
  76. return X.first;
  77. }
  78. };
  79. //////////
  80. // I'm putting all the hash functions inside a namespace since hash
  81. // is such a common identifier.
  82. //////////
  83. namespace hash_util
  84. {
  85. ///////////////////////////////////////////////////////////////////////////////
  86. //
  87. // FUNCTION
  88. //
  89. // hash(const std::basic_string<E>& str)
  90. //
  91. // DESCRIPTION
  92. //
  93. // Function to compute a hash value for an STL string.
  94. //
  95. ///////////////////////////////////////////////////////////////////////////////
  96. template <class E>
  97. inline ULONG hash(const std::basic_string<E>& key)
  98. {
  99. return IASHashBytes((CONST BYTE*)key.data(), key.length() * sizeof(E));
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////
  102. //
  103. // FUNCTION
  104. //
  105. // hash(ULONG key)
  106. //
  107. // and
  108. //
  109. // hash(LONG key)
  110. //
  111. // DESCRIPTION
  112. //
  113. // Functions to compute a hash value for a 32-bit integer.
  114. // Uses Robert Jenkins' 32-bit mix function.
  115. //
  116. ///////////////////////////////////////////////////////////////////////////////
  117. inline ULONG hash(ULONG key)
  118. {
  119. key += (key << 12);
  120. key ^= (key >> 22);
  121. key += (key << 4);
  122. key ^= (key >> 9);
  123. key += (key << 10);
  124. key ^= (key >> 2);
  125. key += (key << 7);
  126. key ^= (key >> 12);
  127. return key;
  128. }
  129. inline ULONG hash(LONG key)
  130. {
  131. return hash((ULONG)key);
  132. }
  133. ///////////////////////////////////////////////////////////////////////////////
  134. //
  135. // FUNCTION
  136. //
  137. // hash(const T* key)
  138. //
  139. // DESCRIPTION
  140. //
  141. // Function to compute a hash value for a pointer.
  142. // Implements Knuth's multiplicative hash with a bit shift to account for
  143. // address alignment.
  144. //
  145. ///////////////////////////////////////////////////////////////////////////////
  146. template <class T>
  147. inline ULONG hash(const T* key)
  148. {
  149. return 2654435761 * ((unsigned long)key >> 3);
  150. }
  151. //////////
  152. // Overloadings of the above to hash strings.
  153. //////////
  154. template<>
  155. inline ULONG hash<char>(const char* key)
  156. {
  157. return IASHashBytes((CONST BYTE*)key,
  158. key ? strlen(key) : 0);
  159. }
  160. template<>
  161. inline ULONG hash<wchar_t>(const wchar_t* key)
  162. {
  163. return IASHashBytes((CONST BYTE*)key,
  164. key ? wcslen(key) * sizeof(wchar_t) : 0);
  165. }
  166. ///////////////////////////////////////////////////////////////////////////////
  167. //
  168. // CLASS
  169. //
  170. // Hasher
  171. //
  172. // DESCRIPTION
  173. //
  174. // Function class that uses the 'default' hash functions defined above.
  175. //
  176. ///////////////////////////////////////////////////////////////////////////////
  177. template <class _Ty>
  178. struct Hasher
  179. : public std::unary_function<_Ty, ULONG>
  180. {
  181. ULONG operator()(const _Ty& _X) const
  182. {
  183. return hash(_X);
  184. }
  185. };
  186. ///////////////////////////////////////////////////////////////////////////////
  187. //
  188. // CLASS
  189. //
  190. // ObjectHasher
  191. //
  192. // DESCRIPTION
  193. //
  194. // Function class that invokes a bound 'hash' method.
  195. //
  196. ///////////////////////////////////////////////////////////////////////////////
  197. template <class _Ty>
  198. struct ObjectHasher
  199. : public std::unary_function<_Ty, ULONG>
  200. {
  201. ULONG operator()(const _Ty& _X) const
  202. {
  203. return _X.hash();
  204. }
  205. };
  206. } // hash_util
  207. ///////////////////////////////////////////////////////////////////////////////
  208. //
  209. // CLASS
  210. //
  211. // hash_table<Key, Hasher, Value, Extractor, KeyMatch>
  212. //
  213. // DESCRIPTION
  214. //
  215. // Implements a general-purpose hash table. This can implement a map, a
  216. // set, or a hybrid depending on how Key, Value, and Extractor are
  217. // specified. Note that the default parameters for Value and Extractor
  218. // implement a set.
  219. //
  220. // NOTES
  221. //
  222. // Although I used similar nomenclature, this is not an STL collection.
  223. // In particular, the iterator does not conform to the STL guidelines.
  224. //
  225. // This class is not thread safe.
  226. //
  227. ///////////////////////////////////////////////////////////////////////////////
  228. template <
  229. class Key,
  230. class Hasher = hash_util::ObjectHasher<Key>,
  231. class Value = Key,
  232. class Extractor = Caster<Value, Key>,
  233. class KeyMatch = std::equal_to<Key>
  234. >
  235. class hash_table : NonCopyable
  236. {
  237. public:
  238. typedef hash_table<Key, Hasher, Value, Extractor, KeyMatch> table_type;
  239. typedef Key key_type;
  240. typedef Value value_type;
  241. protected:
  242. //////////
  243. // Singly-linked list node.
  244. //////////
  245. struct Node
  246. {
  247. Node* next; // Next node in the list (is NULL for last item).
  248. value_type value; // Value stored in this node.
  249. Node(const value_type& _V) : value(_V) {}
  250. // Erase the node immediately following this.
  251. void erase_next()
  252. {
  253. Node* node = next;
  254. next = next->next;
  255. delete node;
  256. }
  257. };
  258. //////////
  259. //
  260. // Singly-linked list. This is not intended to be a general-purpose class;
  261. // it is only intended to serve as a bucket in a hash table.
  262. //
  263. // Note: I have intentionally NOT deleted the list nodes in the destructor.
  264. // This is to support the hash_table grow() method.
  265. //
  266. //////////
  267. struct SList
  268. {
  269. Node* head; // The first node in the list (if any).
  270. SList() : head(NULL) {}
  271. // Delete all nodes in the list.
  272. void clear()
  273. {
  274. while (head) pop_front();
  275. }
  276. // Remove a node from the front of the list.
  277. void pop_front()
  278. {
  279. ((Node*)&head)->erase_next();
  280. }
  281. // Add a node to the front of the list.
  282. void push_front(Node* node)
  283. {
  284. node->next = head;
  285. head = node;
  286. }
  287. };
  288. public:
  289. //////////
  290. //
  291. // Hash table iterator.
  292. //
  293. // Note: This iterator is NOT safe. If the hash table is resized, the
  294. // iterator will no longer be valid.
  295. //
  296. //////////
  297. class const_iterator
  298. {
  299. public:
  300. const_iterator(SList* _first, SList* _end)
  301. : node(_first->head), bucket(_first), end(_end)
  302. {
  303. find_node();
  304. }
  305. const value_type& operator*() const
  306. {
  307. return node->value;
  308. }
  309. const value_type* operator->() const
  310. {
  311. return &**this;
  312. }
  313. void operator++()
  314. {
  315. node = node->next;
  316. find_node();
  317. }
  318. bool more() const
  319. {
  320. return bucket != end;
  321. }
  322. protected:
  323. friend table_type;
  324. Node* MyNode() const
  325. {
  326. return node;
  327. }
  328. // Advance until we're on a node or we've reached the end.
  329. void find_node()
  330. {
  331. while (!node && ++bucket != end)
  332. {
  333. node = bucket->head;
  334. }
  335. }
  336. Node* node; // The node under the iterator.
  337. SList* bucket; // The current bucket.
  338. SList* end; // The end of the bucket array.
  339. };
  340. typedef const_iterator iterator;
  341. //////////
  342. // Constructor.
  343. //////////
  344. hash_table(size_t size = 16,
  345. const Hasher& h = Hasher(),
  346. const Extractor& e = Extractor(),
  347. const KeyMatch& k = KeyMatch())
  348. : buckets(1),
  349. entries(0),
  350. hasher(h),
  351. extractor(e),
  352. key_match(k)
  353. {
  354. // Set buckets to smallest power of 2 greater than or equal to size.
  355. while (buckets < size) buckets <<= 1;
  356. table = new SList[buckets];
  357. // Calculate the hash mask.
  358. mask = buckets - 1;
  359. }
  360. //////////
  361. // Destructor.
  362. //////////
  363. ~hash_table()
  364. {
  365. clear();
  366. delete[] table;
  367. }
  368. //////////
  369. // Return an iterator positioned at the start of the hash table.
  370. //////////
  371. const_iterator begin() const
  372. {
  373. return const_iterator(table, table + buckets);
  374. }
  375. //////////
  376. // Clear all entries from the hash table.
  377. //////////
  378. void clear()
  379. {
  380. if (!empty())
  381. {
  382. for (size_t i=0; i<buckets; i++)
  383. {
  384. table[i].clear();
  385. }
  386. entries = 0;
  387. }
  388. }
  389. bool empty() const
  390. {
  391. return entries == 0;
  392. }
  393. //////////
  394. // Erase all entries matching the given key. Returns the number of entries
  395. // erased.
  396. //////////
  397. size_t erase(const key_type& key)
  398. {
  399. size_t erased = 0;
  400. Node* node = (Node*)&(get_bucket(key).head);
  401. while (node->next)
  402. {
  403. if (key_match(extractor(node->next->value), key))
  404. {
  405. node->erase_next();
  406. ++erased;
  407. }
  408. else
  409. {
  410. node = node->next;
  411. }
  412. }
  413. entries -= erased;
  414. return erased;
  415. }
  416. //////////
  417. // Erases the entry under the current iterator.
  418. //////////
  419. void erase(iterator& it)
  420. {
  421. // Only look in the bucket indicated by the iterator.
  422. Node* node = (Node*)&(it.bucket->head);
  423. while (node->next)
  424. {
  425. // Look for a pointer match -- not a key match.
  426. if (node->next == it.node)
  427. {
  428. // Advance the iterator to a valid node ...
  429. ++it;
  430. // ... then delete the current one.
  431. node->erase_next();
  432. break;
  433. }
  434. node = node->next;
  435. }
  436. }
  437. //////////
  438. // Search the hash table for the first entry matching key.
  439. //////////
  440. const value_type* find(const key_type& key) const
  441. {
  442. return search_bucket(get_bucket(key), key);
  443. }
  444. //////////
  445. // Insert a new entry into the hash table ONLY if the key is unique. Returns
  446. // true if successful, false otherwise.
  447. //////////
  448. bool insert(const value_type& value)
  449. {
  450. reserve_space();
  451. SList& b = get_bucket(extractor(value));
  452. if (search_bucket(b, extractor(value))) return false;
  453. b.push_front(new Node(value));
  454. add_entry();
  455. return true;
  456. }
  457. //////////
  458. // Insert a new entry into the hash table without checking uniqueness.
  459. //////////
  460. void multi_insert(const value_type& value)
  461. {
  462. reserve_space();
  463. get_bucket(extractor(value)).push_front(new Node(value));
  464. add_entry();
  465. }
  466. //////////
  467. // Inserts the entry if the key is unique. Otherwise, overwrites the first
  468. // entry found with a matching key. Returns true if an entry was
  469. // overwritten, false otherwise.
  470. //////////
  471. bool overwrite(const value_type& value)
  472. {
  473. reserve_space();
  474. SList& b = get_bucket(extractor(value));
  475. const value_type* existing = search_bucket(b, extractor(value));
  476. if (existing)
  477. {
  478. // We can get away with modifying the value in place, because we
  479. // know the hash value must be the same. I destroy the old value
  480. // and construct a new one inplace, so that Value doesn't need an
  481. // assignment operator.
  482. existing->~value_type();
  483. new ((void*)existing) value_type(value);
  484. return true;
  485. }
  486. b.push_front(new Node(value));
  487. add_entry();
  488. return false;
  489. }
  490. //////////
  491. // Return the number of entries in the hash table.
  492. //////////
  493. size_t size() const
  494. {
  495. return entries;
  496. }
  497. protected:
  498. //////////
  499. // Increment the entries count.
  500. //////////
  501. void add_entry()
  502. {
  503. ++entries;
  504. }
  505. //////////
  506. // Grow the hash table as needed. We have to separate reserve_space and
  507. // add_entry to make the collection exception safe (since there will be
  508. // an intervening new).
  509. //////////
  510. void reserve_space()
  511. {
  512. if (entries >= buckets) grow();
  513. }
  514. //////////
  515. // Return the bucket for a given key.
  516. //////////
  517. SList& get_bucket(const key_type& key) const
  518. {
  519. return table[hasher(key) & mask];
  520. }
  521. //////////
  522. // Increase the capacity of the hash table.
  523. //////////
  524. void grow()
  525. {
  526. // We must allocate the memory first to be exception-safe.
  527. SList* newtbl = new SList[buckets << 1];
  528. // Initialize an iterator for the old table ...
  529. const_iterator i = begin();
  530. // ... then swap in the new table.
  531. std::swap(table, newtbl);
  532. buckets <<= 1;
  533. mask = buckets - 1;
  534. // Iterate through the old and insert the entries into the new.
  535. while (i.more())
  536. {
  537. Node* node = i.MyNode();
  538. // Increment the iterator ...
  539. ++i;
  540. // ... before we clobber the node's next pointer.
  541. get_bucket(extractor(node->value)).push_front(node);
  542. }
  543. // Delete the old table.
  544. delete[] newtbl;
  545. }
  546. //////////
  547. // Search a bucket for a specified key.
  548. //////////
  549. const value_type* search_bucket(SList& bucket, const key_type& key) const
  550. {
  551. Node* node = bucket.head;
  552. while (node)
  553. {
  554. if (key_match(extractor(node->value), key))
  555. {
  556. return &node->value;
  557. }
  558. node = node->next;
  559. }
  560. return NULL;
  561. }
  562. size_t buckets; // The number of buckets in the hash table.
  563. size_t mask; // Bit mask used for reducing hash values.
  564. size_t entries; // The number of entries in the hash table.
  565. SList* table; // An array of buckets.
  566. Hasher hasher; // Used to hash keys.
  567. Extractor extractor; // Used to convert values to keys.
  568. KeyMatch key_match; // Used to test keys for equality.
  569. };
  570. #endif // _HASHTBL_H_