|
| 1 | +/** |
| 2 | + * @copyright Copyright The SimpleKernel Contributors |
| 3 | + */ |
| 4 | + |
| 5 | +#ifndef SIMPLEKERNEL_SRC_LIBCXX_INCLUDE_SK_LIST_ |
| 6 | +#define SIMPLEKERNEL_SRC_LIBCXX_INCLUDE_SK_LIST_ |
| 7 | + |
| 8 | +#include <cstddef> |
| 9 | +#include <new> |
| 10 | + |
| 11 | +namespace sk_std { |
| 12 | + |
| 13 | +struct list_node_base { |
| 14 | + list_node_base* prev; |
| 15 | + list_node_base* next; |
| 16 | + |
| 17 | + list_node_base() : prev(this), next(this) {} |
| 18 | +}; |
| 19 | + |
| 20 | +template <typename T> |
| 21 | +struct list_node : public list_node_base { |
| 22 | + T data; |
| 23 | + |
| 24 | + list_node(const T& val) : list_node_base(), data(val) {} |
| 25 | +}; |
| 26 | + |
| 27 | +template <typename T> |
| 28 | +class list_iterator { |
| 29 | + public: |
| 30 | + using node_type = list_node<T>; |
| 31 | + using base_node_type = list_node_base; |
| 32 | + using self_type = list_iterator<T>; |
| 33 | + using value_type = T; |
| 34 | + using pointer = T*; |
| 35 | + using reference = T&; |
| 36 | + |
| 37 | + base_node_type* node; |
| 38 | + |
| 39 | + list_iterator(base_node_type* n) : node(n) {} |
| 40 | + |
| 41 | + reference operator*() const { return static_cast<node_type*>(node)->data; } |
| 42 | + pointer operator->() const { return &static_cast<node_type*>(node)->data; } |
| 43 | + |
| 44 | + self_type& operator++() { |
| 45 | + node = node->next; |
| 46 | + return *this; |
| 47 | + } |
| 48 | + |
| 49 | + self_type operator++(int) { |
| 50 | + self_type tmp = *this; |
| 51 | + node = node->next; |
| 52 | + return tmp; |
| 53 | + } |
| 54 | + |
| 55 | + self_type& operator--() { |
| 56 | + node = node->prev; |
| 57 | + return *this; |
| 58 | + } |
| 59 | + |
| 60 | + self_type operator--(int) { |
| 61 | + self_type tmp = *this; |
| 62 | + node = node->prev; |
| 63 | + return tmp; |
| 64 | + } |
| 65 | + |
| 66 | + bool operator==(const self_type& other) const { return node == other.node; } |
| 67 | + bool operator!=(const self_type& other) const { return node != other.node; } |
| 68 | +}; |
| 69 | + |
| 70 | +template <typename T> |
| 71 | +class list_const_iterator { |
| 72 | + public: |
| 73 | + using node_type = list_node<T>; |
| 74 | + using base_node_type = list_node_base; |
| 75 | + using self_type = list_const_iterator<T>; |
| 76 | + using value_type = T; |
| 77 | + using pointer = const T*; |
| 78 | + using reference = const T&; |
| 79 | + |
| 80 | + const base_node_type* node; |
| 81 | + |
| 82 | + list_const_iterator(const base_node_type* n) : node(n) {} |
| 83 | + |
| 84 | + reference operator*() const { |
| 85 | + return static_cast<const node_type*>(node)->data; |
| 86 | + } |
| 87 | + pointer operator->() const { |
| 88 | + return &static_cast<const node_type*>(node)->data; |
| 89 | + } |
| 90 | + |
| 91 | + self_type& operator++() { |
| 92 | + node = node->next; |
| 93 | + return *this; |
| 94 | + } |
| 95 | + |
| 96 | + self_type operator++(int) { |
| 97 | + self_type tmp = *this; |
| 98 | + node = node->next; |
| 99 | + return tmp; |
| 100 | + } |
| 101 | + |
| 102 | + self_type& operator--() { |
| 103 | + node = node->prev; |
| 104 | + return *this; |
| 105 | + } |
| 106 | + |
| 107 | + self_type operator--(int) { |
| 108 | + self_type tmp = *this; |
| 109 | + node = node->prev; |
| 110 | + return tmp; |
| 111 | + } |
| 112 | + |
| 113 | + bool operator==(const self_type& other) const { return node == other.node; } |
| 114 | + bool operator!=(const self_type& other) const { return node != other.node; } |
| 115 | +}; |
| 116 | + |
| 117 | +template <typename T> |
| 118 | +class list { |
| 119 | + public: |
| 120 | + using node_type = list_node<T>; |
| 121 | + using base_node_type = list_node_base; |
| 122 | + using iterator = list_iterator<T>; |
| 123 | + using const_iterator = list_const_iterator<T>; |
| 124 | + using value_type = T; |
| 125 | + using reference = value_type&; |
| 126 | + using const_reference = const value_type&; |
| 127 | + using size_type = size_t; |
| 128 | + |
| 129 | + list() : _size(0) { |
| 130 | + // Sentinel already initialized by default ctor of list_node_base |
| 131 | + } |
| 132 | + |
| 133 | + ~list() { clear(); } |
| 134 | + |
| 135 | + list(const list& other) : _size(0) { |
| 136 | + for (const auto& item : other) { |
| 137 | + push_back(item); |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + list& operator=(const list& other) { |
| 142 | + if (this != &other) { |
| 143 | + clear(); |
| 144 | + for (const auto& item : other) { |
| 145 | + push_back(item); |
| 146 | + } |
| 147 | + } |
| 148 | + return *this; |
| 149 | + } |
| 150 | + |
| 151 | + iterator begin() { return iterator(sentinel.next); } |
| 152 | + iterator end() { return iterator(&sentinel); } |
| 153 | + const_iterator begin() const { return const_iterator(sentinel.next); } |
| 154 | + const_iterator end() const { return const_iterator(&sentinel); } |
| 155 | + |
| 156 | + bool empty() const { return _size == 0; } |
| 157 | + size_type size() const { return _size; } |
| 158 | + |
| 159 | + T& front() { return *begin(); } |
| 160 | + const T& front() const { return *begin(); } |
| 161 | + T& back() { return *(--end()); } |
| 162 | + const T& back() const { return *(--end()); } |
| 163 | + |
| 164 | + void push_front(const T& val) { insert(begin(), val); } |
| 165 | + |
| 166 | + void push_back(const T& val) { insert(end(), val); } |
| 167 | + |
| 168 | + void pop_front() { erase(begin()); } |
| 169 | + |
| 170 | + void pop_back() { erase(--end()); } |
| 171 | + |
| 172 | + iterator insert(iterator pos, const T& val) { |
| 173 | + node_type* new_node = new node_type(val); |
| 174 | + base_node_type* p = pos.node; |
| 175 | + base_node_type* prev = p->prev; |
| 176 | + |
| 177 | + new_node->next = p; |
| 178 | + new_node->prev = prev; |
| 179 | + prev->next = new_node; |
| 180 | + p->prev = new_node; |
| 181 | + |
| 182 | + _size++; |
| 183 | + return iterator(new_node); |
| 184 | + } |
| 185 | + |
| 186 | + iterator erase(iterator pos) { |
| 187 | + if (pos == end()) return end(); |
| 188 | + |
| 189 | + base_node_type* p = pos.node; |
| 190 | + base_node_type* prev = p->prev; |
| 191 | + base_node_type* next = p->next; |
| 192 | + |
| 193 | + prev->next = next; |
| 194 | + next->prev = prev; |
| 195 | + |
| 196 | + delete static_cast<node_type*>(p); |
| 197 | + |
| 198 | + _size--; |
| 199 | + return iterator(next); |
| 200 | + } |
| 201 | + |
| 202 | + void clear() { |
| 203 | + while (!empty()) { |
| 204 | + pop_front(); |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | + private: |
| 209 | + list_node_base sentinel; |
| 210 | + size_type _size; |
| 211 | +}; |
| 212 | + |
| 213 | +} // namespace sk_std |
| 214 | + |
| 215 | +#endif // SIMPLEKERNEL_SRC_LIBCXX_INCLUDE_SK_LIST_ |
0 commit comments