Viewing file: ilist.h (6.85 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* Copyright (c) 2019, 2020, MariaDB
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef ILIST_H #define ILIST_H
#include "my_dbug.h"
#include <cstddef> #include <iterator>
// Derive your class from this struct to insert to a linked list. template <class Tag= void> struct ilist_node { #ifndef DBUG_OFF ilist_node() noexcept : next(NULL), prev(NULL) {} #else ilist_node() = default; #endif
ilist_node(ilist_node *next, ilist_node *prev) noexcept : next(next), prev(prev) { }
ilist_node *next; ilist_node *prev; };
// Modelled after std::list<T> template <class T, class Tag= void> class ilist { public: typedef ilist_node<Tag> ListNode; class Iterator;
// All containers in C++ should define these types to implement generic // container interface. typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type &reference; typedef const value_type &const_reference; typedef T *pointer; typedef const T *const_pointer; typedef Iterator iterator; typedef Iterator const_iterator; /* FIXME */ typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const iterator> const_reverse_iterator;
class Iterator { public: // All iterators in C++ should define these types to implement generic // iterator interface. typedef std::bidirectional_iterator_tag iterator_category; typedef T value_type; typedef std::ptrdiff_t difference_type; typedef T *pointer; typedef T &reference;
Iterator(ListNode *node) noexcept : node_(node) { DBUG_ASSERT(node_ != nullptr); }
Iterator &operator++() noexcept { node_= node_->next; DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator++(int) noexcept { Iterator tmp(*this); operator++(); return tmp; }
Iterator &operator--() noexcept { node_= node_->prev; DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator--(int) noexcept { Iterator tmp(*this); operator--(); return tmp; }
reference operator*() noexcept { return *static_cast<pointer>(node_); } pointer operator->() noexcept { return static_cast<pointer>(node_); }
friend bool operator==(const Iterator &lhs, const Iterator &rhs) noexcept { return lhs.node_ == rhs.node_; } friend bool operator!=(const Iterator &lhs, const Iterator &rhs) noexcept { return !(lhs == rhs); }
private: ListNode *node_;
friend class ilist; };
ilist() noexcept : sentinel_(&sentinel_, &sentinel_) {}
reference front() noexcept { return *begin(); } reference back() noexcept { return *--end(); } const_reference front() const noexcept { return *begin(); } const_reference back() const noexcept { return *--end(); }
iterator begin() noexcept { return iterator(sentinel_.next); } const_iterator begin() const noexcept { return iterator(const_cast<ListNode *>(sentinel_.next)); } iterator end() noexcept { return iterator(&sentinel_); } const_iterator end() const noexcept { return iterator(const_cast<ListNode *>(&sentinel_)); }
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } const_reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } reverse_iterator rend() noexcept { return reverse_iterator(begin()); } const_reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
bool empty() const noexcept { return sentinel_.next == &sentinel_; }
// Not implemented because it's O(N) // size_type size() const // { // return static_cast<size_type>(std::distance(begin(), end())); // }
void clear() noexcept { sentinel_.next= &sentinel_; sentinel_.prev= &sentinel_; }
iterator insert(iterator pos, reference value) noexcept { ListNode *curr= pos.node_; ListNode *prev= pos.node_->prev;
prev->next= &value; curr->prev= &value;
static_cast<ListNode &>(value).prev= prev; static_cast<ListNode &>(value).next= curr;
return iterator(&value); }
iterator erase(iterator pos) noexcept { ListNode *prev= pos.node_->prev; ListNode *next= pos.node_->next;
prev->next= next; next->prev= prev;
#ifndef DBUG_OFF ListNode *curr= pos.node_; curr->prev= nullptr; curr->next= nullptr; #endif
return next; }
void push_back(reference value) noexcept { insert(end(), value); } void pop_back() noexcept { erase(end()); }
void push_front(reference value) noexcept { insert(begin(), value); } void pop_front() noexcept { erase(begin()); }
// STL version is O(n) but this is O(1) because an element can't be inserted // several times in the same ilist. void remove(reference value) noexcept { erase(iterator(&value)); }
private: ListNode sentinel_; };
// Similar to ilist but also has O(1) size() method. template <class T, class Tag= void> class sized_ilist : public ilist<T, Tag> { typedef ilist<T, Tag> BASE;
public: // All containers in C++ should define these types to implement generic // container interface. typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type &reference; typedef const value_type &const_reference; typedef T *pointer; typedef const T *const_pointer; typedef typename BASE::Iterator iterator; typedef const typename BASE::Iterator const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const iterator> const_reverse_iterator;
sized_ilist() noexcept : size_(0) {}
size_type size() const noexcept { return size_; }
void clear() noexcept { BASE::clear(); size_= 0; }
iterator insert(iterator pos, reference value) noexcept { ++size_; return BASE::insert(pos, value); }
iterator erase(iterator pos) noexcept { --size_; return BASE::erase(pos); }
void push_back(reference value) noexcept { insert(BASE::end(), value); } void pop_back() noexcept { erase(BASE::end()); }
void push_front(reference value) noexcept { insert(BASE::begin(), value); } void pop_front() noexcept { erase(BASE::begin()); }
void remove(reference value) noexcept { erase(iterator(&value)); }
private: size_type size_; };
#endif
|