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_List.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, 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
21
22
23 #ifndef __LIST_H
24 #define __LIST_H
25
26 #include "assert.h"
27 #include <string.h> // memmove
28 #include "Export.h"
29 #include "memoryoverride.h"
30
32 static const unsigned int MAX_UNSIGNED_LONG = 4294967295U;
33
36 namespace DataStructures
37 {
40 template <class list_type>
41 class RAK_DLL_EXPORT List
42 {
43 public:
45 List();
46
47 // Destructor
48 ~List();
49
52 List( const List& original_copy );
53
55 List& operator= ( const List& original_copy );
56
60 list_type& operator[] ( const unsigned int position ) const;
61
65 list_type& Get ( const unsigned int position ) const;
66
69 void Push(const list_type &input, const char *file, unsigned int line );
70
74 list_type& Pop(void);
75
79 void Insert( const list_type &input, const unsigned int position, const char *file, unsigned int line );
80
83 void Insert( const list_type &input, const char *file, unsigned int line );
84
91 void Replace( const list_type &input, const list_type filler, const unsigned int position, const char *file, unsigned int line );
92
95 void Replace( const list_type &input );
96
99 void RemoveAtIndex( const unsigned int position );
100
104 void RemoveAtIndexFast( const unsigned int position );
105
107 void RemoveFromEnd(const unsigned num=1);
108
114 unsigned int GetIndexOf( const list_type &input ) const;
115
117 unsigned int Size( void ) const;
118
120 void Clear( bool doNotDeallocateSmallBlocks, const char *file, unsigned int line );
121
123 void Preallocate( unsigned countNeeded, const char *file, unsigned int line );
124
128 void Compress( const char *file, unsigned int line );
129
130 private:
132 list_type* listArray;
133
135 unsigned int list_size;
136
138 unsigned int allocation_size;
139 };
140 template <class list_type>
141 List<list_type>::List()
142 {
143 allocation_size = 0;
144 listArray = 0;
145 list_size = 0;
146 }
147
148 template <class list_type>
149 List<list_type>::~List()
150 {
151 if (allocation_size>0)
152 SLNet::OP_DELETE_ARRAY(listArray, _FILE_AND_LINE_);
153 }
154
155
156 template <class list_type>
157 List<list_type>::List( const List& original_copy )
158 {
159 // Allocate memory for copy
160
161 if ( original_copy.list_size == 0 )
162 {
163 list_size = 0;
164 allocation_size = 0;
165 }
166 else
167 {
168 listArray = SLNet::OP_NEW_ARRAY<list_type >( original_copy.list_size , _FILE_AND_LINE_ );
169
170 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter )
171 listArray[ counter ] = original_copy.listArray[ counter ];
172
173 // Don't call constructors, assignment operators, etc.
174 //memcpy(listArray, original_copy.listArray, original_copy.list_size*sizeof(list_type));
175
176 list_size = allocation_size = original_copy.list_size;
177 }
178 }
179
180 template <class list_type>
181 List<list_type>& List<list_type>::operator= ( const List& original_copy )
182 {
183 if ( ( &original_copy ) != this )
184 {
185 Clear( false, _FILE_AND_LINE_ );
186
187 // Allocate memory for copy
188
189 if ( original_copy.list_size == 0 )
190 {
191 list_size = 0;
192 allocation_size = 0;
193 }
194
195 else
196 {
197 listArray = SLNet::OP_NEW_ARRAY<list_type >( original_copy.list_size , _FILE_AND_LINE_ );
198
199 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter )
200 listArray[ counter ] = original_copy.listArray[ counter ];
201 // Don't call constructors, assignment operators, etc.
202 //memcpy(listArray, original_copy.listArray, original_copy.list_size*sizeof(list_type));
203
204 list_size = allocation_size = original_copy.list_size;
205 }
206 }
207
208 return *this;
209 }
210
211
212 template <class list_type>
213 inline list_type& List<list_type>::operator[] ( const unsigned int position ) const
214 {
215 #ifdef _DEBUG
216 if (position>=list_size)
217 {
218 RakAssert ( position < list_size );
219 }
220 #endif
221 return listArray[ position ];
222 }
223
224 // Just here for debugging
225 template <class list_type>
226 inline list_type& List<list_type>::Get ( const unsigned int position ) const
227 {
228 return listArray[ position ];
229 }
230
231 template <class list_type>
232 void List<list_type>::Push(const list_type &input, const char *file, unsigned int line)
233 {
234 Insert(input, file, line);
235 }
236
237 template <class list_type>
238 inline list_type& List<list_type>::Pop(void)
239 {
240 #ifdef _DEBUG
241 RakAssert(list_size>0);
242 #endif
243 --list_size;
244 return listArray[list_size];
245 }
246
247 template <class list_type>
248 void List<list_type>::Insert( const list_type &input, const unsigned int position, const char *file, unsigned int line )
249 {
250 #ifdef _DEBUG
251 if (position>list_size)
252 {
253 RakAssert( position <= list_size );
254 }
255 #endif
256
257 // Reallocate list if necessary
258 if ( list_size == allocation_size )
259 {
260 // allocate twice the currently allocated memory
261 list_type * new_array;
262
263 if ( allocation_size == 0 )
264 allocation_size = 16;
265 else
266 allocation_size *= 2;
267
268 new_array = SLNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line );
269
270 // copy old array over
271 for ( unsigned int counter = 0; counter < list_size; ++counter )
272 new_array[ counter ] = listArray[ counter ];
273
274 // Don't call constructors, assignment operators, etc.
275 //memcpy(new_array, listArray, list_size*sizeof(list_type));
276
277 // set old array to point to the newly allocated and twice as large array
278 SLNet::OP_DELETE_ARRAY(listArray, file, line);
279
280 listArray = new_array;
281 }
282
283 // Move the elements in the list to make room
284 for ( unsigned int counter = list_size; counter != position; counter-- )
285 listArray[ counter ] = listArray[ counter - 1 ];
286
287 // Don't call constructors, assignment operators, etc.
288 //memmove(listArray+position+1, listArray+position, (list_size-position)*sizeof(list_type));
289
290 // Insert the new item at the correct spot
291 listArray[ position ] = input;
292
293 ++list_size;
294
295 }
296
297
298 template <class list_type>
299 void List<list_type>::Insert( const list_type &input, const char *file, unsigned int line )
300 {
301 // Reallocate list if necessary
302
303 if ( list_size == allocation_size )
304 {
305 // allocate twice the currently allocated memory
306 list_type * new_array;
307
308 if ( allocation_size == 0 )
309 allocation_size = 16;
310 else
311 allocation_size *= 2;
312
313 new_array = SLNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line );
314
315 if (listArray)
316 {
317 // copy old array over
318 for ( unsigned int counter = 0; counter < list_size; ++counter )
319 new_array[ counter ] = listArray[ counter ];
320
321 // Don't call constructors, assignment operators, etc.
322 //memcpy(new_array, listArray, list_size*sizeof(list_type));
323
324 // set old array to point to the newly allocated and twice as large array
325 SLNet::OP_DELETE_ARRAY(listArray, file, line);
326 }
327
328 listArray = new_array;
329 }
330
331 // Insert the new item at the correct spot
332 listArray[ list_size ] = input;
333
334 ++list_size;
335 }
336
337 template <class list_type>
338 inline void List<list_type>::Replace( const list_type &input, const list_type filler, const unsigned int position, const char *file, unsigned int line )
339 {
340 if ( ( list_size > 0 ) && ( position < list_size ) )
341 {
342 // Direct replacement
343 listArray[ position ] = input;
344 }
345 else
346 {
347 if ( position >= allocation_size )
348 {
349 // Reallocate the list to size position and fill in blanks with filler
350 list_type * new_array;
351 allocation_size = position + 1;
352
353 new_array = SLNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line );
354
355 // copy old array over
356
357 for ( unsigned int counter = 0; counter < list_size; ++counter )
358 new_array[ counter ] = listArray[ counter ];
359
360 // Don't call constructors, assignment operators, etc.
361 //memcpy(new_array, listArray, list_size*sizeof(list_type));
362
363 // set old array to point to the newly allocated array
364 SLNet::OP_DELETE_ARRAY(listArray, file, line);
365
366 listArray = new_array;
367 }
368
369 // Fill in holes with filler
370 while ( list_size < position )
371 listArray[ list_size++ ] = filler;
372
373 // Fill in the last element with the new item
374 listArray[ list_size++ ] = input;
375
376 #ifdef _DEBUG
377
378 RakAssert( list_size == position + 1 );
379
380 #endif
381
382 }
383 }
384
385 template <class list_type>
386 inline void List<list_type>::Replace( const list_type &input )
387 {
388 if ( list_size > 0 )
389 listArray[ list_size - 1 ] = input;
390 }
391
392 template <class list_type>
393 void List<list_type>::RemoveAtIndex( const unsigned int position )
394 {
395 #ifdef _DEBUG
396 if (position >= list_size)
397 {
398 RakAssert( position < list_size );
399 return;
400 }
401 #endif
402
403 if ( position < list_size )
404 {
405 // Compress the array
406 for ( unsigned int counter = position; counter < list_size - 1 ; ++counter )
407 listArray[ counter ] = listArray[ counter + 1 ];
408 // Don't call constructors, assignment operators, etc.
409 // memmove(listArray+position, listArray+position+1, (list_size-1-position) * sizeof(list_type));
410
411 RemoveFromEnd();
412 }
413 }
414
415 template <class list_type>
416 void List<list_type>::RemoveAtIndexFast( const unsigned int position )
417 {
418 #ifdef _DEBUG
419 if (position >= list_size)
420 {
421 RakAssert( position < list_size );
422 return;
423 }
424 #endif
425 --list_size;
426 listArray[position]=listArray[list_size];
427 }
428
429 template <class list_type>
430 inline void List<list_type>::RemoveFromEnd( const unsigned num )
431 {
432 // Delete the last elements on the list. No compression needed
433 #ifdef _DEBUG
434 RakAssert(list_size>=num);
435 #endif
436 list_size-=num;
437 }
438
439 template <class list_type>
440 unsigned int List<list_type>::GetIndexOf( const list_type &input ) const
441 {
442 for ( unsigned int i = 0; i < list_size; ++i )
443 if ( listArray[ i ] == input )
444 return i;
445
446 return MAX_UNSIGNED_LONG;
447 }
448
449 template <class list_type>
450 inline unsigned int List<list_type>::Size( void ) const
451 {
452 return list_size;
453 }
454
455 template <class list_type>
456 void List<list_type>::Clear( bool doNotDeallocateSmallBlocks, const char *file, unsigned int line )
457 {
458 if ( allocation_size == 0 )
459 return;
460
461 if (allocation_size>512 || doNotDeallocateSmallBlocks==false)
462 {
463 SLNet::OP_DELETE_ARRAY(listArray, file, line);
464 allocation_size = 0;
465 listArray = 0;
466 }
467 list_size = 0;
468 }
469
470 template <class list_type>
471 void List<list_type>::Compress( const char *file, unsigned int line )
472 {
473 list_type * new_array;
474
475 if ( allocation_size == 0 )
476 return ;
477
478 new_array = SLNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line );
479
480 // copy old array over
481 for ( unsigned int counter = 0; counter < list_size; ++counter )
482 new_array[ counter ] = listArray[ counter ];
483
484 // Don't call constructors, assignment operators, etc.
485 //memcpy(new_array, listArray, list_size*sizeof(list_type));
486
487 // set old array to point to the newly allocated array
488 SLNet::OP_DELETE_ARRAY(listArray, file, line);
489
490 listArray = new_array;
491 }
492
493 template <class list_type>
494 void List<list_type>::Preallocate( unsigned countNeeded, const char *file, unsigned int line )
495 {
496 unsigned amountToAllocate = allocation_size;
497 if (allocation_size==0)
498 amountToAllocate=16;
499 while (amountToAllocate < countNeeded)
500 amountToAllocate<<=1;
501
502 if ( allocation_size < amountToAllocate)
503 {
504 // allocate twice the currently allocated memory
505 list_type * new_array;
506
507 allocation_size=amountToAllocate;
508
509 new_array = SLNet::OP_NEW_ARRAY< list_type >( allocation_size , file, line );
510
511 if (listArray)
512 {
513 // copy old array over
514 for ( unsigned int counter = 0; counter < list_size; ++counter )
515 new_array[ counter ] = listArray[ counter ];
516
517 // Don't call constructors, assignment operators, etc.
518 //memcpy(new_array, listArray, list_size*sizeof(list_type));
519
520 // set old array to point to the newly allocated and twice as large array
521 SLNet::OP_DELETE_ARRAY(listArray, file, line);
522 }
523
524 listArray = new_array;
525 }
526 }
527
528 } // End namespace
529
530 #endif