1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.collection.LinkedList;
13 
14 import hunt.collection.AbstractList;
15 import hunt.collection.AbstractSequentialList;
16 import hunt.collection.Collection;
17 import hunt.collection.Deque;
18 import hunt.collection.List;
19 
20 import hunt.Exceptions;
21 import hunt.Object;
22 import hunt.util.Common;
23 
24 import std.conv;
25 import std.container;
26 import std.range;
27 
28 import hunt.util.CompilerHelper;
29 
30 
31 /**
32  * Doubly-linked list implementation of the {@code List} and {@code Deque}
33  * interfaces.  Implements all optional list operations, and permits all
34  * elements (including {@code null}).
35  *
36  * <p>All of the operations perform as could be expected for a doubly-linked
37  * list.  Operations that index into the list will traverse the list from
38  * the beginning or the end, whichever is closer to the specified index.
39  *
40  * <p><strong>Note that this implementation is not synchronized.</strong>
41  * If multiple threads access a linked list concurrently, and at least
42  * one of the threads modifies the list structurally, it <i>must</i> be
43  * synchronized externally.  (A structural modification is any operation
44  * that adds or deletes one or more elements; merely setting the value of
45  * an element is not a structural modification.)  This is typically
46  * accomplished by synchronizing on some object that naturally
47  * encapsulates the list.
48  *
49  * If no such object exists, the list should be "wrapped" using the
50  * {@link Collections#synchronizedList Collections.synchronizedList}
51  * method.  This is best done at creation time, to prevent accidental
52  * unsynchronized access to the list:<pre>
53  *   List list = Collections.synchronizedList(new LinkedList(...));</pre>
54  *
55  * <p>The iterators returned by this class's {@code iterator} and
56  * {@code listIterator} methods are <i>fail-fast</i>: if the list is
57  * structurally modified at any time after the iterator is created, in
58  * any way except through the Iterator's own {@code remove} or
59  * {@code add} methods, the iterator will throw a {@link
60  * ConcurrentModificationException}.  Thus, in the face of concurrent
61  * modification, the iterator fails quickly and cleanly, rather than
62  * risking arbitrary, non-deterministic behavior at an undetermined
63  * time in the future.
64  *
65  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
66  * as it is, generally speaking, impossible to make any hard guarantees in the
67  * presence of unsynchronized concurrent modification.  Fail-fast iterators
68  * throw {@code ConcurrentModificationException} on a best-effort basis.
69  * Therefore, it would be wrong to write a program that depended on this
70  * exception for its correctness:   <i>the fail-fast behavior of iterators
71  * should be used only to detect bugs.</i>
72  *
73  * <p>This class is a member of the
74  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
75  * Java Collections Framework</a>.
76  *
77  * @author  Josh Bloch
78  * @see     List
79  * @see     ArrayList
80  * @param E the type of elements held in this collection
81  */
82 
83 class LinkedList(E) : AbstractSequentialList!E,  Deque!E {  //, Cloneable 
84     // alias remove = AbstractSequentialList!E.remove;
85 
86     DList!E _dlist;
87     int _size = 0;
88 
89     /**
90      * Constructs an empty list.
91      */
92     this() {
93     }
94 
95     /**
96      * Constructs a list containing the elements of the specified
97      * collection, in the order they are returned by the collection's
98      * iterator.
99      *
100      * @param  c the collection whose elements are to be placed into this list
101      * @throws NullPointerException if the specified collection is null
102      */
103     this(Collection!E c) {
104         this();
105         addAll(c);
106     }
107 
108 
109     this(E[] c) {
110         this();
111         addAll(c);
112     }
113 
114     /**
115      * Links e as first element.
116      */
117     private void linkFirst(E e) {
118         _dlist.insertFront(e);
119         _size++;
120         modCount++;
121     }
122 
123     /**
124      * Links e as last element.
125      */
126     void linkLast(E e) {
127         _dlist.insertBack(e);
128         _size++;
129         modCount++;
130     }
131 
132     /**
133      * Inserts element e before non-null Node succ.
134      */
135     // void linkBefore(E e, Node!E succ) {
136     //     // assert succ !is null;
137     //     final Node!E pred = succ.prev;
138     //     final Node!E newNode = new Node<>(pred, e, succ);
139     //     succ.prev = newNode;
140     //     if (pred is null)
141     //         first = newNode;
142     //     else
143     //         pred.next = newNode;
144     //     _size++;
145     //     modCount++;
146     // }
147 
148     /**
149      * Unlinks non-null first node f.
150      */
151     private E unlinkFirst() {
152         E element = _dlist.front;
153         _dlist.removeFront();
154         _size--;
155         modCount++;
156         return element;
157     }
158 
159     /**
160      * Unlinks non-null last node l.
161      */
162     private E unlinkLast() {
163         E element = _dlist.back;
164         _dlist.removeBack;
165         _size--;
166         modCount++;
167         return element;
168     }
169 
170 
171     /**
172      * Returns the first element in this list.
173      *
174      * @return the first element in this list
175      * @throws NoSuchElementException if this list is empty
176      */
177     E getFirst() {
178         return _dlist.front;
179     }
180 
181     /**
182      * Returns the last element in this list.
183      *
184      * @return the last element in this list
185      * @throws NoSuchElementException if this list is empty
186      */
187     E getLast() {
188         return _dlist.back;
189     }
190 
191     /**
192      * Removes and returns the first element from this list.
193      *
194      * @return the first element from this list
195      * @throws NoSuchElementException if this list is empty
196      */
197     E removeFirst() {
198         if(_size<=0)  return E.init;
199         return unlinkFirst();
200     }
201 
202     /**
203      * Removes and returns the last element from this list.
204      *
205      * @return the last element from this list
206      * @throws NoSuchElementException if this list is empty
207      */
208     E removeLast() {
209         if(_size<=0) return E.init;
210         return unlinkLast();
211     }
212 
213     /**
214      * Inserts the specified element at the beginning of this list.
215      *
216      * @param e the element to add
217      */
218     void addFirst(E e) {
219         linkFirst(e);
220     }
221 
222     /**
223      * Appends the specified element to the end of this list.
224      *
225      * <p>This method is equivalent to {@link #add}.
226      *
227      * @param e the element to add
228      */
229     void addLast(E e) {
230         linkLast(e);
231     }
232 
233     /**
234      * Returns {@code true} if this list contains the specified element.
235      * More formally, returns {@code true} if and only if this list contains
236      * at least one element {@code e} such that
237      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
238      *
239      * @param o element whose presence in this list is to be tested
240      * @return {@code true} if this list contains the specified element
241      */
242     override bool contains(E o) {
243         return indexOf(o) != -1;
244     }
245 
246     /**
247      * Returns the number of elements in this list.
248      *
249      * @return the number of elements in this list
250      */
251     override int size() {
252         return _size;
253     }
254 
255     /**
256      * Appends the specified element to the end of this list.
257      *
258      * <p>This method is equivalent to {@link #addLast}.
259      *
260      * @param e element to be appended to this list
261      * @return {@code true} (as specified by {@link Collection#add})
262      */
263     override bool add(E e) {
264         linkLast(e);
265         return true;
266     }
267 
268     /**
269      * Removes the first occurrence of the specified element from this list,
270      * if it is present.  If this list does not contain the element, it is
271      * unchanged.  More formally, removes the element with the lowest index
272      * {@code i} such that
273      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
274      * (if such an element exists).  Returns {@code true} if this list
275      * contained the specified element (or equivalently, if this list
276      * changed as a result of the call).
277      *
278      * @param o element to be removed from this list, if present
279      * @return {@code true} if this list contained the specified element
280      */
281     override bool remove(E o) {
282         static if(CompilerHelper.isLessThan(2077)) {
283                 auto range = _dlist[];
284                 for ( ; !range.empty; range.popFront())
285                 {
286                     if (range.front == o)
287                     {
288                         _dlist.stableLinearRemove(take(range, 1));
289                         _size--;
290                         modCount++;
291                         return true;
292                     }
293                 }
294                 return false;
295         } else {
296             if(_dlist.linearRemoveElement(o)) {
297                 _size--;
298                 modCount++;
299                 return true;
300             }   else {
301                 return false;
302             }
303         }
304     }
305 
306     // /**
307     //  * Appends all of the elements in the specified collection to the end of
308     //  * this list, in the order that they are returned by the specified
309     //  * collection's iterator.  The behavior of this operation is undefined if
310     //  * the specified collection is modified while the operation is in
311     //  * progress.  (Note that this will occur if the specified collection is
312     //  * this list, and it's nonempty.)
313     //  *
314     //  * @param c collection containing elements to be added to this list
315     //  * @return {@code true} if this list changed as a result of the call
316     //  * @throws NullPointerException if the specified collection is null
317     //  */
318     // override bool addAll(Collection!E c) {
319 
320     //     bool modified = c.size() > 0;
321     //     foreach (E e ; c) {
322     //         linkLast(e);
323     //     }
324     //     return modified;
325 
326     //     // return addAll(_size, c);
327     // }
328 
329     // bool addAll(E[] c) {
330 
331     //     bool modified = c.length > 0;
332     //     foreach (E e ; c) {
333     //         linkLast(e);
334     //     }
335     //     return modified;
336     // }
337 
338 //     /**
339 //      * Inserts all of the elements in the specified collection into this
340 //      * list, starting at the specified position.  Shifts the element
341 //      * currently at that position (if any) and any subsequent elements to
342 //      * the right (increases their indices).  The new elements will appear
343 //      * in the list in the order that they are returned by the
344 //      * specified collection's iterator.
345 //      *
346 //      * @param index index at which to insert the first element
347 //      *              from the specified collection
348 //      * @param c collection containing elements to be added to this list
349 //      * @return {@code true} if this list changed as a result of the call
350 //      * @throws IndexOutOfBoundsException {@inheritDoc}
351 //      * @throws NullPointerException if the specified collection is null
352 //      */
353 
354 // bool addAll(int index, Collection!E c) {
355 //     throw new NotImplementedException();
356 // }
357 //     bool addAll(int index, Collection<E> c) {
358 //         checkPositionIndex(index);
359 
360 //         Object[] a = c.toArray();
361 //         int numNew = a.length;
362 //         if (numNew == 0)
363 //             return false;
364 
365 //         Node!E pred, succ;
366 //         if (index == _size) {
367 //             succ = null;
368 //             pred = last;
369 //         } else {
370 //             succ = node(index);
371 //             pred = succ.prev;
372 //         }
373 
374 //         for (Object o : a) {
375 //         E e = (E) o;
376 //             Node!E newNode = new Node<>(pred, e, null);
377 //             if (pred is null)
378 //                 first = newNode;
379 //             else
380 //                 pred.next = newNode;
381 //             pred = newNode;
382 //         }
383 
384 //         if (succ is null) {
385 //             last = pred;
386 //         } else {
387 //             pred.next = succ;
388 //             succ.prev = pred;
389 //         }
390 
391 //         _size += numNew;
392 //         modCount++;
393 //         return true;
394 //     }
395 
396     /**
397      * Removes all of the elements from this list.
398      * The list will be empty after this call returns.
399      */
400     override void clear() {
401         _dlist.clear();
402         _size = 0;
403         modCount++;
404     }
405 
406 
407     // Positional Access Operations
408 
409     /**
410      * Returns the element at the specified position in this list.
411      *
412      * @param index index of the element to return
413      * @return the element at the specified position in this list
414      * @throws IndexOutOfBoundsException {@inheritDoc}
415      */
416     override E get(int index) {
417         checkElementIndex(index);
418 
419         int i=0;
420         foreach(v; _dlist)
421         {
422             if(i == index)
423                 return v;
424             i++;
425         }
426         return E.init;
427     }
428 
429     /**
430      * Replaces the element at the specified position in this list with the
431      * specified element.
432      *
433      * @param index index of the element to replace
434      * @param element element to be stored at the specified position
435      * @return the element previously at the specified position
436      * @throws IndexOutOfBoundsException {@inheritDoc}
437      */
438     override E set(int index, E element) {
439         checkElementIndex(index);
440 
441         int i= 0;
442         auto range = _dlist[];
443         range.popFrontN(index);
444         E oldVal = range.front;
445         range.front = element;
446 
447         // for ( ; !range.empty; range.popFront())
448         // {
449         //     if(i == index)
450         //     {
451         //         oldVal = range.front;
452         //         range.front = element;
453         //         break;
454         //     }
455         //     i++;
456         // }
457 
458         return oldVal;
459     }
460 
461     /**
462      * Inserts the specified element at the specified position in this list.
463      * Shifts the element currently at that position (if any) and any
464      * subsequent elements to the right (adds one to their indices).
465      *
466      * @param index index at which the specified element is to be inserted
467      * @param element element to be inserted
468      * @throws IndexOutOfBoundsException {@inheritDoc}
469      */
470     override void add(int index, E element) {
471         checkPositionIndex(index);
472 
473         if (index == _size)
474             linkLast(element);
475         else
476         {
477             auto range = _dlist[];
478             range.popFrontN(index);
479             _dlist.insertBefore(range, element);
480             _size++;
481             modCount++;
482         }
483             // linkBefore(element, node(index));
484     }
485 
486     /**
487      * Removes the element at the specified position in this list.  Shifts any
488      * subsequent elements to the left (subtracts one from their indices).
489      * Returns the element that was removed from the list.
490      *
491      * @param index the index of the element to be removed
492      * @return the element previously at the specified position
493      * @throws IndexOutOfBoundsException {@inheritDoc}
494      */
495      override E removeAt(int index) {
496         checkElementIndex(index);
497         auto range = _dlist[];
498         range.popFrontN(index);
499         auto temp = take(range, 1);
500         _dlist.linearRemove(temp);
501 
502         _size--;
503         modCount++;
504         return temp.front;
505     }
506 
507     /**
508      * Tells if the argument is the index of an existing element.
509      */
510     private bool isElementIndex(int index) {
511         return index >= 0 && index < _size;
512     }
513 
514     /**
515      * Tells if the argument is the index of a valid position for an
516      * iterator or an add operation.
517      */
518     private bool isPositionIndex(int index) {
519         return index >= 0 && index <= _size;
520     }
521 
522     /**
523      * Constructs an IndexOutOfBoundsException detail message.
524      * Of the many possible refactorings of the error handling code,
525      * this "outlining" performs best with both server and client VMs.
526      */
527     private string outOfBoundsMsg(int index) {
528         return "Index: " ~ index.to!string() ~ ", Size: " ~ _size.to!string();
529     }
530 
531     private void checkElementIndex(int index) {
532         if (!isElementIndex(index))
533             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
534     }
535 
536     private void checkPositionIndex(int index) {
537         if (!isPositionIndex(index))
538             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
539     }
540 
541     /**
542      * Returns the (non-null) Node at the specified element index.
543      */
544      
545 //     Node!E node(int index) {
546 //         // assert isElementIndex(index);
547 
548 //         if (index < (_size >> 1)) {
549 //             Node!E x = first;
550 //             for (int i = 0; i < index; i++)
551 //                 x = x.next;
552 //             return x;
553 //         } else {
554 //             Node!E x = last;
555 //             for (int i = _size - 1; i > index; i--)
556 //                 x = x.prev;
557 //             return x;
558 //         }
559 //     }
560 
561     // Search Operations
562 
563     /**
564      * Returns the index of the first occurrence of the specified element
565      * in this list, or -1 if this list does not contain the element.
566      * More formally, returns the lowest index {@code i} such that
567      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
568      * or -1 if there is no such index.
569      *
570      * @param o element to search for
571      * @return the index of the first occurrence of the specified element in
572      *         this list, or -1 if this list does not contain the element
573      */
574     override int indexOf(E o) {
575         int index = 0;
576         foreach(v; _dlist)
577         {
578             static if( is(E == class))
579             {
580                 if(v == o)
581                     return index;
582             }
583             else
584             {
585                 if(v == o)
586                     return index;
587             }
588             index++;
589         }
590         return -1;
591     }
592 
593     /**
594      * Returns the index of the last occurrence of the specified element
595      * in this list, or -1 if this list does not contain the element.
596      * More formally, returns the highest index {@code i} such that
597      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
598      * or -1 if there is no such index.
599      *
600      * @param o element to search for
601      * @return the index of the last occurrence of the specified element in
602      *         this list, or -1 if this list does not contain the element
603      */
604     override int lastIndexOf(E o) {
605         int index = _size;
606         auto range = _dlist[];
607         for(; !range.empty; range.popBack())
608         {
609             index--;
610             if(range.back == o)
611                 return index;
612         }
613         return -1;
614     }
615 
616     // Queue operations.
617 
618     /**
619      * Retrieves, but does not remove, the head (first element) of this list.
620      *
621      * @return the head of this list, or {@code null} if this list is empty
622      */
623     E peek() {        
624         return getFirst();
625     }
626 
627     /**
628      * Retrieves, but does not remove, the head (first element) of this list.
629      *
630      * @return the head of this list
631      * @throws NoSuchElementException if this list is empty
632      */
633     E element() {
634         return getFirst();
635     }
636 
637     /**
638      * Retrieves and removes the head (first element) of this list.
639      *
640      * @return the head of this list, or {@code null} if this list is empty
641      */
642     E poll() {
643         return removeFirst();
644     }
645 
646     /**
647      * Retrieves and removes the head (first element) of this list.
648      *
649      * @return the head of this list
650      * @throws NoSuchElementException if this list is empty
651      */
652     E remove() {
653         return removeFirst();
654     }
655 
656     /**
657      * Adds the specified element as the tail (last element) of this list.
658      *
659      * @param e the element to add
660      * @return {@code true} (as specified by {@link Queue#offer})
661      */
662     bool offer(E e) {
663         return add(e);
664     }
665 
666     // Deque operations
667     /**
668      * Inserts the specified element at the front of this list.
669      *
670      * @param e the element to insert
671      * @return {@code true} (as specified by {@link Deque#offerFirst})
672      */
673     bool offerFirst(E e) {
674         addFirst(e);
675         return true;
676     }
677 
678     /**
679      * Inserts the specified element at the end of this list.
680      *
681      * @param e the element to insert
682      * @return {@code true} (as specified by {@link Deque#offerLast})
683      */
684     bool offerLast(E e) {
685         addLast(e);
686         return true;
687     }
688 
689     /**
690      * Retrieves, but does not remove, the first element of this list,
691      * or returns {@code null} if this list is empty.
692      *
693      * @return the first element of this list, or {@code null}
694      *         if this list is empty
695      */
696     E peekFirst() {
697         return getFirst();
698      }
699 
700     /**
701      * Retrieves, but does not remove, the last element of this list,
702      * or returns {@code null} if this list is empty.
703      *
704      * @return the last element of this list, or {@code null}
705      *         if this list is empty
706      */
707     E peekLast() {
708         return getLast();
709     }
710 
711     /**
712      * Retrieves and removes the first element of this list,
713      * or returns {@code null} if this list is empty.
714      *
715      * @return the first element of this list, or {@code null} if
716      *     this list is empty
717      */
718     E pollFirst() {
719         return removeFirst();
720     }
721 
722     /**
723      * Retrieves and removes the last element of this list,
724      * or returns {@code null} if this list is empty.
725      *
726      * @return the last element of this list, or {@code null} if
727      *     this list is empty
728      */
729     E pollLast() {
730         return removeLast();
731     }
732 
733     /**
734      * Pushes an element onto the stack represented by this list.  In other
735      * words, inserts the element at the front of this list.
736      *
737      * <p>This method is equivalent to {@link #addFirst}.
738      *
739      * @param e the element to push
740      */
741     void push(E e) {
742         addFirst(e);
743     }
744 
745     /**
746      * Pops an element from the stack represented by this list.  In other
747      * words, removes and returns the first element of this list.
748      *
749      * <p>This method is equivalent to {@link #removeFirst()}.
750      *
751      * @return the element at the front of this list (which is the top
752      *         of the stack represented by this list)
753      * @throws NoSuchElementException if this list is empty
754      */
755     E pop() {
756         return removeFirst();
757     }
758 
759     /**
760      * Removes the first occurrence of the specified element in this
761      * list (when traversing the list from head to tail).  If the list
762      * does not contain the element, it is unchanged.
763      *
764      * @param o element to be removed from this list, if present
765      * @return {@code true} if the list contained the specified element
766      */
767     bool removeFirstOccurrence(E o) {
768         return remove(o);
769     }
770 
771     /**
772      * Removes the last occurrence of the specified element in this
773      * list (when traversing the list from head to tail).  If the list
774      * does not contain the element, it is unchanged.
775      *
776      * @param o element to be removed from this list, if present
777      * @return {@code true} if the list contained the specified element
778      */
779     // bool removeLastOccurrence(E o) {
780 
781     //     // if (o is null) {
782     //     //     for (Node!E x = last; x !is null; x = x.prev) {
783     //     //         if (x.item is null) {
784     //     //             unlink(x);
785     //     //             return true;
786     //     //         }
787     //     //     }
788     //     // } else {
789     //     //     for (Node!E x = last; x !is null; x = x.prev) {
790     //     //         if (o.equals(x.item)) {
791     //     //             unlink(x);
792     //     //             return true;
793     //     //         }
794     //     //     }
795     //     // }
796     //     // return false;
797     // }
798 
799 
800 // 
801 //     private LinkedList!E superClone() {
802 //         try {
803 //             return (LinkedList!E) super.clone();
804 //         } catch (CloneNotSupportedException e) {
805 //             throw new InternalError(e);
806 //         }
807 //     }
808 
809 //     /**
810 //      * Returns a shallow copy of this {@code LinkedList}. (The elements
811 //      * themselves are not cloned.)
812 //      *
813 //      * @return a shallow copy of this {@code LinkedList} instance
814 //      */
815 //     // Object clone() {
816 //     //     LinkedList!E clone = superClone();
817 
818 //     //     // Put clone into "virgin" state
819 //     //     clone.first = clone.last = null;
820 //     //     clone.size = 0;
821 //     //     clone.modCount = 0;
822 
823 //     //     // Initialize clone with our elements
824 //     //     for (Node!E x = first; x !is null; x = x.next)
825 //     //         clone.add(x.item);
826 
827 //     //     return clone;
828 //     // }
829 
830     /**
831      * Returns an array containing all of the elements in this list
832      * in proper sequence (from first to last element).
833      *
834      * <p>The returned array will be "safe" in that no references to it are
835      * maintained by this list.  (In other words, this method must allocate
836      * a new array).  The caller is thus free to modify the returned array.
837      *
838      * <p>This method acts as bridge between array-based and collection-based
839      * APIs.
840      *
841      * @return an array containing all of the elements in this list
842      *         in proper sequence
843      */
844     override E[] toArray() {
845         // E[] result = new E[_size];
846         // int i = 0;
847         // for (Node!E x = first; x !is null; x = x.next)
848         //     result[i++] = x.item;
849         return _dlist[].array;
850     }
851 
852     override int opApply(scope int delegate(ref E) dg)
853     {
854         int result = 0;
855         foreach(E v; _dlist)
856         {
857             result = dg(v);
858             if(result != 0) return result;
859         }
860         return result;
861     }
862 
863     override bool opEquals(IObject o) {
864         return opEquals(cast(Object) o);
865     }
866     
867     override bool opEquals(Object o) {
868         return super.opEquals(o);
869     }
870 
871     override size_t toHash() @trusted nothrow {
872         return super.toHash();
873     }
874 
875     override string toString() {
876         return super.toString();
877     }    
878 
879     InputRange!E descendingIterator() {
880         throw new NotImplementedException();
881     }
882 }