bstcommon.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /*
  2. * Copyright 2001 Adrian Thurston <thurston@cs.queensu.ca>
  3. */
  4. /* This file is part of Aapl.
  5. *
  6. * Aapl is free software; you can redistribute it and/or modify it under the
  7. * terms of the GNU Lesser General Public License as published by the Free
  8. * Software Foundation; either version 2.1 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
  12. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
  18. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. /* This header is not wrapped in ifndefs because it is
  21. * not intended to be included by users directly. */
  22. #ifdef AAPL_NAMESPACE
  23. namespace Aapl {
  24. #endif
  25. /* Binary Search Table */
  26. template < BST_TEMPL_DECLARE > class BstTable :
  27. public Compare,
  28. public Vector< Element, Resize >
  29. {
  30. typedef Vector<Element, Resize> BaseVector;
  31. typedef Table<Element> BaseTable;
  32. public:
  33. /**
  34. * \brief Default constructor.
  35. *
  36. * Create an empty binary search table.
  37. */
  38. BstTable() { }
  39. /**
  40. * \brief Construct with initial value.
  41. *
  42. * Constructs a binary search table with an initial item. Uses the default
  43. * constructor for initializing Value.
  44. */
  45. BstTable(const Key &key)
  46. { insert(key); }
  47. #if defined( BSTMAP )
  48. /**
  49. * \brief Construct with initial value.
  50. *
  51. * Constructs a binary search table with an initial key/value pair.
  52. */
  53. BstTable(const Key &key, const Value &val)
  54. { insert(key, val); }
  55. #endif
  56. #if ! defined( BSTSET )
  57. /**
  58. * \brief Construct with initial value.
  59. *
  60. * Constructs a binary search table with an initial Element.
  61. */
  62. BstTable(const Element &el)
  63. { insert(el); }
  64. #endif
  65. Element *insert(const Key &key, Element **lastFound = 0);
  66. Element *insertMulti(const Key &key);
  67. bool insert(const BstTable &other);
  68. void insertMulti(const BstTable &other);
  69. #if defined( BSTMAP )
  70. Element *insert(const Key &key, const Value &val,
  71. Element **lastFound = 0);
  72. Element *insertMulti(const Key &key, const Value &val );
  73. #endif
  74. #if ! defined( BSTSET )
  75. Element *insert(const Element &el, Element **lastFound = 0);
  76. Element *insertMulti(const Element &el);
  77. #endif
  78. Element *find(const Key &key, Element **lastFound = 0) const;
  79. bool findMulti( const Key &key, Element *&lower,
  80. Element *&upper ) const;
  81. bool remove(const Key &key);
  82. bool remove(Element *item);
  83. long removeMulti(const Key &key);
  84. long removeMulti(Element *lower, Element *upper);
  85. /* The following provide access to the underlying insert and remove
  86. * functions that my be hidden by the BST insert and remove. The insertDup
  87. * and insertNew functions will never be hidden. They are provided for
  88. * consistency. The difference between the non-shared and the shared
  89. * tables is the documentation reference to the invoked function. */
  90. #if !defined( SHARED_BST )
  91. /*@{*/
  92. /** \brief Call the insert of the underlying vector.
  93. *
  94. * Provides to access to the vector insert, which may become hidden. Care
  95. * should be taken to ensure that after the insert the ordering of
  96. * elements is preserved.
  97. * Invokes Vector::insert( long pos, const T &val ).
  98. */
  99. void vinsert(long pos, const Element &val)
  100. { Vector< Element, Resize >::insert( pos, &val, 1 ); }
  101. /** \brief Call the insert of the underlying vector.
  102. *
  103. * Provides to access to the vector insert, which may become hidden. Care
  104. * should be taken to ensure that after the insert the ordering of
  105. * elements is preserved.
  106. * Invokes Vector::insert( long pos, const T *val, long len ).
  107. */
  108. void vinsert(long pos, const Element *val, long len)
  109. { Vector< Element, Resize >::insert( pos, val, len ); }
  110. /** \brief Call the insert of the underlying vector.
  111. *
  112. * Provides to access to the vector insert, which may become hidden. Care
  113. * should be taken to ensure that after the insert the ordering of
  114. * elements is preserved.
  115. * Invokes Vector::insert( long pos, const Vector &v ).
  116. */
  117. void vinsert(long pos, const BstTable &v)
  118. { Vector< Element, Resize >::insert( pos, v.data, v.tabLen ); }
  119. /*@}*/
  120. /*@{*/
  121. /** \brief Call the remove of the underlying vector.
  122. *
  123. * Provides access to the vector remove, which may become hidden.
  124. * Invokes Vector::remove( long pos ).
  125. */
  126. void vremove(long pos)
  127. { Vector< Element, Resize >::remove( pos, 1 ); }
  128. /** \brief Call the remove of the underlying vector.
  129. *
  130. * Proves access to the vector remove, which may become hidden.
  131. * Invokes Vector::remove( long pos, long len ).
  132. */
  133. void vremove(long pos, long len)
  134. { Vector< Element, Resize >::remove( pos, len ); }
  135. /*@}*/
  136. #else /* SHARED_BST */
  137. /*@{*/
  138. /** \brief Call the insert of the underlying vector.
  139. *
  140. * Provides to access to the vector insert, which may become hidden. Care
  141. * should be taken to ensure that after the insert the ordering of
  142. * elements is preserved.
  143. * Invokes SVector::insert( long pos, const T &val ).
  144. */
  145. void vinsert(long pos, const Element &val)
  146. { Vector< Element, Resize >::insert( pos, &val, 1 ); }
  147. /** \brief Call the insert of the underlying vector.
  148. *
  149. * Provides to access to the vector insert, which may become hidden. Care
  150. * should be taken to ensure that after the insert the ordering of
  151. * elements is preserved.
  152. * Invokes SVector::insert( long pos, const T *val, long len ).
  153. */
  154. void vinsert(long pos, const Element *val, long len)
  155. { Vector< Element, Resize >::insert( pos, val, len ); }
  156. /** \brief Call the insert of the underlying vector.
  157. *
  158. * Provides to access to the vector insert, which may become hidden. Care
  159. * should be taken to ensure that after the insert the ordering of
  160. * elements is preserved.
  161. * Invokes SVector::insert( long pos, const SVector &v ).
  162. */
  163. void vinsert(long pos, const BstTable &v)
  164. { Vector< Element, Resize >::insert( pos, v.data, v.length() ); }
  165. /*@}*/
  166. /*@{*/
  167. /** \brief Call the remove of the underlying vector.
  168. *
  169. * Provides access to the vector remove, which may become hidden.
  170. * Invokes SVector::remove( long pos ).
  171. */
  172. void vremove(long pos)
  173. { Vector< Element, Resize >::remove( pos, 1 ); }
  174. /** \brief Call the remove of the underlying vector.
  175. *
  176. * Proves access to the vector remove, which may become hidden.
  177. * Invokes SVector::remove( long pos, long len ).
  178. */
  179. void vremove(long pos, long len)
  180. { Vector< Element, Resize >::remove( pos, len ); }
  181. /*@}*/
  182. #endif /* SHARED_BST */
  183. };
  184. #if 0
  185. #if defined( SHARED_BST )
  186. /**
  187. * \brief Construct a binary search table with an initial amount of
  188. * allocation.
  189. *
  190. * The table is initialized to have room for allocLength elements. The
  191. * table starts empty.
  192. */
  193. template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
  194. BstTable( long allocLen )
  195. {
  196. /* Allocate the space if we are given a positive allocLen. */
  197. if ( allocLen > 0 ) {
  198. /* Allocate the data needed. */
  199. STabHead *head = (STabHead*)
  200. malloc( sizeof(STabHead) + sizeof(Element) * allocLen );
  201. if ( head == 0 )
  202. throw std::bad_alloc();
  203. /* Set up the header and save the data pointer. */
  204. head->refCount = 1;
  205. head->allocLen = allocLen;
  206. head->tabLen = 0;
  207. BaseTable::data = (Element*) (head + 1);
  208. }
  209. }
  210. #else
  211. /**
  212. * \brief Construct a binary search table with an initial amount of
  213. * allocation.
  214. *
  215. * The table is initialized to have room for allocLength elements. The
  216. * table starts empty.
  217. */
  218. template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
  219. BstTable( long allocLen )
  220. {
  221. /* Allocate the space if we are given a positive allocLen. */
  222. BaseTable::allocLen = allocLen;
  223. if ( BaseTable::allocLen > 0 ) {
  224. BaseTable::data = (Element*) malloc(sizeof(Element) * BaseTable::allocLen);
  225. if ( BaseTable::data == NULL )
  226. throw std::bad_alloc();
  227. }
  228. }
  229. #endif
  230. #endif
  231. /**
  232. * \brief Find the element with the given key and remove it.
  233. *
  234. * If multiple elements with the given key exist, then it is unspecified which
  235. * element will be removed.
  236. *
  237. * \returns True if an element is found and consequently removed, false
  238. * otherwise.
  239. */
  240. template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
  241. remove(const Key &key)
  242. {
  243. Element *el = find(key);
  244. if ( el != 0 ) {
  245. Vector< Element >::remove(el - BaseTable::data);
  246. return true;
  247. }
  248. return false;
  249. }
  250. /**
  251. * \brief Remove the element pointed to by item.
  252. *
  253. * If item does not point to an element in the tree, then undefined behaviour
  254. * results. If item is null, then remove has no effect.
  255. *
  256. * \returns True if item is not null, false otherwise.
  257. */
  258. template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
  259. remove( Element *item )
  260. {
  261. if ( item != 0 ) {
  262. Vector< Element >::remove(item - BaseTable::data);
  263. return true;
  264. }
  265. return false;
  266. }
  267. /**
  268. * \brief Find and remove the entire range of elements with the given key.
  269. *
  270. * \returns The number of elements removed.
  271. */
  272. template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
  273. removeMulti(const Key &key)
  274. {
  275. Element *low, *high;
  276. if ( findMulti(key, low, high) ) {
  277. /* Get the length of the range. */
  278. long num = high - low + 1;
  279. Vector< Element >::remove(low - BaseTable::data, num);
  280. return num;
  281. }
  282. return 0;
  283. }
  284. template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
  285. removeMulti(Element *lower, Element *upper)
  286. {
  287. /* Get the length of the range. */
  288. long num = upper - lower + 1;
  289. Vector< Element >::remove(lower - BaseTable::data, num);
  290. return num;
  291. }
  292. /**
  293. * \brief Find a range of elements with the given key.
  294. *
  295. * If any elements with the given key exist then lower and upper are set to
  296. * the low and high ends of the continous range of elements with the key.
  297. * Lower and upper will point to the first and last elements with the key.
  298. *
  299. * \returns True if any elements are found, false otherwise.
  300. */
  301. template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
  302. findMulti(const Key &key, Element *&low, Element *&high ) const
  303. {
  304. const Element *lower, *mid, *upper;
  305. long keyRelation;
  306. const long tblLen = BaseTable::length();
  307. if ( BaseTable::data == 0 )
  308. return false;
  309. lower = BaseTable::data;
  310. upper = BaseTable::data + tblLen - 1;
  311. while ( true ) {
  312. if ( upper < lower ) {
  313. /* Did not find the fd in the array. */
  314. return false;
  315. }
  316. mid = lower + ((upper-lower)>>1);
  317. keyRelation = this->compare(key, GET_KEY(*mid));
  318. if ( keyRelation < 0 )
  319. upper = mid - 1;
  320. else if ( keyRelation > 0 )
  321. lower = mid + 1;
  322. else {
  323. Element *lowEnd = BaseTable::data - 1;
  324. Element *highEnd = BaseTable::data + tblLen;
  325. lower = mid - 1;
  326. while ( lower != lowEnd &&
  327. this->compare(key, GET_KEY(*lower)) == 0 )
  328. lower--;
  329. upper = mid + 1;
  330. while ( upper != highEnd &&
  331. this->compare(key, GET_KEY(*upper)) == 0 )
  332. upper++;
  333. low = (Element*)lower + 1;
  334. high = (Element*)upper - 1;
  335. return true;
  336. }
  337. }
  338. }
  339. /**
  340. * \brief Find an element with the given key.
  341. *
  342. * If the find succeeds then lastFound is set to the element found. If the
  343. * find fails then lastFound is set the location where the key would be
  344. * inserted. If there is more than one element in the tree with the given key,
  345. * then it is unspecified which element is returned as the match.
  346. *
  347. * \returns The element found on success, null on failure.
  348. */
  349. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  350. find( const Key &key, Element **lastFound ) const
  351. {
  352. const Element *lower, *mid, *upper;
  353. long keyRelation;
  354. const long tblLen = BaseTable::length();
  355. if ( BaseTable::data == 0 )
  356. return 0;
  357. lower = BaseTable::data;
  358. upper = BaseTable::data + tblLen - 1;
  359. while ( true ) {
  360. if ( upper < lower ) {
  361. /* Did not find the key. Last found gets the insert location. */
  362. if ( lastFound != 0 )
  363. *lastFound = (Element*)lower;
  364. return 0;
  365. }
  366. mid = lower + ((upper-lower)>>1);
  367. keyRelation = this->compare(key, GET_KEY(*mid));
  368. if ( keyRelation < 0 )
  369. upper = mid - 1;
  370. else if ( keyRelation > 0 )
  371. lower = mid + 1;
  372. else {
  373. /* Key is found. Last found gets the found record. */
  374. if ( lastFound != 0 )
  375. *lastFound = (Element*)mid;
  376. return (Element*)mid;
  377. }
  378. }
  379. }
  380. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  381. insert(const Key &key, Element **lastFound)
  382. {
  383. const Element *lower, *mid, *upper;
  384. long keyRelation, insertPos;
  385. const long tblLen = BaseTable::length();
  386. if ( tblLen == 0 ) {
  387. /* If the table is empty then go straight to insert. */
  388. lower = BaseTable::data;
  389. goto insert;
  390. }
  391. lower = BaseTable::data;
  392. upper = BaseTable::data + tblLen - 1;
  393. while ( true ) {
  394. if ( upper < lower ) {
  395. /* Did not find the key in the array.
  396. * Place to insert at is lower. */
  397. goto insert;
  398. }
  399. mid = lower + ((upper-lower)>>1);
  400. keyRelation = this->compare(key, GET_KEY(*mid));
  401. if ( keyRelation < 0 )
  402. upper = mid - 1;
  403. else if ( keyRelation > 0 )
  404. lower = mid + 1;
  405. else {
  406. if ( lastFound != 0 )
  407. *lastFound = (Element*)mid;
  408. return 0;
  409. }
  410. }
  411. insert:
  412. /* Get the insert pos. */
  413. insertPos = lower - BaseTable::data;
  414. /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
  415. BaseVector::makeRawSpaceFor(insertPos, 1);
  416. new(BaseTable::data + insertPos) Element(key);
  417. /* Set lastFound */
  418. if ( lastFound != 0 )
  419. *lastFound = BaseTable::data + insertPos;
  420. return BaseTable::data + insertPos;
  421. }
  422. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  423. insertMulti(const Key &key)
  424. {
  425. const Element *lower, *mid, *upper;
  426. long keyRelation, insertPos;
  427. const long tblLen = BaseTable::length();
  428. if ( tblLen == 0 ) {
  429. /* If the table is empty then go straight to insert. */
  430. lower = BaseTable::data;
  431. goto insert;
  432. }
  433. lower = BaseTable::data;
  434. upper = BaseTable::data + tblLen - 1;
  435. while ( true ) {
  436. if ( upper < lower ) {
  437. /* Did not find the key in the array.
  438. * Place to insert at is lower. */
  439. goto insert;
  440. }
  441. mid = lower + ((upper-lower)>>1);
  442. keyRelation = compare(key, GET_KEY(*mid));
  443. if ( keyRelation < 0 )
  444. upper = mid - 1;
  445. else if ( keyRelation > 0 )
  446. lower = mid + 1;
  447. else {
  448. lower = mid;
  449. goto insert;
  450. }
  451. }
  452. insert:
  453. /* Get the insert pos. */
  454. insertPos = lower - BaseTable::data;
  455. /* Do the insert. */
  456. BaseVector::makeRawSpaceFor(insertPos, 1);
  457. new(BaseTable::data + insertPos) Element(key);
  458. /* Return the element inserted. */
  459. return BaseTable::data + insertPos;
  460. }
  461. /**
  462. * \brief Insert each element from other.
  463. *
  464. * Always attempts to insert all elements even if the insert of some item from
  465. * other fails.
  466. *
  467. * \returns True if all items inserted successfully, false if any insert
  468. * failed.
  469. */
  470. template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
  471. insert(const BstTable &other)
  472. {
  473. bool allSuccess = true;
  474. long otherLen = other.length();
  475. for ( long i = 0; i < otherLen; i++ ) {
  476. Element *el = insert( other.data[i] );
  477. if ( el == 0 )
  478. allSuccess = false;
  479. }
  480. return allSuccess;
  481. }
  482. /**
  483. * \brief Insert each element from other even if the elements exist already.
  484. *
  485. * No individual insertMulti can fail.
  486. */
  487. template <BST_TEMPL_DEF> void BstTable<BST_TEMPL_USE>::
  488. insertMulti(const BstTable &other)
  489. {
  490. long otherLen = other.length();
  491. for ( long i = 0; i < otherLen; i++ )
  492. insertMulti( other.data[i] );
  493. }
  494. #if ! defined( BSTSET )
  495. /**
  496. * \brief Insert the given element.
  497. *
  498. * If the key in the given element does not already exist in the table then a
  499. * new element is inserted. They element copy constructor is used to place the
  500. * element into the table. If lastFound is given, it is set to the new element
  501. * created. If the insert fails then lastFound is set to the existing element
  502. * of the same key.
  503. *
  504. * \returns The new element created upon success, null upon failure.
  505. */
  506. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  507. insert(const Element &el, Element **lastFound )
  508. {
  509. const Element *lower, *mid, *upper;
  510. long keyRelation, insertPos;
  511. const long tblLen = BaseTable::length();
  512. if ( tblLen == 0 ) {
  513. /* If the table is empty then go straight to insert. */
  514. lower = BaseTable::data;
  515. goto insert;
  516. }
  517. lower = BaseTable::data;
  518. upper = BaseTable::data + tblLen - 1;
  519. while ( true ) {
  520. if ( upper < lower ) {
  521. /* Did not find the key in the array.
  522. * Place to insert at is lower. */
  523. goto insert;
  524. }
  525. mid = lower + ((upper-lower)>>1);
  526. keyRelation = compare(GET_KEY(el), GET_KEY(*mid));
  527. if ( keyRelation < 0 )
  528. upper = mid - 1;
  529. else if ( keyRelation > 0 )
  530. lower = mid + 1;
  531. else {
  532. if ( lastFound != 0 )
  533. *lastFound = (Element*)mid;
  534. return 0;
  535. }
  536. }
  537. insert:
  538. /* Get the insert pos. */
  539. insertPos = lower - BaseTable::data;
  540. /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
  541. BaseVector::makeRawSpaceFor(insertPos, 1);
  542. new(BaseTable::data + insertPos) Element(el);
  543. /* Set lastFound */
  544. if ( lastFound != 0 )
  545. *lastFound = BaseTable::data + insertPos;
  546. return BaseTable::data + insertPos;
  547. }
  548. /**
  549. * \brief Insert the given element even if it exists already.
  550. *
  551. * If the key in the given element exists already then the new element is
  552. * placed next to some other element of the same key. InsertMulti cannot fail.
  553. * The element copy constructor is used to place the element in the table.
  554. *
  555. * \returns The new element created.
  556. */
  557. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  558. insertMulti(const Element &el)
  559. {
  560. const Element *lower, *mid, *upper;
  561. long keyRelation, insertPos;
  562. const long tblLen = BaseTable::length();
  563. if ( tblLen == 0 ) {
  564. /* If the table is empty then go straight to insert. */
  565. lower = BaseTable::data;
  566. goto insert;
  567. }
  568. lower = BaseTable::data;
  569. upper = BaseTable::data + tblLen - 1;
  570. while ( true ) {
  571. if ( upper < lower ) {
  572. /* Did not find the fd in the array.
  573. * Place to insert at is lower. */
  574. goto insert;
  575. }
  576. mid = lower + ((upper-lower)>>1);
  577. keyRelation = this->compare(GET_KEY(el), GET_KEY(*mid));
  578. if ( keyRelation < 0 )
  579. upper = mid - 1;
  580. else if ( keyRelation > 0 )
  581. lower = mid + 1;
  582. else {
  583. lower = mid;
  584. goto insert;
  585. }
  586. }
  587. insert:
  588. /* Get the insert pos. */
  589. insertPos = lower - BaseTable::data;
  590. /* Do the insert. */
  591. BaseVector::makeRawSpaceFor(insertPos, 1);
  592. new(BaseTable::data + insertPos) Element(el);
  593. /* Return the element inserted. */
  594. return BaseTable::data + insertPos;
  595. }
  596. #endif
  597. #if defined( BSTMAP )
  598. /**
  599. * \brief Insert the given key-value pair.
  600. *
  601. * If the given key does not already exist in the table then the key-value
  602. * pair is inserted. Copy constructors are used to place the pair in the
  603. * table. If lastFound is given, it is set to the new entry created. If the
  604. * insert fails then lastFound is set to the existing pair of the same key.
  605. *
  606. * \returns The new element created upon success, null upon failure.
  607. */
  608. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  609. insert(const Key &key, const Value &val, Element **lastFound)
  610. {
  611. const Element *lower, *mid, *upper;
  612. long keyRelation, insertPos;
  613. const long tblLen = BaseTable::length();
  614. if ( tblLen == 0 ) {
  615. /* If the table is empty then go straight to insert. */
  616. lower = BaseTable::data;
  617. goto insert;
  618. }
  619. lower = BaseTable::data;
  620. upper = BaseTable::data + tblLen - 1;
  621. while ( true ) {
  622. if ( upper < lower ) {
  623. /* Did not find the fd in the array.
  624. * Place to insert at is lower. */
  625. goto insert;
  626. }
  627. mid = lower + ((upper-lower)>>1);
  628. keyRelation = Compare::compare(key, mid->key);
  629. if ( keyRelation < 0 )
  630. upper = mid - 1;
  631. else if ( keyRelation > 0 )
  632. lower = mid + 1;
  633. else {
  634. if ( lastFound != NULL )
  635. *lastFound = (Element*)mid;
  636. return 0;
  637. }
  638. }
  639. insert:
  640. /* Get the insert pos. */
  641. insertPos = lower - BaseTable::data;
  642. /* Do the insert. */
  643. BaseVector::makeRawSpaceFor(insertPos, 1);
  644. new(BaseTable::data + insertPos) Element(key, val);
  645. /* Set lastFound */
  646. if ( lastFound != NULL )
  647. *lastFound = BaseTable::data + insertPos;
  648. return BaseTable::data + insertPos;
  649. }
  650. /**
  651. * \brief Insert the given key-value pair even if the key exists already.
  652. *
  653. * If the key exists already then the key-value pair is placed next to some
  654. * other pair of the same key. InsertMulti cannot fail. Copy constructors are
  655. * used to place the pair in the table.
  656. *
  657. * \returns The new element created.
  658. */
  659. template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
  660. insertMulti(const Key &key, const Value &val)
  661. {
  662. const Element *lower, *mid, *upper;
  663. long keyRelation, insertPos;
  664. const long tblLen = BaseTable::length();
  665. if ( tblLen == 0 ) {
  666. /* If the table is empty then go straight to insert. */
  667. lower = BaseTable::data;
  668. goto insert;
  669. }
  670. lower = BaseTable::data;
  671. upper = BaseTable::data + tblLen - 1;
  672. while ( true ) {
  673. if ( upper < lower ) {
  674. /* Did not find the key in the array.
  675. * Place to insert at is lower. */
  676. goto insert;
  677. }
  678. mid = lower + ((upper-lower)>>1);
  679. keyRelation = Compare::compare(key, mid->key);
  680. if ( keyRelation < 0 )
  681. upper = mid - 1;
  682. else if ( keyRelation > 0 )
  683. lower = mid + 1;
  684. else {
  685. lower = mid;
  686. goto insert;
  687. }
  688. }
  689. insert:
  690. /* Get the insert pos. */
  691. insertPos = lower - BaseTable::data;
  692. /* Do the insert. */
  693. BaseVector::makeRawSpaceFor(insertPos, 1);
  694. new(BaseTable::data + insertPos) Element(key, val);
  695. /* Return the element inserted. */
  696. return BaseTable::data + insertPos;
  697. }
  698. #endif
  699. #ifdef AAPL_NAMESPACE
  700. }
  701. #endif