/indra/llcommon/llskipmap.h

https://bitbucket.org/lindenlab/viewer-beta/ · C++ Header · 1022 lines · 770 code · 141 blank · 111 comment · 99 complexity · 7d6903eb01d575a763f3e9cc8dad502b MD5 · raw file

  1. /**
  2. * @file llskipmap.h
  3. * @brief Associative container based on the skiplist algorithm.
  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_LLSKIPMAP_H
  27. #define LL_LLSKIPMAP_H
  28. #include "llerror.h"
  29. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH = 8>
  30. class LLSkipMap
  31. {
  32. public:
  33. // basic constructor
  34. LLSkipMap();
  35. // basic constructor including sorter
  36. LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second),
  37. BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
  38. ~LLSkipMap();
  39. void setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second));
  40. void setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
  41. DATA_TYPE &addData(const INDEX_TYPE &index, DATA_TYPE datap);
  42. DATA_TYPE &addData(const INDEX_TYPE &index);
  43. DATA_TYPE &getData(const INDEX_TYPE &index);
  44. DATA_TYPE &operator[](const INDEX_TYPE &index);
  45. // If index present, returns data.
  46. // If index not present, adds <index,NULL> and returns NULL.
  47. DATA_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry);
  48. // Returns TRUE if data present in map.
  49. BOOL checkData(const INDEX_TYPE &index);
  50. // Returns TRUE if key is present in map. This is useful if you
  51. // are potentially storing NULL pointers in the map
  52. BOOL checkKey(const INDEX_TYPE &index);
  53. // If there, returns the data.
  54. // If not, returns NULL.
  55. // Never adds entries to the map.
  56. DATA_TYPE getIfThere(const INDEX_TYPE &index);
  57. INDEX_TYPE reverseLookup(const DATA_TYPE datap);
  58. // returns number of items in the list
  59. S32 getLength(); // WARNING! getLength is O(n), not O(1)!
  60. BOOL removeData(const INDEX_TYPE &index);
  61. // remove all nodes from the list but do not delete data
  62. void removeAllData();
  63. // place mCurrentp on first node
  64. void resetList();
  65. // return the data currently pointed to
  66. DATA_TYPE getCurrentDataWithoutIncrement();
  67. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  68. DATA_TYPE getCurrentData();
  69. // same as getCurrentData() but a more intuitive name for the operation
  70. DATA_TYPE getNextData();
  71. INDEX_TYPE getNextKey();
  72. // return the key currently pointed to
  73. INDEX_TYPE getCurrentKeyWithoutIncrement();
  74. // The internal iterator is at the end of the list.
  75. BOOL notDone() const;
  76. // remove the Node at mCurentOperatingp
  77. // leave mCurrentp and mCurentOperatingp on the next entry
  78. void removeCurrentData();
  79. void deleteCurrentData();
  80. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  81. DATA_TYPE getFirstData();
  82. INDEX_TYPE getFirstKey();
  83. class LLSkipMapNode
  84. {
  85. public:
  86. LLSkipMapNode()
  87. {
  88. S32 i;
  89. for (i = 0; i < BINARY_DEPTH; i++)
  90. {
  91. mForward[i] = NULL;
  92. }
  93. U8 *zero = (U8 *)&mIndex;
  94. for (i = 0; i < (S32)sizeof(INDEX_TYPE); i++)
  95. {
  96. *(zero + i) = 0;
  97. }
  98. zero = (U8 *)&mData;
  99. for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
  100. {
  101. *(zero + i) = 0;
  102. }
  103. }
  104. LLSkipMapNode(const INDEX_TYPE &index)
  105. : mIndex(index)
  106. {
  107. S32 i;
  108. for (i = 0; i < BINARY_DEPTH; i++)
  109. {
  110. mForward[i] = NULL;
  111. }
  112. U8 *zero = (U8 *)&mData;
  113. for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
  114. {
  115. *(zero + i) = 0;
  116. }
  117. }
  118. LLSkipMapNode(const INDEX_TYPE &index, DATA_TYPE datap)
  119. : mIndex(index)
  120. {
  121. S32 i;
  122. for (i = 0; i < BINARY_DEPTH; i++)
  123. {
  124. mForward[i] = NULL;
  125. }
  126. mData = datap;
  127. }
  128. ~LLSkipMapNode()
  129. {
  130. }
  131. INDEX_TYPE mIndex;
  132. DATA_TYPE mData;
  133. LLSkipMapNode *mForward[BINARY_DEPTH];
  134. private:
  135. // Disallow copying of LLSkipMapNodes by not implementing these methods.
  136. LLSkipMapNode(const LLSkipMapNode &);
  137. LLSkipMapNode &operator=(const LLSkipMapNode &rhs);
  138. };
  139. static BOOL defaultEquals(const INDEX_TYPE &first, const INDEX_TYPE &second)
  140. {
  141. return first == second;
  142. }
  143. private:
  144. // don't generate implicit copy constructor or copy assignment
  145. LLSkipMap(const LLSkipMap &);
  146. LLSkipMap &operator=(const LLSkipMap &);
  147. private:
  148. LLSkipMapNode mHead;
  149. LLSkipMapNode *mUpdate[BINARY_DEPTH];
  150. LLSkipMapNode *mCurrentp;
  151. LLSkipMapNode *mCurrentOperatingp;
  152. S32 mLevel;
  153. BOOL (*mInsertFirst)(const INDEX_TYPE &first, const INDEX_TYPE &second);
  154. BOOL (*mEquals)(const INDEX_TYPE &first, const INDEX_TYPE &second);
  155. S32 mNumberOfSteps;
  156. };
  157. //////////////////////////////////////////////////
  158. //
  159. // LLSkipMap implementation
  160. //
  161. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  162. inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap()
  163. : mInsertFirst(NULL),
  164. mEquals(defaultEquals)
  165. {
  166. // Skipmaps must have binary depth of at least 2
  167. cassert(BINARY_DEPTH >= 2);
  168. S32 i;
  169. for (i = 0; i < BINARY_DEPTH; i++)
  170. {
  171. mUpdate[i] = NULL;
  172. }
  173. mLevel = 1;
  174. mCurrentp = *(mHead.mForward);
  175. mCurrentOperatingp = *(mHead.mForward);
  176. }
  177. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  178. inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second),
  179. BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second))
  180. : mInsertFirst(insert_first),
  181. mEquals(equals)
  182. {
  183. // Skipmaps must have binary depth of at least 2
  184. cassert(BINARY_DEPTH >= 2);
  185. mLevel = 1;
  186. S32 i;
  187. for (i = 0; i < BINARY_DEPTH; i++)
  188. {
  189. mHead.mForward[i] = NULL;
  190. mUpdate[i] = NULL;
  191. }
  192. mCurrentp = *(mHead.mForward);
  193. mCurrentOperatingp = *(mHead.mForward);
  194. }
  195. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  196. inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::~LLSkipMap()
  197. {
  198. removeAllData();
  199. }
  200. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  201. inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second))
  202. {
  203. mInsertFirst = insert_first;
  204. }
  205. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  206. inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second))
  207. {
  208. mEquals = equals;
  209. }
  210. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  211. inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index, DATA_TYPE datap)
  212. {
  213. S32 level;
  214. LLSkipMapNode *current = &mHead;
  215. LLSkipMapNode *temp;
  216. // find the pointer one in front of the one we want
  217. if (mInsertFirst)
  218. {
  219. for (level = mLevel - 1; level >= 0; level--)
  220. {
  221. temp = *(current->mForward + level);
  222. while ( (temp)
  223. &&(mInsertFirst(temp->mIndex, index)))
  224. {
  225. current = temp;
  226. temp = *(current->mForward + level);
  227. }
  228. *(mUpdate + level) = current;
  229. }
  230. }
  231. else
  232. {
  233. for (level = mLevel - 1; level >= 0; level--)
  234. {
  235. temp = *(current->mForward + level);
  236. while ( (temp)
  237. &&(temp->mIndex < index))
  238. {
  239. current = temp;
  240. temp = *(current->mForward + level);
  241. }
  242. *(mUpdate + level) = current;
  243. }
  244. }
  245. // we're now just in front of where we want to be . . . take one step forward
  246. current = *current->mForward;
  247. // replace the existing data if a node is already there
  248. if ( (current)
  249. &&(mEquals(current->mIndex, index)))
  250. {
  251. current->mData = datap;
  252. return current->mData;
  253. }
  254. // now add the new node
  255. S32 newlevel;
  256. for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
  257. {
  258. if (rand() & 1)
  259. {
  260. break;
  261. }
  262. }
  263. LLSkipMapNode *snode = new LLSkipMapNode(index, datap);
  264. if (newlevel > mLevel)
  265. {
  266. mHead.mForward[mLevel] = NULL;
  267. mUpdate[mLevel] = &mHead;
  268. mLevel = newlevel;
  269. }
  270. for (level = 0; level < newlevel; level++)
  271. {
  272. snode->mForward[level] = mUpdate[level]->mForward[level];
  273. mUpdate[level]->mForward[level] = snode;
  274. }
  275. return snode->mData;
  276. }
  277. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  278. inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index)
  279. {
  280. S32 level;
  281. LLSkipMapNode *current = &mHead;
  282. LLSkipMapNode *temp;
  283. // find the pointer one in front of the one we want
  284. if (mInsertFirst)
  285. {
  286. for (level = mLevel - 1; level >= 0; level--)
  287. {
  288. temp = *(current->mForward + level);
  289. while ( (temp)
  290. &&(mInsertFirst(temp->mIndex, index)))
  291. {
  292. current = temp;
  293. temp = *(current->mForward + level);
  294. }
  295. *(mUpdate + level) = current;
  296. }
  297. }
  298. else
  299. {
  300. for (level = mLevel - 1; level >= 0; level--)
  301. {
  302. temp = *(current->mForward + level);
  303. while ( (temp)
  304. &&(temp->mIndex < index))
  305. {
  306. current = temp;
  307. temp = *(current->mForward + level);
  308. }
  309. *(mUpdate + level) = current;
  310. }
  311. }
  312. // we're now just in front of where we want to be . . . take one step forward
  313. current = *current->mForward;
  314. // now add the new node
  315. S32 newlevel;
  316. for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
  317. {
  318. if (rand() & 1)
  319. break;
  320. }
  321. LLSkipMapNode *snode = new LLSkipMapNode(index);
  322. if (newlevel > mLevel)
  323. {
  324. mHead.mForward[mLevel] = NULL;
  325. mUpdate[mLevel] = &mHead;
  326. mLevel = newlevel;
  327. }
  328. for (level = 0; level < newlevel; level++)
  329. {
  330. snode->mForward[level] = mUpdate[level]->mForward[level];
  331. mUpdate[level]->mForward[level] = snode;
  332. }
  333. return snode->mData;
  334. }
  335. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  336. inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index)
  337. {
  338. S32 level;
  339. LLSkipMapNode *current = &mHead;
  340. LLSkipMapNode *temp;
  341. mNumberOfSteps = 0;
  342. // find the pointer one in front of the one we want
  343. if (mInsertFirst)
  344. {
  345. for (level = mLevel - 1; level >= 0; level--)
  346. {
  347. temp = *(current->mForward + level);
  348. while ( (temp)
  349. &&(mInsertFirst(temp->mIndex, index)))
  350. {
  351. current = temp;
  352. temp = *(current->mForward + level);
  353. mNumberOfSteps++;
  354. }
  355. *(mUpdate + level) = current;
  356. }
  357. }
  358. else
  359. {
  360. for (level = mLevel - 1; level >= 0; level--)
  361. {
  362. temp = *(current->mForward + level);
  363. while ( (temp)
  364. &&(temp->mIndex < index))
  365. {
  366. current = temp;
  367. temp = *(current->mForward + level);
  368. mNumberOfSteps++;
  369. }
  370. *(mUpdate + level) = current;
  371. }
  372. }
  373. // we're now just in front of where we want to be . . . take one step forward
  374. current = *current->mForward;
  375. mNumberOfSteps++;
  376. if ( (current)
  377. &&(mEquals(current->mIndex, index)))
  378. {
  379. return current->mData;
  380. }
  381. // now add the new node
  382. S32 newlevel;
  383. for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
  384. {
  385. if (rand() & 1)
  386. break;
  387. }
  388. LLSkipMapNode *snode = new LLSkipMapNode(index);
  389. if (newlevel > mLevel)
  390. {
  391. mHead.mForward[mLevel] = NULL;
  392. mUpdate[mLevel] = &mHead;
  393. mLevel = newlevel;
  394. }
  395. for (level = 0; level < newlevel; level++)
  396. {
  397. snode->mForward[level] = mUpdate[level]->mForward[level];
  398. mUpdate[level]->mForward[level] = snode;
  399. }
  400. return snode->mData;
  401. }
  402. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  403. inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::operator[](const INDEX_TYPE &index)
  404. {
  405. return getData(index);
  406. }
  407. // If index present, returns data.
  408. // If index not present, adds <index,NULL> and returns NULL.
  409. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  410. inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index, BOOL &b_new_entry)
  411. {
  412. S32 level;
  413. LLSkipMapNode *current = &mHead;
  414. LLSkipMapNode *temp;
  415. mNumberOfSteps = 0;
  416. // find the pointer one in front of the one we want
  417. if (mInsertFirst)
  418. {
  419. for (level = mLevel - 1; level >= 0; level--)
  420. {
  421. temp = *(current->mForward + level);
  422. while ( (temp)
  423. &&(mInsertFirst(temp->mIndex, index)))
  424. {
  425. current = temp;
  426. temp = *(current->mForward + level);
  427. mNumberOfSteps++;
  428. }
  429. *(mUpdate + level) = current;
  430. }
  431. }
  432. else
  433. {
  434. for (level = mLevel - 1; level >= 0; level--)
  435. {
  436. temp = *(current->mForward + level);
  437. while ( (temp)
  438. &&(temp->mIndex < index))
  439. {
  440. current = temp;
  441. temp = *(current->mForward + level);
  442. mNumberOfSteps++;
  443. }
  444. *(mUpdate + level) = current;
  445. }
  446. }
  447. // we're now just in front of where we want to be . . . take one step forward
  448. mNumberOfSteps++;
  449. current = *current->mForward;
  450. if ( (current)
  451. &&(mEquals(current->mIndex, index)))
  452. {
  453. return current->mData;
  454. }
  455. b_new_entry = TRUE;
  456. addData(index);
  457. return current->mData;
  458. }
  459. // Returns TRUE if data present in map.
  460. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  461. inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkData(const INDEX_TYPE &index)
  462. {
  463. S32 level;
  464. LLSkipMapNode *current = &mHead;
  465. LLSkipMapNode *temp;
  466. // find the pointer one in front of the one we want
  467. if (mInsertFirst)
  468. {
  469. for (level = mLevel - 1; level >= 0; level--)
  470. {
  471. temp = *(current->mForward + level);
  472. while ( (temp)
  473. &&(mInsertFirst(temp->mIndex, index)))
  474. {
  475. current = temp;
  476. temp = *(current->mForward + level);
  477. }
  478. *(mUpdate + level) = current;
  479. }
  480. }
  481. else
  482. {
  483. for (level = mLevel - 1; level >= 0; level--)
  484. {
  485. temp = *(current->mForward + level);
  486. while ( (temp)
  487. &&(temp->mIndex < index))
  488. {
  489. current = temp;
  490. temp = *(current->mForward + level);
  491. }
  492. *(mUpdate + level) = current;
  493. }
  494. }
  495. // we're now just in front of where we want to be . . . take one step forward
  496. current = *current->mForward;
  497. if (current)
  498. {
  499. // Gets rid of some compiler ambiguity for the LLPointer<> templated class.
  500. if (current->mData)
  501. {
  502. return mEquals(current->mIndex, index);
  503. }
  504. }
  505. return FALSE;
  506. }
  507. // Returns TRUE if key is present in map. This is useful if you
  508. // are potentially storing NULL pointers in the map
  509. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  510. inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkKey(const INDEX_TYPE &index)
  511. {
  512. S32 level;
  513. LLSkipMapNode *current = &mHead;
  514. LLSkipMapNode *temp;
  515. // find the pointer one in front of the one we want
  516. if (mInsertFirst)
  517. {
  518. for (level = mLevel - 1; level >= 0; level--)
  519. {
  520. temp = *(current->mForward + level);
  521. while ( (temp)
  522. &&(mInsertFirst(temp->mIndex, index)))
  523. {
  524. current = temp;
  525. temp = *(current->mForward + level);
  526. }
  527. *(mUpdate + level) = current;
  528. }
  529. }
  530. else
  531. {
  532. for (level = mLevel - 1; level >= 0; level--)
  533. {
  534. temp = *(current->mForward + level);
  535. while ( (temp)
  536. &&(temp->mIndex < index))
  537. {
  538. current = temp;
  539. temp = *(current->mForward + level);
  540. }
  541. *(mUpdate + level) = current;
  542. }
  543. }
  544. // we're now just in front of where we want to be . . . take one step forward
  545. current = *current->mForward;
  546. if (current)
  547. {
  548. return mEquals(current->mIndex, index);
  549. }
  550. return FALSE;
  551. }
  552. // If there, returns the data.
  553. // If not, returns NULL.
  554. // Never adds entries to the map.
  555. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  556. inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getIfThere(const INDEX_TYPE &index)
  557. {
  558. S32 level;
  559. LLSkipMapNode *current = &mHead;
  560. LLSkipMapNode *temp;
  561. mNumberOfSteps = 0;
  562. // find the pointer one in front of the one we want
  563. if (mInsertFirst)
  564. {
  565. for (level = mLevel - 1; level >= 0; level--)
  566. {
  567. temp = *(current->mForward + level);
  568. while ( (temp)
  569. &&(mInsertFirst(temp->mIndex, index)))
  570. {
  571. current = temp;
  572. temp = *(current->mForward + level);
  573. mNumberOfSteps++;
  574. }
  575. *(mUpdate + level) = current;
  576. }
  577. }
  578. else
  579. {
  580. for (level = mLevel - 1; level >= 0; level--)
  581. {
  582. temp = *(current->mForward + level);
  583. while ( (temp)
  584. &&(temp->mIndex < index))
  585. {
  586. current = temp;
  587. temp = *(current->mForward + level);
  588. mNumberOfSteps++;
  589. }
  590. *(mUpdate + level) = current;
  591. }
  592. }
  593. // we're now just in front of where we want to be . . . take one step forward
  594. mNumberOfSteps++;
  595. current = *current->mForward;
  596. if (current)
  597. {
  598. if (mEquals(current->mIndex, index))
  599. {
  600. return current->mData;
  601. }
  602. }
  603. // Avoid Linux compiler warning on returning NULL.
  604. return DATA_TYPE();
  605. }
  606. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  607. inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::reverseLookup(const DATA_TYPE datap)
  608. {
  609. LLSkipMapNode *current = &mHead;
  610. while (current)
  611. {
  612. if (datap == current->mData)
  613. {
  614. return current->mIndex;
  615. }
  616. current = *current->mForward;
  617. }
  618. // not found! return NULL
  619. return INDEX_TYPE();
  620. }
  621. // returns number of items in the list
  622. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  623. inline S32 LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getLength()
  624. {
  625. U32 length = 0;
  626. for (LLSkipMapNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
  627. {
  628. length++;
  629. }
  630. return length;
  631. }
  632. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  633. inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeData(const INDEX_TYPE &index)
  634. {
  635. S32 level;
  636. LLSkipMapNode *current = &mHead;
  637. LLSkipMapNode *temp;
  638. // find the pointer one in front of the one we want
  639. if (mInsertFirst)
  640. {
  641. for (level = mLevel - 1; level >= 0; level--)
  642. {
  643. temp = *(current->mForward + level);
  644. while ( (temp)
  645. &&(mInsertFirst(temp->mIndex, index)))
  646. {
  647. current = temp;
  648. temp = *(current->mForward + level);
  649. }
  650. *(mUpdate + level) = current;
  651. }
  652. }
  653. else
  654. {
  655. for (level = mLevel - 1; level >= 0; level--)
  656. {
  657. temp = *(current->mForward + level);
  658. while ( (temp)
  659. &&(temp->mIndex < index))
  660. {
  661. current = temp;
  662. temp = *(current->mForward + level);
  663. }
  664. *(mUpdate + level) = current;
  665. }
  666. }
  667. // we're now just in front of where we want to be . . . take one step forward
  668. current = *current->mForward;
  669. if (!current)
  670. {
  671. // empty list or beyond the end!
  672. return FALSE;
  673. }
  674. // is this the one we want?
  675. if (!mEquals(current->mIndex, index))
  676. {
  677. // nope!
  678. return FALSE;
  679. }
  680. else
  681. {
  682. // do we need to fix current or currentop?
  683. if (current == mCurrentp)
  684. {
  685. mCurrentp = *current->mForward;
  686. }
  687. if (current == mCurrentOperatingp)
  688. {
  689. mCurrentOperatingp = *current->mForward;
  690. }
  691. // yes it is! change pointers as required
  692. for (level = 0; level < mLevel; level++)
  693. {
  694. if (*((*(mUpdate + level))->mForward + level) != current)
  695. {
  696. // cool, we've fixed all the pointers!
  697. break;
  698. }
  699. *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
  700. }
  701. delete current;
  702. // clean up mHead
  703. while ( (mLevel > 1)
  704. &&(!*(mHead.mForward + mLevel - 1)))
  705. {
  706. mLevel--;
  707. }
  708. }
  709. return TRUE;
  710. }
  711. // remove all nodes from the list but do not delete data
  712. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  713. void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeAllData()
  714. {
  715. LLSkipMapNode *temp;
  716. // reset mCurrentp
  717. mCurrentp = *(mHead.mForward);
  718. while (mCurrentp)
  719. {
  720. temp = mCurrentp->mForward[0];
  721. delete mCurrentp;
  722. mCurrentp = temp;
  723. }
  724. S32 i;
  725. for (i = 0; i < BINARY_DEPTH; i++)
  726. {
  727. mHead.mForward[i] = NULL;
  728. mUpdate[i] = NULL;
  729. }
  730. mCurrentp = *(mHead.mForward);
  731. mCurrentOperatingp = *(mHead.mForward);
  732. }
  733. // place mCurrentp on first node
  734. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  735. inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::resetList()
  736. {
  737. mCurrentp = *(mHead.mForward);
  738. mCurrentOperatingp = *(mHead.mForward);
  739. }
  740. // return the data currently pointed to
  741. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  742. inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
  743. {
  744. if (mCurrentOperatingp)
  745. {
  746. return mCurrentOperatingp->mData;
  747. }
  748. else
  749. {
  750. return DATA_TYPE();
  751. }
  752. }
  753. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  754. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  755. inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentData()
  756. {
  757. if (mCurrentp)
  758. {
  759. mCurrentOperatingp = mCurrentp;
  760. mCurrentp = mCurrentp->mForward[0];
  761. return mCurrentOperatingp->mData;
  762. }
  763. else
  764. {
  765. // Basic types, like int, have default constructors that initialize
  766. // them to zero. g++ 2.95 supports this. "int()" is zero.
  767. // This also is nice for LLUUID()
  768. return DATA_TYPE();
  769. }
  770. }
  771. // same as getCurrentData() but a more intuitive name for the operation
  772. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  773. inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextData()
  774. {
  775. if (mCurrentp)
  776. {
  777. mCurrentOperatingp = mCurrentp;
  778. mCurrentp = mCurrentp->mForward[0];
  779. return mCurrentOperatingp->mData;
  780. }
  781. else
  782. {
  783. // Basic types, like int, have default constructors that initialize
  784. // them to zero. g++ 2.95 supports this. "int()" is zero.
  785. // This also is nice for LLUUID()
  786. return DATA_TYPE();
  787. }
  788. }
  789. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  790. inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextKey()
  791. {
  792. if (mCurrentp)
  793. {
  794. mCurrentOperatingp = mCurrentp;
  795. mCurrentp = mCurrentp->mForward[0];
  796. return mCurrentOperatingp->mIndex;
  797. }
  798. else
  799. {
  800. return mHead.mIndex;
  801. }
  802. }
  803. // return the key currently pointed to
  804. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  805. inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
  806. {
  807. if (mCurrentOperatingp)
  808. {
  809. return mCurrentOperatingp->mIndex;
  810. }
  811. else
  812. {
  813. // See comment for getNextData()
  814. return INDEX_TYPE();
  815. }
  816. }
  817. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  818. inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::notDone() const
  819. {
  820. if (mCurrentOperatingp)
  821. {
  822. return TRUE;
  823. }
  824. else
  825. {
  826. return FALSE;
  827. }
  828. }
  829. // remove the Node at mCurentOperatingp
  830. // leave mCurrentp and mCurentOperatingp on the next entry
  831. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  832. inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
  833. {
  834. if (mCurrentOperatingp)
  835. {
  836. removeData(mCurrentOperatingp->mIndex);
  837. }
  838. }
  839. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  840. inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
  841. {
  842. if (mCurrentOperatingp)
  843. {
  844. deleteData(mCurrentOperatingp->mIndex);
  845. }
  846. }
  847. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  848. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  849. inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstData()
  850. {
  851. mCurrentp = *(mHead.mForward);
  852. mCurrentOperatingp = *(mHead.mForward);
  853. if (mCurrentp)
  854. {
  855. mCurrentOperatingp = mCurrentp;
  856. mCurrentp = mCurrentp->mForward[0];
  857. return mCurrentOperatingp->mData;
  858. }
  859. else
  860. {
  861. // See comment for getNextData()
  862. return DATA_TYPE();
  863. }
  864. }
  865. template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
  866. inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstKey()
  867. {
  868. mCurrentp = *(mHead.mForward);
  869. mCurrentOperatingp = *(mHead.mForward);
  870. if (mCurrentp)
  871. {
  872. mCurrentOperatingp = mCurrentp;
  873. mCurrentp = mCurrentp->mForward[0];
  874. return mCurrentOperatingp->mIndex;
  875. }
  876. else
  877. {
  878. return mHead.mIndex;
  879. }
  880. }
  881. #endif