Dynalib Utils
DynaLinkedListImpl.h
Go to the documentation of this file.
1 //
2 // Created by Ken Kopelson on 4/03/18.
3 //
4 
5 #ifndef DYNALINKEDLISTIMPL_H
6 #define DYNALINKEDLISTIMPL_H
7 
8 #include "DynaLinkedList.h"
9 
10 #define MAKE_LINKEDLISTTYPE_INSTANCE(C, T) \
11  template class LinkedEntry<C>; \
12  typedef LinkedEntry<C> T##LinkedEntry; \
13  template class DynaLinkedList<C>; \
14  typedef DynaLinkedList<C> T##LinkedList
15 
16 //===========================================================================
17 // LinkedEntry Methods
18 //===========================================================================
19 template <class T> LinkedEntry<T>::LinkedEntry(T* object, bool ownsObject) :
20  _owner(nullptr), _prev(nullptr), _next(nullptr), _ownsObject(ownsObject), _object(object){}
21 
22 template <class T> LinkedEntry<T>::~LinkedEntry() {
23  if (_object != nullptr && _ownsObject) {
24  delete _object;
25  _object = nullptr;
26  }
27 }
28 
29 template <class T> LinkedEntry<T>::LinkedEntry(const LinkedEntry<T>& other) {
30  _owner = nullptr;
31  _prev = nullptr;
32  _next = nullptr;
33  _object = other._object;
34  _ownsObject = other._ownsObject;
35 }
36 
37 template <class T> LinkedEntry<T>* LinkedEntry<T>::copy() {
38  return new LinkedEntry<T>(*this);
39 }
40 
41 
43  return _owner;
44 }
45 
47  return _prev;
48 }
49 
50 template <class T> LinkedEntry<T>* LinkedEntry<T>::getNext() {
51  return _next;
52 }
53 
54 template <class T> bool LinkedEntry<T>::isOwnsObject() {
55  return _ownsObject;
56 }
57 
58 template <class T> T* LinkedEntry<T>::getObject() const {
59  return _object;
60 }
61 
63  _owner = owner;
64  return this;
65 }
66 
68  _next = next;
69  return this;
70 }
71 
73  _prev = previous;
74  return this;
75 }
76 
77 template <class T> LinkedEntry<T>* LinkedEntry<T>::setObject(T* object) {
78  _object = object;
79  return this;
80 }
81 
82 //=========================================================================================
83 // Miscellaneous Methods
84 //=========================================================================================
85 template <class T> DynaLinkedList<T>::DynaLinkedList() :
86  _first(nullptr), _last(nullptr), _ownsMembers(true), _entryCount(0){}
87 
88 template<class T>
90  clear();
91 }
92 
93 template<class T>
95  _ownsMembers(other._ownsMembers), _entryCount(other._entryCount) {
96  auto it = LinkedEntryIter<T>(const_cast<DynaLinkedList<T>*>(&other), _first);
97  for (LinkedEntry<T>* entry : it) {
98  pushEntry(entry->copy());
99  }
100 }
101 
102 template<class T>
104  return new DynaLinkedList<T>(*this);
105 }
106 
107 template <class T> void DynaLinkedList<T>::clear() {
108  auto it = LinkedEntryIter<T>(this, _first);
109  while (it.hasNext()) {
110  it.remove();
111  }
112  _first = nullptr;
113  _last = nullptr;
114  _entryCount = 0;
115 }
116 
117 template<class T>
119  return _entryCount;
120 }
121 
122 
123 template<class T>
125  return _first;
126 }
127 
128 template<class T>
130  return _last;
131 }
132 
133 template<class T>
135  return entry != nullptr && entry == _first;
136 }
137 
138 template<class T>
140  return entry != nullptr && entry == _last;
141 }
142 
143 template<class T>
145  return _ownsMembers;
146 }
147 
148 template<class T>
149 void DynaLinkedList<T>::setOwnsMembers(bool ownsMembers) {
150  _ownsMembers = ownsMembers;
151 }
152 
153 template<class T>
155  auto it = LinkedEntryIter<T>(this, _first);
156  int idx = 0;
157  for (LinkedEntry<T>* entry : it) {
158  if (idx == index)
159  return entry;
160  ++idx;
161  }
162  return nullptr;
163 }
164 
165 template<class T>
167  return _entryCount;
168 }
169 
170 template<class T>
172  return _entryCount;
173 }
174 
175 //=========================================================================================
176 // Find/Locate Methods
177 //=========================================================================================
178 template<class T>
180  auto it = LinkedEntryIter<T>(this, _first);
181  int index = 0;
182  for (LinkedEntry<T>* e : it) {
183  if (e == entry)
184  return index;
185  ++index;
186  }
187  return INVALID_INDEX;
188 }
189 
190 template<class T>
192  auto it = LinkedEntryIter<T>(this, _first);
193  for (LinkedEntry<T>* entry : it) {
194  if (entry->getObject() == object)
195  return entry;
196  }
197  return nullptr;
198 }
199 
200 template<class T>
202  auto it = LinkedIter<T>(this, _first);
203  int index = 0;
204  for (T* obj : it) {
205  if (obj == object)
206  return index;
207  ++index;
208  }
209  return INVALID_INDEX;
210 }
211 
212 template<class T>
213 T* DynaLinkedList<T>::find(T* object) {
214  auto it = LinkedIter<T>(this, _first);
215  for (T* obj : it) {
216  if (obj == object)
217  return obj;
218  }
219  return nullptr;
220 }
221 
222 //=========================================================================================
223 // Entry-Oriented Methods
224 //=========================================================================================
225 template<class T>
227  if (entry != nullptr) {
228  if (entry->getOwner() == nullptr) {
229  if (after) {
230  if (destLink == nullptr)
231  destLink = _last;
232  if (_first == nullptr)
233  _first = entry;
234  if (_last == nullptr || destLink == _last)
235  _last = entry;
236  if (destLink != nullptr) {
237  entry->setPrevious(destLink);
238  entry->setNext(destLink->getNext());
239  if (destLink->getNext() != nullptr)
240  destLink->getNext()->setPrevious(entry);
241  destLink->setNext(entry);
242  }
243  }
244  else {
245  if (destLink == nullptr)
246  destLink = _first;
247  if (_first == nullptr || destLink == _first)
248  _first = entry;
249  if (_last == nullptr)
250  _last = entry;
251  if (destLink != nullptr) {
252  entry->setPrevious(destLink->getPrevious());
253  entry->setNext(destLink);
254  if (destLink->getPrevious() != nullptr)
255  destLink->getPrevious()->setNext(entry);
256  destLink->setPrevious(entry);
257  }
258  }
259  entry->setOwner(this);
260  ++_entryCount;
261  }
262  else
263  entry = nullptr;
264  }
265  return entry;
266 }
267 
268 template<class T>
270  if (object != nullptr) {
271  auto* entry = new LinkedEntry<T>(object, _ownsMembers);
272  insertEntry(entry, destLink, after);
273  return entry;
274  }
275  return nullptr;
276 }
277 
278 template<class T>
280  return insertEntry(entry, _last, true);
281 }
282 
283 template<class T>
285  return insertEntry(object, _last, true);
286 }
287 
288 template<class T>
290  return insertEntry(entry, _first, false);
291 }
292 
293 template<class T>
295  return insertEntry(object, _first, false);
296 }
297 
299  if (entry != nullptr) {
300  if (entry->getOwner() == this) {
301  if (entry->getPrevious() != nullptr)
302  entry->getPrevious()->setNext(entry->getNext());
303  if (entry->getNext() != nullptr)
304  entry->getNext()->setPrevious(entry->getPrevious());
305  if (_first == entry)
306  _first = entry->getNext();
307  if (_last == entry)
308  _last = entry->getPrevious();
309  entry->setNext(nullptr);
310  entry->setPrevious(nullptr);
311  entry->setOwner(nullptr);
312  --_entryCount;
313  }
314  else
315  entry = nullptr;
316  }
317  return entry;
318 }
319 
320 template <class T> bool DynaLinkedList<T>::deleteEntry(LinkedEntry<T>* entry) {
321  if (entry != nullptr)
322  entry = removeEntry(entry);
323  if (entry != nullptr) {
324  delete entry;
325  return true;
326  }
327  return false;
328 }
329 
330 template<class T>
332  return removeEntry(_first);
333 }
334 
335 template<class T>
337  return removeEntry(_last);
338 }
339 
340 template<class T>
341 bool DynaLinkedList<T>::move(LinkedEntry<T>* entry, LinkedEntry<T>* destEntry, bool after) {
342  if (entry != nullptr && entry != destEntry) {
343  if (entry->getOwner() == this)
344  removeEntry(entry);
345  else if (entry->getOwner() != nullptr)
346  entry->getOwner()->removeEntry(entry);
347  if (destEntry == nullptr || destEntry->getOwner() == this) {
348  insertEntry(entry, destEntry, after);
349  return true;
350  }
351  else if (destEntry->getOwner() != nullptr) {
352  destEntry->getOwner()->insertEntry(entry, destEntry, after);
353  return true;
354  }
355  }
356  return false;
357 }
358 
359 template<class T>
361  return move(entry, _first, false);
362 }
363 
364 template<class T>
366  return move(entry, _last, true);
367 }
368 
369 template<class T>
371  if (atEntry != nullptr && atEntry->getOwner() == this) {
372  auto* newList = new DynaLinkedList<T>();
373  newList->_first = atEntry;
374  newList->_last = _last;
375  if (atEntry->getPrevious() != nullptr) {
376  atEntry->getPrevious()->setNext(nullptr);
377  _last = atEntry->getPrevious();
378  atEntry->setPrevious(nullptr);
379  }
380  else {
381  _first = _last = nullptr;
382  }
383  auto it = LinkedEntryIter<T>(newList, _first);
384  int count = 0;
385  for (LinkedEntry<T>* entry : it) {
386  entry->setOwner(newList);
387  ++count;
388  }
389  _entryCount -= count;
390  newList->_entryCount = count;
391  return newList;
392  }
393  return nullptr;
394 }
395 
396 template<class T>
398  if (list != this && list->_first != nullptr) {
399  if (_last != nullptr) {
400  _last->setNext(list->_first);
401  if (list->_first != nullptr)
402  list->_first->setPrevious(_last);
403  _last = list->_last;
404  }
405  else {
406  _first = list->_first;
407  _last = list->_last;
408  }
409  auto it = LinkedEntryIter<T>(list, list->_first);
410  int count = 0;
411  for (LinkedEntry<T>* entry : it) {
412  entry->setOwner(this);
413  ++count;
414  }
415  _entryCount += count;
416  list->_first = list->_last = nullptr;
417  list->_entryCount = 0;
418  return this;
419  }
420  return nullptr;
421 }
422 
423 //=========================================================================================
424 // Object-Oriented Methods
425 //=========================================================================================
426 template<class T>
427 T* DynaLinkedList<T>::insert(T* object, LinkedEntry<T>* destLink, bool after) {
428  if (object != nullptr) {
429  auto* entry = new LinkedEntry<T>(object, _ownsMembers);
430  insertEntry(entry, destLink, after);
431  }
432  return object;
433 }
434 
435 template<class T>
437  return insert(object, _last, true);
438 }
439 
440 template<class T>
441 T* DynaLinkedList<T>::push(T* object) {
442  return insert(object, _first, false);
443 }
444 
445 template <class T> T* DynaLinkedList<T>::remove(LinkedEntry<T>* entry) {
446  if (entry != nullptr)
447  entry = removeEntry(entry);
448  if (entry != nullptr) {
449  T* object = entry->getObject();
450  entry->setObject(nullptr);
451  delete entry;
452  return object;
453  }
454  return nullptr;
455 }
456 
457 template<class T>
459  return remove(_first);
460 }
461 
462 template<class T>
464  return remove(_last);
465 }
466 
468  return LinkedIter<T>( this, _first );
469 }
470 
471 template <class T> LinkedIter<T> DynaLinkedList<T>::end () {
472  return LinkedIter<T>( this, nullptr );
473 }
474 
475 
476 //=========================================================================================
477 // Linked Iterator Methods
478 //=========================================================================================
480  : _list(list), _current(list->getFirst()) {}
481 
483  : _current(start), _list(list) {}
484 
485 template <class T> bool LinkedIter<T>::hasNext() {
486  return _current == nullptr ? _list->getFirst() != nullptr : _current->getNext() != nullptr;
487 }
488 
489 template <class T> bool LinkedIter<T>::hasPrevious() {
490  return _current == nullptr ? _list->getLast() != nullptr : _current->getPrevious() != nullptr;
491 }
492 
493 template <class T> T* LinkedIter<T>::next() {
494  _current = _current == nullptr ? _list->getFirst() : _current->getNext();
495  return _current != nullptr ? _current->getObject() : nullptr;
496 }
497 
498 template <class T> T* LinkedIter<T>::previous() {
499  _current = _current == nullptr ? _list->getLast() : _current->getPrevious();
500  return _current != nullptr ? _current->getObject() : nullptr;
501 }
502 
503 template <class T> void LinkedIter<T>::remove() {
504  if (_current != nullptr) {
505  LinkedEntry<T>* next = _current->getNext();
506  if (next == nullptr)
507  next = _current->getPrevious();
508  _list->deleteEntry(_current);
509  _current = next;
510  }
511 }
512 
513 template <class T> bool LinkedIter<T>::operator== (const LinkedIter<T>& other) const {
514  return _current == other._current;
515 }
516 
517 template <class T> bool LinkedIter<T>::operator!= (const LinkedIter<T>& other) const {
518  return _current != other._current;
519 }
520 
521 template <class T> T* LinkedIter<T>::operator* () const {
522  return _current->getObject();
523 }
524 
525 template <class T> const LinkedIter<T>& LinkedIter<T>::operator++ () {
526  next();
527  return *this;
528 }
529 
530 template <class T> const LinkedIter<T>& LinkedIter<T>::operator-- () {
531  previous();
532  return *this;
533 }
534 
535 template <class T> LinkedIter<T> LinkedIter<T>::begin() {
536  return LinkedIter<T>( _list, _list->getFirst() );
537 }
538 
539 template <class T> LinkedIter<T> LinkedIter<T>::end() {
540  return LinkedIter<T>( _list, nullptr );
541 }
542 
543 
544 //=========================================================================================
545 // Linked Entry Iterator Methods
546 //=========================================================================================
548  : _list(list), _current(list->getFirst()) {}
549 
551  : _current(start),_list(list) {}
552 
553 template <class T> bool LinkedEntryIter<T>::hasNext() {
554  return _current == nullptr ? _list->getFirst() != nullptr :
555  ( _current->getNext() != nullptr || _list->getLast() != nullptr );
556 }
557 
558 template <class T> bool LinkedEntryIter<T>::hasPrevious() {
559  return _current == nullptr ? _list->getLast() != nullptr :
560  ( _current->getPrevious() != nullptr || _list->getFirst() != nullptr );
561 }
562 
564  _current = _current == nullptr ? _list->getFirst() :
565  ( _current->getNext() != nullptr ? _current->getNext() : _list->getLast() );
566  return _current;
567 }
568 
570  _current = _current == nullptr ? _list->getLast() :
571  ( _current->getPrevious() != nullptr ? _current->getPrevious() : _list->getFirst() );
572  return _current;
573 }
574 
575 template <class T> void LinkedEntryIter<T>::remove() {
576  if (_current != nullptr) {
577  LinkedEntry<T>* next = _current->getNext();
578  if (next == nullptr)
579  next = _current->getPrevious();
580  _list->deleteEntry(_current);
581  _current = next;
582  }
583 }
584 
585 template <class T> bool LinkedEntryIter<T>::operator== (const LinkedEntryIter<T>& other) const {
586  return _current == other._current;
587 }
588 
589 template <class T> bool LinkedEntryIter<T>::operator!= (const LinkedEntryIter<T>& other) const {
590  return _current != other._current;
591 }
592 
593 template <class T> LinkedEntry<T>* LinkedEntryIter<T>::operator* () const {
594  return _current;
595 }
596 
598  next();
599  return *this;
600 }
601 
603  previous();
604  return *this;
605 }
606 
608  return LinkedEntryIter<T>( _list, _list->getFirst() );
609 }
610 
612  return LinkedEntryIter<T>( _list, nullptr );
613 }
614 
615 #endif //DYNALINKEDLISTIMPL_H
LinkedIter< T > end()
Definition: DynaLinkedListImpl.h:471
T * getObject() const
Definition: DynaLinkedListImpl.h:58
T * append(T *object)
Definition: DynaLinkedListImpl.h:436
DynaLinkedList< T > * copy() override
Definition: DynaLinkedListImpl.h:103
T * insert(T *object, LinkedEntry< T > *destLink, bool after)
Definition: DynaLinkedListImpl.h:427
DynaLinkedList()
Definition: DynaLinkedListImpl.h:85
void setOwnsMembers(bool ownsMembers)
Definition: DynaLinkedListImpl.h:149
LinkedEntry(T *object, bool ownsObject)
Definition: DynaLinkedListImpl.h:19
LinkedEntryIter< T > end()
Definition: DynaLinkedListImpl.h:611
LinkedEntry< T > * previous()
Definition: DynaLinkedListImpl.h:569
LinkedEntry< T > * operator*() const
Definition: DynaLinkedListImpl.h:593
LinkedEntry< T > * setOwner(DynaLinkedList< T > *owner)
Definition: DynaLinkedListImpl.h:62
bool hasNext()
Definition: DynaLinkedListImpl.h:553
bool isLast(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:139
int indexOfEntry(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:179
LinkedIter< T > end()
Definition: DynaLinkedListImpl.h:539
Definition: DynaLinkedList.h:29
T * find(T *object)
Definition: DynaLinkedListImpl.h:213
T * operator*() const
Definition: DynaLinkedListImpl.h:521
LinkedEntry< T > * getLast() const
Definition: DynaLinkedListImpl.h:129
Definition: DynaLinkedList.h:32
bool hasPrevious()
Definition: DynaLinkedListImpl.h:558
#define INVALID_INDEX
Definition: DynaArray.h:20
bool operator==(const LinkedEntryIter< T > &other) const
Definition: DynaLinkedListImpl.h:585
int indexOf(T *object)
Definition: DynaLinkedListImpl.h:201
virtual ~LinkedEntry()
Definition: DynaLinkedListImpl.h:22
const LinkedIter< T > & operator++()
Definition: DynaLinkedListImpl.h:525
bool isOwnsObject()
Definition: DynaLinkedListImpl.h:54
int size()
Definition: DynaLinkedListImpl.h:118
LinkedEntry< T > * next()
Definition: DynaLinkedListImpl.h:563
void remove()
Definition: DynaLinkedListImpl.h:503
LinkedEntryIter< T > begin()
Definition: DynaLinkedListImpl.h:607
LinkedEntry< T > * copy() override
Definition: DynaLinkedListImpl.h:37
bool operator!=(const LinkedEntryIter< T > &other) const
Definition: DynaLinkedListImpl.h:589
LinkedEntry< T > * appendEntry(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:279
bool hasNext()
Definition: DynaLinkedListImpl.h:485
LinkedEntry< T > * setObject(T *object)
Definition: DynaLinkedListImpl.h:77
LinkedEntry< T > * get(int index)
Definition: DynaLinkedListImpl.h:154
LinkedEntry< T > * insertEntry(LinkedEntry< T > *entry, LinkedEntry< T > *destLink, bool after)
Definition: DynaLinkedListImpl.h:226
bool isFirst(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:134
bool operator==(const LinkedIter< T > &other) const
Definition: DynaLinkedListImpl.h:513
bool move(LinkedEntry< T > *entry, LinkedEntry< T > *destEntry, bool after)
Definition: DynaLinkedListImpl.h:341
LinkedEntry< T > * setPrevious(LinkedEntry< T > *previous)
Definition: DynaLinkedListImpl.h:72
LinkedEntry< T > * pushEntry(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:289
T * push(T *object)
Definition: DynaLinkedListImpl.h:441
T * popLast()
Definition: DynaLinkedListImpl.h:463
uint count()
Definition: DynaLinkedListImpl.h:171
uint getCount()
Definition: DynaLinkedListImpl.h:166
Definition: DynaLinkedList.h:28
bool isOwnsMembers()
Definition: DynaLinkedListImpl.h:144
Definition: DynaLinkedList.h:30
LinkedEntryIter(DynaLinkedList< T > *list)
Definition: DynaLinkedListImpl.h:547
LinkedEntry< T > * getNext()
Definition: DynaLinkedListImpl.h:50
LinkedEntry< T > * popEntry()
Definition: DynaLinkedListImpl.h:331
T * remove(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:445
T * previous()
Definition: DynaLinkedListImpl.h:498
bool deleteEntry(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:320
const LinkedIter< T > & operator--()
Definition: DynaLinkedListImpl.h:530
LinkedIter< T > begin()
Definition: DynaLinkedListImpl.h:535
bool moveToLast(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:365
LinkedIter< T > begin()
Definition: DynaLinkedListImpl.h:467
const LinkedEntryIter< T > & operator--()
Definition: DynaLinkedListImpl.h:602
LinkedEntry< T > * getPrevious()
Definition: DynaLinkedListImpl.h:46
bool hasPrevious()
Definition: DynaLinkedListImpl.h:489
LinkedEntry< T > * popLastEntry()
Definition: DynaLinkedListImpl.h:336
DynaLinkedList< T > * splitList(LinkedEntry< T > *atEntry)
Definition: DynaLinkedListImpl.h:370
LinkedIter(DynaLinkedList< T > *list)
Definition: DynaLinkedListImpl.h:479
T * next()
Definition: DynaLinkedListImpl.h:493
LinkedEntry< T > * removeEntry(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:298
LinkedEntry< T > * findEntry(T *object)
Definition: DynaLinkedListImpl.h:191
bool operator!=(const LinkedIter< T > &other) const
Definition: DynaLinkedListImpl.h:517
virtual ~DynaLinkedList()
Definition: DynaLinkedListImpl.h:89
bool moveToFirst(LinkedEntry< T > *entry)
Definition: DynaLinkedListImpl.h:360
DynaLinkedList< T > * getOwner()
Definition: DynaLinkedListImpl.h:42
void remove()
Definition: DynaLinkedListImpl.h:575
T * pop()
Definition: DynaLinkedListImpl.h:458
DynaLinkedList< T > * appendList(DynaLinkedList< T > *list)
Definition: DynaLinkedListImpl.h:397
void clear()
Definition: DynaLinkedListImpl.h:107
LinkedEntry< T > * getFirst() const
Definition: DynaLinkedListImpl.h:124
LinkedEntry< T > * setNext(LinkedEntry< T > *next)
Definition: DynaLinkedListImpl.h:67
const LinkedEntryIter< T > & operator++()
Definition: DynaLinkedListImpl.h:597