DS_OrderedList.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file DS_OrderedList.h
  11. /// \internal
  12. /// \brief Quicksort ordered list.
  13. ///
  14. #include "DS_List.h"
  15. #include "RakMemoryOverride.h"
  16. #include "Export.h"
  17. #ifndef __ORDERED_LIST_H
  18. #define __ORDERED_LIST_H
  19. /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
  20. /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
  21. namespace DataStructures
  22. {
  23. template <class key_type, class data_type>
  24. int defaultOrderedListComparison(const key_type &a, const data_type &b)
  25. {
  26. if (a<b) return -1; if (a==b) return 0; return 1;
  27. }
  28. /// \note IMPORTANT! If you use defaultOrderedListComparison then call IMPLEMENT_DEFAULT_COMPARISON or you will get an unresolved external linker error.
  29. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)=defaultOrderedListComparison<key_type, data_type> >
  30. class RAK_DLL_EXPORT OrderedList
  31. {
  32. public:
  33. static void IMPLEMENT_DEFAULT_COMPARISON(void) {DataStructures::defaultOrderedListComparison<key_type, data_type>(key_type(),data_type());}
  34. OrderedList();
  35. ~OrderedList();
  36. OrderedList( const OrderedList& original_copy );
  37. OrderedList& operator= ( const OrderedList& original_copy );
  38. /// comparisonFunction must take a key_type and a data_type and return <0, ==0, or >0
  39. /// If the data type has comparison operators already defined then you can just use defaultComparison
  40. bool HasData(const key_type &key, int (*cf)(const key_type&, const data_type&)=default_comparison_function) const;
  41. // GetIndexFromKey returns where the insert should go at the same time checks if it is there
  42. unsigned GetIndexFromKey(const key_type &key, bool *objectExists, int (*cf)(const key_type&, const data_type&)=default_comparison_function) const;
  43. data_type GetElementFromKey(const key_type &key, int (*cf)(const key_type&, const data_type&)=default_comparison_function) const;
  44. bool GetElementFromKey(const key_type &key, data_type &element, int (*cf)(const key_type&, const data_type&)=default_comparison_function) const;
  45. unsigned Insert(const key_type &key, const data_type &data, bool assertOnDuplicate, const char *file, unsigned int line, int (*cf)(const key_type&, const data_type&)=default_comparison_function);
  46. unsigned Remove(const key_type &key, int (*cf)(const key_type&, const data_type&)=default_comparison_function);
  47. unsigned RemoveIfExists(const key_type &key, int (*cf)(const key_type&, const data_type&)=default_comparison_function);
  48. data_type& operator[] ( const unsigned int position ) const;
  49. void RemoveAtIndex(const unsigned index);
  50. void InsertAtIndex(const data_type &data, const unsigned index, const char *file, unsigned int line);
  51. void InsertAtEnd(const data_type &data, const char *file, unsigned int line);
  52. void RemoveFromEnd(const unsigned num=1);
  53. void Clear(bool doNotDeallocate, const char *file, unsigned int line);
  54. unsigned Size(void) const;
  55. protected:
  56. DataStructures::List<data_type> orderedList;
  57. };
  58. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  59. OrderedList<key_type, data_type, default_comparison_function>::OrderedList()
  60. {
  61. }
  62. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  63. OrderedList<key_type, data_type, default_comparison_function>::~OrderedList()
  64. {
  65. Clear(false, _FILE_AND_LINE_);
  66. }
  67. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  68. OrderedList<key_type, data_type, default_comparison_function>::OrderedList( const OrderedList& original_copy )
  69. {
  70. orderedList=original_copy.orderedList;
  71. }
  72. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  73. OrderedList<key_type, data_type, default_comparison_function>& OrderedList<key_type, data_type, default_comparison_function>::operator= ( const OrderedList& original_copy )
  74. {
  75. orderedList=original_copy.orderedList;
  76. return *this;
  77. }
  78. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  79. bool OrderedList<key_type, data_type, default_comparison_function>::HasData(const key_type &key, int (*cf)(const key_type&, const data_type&)) const
  80. {
  81. bool objectExists;
  82. GetIndexFromKey(key, &objectExists, cf);
  83. return objectExists;
  84. }
  85. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  86. data_type OrderedList<key_type, data_type, default_comparison_function>::GetElementFromKey(const key_type &key, int (*cf)(const key_type&, const data_type&)) const
  87. {
  88. bool objectExists;
  89. unsigned index;
  90. index = GetIndexFromKey(key, &objectExists, cf);
  91. RakAssert(objectExists);
  92. return orderedList[index];
  93. }
  94. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  95. bool OrderedList<key_type, data_type, default_comparison_function>::GetElementFromKey(const key_type &key, data_type &element, int (*cf)(const key_type&, const data_type&)) const
  96. {
  97. bool objectExists;
  98. unsigned index;
  99. index = GetIndexFromKey(key, &objectExists, cf);
  100. if (objectExists)
  101. element = orderedList[index];
  102. return objectExists;
  103. }
  104. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  105. unsigned OrderedList<key_type, data_type, default_comparison_function>::GetIndexFromKey(const key_type &key, bool *objectExists, int (*cf)(const key_type&, const data_type&)) const
  106. {
  107. int index, upperBound, lowerBound;
  108. int res;
  109. if (orderedList.Size()==0)
  110. {
  111. *objectExists=false;
  112. return 0;
  113. }
  114. upperBound=(int)orderedList.Size()-1;
  115. lowerBound=0;
  116. index = (int)orderedList.Size()/2;
  117. #ifdef _MSC_VER
  118. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  119. #endif
  120. while (1)
  121. {
  122. res = cf(key,orderedList[index]);
  123. if (res==0)
  124. {
  125. *objectExists=true;
  126. return (unsigned)index;
  127. }
  128. else if (res<0)
  129. {
  130. upperBound=index-1;
  131. }
  132. else// if (res>0)
  133. {
  134. lowerBound=index+1;
  135. }
  136. index=lowerBound+(upperBound-lowerBound)/2;
  137. if (lowerBound>upperBound)
  138. {
  139. *objectExists=false;
  140. return (unsigned)lowerBound; // No match
  141. }
  142. if (index < 0 || index >= (int) orderedList.Size())
  143. {
  144. // This should never hit unless the comparison function was inconsistent
  145. RakAssert(index && 0);
  146. *objectExists=false;
  147. return 0;
  148. }
  149. }
  150. }
  151. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  152. unsigned OrderedList<key_type, data_type, default_comparison_function>::Insert(const key_type &key, const data_type &data, bool assertOnDuplicate, const char *file, unsigned int line, int (*cf)(const key_type&, const data_type&))
  153. {
  154. (void) assertOnDuplicate;
  155. bool objectExists;
  156. unsigned index;
  157. index = GetIndexFromKey(key, &objectExists, cf);
  158. // Don't allow duplicate insertion.
  159. if (objectExists)
  160. {
  161. // This is usually a bug!
  162. RakAssert(assertOnDuplicate==false);
  163. return (unsigned)-1;
  164. }
  165. if (index>=orderedList.Size())
  166. {
  167. orderedList.Insert(data, file, line);
  168. return orderedList.Size()-1;
  169. }
  170. else
  171. {
  172. orderedList.Insert(data,index, file, line);
  173. return index;
  174. }
  175. }
  176. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  177. unsigned OrderedList<key_type, data_type, default_comparison_function>::Remove(const key_type &key, int (*cf)(const key_type&, const data_type&))
  178. {
  179. bool objectExists;
  180. unsigned index;
  181. index = GetIndexFromKey(key, &objectExists, cf);
  182. // Can't find the element to remove if this assert hits
  183. // RakAssert(objectExists==true);
  184. if (objectExists==false)
  185. {
  186. RakAssert(objectExists==true);
  187. return 0;
  188. }
  189. orderedList.RemoveAtIndex(index);
  190. return index;
  191. }
  192. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  193. unsigned OrderedList<key_type, data_type, default_comparison_function>::RemoveIfExists(const key_type &key, int (*cf)(const key_type&, const data_type&))
  194. {
  195. bool objectExists;
  196. unsigned index;
  197. index = GetIndexFromKey(key, &objectExists, cf);
  198. // Can't find the element to remove if this assert hits
  199. if (objectExists==false)
  200. return 0;
  201. orderedList.RemoveAtIndex(index);
  202. return index;
  203. }
  204. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  205. void OrderedList<key_type, data_type, default_comparison_function>::RemoveAtIndex(const unsigned index)
  206. {
  207. orderedList.RemoveAtIndex(index);
  208. }
  209. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  210. void OrderedList<key_type, data_type, default_comparison_function>::InsertAtIndex(const data_type &data, const unsigned index, const char *file, unsigned int line)
  211. {
  212. orderedList.Insert(data, index, file, line);
  213. }
  214. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  215. void OrderedList<key_type, data_type, default_comparison_function>::InsertAtEnd(const data_type &data, const char *file, unsigned int line)
  216. {
  217. orderedList.Insert(data, file, line);
  218. }
  219. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  220. void OrderedList<key_type, data_type, default_comparison_function>::RemoveFromEnd(const unsigned num)
  221. {
  222. orderedList.RemoveFromEnd(num);
  223. }
  224. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  225. void OrderedList<key_type, data_type, default_comparison_function>::Clear(bool doNotDeallocate, const char *file, unsigned int line)
  226. {
  227. orderedList.Clear(doNotDeallocate, file, line);
  228. }
  229. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  230. data_type& OrderedList<key_type, data_type, default_comparison_function>::operator[]( const unsigned int position ) const
  231. {
  232. return orderedList[position];
  233. }
  234. template <class key_type, class data_type, int (*default_comparison_function)(const key_type&, const data_type&)>
  235. unsigned OrderedList<key_type, data_type, default_comparison_function>::Size(void) const
  236. {
  237. return orderedList.Size();
  238. }
  239. }
  240. #endif
粤ICP备19079148号