danicoin/src/CryptoNoteCore/IntrusiveLinkedList.h
2016-01-18 15:33:29 +00:00

199 lines
4.9 KiB
C++

// 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<Value>::hook& getHook()
template<class Value> class IntrusiveLinkedList {
public:
class hook {
public:
friend class IntrusiveLinkedList<Value>;
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<class Value>
IntrusiveLinkedList<Value>::IntrusiveLinkedList() : head(nullptr), tail(nullptr) {}
template<class Value>
bool IntrusiveLinkedList<Value>::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<class Value>
bool IntrusiveLinkedList<Value>::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<class Value>
bool IntrusiveLinkedList<Value>::empty() const {
return head == nullptr;
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator IntrusiveLinkedList<Value>::begin() {
return iterator(head);
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator IntrusiveLinkedList<Value>::end() {
return iterator(nullptr);
}
template<class Value>
IntrusiveLinkedList<Value>::hook::hook() : prev(nullptr), next(nullptr), used(false) {}
template<class Value>
IntrusiveLinkedList<Value>::iterator::iterator(Value* value) : currentElement(value) {}
template<class Value>
bool IntrusiveLinkedList<Value>::iterator::operator!=(const typename IntrusiveLinkedList<Value>::iterator& other) const {
return currentElement != other.currentElement;
}
template<class Value>
bool IntrusiveLinkedList<Value>::iterator::operator==(const typename IntrusiveLinkedList<Value>::iterator& other) const {
return currentElement == other.currentElement;
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator& IntrusiveLinkedList<Value>::iterator::operator++() {
assert(currentElement != nullptr);
currentElement = currentElement->getHook().next;
return *this;
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator IntrusiveLinkedList<Value>::iterator::operator++(int) {
IntrusiveLinkedList<Value>::iterator copy = *this;
assert(currentElement != nullptr);
currentElement = currentElement->getHook().next;
return copy;
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator& IntrusiveLinkedList<Value>::iterator::operator--() {
assert(currentElement != nullptr);
currentElement = currentElement->getHook().prev;
return *this;
}
template<class Value>
typename IntrusiveLinkedList<Value>::iterator IntrusiveLinkedList<Value>::iterator::operator--(int) {
IntrusiveLinkedList<Value>::iterator copy = *this;
assert(currentElement != nullptr);
currentElement = currentElement->getHook().prev;
return copy;
}
template<class Value>
Value& IntrusiveLinkedList<Value>::iterator::operator*() const {
assert(currentElement != nullptr);
return *currentElement;
}
template<class Value>
Value* IntrusiveLinkedList<Value>::iterator::operator->() const {
return currentElement;
}
}