Files
Custom-Operating-System/libs/libcxx/include/list

271 lines
6.7 KiB
Plaintext
Raw Normal View History

2025-02-12 09:54:05 -05:00
#pragma GCC system_header
#ifndef _LIBCXX_LIST
#define _LIBCXX_LIST
#include <__config>
#include <memory>
#include <stddef.h>
#include <type_traits>
_LIBCXX_BEGIN_NAMESPACE_STD
namespace details {
template <class T>
class list_node {
public:
using value_type = T;
using pointer = T*;
using reference = T&;
using const_reference = const T&;
private:
using __node_type = details::list_node<value_type>;
using __node_pointer = __node_type*;
public:
list_node(const_reference elem, __node_pointer next = nullptr, __node_pointer prev = nullptr)
: m_elem(elem)
, m_next(next)
, m_prev(prev)
{
}
list_node(value_type&& elem, __node_pointer next = nullptr, __node_pointer prev = nullptr)
: m_elem(std::move(elem))
, m_next(next)
, m_prev(prev)
{
}
~list_node() = default;
inline reference get() { return m_elem; }
inline const_reference get() const { return m_elem; }
inline reference operator*() { return m_elem; }
inline __node_pointer next() const { return m_next; }
inline __node_pointer prev() const { return m_prev; }
inline void set_prev(__node_pointer prev) { m_prev = prev; };
inline void set_next(__node_pointer next) { m_next = next; };
private:
value_type m_elem;
__node_pointer m_prev { nullptr };
__node_pointer m_next { nullptr };
};
}
template <class T, class Alloc>
class list;
template <class T>
class list_iter {
template <class U, class Alloctor>
friend class list;
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
using const_reference = const T&;
using iterator_category = std::bidirectional_iterator_tag;
private:
using __node_type = details::list_node<value_type>;
using __node_pointer = __node_type*;
public:
list_iter() = default;
list_iter(nullptr_t) { }
list_iter(__node_pointer v)
: m_value(v)
{
}
~list_iter() = default;
bool operator!=(const list_iter& other) const { return m_value != other.m_value; }
bool operator==(const list_iter& other) const { return m_value == other.m_value; }
list_iter& operator++()
{
if (m_value) {
m_prev_value = m_value;
m_value = m_value->next();
}
return *this;
}
list_iter& operator--()
{
if (m_value == end()) {
m_value = m_prev_value;
} else {
m_value = m_value->prev();
}
return *this;
}
list_iter operator++(int)
{
auto tmp = *this;
operator++();
return tmp;
}
list_iter operator--(int)
{
auto tmp = *this;
operator--();
return tmp;
}
list_iter& operator=(const list_iter& other)
{
m_value = other.m_value;
m_prev_value = other.m_prev_value;
return *this;
}
reference operator*() { return m_value->get(); }
__node_pointer end() { return nullptr; }
private:
__node_pointer get_value() { return m_value; }
__node_pointer m_value { nullptr };
__node_pointer m_prev_value { nullptr };
};
template <class T, class Allocator = std::allocator<T>>
class list {
public:
using value_type = T;
using pointer = T*;
using reference = T&;
using const_reference = const T&;
using allocator_type = Allocator;
using size_type = size_t;
using iterator = list_iter<value_type>;
using const_iterator = list_iter<const value_type>;
using reverse_iterator = std::reverse_iterator<iterator>;
private:
using __node_type = details::list_node<value_type>;
using __node_pointer = __node_type*;
typedef typename __rebind_alloc_helper<allocator_type, __node_type>::type __node_alloc_type;
public:
list() = default;
~list() = default;
iterator insert(iterator pos, value_type&& value)
{
__node_pointer next_elem = pos.get_value();
__node_pointer prev_elem = m_tail;
if (next_elem) {
prev_elem = next_elem->prev();
}
__node_pointer new_elem = m_node_allocator.allocate(1);
construct_at(new_elem, std::move(value));
new_elem->set_prev(prev_elem);
if (!prev_elem) {
m_head = new_elem;
} else {
prev_elem->set_next(new_elem);
}
new_elem->set_next(next_elem);
if (!next_elem) {
m_tail = new_elem;
} else {
next_elem->set_prev(new_elem);
}
++m_size;
return iterator(new_elem);
}
iterator insert(iterator pos, const_reference value)
{
return insert(pos, value_type(value));
}
void push_back(const_reference value) { insert(end(), value); }
void push_back(value_type&& value) { insert(end(), std::move(value)); }
void push_front(const_reference value) { insert(begin(), value); }
void push_front(value_type&& value) { insert(begin(), std::move(value)); }
iterator erase(iterator pos)
{
__node_pointer this_elem = pos.get_value();
if (!this_elem) {
return end();
}
__node_pointer next_elem = this_elem->next();
__node_pointer prev_elem = this_elem->prev();
if (m_head == this_elem) {
m_head = next_elem;
}
if (m_tail == this_elem) {
m_tail = prev_elem;
}
if (next_elem) {
next_elem->set_prev(prev_elem);
}
if (prev_elem) {
prev_elem->set_next(next_elem);
}
destroy_at(this_elem);
m_node_allocator.deallocate(this_elem, 1);
--m_size;
return iterator(next_elem);
}
void pop_back() { erase(--end()); }
void pop_front() { erase(begin()); }
inline reference front() { return m_head->get(); }
inline const_reference front() const { return m_head->get(); }
inline reference back() { return m_tail->get(); }
inline const_reference back() const { return m_tail->get(); }
inline size_type size() const { return m_size; }
inline bool empty() const { return size() == 0; }
inline iterator begin() const { return iterator(m_head); }
inline iterator end() const { return ++iterator(m_tail); }
inline reverse_iterator rbegin() const { return reverse_iterator(m_tail); }
inline reverse_iterator rend() const { return ++reverse_iterator(m_head); }
allocator_type allocator() const { return m_allocator; }
private:
__node_alloc_type node_allocator() { return m_node_allocator; }
__node_pointer m_head { nullptr };
__node_pointer m_tail { nullptr };
size_type m_size { 0 };
__node_alloc_type m_node_allocator {};
allocator_type m_allocator {};
};
_LIBCXX_END_NAMESPACE_STD
#endif // _LIBCXX_LIST