/* The MIT License Copyright (c) 2016 Thomas Sarlandie thomas@sarlandie.net Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. A big thanks to NorthWestern University ~riesbeck on implementing iterators. Could not have done it without you! http://www.cs.northwestern.edu/~riesbeck/programming/c++/stl-iterator-define.html */ #pragma once //#define _USE_STD_LIST_FOR_LINKED_LIST_ #ifdef _USE_STD_LIST_FOR_LINKED_LIST_ #include template using LinkedList = std::list; #else template class LinkedListIterator; template class LinkedListConstIterator; template class LinkedListCircularIterator; template class LinkedList { private: class node { public: T value; node *next; node(const T &v) : value(v), next(0) {}; }; node *head; friend class LinkedListIterator; friend class LinkedListConstIterator; friend class LinkedListCircularIterator; public: typedef LinkedListIterator iterator; typedef LinkedListConstIterator const_iterator; using constIterator=const_iterator; typedef LinkedListCircularIterator circularIterator; LinkedList() : head(0) {}; LinkedList(const LinkedList &l) : head(0) { for (constIterator it = l.begin(); it != l.end(); it++) { add(*it); } }; ~LinkedList() { clear(); }; LinkedList& operator=(const LinkedList &l) { clear(); for (constIterator it = l.begin(); it != l.end(); it++) { add(*it); } return *this; }; void push_back(const T &v) { if (head == 0) { head = new node(v); } else { node *n = head; while (n->next != 0) { n = n->next; } n->next = new node(v); } }; inline void add(const T &v) { push_back(v); } iterator insert(iterator pos, const T& v) { if ( head==0 || pos._current==head ) { head=new node(v); head->next=pos._current; pos._current=head; } else { node *n; for ( n=head;n->next!=pos._current; n=n->next ); n->next=new node(v); n->next->next=pos._current; pos._current=n->next; } return pos; } T& front() { return head->value; } T& back() { node *n = head; while ( n!=0 && n->next!=0 ) { n=n->next; } return n->value; } void remove(const T &v) { node *n = head; // remove from beginning while ( n!=0 && n->value==v ) { head=n->next; delete(n); n=head; } while ( n!=0 ) { node *del=n->next; if ( del!=0 && del->value==v ) { n->next=del->next; delete(del); } n=n->next; } } void clear() { node *n = head; while (n != 0) { node *next = n->next; delete(n); n = next; } head = 0; }; iterator erase(LinkedListIterator l) { if ( l==end() ) return l; node *dn = l._current; l++; if ( dn==head ) { head=dn->next; } else { node *n=head; for ( ;n->next!=dn;n=n->next ); n->next=dn->next; } delete dn; return l; } void removeFirst() { node *n = head; if (head) { head = head->next; delete(n); } }; iterator begin() { return iterator(head); }; constIterator begin() const { return constIterator(head); }; iterator end() { return iterator(0); }; constIterator end() const { return constIterator(0); }; circularIterator circularBegin() { return circularIterator(head); }; circularIterator circularEnd() { return circularIterator(0); }; int size() const { LinkedList::node *n = head; int sz = 0; while (n != 0) { n = n->next; sz++; } return sz; }; bool operator==(const LinkedList &l) const { auto it=begin(); auto oit=l.begin(); for (;it!=end() && oit!=l.end() && (*it)==(*oit); it++, oit++); return ( (*it)==(*oit) ); }; bool operator!=(const LinkedList &l) const { return !(*this==l); }; template< class Compare > void sort( Compare comp ) { if ( head==0 || head->next==0 ) return; // Empty list or 1 element list bool sortDone; do { sortDone=true; node *pa=head; node *a=head; node *b=a->next; while ( b!=0 ) { if ( !(*comp)(b->value,a->value) ) { pa=a; } else { // sort required sortDone=false; a->next=b->next; b->next=a; if ( a==head ) { head=b; } else { pa->next=b; } } a=pa->next; b=a->next; } } while ( !sortDone ); } protected: template friend void MoveListItemForward(LinkedList &list, const L &v); template friend void MoveListItemBack(LinkedList &list, const L &v); void moveBack(const T &v) { node *n = head; if ( n==0 || n->value==v ) return; // can not move node *p=n; n=n->next; if ( n!=0 && n->value==v ) { // move second head->next=n->next; head=n; n->next=p; } node *pp=p; for (p=n,n=n->next;n!=0 && n->value!=v; pp=p, p=n, n=n->next ); if ( n==0 ) return; p->next=n->next; pp->next=n; n->next=p; } void moveForward(const T &v) { node *n = head; if ( n==0 || n->next==0 ) return; // can not move, only one value node *p=n; n=n->next; if ( p->value==v ) { // move first head=n; p->next=n->next; n->next=p; } node *pp=p; for (p=n,n=n->next;n!=0 && p->value!=v; pp=p, p=n, n=n->next ); if ( n==0 ) return; pp->next=n; p->next=n->next; n->next=p; } }; template class LinkedListIterator { friend class LinkedList; protected: typename LinkedList::node *_current; public: LinkedListIterator(typename LinkedList::node *node=0) : _current(node) {}; LinkedListIterator& operator=(const LinkedListIterator &l) { _current = l._current; return *this; }; LinkedListIterator& operator=(const LinkedListConstIterator &l) { _current = l._current; return *this; }; bool operator==(LinkedListIterator l) { return l._current == _current; } bool operator!=(LinkedListIterator l) { return l._current != _current; } LinkedListIterator & operator++() { if ( _current!=0) _current = _current->next; return *this; } // Postfix operator takes an argument (that we do not use) LinkedListIterator operator++(int) { LinkedListIterator clone(*this); ++(*this); return clone; } T & operator*() { return _current->value; } T * operator->() { return &(operator*()); } }; template class LinkedListConstIterator { protected: friend class LinkedListIterator; typename LinkedList::node const *_current; public: LinkedListConstIterator(typename LinkedList::node const *node) : _current(node) {}; bool operator==(LinkedListConstIterator l) { return l._current == _current; } bool operator!=(LinkedListConstIterator l) { return l._current != _current; } LinkedListConstIterator & operator++() { if ( _current!=0) _current = _current->next; return *this; } // Postfix operator takes an argument (that we do not use) LinkedListConstIterator operator++(int) { LinkedListConstIterator clone(*this); _current = _current->next; return clone; } const T & operator*() { return _current->value; } }; template class LinkedListCircularIterator : public LinkedListIterator { protected: typename LinkedList::node *_head; public: LinkedListCircularIterator(typename LinkedList::node *head) : LinkedListIterator(head), _head(head) {}; LinkedListCircularIterator & operator++() { if (this->_current->next) { this->_current = this->_current->next; } else { this->_current = this->_head; } return *this; }; LinkedListIterator operator++(int) { LinkedListIterator clone(*this); ++(*this); return clone; }; }; #ifdef DEBUG_TEST_LINKED_LIST LinkedList DoubleList; void PrintTestList() { for (auto it=DoubleList.begin(); it!=DoubleList.end(); it++) { Serial.println((*it)); } } void TestList() { DoubleList.add(5); DoubleList.add(6); DoubleList.add(9); PrintTestList(); DoubleList.remove(6); PrintTestList(); } #endif #endif template void MoveListItemForward(LinkedList &list, const T &v) { #ifdef _USE_STD_LIST_FOR_LINKED_LIST_ auto it=list.begin(); if ( it==list.end() ) return; // Empty list for ( ;it!=list.end() && (*it)!=v; it++); if ( it==list.end() ) return; // not found auto itn=it; itn++; if ( itn==list.end() ) return; // v is last value itn++; list.erase(it); list.insert(itn,v); #else list.moveForward(v); #endif } template void MoveListItemBack(LinkedList &list, const T &v) { #ifdef _USE_STD_LIST_FOR_LINKED_LIST_ auto it=list.begin(); if ( it==list.end() ) return; // Empty list if ( (*it)==v ) return; // v at begin auto itp=it; it++; for ( ;it!=list.end() && (*it)!=v; itp=it, it++); if ( it==list.end() ) return; // not found list.erase(it); list.insert(itp,v); #else list.moveBack(v); #endif }