Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. map.hxx
  6. Author:
  7. Benjamin Leis (benl) 11/13/95
  8. Revision History:
  9. --*/
  10. #ifndef _MAP
  11. #define _MAP
  12. #define MAP_STACK_SIZE 40
  13. //+---------------------------------------------------------------------------
  14. //
  15. // Class: CMap ()
  16. //
  17. // Purpose:
  18. //
  19. // Interface: CMap --
  20. // ~CMap --
  21. // Insert -- insert a key and item into map
  22. // Replace -- replaces a key's data or inserts it if is not in
  23. // the map already
  24. // Remove --
  25. // Lookup --
  26. // DeleteAll -- removes all the entries in the map and sets it to
  27. // empty
  28. // Lookup --
  29. // Enum --
  30. // DeleteNode --
  31. // pRoot --
  32. //
  33. // History: 12-05-1996 benl Created
  34. // 12-18-1997 benl modified
  35. //
  36. // Notes: works by copying values not be reference - so need constructors
  37. // / destructors
  38. //
  39. //----------------------------------------------------------------------------
  40. template <class T, class S> class CMapIter;
  41. template <class T, class S> class CMap {
  42. public:
  43. friend CMapIter<T,S>;
  44. CMap(void);
  45. ~CMap(void);
  46. void Insert(const T & tKey, const S & sItem);
  47. void Replace(const T & tkey, const S& sItem);
  48. BOOL Remove(const T & tKey);
  49. BOOL Lookup(const T & tKey, S & sItem) const;
  50. void DeleteAll();
  51. // Second style of lookup
  52. S * Lookup(const T & tKey);
  53. CMapIter<T,S> * Enum();
  54. protected:
  55. class CNode {
  56. public:
  57. CNode(const T & t, const S & s) {
  58. tKey = t;
  59. sData = s;
  60. pLeft = NULL;
  61. pRight = NULL;
  62. bDeleted = FALSE;
  63. }
  64. CNode() {
  65. pLeft = NULL;
  66. pRight = NULL;
  67. bDeleted = FALSE;
  68. }
  69. CNode * pLeft;
  70. CNode * pRight;
  71. T tKey;
  72. S sData;
  73. BOOL bDeleted;
  74. };
  75. void DeleteNode(CNode * pNode);
  76. CNode * pRoot;
  77. };
  78. //+---------------------------------------------------------------------------
  79. //
  80. // Class: CMapIter ()
  81. //
  82. // Purpose:
  83. //
  84. // Interface: CMapIter --
  85. // ~CMapIter --
  86. // Next --
  87. // _nodeStack --
  88. // _iTop --
  89. // _nodeDummy --
  90. //
  91. // History: 2-13-1997 benl Created
  92. //
  93. // Notes:
  94. //
  95. //----------------------------------------------------------------------------
  96. template <class T, class S> class CMapIter {
  97. public:
  98. CMapIter ( CMap<T,S>::CNode * pRoot);
  99. ~CMapIter();
  100. BOOLEAN Next(T & t, S & s);
  101. private:
  102. //data
  103. CMap<T,S>::CNode * _nodeStack[MAP_STACK_SIZE];
  104. INT _iTop;
  105. CMap<T,S>::CNode _nodeDummy;
  106. };
  107. //+---------------------------------------------------------------------------
  108. //
  109. // Member: CMapIter::CMapiter
  110. //
  111. // Synopsis: Constructor
  112. //
  113. // Arguments: [pRoot] --
  114. //
  115. // Returns:
  116. //
  117. // History: 7-10-1997 benl Created
  118. //
  119. // Notes: called by CMap and given root to traverse
  120. //
  121. //----------------------------------------------------------------------------
  122. template <class T, class S>
  123. CMapIter<T,S>::CMapIter(CMap<T,S>::CNode * pRoot)
  124. {
  125. _iTop = 0;
  126. _nodeStack[_iTop] = pRoot;
  127. while (_nodeStack[_iTop]->pLeft != NULL) {
  128. // assert(_iTop < MAP_STACK_SIZE);
  129. _nodeStack[_iTop + 1] = _nodeStack[_iTop]->pLeft;
  130. _iTop++;
  131. }
  132. //add a dummy node at the bottom
  133. // assert(_iTop < MAP_STACK_SIZE);
  134. _nodeStack[_iTop + 1] = &_nodeDummy;
  135. _iTop++;
  136. } // ::CNode
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Member: ::~CMapIter
  140. //
  141. // Synopsis:
  142. //
  143. // Arguments: (none)
  144. //
  145. // Returns:
  146. //
  147. // History: 2-13-1997 benl Created
  148. //
  149. // Notes:
  150. //
  151. //----------------------------------------------------------------------------
  152. template <class T, class S>
  153. CMapIter<T,S>::~CMapIter()
  154. {
  155. } //::~CMapIter
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Member: ::Next
  159. //
  160. // Synopsis:
  161. //
  162. // Arguments: [t] --
  163. // [s] --
  164. //
  165. // Returns:
  166. //
  167. // History: 2-13-1997 benl Created
  168. //
  169. // Notes:
  170. //
  171. //----------------------------------------------------------------------------
  172. template <class T, class S>
  173. BOOLEAN CMapIter<T,S>::Next(T & t, S & s)
  174. {
  175. CMap<T,S>::CNode * pTemp;
  176. if (_nodeStack[_iTop]->pRight != NULL) {
  177. //go to the leftmostest item below
  178. _nodeStack[_iTop] = _nodeStack[_iTop]->pRight;
  179. while (_nodeStack[_iTop]->pLeft != NULL) {
  180. // assert(_iTop < MAP_STACK_SIZE);
  181. _nodeStack[_iTop + 1] = _nodeStack[_iTop]->pLeft;
  182. _iTop++;
  183. }
  184. } else if (_iTop != 0) {
  185. // o.w backtrack up one level
  186. _iTop--;
  187. } else {
  188. //o.w we're done
  189. return FALSE;
  190. }
  191. //if current element is deleted recurse
  192. if (_nodeStack[_iTop]->bDeleted) {
  193. return Next(t, s);
  194. } else {
  195. t = _nodeStack[_iTop]->tKey;
  196. s = _nodeStack[_iTop]->sData;
  197. return TRUE;
  198. }
  199. } //::Next
  200. //+---------------------------------------------------------------------------
  201. //
  202. // Member: CMap::CMap
  203. //
  204. // Synopsis:
  205. //
  206. // Arguments: (none)
  207. //
  208. // Returns:
  209. //
  210. // History: 12-05-1996 benl Created
  211. //
  212. // Notes:
  213. //
  214. //----------------------------------------------------------------------------
  215. template<class T, class S>
  216. inline CMap<T,S>::CMap(void)
  217. {
  218. pRoot = NULL;
  219. } //::CMap
  220. //+---------------------------------------------------------------------------
  221. //
  222. // Member: ::DeleteNode
  223. //
  224. // Synopsis:
  225. //
  226. // Arguments: [pNode] --
  227. //
  228. // Returns:
  229. //
  230. // History: 12-05-1996 benl Created
  231. //
  232. // Notes:
  233. //
  234. //----------------------------------------------------------------------------
  235. template<class T, class S>
  236. inline void CMap<T,S>::DeleteNode(CNode * pNode)
  237. {
  238. if (pNode != NULL) {
  239. DeleteNode(pNode->pLeft);
  240. DeleteNode(pNode->pRight);
  241. delete pNode;
  242. }
  243. } //::DeleteNode
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Member: ::~CMap
  247. //
  248. // Synopsis:
  249. //
  250. // Arguments: (none)
  251. //
  252. // Returns:
  253. //
  254. // History: 12-05-1996 benl Created
  255. //
  256. // Notes:
  257. //
  258. //----------------------------------------------------------------------------
  259. template<class T, class S>
  260. inline CMap<T,S>::~CMap(void)
  261. {
  262. // printf("map destruct %x\n", this);
  263. DeleteAll();
  264. } //::~CMap
  265. //+---------------------------------------------------------------------------
  266. //
  267. // Member: ::Insert
  268. //
  269. // Synopsis:
  270. //
  271. // Arguments: [tKey] --
  272. // [sData] --
  273. //
  274. // Returns:
  275. //
  276. // History: 12-05-1996 benl Created
  277. //
  278. // Notes:
  279. //
  280. //----------------------------------------------------------------------------
  281. template<class T, class S>
  282. inline void CMap<T,S>::Insert(const T & tKey, const S & sData)
  283. {
  284. CNode * pnodeTemp = pRoot;
  285. if (pRoot == NULL)
  286. pRoot = new CNode(tKey,sData);
  287. else {
  288. while (pnodeTemp != NULL) {
  289. if (pnodeTemp->tKey <= tKey) {
  290. if (pnodeTemp->pRight == NULL) {
  291. pnodeTemp->pRight = new CNode(tKey,sData);
  292. return;
  293. } else pnodeTemp = pnodeTemp->pRight;
  294. } else {
  295. if (pnodeTemp->pLeft == NULL) {
  296. pnodeTemp->pLeft = new CNode(tKey,sData);
  297. return;
  298. } else pnodeTemp = pnodeTemp->pLeft;
  299. }
  300. } //endwhile
  301. } //endif
  302. } //::Insert
  303. //+---------------------------------------------------------------------------
  304. //
  305. // Member: ::Replace
  306. //
  307. // Synopsis: if the key exits replace its data with the new data
  308. // o.w just insert it
  309. //
  310. // Arguments: [tKey] -- the key to search for
  311. // [sData] -- the new data
  312. //
  313. // Returns: always succeeds
  314. //
  315. // History: 12-05-1996 benl Created
  316. //
  317. // Notes:
  318. //
  319. //----------------------------------------------------------------------------
  320. template<class T, class S>
  321. inline void CMap<T,S>::Replace(const T & tKey, const S & sData)
  322. {
  323. CNode * pnodeTemp = pRoot;
  324. if (pRoot == NULL) {
  325. pRoot = new CNode(tKey,sData);
  326. } else {
  327. while (pnodeTemp != NULL) {
  328. //match - so replace its data
  329. if (pnodeTemp->tKey == tKey && !pnodeTemp->bDeleted) {
  330. pnodeTemp->sData = sData;
  331. return;
  332. }
  333. //recurse right
  334. else if (pnodeTemp->tKey < tKey) {
  335. if (NULL == pnodeTemp->pRight) {
  336. pnodeTemp->pRight = new CNode(tKey,sData);
  337. return;
  338. } else pnodeTemp = pnodeTemp->pRight;
  339. }
  340. //recurse left
  341. else {
  342. if (NULL == pnodeTemp->pLeft) {
  343. pnodeTemp->pLeft = new CNode(tKey,sData);
  344. return;
  345. } else pnodeTemp = pnodeTemp->pLeft;
  346. }
  347. } //endwhile
  348. } //endif
  349. } //::Replace
  350. //+---------------------------------------------------------------------------
  351. //
  352. // Member: ::Remove
  353. //
  354. // Synopsis:
  355. //
  356. // Arguments: [tKey] --
  357. //
  358. // Returns:
  359. //
  360. // History: 12-05-1996 benl Created
  361. //
  362. // Notes:
  363. //
  364. //----------------------------------------------------------------------------
  365. template<class T, class S>
  366. inline BOOL CMap<T,S>::Remove(const T & tKey)
  367. {
  368. CNode * pnodeTemp = pRoot;
  369. CNode * pnodeParent = NULL;
  370. CNode * pnodeOrphan = NULL;
  371. if (pRoot == NULL)
  372. return FALSE;
  373. else {
  374. while (pnodeTemp != NULL) {
  375. if (pnodeTemp->tKey == tKey && (pnodeTemp->bDeleted == FALSE)) {
  376. if (pnodeParent == NULL) {
  377. //
  378. // deleting the root
  379. //
  380. if (pnodeTemp->pLeft != NULL) {
  381. pRoot = pnodeTemp->pLeft;
  382. pnodeOrphan = pnodeTemp->pRight;
  383. } else {
  384. pRoot = pnodeTemp->pRight;
  385. pnodeOrphan = pnodeTemp->pLeft;
  386. }
  387. } else {
  388. //
  389. // deleting an interor node
  390. //
  391. if (pnodeParent->pLeft == pnodeTemp) {
  392. pnodeParent->pLeft = pnodeTemp->pRight;
  393. pnodeOrphan = pnodeTemp->pLeft;
  394. } else {
  395. pnodeParent->pRight = pnodeTemp->pLeft;
  396. pnodeOrphan = pnodeTemp->pRight;
  397. }
  398. }
  399. delete pnodeTemp;
  400. //
  401. // re-insert the orphan
  402. //
  403. if (pnodeOrphan != NULL) {
  404. pnodeTemp = pRoot;
  405. while (pnodeTemp != NULL) {
  406. if (pnodeTemp->tKey <= pnodeOrphan->tKey) {
  407. if (pnodeTemp->pRight == NULL) {
  408. pnodeTemp->pRight = pnodeOrphan;
  409. break;
  410. } else pnodeTemp = pnodeTemp->pRight;
  411. } else {
  412. if (pnodeTemp->pLeft == NULL) {
  413. pnodeTemp->pLeft = pnodeOrphan;
  414. break;
  415. } else pnodeTemp = pnodeTemp->pLeft;
  416. }
  417. } //endwhile
  418. }
  419. return TRUE;
  420. } else if (pnodeTemp->tKey < tKey) {
  421. pnodeParent = pnodeTemp;
  422. pnodeTemp = pnodeTemp->pRight;
  423. } else {
  424. pnodeParent = pnodeTemp;
  425. pnodeTemp = pnodeTemp->pLeft;
  426. }
  427. } //endwhile
  428. } //endif
  429. return FALSE;
  430. } //::Remove
  431. //+---------------------------------------------------------------------------
  432. //
  433. // Member: ::Lookup
  434. //
  435. // Synopsis:
  436. //
  437. // Arguments: [tKey] --
  438. // [sItem] --
  439. //
  440. // Returns:
  441. //
  442. // History: 12-05-1996 benl Created
  443. //
  444. // Notes:
  445. //
  446. //----------------------------------------------------------------------------
  447. template<class T, class S>
  448. inline BOOL CMap<T,S>::Lookup(const T & tKey, S & sItem) const
  449. {
  450. CNode * pnodeTemp = pRoot;
  451. if (pRoot == NULL)
  452. return FALSE;
  453. else {
  454. while (pnodeTemp != NULL) {
  455. if (pnodeTemp->tKey == tKey && pnodeTemp->bDeleted == FALSE) {
  456. sItem = pnodeTemp->sData;
  457. return TRUE;
  458. } else if (pnodeTemp->tKey <= tKey) {
  459. pnodeTemp = pnodeTemp->pRight;
  460. } else {
  461. pnodeTemp = pnodeTemp->pLeft;
  462. }
  463. } //endwhile
  464. } //endif
  465. return FALSE;
  466. } //::Lookup
  467. //+---------------------------------------------------------------------------
  468. //
  469. // Member: ::Lookup
  470. //
  471. // Synopsis:
  472. //
  473. // Arguments: [tKey] --
  474. //
  475. // Returns:
  476. //
  477. // History: 12-05-1996 benl Created
  478. //
  479. // Notes:
  480. //
  481. //----------------------------------------------------------------------------
  482. template<class T, class S>
  483. inline S * CMap<T,S>::Lookup(const T & tKey)
  484. {
  485. CNode * pnodeTemp = pRoot;
  486. if (pRoot == NULL)
  487. return NULL;
  488. else {
  489. while (pnodeTemp != NULL) {
  490. if (pnodeTemp->tKey == tKey && pnodeTemp->bDeleted == FALSE) {
  491. return &(pnodeTemp->sData);
  492. } else if (pnodeTemp->tKey < tKey) {
  493. pnodeTemp = pnodeTemp->pRight;
  494. } else {
  495. pnodeTemp = pnodeTemp->pLeft;
  496. }
  497. } //endwhile
  498. } //endif
  499. return NULL;
  500. } //::Lookup
  501. //+---------------------------------------------------------------------------
  502. //
  503. // Member: ::Enum
  504. //
  505. // Synopsis: returns the iterator
  506. //
  507. // Arguments: (none)
  508. //
  509. // Returns: iterator or null if map is empty
  510. //
  511. // History: 2-13-1997 benl Created
  512. //
  513. // Notes:
  514. //
  515. //----------------------------------------------------------------------------
  516. template<class T, class S>
  517. inline CMapIter<T,S> * CMap<T,S>::Enum()
  518. {
  519. if (pRoot) {
  520. return new CMapIter<T,S>(pRoot);
  521. } else {
  522. return NULL;
  523. }
  524. } //::Enum
  525. //+---------------------------------------------------------------------------
  526. //
  527. // Member: ::DeleteAll
  528. //
  529. // Synopsis: NonRecursive delete
  530. //
  531. // Arguments: (none)
  532. //
  533. // Returns:
  534. //
  535. // History: 12-18-1997 benl Created
  536. //
  537. // Notes: Cleans up the entire tree and sets it to empty
  538. // Does it nonrecursively but swiveling ptrs around
  539. //
  540. //----------------------------------------------------------------------------
  541. template <class T, class S>
  542. inline void CMap<T,S>::DeleteAll()
  543. {
  544. CNode * pParent = 0;
  545. CNode * pNext = 0;
  546. CNode * pCurrent = pRoot;
  547. while (pCurrent) {
  548. //advance next to left and the set the left back to parent
  549. pNext = pCurrent->pLeft;
  550. pCurrent->pLeft = pParent;
  551. //If there is a left child move onto it
  552. //else if there is a right child move to it
  553. //o.w move up thru left ptr and delete current node
  554. if (pNext) {
  555. pParent = pCurrent;
  556. pCurrent = pNext;
  557. } else if (pCurrent->pRight) {
  558. pParent = pCurrent;
  559. pCurrent = pCurrent->pRight;
  560. pParent->pRight = 0;
  561. } else {
  562. //this is really a move up back the parent is now in pLeft
  563. pParent = pCurrent->pLeft;
  564. delete pCurrent;
  565. pCurrent = pParent;
  566. if (pCurrent) {
  567. pParent = pCurrent->pLeft;
  568. pCurrent->pLeft = 0;
  569. }
  570. }
  571. }
  572. pRoot = NULL;
  573. } // ::DeleteAll
  574. #endif