// 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;
}
}