PageRenderTime 96ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/lllocalidhashmap.h

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