SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_RangeList.h
Go to the documentation of this file.
1 /*
2 * Original work: 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 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2017-2018, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21
22 #ifndef __RANGE_LIST_H
23 #define __RANGE_LIST_H
24
25 #include "DS_OrderedList.h"
26 #include "BitStream.h"
27 #include "memoryoverride.h"
28 #include "assert.h"
29
30 namespace DataStructures
31 {
32 template <class range_type>
33 struct RangeNode
34 {
35 RangeNode() {}
36 ~RangeNode() {}
37 RangeNode(range_type min, range_type max) {minIndex=min; maxIndex=max;}
38 range_type minIndex;
39 range_type maxIndex;
40 };
41
42
43 template <class range_type>
44 int RangeNodeComp(const range_type &a, const RangeNode<range_type> &b)
45 {
46 if (a < b.minIndex) {
47 return -1;
48 }
49 if (a > b.maxIndex) {
50 return 1;
51 }
52 return 0;
53 }
54
55 template <class range_type>
56 class RAK_DLL_EXPORT RangeList
57 {
58 public:
59 RangeList();
60 ~RangeList();
61 void Insert(range_type index);
62 void Clear(void);
63 bool IsWithinRange(range_type value) const;
64 unsigned Size(void) const;
65 unsigned RangeSum(void) const;
66 SLNet::BitSize_t Serialize(SLNet::BitStream *in, SLNet::BitSize_t maxBits, bool clearSerialized);
67 bool Deserialize(SLNet::BitStream *out);
68
69 DataStructures::OrderedList<range_type, RangeNode<range_type> , RangeNodeComp<range_type> > ranges;
70
71 // internal helpers
72 private:
73 static bool DeserializeSingleRange(SLNet::BitStream *out, range_type& min, range_type& max);
74 };
75
76 template <class range_type>
77 SLNet::BitSize_t RangeList<range_type>::Serialize(SLNet::BitStream *in, SLNet::BitSize_t maxBits, bool clearSerialized)
78 {
79 RakAssert(ranges.Size() < (unsigned short)-1);
80 SLNet::BitStream tempBS;
81 SLNet::BitSize_t bitsWritten;
82 unsigned short countWritten;
83 unsigned i;
84 countWritten=0;
85 bitsWritten=0;
86 for (i=0; i < ranges.Size(); i++)
87 {
88 if ((int)sizeof(unsigned short)*8+bitsWritten+(int)sizeof(range_type)*8*2+1>maxBits)
89 break;
90 unsigned char minEqualsMax;
91 if (ranges[i].minIndex==ranges[i].maxIndex)
92 minEqualsMax=1;
93 else
94 minEqualsMax=0;
95 tempBS.Write(minEqualsMax); // Use one byte, intead of one bit, for speed, as this is done a lot
96 tempBS.Write(ranges[i].minIndex);
97 bitsWritten+=sizeof(range_type)*8+8;
98 if (ranges[i].minIndex!=ranges[i].maxIndex)
99 {
100 tempBS.Write(ranges[i].maxIndex);
101 bitsWritten+=sizeof(range_type)*8;
102 }
103 countWritten++;
104 }
105
106 in->AlignWriteToByteBoundary();
107 SLNet::BitSize_t before=in->GetWriteOffset();
108 in->Write(countWritten);
109 bitsWritten+=in->GetWriteOffset()-before;
110 // RAKNET_DEBUG_PRINTF("%i ", in->GetNumberOfBitsUsed());
111 in->Write(&tempBS, tempBS.GetNumberOfBitsUsed());
112 // RAKNET_DEBUG_PRINTF("%i %i \n", tempBS.GetNumberOfBitsUsed(),in->GetNumberOfBitsUsed());
113
114 if (clearSerialized && countWritten)
115 {
116 unsigned rangeSize=ranges.Size();
117 for (i=0; i < rangeSize-countWritten; i++)
118 {
119 ranges[i]=ranges[i+countWritten];
120 }
121 ranges.RemoveFromEnd(countWritten);
122 }
123
124 return bitsWritten;
125 }
126 template <class range_type>
127 bool RangeList<range_type>::Deserialize(SLNet::BitStream *out)
128 {
129 ranges.Clear(true, _FILE_AND_LINE_);
130 unsigned short count;
131 out->AlignReadToByteBoundary();
132 if (!out->Read(count)) {
133 return false;
134 }
135 unsigned short i;
136 range_type absMin;
137 range_type min, max;
138
139 if (count == 0) {
140 return true;
141 }
142
143 if (!DeserializeSingleRange(out, min, max)) {
144 return false;
145 }
146 ranges.InsertAtEnd(RangeNode<range_type>(min, max), _FILE_AND_LINE_);
147
148 for (i = 1; i < count; i++) {
149 absMin = max;
150
151 if (!DeserializeSingleRange(out, min, max)) {
152 return false;
153 }
154 if (min <= absMin) {
155 return false;
156 }
157 ranges.InsertAtEnd(RangeNode<range_type>(min, max), _FILE_AND_LINE_);
158 }
159 return true;
160 }
161
162 template <class range_type>
163 bool RangeList<range_type>::DeserializeSingleRange(SLNet::BitStream *out, range_type& min, range_type& max)
164 {
165 unsigned char maxEqualToMin;
166
167 if (!out->Read(maxEqualToMin)) {
168 return false;
169 }
170 if (!out->Read(min)) {
171 return false;
172 }
173 if (maxEqualToMin == 0) {
174 if (!out->Read(max)) {
175 return false;
176 }
177 if (max <= min) {
178 return false;
179 }
180 } else {
181 max = min;
182 }
183
184 return true;
185 }
186
187 template <class range_type>
188 RangeList<range_type>::RangeList()
189 {
190 RangeNodeComp<range_type>(0, RangeNode<range_type>());
191 }
192
193 template <class range_type>
194 RangeList<range_type>::~RangeList()
195 {
196 Clear();
197 }
198
199 template <class range_type>
200 void RangeList<range_type>::Insert(range_type index)
201 {
202 if (ranges.Size()==0)
203 {
204 ranges.Insert(index, RangeNode<range_type>(index, index), true, _FILE_AND_LINE_);
205 return;
206 }
207
208 bool objectExists;
209 unsigned insertionIndex=ranges.GetIndexFromKey(index, &objectExists);
210 if (objectExists) {
211 return; // index already covered by a range entry - do not create a duplicated entry
212 }
213
214 if (insertionIndex==ranges.Size())
215 {
216 if (index == ranges[insertionIndex-1].maxIndex+(range_type)1)
217 ranges[insertionIndex-1].maxIndex++;
218 else if (index > ranges[insertionIndex-1].maxIndex+(range_type)1)
219 {
220 // Insert at end
221 ranges.Insert(index, RangeNode<range_type>(index, index), true, _FILE_AND_LINE_);
222 }
223
224 return;
225 }
226
227 // verify it's really not within the current range (otherwise objectExists should have been true)
228 RakAssert(index < ranges[insertionIndex].minIndex || index > ranges[insertionIndex].maxIndex);
229
230 if (index < ranges[insertionIndex].minIndex-(range_type)1)
231 {
232 // Insert here
233 ranges.InsertAtIndex(RangeNode<range_type>(index, index), insertionIndex, _FILE_AND_LINE_);
234
235 return;
236 }
237 else if (index == ranges[insertionIndex].minIndex-(range_type)1)
238 {
239 // Decrease minIndex and join left
240 ranges[insertionIndex].minIndex--;
241 if (insertionIndex>0 && ranges[insertionIndex-1].maxIndex+(range_type)1==ranges[insertionIndex].minIndex)
242 {
243 ranges[insertionIndex-1].maxIndex=ranges[insertionIndex].maxIndex;
244 ranges.RemoveAtIndex(insertionIndex);
245 }
246
247 return;
248 }
249
250 if (index == ranges[insertionIndex].maxIndex+(range_type)1)
251 {
252 // Increase maxIndex and join right
253 ranges[insertionIndex].maxIndex++;
254 if (insertionIndex<ranges.Size()-1 && ranges[insertionIndex+(range_type)1].minIndex==ranges[insertionIndex].maxIndex+(range_type)1)
255 {
256 ranges[insertionIndex+1].minIndex=ranges[insertionIndex].minIndex;
257 ranges.RemoveAtIndex(insertionIndex);
258 }
259
260 return;
261 }
262 }
263
264 template <class range_type>
265 void RangeList<range_type>::Clear(void)
266 {
267 ranges.Clear(true, _FILE_AND_LINE_);
268 }
269
270 template <class range_type>
271 bool RangeList<range_type>::IsWithinRange(range_type value) const
272 {
273 bool objectExists;
274 // not interested in the return value
275 (void)ranges.GetIndexFromKey(value, &objectExists);
276 return objectExists;
277 }
278
279 template <class range_type>
280 unsigned RangeList<range_type>::Size(void) const
281 {
282 return ranges.Size();
283 }
284
285 template <class range_type>
286 unsigned RangeList<range_type>::RangeSum(void) const
287 {
288 unsigned sum=0,i;
289 for (i=0; i < ranges.Size(); i++)
290 sum+=ranges[i].maxIndex-ranges[i].minIndex+1;
291 return sum;
292 }
293
294 }
295
296 #endif