// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // // Bytecoin is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Bytecoin is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . #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; } }