This repository has been archived on 2025-02-26. You can view files and clone it, but cannot push or open issues or pull requests.
hilbert-os/euler/include/std/list.hpp

275 lines
5.9 KiB
C++

#pragma once
#include <iterator>
#include <memory>
namespace std {
template <class T>
class list {
public:
struct node {
T value;
node *prev;
node *next;
};
template <class V>
struct generic_iterator {
node *the_node;
node *last_node;
using iterator_category = std::bidirectional_iterator_tag;
using reference = V &;
using pointer = V *;
using value_type = V;
using difference_type = size_t;
bool operator ==(const generic_iterator &other) const {
return the_node == other.the_node;
}
bool operator !=(const generic_iterator &other) const {
return the_node != other.the_node;
}
V &operator *() {
return the_node->value;
}
V *operator ->() {
return &the_node->value;
}
generic_iterator &operator ++() {
the_node = the_node->next;
return *this;
}
generic_iterator &operator --() {
if (the_node == 0)
the_node = last_node;
else
the_node = the_node->prev;
return *this;
}
generic_iterator operator -(size_t count) const {
generic_iterator it = { .the_node = the_node };
for (size_t i = 0; i < count; ++i)
--it;
return it;
}
};
using iterator = generic_iterator< T>;
using const_iterator = generic_iterator<const T>;
using reverse_iterator = std::reverse_iterator< iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
node *first_node;
node *last_node;
size_t count;
public:
void push_back(const T &value) {
node *n = new node { .value = value,
.prev = last_node, .next = 0 };
if (last_node) last_node->next = n;
else first_node = n;
last_node = n;
++count;
}
void push_back(T &&value) {
node *n = new node {
.value = std::move(value),
.prev = last_node, .next = 0 };
if (last_node) last_node->next = n;
else first_node = n;
last_node = n;
++count;
}
iterator erase(iterator pos) {
--count;
auto *n = pos.the_node;
auto *r = n->next;
if (n->prev) n->prev->next = n->next;
else first_node = n->next;
if (n->next) n->next->prev = n->prev;
else last_node = n->prev;
delete n;
return iterator {
.the_node = r,
.last_node = last_node
};
}
iterator begin() noexcept {
return iterator {
.the_node = first_node,
.last_node = last_node
};
}
iterator end() noexcept {
return iterator {
.the_node = 0,
.last_node = last_node
};
}
const_iterator begin() const noexcept {
return iterator {
.the_node = first_node,
.last_node = last_node
};
}
const_iterator end() const noexcept {
return iterator {
.the_node = 0,
.last_node = last_node
};
}
const_iterator cbegin() const noexcept {
return iterator {
.the_node = first_node,
.last_node = last_node
};
}
const_iterator cend() const noexcept {
return iterator {
.the_node = 0,
.last_node = last_node
};
}
reverse_iterator rbegin() noexcept {
return reverse_iterator(
iterator {
.the_node = 0,
.last_node = last_node
});
}
reverse_iterator rend() noexcept {
return reverse_iterator(
iterator {
.the_node = first_node,
.last_node = last_node
});
}
const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(
iterator {
.the_node = 0,
.last_node = last_node
});
}
const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(
iterator {
.the_node = first_node,
.last_node = last_node
});
}
const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(
iterator {
.the_node = 0,
.last_node = last_node
});
}
const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(
iterator {
.the_node = first_node,
.last_node = last_node
});
}
size_t remove(const T &value) {
size_t removed = 0;
auto it = begin();
while (it != end())
if (*it == value) {
it = erase(it);
++removed;
}
else
++it;
count -= removed;
return removed;
}
list() : first_node(0), last_node(0), count(0) {}
list(const list &other) : first_node(0), last_node(0), count(0) {
for (node *n = other.first_node; n; n = n->next)
push_back(n->value);
}
list(list &&other) : first_node(other.first_node),
last_node(other.last_node), count(other.count) {
other.first_node = 0;
other.last_node = 0;
other.count = 0;
}
void clear() {
if (count == 0) return;
for (node *n = first_node->next; n; n = n->next)
delete n->prev;
delete last_node;
first_node = 0;
last_node = 0;
count = 0;
}
~list() {
clear();
}
list &operator =(const list &other) {
clear();
for (node *n = other.first_node; n; n = n->next)
push_back(n->value);
return *this;
}
list &operator =(list &&other) {
clear();
first_node = other.first_node;
last_node = other.last_node;
count = other.count;
other.first_node = 0;
other.last_node = 0;
other.count = 0;
return *this;
}
T &back() { return last_node->value; }
const T &back() const { return last_node->value; }
size_t size() const noexcept { return count; }
};
}