| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #include "tb_linklist.h"
- namespace tb {
- // == TBLinkListIterator ====================================================================================
- TBLinkListIterator::TBLinkListIterator(TBLinkList *linklist, TBLink *current_link, bool forward)
- : m_linklist(linklist)
- , m_current_link(current_link)
- , m_forward(forward)
- {
- Register();
- }
- TBLinkListIterator::TBLinkListIterator(const TBLinkListIterator &iter)
- : m_linklist(iter.m_linklist)
- , m_current_link(iter.m_current_link)
- , m_forward(iter.m_forward)
- {
- Register();
- }
- TBLinkListIterator::~TBLinkListIterator()
- {
- Unregister();
- }
- void TBLinkListIterator::Register()
- {
- m_prev = nullptr;
- m_next = m_linklist->first_iterator;
- if (m_linklist->first_iterator)
- m_linklist->first_iterator->m_prev = this;
- m_linklist->first_iterator = this;
- }
- void TBLinkListIterator::Unregister()
- {
- if (!m_linklist) // Already unregistered
- return;
- if (m_prev)
- m_prev->m_next = m_next;
- if (m_next)
- m_next->m_prev = m_prev;
- if (m_linklist->first_iterator == this)
- m_linklist->first_iterator = m_next;
- }
- void TBLinkListIterator::UnregisterAndClear()
- {
- Unregister();
- m_linklist = nullptr;
- m_current_link = nullptr;
- m_prev = nullptr;
- m_next = nullptr;
- }
- const TBLinkListIterator& TBLinkListIterator::operator = (const TBLinkListIterator &iter)
- {
- if (m_linklist != iter.m_linklist)
- {
- // Change where we are registered if we change linklist.
- Unregister();
- m_linklist = iter.m_linklist;
- Register();
- }
- m_linklist = iter.m_linklist;
- m_current_link = iter.m_current_link;
- m_forward = iter.m_forward;
- return *this;
- }
- void TBLinkListIterator::Reset()
- {
- if (m_linklist)
- m_current_link = m_forward ? m_linklist->first : m_linklist->last;
- else
- m_current_link = nullptr;
- }
- TBLink *TBLinkListIterator::GetAndStep()
- {
- if (!m_current_link)
- return nullptr;
- TBLink *current = m_current_link;
- m_current_link = m_forward ? m_current_link->next : m_current_link->prev;
- return current;
- }
- void TBLinkListIterator::RemoveLink(TBLink *link)
- {
- // If the current link is being removed, step away from it
- if (m_current_link == link)
- GetAndStep();
- }
- // == TBLinkList ============================================================================================
- TBLinkList::~TBLinkList()
- {
- RemoveAll();
- // Make sure any live iterators for this linklist are cleared!
- while (first_iterator)
- first_iterator->UnregisterAndClear();
- }
- void TBLinkList::AddFirst(TBLink *link)
- {
- assert(!link->linklist); // Link is already in some list!
- link->linklist = this;
- link->next = first;
- if (first)
- first->prev = link;
- first = link;
- if (!last)
- last = link;
- }
- void TBLinkList::AddLast(TBLink *link)
- {
- assert(!link->linklist); // Link is already in some list!
- link->linklist = this;
- link->prev = last;
- if (last)
- last->next = link;
- last = link;
- if (!first)
- first = link;
- }
- void TBLinkList::AddBefore(TBLink *link, TBLink *reference)
- {
- assert(reference->linklist == this); // Reference is not added to this list!
- link->linklist = this;
- link->prev = reference->prev;
- link->next = reference;
- if (reference->prev)
- reference->prev->next = link;
- else
- first = link;
- reference->prev = link;
- }
- void TBLinkList::AddAfter(TBLink *link, TBLink *reference)
- {
- assert(reference->linklist == this); // Reference is not added to this list!
- link->linklist = this;
- link->prev = reference;
- link->next = reference->next;
- if (reference->next)
- reference->next->prev = link;
- else
- last = link;
- reference->next = link;
- }
- void TBLinkList::Remove(TBLink *link)
- {
- assert(link->linklist == this); // Link is not added to this list!
- // Go through iterators and make sure there are no pointers
- // to the link we remove.
- TBLinkListIterator *iter = first_iterator;
- while (iter)
- {
- iter->RemoveLink(link);
- iter = iter->m_next;
- }
- // Remove the link
- if (link->next)
- link->next->prev = link->prev;
- if (link->prev)
- link->prev->next = link->next;
- if (first == link)
- first = link->next;
- if (last == link)
- last = link->prev;
- link->linklist = nullptr;
- link->prev = nullptr;
- link->next = nullptr;
- }
- void TBLinkList::RemoveAll()
- {
- // Reset all iterators.
- TBLinkListIterator *iter = first_iterator;
- while (iter)
- {
- iter->m_current_link = nullptr;
- iter = iter->m_next;
- }
- // Remove all links
- TBLink *link = first;
- while (link)
- {
- TBLink *next = link->next;
- link->linklist = nullptr;
- link->prev = nullptr;
- link->next = nullptr;
- link = next;
- }
- first = nullptr;
- last = nullptr;
- }
- int TBLinkList::CountLinks() const
- {
- int count = 0;
- for (TBLink *link = first; link; link = link->next)
- count++;
- return count;
- }
- }; // namespace tb
|