DS_RangeList.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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_RangeList.h
  11. /// \internal
  12. /// \brief A queue implemented as a linked list.
  13. ///
  14. #ifndef __RANGE_LIST_H
  15. #define __RANGE_LIST_H
  16. #include "DS_OrderedList.h"
  17. #include "BitStream.h"
  18. #include "RakMemoryOverride.h"
  19. #include "RakAssert.h"
  20. namespace DataStructures
  21. {
  22. template <class range_type>
  23. struct RangeNode
  24. {
  25. RangeNode() {}
  26. ~RangeNode() {}
  27. RangeNode(range_type min, range_type max) {minIndex=min; maxIndex=max;}
  28. range_type minIndex;
  29. range_type maxIndex;
  30. };
  31. template <class range_type>
  32. int RangeNodeComp(const range_type &a, const RangeNode<range_type> &b)
  33. {
  34. if (a<b.minIndex)
  35. return -1;
  36. if (a==b.minIndex)
  37. return 0;
  38. return 1;
  39. }
  40. template <class range_type>
  41. class RAK_DLL_EXPORT RangeList
  42. {
  43. public:
  44. RangeList();
  45. ~RangeList();
  46. void Insert(range_type index);
  47. void Clear(void);
  48. unsigned Size(void) const;
  49. unsigned RangeSum(void) const;
  50. RakNet::BitSize_t Serialize(RakNet::BitStream *in, RakNet::BitSize_t maxBits, bool clearSerialized);
  51. bool Deserialize(RakNet::BitStream *out);
  52. DataStructures::OrderedList<range_type, RangeNode<range_type> , RangeNodeComp<range_type> > ranges;
  53. };
  54. template <class range_type>
  55. RakNet::BitSize_t RangeList<range_type>::Serialize(RakNet::BitStream *in, RakNet::BitSize_t maxBits, bool clearSerialized)
  56. {
  57. RakAssert(ranges.Size() < (unsigned short)-1);
  58. RakNet::BitStream tempBS;
  59. RakNet::BitSize_t bitsWritten;
  60. unsigned short countWritten;
  61. unsigned i;
  62. countWritten=0;
  63. bitsWritten=0;
  64. for (i=0; i < ranges.Size(); i++)
  65. {
  66. if ((int)sizeof(unsigned short)*8+bitsWritten+(int)sizeof(range_type)*8*2+1>maxBits)
  67. break;
  68. unsigned char minEqualsMax;
  69. if (ranges[i].minIndex==ranges[i].maxIndex)
  70. minEqualsMax=1;
  71. else
  72. minEqualsMax=0;
  73. tempBS.Write(minEqualsMax); // Use one byte, intead of one bit, for speed, as this is done a lot
  74. tempBS.Write(ranges[i].minIndex);
  75. bitsWritten+=sizeof(range_type)*8+8;
  76. if (ranges[i].minIndex!=ranges[i].maxIndex)
  77. {
  78. tempBS.Write(ranges[i].maxIndex);
  79. bitsWritten+=sizeof(range_type)*8;
  80. }
  81. countWritten++;
  82. }
  83. in->AlignWriteToByteBoundary();
  84. RakNet::BitSize_t before=in->GetWriteOffset();
  85. in->Write(countWritten);
  86. bitsWritten+=in->GetWriteOffset()-before;
  87. // RAKNET_DEBUG_PRINTF("%i ", in->GetNumberOfBitsUsed());
  88. in->Write(&tempBS, tempBS.GetNumberOfBitsUsed());
  89. // RAKNET_DEBUG_PRINTF("%i %i \n", tempBS.GetNumberOfBitsUsed(),in->GetNumberOfBitsUsed());
  90. if (clearSerialized && countWritten)
  91. {
  92. unsigned rangeSize=ranges.Size();
  93. for (i=0; i < rangeSize-countWritten; i++)
  94. {
  95. ranges[i]=ranges[i+countWritten];
  96. }
  97. ranges.RemoveFromEnd(countWritten);
  98. }
  99. return bitsWritten;
  100. }
  101. template <class range_type>
  102. bool RangeList<range_type>::Deserialize(RakNet::BitStream *out)
  103. {
  104. ranges.Clear(true, _FILE_AND_LINE_);
  105. unsigned short count;
  106. out->AlignReadToByteBoundary();
  107. out->Read(count);
  108. unsigned short i;
  109. range_type min,max;
  110. unsigned char maxEqualToMin=0;
  111. for (i=0; i < count; i++)
  112. {
  113. out->Read(maxEqualToMin);
  114. if (out->Read(min)==false)
  115. return false;
  116. if (maxEqualToMin==false)
  117. {
  118. if (out->Read(max)==false)
  119. return false;
  120. if (max<min)
  121. return false;
  122. }
  123. else
  124. max=min;
  125. ranges.InsertAtEnd(RangeNode<range_type>(min,max), _FILE_AND_LINE_);
  126. }
  127. return true;
  128. }
  129. template <class range_type>
  130. RangeList<range_type>::RangeList()
  131. {
  132. RangeNodeComp<range_type>(0, RangeNode<range_type>());
  133. }
  134. template <class range_type>
  135. RangeList<range_type>::~RangeList()
  136. {
  137. Clear();
  138. }
  139. template <class range_type>
  140. void RangeList<range_type>::Insert(range_type index)
  141. {
  142. if (ranges.Size()==0)
  143. {
  144. ranges.Insert(index, RangeNode<range_type>(index, index), true, _FILE_AND_LINE_);
  145. return;
  146. }
  147. bool objectExists;
  148. unsigned insertionIndex=ranges.GetIndexFromKey(index, &objectExists);
  149. if (insertionIndex==ranges.Size())
  150. {
  151. if (index == ranges[insertionIndex-1].maxIndex+(range_type)1)
  152. ranges[insertionIndex-1].maxIndex++;
  153. else if (index > ranges[insertionIndex-1].maxIndex+(range_type)1)
  154. {
  155. // Insert at end
  156. ranges.Insert(index, RangeNode<range_type>(index, index), true, _FILE_AND_LINE_);
  157. }
  158. return;
  159. }
  160. if (index < ranges[insertionIndex].minIndex-(range_type)1)
  161. {
  162. // Insert here
  163. ranges.InsertAtIndex(RangeNode<range_type>(index, index), insertionIndex, _FILE_AND_LINE_);
  164. return;
  165. }
  166. else if (index == ranges[insertionIndex].minIndex-(range_type)1)
  167. {
  168. // Decrease minIndex and join left
  169. ranges[insertionIndex].minIndex--;
  170. if (insertionIndex>0 && ranges[insertionIndex-1].maxIndex+(range_type)1==ranges[insertionIndex].minIndex)
  171. {
  172. ranges[insertionIndex-1].maxIndex=ranges[insertionIndex].maxIndex;
  173. ranges.RemoveAtIndex(insertionIndex);
  174. }
  175. return;
  176. }
  177. else if (index >= ranges[insertionIndex].minIndex && index <= ranges[insertionIndex].maxIndex)
  178. {
  179. // Already exists
  180. return;
  181. }
  182. else if (index == ranges[insertionIndex].maxIndex+(range_type)1)
  183. {
  184. // Increase maxIndex and join right
  185. ranges[insertionIndex].maxIndex++;
  186. if (insertionIndex<ranges.Size()-1 && ranges[insertionIndex+(range_type)1].minIndex==ranges[insertionIndex].maxIndex+(range_type)1)
  187. {
  188. ranges[insertionIndex+1].minIndex=ranges[insertionIndex].minIndex;
  189. ranges.RemoveAtIndex(insertionIndex);
  190. }
  191. return;
  192. }
  193. }
  194. template <class range_type>
  195. void RangeList<range_type>::Clear(void)
  196. {
  197. ranges.Clear(true, _FILE_AND_LINE_);
  198. }
  199. template <class range_type>
  200. unsigned RangeList<range_type>::Size(void) const
  201. {
  202. return ranges.Size();
  203. }
  204. template <class range_type>
  205. unsigned RangeList<range_type>::RangeSum(void) const
  206. {
  207. unsigned sum=0,i;
  208. for (i=0; i < ranges.Size(); i++)
  209. sum+=ranges[i].maxIndex-ranges[i].minIndex+1;
  210. return sum;
  211. }
  212. }
  213. #endif
粤ICP备19079148号