lllocalidhashmap.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:21k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lllocalidhashmap.h
  3.  * @brief Map specialized for dealing with local ids
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #ifndef LL_LLLOCALIDHASHMAP_H
  33. #define LL_LLLOCALIDHASHMAP_H
  34. #include "stdtypes.h"
  35. #include "llerror.h"
  36. const S32 MAX_ITERS = 4;
  37. // LocalID hash map
  38. //
  39. // LLLocalIDHashNode
  40. //
  41. template <class DATA, int SIZE>
  42. class LLLocalIDHashNode
  43. {
  44. public:
  45. LLLocalIDHashNode();
  46. public:
  47. S32 mCount;
  48. U32 mKey[SIZE];
  49. DATA mData[SIZE];
  50. LLLocalIDHashNode<DATA, SIZE> *mNextNodep;
  51. };
  52. //
  53. // LLLocalIDHashNode implementation
  54. //
  55. template <class DATA, int SIZE>
  56. LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode()
  57. {
  58. mCount = 0;
  59. mNextNodep = NULL;
  60. }
  61. //
  62. // LLLocalIDHashMapIter
  63. //
  64. template <class DATA_TYPE, int SIZE>
  65. class LLLocalIDHashMap;
  66. template <class DATA_TYPE, int SIZE>
  67. class LLLocalIDHashMapIter
  68. {
  69. public:
  70. LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
  71. ~LLLocalIDHashMapIter();
  72. void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
  73. inline void first();
  74. inline void next();
  75. inline DATA_TYPE& current(); // *NOTE: Deprecate? Phoenix 2005-04-15
  76. inline BOOL done() const;
  77. inline S32  currentBin() const;
  78. inline void setBin(S32 bin);
  79. DATA_TYPE& operator*() const
  80. {
  81. return mCurHashNodep->mData[mCurHashNodeKey];
  82. }
  83. DATA_TYPE* operator->() const
  84. {
  85. return &(operator*());
  86. }
  87. LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
  88. LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
  89. S32 mCurHashMapNodeNum;
  90. S32 mCurHashNodeKey;
  91. DATA_TYPE mNull;
  92. S32 mIterID;
  93. };
  94. template <class DATA_TYPE, int SIZE>
  95. class LLLocalIDHashMap
  96. {
  97. public:
  98. friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>;
  99. LLLocalIDHashMap(); // DO NOT use this unless you explicitly setNull, or the data type constructs a "null"
  100. // object by default
  101. // basic constructor including sorter
  102. LLLocalIDHashMap(const DATA_TYPE &null_data);
  103. // Hack, this should really be a const ref, but I'm not doing it that way because the sim
  104. // usually uses pointers.
  105. ~LLLocalIDHashMap();
  106. inline DATA_TYPE &get(const U32 local_id);
  107. inline BOOL check(const U32 local_id) const;
  108. inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data);
  109. inline BOOL remove(const U32 local_id);
  110. void removeAll();
  111. void setNull(const DATA_TYPE data) { mNull = data; }
  112. inline S32 getLength() const; // Warning, NOT O(1!)
  113. void dumpIter();
  114. void dumpBin(U32 bin);
  115. protected:
  116. // Only used by the iterator.
  117. void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
  118. void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
  119. // Remove the item and shift all items afterward down the list,
  120. // fixing up iterators as we go.
  121. BOOL removeWithShift(const U32 local_id);
  122. protected:
  123. LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256];
  124. S32 mIterCount;
  125. LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS];
  126. DATA_TYPE mNull;
  127. };
  128. //
  129. // LLLocalIDHashMap implementation
  130. //
  131. template <class DATA_TYPE, int SIZE>
  132. LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap()
  133. : mIterCount(0),
  134. mNull()
  135. {
  136. S32 i;
  137. for (i = 0; i < MAX_ITERS; i++)
  138. {
  139. mIters[i] = NULL;
  140. }
  141. }
  142. template <class DATA_TYPE, int SIZE>
  143. LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data)
  144. : mIterCount(0),
  145. mNull(null_data)
  146. {
  147. S32 i;
  148. for (i = 0; i < MAX_ITERS; i++)
  149. {
  150. mIters[i] = NULL;
  151. }
  152. }
  153. template <class DATA_TYPE, int SIZE>
  154. LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap()
  155. {
  156. S32 i;
  157. for (i = 0; i < MAX_ITERS; i++)
  158. {
  159. if (mIters[i])
  160. {
  161. mIters[i]->mHashMapp = NULL;
  162. mIterCount--;
  163. }
  164. }
  165. removeAll();
  166. }
  167. template <class DATA_TYPE, int SIZE>
  168. void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll()
  169. {
  170. S32 bin;
  171. for (bin = 0; bin < 256; bin++)
  172. {
  173. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
  174. BOOL first = TRUE;
  175. do // First node guaranteed to be there
  176. {
  177. S32 i;
  178. const S32 count = nodep->mCount;
  179. // Iterate through all members of this node
  180. for (i = 0; i < count; i++)
  181. {
  182. nodep->mData[i] = mNull;
  183. }
  184. nodep->mCount = 0;
  185. // Done with all objects in this node, go to the next.
  186. LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
  187. nodep = nodep->mNextNodep;
  188. // Delete the node if it's not the first node
  189. if (first)
  190. {
  191. first = FALSE;
  192. curp->mNextNodep = NULL;
  193. }
  194. else
  195. {
  196. delete curp;
  197. }
  198. } while (nodep);
  199. }
  200. }
  201. template <class DATA_TYPE, int SIZE>
  202. void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter()
  203. {
  204. std::cout << "Hash map with " << mIterCount << " iterators" << std::endl;
  205. std::cout << "Hash Map Iterators:" << std::endl;
  206. S32 i;
  207. for (i = 0; i < MAX_ITERS; i++)
  208. {
  209. if (mIters[i])
  210. {
  211. llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl;
  212. }
  213. else
  214. {
  215. llinfos << i << "null" << llendl;
  216. }
  217. }
  218. }
  219. template <class DATA_TYPE, int SIZE>
  220. void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin)
  221. {
  222. std::cout << "Dump bin " << bin << std::endl;
  223. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
  224. S32 node = 0;
  225. do // First node guaranteed to be there.
  226. {
  227. std::cout << "Bin " << bin 
  228. << " node " << node
  229. << " count " << nodep->mCount
  230. << " contains " << std::flush;
  231. S32 i;
  232. for (i = 0; i < nodep->mCount; i++)
  233. {
  234. std::cout << nodep->mData[i] << " " << std::flush;
  235. }
  236. std::cout << std::endl;
  237. nodep = nodep->mNextNodep;
  238. node++;
  239. } while (nodep);
  240. }
  241. template <class DATA_TYPE, int SIZE>
  242. inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const
  243. {
  244. S32 count = 0;
  245. S32 bin;
  246. for (bin = 0; bin < 256; bin++)
  247. {
  248. const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
  249. while (nodep)
  250. {
  251. count += nodep->mCount;
  252. nodep = nodep->mNextNodep;
  253. }
  254. }
  255. return count;
  256. }
  257. template <class DATA_TYPE, int SIZE>
  258. inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id)
  259. {
  260. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
  261. do // First node guaranteed to be there
  262. {
  263. S32 i;
  264. const S32 count = nodep->mCount;
  265. // Iterate through all members of this node
  266. for (i = 0; i < count; i++)
  267. {
  268. if (nodep->mKey[i] == local_id)
  269. {
  270. // We found it.
  271. return nodep->mData[i];
  272. }
  273. }
  274. // Done with all objects in this node, go to the next.
  275. nodep = nodep->mNextNodep;
  276. } while (nodep);
  277. return mNull;
  278. }
  279. template <class DATA_TYPE, int SIZE>
  280. inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const
  281. {
  282. const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
  283. do // First node guaranteed to be there
  284. {
  285. S32 i;
  286. const S32 count = nodep->mCount;
  287. // Iterate through all members of this node
  288. for (i = 0; i < count; i++)
  289. {
  290. if (nodep->mKey[i] == local_id)
  291. {
  292. // We found it.
  293. return TRUE;
  294. }
  295. }
  296. // Done with all objects in this node, go to the next.
  297. nodep = nodep->mNextNodep;
  298. } while (nodep);
  299. // Didn't find anything
  300. return FALSE;
  301. }
  302. template <class DATA_TYPE, int SIZE>
  303. inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data)
  304. {
  305. // Set is just like a normal find, except that if we find a match
  306. // we replace it with the input value.
  307. // If we don't find a match, we append to the end of the list.
  308. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
  309. while (1)
  310. {
  311. const S32 count = nodep->mCount;
  312. S32 i;
  313. for (i = 0; i < count; i++)
  314. {
  315. if (nodep->mKey[i] == local_id)
  316. {
  317. // We found a match for this key, replace the data with
  318. // the incoming data.
  319. nodep->mData[i] = data;
  320. return nodep->mData[i];
  321. }
  322. }
  323. if (!nodep->mNextNodep)
  324. {
  325. // We've iterated through all of the keys without finding a match
  326. if (i < SIZE)
  327. {
  328. // There's still some space on this node, append
  329. // the key and data to it.
  330. nodep->mKey[i] = local_id;
  331. nodep->mData[i] = data;
  332. nodep->mCount++;
  333. return nodep->mData[i];
  334. }
  335. else
  336. {
  337. // This node is full, append a new node to the end.
  338. nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>;
  339. nodep->mNextNodep->mKey[0] = local_id;
  340. nodep->mNextNodep->mData[0] = data;
  341. nodep->mNextNodep->mCount = 1;
  342. return nodep->mNextNodep->mData[0];
  343. }
  344. }
  345. // No match on this node, go to the next
  346. nodep = nodep->mNextNodep;
  347. }
  348. }
  349. template <class DATA_TYPE, int SIZE>
  350. inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id)
  351. {
  352. // Remove is the trickiest operation.
  353. // What we want to do is swap the last element of the last
  354. // node if we find the one that we want to remove, but we have
  355. // to deal with deleting the node from the tail if it's empty, but
  356. // NOT if it's the only node left.
  357. const S32 node_index = local_id & 0xff;
  358. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
  359. // A modification of the standard search algorithm.
  360. do // First node guaranteed to be there
  361. {
  362. const S32 count = nodep->mCount;
  363. S32 i;
  364. for (i = 0; i < count; i++)
  365. {
  366. if (nodep->mKey[i] == local_id)
  367. {
  368. // If we're removing the item currently pointed to by one
  369. // or more iterators, we can just swap in the last item
  370. // and back the iterator(s) up by one.
  371. // Otherwise, we need to do a slow and safe shift of all
  372. // items back to one position to fill the hole and fix up 
  373. // all iterators we find.
  374. BOOL need_shift = FALSE;
  375. S32 cur_iter;
  376. if (mIterCount)
  377. {
  378. for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
  379. {
  380. if (mIters[cur_iter])
  381. {
  382. // We only care if the hash map node is on the one
  383. // that we're working on.  If it's before, we've already
  384. // traversed it, if it's after, changing the order doesn't
  385. // matter.
  386. if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
  387. {
  388. if ((mIters[cur_iter]->mCurHashNodep == nodep)
  389. && (mIters[cur_iter]->mCurHashNodeKey == i))
  390. {
  391. // it's on the one we're deleting, we'll
  392. // fix the iterator quickly below.
  393. }
  394. else
  395. {
  396. // We're trying to remove an item on this
  397. // iterator's chain that this
  398. // iterator doesn't point to!  We need to do
  399. // the slow remove-and-shift-down case.
  400. need_shift = TRUE;
  401. }
  402. }
  403. }
  404. }
  405. }
  406. // Removing an item that isn't pointed to by all iterators
  407. if (need_shift)
  408. {
  409. return removeWithShift(local_id);
  410. }
  411. // Fix the iterators that point to this node/i pair, the
  412. // one we're deleting
  413. for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
  414. {
  415. if (mIters[cur_iter])
  416. {
  417. // We only care if the hash map node is on the one
  418. // that we're working on.  If it's before, we've already
  419. // traversed it, if it's after, changing the order doesn't
  420. // matter.
  421. if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
  422. {
  423. if ((mIters[cur_iter]->mCurHashNodep == nodep)
  424. && (mIters[cur_iter]->mCurHashNodeKey == i))
  425. {
  426. // We can handle the case where we're deleting 
  427. // the element we're on trivially (sort of).
  428. if (nodep->mCount > 1)
  429. {
  430. // If we're not going to delete this node,
  431. // it's OK.
  432. mIters[cur_iter]->mCurHashNodeKey--;
  433. }
  434. else
  435. {
  436. // We're going to delete this node, because this
  437. // is the last element on it.
  438. // Find the next node, and then back up one.
  439. mIters[cur_iter]->next();
  440. mIters[cur_iter]->mCurHashNodeKey--;
  441. }
  442. }
  443. }
  444. }
  445. }
  446. // We found the node that we want to remove.
  447. // Find the last (and next-to-last) node, and the index of the last
  448. // element.  We could conceviably start from the node we're on,
  449. // but that makes it more complicated, this is easier.
  450. LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index];
  451. LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
  452. // Find the last and next-to-last
  453. while (lastp->mNextNodep)
  454. {
  455. prevp = lastp;
  456. lastp = lastp->mNextNodep;
  457. }
  458. // First, swap in the last to the current location.
  459. nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
  460. nodep->mData[i] = lastp->mData[lastp->mCount - 1];
  461. // Now, we delete the entry
  462. lastp->mCount--;
  463. lastp->mData[lastp->mCount] = mNull;
  464. if (!lastp->mCount)
  465. {
  466. // We deleted the last element!
  467. if (lastp != &mNodes[local_id & 0xff])
  468. {
  469. // Only blitz the node if it's not the head
  470. // Set the previous node to point to NULL, then
  471. // blitz the empty last node
  472. prevp->mNextNodep = NULL;
  473. delete lastp;
  474. }
  475. }
  476. return TRUE;
  477. }
  478. }
  479. // Iterate to the next node, we've scanned all the entries in this one.
  480. nodep = nodep->mNextNodep;
  481. } while (nodep);
  482. return FALSE;
  483. }
  484. template <class DATA_TYPE, int SIZE>
  485. BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id)
  486. {
  487. const S32 node_index = local_id & 0xFF;
  488. LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
  489. LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL;
  490. BOOL found = FALSE;
  491. do // First node guaranteed to be there
  492. {
  493. const S32 count = nodep->mCount;
  494. S32 i;
  495. for (i = 0; i < count; i++)
  496. {
  497. if (nodep->mKey[i] == local_id)
  498. {
  499. // Found the item.  Start shifting items from later
  500. // in the list over this item.
  501. found = TRUE;
  502. }
  503. if (found)
  504. {
  505. // If there is an iterator on this node, we need to 
  506. // back it up.
  507. S32 cur_iter;
  508. for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++)
  509. {
  510. LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter;
  511. iter = mIters[cur_iter];
  512. // If an iterator is on this node,i pair, then back it up.
  513. if (iter
  514. && iter->mCurHashMapNodeNum == node_index
  515. && iter->mCurHashNodep == nodep
  516. && iter->mCurHashNodeKey == i)
  517. {
  518. if (i > 0)
  519. {
  520. // Don't need to move iterator nodep, since 
  521. // we're in the same node.
  522. iter->mCurHashNodeKey--;
  523. }
  524. else if (prevp)
  525. {
  526. // need to go the previous node, last item
  527. iter->mCurHashNodep = prevp;
  528. iter->mCurHashNodeKey = prevp->mCount - 1;
  529. }
  530. else
  531. {
  532. // we're on the first item in the list, but
  533. // need to go back anyhow.
  534. // BUG: If this deletion empties the list, 
  535. // iter->done() will be wrong until
  536. // iter->next() is called.
  537. iter->mCurHashNodeKey = -1;
  538. }
  539. }
  540. }
  541. // Copy data from the next position into this position.
  542. if (i < count-1)
  543. {
  544. // we're not on the last item in the node,
  545. // so we can copy within the node
  546. nodep->mKey[i] = nodep->mKey[i+1];
  547. nodep->mData[i] = nodep->mData[i+1];
  548. }
  549. else if (nodep->mNextNodep)
  550. {
  551. // we're on the last item in the node,
  552. // but there's a next node we can copy from
  553. nodep->mKey[i] = nodep->mNextNodep->mKey[0];
  554. nodep->mData[i] = nodep->mNextNodep->mData[0];
  555. }
  556. else
  557. {
  558. // We're on the last position in the list.
  559. // No one to copy from.  Replace with nothing.
  560. nodep->mKey[i] = 0;
  561. nodep->mData[i] = mNull;
  562. }
  563. }
  564. }
  565. // Last node in chain, so delete the last node
  566. if (found
  567. && !nodep->mNextNodep)
  568. {
  569. // delete the last item off the last node
  570. nodep->mCount--;
  571. if (nodep->mCount == 0)
  572. {
  573. // We deleted the last element!
  574. if (nodep != &mNodes[node_index])
  575. {
  576. // Always have a prevp if we're not the head.
  577. llassert(prevp);
  578. // Only blitz the node if it's not the head
  579. // Set the previous node to point to NULL, then
  580. // blitz the empty last node
  581. prevp->mNextNodep = NULL;
  582. delete nodep;
  583. nodep = NULL;
  584. }
  585. }
  586. // Deleted last item in chain, so we're done.
  587. return found;
  588. }
  589. prevp = nodep;
  590. nodep = nodep->mNextNodep;
  591. } while (nodep);
  592. return found;
  593. }
  594. template <class DATA_TYPE, int SIZE>
  595. void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
  596. {
  597. S32 i;
  598. for (i = 0; i < MAX_ITERS; i++)
  599. {
  600. if (mIters[i] == iter)
  601. {
  602. mIters[i] = NULL;
  603. mIterCount--;
  604. return;
  605. }
  606. }
  607. llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl;
  608. }
  609. template <class DATA_TYPE, int SIZE>
  610. void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
  611. {
  612. S32 i;
  613. for (i = 0; i < MAX_ITERS; i++)
  614. {
  615. if (mIters[i] == NULL)
  616. {
  617. mIters[i] = iter;
  618. mIterCount++;
  619. return;
  620. }
  621. }
  622. llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl;
  623. }
  624. //
  625. // LLLocalIDHashMapIter Implementation
  626. //
  627. template <class DATA_TYPE, int SIZE>
  628. LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
  629. {
  630. mHashMapp = NULL;
  631. setMap(hash_mapp);
  632. }
  633. template <class DATA_TYPE, int SIZE>
  634. LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter()
  635. {
  636. if (mHashMapp)
  637. {
  638. mHashMapp->removeIter(this);
  639. }
  640. }
  641. template <class DATA_TYPE, int SIZE>
  642. void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
  643. {
  644. if (mHashMapp)
  645. {
  646. mHashMapp->removeIter(this);
  647. }
  648. mHashMapp = hash_mapp;
  649. if (mHashMapp)
  650. {
  651. mHashMapp->addIter(this);
  652. }
  653. mCurHashNodep = NULL;
  654. mCurHashMapNodeNum = -1;
  655. mCurHashNodeKey = 0;
  656. }
  657. template <class DATA_TYPE, int SIZE>
  658. inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first()
  659. {
  660. // Iterate through until we find the first non-empty node;
  661. S32 i;
  662. for (i = 0; i < 256; i++)
  663. {
  664. if (mHashMapp->mNodes[i].mCount)
  665. {
  666. mCurHashNodep = &mHashMapp->mNodes[i];
  667. mCurHashMapNodeNum = i;
  668. mCurHashNodeKey = 0;
  669. //return mCurHashNodep->mData[0];
  670. return;
  671. }
  672. }
  673. // Completely empty!
  674. mCurHashNodep = NULL;
  675. //return mNull;
  676. return;
  677. }
  678. template <class DATA_TYPE, int SIZE>
  679. inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const
  680. {
  681. return mCurHashNodep ? FALSE : TRUE;
  682. }
  683. template <class DATA_TYPE, int SIZE>
  684. inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const
  685. {
  686. if (  (mCurHashMapNodeNum > 255)
  687. ||(mCurHashMapNodeNum < 0))
  688. {
  689. return 0;
  690. }
  691. else
  692. {
  693. return mCurHashMapNodeNum;
  694. }
  695. }
  696. template <class DATA_TYPE, int SIZE>
  697. inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin)
  698. {
  699. // Iterate through until we find the first non-empty node;
  700. S32 i;
  701. bin = llclamp(bin, 0, 255);
  702. for (i = bin; i < 256; i++)
  703. {
  704. if (mHashMapp->mNodes[i].mCount)
  705. {
  706. mCurHashNodep = &mHashMapp->mNodes[i];
  707. mCurHashMapNodeNum = i;
  708. mCurHashNodeKey = 0;
  709. return;
  710. }
  711. }
  712. for (i = 0; i < bin; i++)
  713. {
  714. if (mHashMapp->mNodes[i].mCount)
  715. {
  716. mCurHashNodep = &mHashMapp->mNodes[i];
  717. mCurHashMapNodeNum = i;
  718. mCurHashNodeKey = 0;
  719. return;
  720. }
  721. }
  722. // Completely empty!
  723. mCurHashNodep = NULL;
  724. }
  725. template <class DATA_TYPE, int SIZE>
  726. inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current()
  727. {
  728. if (!mCurHashNodep)
  729. {
  730. return mNull;
  731. }
  732. return mCurHashNodep->mData[mCurHashNodeKey];
  733. }
  734. template <class DATA_TYPE, int SIZE>
  735. inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next()
  736. {
  737. // No current entry, this iterator is done
  738. if (!mCurHashNodep)
  739. {
  740. //return mNull;
  741. return;
  742. }
  743. // Go to the next element
  744. mCurHashNodeKey++;
  745. if (mCurHashNodeKey < mCurHashNodep->mCount)
  746. {
  747. // We're not done with this node, return the current element
  748. //return mCurHashNodep->mData[mCurHashNodeKey];
  749. return;
  750. }
  751. // Done with this node, move to the next
  752. mCurHashNodep = mCurHashNodep->mNextNodep;
  753. if (mCurHashNodep)
  754. {
  755. // Return the first element
  756. mCurHashNodeKey = 0;
  757. //return mCurHashNodep->mData[0];
  758. return;
  759. }
  760. // Find the next non-empty node (keyed on the first byte)
  761. mCurHashMapNodeNum++;
  762. S32 i;
  763. for (i = mCurHashMapNodeNum; i < 256; i++)
  764. {
  765. if (mHashMapp->mNodes[i].mCount)
  766. {
  767. // We found one that wasn't empty
  768. mCurHashNodep = &mHashMapp->mNodes[i];
  769. mCurHashMapNodeNum = i;
  770. mCurHashNodeKey = 0;
  771. //return mCurHashNodep->mData[0];
  772. return;
  773. }
  774. }
  775. // OK, we're done, nothing else to iterate
  776. mCurHashNodep = NULL;
  777. mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
  778. //return mNull;
  779. return;
  780. }
  781. #endif // LL_LLLOCALIDHASHMAP_H