// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE namespace anki { namespace detail { template ListIterator& ListIterator::operator--() { ANKI_ASSERT(m_list); if(m_node) { m_node = m_node->m_prev; } else { m_node = m_list->m_tail; } return *this; } template Bool ListBase::operator==(const ListBase& b) const { Bool same = true; ConstIterator ita = getBegin(); ConstIterator itb = b.getBegin(); while(same && ita != getEnd() && itb != b.getEnd()) { same = *ita == *itb; ++ita; ++itb; } if(same && (ita != getEnd() || itb != b.getEnd())) { same = false; } return same; } template void ListBase::pushBackNode(TNode* node) { ANKI_ASSERT(node); ANKI_ASSERT(node->m_next == nullptr && node->m_prev == nullptr); if(m_tail != nullptr) { ANKI_ASSERT(m_head != nullptr); m_tail->m_next = node; node->m_prev = m_tail; m_tail = node; } else { ANKI_ASSERT(m_head == nullptr); m_tail = m_head = node; } } template void ListBase::pushFrontNode(TNode* node) { ANKI_ASSERT(node); ANKI_ASSERT(node->m_next == nullptr && node->m_prev == nullptr); if(m_head != nullptr) { ANKI_ASSERT(m_tail != nullptr); m_head->m_prev = node; node->m_next = m_head; m_head = node; } else { ANKI_ASSERT(m_tail == nullptr); m_tail = m_head = node; } } template void ListBase::insertNode(TNode* pos, TNode* node) { ANKI_ASSERT(node); ANKI_ASSERT(node->m_next == nullptr && node->m_prev == nullptr); if(pos == nullptr) { // Place after the last if(m_tail != nullptr) { ANKI_ASSERT(m_head != nullptr); m_tail->m_next = node; node->m_prev = m_tail; m_tail = node; } else { ANKI_ASSERT(m_head == nullptr); m_tail = m_head = node; } } else { node->m_prev = pos->m_prev; node->m_next = pos; pos->m_prev = node; if(pos == m_head) { ANKI_ASSERT(m_tail != nullptr); m_head = node; } } } template template Error ListBase::iterateForward(TFunc func) { Error err = Error::kNone; TNode* node = m_head; while(node && !err) { err = func(detail::GetListNodeValueFunc()(*node)); node = node->m_next; } return err; } template template Error ListBase::iterateBackward(TFunc func) { Error err = Error::kNone; TNode* node = m_tail; while(node && !err) { err = func(detail::GetListNodeValueFunc()(*node)); node = node->m_prev; } return err; } template template void ListBase::sort(TCompFunc compFunc) { TNode* sortPtr; TNode* newTail = m_tail; while(newTail != m_head) { sortPtr = m_head; Bool swapped = false; Bool finished = false; do { ANKI_ASSERT(sortPtr != nullptr); TNode* sortPtrNext = sortPtr->m_next; ANKI_ASSERT(sortPtrNext != nullptr); if(compFunc(detail::GetListNodeValueFunc()(*sortPtrNext), detail::GetListNodeValueFunc()(*sortPtr))) { sortPtr = swap(sortPtr, sortPtrNext); swapped = true; } else { sortPtr = sortPtrNext; } if(sortPtr == m_tail || sortPtr == newTail) { if(swapped) { newTail = sortPtr->m_prev; } else { newTail = m_head; } finished = true; } } while(!finished); } } template TNode* ListBase::swap(TNode* one, TNode* two) { if(one->m_prev == nullptr) { m_head = two; } else { ANKI_ASSERT(one->m_prev); one->m_prev->m_next = two; } if(two->m_next == nullptr) { m_tail = one; } else { ANKI_ASSERT(two->m_next); two->m_next->m_prev = one; } two->m_prev = one->m_prev; one->m_next = two->m_next; one->m_prev = two; two->m_next = one; return one; } template void ListBase::removeNode(TNode* node) { ANKI_ASSERT(node); if(node != m_head) { ANKI_ASSERT(!(node->m_prev == nullptr && node->m_next == nullptr)); } if(node == m_tail) { m_tail = node->m_prev; } if(node == m_head) { m_head = node->m_next; } if(node->m_prev) { ANKI_ASSERT(node->m_prev->m_next == node); node->m_prev->m_next = node->m_next; } if(node->m_next) { ANKI_ASSERT(node->m_next->m_prev == node); node->m_next->m_prev = node->m_prev; } node->m_next = node->m_prev = nullptr; } template typename ListBase::Iterator ListBase::find(const Value& a) { Iterator it = getBegin(); Iterator endit = getEnd(); while(it != endit) { if(*it == a) { break; } ++it; } return it; } template PtrSize ListBase::getSize() const { PtrSize size = 0; ConstIterator it = getBegin(); ConstIterator endit = getEnd(); for(; it != endit; it++) { ++size; } return size; } template void ListBase::popBack() { ANKI_ASSERT(m_tail); removeNode(m_tail); } template void ListBase::popFront() { ANKI_ASSERT(m_head); removeNode(m_head); } } // end namespace detail template void List::destroy() { Node* el = Base::m_head; while(el) { Node* next = el->m_next; deleteInstance(m_pool, el); el = next; } Base::m_head = Base::m_tail = nullptr; } } // end namespace anki