Source code of Windows XP (NT5)
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.

540 lines
15 KiB

  1. // xhash internal header
  2. #pragma once
  3. #ifndef _XHASH_
  4. #define _XHASH_
  5. #include <functional>
  6. #include <list>
  7. #include <vector>
  8. #pragma pack(push,8)
  9. #pragma warning(push,3)
  10. #pragma warning(disable: 4127)
  11. _STD_BEGIN
  12. // TEMPLATE CLASS hash_compare
  13. template<class _Kty,
  14. class _Pr = less<_Kty> >
  15. class hash_compare
  16. { // traits class for hash containers
  17. public:
  18. enum
  19. { // parameters for hash table
  20. bucket_size = 4, // 0 < bucket_size
  21. min_buckets = 8}; // min_buckets = 2 ^^ N, 0 < N
  22. hash_compare()
  23. : comp()
  24. { // construct with default comparator
  25. }
  26. hash_compare(_Pr _Pred)
  27. : comp(_Pred)
  28. { // construct with _Pred comparator
  29. }
  30. size_t operator()(const _Kty& _Keyval) const
  31. { // hash _Keyval to size_t value
  32. return ((size_t)_Keyval);
  33. }
  34. // size_t operator()(const _Kty& _Keyval) const
  35. // { // hash _Keyval to size_t value by pseudorandomizing transform
  36. // ldiv_t _Qrem = ldiv((size_t)_Keyval, 127773);
  37. // _Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
  38. // if (_Qrem.rem < 0)
  39. // _Qrem.rem += 2147483647;
  40. // return ((size_t)_Qrem.rem); }
  41. bool operator()(const _Kty& _Keyval1, const _Kty& _Keyval2) const
  42. { // test if _Keyval1 ordered before _Keyval2
  43. return (comp(_Keyval1, _Keyval2));
  44. }
  45. private:
  46. _Pr comp; // the comparator object
  47. };
  48. // TEMPLATE CLASS _Hash
  49. template<class _Tr>
  50. class _Hash : public _Tr // traits serves as base class
  51. { // hash table -- list with vector of iterators for quick access
  52. public:
  53. typedef _Hash<_Tr> _Myt;
  54. typedef typename _Tr::key_type key_type;
  55. typedef typename _Tr::key_compare key_compare;
  56. typedef typename _Tr::value_compare value_compare;
  57. enum
  58. { // hoist constants from key_compare
  59. bucket_size = key_compare::bucket_size,
  60. min_buckets = key_compare::min_buckets,
  61. _Multi = _Tr::_Multi};
  62. typedef list<typename _Tr::value_type,
  63. typename _Tr::allocator_type> _Mylist;
  64. typedef typename _Mylist::allocator_type allocator_type;
  65. typedef typename _Mylist::size_type size_type;
  66. typedef typename _Mylist::difference_type difference_type;
  67. typedef typename _Mylist::pointer pointer;
  68. typedef typename _Mylist::const_pointer const_pointer;
  69. typedef typename _Mylist::reference reference;
  70. typedef typename _Mylist::const_reference const_reference;
  71. typedef typename _Mylist::iterator iterator;
  72. typedef typename _Mylist::const_iterator const_iterator;
  73. typedef typename _Mylist::reverse_iterator
  74. reverse_iterator;
  75. typedef typename _Mylist::const_reverse_iterator
  76. const_reverse_iterator;
  77. typedef typename _Mylist::value_type value_type;
  78. typedef vector<iterator,
  79. typename allocator_type::_TEMPLATE_MEMBER
  80. rebind<iterator>::other> _Myvec;
  81. typedef pair<iterator, bool> _Pairib;
  82. typedef pair<iterator, iterator> _Pairii;
  83. typedef pair<const_iterator, const_iterator> _Paircc;
  84. explicit _Hash(const key_compare& _Traits,
  85. const allocator_type& _Al)
  86. : _Tr(_Traits), _List(_Al),
  87. _Vec(min_buckets + 1, end(), _Al),
  88. _Mask(1), _Maxidx(1)
  89. { // construct empty hash table
  90. }
  91. _Hash(const value_type *_First, const value_type *_Last,
  92. const key_compare& _Traits, const allocator_type& _Al)
  93. : _Tr(_Traits), _List(_Al),
  94. _Vec(min_buckets + 1, end(), _Al),
  95. _Mask(1), _Maxidx(1)
  96. { // construct hash table from [_First, _Last) array
  97. insert(_First, _Last);
  98. }
  99. _Hash(const _Myt& _Right)
  100. : _Tr(_Right.comp), _List(_Right.get_allocator()),
  101. _Vec(_Right.get_allocator())
  102. { // construct hash table by copying right
  103. _Copy(_Right);
  104. }
  105. ~_Hash()
  106. { // destroy hash table
  107. }
  108. _Myt& operator=(const _Myt& _Right)
  109. { // replace contents from _Right
  110. if (this != &_Right)
  111. _Copy(_Right);
  112. return (*this);
  113. }
  114. iterator begin()
  115. { // return iterator for beginning of mutable sequence
  116. return (_List.begin());
  117. }
  118. const_iterator begin() const
  119. { // return iterator for beginning of nonmutable sequence
  120. return (_List.begin());
  121. }
  122. iterator end()
  123. { // return iterator for end of mutable sequence
  124. return (_List.end());
  125. }
  126. const_iterator end() const
  127. { // return iterator for end of nonmutable sequence
  128. return (_List.end());
  129. }
  130. reverse_iterator rbegin()
  131. { // return iterator for beginning of reversed mutable sequence
  132. return (_List.rbegin());
  133. }
  134. const_reverse_iterator rbegin() const
  135. { // return iterator for beginning of reversed nonmutable sequence
  136. return (_List.rbegin());
  137. }
  138. reverse_iterator rend()
  139. { // return iterator for end of reversed mutable sequence
  140. return (_List.rend());
  141. }
  142. const_reverse_iterator rend() const
  143. { // return iterator for end of reversed nonmutable sequence
  144. return (_List.rend());
  145. }
  146. size_type size() const
  147. { // return length of sequence
  148. return (_List.size());
  149. }
  150. size_type max_size() const
  151. { // return maximum possible length of sequence
  152. return (_List.max_size());
  153. }
  154. bool empty() const
  155. { // return true only if sequence is empty
  156. return (_List.empty());
  157. }
  158. allocator_type get_allocator() const
  159. { // return allocator object for values
  160. return (_List.get_allocator());
  161. }
  162. key_compare key_comp() const
  163. { // return object for comparing keys
  164. return (this->comp);
  165. }
  166. value_compare value_comp() const
  167. { // return object for comparing values
  168. return (value_compare(key_comp()));
  169. }
  170. _Pairib insert(const value_type& _Val)
  171. { // try to insert node with value _Val
  172. iterator _Plist, _Where;
  173. if (_Maxidx <= size() / bucket_size)
  174. { // too dense, need to grow hash table
  175. if (_Vec.size() - 1 <= _Maxidx)
  176. { // table full, double its size
  177. _Mask = ((_Vec.size() - 1) << 1) - 1;
  178. _Vec.resize(_Mask + 2, end());
  179. }
  180. else if (_Mask < _Maxidx)
  181. _Mask = (_Mask << 1) + 1;
  182. size_type _Bucket = _Maxidx - (_Mask >> 1) - 1;
  183. for (_Plist = _Vec[_Bucket]; _Plist != _Vec[_Bucket + 1]; )
  184. if ((this->comp(this->_Kfn(*_Plist)) & _Mask) == _Bucket)
  185. ++_Plist; // leave element in old bucket
  186. else
  187. { // move element to new bucket
  188. iterator _Pnext = _Plist;
  189. size_type _Idx;
  190. for (_Idx = _Maxidx; _Bucket < _Idx; --_Idx)
  191. { // update end iterators if new bucket filled
  192. if (_Vec[_Idx] != end())
  193. break;
  194. _Vec[_Idx] = _Plist;
  195. }
  196. if (++_Pnext == end())
  197. break;
  198. else
  199. { // not at end, move it
  200. for (_Idx = _Bucket; _Plist == _Vec[_Idx]; --_Idx)
  201. { // update end iterators if moving first
  202. ++_Vec[_Idx];
  203. if (_Idx == 0)
  204. break;
  205. }
  206. _List.splice(end(), _List, _Plist);
  207. _Plist = _Pnext;
  208. _Vec[_Maxidx + 1] = end();
  209. }
  210. }
  211. ++_Maxidx; // open new bucket for hash lookup
  212. }
  213. size_type _Bucket = _Hashval(this->_Kfn(_Val));
  214. for (_Plist = _Vec[_Bucket + 1]; _Plist != _Vec[_Bucket]; )
  215. if (this->comp(this->_Kfn(_Val), this->_Kfn(*--_Plist)))
  216. ; // still too high in bucket list
  217. else if (this->comp(this->_Kfn(*_Plist), this->_Kfn(_Val)))
  218. { // found insertion point, back up to it
  219. ++_Plist;
  220. break;
  221. }
  222. else if (_Multi)
  223. break; // equivalent, insert only if multi
  224. else
  225. return (_Pairib(_Plist, false)); // already present
  226. _Where = _List.insert(_Plist, _Val); // insert new element
  227. for (; _Plist == _Vec[_Bucket]; --_Bucket)
  228. { // update end iterators if new first bucket element
  229. _Vec[_Bucket] = _Where;
  230. if (_Bucket == 0)
  231. break;
  232. }
  233. return (_Pairib(_Where, true)); // return iterator for new element
  234. }
  235. iterator insert(iterator, const value_type& _Val)
  236. { // try to insert node with value _Val, ignore hint
  237. return (insert(_Val).first);
  238. }
  239. template<class _Iter>
  240. void insert(_Iter _First, _Iter _Last)
  241. { // insert [_First, _Last) one at a time
  242. for (; _First != _Last; ++_First)
  243. insert(*_First);
  244. }
  245. iterator erase(iterator _Where)
  246. { // erase element at _Where
  247. size_type _Bucket = _Hashval(this->_Kfn(*_Where));
  248. for (; _Where == _Vec[_Bucket]; --_Bucket)
  249. { // update end iterators if erasing first
  250. ++_Vec[_Bucket];
  251. if (_Bucket == 0)
  252. break;
  253. }
  254. return (_List.erase(_Where));
  255. }
  256. iterator erase(iterator _First, iterator _Last)
  257. { // erase [_First, _Last)
  258. if (_First == begin() && _Last == end())
  259. { // erase all
  260. clear();
  261. return (begin());
  262. }
  263. else
  264. { // partial erase, one at a time
  265. while (_First != _Last)
  266. erase(_First++);
  267. return (_First);
  268. }
  269. }
  270. size_type erase(const key_type& _Keyval)
  271. { // erase and count all that match _Keyval
  272. _Pairii _Where = equal_range(_Keyval);
  273. size_type _Num = 0;
  274. _Distance(_Where.first, _Where.second, _Num);
  275. erase(_Where.first, _Where.second);
  276. return (_Num);
  277. }
  278. void erase(const key_type *_First, const key_type *_Last)
  279. { // erase all that match array of keys [_First, _Last)
  280. for (; _First != _Last; ++_First)
  281. erase(*_First);
  282. }
  283. void clear()
  284. { // erase all
  285. _List.clear();
  286. _Vec.assign(min_buckets + 1, end());
  287. _Mask = 1;
  288. _Maxidx = 1;
  289. }
  290. iterator find(const key_type& _Keyval)
  291. { // find an element in mutable hash table that matches _Keyval
  292. return (lower_bound(_Keyval));
  293. }
  294. const_iterator find(const key_type& _Keyval) const
  295. { // find an element in nonmutable hash table that matches _Keyval
  296. return (lower_bound(_Keyval));
  297. }
  298. size_type count(const key_type& _Keyval) const
  299. { // count all elements that match _Keyval
  300. _Paircc _Ans = equal_range(_Keyval);
  301. size_type _Num = 0;
  302. _Distance(_Ans.first, _Ans.second, _Num);
  303. return (_Num);
  304. }
  305. iterator lower_bound(const key_type& _Keyval)
  306. { // find leftmost not less than _Keyval in mutable hash table
  307. size_type _Bucket = _Hashval(_Keyval);
  308. iterator _Where;
  309. for (_Where = _Vec[_Bucket]; _Where != _Vec[_Bucket + 1]; ++_Where)
  310. if (!this->comp(this->_Kfn(*_Where), _Keyval))
  311. return (this->comp(_Keyval,
  312. this->_Kfn(*_Where)) ? end() : _Where);
  313. return (end());
  314. }
  315. const_iterator lower_bound(const key_type& _Keyval) const
  316. { // find leftmost not less than _Keyval in nonmutable hash table
  317. size_type _Bucket = _Hashval(_Keyval);
  318. const_iterator _Where;
  319. for (_Where = _Vec[_Bucket]; _Where != _Vec[_Bucket + 1]; ++_Where)
  320. if (!this->comp(this->_Kfn(*_Where), _Keyval))
  321. return (this->comp(_Keyval,
  322. this->_Kfn(*_Where)) ? end() : _Where);
  323. return (end());
  324. }
  325. iterator upper_bound(const key_type& _Keyval)
  326. { // find leftmost not greater than _Keyval in mutable hash table
  327. size_type _Bucket = _Hashval(_Keyval);
  328. iterator _Where;
  329. for (_Where = _Vec[_Bucket + 1]; _Where != _Vec[_Bucket]; )
  330. if (!this->comp(_Keyval, this->_Kfn(*--_Where)))
  331. return (this->comp(this->_Kfn(*_Where),
  332. _Keyval) ? end() : ++_Where);
  333. return (end());
  334. }
  335. const_iterator upper_bound(const key_type& _Keyval) const
  336. { // find leftmost not greater than _Keyval in nonmutable hash table
  337. size_type _Bucket = _Hashval(_Keyval);
  338. const_iterator _Where;
  339. for (_Where = _Vec[_Bucket + 1]; _Where != _Vec[_Bucket]; )
  340. if (!this->comp(_Keyval, this->_Kfn(*--_Where)))
  341. return (this->comp(this->_Kfn(*_Where),
  342. _Keyval) ? end() : ++_Where);
  343. return (end());
  344. }
  345. _Pairii equal_range(const key_type& _Keyval)
  346. { // find range equivalent to _Keyval in mutable hash table
  347. size_type _Bucket = _Hashval(_Keyval);
  348. iterator _First, _Where;
  349. for (_Where = _Vec[_Bucket]; _Where != _Vec[_Bucket + 1]; ++_Where)
  350. if (!this->comp(this->_Kfn(*_Where), _Keyval))
  351. { // found _First, look for end of range
  352. for (_First = _Where; _Where != _Vec[_Bucket + 1]; ++_Where)
  353. if (this->comp(_Keyval, this->_Kfn(*_Where)))
  354. break;
  355. if (_First == _Where)
  356. break;
  357. return (_Pairii(_First, _Where));
  358. }
  359. return (_Pairii(end(), end()));
  360. }
  361. _Paircc equal_range(const key_type& _Keyval) const
  362. { // find range equivalent to _Keyval in nonmutable hash table
  363. size_type _Bucket = _Hashval(_Keyval);
  364. iterator _First, _Where;
  365. for (_Where = _Vec[_Bucket]; _Where != _Vec[_Bucket + 1]; ++_Where)
  366. if (!this->comp(this->_Kfn(*_Where), _Keyval))
  367. { // found _First, look for end of range
  368. for (_First = _Where; _Where != _Vec[_Bucket + 1]; ++_Where)
  369. if (this->comp(_Keyval, this->_Kfn(*_Where)))
  370. break;
  371. if (_First == _Where)
  372. break;
  373. return (_Paircc(_First, _Where));
  374. }
  375. return (_Paircc(end(), end()));
  376. }
  377. void swap(_Myt& _Right)
  378. { // exchange contents with _Right
  379. if (get_allocator() == _Right.get_allocator())
  380. { // same allocator, swap control information
  381. _List.swap(_Right._List);
  382. std::swap(_Vec, _Right._Vec);
  383. std::swap(_Mask, _Right._Mask);
  384. std::swap(_Maxidx, _Right._Maxidx);
  385. std::swap(this->comp, _Right.comp);
  386. }
  387. else
  388. { // different allocator, do multiple assigns
  389. _Myt _Tmp = *this; *this = _Right, _Right = _Tmp;
  390. }
  391. }
  392. friend void swap(_Myt& _Left, _Myt& _Right)
  393. { // swap _Left and _Right trees
  394. _Left.swap(_Right);
  395. }
  396. protected:
  397. void _Copy(const _Myt& _Right)
  398. { // copy entire hash table
  399. _Vec.resize(_Right._Vec.size(), end());
  400. _Mask = _Right._Mask;
  401. _Maxidx = _Right._Maxidx;
  402. _List.clear();
  403. _TRY_BEGIN
  404. _List.insert(end(), _Right._List.begin(), _Right._List.end());
  405. this->comp = _Right.comp;
  406. _CATCH_ALL
  407. _List.clear(); // list or compare copy failed, bail out
  408. fill(_Vec.begin(), _Vec.end(), end());
  409. _RERAISE;
  410. _CATCH_END
  411. iterator _Whereto = begin();
  412. const_iterator _Wherefrom = _Right.begin();
  413. for (size_type _Bucket = 0; _Bucket < _Vec.size(); )
  414. if (_Wherefrom == _Right._Vec[_Bucket])
  415. _Vec[_Bucket] = _Whereto, ++_Bucket;
  416. else
  417. ++_Whereto, ++_Wherefrom;
  418. }
  419. size_type _Hashval(const key_type& _Keyval) const
  420. { // return hash value, masked and wrapped to current table size
  421. size_type _Num = this->comp(_Keyval) & _Mask;
  422. if (_Maxidx <= _Num)
  423. _Num -= (_Mask >> 1) + 1;
  424. return (_Num);
  425. }
  426. _Mylist _List; // the list of elements, must initialize before _Vec
  427. _Myvec _Vec; // the vector of list iterators
  428. size_type _Mask; // the key mask
  429. size_type _Maxidx; // current maximum key value
  430. };
  431. // _Hash TEMPLATE OPERATORS
  432. template<class _Tr> inline
  433. bool operator==(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  434. { // test for hash table equality
  435. return (_Left.size() == _Right.size()
  436. && equal(_Left.begin(), _Left.end(), _Right.begin()));
  437. }
  438. template<class _Tr> inline
  439. bool operator!=(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  440. { // test for hash table inequality
  441. return (!(_Left == _Right));
  442. }
  443. template<class _Tr> inline
  444. bool operator<(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  445. { // test if _Left < _Right for hash tables
  446. return (lexicographical_compare(_Left.begin(), _Left.end(),
  447. _Right.begin(), _Right.end()));
  448. }
  449. template<class _Tr> inline
  450. bool operator>(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  451. { // test if _Left > _Right for hash tables
  452. return (_Right < _Left);
  453. }
  454. template<class _Tr> inline
  455. bool operator<=(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  456. { // test if _Left <= _Right for hash tables
  457. return (!(_Right < _Left));
  458. }
  459. template<class _Tr> inline
  460. bool operator>=(const _Hash<_Tr>& _Left, const _Hash<_Tr>& _Right)
  461. { // test if _Left >= _Right for hash tables
  462. return (!(_Left < _Right));
  463. }
  464. _STD_END
  465. #pragma warning(default: 4127)
  466. #pragma warning(pop)
  467. #pragma pack(pop)
  468. #endif /* _XHASH_ */
  469. /*
  470. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  471. * Consult your license regarding permissions and restrictions.
  472. V3.10:0009 */