ScummVM API documentation
dgList.h
1 /* Copyright (c) <2003-2011> <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 __dgList__
23 #define __dgList__
24 
25 #include "dgStdafx.h"
26 #include "dgRef.h"
27 #include "dgDebug.h"
28 #include "dgMemory.h"
29 
30 
31 
32 template<class T>
33 class dgList {
34 public:
35  class dgListNode {
36  DG_CLASS_ALLOCATOR(allocator)
37 
38  dgListNode(dgListNode *const prev, dgListNode *const next)
39  : m_info() {
40 // NEWTON_ASSERT ((dgUnsigned64 (&m_info) & 0x0f) == 0);
41  m_prev = prev;
42  m_next = next;
43  if (m_prev) {
44  m_prev->m_next = this;
45  }
46  if (m_next) {
47  m_next->m_prev = this;
48  }
49  }
50 
51  dgListNode(const T &info, dgListNode *const prev, dgListNode *const next)
52  : m_info(info) {
53 // NEWTON_ASSERT ((dgUnsigned64 (&m_info) & 0x0f) == 0);
54  m_prev = prev;
55  m_next = next;
56  if (m_prev) {
57  m_prev->m_next = this;
58  }
59  if (m_next) {
60  m_next->m_prev = this;
61  }
62  }
63 
64  virtual ~dgListNode() {
65 // Unlink ();
66  }
67 
68  void Unlink() {
69  if (m_prev) {
70  m_prev->m_next = m_next;
71  }
72 
73  if (m_next) {
74  m_next->m_prev = m_prev;
75  }
76  m_prev = NULL;
77  m_next = NULL;
78  }
79 
80 // void Remove()
81 // {
82 // NEWTON_ASSERT (0);
83 // Kill();
84 // Unlink();
85 // Release();
86 // }
87 
88  void AddLast(dgListNode *const node) {
89  m_next = node;
90  node->m_prev = this;
91  }
92 
93  void AddFirst(dgListNode *const node) {
94  m_prev = node;
95  node->m_next = this;
96  }
97 
98 
99 
100  public:
101  T &GetInfo() {
102  return m_info;
103  }
104 
105  dgListNode *GetNext() const {
106  return m_next;
107  }
108 
109  dgListNode *GetPrev() const {
110  return m_prev;
111  }
112 
113  private:
114  T m_info;
115  dgListNode *m_next;
116  dgListNode *m_prev;
117  friend class dgList<T>;
118 
119  };
120 
121  class Iterator {
122  public:
123  Iterator(const dgList<T> &me) {
124  m_ptr = NULL;
125  m_list = (dgList *)&me;
126  }
127 
128  ~Iterator() {
129  }
130 
131  operator dgInt32() const {
132  return m_ptr != NULL;
133  }
134 
135  bool operator== (const Iterator &target) const {
136  return (m_ptr == target.m_ptr) && (m_list == target.m_list);
137  }
138 
139  void Begin() {
140  m_ptr = m_list->GetFirst();
141  }
142 
143  void End() {
144  m_ptr = m_list->GetLast();
145  }
146 
147  void Set(dgListNode *const node) {
148  m_ptr = node;
149  }
150 
151  void operator++ () {
152  NEWTON_ASSERT(m_ptr);
153  m_ptr = m_ptr->m_next();
154  }
155 
156  void operator++ (int) {
157  NEWTON_ASSERT(m_ptr);
158  m_ptr = m_ptr->GetNext();
159  }
160 
161  void operator-- () {
162  NEWTON_ASSERT(m_ptr);
163  m_ptr = m_ptr->GetPrev();
164  }
165 
166  void operator-- (int) {
167  NEWTON_ASSERT(m_ptr);
168  m_ptr = m_ptr->GetPrev();
169  }
170 
171  T &operator* () const {
172  return m_ptr->GetInfo();
173  }
174 
175  dgListNode *GetNode() const {
176  return m_ptr;
177  }
178 
179  private:
180  dgList *m_list;
181  dgListNode *m_ptr;
182  };
183 
184  // ***********************************************************
185  // member functions
186  // ***********************************************************
187 public:
188  DG_CLASS_ALLOCATOR(allocator)
189 
190 // dgList ();
191  dgList(dgMemoryAllocator *const allocator);
192  virtual ~dgList();
193 
194  dgMemoryAllocator *GetAllocator() const;
195  void SetAllocator(dgMemoryAllocator *const allocator);
196 
197  operator dgInt32() const;
198  dgInt32 GetCount() const;
199  dgListNode *GetLast() const;
200  dgListNode *GetFirst() const;
201  dgListNode *Append();
202  dgListNode *Append(dgListNode *const node);
203  dgListNode *Append(const T &element);
204  dgListNode *Addtop();
205  dgListNode *Addtop(dgListNode *const node);
206  dgListNode *Addtop(const T &element);
207 
208  void RotateToEnd(dgListNode *const node);
209  void RotateToBegin(dgListNode *const node);
210  void InsertAfter(dgListNode *const root, dgListNode *const node);
211  void InsertBefore(dgListNode *const root, dgListNode *const node);
212 
213 
214  dgListNode *Find(const T &element) const;
215  dgListNode *GetNodeFromInfo(T &m_info) const;
216  void Remove(dgListNode *const node);
217  void Remove(const T &element);
218  void RemoveAll();
219 
220  void Merge(dgList<T> &list);
221  void Unlink(dgListNode *const node);
222  bool SanityCheck() const;
223 
224 
225 
226  // ***********************************************************
227  // member variables
228  // ***********************************************************
229 private:
230  dgInt32 m_count;
231  dgListNode *m_last;
232  dgListNode *m_first;
233  dgMemoryAllocator *m_allocator;
234 
235 // static dgInt32 m_size;
236 // static dgMemoryAllocator* m_staticAllocator;
237  friend class dgListNode;
238 };
239 
240 /*
241 template<class T>
242 dgList<T>::dgList ()
243 {
244  m_count = 0;
245  m_first = NULL;
246  m_last = NULL;
247  m_allocator = NULL;
248 }
249 */
250 
251 template<class T>
252 dgList<T>::dgList(dgMemoryAllocator *const allocator) {
253  m_count = 0;
254  m_first = NULL;
255  m_last = NULL;
256  m_allocator = allocator;
257 }
258 
259 
260 template<class T>
262  RemoveAll();
263 }
264 
265 template<class T>
266 void dgList<T>::SetAllocator(dgMemoryAllocator *const allocator) {
267  if ((m_count == 0) && (m_allocator == NULL)) {
268  m_allocator = allocator;
269  }
270 }
271 
272 template<class T>
274  return m_allocator;
275 }
276 
277 
278 template<class T>
279 dgInt32 dgList<T>::GetCount() const {
280  return m_count;
281 }
282 
283 template<class T>
284 dgList<T>::operator dgInt32() const {
285  return m_first != NULL;
286 }
287 
288 template<class T>
289 typename dgList<T>::dgListNode *dgList<T>::GetFirst() const {
290  return m_first;
291 }
292 
293 template<class T>
294 typename dgList<T>::dgListNode *dgList<T>::GetLast() const {
295  return m_last;
296 }
297 
298 template<class T>
299 typename dgList<T>::dgListNode *dgList<T>::Append(dgListNode *const node) {
300  NEWTON_ASSERT(node->m_next == NULL);
301  NEWTON_ASSERT(node->m_prev == NULL);
302  m_count ++;
303  if (m_first == NULL) {
304  m_last = node;
305  m_first = node;
306  } else {
307  m_last->AddLast(node);
308  m_last = node;
309  }
310 #ifdef __ENABLE_SANITY_CHECK
311  NEWTON_ASSERT(SanityCheck());
312 #endif
313  return m_last;
314 }
315 
316 template<class T>
318  m_count ++;
319  if (m_first == NULL) {
320  m_first = new (m_allocator) dgListNode(NULL, NULL);
321  m_last = m_first;
322  } else {
323  m_last = new (m_allocator) dgListNode(m_last, NULL);
324  }
325 #ifdef __ENABLE_SANITY_CHECK
326  NEWTON_ASSERT(SanityCheck());
327 #endif
328  return m_last;
329 }
330 
331 template<class T>
332 typename dgList<T>::dgListNode *dgList<T>::Append(const T &element) {
333  m_count ++;
334  if (m_first == NULL) {
335  m_first = new (m_allocator) dgListNode(element, NULL, NULL);
336  m_last = m_first;
337  } else {
338  m_last = new (m_allocator) dgListNode(element, m_last, NULL);
339  }
340 #ifdef __ENABLE_SANITY_CHECK
341  NEWTON_ASSERT(SanityCheck());
342 #endif
343 
344  return m_last;
345 }
346 
347 template<class T>
348 typename dgList<T>::dgListNode *dgList<T>::Addtop(dgListNode *const node) {
349  NEWTON_ASSERT(node->m_next == NULL);
350  NEWTON_ASSERT(node->m_prev == NULL);
351  m_count ++;
352  if (m_last == NULL) {
353  m_last = node;
354  m_first = node;
355  } else {
356  m_first->AddFirst(node);
357  m_first = node;
358  }
359 #ifdef __ENABLE_SANITY_CHECK
360  NEWTON_ASSERT(SanityCheck());
361 #endif
362  return m_first;
363 }
364 
365 
366 template<class T>
368  m_count ++;
369  if (m_last == NULL) {
370  m_last = new (m_allocator) dgListNode(NULL, NULL);
371  m_first = m_last;
372  } else {
373  m_first = new (m_allocator) dgListNode(NULL, m_first);
374  }
375 #ifdef __ENABLE_SANITY_CHECK
376  NEWTON_ASSERT(SanityCheck());
377 #endif
378  return m_first;
379 }
380 
381 
382 template<class T>
383 typename dgList<T>::dgListNode *dgList<T>::Addtop(const T &element) {
384  m_count ++;
385  if (m_last == NULL) {
386  m_last = new (m_allocator) dgListNode(element, NULL, NULL);
387  m_first = m_last;
388  } else {
389  m_first = new (m_allocator) dgListNode(element, NULL, m_first);
390  }
391 #ifdef __ENABLE_SANITY_CHECK
392  NEWTON_ASSERT(SanityCheck());
393 #endif
394  return m_first;
395 }
396 
397 template<class T>
398 void dgList<T>::InsertAfter(dgListNode *const root, dgListNode *const node) {
399  NEWTON_ASSERT(root);
400  NEWTON_ASSERT(node != root);
401 
402  if (root->m_next != node) {
403  if (node == m_first) {
404  m_first = node->m_next;
405  }
406  if (node == m_last) {
407  m_last = node->m_prev;
408  }
409  node->Unlink();
410 
411  node->m_prev = root;
412  node->m_next = root->m_next;
413  if (root->m_next) {
414  root->m_next->m_prev = node;
415  }
416  root->m_next = node;
417 
418  if (node->m_next == NULL) {
419  m_last = node;
420  }
421 
422  NEWTON_ASSERT(m_last);
423  NEWTON_ASSERT(!m_last->m_next);
424  NEWTON_ASSERT(m_first);
425  NEWTON_ASSERT(!m_first->m_prev);
426  NEWTON_ASSERT(SanityCheck());
427  }
428 }
429 
430 
431 template<class T>
432 void dgList<T>::InsertBefore(dgListNode *const root, dgListNode *const node) {
433  NEWTON_ASSERT(root);
434  NEWTON_ASSERT(node != root);
435 
436  if (root->m_prev != node) {
437  if (node == m_last) {
438  m_last = node->m_prev;
439  }
440  if (node == m_first) {
441  m_first = node->m_next;
442  }
443  node->Unlink();
444 
445  node->m_next = root;
446  node->m_prev = root->m_prev;
447  if (root->m_prev) {
448  root->m_prev->m_next = node;
449  }
450  root->m_prev = node;
451 
452  if (node->m_prev == NULL) {
453  m_first = node;
454  }
455 
456  NEWTON_ASSERT(m_first);
457  NEWTON_ASSERT(!m_first->m_prev);
458  NEWTON_ASSERT(m_last);
459  NEWTON_ASSERT(!m_last->m_next);
460  NEWTON_ASSERT(SanityCheck());
461  }
462 }
463 
464 
465 template<class T>
466 void dgList<T>::RotateToEnd(dgListNode *const node) {
467  if (node != m_last) {
468  if (m_last != m_first) {
469  if (node == m_first) {
470  m_first = m_first->GetNext();
471  }
472  node->Unlink();
473  m_last->AddLast(node);
474  m_last = node;
475  }
476  }
477 
478 #ifdef __ENABLE_SANITY_CHECK
479  NEWTON_ASSERT(SanityCheck());
480 #endif
481 }
482 
483 template<class T>
484 void dgList<T>::RotateToBegin(dgListNode *const node) {
485  if (node != m_first) {
486  if (m_last != m_first) {
487  if (node == m_last) {
488  m_last = m_last->GetPrev();
489  }
490  node->Unlink();
491  m_first->AddFirst(node);
492  m_first = node;
493  }
494  }
495 
496 #ifdef __ENABLE_SANITY_CHECK
497  NEWTON_ASSERT(SanityCheck());
498 #endif
499 }
500 
501 
502 template<class T>
503 typename dgList<T>::dgListNode *dgList<T>::Find(const T &element) const {
504  dgListNode *node;
505  for (node = m_first; node; node = node->GetNext()) {
506  if (element == node->m_info) {
507  break;
508  }
509  }
510  return node;
511 }
512 
513 template<class T>
514 typename dgList<T>::dgListNode *dgList<T>::GetNodeFromInfo(T &info) const {
515 // dgInt64 offset;
516 // dgListNode *node;
517 
518  dgListNode *const node = (dgListNode *) &info;
519  dgInt64 offset = ((char *) &node->m_info) - ((char *) node);
520  dgListNode *const retnode = (dgListNode *)(((char *) node) - offset);
521 
522  NEWTON_ASSERT(&retnode->GetInfo() == &info);
523  return retnode;
524 }
525 
526 
527 template<class T>
528 void dgList<T>::Remove(const T &element) {
529  dgListNode *const node = Find(element);
530  if (node) {
531  Remove(node);
532  }
533 }
534 
535 template<class T>
536 void dgList<T>::Unlink(dgListNode *const node) {
537  NEWTON_ASSERT(node);
538 
539  m_count --;
540  NEWTON_ASSERT(m_count >= 0);
541 
542  if (node == m_first) {
543  m_first = m_first->GetNext();
544  }
545  if (node == m_last) {
546  m_last = m_last->GetPrev();
547  }
548 // node->Remove();
549  node->Unlink();
550 
551 #ifdef __ENABLE_SANITY_CHECK
552  NEWTON_ASSERT(SanityCheck());
553 #endif
554 }
555 
556 template<class T>
557 void dgList<T>::Merge(dgList<T> &list) {
558  m_count += list.m_count;
559  if (list.m_first) {
560  list.m_first->m_prev = m_last;
561  }
562  if (m_last) {
563  m_last->m_next = list.m_first;
564  }
565  m_last = list.m_last;
566  if (!m_first) {
567  m_first = list.m_first;
568  }
569 
570  list.m_count = 0;
571  list.m_last = NULL;
572  list.m_first = NULL;
573 #ifdef __ENABLE_SANITY_CHECK
574  NEWTON_ASSERT(SanityCheck());
575 #endif
576 }
577 
578 
579 template<class T>
580 void dgList<T>::Remove(dgListNode *const node) {
581  Unlink(node);
582  delete node;
583 }
584 
585 
586 template<class T>
587 void dgList<T>::RemoveAll() {
588  for (dgListNode *node = m_first; node; node = m_first) {
589  m_count --;
590  m_first = node->GetNext();
591 // node->Remove();
592  node->Unlink();
593  delete node;
594  }
595  NEWTON_ASSERT(m_count == 0);
596  m_last = NULL;
597  m_first = NULL;
598 }
599 
600 template<class T>
601 bool dgList<T>::SanityCheck() const {
602 #ifdef _DEBUG
603  dgInt32 tCount = 0;
604  for (dgListNode *node = m_first; node; node = node->GetNext()) {
605  tCount ++;
606  if (node->GetPrev()) {
607  NEWTON_ASSERT(node->GetPrev() != node->GetNext());
608  if (node->GetPrev()->GetNext() != node) {
609  NEWTON_ASSERT(0);
610  return false;
611  }
612  }
613  if (node->GetNext()) {
614  NEWTON_ASSERT(node->GetPrev() != node->GetNext());
615  if (node->GetNext()->GetPrev() != node) {
616  NEWTON_ASSERT(0);
617  return false;
618  }
619  }
620  }
621  if (tCount != m_count) {
622  NEWTON_ASSERT(0);
623  return false;
624  }
625 #endif
626  return true;
627 }
628 
629 
630 //template<class T>
631 //void dgList<T>::SetAllocator (dgMemoryAllocator * allocator)
632 //{
633 // m_allocator = allocator;
634 //}
635 
636 //template<class T>
637 //dgMemoryAllocator* dgList<T>::GetAllocator () const
638 //{
639 // return m_allocator;
640 //}
641 //template<class T> dgInt32 dgList <T>::m_size = 0;
642 //template<class T> dgMemoryAllocator* dgList<T>::m_staticAllocator = NULL;
643 
644 
645 #endif
Definition: dgList.h:35
Definition: dgList.h:33
Definition: dgList.h:121
Definition: dgMemory.h:80