listwrappers.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. #ifndef _listwrappers_h_
  2. #define _listwrappers_h_
  3. //////////////////////////////////////////////////////////////////////////////
  4. //
  5. // ListEventSource
  6. //
  7. //////////////////////////////////////////////////////////////////////////////
  8. class ListEventSource
  9. {
  10. TRef<EventSourceImpl> m_peventSource;
  11. public:
  12. ListEventSource()
  13. : m_peventSource(new EventSourceImpl()) {};
  14. ListEventSource(const ListEventSource& les)
  15. : m_peventSource(les.m_peventSource) {};
  16. void operator () ()
  17. { m_peventSource->Trigger(); };
  18. virtual IEventSource* GetEvent()
  19. {
  20. return m_peventSource;
  21. }
  22. };
  23. //////////////////////////////////////////////////////////////////////////////
  24. //
  25. // Slist_utlListWrapper
  26. //
  27. //////////////////////////////////////////////////////////////////////////////
  28. // these could be implemented much more efficently if it's useful to do so
  29. template <class T>
  30. class Slist_utlListWrapper : public List, public Slist_utl<T, ListEventSource> {
  31. public:
  32. typedef Slink_utl<T, ListEventSource> Link;
  33. virtual int GetCount()
  34. {
  35. // review: we could change this to O(1)
  36. int nCount = 0;
  37. // VSNet 2003 port: resolve error C2475
  38. #if _MSC_VER >= 1300
  39. for (Slink_utl<T, ListEventSource>* link = first(); link != NULL; link = (link->next)())
  40. #else
  41. for (Slink_utl<T, ListEventSource>* link = first(); link != NULL; link = link->next)
  42. #endif
  43. nCount++;
  44. return nCount;
  45. }
  46. virtual ItemID GetItem(int index)
  47. {
  48. return (*this)[index];
  49. }
  50. virtual int GetIndex(ItemID pitem)
  51. {
  52. int nIndex = 0;
  53. // VSNet 2003 port: resolve error C2475
  54. #if _MSC_VER >= 1300
  55. for (Link* link = first(); link != NULL; link = (link->next)())
  56. #else
  57. for (Link* link = first(); link != NULL; link = link->next)
  58. #endif
  59. {
  60. if ((ItemID)link == pitem)
  61. return nIndex;
  62. nIndex++;
  63. }
  64. return -1;
  65. }
  66. virtual ItemID GetNext(ItemID pitem)
  67. {
  68. return ((Link*)pitem)->next();
  69. }
  70. virtual IEventSource* GetChangedEvent()
  71. {
  72. return sink.GetEvent();
  73. }
  74. };
  75. //////////////////////////////////////////////////////////////////////////////
  76. //
  77. // IntItemIDWrapper
  78. //
  79. //////////////////////////////////////////////////////////////////////////////
  80. // unfortunately, ID=0 corresponds to NULL, so we can't use the default casts
  81. // between ItemID and things like ShipID, since 0 is a valid ShipID
  82. template <class T>
  83. class IntItemIDWrapper
  84. {
  85. T m_t;
  86. enum { ZeroValue = ~(1 << (sizeof(T)*8 - 2)) };
  87. public:
  88. IntItemIDWrapper() {}
  89. IntItemIDWrapper(T t) : m_t(t) {}
  90. IntItemIDWrapper(ItemID pitem) { m_t = ((int)pitem == ZeroValue) ? 0 : (T)pitem; }
  91. operator = (T t) { m_t = t; }
  92. operator T () { return m_t; }
  93. operator ItemID () { return (ItemID)((m_t == 0) ? (T)ZeroValue : m_t); };
  94. bool operator == (IntItemIDWrapper<T> t) const { return m_t == t; }
  95. bool operator <= (IntItemIDWrapper<T> t) const { return m_t <= t; }
  96. bool operator >= (IntItemIDWrapper<T> t) const { return m_t >= t; }
  97. bool operator < (IntItemIDWrapper<T> t) const { return m_t < t; }
  98. bool operator > (IntItemIDWrapper<T> t) const { return m_t > t; }
  99. };
  100. //////////////////////////////////////////////////////////////////////////////
  101. //
  102. // TListListWrapper
  103. //
  104. //////////////////////////////////////////////////////////////////////////////
  105. // these could be implemented much more efficently if it's useful to do so
  106. template <
  107. class T,
  108. class EqualsType = DefaultEquals,
  109. class CompareType = DefaultNoCompare
  110. >
  111. class TListListWrapper : public List, public TList<T, EqualsType, CompareType, ListEventSource> {
  112. public:
  113. TListListWrapper()
  114. {
  115. }
  116. TListListWrapper(EqualsType equals, CompareType compare)
  117. : TList<T, EqualsType, CompareType, ListEventSource>(equals, compare)
  118. {
  119. }
  120. virtual int GetCount()
  121. {
  122. return TList<T, EqualsType, CompareType, ListEventSource>::GetCount();
  123. }
  124. virtual ItemID GetItem(int index)
  125. {
  126. if (index < 0 || index >= GetCount())
  127. return NULL;
  128. else
  129. return (ItemID)((*this)[index]);
  130. }
  131. virtual int GetIndex(ItemID pitem)
  132. {
  133. // review: returning the key may be more efficient than returning the value.
  134. int nIndex = 0;
  135. for (Iterator iter(*this); !iter.End(); iter.Next())
  136. {
  137. if ((ItemID)iter.Value() == pitem)
  138. return nIndex;
  139. nIndex++;
  140. }
  141. return -1;
  142. }
  143. virtual ItemID GetNext(ItemID pitem)
  144. {
  145. for (Iterator iter(*this); !iter.End(); iter.Next())
  146. {
  147. if ((ItemID)iter.Value() == pitem)
  148. {
  149. iter.Next();
  150. if (iter.End())
  151. return NULL;
  152. else
  153. return (ItemID)iter.Value();
  154. }
  155. }
  156. return NULL;
  157. }
  158. virtual IEventSource* GetChangedEvent()
  159. {
  160. return GetSink().GetEvent();
  161. }
  162. };
  163. //////////////////////////////////////////////////////////////////////////////
  164. //
  165. // TMapListWrapper
  166. //
  167. //////////////////////////////////////////////////////////////////////////////
  168. // these could be implemented much more efficently if it's useful to do so
  169. template <class T, class U>
  170. class TMapListWrapper : public List, public TMap<T, U, ListEventSource> {
  171. public:
  172. virtual int GetCount()
  173. {
  174. return Count();
  175. }
  176. virtual ItemID GetItem(int index)
  177. {
  178. Iterator iter(*this);
  179. for (int currentIndex = 0; !iter.End() && currentIndex < index; currentIndex++)
  180. {
  181. iter.Next();
  182. }
  183. if (iter.End())
  184. return NULL;
  185. else
  186. return (ItemID)iter.Value();
  187. }
  188. virtual int GetIndex(ItemID pitem)
  189. {
  190. // review: returning the key may be more efficient than returning the value.
  191. int nIndex = 0;
  192. for (Iterator iter(*this); !iter.End(); iter.Next())
  193. {
  194. if ((ItemID)iter.Value() == pitem)
  195. return nIndex;
  196. nIndex++;
  197. }
  198. return -1;
  199. }
  200. virtual ItemID GetNext(ItemID pitem)
  201. {
  202. for (Iterator iter(*this); !iter.End(); iter.Next())
  203. {
  204. if ((ItemID)iter.Value() == pitem)
  205. {
  206. iter.Next();
  207. if (iter.End())
  208. return NULL;
  209. else
  210. return (ItemID)iter.Value();
  211. }
  212. }
  213. return NULL;
  214. }
  215. virtual IEventSource* GetChangedEvent()
  216. {
  217. return GetSink().GetEvent();
  218. }
  219. };
  220. ///////////////////////////////////////////////////////////////////////////////
  221. //
  222. // FilteredList
  223. //
  224. ///////////////////////////////////////////////////////////////////////////////
  225. template <class Filter>
  226. class FilteredList : public List
  227. {
  228. TRef<List> m_list;
  229. Filter m_filter;
  230. public:
  231. FilteredList(List* list)
  232. : m_list(list) {};
  233. FilteredList(List* list, Filter filter)
  234. : m_list(list), m_filter(filter) {};
  235. void SetFilter(Filter filter)
  236. {
  237. m_filter = filter;
  238. }
  239. virtual int GetCount()
  240. {
  241. // this could be O(n) if we hooked the "changed" event
  242. int nCount = 0;
  243. ItemID currentItem = m_list->GetItem(0);
  244. while (currentItem != NULL)
  245. {
  246. if (m_filter(currentItem))
  247. nCount++;
  248. currentItem = m_list->GetNext(currentItem);
  249. }
  250. return nCount;
  251. }
  252. virtual ItemID GetItem(int index)
  253. {
  254. int nCurrentIndex = 0;
  255. ItemID currentItem = m_list->GetItem(0);
  256. while (currentItem != NULL)
  257. {
  258. if (m_filter(currentItem))
  259. {
  260. if (nCurrentIndex == index)
  261. break;
  262. else
  263. nCurrentIndex++;
  264. }
  265. currentItem = m_list->GetNext(currentItem);
  266. }
  267. return currentItem;
  268. }
  269. virtual int GetIndex(ItemID pitem)
  270. {
  271. // review: returning the key may be more efficient than returning the value.
  272. int nIndex = 0;
  273. ItemID currentItem = m_list->GetItem(0);
  274. while (currentItem != NULL)
  275. {
  276. if (m_filter(currentItem))
  277. {
  278. if (currentItem == pitem)
  279. return nIndex;
  280. else
  281. nIndex++;
  282. }
  283. currentItem = m_list->GetNext(currentItem);
  284. }
  285. return -1;
  286. }
  287. virtual ItemID GetNext(ItemID pitem)
  288. {
  289. ItemID currentItem = m_list->GetNext(pitem);
  290. while (currentItem != NULL)
  291. {
  292. if (m_filter(currentItem))
  293. {
  294. return currentItem;
  295. }
  296. currentItem = m_list->GetNext(currentItem);
  297. }
  298. return NULL;
  299. }
  300. virtual IEventSource* GetChangedEvent()
  301. {
  302. return m_list->GetChangedEvent();
  303. }
  304. };
  305. ///////////////////////////////////////////////////////////////////////////////
  306. //
  307. // ListDelegate
  308. //
  309. ///////////////////////////////////////////////////////////////////////////////
  310. class ListDelegate : public List
  311. {
  312. private:
  313. List* m_plist;
  314. TRef<IObject> m_pcontainer;
  315. public:
  316. ListDelegate(List* plist, IObject* pcontainer = NULL)
  317. : m_plist(plist), m_pcontainer(pcontainer) {}
  318. virtual int GetCount()
  319. {
  320. return m_plist->GetCount();
  321. }
  322. virtual ItemID GetItem(int index)
  323. {
  324. return m_plist->GetItem(index);
  325. }
  326. virtual int GetIndex(ItemID pitem)
  327. {
  328. return m_plist->GetIndex(pitem);
  329. }
  330. virtual ItemID GetNext(ItemID pitem)
  331. {
  332. return m_plist->GetNext(pitem);
  333. }
  334. virtual IEventSource* GetChangedEvent()
  335. {
  336. return m_plist->GetChangedEvent();
  337. }
  338. };
  339. ///////////////////////////////////////////////////////////////////////////////
  340. //
  341. // ConcatinatedList
  342. //
  343. ///////////////////////////////////////////////////////////////////////////////
  344. class ConcatinatedList : public List, public IEventSink
  345. {
  346. TRef<List> m_list1;
  347. TRef<List> m_list2;
  348. ListEventSource m_pfnChanged;
  349. TRef<IEventSink> m_sinkDelegate;
  350. public:
  351. ConcatinatedList(List* list1, List* list2)
  352. : m_list1(list1), m_list2(list2)
  353. {
  354. // add this to the changed notifications of the sublists
  355. m_sinkDelegate = IEventSink::CreateDelegate(this);
  356. m_list1->GetChangedEvent()->AddSink(m_sinkDelegate);
  357. m_list2->GetChangedEvent()->AddSink(m_sinkDelegate);
  358. };
  359. ~ConcatinatedList()
  360. {
  361. m_list1->GetChangedEvent()->RemoveSink(m_sinkDelegate);
  362. m_list2->GetChangedEvent()->RemoveSink(m_sinkDelegate);
  363. }
  364. virtual int GetCount()
  365. {
  366. return m_list1->GetCount() + m_list2->GetCount();
  367. }
  368. virtual ItemID GetItem(int index)
  369. {
  370. int nList1Count = m_list1->GetCount();
  371. if (index < nList1Count)
  372. return m_list1->GetItem(index);
  373. else
  374. return m_list2->GetItem(index - nList1Count);
  375. }
  376. virtual int GetIndex(ItemID pitem)
  377. {
  378. int index = m_list1->GetIndex(pitem);
  379. if (index == -1)
  380. {
  381. index = m_list2->GetIndex(pitem);
  382. if (index != -1)
  383. index += m_list1->GetCount();
  384. }
  385. return index;
  386. }
  387. virtual ItemID GetNext(ItemID pitem)
  388. {
  389. // case 1: pitem and pitem->next are in list1
  390. ItemID next = m_list1->GetNext(pitem);
  391. if (next == NULL)
  392. {
  393. // case 2: pitem and pitem->next are in list2
  394. next = m_list2->GetNext(pitem);
  395. if ((next == NULL) && (m_list1->GetIndex(pitem) != -1))
  396. {
  397. // case 3: pitem is in list1, pitem next is in list2
  398. next = m_list2->GetItem(0);
  399. }
  400. }
  401. return next;
  402. }
  403. virtual IEventSource* GetChangedEvent()
  404. {
  405. return m_pfnChanged.GetEvent();
  406. }
  407. virtual bool OnEvent(IEventSource* pevent)
  408. {
  409. m_pfnChanged();
  410. return true;
  411. }
  412. };
  413. ///////////////////////////////////////////////////////////////////////////////
  414. //
  415. // SortedList
  416. //
  417. ///////////////////////////////////////////////////////////////////////////////
  418. typedef bool (*ItemIDCompareFunction)(ItemID id1, ItemID id2);
  419. template <class CompareFunctionType>
  420. class SortedList : public List, public IEventSink
  421. {
  422. // a sorted list of the items in question
  423. typedef TList<ItemID, DefaultEquals, CompareFunctionType> SortedListType;
  424. SortedListType m_listSorted;
  425. TRef<List> m_list;
  426. bool m_fNeedsSort;
  427. ListEventSource m_pfnChanged;
  428. TRef<IEventSink> m_sinkDelegate;
  429. void CheckSorting()
  430. {
  431. if (m_fNeedsSort)
  432. {
  433. m_listSorted.SetEmpty();
  434. // use an insertion sort - O(n^2), but it's a stable sort
  435. ItemID pitem = m_list->GetItem(0);
  436. while (pitem) {
  437. m_listSorted.InsertSorted(pitem);
  438. pitem = m_list->GetNext(pitem);
  439. }
  440. m_fNeedsSort = false;
  441. }
  442. }
  443. public:
  444. SortedList(List* list, CompareFunctionType fnCompare)
  445. : m_list(list), m_listSorted(DefaultEquals(), fnCompare), m_fNeedsSort(true)
  446. {
  447. // add this to the changed notifications of the unsorted list
  448. m_sinkDelegate = IEventSink::CreateDelegate(this);
  449. m_list->GetChangedEvent()->AddSink(m_sinkDelegate);
  450. };
  451. ~SortedList()
  452. {
  453. m_list->GetChangedEvent()->RemoveSink(m_sinkDelegate);
  454. }
  455. virtual int GetCount()
  456. {
  457. return m_list->GetCount();
  458. }
  459. virtual ItemID GetItem(int index)
  460. {
  461. CheckSorting();
  462. SortedListType::Iterator iter(m_listSorted);
  463. for (int currentIndex = 0; !iter.End() && currentIndex < index; currentIndex++)
  464. {
  465. iter.Next();
  466. }
  467. if (iter.End())
  468. return NULL;
  469. else
  470. return (ItemID)iter.Value();
  471. }
  472. virtual int GetIndex(ItemID pitem)
  473. {
  474. CheckSorting();
  475. int nIndex = 0;
  476. for (SortedListType::Iterator iter(m_listSorted); !iter.End(); iter.Next())
  477. {
  478. if ((ItemID)iter.Value() == pitem)
  479. return nIndex;
  480. nIndex++;
  481. }
  482. return -1;
  483. }
  484. virtual ItemID GetNext(ItemID pitem)
  485. {
  486. CheckSorting();
  487. for (SortedListType::Iterator iter(m_listSorted); !iter.End(); iter.Next())
  488. {
  489. if ((ItemID)iter.Value() == pitem)
  490. {
  491. iter.Next();
  492. if (iter.End())
  493. return NULL;
  494. else
  495. return (ItemID)iter.Value();
  496. }
  497. }
  498. return NULL;
  499. }
  500. virtual IEventSource* GetChangedEvent()
  501. {
  502. return m_pfnChanged.GetEvent();
  503. }
  504. virtual bool OnEvent(IEventSource* pevent)
  505. {
  506. m_fNeedsSort = true;
  507. m_pfnChanged();
  508. return true;
  509. }
  510. };
  511. ///////////////////////////////////////////////////////////////////////////////
  512. //
  513. // SingletonList
  514. //
  515. ///////////////////////////////////////////////////////////////////////////////
  516. class SingletonList : public List
  517. {
  518. ListEventSource m_pfnChanged;
  519. ItemID m_itemID;
  520. public:
  521. SingletonList(ItemID itemID = NULL)
  522. : m_itemID(itemID)
  523. {
  524. }
  525. void SetItem(ItemID itemID)
  526. {
  527. m_itemID = itemID;
  528. m_pfnChanged();
  529. }
  530. //
  531. // List interface:
  532. //
  533. virtual int GetCount()
  534. {
  535. return 1;
  536. }
  537. virtual ItemID GetItem(int index)
  538. {
  539. if (index == 0)
  540. return m_itemID;
  541. else
  542. return NULL;
  543. }
  544. virtual int GetIndex(ItemID pitem)
  545. {
  546. if (pitem = m_itemID)
  547. return 0;
  548. else
  549. return -1;
  550. }
  551. virtual ItemID GetNext(ItemID pitem)
  552. {
  553. return NULL;
  554. }
  555. virtual IEventSource* GetChangedEvent()
  556. {
  557. return m_pfnChanged.GetEvent();
  558. }
  559. };
  560. #endif