1 /// \file Stack.d
2 
3 module tagion.betterC.utils.Stack;
4 
5 @nogc:
6 
7 import tagion.betterC.utils.Memory;
8 
9 //import core.stdc.stdio;
10 
11 struct Stack(T) {
12 @nogc:
13     struct Element {
14         Element* next;
15         T value;
16     }
17 
18     protected {
19         Element* root;
20     }
21     // this() {
22     //     top=null;
23     // }
24     ~this() {
25         dispose;
26     }
27 
28     void dispose() {
29         static void _dispose(ref Element* e) {
30             if (e !is null) {
31                 _dispose(e.next);
32 
33                 
34 
35                 .dispose!false(e);
36             }
37         }
38 
39         _dispose(root);
40     }
41 
42     void push(T x) {
43         auto new_e = create!Element;
44         new_e.value = x;
45         new_e.next = root;
46         root = new_e;
47     }
48 
49     T pop() {
50         scope (exit) {
51             if (root !is null) {
52                 auto temp_e = root;
53                 root = root.next;
54                 temp_e.dispose;
55             }
56         }
57         return root.value;
58     }
59 
60     @property T top() {
61         return root.value;
62     }
63 
64     @property bool empty() const pure {
65         return root is null;
66     }
67 
68     @property size_t length() const pure {
69         size_t count;
70         for (Element* e = cast(Element*) root; e !is null; e = e.next) {
71             count++;
72         }
73         return count;
74     }
75 
76     Range opSlice() {
77         return Range(root);
78     }
79 
80     struct Range {
81         private Element* current;
82         bool empty() const pure {
83             return (current is null);
84         }
85 
86         T front() pure {
87             return current.value;
88         }
89 
90         void popFront() {
91             current = current.next;
92         }
93     }
94 
95 }
96 
97 unittest {
98     Stack!int q;
99     const(int[7]) table = [7, 6, 5, 4, 3, 2, 1];
100 
101     assert(q.empty);
102     foreach (t; table) {
103         q.push(t);
104     }
105 
106     assert(!q.empty);
107     assert(table.length == q.length);
108     assert(q.top == table[table.length - 1]);
109 
110     size_t i = table.length;
111     int[table.length] check = table;
112     foreach (b; q[]) {
113         i--;
114         assert(check[i] is b);
115     }
116 
117     foreach_reverse (j; 0 .. table.length) {
118         assert(q.top == table[j]);
119         q.pop;
120     }
121 }