The preset dropdown reset any time the value is changed, which includes on parameter loads from the radio. It should only reset on user input, but it's not worth finding out how right now.
157 lines
3.3 KiB
C++
157 lines
3.3 KiB
C++
#pragma once
|
|
|
|
template <typename DataType>
|
|
class LinkedList {
|
|
|
|
struct Node {
|
|
DataType data;
|
|
Node* next;
|
|
Node* previous;
|
|
|
|
Node(DataType data, Node* next, Node* previous):
|
|
data(data),
|
|
next(next),
|
|
previous(previous)
|
|
{}
|
|
};
|
|
|
|
int count = 0;
|
|
Node* head = nullptr;
|
|
Node* tail = nullptr;
|
|
|
|
public:
|
|
class Iterator {
|
|
Node *node = nullptr;
|
|
public:
|
|
Iterator(Node* node)
|
|
: node(node) {}
|
|
|
|
bool advance(size_t n) {
|
|
size_t i = 0;
|
|
if (n == 0) {
|
|
return true;
|
|
}
|
|
|
|
for (; node && (i < n); ++i) {
|
|
node = node->next;
|
|
}
|
|
return (i > 0);
|
|
}
|
|
|
|
DataType& operator* ()
|
|
{
|
|
return node->data;
|
|
}
|
|
|
|
DataType* operator-> ()
|
|
{
|
|
return &(node->data);
|
|
}
|
|
|
|
Iterator operator++ (int) {
|
|
assert(advance(1));
|
|
Iterator i(node);
|
|
return i;
|
|
}
|
|
|
|
bool operator==(const Iterator& right) const {
|
|
return node == right.node;
|
|
}
|
|
|
|
bool operator!=(const Iterator& right) const {
|
|
return node != right.node;
|
|
}
|
|
};
|
|
|
|
void pushFront(DataType data) {
|
|
auto* new_node = new Node(data, head, nullptr);
|
|
|
|
if (head != nullptr) {
|
|
head->previous = new_node;
|
|
}
|
|
|
|
if (tail == nullptr) {
|
|
tail = new_node;
|
|
}
|
|
|
|
head = new_node;
|
|
count++;
|
|
}
|
|
|
|
void pushBack(DataType data) {
|
|
auto* new_node = new Node(data, nullptr, tail);
|
|
|
|
if (head == nullptr) {
|
|
head = new_node;
|
|
}
|
|
|
|
if (tail != nullptr) {
|
|
tail->next = new_node;
|
|
}
|
|
|
|
tail = new_node;
|
|
count++;
|
|
}
|
|
|
|
void popFront() {
|
|
if (head != nullptr) {
|
|
bool is_last_node = (head == tail);
|
|
Node* node_to_delete = head;
|
|
head = node_to_delete->next;
|
|
if (is_last_node) {
|
|
tail = nullptr;
|
|
}
|
|
delete node_to_delete;
|
|
count--;
|
|
}
|
|
}
|
|
|
|
void popBack() {
|
|
if (tail != nullptr) {
|
|
bool is_last_node = (head == tail);
|
|
Node* node_to_delete = tail;
|
|
tail = node_to_delete->previous;
|
|
if (is_last_node) {
|
|
head = nullptr;
|
|
}
|
|
delete node_to_delete;
|
|
count--;
|
|
}
|
|
}
|
|
|
|
DataType back() const {
|
|
assert(tail != nullptr);
|
|
return tail->data;
|
|
}
|
|
|
|
DataType front() const {
|
|
assert(head != nullptr);
|
|
return head->data;
|
|
}
|
|
|
|
Iterator begin() const {
|
|
return Iterator(head);
|
|
}
|
|
|
|
Iterator end() const {
|
|
return Iterator(nullptr);
|
|
}
|
|
|
|
bool empty() const {
|
|
return head == nullptr;
|
|
}
|
|
|
|
int size() const { return count; }
|
|
|
|
DataType operator [] (int i) const {
|
|
auto iter = begin();
|
|
assert(iter.advance(i));
|
|
return *iter;
|
|
}
|
|
DataType& operator [] (int i) {
|
|
auto iter = begin();
|
|
assert(iter.advance(i));
|
|
return *iter;
|
|
}
|
|
};
|