Newton Dynamics  4.00
dList.h
1 /* Copyright (c) <2003-2019> <Julio Jerez, Newton Game Dynamics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 *
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 *
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #ifndef __D_LIST_H__
23 #define __D_LIST_H__
24 
25 #include "dCoreStdafx.h"
26 #include "dTypes.h"
27 #include "dMemory.h"
28 #include "dContainersAlloc.h"
29 
30 template<class T, class allocator = dContainersAlloc<T> >
31 class dList
32 {
33  public:
34  class dListNode: public allocator
35  {
36  dListNode (dListNode* const prev, dListNode* const next)
37  :allocator()
38  ,m_info ()
39  ,m_prev(prev)
40  ,m_next(next)
41  {
42  if (m_prev)
43  {
44  m_prev->m_next = this;
45  }
46  if (m_next)
47  {
48  m_next->m_prev = this;
49  }
50  }
51 
52  dListNode (const T &info, dListNode* const prev, dListNode* const next)
53  :allocator()
54  ,m_info (info)
55  ,m_prev(prev)
56  ,m_next(next)
57  {
58  if (m_prev)
59  {
60  m_prev->m_next = this;
61  }
62  if (m_next)
63  {
64  m_next->m_prev = this;
65  }
66  }
67 
68  ~dListNode()
69  {
70  }
71 
72  void Unlink ()
73  {
74  if (m_prev)
75  {
76  m_prev->m_next = m_next;
77  }
78  if (m_next)
79  {
80  m_next->m_prev = m_prev;
81  }
82  m_prev = nullptr;
83  m_next = nullptr;
84  }
85 
86  void AddLast(dListNode* const node)
87  {
88  m_next = node;
89  node->m_prev = this;
90  }
91 
92  void AddFirst(dListNode* const node)
93  {
94  m_prev = node;
95  node->m_next = this;
96  }
97 
98  public:
99  T& GetInfo()
100  {
101  return m_info;
102  }
103 
104  dListNode *GetNext() const
105  {
106  return m_next;
107  }
108 
109  dListNode *GetPrev() const
110  {
111  return m_prev;
112  }
113 
114  private:
115  T m_info;
116  dListNode *m_next;
117  dListNode *m_prev;
118  friend class dList<T, allocator>;
119  };
120 
121  class Iterator
122  {
123  public:
124  Iterator (const dList<T, allocator> &me)
125  {
126  m_ptr = nullptr;
127  m_list = (dList *)&me;
128  }
129 
130  ~Iterator ()
131  {
132  }
133 
134  operator dInt32() const
135  {
136  return m_ptr != nullptr;
137  }
138 
139  bool operator== (const Iterator &target) const
140  {
141  return (m_ptr == target.m_ptr) && (m_list == target.m_list);
142  }
143 
144  void Begin()
145  {
146  m_ptr = m_list->GetFirst();
147  }
148 
149  void End()
150  {
151  m_ptr = m_list->GetLast();
152  }
153 
154  void Set (dListNode* const node)
155  {
156  m_ptr = node;
157  }
158 
159  void operator++ ()
160  {
161  dAssert (m_ptr);
162  m_ptr = m_ptr->m_next();
163  }
164 
165  void operator++ (dInt32)
166  {
167  dAssert (m_ptr);
168  m_ptr = m_ptr->GetNext();
169  }
170 
171  void operator-- ()
172  {
173  dAssert (m_ptr);
174  m_ptr = m_ptr->GetPrev();
175  }
176 
177  void operator-- (dInt32)
178  {
179  dAssert (m_ptr);
180  m_ptr = m_ptr->GetPrev();
181  }
182 
183  T &operator* () const
184  {
185  return m_ptr->GetInfo();
186  }
187 
188  dListNode *GetNode() const
189  {
190  return m_ptr;
191  }
192 
193  private:
194  dList *m_list;
195  dListNode *m_ptr;
196  };
197 
198  // ***********************************************************
199  // member functions
200  // ***********************************************************
201  public:
202  dList ();
203  ~dList ();
204 
205  operator dInt32() const;
206  const dInt32 GetCount() const;
207  dListNode* GetLast() const;
208  dListNode* GetFirst() const;
209  dListNode* Append ();
210  dListNode* Append (dListNode* const node);
211  dListNode* Append (const T &element);
212  dListNode* Addtop ();
213  dListNode* Addtop (dListNode* const node);
214  dListNode* Addtop (const T &element);
215 
216  void RotateToEnd (dListNode* const node);
217  void RotateToBegin (dListNode* const node);
218  void InsertAfter (dListNode* const root, dListNode* const node);
219  void InsertBefore (dListNode* const root, dListNode* const node);
220 
221  dListNode* Find (const T &element) const;
222  dListNode* GetNodeFromInfo (T &m_info) const;
223  void Remove (dListNode* const node);
224  void Remove (const T &element);
225  void RemoveAll ();
226 
227  void Merge (dList<T, allocator>& list);
228  void Unlink (dListNode* const node);
229  bool SanityCheck () const;
230 
231  static void FlushFreeList()
232  {
233  allocator::FlushFreeList();
234  }
235 
236  protected:
237  // ***********************************************************
238  // member variables
239  // ***********************************************************
240  private:
241  dListNode* m_first;
242  dListNode* m_last;
243  dInt32 m_count;
244  friend class dListNode;
245 };
246 
247 template<class T, class allocator = dContainersAlloc<T> >
249  :m_first(nullptr)
250  ,m_last(nullptr)
251  ,m_count(0)
252 {
253 }
254 
255 template<class T, class allocator = dContainersAlloc<T> >
257 {
258  RemoveAll ();
259 }
260 
261 template<class T, class allocator = dContainersAlloc<T> >
262 const dInt32 dList<T,allocator>::GetCount() const
263 {
264  return m_count;
265 }
266 
267 template<class T, class allocator = dContainersAlloc<T> >
268 dList<T,allocator>::operator dInt32() const
269 {
270  return m_first != nullptr;
271 }
272 
273 template<class T, class allocator = dContainersAlloc<T> >
275 {
276  return m_first;
277 }
278 
279 template<class T, class allocator = dContainersAlloc<T> >
281 {
282  return m_last;
283 }
284 
285 template<class T, class allocator = dContainersAlloc<T> >
286 typename dList<T,allocator>::dListNode *dList<T,allocator>::Append (dListNode* const node)
287 {
288  dAssert (node->m_next == nullptr);
289  dAssert (node->m_prev == nullptr);
290  m_count ++;
291  if (m_first == nullptr)
292  {
293  m_last = node;
294  m_first = node;
295  }
296  else
297  {
298  m_last->AddLast (node);
299  m_last = node;
300  }
301 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
302  dAssert (SanityCheck ());
303 #endif
304  return m_last;
305 }
306 
307 template<class T, class allocator = dContainersAlloc<T> >
309 {
310  m_count ++;
311  if (m_first == nullptr)
312  {
313  m_first = new dListNode(nullptr, nullptr);
314  m_last = m_first;
315  }
316  else
317  {
318  m_last = new dListNode(m_last, nullptr);
319  }
320 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
321  dAssert (SanityCheck ());
322 #endif
323  return m_last;
324 }
325 
326 template<class T, class allocator = dContainersAlloc<T> >
328 {
329  m_count ++;
330  if (m_first == nullptr)
331  {
332  m_first = new dListNode(element, nullptr, nullptr);
333  m_last = m_first;
334  }
335  else
336  {
337  m_last = new dListNode(element, m_last, nullptr);
338  }
339 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
340  dAssert (SanityCheck ());
341 #endif
342 
343  return m_last;
344 }
345 
346 template<class T, class allocator = dContainersAlloc<T> >
347 typename dList<T,allocator>::dListNode *dList<T,allocator>::Addtop (dListNode* const node)
348 {
349  dAssert (node->m_next == nullptr);
350  dAssert (node->m_prev == nullptr);
351  m_count ++;
352  if (m_last == nullptr)
353  {
354  m_last = node;
355  m_first = node;
356  }
357  else
358  {
359  m_first->AddFirst(node);
360  m_first = node;
361  }
362 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
363  dAssert (SanityCheck ());
364 #endif
365  return m_first;
366 }
367 
368 template<class T, class allocator = dContainersAlloc<T> >
370 {
371  m_count ++;
372  if (m_last == nullptr)
373  {
374  m_last = new dListNode(nullptr, nullptr);
375  m_first = m_last;
376  }
377  else
378  {
379  m_first = new dListNode(nullptr, m_first);
380  }
381 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
382  dAssert (SanityCheck ());
383 #endif
384  return m_first;
385 }
386 
387 template<class T, class allocator = dContainersAlloc<T> >
389 {
390  m_count ++;
391  if (m_last == nullptr)
392  {
393  m_last = new dListNode(element, nullptr, nullptr);
394  m_first = m_last;
395  }
396  else
397  {
398  m_first = new dListNode(element, nullptr, m_first);
399  }
400 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
401  dAssert (SanityCheck ());
402 #endif
403  return m_first;
404 }
405 
406 template<class T, class allocator = dContainersAlloc<T> >
407 void dList<T,allocator>::InsertAfter (dListNode* const root, dListNode* const node)
408 {
409  dAssert (root);
410  if (node != root)
411  {
412  if (root->m_next != node)
413  {
414  if (node == m_first)
415  {
416  m_first = node->m_next;
417  }
418  if (node == m_last)
419  {
420  m_last = node->m_prev;
421  }
422  node->Unlink ();
423 
424  node->m_prev = root;
425  node->m_next = root->m_next;
426  if (root->m_next)
427  {
428  root->m_next->m_prev = node;
429  }
430  root->m_next = node;
431 
432  if (node->m_next == nullptr)
433  {
434  m_last = node;
435  }
436 
437  dAssert (m_last);
438  dAssert (!m_last->m_next);
439  dAssert (m_first);
440  dAssert (!m_first->m_prev);
441  dAssert (SanityCheck ());
442  }
443  }
444 }
445 
446 template<class T, class allocator = dContainersAlloc<T> >
447 void dList<T,allocator>::InsertBefore (dListNode* const root, dListNode* const node)
448 {
449  dAssert (root);
450  if (node != root)
451  {
452  if (root->m_prev != node)
453  {
454  if (node == m_last)
455  {
456  m_last = node->m_prev;
457  }
458  if (node == m_first) {
459  m_first = node->m_next;
460  }
461  node->Unlink ();
462 
463  node->m_next = root;
464  node->m_prev = root->m_prev;
465  if (root->m_prev)
466  {
467  root->m_prev->m_next = node;
468  }
469  root->m_prev = node;
470 
471  if (node->m_prev == nullptr) {
472  m_first = node;
473  }
474 
475  dAssert (m_first);
476  dAssert (!m_first->m_prev);
477  dAssert (m_last);
478  dAssert (!m_last->m_next);
479  dAssert (SanityCheck ());
480  }
481  }
482 }
483 
484 template<class T, class allocator = dContainersAlloc<T> >
485 void dList<T,allocator>::RotateToEnd (dListNode* const node)
486 {
487  if (node != m_last)
488  {
489  if (m_last != m_first)
490  {
491  if (node == m_first)
492  {
493  m_first = m_first->GetNext();
494  }
495  node->Unlink();
496  m_last->AddLast(node);
497  m_last = node;
498  }
499  }
500 
501 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
502  dAssert (SanityCheck ());
503 #endif
504 }
505 
506 template<class T, class allocator = dContainersAlloc<T> >
507 void dList<T,allocator>::RotateToBegin (dListNode* const node)
508 {
509  if (node != m_first)
510  {
511  if (m_last != m_first)
512  {
513  if (node == m_last)
514  {
515  m_last = m_last->GetPrev();
516  }
517  node->Unlink();
518  m_first->AddFirst(node);
519  m_first = node;
520  }
521  }
522 
523 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
524  dAssert (SanityCheck ());
525 #endif
526 }
527 
528 template<class T, class allocator = dContainersAlloc<T> >
529 typename dList<T,allocator>::dListNode *dList<T,allocator>::Find (const T &element) const
530 {
531  dListNode *node;
532  for (node = m_first; node; node = node->GetNext())
533  {
534  if (element == node->m_info)
535  {
536  break;
537  }
538  }
539  return node;
540 }
541 
542 template<class T, class allocator = dContainersAlloc<T> >
544 {
545  dListNode* const node = (dListNode *) &info;
546  dInt64 offset = ((char*) &node->m_info) - ((char *) node);
547  dListNode* const retnode = (dListNode *) (((char *) node) - offset);
548 
549  dAssert (&retnode->GetInfo () == &info);
550  return retnode;
551 }
552 
553 template<class T, class allocator = dContainersAlloc<T> >
554 void dList<T,allocator>::Remove (const T &element)
555 {
556  dListNode *const node = Find (element);
557  if (node)
558  {
559  Remove (node);
560  }
561 }
562 
563 template<class T, class allocator = dContainersAlloc<T> >
564 void dList<T,allocator>::Unlink (dListNode* const node)
565 {
566  dAssert (node);
567 
568  m_count --;
569  dAssert (m_count >= 0);
570 
571  if (node == m_first)
572  {
573  m_first = m_first->GetNext();
574  }
575  if (node == m_last)
576  {
577  m_last = m_last->GetPrev();
578  }
579  node->Unlink();
580 
581 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
582  dAssert (SanityCheck ());
583 #endif
584 }
585 
586 template<class T, class allocator = dContainersAlloc<T> >
588 {
589  m_count += list.m_count;
590  if (list.m_first)
591  {
592  list.m_first->m_prev = m_last;
593  }
594  if (m_last)
595  {
596  m_last->m_next = list.m_first;
597  }
598  m_last = list.m_last;
599  if (!m_first)
600  {
601  m_first = list.m_first;
602  }
603 
604  list.m_count = 0;
605  list.m_last = nullptr;
606  list.m_first = nullptr;
607 #ifdef __ENABLE_DG_CONTAINERS_SANITY_CHECK
608  dAssert (SanityCheck ());
609 #endif
610 }
611 
612 template<class T, class allocator = dContainersAlloc<T> >
613 void dList<T,allocator>::Remove (dListNode* const node)
614 {
615  Unlink (node);
616  delete node;
617 }
618 
619 template<class T, class allocator = dContainersAlloc<T> >
621 {
622  for (dListNode *node = m_first; node; node = m_first)
623  {
624  m_count --;
625  m_first = node->GetNext();
626  node->Unlink();
627  delete node;
628  }
629  dAssert (m_count == 0);
630  m_last = nullptr;
631  m_first = nullptr;
632 }
633 
634 template<class T, class allocator = dContainersAlloc<T> >
636 {
637  #ifdef _DEBUG
638  dInt32 tCount = 0;
639  for (dListNode * node = m_first; node; node = node->GetNext())
640  {
641  tCount ++;
642  if (node->GetPrev()) {
643  dAssert (node->GetPrev() != node->GetNext());
644  if (node->GetPrev()->GetNext() != node)
645  {
646  dAssert (0);
647  return false;
648  }
649  }
650  if (node->GetNext())
651  {
652  dAssert (node->GetPrev() != node->GetNext());
653  if (node->GetNext()->GetPrev() != node)
654  {
655  dAssert (0);
656  return false;
657  }
658  }
659  }
660  if (tCount != m_count)
661  {
662  dAssert (0);
663  return false;
664  }
665  #endif
666  return true;
667 }
668 
669 #endif
670 
671 
dList::Iterator
Definition: dList.h:122
dList
Definition: dList.h:32
dList::dListNode
Definition: dList.h:35