1 module kontainer.linkedlist.linkedlist;
2 import kontainer.linkedlist.node;
3 import kontainer.stack;
4 import core.memory;
5 
6 struct LinkedList(T) {
7   private {
8     Node!T* _firstNode;
9     Node!T* _thisNode;
10     Node!T* _lastNode;
11     Node!T* swap;
12   }
13 
14   @property Node!T* firstNode() {
15     return _firstNode;
16   }
17 
18   @property Node!T* thisNode() {
19     return _thisNode;
20   }
21 
22   @property Node!T* lastNode() {
23     return _lastNode;
24   }
25 
26   void append(T value) {
27     Node!T* newNode = cast(Node!T*)GC.malloc(Node!T.sizeof, GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE);
28 
29     newNode.value    = value;
30     newNode.nextNode = null;
31 
32     if (lastNode !is null) {
33       // ALready exists some value.
34       lastNode.nextNode = newNode;
35       newNode.prevNode  = lastNode;
36       _lastNode         = newNode;
37     } else {
38       _firstNode = _lastNode = _thisNode = newNode;
39       newNode.prevNode = null;
40       newNode.nextNode = null;
41     }
42   }
43 
44   void moveFirst() {
45     _thisNode = _firstNode;
46   }
47 
48   void removeNode(Node!T* node) {
49     moveFirst;
50 
51     if (node == _firstNode) {
52       auto tempNode = _firstNode;
53       _firstNode = _firstNode.nextNode;
54       _firstNode.prevNode = null;
55 
56       freeNode(tempNode);
57       return;
58     } else if (node == _lastNode) {
59       auto tempNode = _lastNode;
60 
61       _lastNode = _lastNode.prevNode;
62       _lastNode.nextNode = null;
63 
64       freeNode(tempNode);
65       return;
66     }
67 
68     foreach (tnode; this) {
69       if (tnode == node) {
70         tnode.prevNode.nextNode = tnode.nextNode;
71         tnode.nextNode.prevNode = tnode.prevNode;
72 
73         freeNode(tnode);
74         return;
75       }
76     }
77   }
78 
79   Node!T* findNode(T key) {
80     _thisNode = _firstNode;
81 
82     foreach (tnode; this) {
83       if (tnode.value == key) {
84         return tnode;
85       }
86     }
87 
88     return null;
89   }
90 
91   void freeNode(Node!T* node) {
92     if (node !is null) {
93       GC.free(node);
94     }
95   }
96 
97   void freeAllNode() {
98     Stack!(Node!T*) stack;
99 
100     foreach (node; this) {
101       stack.push(node);
102     }
103 
104     foreach (node; stack) {
105       GC.free(node);
106     }
107   }
108 
109   @property size_t length() {
110     size_t idx;
111 
112     foreach (_; this) {
113       idx++;
114     }
115 
116     return idx;
117   }
118 
119   @property bool empty() {
120     bool ret = thisNode is null;
121 
122     if (ret && thisNode != _firstNode) {
123       _thisNode = _firstNode;
124     }
125 
126     return ret;
127   }
128 
129   @property Node!T* front() {
130     return thisNode;
131   }
132 
133   @property void popFront() {
134     _thisNode = thisNode.nextNode;
135   }
136 
137   bool find(T value) {
138     foreach (node; this) {
139       if (node.value == value) {
140         return true;
141       }
142     }
143 
144     return false;
145   }
146 
147   private {
148     void thisToSwap() {   
149       swap = _thisNode;
150     }
151 
152     void swapToThis() {
153       _thisNode = swap;
154     }
155   }
156 }
157