list.h
1 /*************************************************************************/
2 /* list.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef GLOBALS_LIST_H
30 #define GLOBALS_LIST_H
31 
32 #include "os/memory.h"
33 #include "sort.h"
34 
43 template <class T,class A=DefaultAllocator>
44 class List {
45  struct _Data;
46 public:
47 
48 
49  class Element {
50 
51  private:
52  friend class List<T,A>;
53 
54  T value;
55  Element* next_ptr;
56  Element* prev_ptr;
57  _Data *data;
58  public:
59 
63  _FORCE_INLINE_ const Element* next() const {
64 
65  return next_ptr;
66  };
70  _FORCE_INLINE_ Element* next() {
71 
72  return next_ptr;
73  };
74 
78  _FORCE_INLINE_ const Element* prev() const {
79 
80  return prev_ptr;
81  };
85  _FORCE_INLINE_ Element* prev() {
86 
87  return prev_ptr;
88  };
89 
93  _FORCE_INLINE_ const T& operator *() const {
94  return value;
95  };
99  _FORCE_INLINE_ const T* operator->() const {
100 
101  return &value;
102  };
106  _FORCE_INLINE_ T& operator *() {
107  return value;
108  };
112  _FORCE_INLINE_ T* operator->() {
113  return &value;
114  };
115 
119  _FORCE_INLINE_ T& get() {
120  return value;
121  };
125  _FORCE_INLINE_ const T& get() const {
126  return value;
127  };
131  _FORCE_INLINE_ void set(const T& p_value) {
132  value = (T&)p_value;
133  };
134 
135  void erase() {
136 
137  data->erase(this);
138  }
139 
140  _FORCE_INLINE_ Element() {
141  next_ptr = 0;
142  prev_ptr = 0;
143  data=NULL;
144  };
145  };
146 
147 private:
148 
149  struct _Data {
150 
151  Element* first;
152  Element* last;
153  int size_cache;
154 
155 
156  bool erase(const Element* p_I) {
157 
158  ERR_FAIL_COND_V(!p_I,false);
159  ERR_FAIL_COND_V(p_I->data!=this,false);
160 
161  if (first==p_I) {
162  first=p_I->next_ptr;
163  };
164 
165  if (last==p_I)
166  last=p_I->prev_ptr;
167 
168  if (p_I->prev_ptr)
169  p_I->prev_ptr->next_ptr=p_I->next_ptr;
170 
171  if (p_I->next_ptr)
172  p_I->next_ptr->prev_ptr=p_I->prev_ptr;
173 
174  memdelete_allocator<Element,A>( const_cast<Element*>(p_I) );
175  size_cache--;
176 
177  return true;
178  }
179  };
180 
181  _Data *_data;
182 
183 
184 public:
185 
189  _FORCE_INLINE_ const Element* front() const {
190 
191  return _data?_data->first:0;
192  };
193 
197  _FORCE_INLINE_ Element* front() {
198  return _data?_data->first:0;
199  };
200 
204  _FORCE_INLINE_ const Element* back() const {
205 
206  return _data?_data->last:0;
207  };
208 
212  _FORCE_INLINE_ Element* back() {
213 
214  return _data?_data->last:0;
215  };
216 
220  Element* push_back(const T& value) {
221 
222  if (!_data) {
223 
224  _data=memnew_allocator(_Data,A);
225  _data->first=NULL;
226  _data->last=NULL;
227  _data->size_cache=0;
228  }
229 
230  Element* n = memnew_allocator(Element,A);
231  n->value = (T&)value;
232 
233  n->prev_ptr=_data->last;
234  n->next_ptr=0;
235  n->data=_data;
236 
237  if (_data->last) {
238 
239  _data->last->next_ptr=n;
240  }
241 
242  _data->last = n;
243 
244  if (!_data->first)
245  _data->first=n;
246 
247  _data->size_cache++;
248 
249  return n;
250  };
251 
252  void pop_back() {
253 
254  if (_data && _data->last)
255  erase(_data->last);
256  }
257 
261  Element* push_front(const T& value) {
262 
263  if (!_data) {
264 
265  _data=memnew_allocator(_Data,A);
266  _data->first=NULL;
267  _data->last=NULL;
268  _data->size_cache=0;
269  }
270 
271  Element* n = memnew_allocator(Element,A);
272  n->value = (T&)value;
273  n->prev_ptr = 0;
274  n->next_ptr = _data->first;
275  n->data=_data;
276 
277  if (_data->first) {
278 
279  _data->first->prev_ptr=n;
280  }
281 
282  _data->first = n;
283 
284  if (!_data->last)
285  _data->last=n;
286 
287  _data->size_cache++;
288 
289  return n;
290  };
291 
292  void pop_front() {
293 
294  if (_data && _data->first)
295  erase(_data->first);
296  }
297 
301  template<class T_v>
302  Element* find(const T_v& p_val) {
303 
304  Element* it = front();
305  while (it) {
306  if (it->value == p_val) return it;
307  it = it->next();
308  };
309 
310  return NULL;
311  };
312 
316  bool erase(const Element* p_I) {
317 
318  if (_data) {
319  bool ret = _data->erase(p_I);
320 
321  if (_data->size_cache==0) {
322  memdelete_allocator<_Data,A>(_data);
323  _data=NULL;
324  }
325 
326  return ret;
327  }
328 
329  return false;
330  };
331 
335  bool erase(const T& value) {
336 
337  Element* I = find(value);
338  return erase(I);
339  };
340 
344  _FORCE_INLINE_ bool empty() const {
345 
346  return (!_data || !_data->size_cache);
347  }
348 
352  void clear() {
353 
354  while (front()) {
355  erase(front());
356  };
357  };
358 
359  _FORCE_INLINE_ int size() const {
360 
361  return _data?_data->size_cache:0;
362 
363  }
364 
365  void swap(Element* p_A, Element *p_B) {
366 
367  ERR_FAIL_COND(!p_A || !p_B);
368  ERR_FAIL_COND(p_A->data!=_data);
369  ERR_FAIL_COND(p_B->data!=_data);
370 
371  Element* A_prev=p_A->prev_ptr;
372  Element* A_next=p_A->next_ptr;
373 
374  p_A->next_ptr=p_B->next_ptr;
375  p_A->prev_ptr=p_B->prev_ptr;
376 
377  p_B->next_ptr=A_next;
378  p_B->prev_ptr=A_prev;
379 
380  if (p_A->prev_ptr)
381  p_A->prev_ptr->next_ptr=p_A;
382  if (p_A->next_ptr)
383  p_A->next_ptr->prev_ptr=p_A;
384 
385  if (p_B->prev_ptr)
386  p_B->prev_ptr->next_ptr=p_B;
387  if (p_B->next_ptr)
388  p_B->next_ptr->prev_ptr=p_B;
389 
390  }
394  void operator=(const List& p_list) {
395 
396  clear();
397  const Element *it=p_list.front();
398  while (it) {
399 
400  push_back( it->get() );
401  it=it->next();
402  }
403 
404  }
405 
406  T& operator[](int p_index) {
407 
408  if (p_index<0 || p_index>=size()) {
409  T& aux=*((T*)0); //nullreturn
410  ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
411  }
412 
413  Element *I=front();
414  int c=0;
415  while(I) {
416 
417  if (c==p_index) {
418 
419  return I->get();
420  }
421  I=I->next();
422  c++;
423  }
424 
425  ERR_FAIL_V( *((T*)0) ); // bug!!
426  }
427 
428  const T& operator[](int p_index) const {
429 
430  if (p_index<0 || p_index>=size()) {
431  T& aux=*((T*)0); //nullreturn
432  ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
433  }
434 
435  const Element *I=front();
436  int c=0;
437  while(I) {
438 
439  if (c==p_index) {
440 
441  return I->get();
442  }
443  I=I->next();
444  c++;
445  }
446 
447  ERR_FAIL_V( *((T*)0) ); // bug!
448  }
449 
450 
451  void move_to_back(Element* p_I) {
452 
453  ERR_FAIL_COND(p_I->data!=_data);
454  if (!p_I->next_ptr)
455  return;
456 
457  if (_data->first==p_I) {
458  _data->first=p_I->next_ptr;
459  };
460 
461  if (_data->last==p_I)
462  _data->last=p_I->prev_ptr;
463 
464  if (p_I->prev_ptr)
465  p_I->prev_ptr->next_ptr=p_I->next_ptr;
466 
467  if (p_I->next_ptr)
468  p_I->next_ptr->prev_ptr=p_I->prev_ptr;
469 
470 
471  _data->last->next_ptr=p_I;
472  p_I->prev_ptr=_data->last;
473  p_I->next_ptr=NULL;
474  _data->last=p_I;
475 
476  }
477 
478  void invert() {
479 
480  int s = size() / 2;
481  Element *F = front();
482  Element *B = back();
483  for(int i=0;i<s;i++) {
484 
485  SWAP( F->value, B->value );
486  F=F->next();
487  B=B->prev();
488  }
489  }
490 
491  void move_to_front(Element* p_I) {
492 
493  ERR_FAIL_COND(p_I->data!=_data);
494  if (!p_I->prev_ptr)
495  return;
496 
497  if (_data->first==p_I) {
498  _data->first=p_I->next_ptr;
499  };
500 
501  if (_data->last==p_I)
502  _data->last=p_I->prev_ptr;
503 
504  if (p_I->prev_ptr)
505  p_I->prev_ptr->next_ptr=p_I->next_ptr;
506 
507  if (p_I->next_ptr)
508  p_I->next_ptr->prev_ptr=p_I->prev_ptr;
509 
510  _data->first->prev_ptr=p_I;
511  p_I->next_ptr=_data->first;
512  p_I->prev_ptr=NULL;
513  _data->first=p_I;
514 
515  }
516 
517  void move_before(Element* value, Element* where) {
518 
519  if (value->prev_ptr) {
520  value->prev_ptr->next_ptr = value->next_ptr;
521  }
522  else {
523  _data->first = value->next_ptr;
524  }
525  if (value->next_ptr) {
526  value->next_ptr->prev_ptr = value->prev_ptr;
527  }
528  else {
529  _data->last = value->prev_ptr;
530  }
531 
532  value->next_ptr = where;
533  if (!where) {
534  value->prev_ptr = _data->last;
535  _data->last = value;
536  return;
537  };
538 
539  value->prev_ptr = where->prev_ptr;
540 
541  if (where->prev_ptr) {
542  where->prev_ptr->next_ptr = value;
543  } else {
544  _data->first = value;
545  };
546 
547  where->prev_ptr = value;
548  };
549 
554  void sort() {
555 
556  sort_custom< Comparator<T> >();
557  }
558 
559  template<class C>
560  void sort_custom_inplace() {
561 
562  if(size()<2)
563  return;
564 
565  Element *from=front();
566  Element *current=from;
567  Element *to=from;
568 
569  while(current) {
570 
571  Element *next=current->next_ptr;
572 
573  //disconnect
574  current->next_ptr=NULL;
575 
576  if (from!=current) {
577 
578  current->prev_ptr=NULL;
579  current->next_ptr=from;
580 
581  Element *find=from;
582  C less;
583  while( find && less(find->value,current->value) ) {
584 
585  current->prev_ptr=find;
586  current->next_ptr=find->next_ptr;
587  find=find->next_ptr;
588  }
589 
590  if (current->prev_ptr)
591  current->prev_ptr->next_ptr=current;
592  else
593  from=current;
594 
595  if (current->next_ptr)
596  current->next_ptr->prev_ptr=current;
597  else
598  to=current;
599  } else {
600 
601  current->prev_ptr=NULL;
602  current->next_ptr=NULL;
603 
604  }
605 
606  current=next;
607  }
608  _data->first=from;
609  _data->last=to;
610  }
611 
612  template<class C>
614 
615  C compare;
616  _FORCE_INLINE_ bool operator()(const Element *a,const Element* b) const {
617 
618  return compare(a->value,b->value);
619  }
620  };
621 
622  template<class C>
623  void sort_custom() {
624 
625  //this version uses auxiliary memory for speed.
626  //if you don't want to use auxiliary memory, use the in_place version
627 
628  int s = size();
629  if(s<2)
630  return;
631 
632 
633  Element **aux_buffer = memnew_arr(Element*,s);
634 
635  int idx=0;
636  for(Element *E=front();E;E=E->next_ptr) {
637 
638  aux_buffer[idx]=E;
639  idx++;
640  }
641 
643  sort.sort(aux_buffer,s);
644 
645  _data->first=aux_buffer[0];
646  aux_buffer[0]->prev_ptr=NULL;
647  aux_buffer[0]->next_ptr=aux_buffer[1];
648 
649  _data->last=aux_buffer[s-1];
650  aux_buffer[s-1]->prev_ptr=aux_buffer[s-2];
651  aux_buffer[s-1]->next_ptr=NULL;
652 
653  for(int i=1;i<s-1;i++) {
654 
655  aux_buffer[i]->prev_ptr=aux_buffer[i-1];
656  aux_buffer[i]->next_ptr=aux_buffer[i+1];
657 
658  }
659 
660  memdelete_arr(aux_buffer);
661  }
662 
663 
667  List(const List& p_list) {
668 
669  _data=NULL;
670  const Element *it=p_list.front();
671  while (it) {
672 
673  push_back( it->get() );
674  it=it->next();
675  }
676 
677  }
678 
679  List() {
680  _data=NULL;
681  };
682  ~List() {
683  clear();
684  if (_data) {
685 
686  ERR_FAIL_COND(_data->size_cache);
687  memdelete_allocator<_Data,A>(_data);
688  }
689  };
690 };
691 
692 #endif
void sort()
Definition: list.h:554
void operator=(const List &p_list)
Definition: list.h:394
Element * push_back(const T &value)
Definition: list.h:220
Definition: list.h:49
_FORCE_INLINE_ Element * front()
Definition: list.h:197
_FORCE_INLINE_ const Element * prev() const
Definition: list.h:78
List(const List &p_list)
Definition: list.h:667
Element * push_front(const T &value)
Definition: list.h:261
_FORCE_INLINE_ const Element * front() const
Definition: list.h:189
Definition: list.h:613
bool erase(const T &value)
Definition: list.h:335
_FORCE_INLINE_ bool empty() const
Definition: list.h:344
_FORCE_INLINE_ const Element * back() const
Definition: list.h:204
Definition: list.h:44
_FORCE_INLINE_ const Element * next() const
Definition: list.h:63
bool erase(const Element *p_I)
Definition: list.h:316
Definition: sort.h:44
_FORCE_INLINE_ Element * prev()
Definition: list.h:85
Element * find(const T_v &p_val)
Definition: list.h:302
_FORCE_INLINE_ const T * operator->() const
Definition: list.h:99
_FORCE_INLINE_ Element * back()
Definition: list.h:212
_FORCE_INLINE_ const T & operator*() const
Definition: list.h:93
_FORCE_INLINE_ Element * next()
Definition: list.h:70
void clear()
Definition: list.h:352
_FORCE_INLINE_ T * operator->()
Definition: list.h:112