Control Surface  1.1.1
MIDI Control Surface library for Arduino
LinkedList.hpp
Go to the documentation of this file.
1 /* ✔ */
2 
3 #pragma once
4 
6 
7 AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
8 
9 #include <AH/Debug/Debug.hpp>
10 #include <AH/Math/MinMaxFix.hpp>
11 #include <stdlib.h>
12 
13 #ifndef __AVR__
14 #include <iterator>
15 #endif
16 
19 
26 template <class Node>
28  public:
30  template <class INode>
32  public:
34 
35  bool operator!=(const node_iterator_base &rhs) const {
36  return node != rhs.node;
37  }
38 
39  INode &operator*() const {
40  // TODO: check node != nullptr
41  return *node;
42  }
43 
44  protected:
45  INode *node;
46  };
47 
49  template <class INode>
50  class node_iterator : public node_iterator_base<INode> {
51  public:
53 
54 #ifndef __AVR__
55  using difference_type = void;
56  using value_type = INode;
57  using pointer = INode *;
58  using reference = INode &;
59  using iterator_category = std::bidirectional_iterator_tag;
60 #endif
61 
64  // TODO: check node != nullptr
65  this->node = this->node->next;
66  return *this;
67  }
68 
71  // TODO: check node != nullptr
72  this->node = this->node->previous;
73  return *this;
74  }
75  };
76 
78  template <class INode>
79  class reverse_node_iterator : public node_iterator_base<INode> {
80  public:
82 
83 #ifndef __AVR__
84  using difference_type = void;
85  using value_type = INode;
86  using pointer = INode *;
87  using reference = INode &;
88  using iterator_category = std::bidirectional_iterator_tag;
89 #endif
90 
93  // TODO: check node != nullptr
94  this->node = this->node->previous;
95  return *this;
96  }
97 
100  // TODO: check node != nullptr
101  this->node = this->node->next;
102  return *this;
103  }
104  };
105 
106  using iterator = node_iterator<Node>;
107  using const_iterator = node_iterator<const Node>;
108  using reverse_iterator = reverse_node_iterator<Node>;
109  using const_reverse_iterator = reverse_node_iterator<const Node>;
110 
117  void append(Node *node) {
118  if (first == nullptr)
119  first = node;
120  node->previous = last;
121  if (node->previous != nullptr)
122  node->previous->next = node;
123  last = node;
124  node->next = nullptr;
125  }
126 
133  void append(Node &node) { append(&node); }
134 
144  void insertBefore(Node *toBeInserted, Node *before) {
145  if (before == first)
146  first = toBeInserted;
147  else
148  before->previous->next = toBeInserted;
149  toBeInserted->previous = before->previous;
150  toBeInserted->next = before;
151  before->previous = toBeInserted;
152  }
153 
155  void insertBefore(Node &toBeInserted, Node &before) {
156  insertBefore(&toBeInserted, &before);
157  }
158 
169  template <class Compare>
170  void insertSorted(Node *node, Compare cmp) {
171  iterator it = this->begin();
172  iterator end = this->end();
173  while (it != end) {
174  if (cmp(*node, *it)) {
175  insertBefore(*node, *it);
176  return;
177  }
178  ++it;
179  }
180  append(node);
181  }
182 
190  void insertSorted(Node *node) {
191  insertSorted(node, [](Node &lhs, Node &rhs) { return lhs < rhs; });
192  }
193 
200  void remove(Node *node) {
201  if (node->previous != nullptr)
202  node->previous->next = node->next;
203  if (node == last)
204  last = node->previous;
205  if (node->next != nullptr)
206  node->next->previous = node->previous;
207  if (node == first)
208  first = node->next;
209  node->previous = nullptr;
210  node->next = nullptr;
211  }
212 
219  void remove(Node &node) { remove(&node); }
220 
232  void moveDown(Node *node) {
233  Node *nodeB = node->previous;
234  if (nodeB == nullptr) // Can't move first node further down
235  return;
236  Node *nodeA = nodeB->previous;
237  Node *nodeD = node->next;
238 
239  if (nodeA != nullptr)
240  nodeA->next = node;
241  else
242  first = node;
243  nodeB->next = nodeD;
244  nodeB->previous = node;
245  node->next = nodeB;
246  node->previous = nodeA;
247  if (nodeD != nullptr)
248  nodeD->previous = nodeB;
249  else
250  last = nodeB;
251  }
252 
268  bool couldContain(Node *node) {
269  return node && (node == first || node->next != nullptr ||
270  node->previous != nullptr);
271  }
272 
273  iterator begin() { return {first}; }
274  iterator end() { return {nullptr}; }
275 
276  const_iterator begin() const { return {first}; }
277  const_iterator end() const { return {nullptr}; }
278 
279  reverse_iterator rbegin() { return {last}; }
280  reverse_iterator rend() { return {nullptr}; }
281 
282  const_reverse_iterator rbegin() const { return {last}; }
283  const_reverse_iterator rend() const { return {nullptr}; }
284 
286  Node *getFirst() const { return first; }
288  Node *getLast() const { return last; }
289 
290  private:
291  Node *first = nullptr;
292  Node *last = nullptr;
293 };
294 
301 template <class Node>
303  protected:
304  friend class DoublyLinkedList<Node>;
305  Node *next = nullptr;
306  Node *previous = nullptr;
307  virtual ~DoublyLinkable() = default;
308 };
309 
311 
DoublyLinkedList< AH::Updatable< NormalUpdatable > >::const_reverse_iterator
reverse_node_iterator< const AH::Updatable< NormalUpdatable > > const_reverse_iterator
Definition: LinkedList.hpp:109
DoublyLinkedList::getFirst
Node * getFirst() const
Get a pointer to the first node.
Definition: LinkedList.hpp:286
DoublyLinkedList::first
Node * first
Definition: LinkedList.hpp:291
DoublyLinkedList::rbegin
const_reverse_iterator rbegin() const
Definition: LinkedList.hpp:282
DoublyLinkedList::reverse_node_iterator
Reverse bidirectional doubly linked list iterator.
Definition: LinkedList.hpp:79
DoublyLinkedList::reverse_node_iterator::operator++
reverse_node_iterator & operator++()
Prefix increment operator.
Definition: LinkedList.hpp:92
DoublyLinkedList::node_iterator::operator++
node_iterator & operator++()
Prefix increment operator.
Definition: LinkedList.hpp:63
Warnings.hpp
DoublyLinkedList::insertBefore
void insertBefore(Node *toBeInserted, Node *before)
Insert a node before another node.
Definition: LinkedList.hpp:144
DoublyLinkedList::remove
void remove(Node &node)
Remove a node from the linked list.
Definition: LinkedList.hpp:219
DoublyLinkedList::rbegin
reverse_iterator rbegin()
Definition: LinkedList.hpp:279
DoublyLinkedList::node_iterator_base::node_iterator_base
node_iterator_base(INode *node)
Definition: LinkedList.hpp:33
DoublyLinkable::previous
Node * previous
Definition: LinkedList.hpp:306
DoublyLinkedList::node_iterator::node_iterator
node_iterator(INode *node)
Definition: LinkedList.hpp:52
DoublyLinkedList::end
iterator end()
Definition: LinkedList.hpp:274
DoublyLinkedList::reverse_node_iterator::reference
INode & reference
Definition: LinkedList.hpp:87
DoublyLinkedList::node_iterator_base::operator!=
bool operator!=(const node_iterator_base &rhs) const
Definition: LinkedList.hpp:35
AH_DIAGNOSTIC_POP
#define AH_DIAGNOSTIC_POP()
Definition: Warnings.hpp:17
DoublyLinkedList::node_iterator::value_type
INode value_type
Definition: LinkedList.hpp:56
DoublyLinkedList::node_iterator_base::node
INode * node
Definition: LinkedList.hpp:45
DoublyLinkedList::node_iterator::operator--
node_iterator & operator--()
Prefix decrement operator.
Definition: LinkedList.hpp:70
DoublyLinkedList< AH::Updatable< NormalUpdatable > >::iterator
node_iterator< AH::Updatable< NormalUpdatable > > iterator
Definition: LinkedList.hpp:106
DoublyLinkedList::insertSorted
void insertSorted(Node *node)
Insert a new node at the correct location into a sorted list, using operator<.
Definition: LinkedList.hpp:190
DoublyLinkedList::last
Node * last
Definition: LinkedList.hpp:292
DoublyLinkedList::append
void append(Node *node)
Append a node to a linked list.
Definition: LinkedList.hpp:117
DoublyLinkedList::getLast
Node * getLast() const
Get a pointer to the last node.
Definition: LinkedList.hpp:288
DoublyLinkedList::node_iterator_base::operator*
INode & operator*() const
Definition: LinkedList.hpp:39
DoublyLinkedList::end
const_iterator end() const
Definition: LinkedList.hpp:277
DoublyLinkedList< AH::Updatable< NormalUpdatable > >::const_iterator
node_iterator< const AH::Updatable< NormalUpdatable > > const_iterator
Definition: LinkedList.hpp:107
DoublyLinkedList::begin
iterator begin()
Definition: LinkedList.hpp:273
DoublyLinkedList::reverse_node_iterator::difference_type
void difference_type
Definition: LinkedList.hpp:84
DoublyLinkedList::node_iterator_base
Base class for doubly linked list iterators.
Definition: LinkedList.hpp:31
DoublyLinkedList::moveDown
void moveDown(Node *node)
Move down the given node in the linked list.
Definition: LinkedList.hpp:232
DoublyLinkedList::reverse_node_iterator::pointer
INode * pointer
Definition: LinkedList.hpp:86
DoublyLinkedList::remove
void remove(Node *node)
Remove a node from the linked list.
Definition: LinkedList.hpp:200
DoublyLinkedList::node_iterator
Forward bidirectional doubly linked list iterator.
Definition: LinkedList.hpp:50
DoublyLinkedList::rend
reverse_iterator rend()
Definition: LinkedList.hpp:280
DoublyLinkedList::node_iterator::difference_type
void difference_type
Definition: LinkedList.hpp:55
DoublyLinkedList::reverse_node_iterator::operator--
reverse_node_iterator & operator--()
Prefix decrement operator.
Definition: LinkedList.hpp:99
DoublyLinkedList::append
void append(Node &node)
Append a node to a linked list.
Definition: LinkedList.hpp:133
DoublyLinkedList< AH::Updatable< NormalUpdatable > >::reverse_iterator
reverse_node_iterator< AH::Updatable< NormalUpdatable > > reverse_iterator
Definition: LinkedList.hpp:108
DoublyLinkedList
A class for doubly linked lists.
Definition: LinkedList.hpp:27
DoublyLinkedList::node_iterator::pointer
INode * pointer
Definition: LinkedList.hpp:57
DoublyLinkable::~DoublyLinkable
virtual ~DoublyLinkable()=default
DoublyLinkable
A class that can be inherited from to allow inserting into a DoublyLinkedList.
Definition: LinkedList.hpp:302
AH_DIAGNOSTIC_WERROR
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:16
DoublyLinkedList::node_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: LinkedList.hpp:59
DoublyLinkedList::reverse_node_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: LinkedList.hpp:88
DoublyLinkable::next
Node * next
Definition: LinkedList.hpp:305
DoublyLinkedList::reverse_node_iterator::reverse_node_iterator
reverse_node_iterator(INode *node)
Definition: LinkedList.hpp:81
DoublyLinkedList::begin
const_iterator begin() const
Definition: LinkedList.hpp:276
DoublyLinkedList::insertSorted
void insertSorted(Node *node, Compare cmp)
Insert a new node at the correct location into a sorted list.
Definition: LinkedList.hpp:170
DoublyLinkedList::reverse_node_iterator::value_type
INode value_type
Definition: LinkedList.hpp:85
DoublyLinkedList::rend
const_reverse_iterator rend() const
Definition: LinkedList.hpp:283
MinMaxFix.hpp
DoublyLinkedList::node_iterator::reference
INode & reference
Definition: LinkedList.hpp:58
DoublyLinkedList::couldContain
bool couldContain(Node *node)
Check if the linked list could contain the given node.
Definition: LinkedList.hpp:268
DoublyLinkedList::insertBefore
void insertBefore(Node &toBeInserted, Node &before)
Definition: LinkedList.hpp:155