tb_linklist.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #ifndef TB_LINKLIST_H
  6. #define TB_LINKLIST_H
  7. #include "tb_core.h"
  8. #include <assert.h>
  9. namespace tb {
  10. class TBLinkList;
  11. class TBLink;
  12. /** TBLinkListIterator - The backend class for a safe iteration of a TBLinkList.
  13. You would normally recieve a typed iterator from a TBLinkListOf::IterateForward
  14. or TBLinkListOf::IterateBackward, instead of creating this object directly.
  15. Safe iteration means that if a link is removed from a linked list, _all_ iterators that currently
  16. point to that link will automatically step to the next link in the iterators direction. */
  17. class TBLinkListIterator
  18. {
  19. public:
  20. TBLinkListIterator(const TBLinkListIterator &iter);
  21. TBLinkListIterator(TBLinkList *linklist, TBLink *current_link, bool forward);
  22. ~TBLinkListIterator();
  23. /** Set the iterator to the first link in we iterate forward,
  24. or set it to the last link if we iterate backward. */
  25. void Reset();
  26. /** Get the current link or nullptr if out of bounds. */
  27. TBLink *Get() const { return m_current_link; }
  28. /** Get the current link and step the iterator to the next (forward or backward). */
  29. TBLink *GetAndStep();
  30. operator TBLink *() const { return m_current_link; }
  31. const TBLinkListIterator& operator = (const TBLinkListIterator &iter);
  32. private:
  33. TBLinkList *m_linklist; ///< The linklist we are iterating.
  34. TBLink *m_current_link; ///< The current link, or nullptr.
  35. bool m_forward; ///< true if we iterate from first to last item.
  36. TBLinkListIterator *m_prev; ///< Link in list of iterators for m_linklist
  37. TBLinkListIterator *m_next; ///< Link in list of iterators for m_linklist
  38. /** RemoveLink is called when removing/deleting links in the target linklist.
  39. This will make sure iterators skip the deleted item. */
  40. void RemoveLink(TBLink *link);
  41. friend class TBLinkList;
  42. /** Add ourself to the chain of iterators in the linklist. */
  43. void Register();
  44. /** Unlink ourself from the chain of iterators in the linklist. */
  45. void Unregister();
  46. void UnregisterAndClear();
  47. };
  48. /** TBLink - The backend class to be inserted in TBLinkList.
  49. Use the typed TBLinkOf for object storing! */
  50. class TBLink
  51. {
  52. public:
  53. TBLink() : prev(nullptr), next(nullptr), linklist(nullptr) {}
  54. /** Return true if the link is currently added to a list. */
  55. bool IsInList() const { return linklist ? true : false; }
  56. public:
  57. TBLink *prev;
  58. TBLink *next;
  59. TBLinkList *linklist;
  60. };
  61. template<class T>
  62. class TBLinkOf : public TBLink
  63. {
  64. public:
  65. inline T *GetPrev() const { return (T *) prev; }
  66. inline T *GetNext() const { return (T *) next; }
  67. };
  68. /** TBLinkList - This is the backend for TBLinkListOf and TBLinkListAutoDeleteOf.
  69. You should use the typed TBLinkListOf or TBLinkListAutoDeleteOf for object storing! */
  70. class TBLinkList
  71. {
  72. public:
  73. TBLinkList() : first(nullptr), last(nullptr), first_iterator(nullptr) {}
  74. ~TBLinkList();
  75. void Remove(TBLink *link);
  76. void RemoveAll();
  77. void AddFirst(TBLink *link);
  78. void AddLast(TBLink *link);
  79. void AddBefore(TBLink *link, TBLink *reference);
  80. void AddAfter(TBLink *link, TBLink *reference);
  81. bool ContainsLink(TBLink *link) const { return link->linklist == this; }
  82. bool HasLinks() const { return first ? true : false; }
  83. int CountLinks() const;
  84. public:
  85. TBLink *first;
  86. TBLink *last;
  87. TBLinkListIterator *first_iterator;
  88. };
  89. /** TBLinkListOf is a double linked linklist. */
  90. template<class T>
  91. class TBLinkListOf
  92. {
  93. public:
  94. /** Remove link from this linklist. */
  95. void Remove(T *link) { m_linklist.Remove(static_cast<TBLinkOf<T>*>(link)); }
  96. /** Remove link from this linklist and delete it. */
  97. void Delete(T *link) { m_linklist.Remove(static_cast<TBLinkOf<T>*>(link)); delete link; }
  98. /** Remove all links without deleting them. */
  99. void RemoveAll() { m_linklist.RemoveAll(); }
  100. /** Delete all links in this linklist. */
  101. void DeleteAll() { while (T *t = GetFirst()) Delete(t); }
  102. /** Add link first in this linklist. */
  103. void AddFirst(T *link) { m_linklist.AddFirst(static_cast<TBLinkOf<T>*>(link)); }
  104. /** Add link last in this linklist. */
  105. void AddLast(T *link) { m_linklist.AddLast(static_cast<TBLinkOf<T>*>(link)); }
  106. /** Add link before the reference link (which must be added to this linklist). */
  107. void AddBefore(T *link, T *reference) { m_linklist.AddBefore(static_cast<TBLinkOf<T>*>(link), reference); }
  108. /** Add link after the reference link (which must be added to this linklist). */
  109. void AddAfter(T *link, T *reference) { m_linklist.AddAfter(static_cast<TBLinkOf<T>*>(link), reference); }
  110. /** Return true if the link is currently added to this linklist. */
  111. bool ContainsLink(T *link) const { return m_linklist.ContainsLink(static_cast<TBLinkOf<T>*>(link)); }
  112. /** Get the first link, or nullptr. */
  113. T *GetFirst() const { return (T *) static_cast<TBLinkOf<T>*>(m_linklist.first); }
  114. /** Get the last link, or nullptr. */
  115. T *GetLast() const { return (T *) static_cast<TBLinkOf<T>*>(m_linklist.last); }
  116. /** Return true if this linklist contains any links. */
  117. bool HasLinks() const { return m_linklist.HasLinks(); }
  118. /** Count the number of links in this list by iterating through all links. */
  119. int CountLinks() const { return m_linklist.CountLinks(); }
  120. /** Typed iterator for safe iteration. For more info, see TBLinkListIterator. */
  121. class Iterator : public TBLinkListIterator
  122. {
  123. public:
  124. Iterator(TBLinkListOf<T> *linklistof, bool forward)
  125. : TBLinkListIterator(&linklistof->m_linklist, forward ? linklistof->m_linklist.first : linklistof->m_linklist.last, forward) {}
  126. Iterator(TBLinkListOf<T> *linklistof, T *link, bool forward) : TBLinkListIterator(&linklistof->m_linklist, link, forward) {}
  127. inline T *Get() const { return (T *) static_cast<TBLinkOf<T>*>(TBLinkListIterator::Get()); }
  128. inline T *GetAndStep() { return (T *) static_cast<TBLinkOf<T>*>(TBLinkListIterator::GetAndStep()); }
  129. inline operator T *() const { return (T *) static_cast<TBLinkOf<T>*>(Get()); }
  130. };
  131. /** Get a forward iterator that starts with the first link. */
  132. Iterator IterateForward() { return Iterator(this, true); }
  133. /** Get a forward iterator that starts with the given link. */
  134. Iterator IterateForward(T *link) { return Iterator(this, link, true); }
  135. /** Get a backward iterator that starts with the last link. */
  136. Iterator IterateBackward() { return Iterator(this, false); }
  137. /** Get a backward iterator that starts with the given link. */
  138. Iterator IterateBackward(T *link) { return Iterator(this, link, false); }
  139. private:
  140. TBLinkList m_linklist;
  141. };
  142. /** TBLinkListAutoDeleteOf is a double linked linklist that deletes all links on destruction. */
  143. template<class T>
  144. class TBLinkListAutoDeleteOf : public TBLinkListOf<T>
  145. {
  146. public:
  147. ~TBLinkListAutoDeleteOf() { TBLinkListOf<T>::DeleteAll(); }
  148. };
  149. }; // namespace tb
  150. #endif // TB_LINKLIST_H