// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once namespace CryptoNote { //Value must have public method IntrusiveLinkedList::hook& getHook() template class IntrusiveLinkedList { public: class hook { public: friend class IntrusiveLinkedList; hook(); private: Value* prev; Value* next; bool used; }; class iterator { public: iterator(Value* value); bool operator!=(const iterator& other) const; bool operator==(const iterator& other) const; iterator& operator++(); iterator operator++(int); iterator& operator--(); iterator operator--(int); Value& operator*() const; Value* operator->() const; private: Value* currentElement; }; IntrusiveLinkedList(); bool insert(Value& value); bool remove(Value& value); bool empty() const; iterator begin(); iterator end(); private: Value* head; Value* tail; }; template IntrusiveLinkedList::IntrusiveLinkedList() : head(nullptr), tail(nullptr) {} template bool IntrusiveLinkedList::insert(Value& value) { if (!value.getHook().used) { if (head == nullptr) { head = &value; tail = head; value.getHook().prev = nullptr; } else { tail->getHook().next = &value; value.getHook().prev = tail; tail = &value; } value.getHook().next = nullptr; value.getHook().used = true; return true; } else { return false; } } template bool IntrusiveLinkedList::remove(Value& value) { if (value.getHook().used && head != nullptr) { Value* toRemove = &value; Value* current = head; while (current->getHook().next != nullptr) { if (toRemove == current) { break; } current = current->getHook().next; } if (toRemove == current) { if (current->getHook().prev == nullptr) { assert(current == head); head = current->getHook().next; if (head != nullptr) { head->getHook().prev = nullptr; } else { tail = nullptr; } } else { current->getHook().prev->getHook().next = current->getHook().next; if (current->getHook().next != nullptr) { current->getHook().next->getHook().prev = current->getHook().prev; } else { tail = current->getHook().prev; } } current->getHook().prev = nullptr; current->getHook().next = nullptr; current->getHook().used = false; return true; } else { return false; } } else { return false; } } template bool IntrusiveLinkedList::empty() const { return head == nullptr; } template typename IntrusiveLinkedList::iterator IntrusiveLinkedList::begin() { return iterator(head); } template typename IntrusiveLinkedList::iterator IntrusiveLinkedList::end() { return iterator(nullptr); } template IntrusiveLinkedList::hook::hook() : prev(nullptr), next(nullptr), used(false) {} template IntrusiveLinkedList::iterator::iterator(Value* value) : currentElement(value) {} template bool IntrusiveLinkedList::iterator::operator!=(const typename IntrusiveLinkedList::iterator& other) const { return currentElement != other.currentElement; } template bool IntrusiveLinkedList::iterator::operator==(const typename IntrusiveLinkedList::iterator& other) const { return currentElement == other.currentElement; } template typename IntrusiveLinkedList::iterator& IntrusiveLinkedList::iterator::operator++() { assert(currentElement != nullptr); currentElement = currentElement->getHook().next; return *this; } template typename IntrusiveLinkedList::iterator IntrusiveLinkedList::iterator::operator++(int) { IntrusiveLinkedList::iterator copy = *this; assert(currentElement != nullptr); currentElement = currentElement->getHook().next; return copy; } template typename IntrusiveLinkedList::iterator& IntrusiveLinkedList::iterator::operator--() { assert(currentElement != nullptr); currentElement = currentElement->getHook().prev; return *this; } template typename IntrusiveLinkedList::iterator IntrusiveLinkedList::iterator::operator--(int) { IntrusiveLinkedList::iterator copy = *this; assert(currentElement != nullptr); currentElement = currentElement->getHook().prev; return copy; } template Value& IntrusiveLinkedList::iterator::operator*() const { assert(currentElement != nullptr); return *currentElement; } template Value* IntrusiveLinkedList::iterator::operator->() const { return currentElement; } }