Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/tango/util/container/more/Stack.d

Revision 5388, 10.4 kB (checked in by kris, 2 years ago)

now returns 'this' instead of void

  • Property svn:eol-style set to native
Line 
1 /*******************************************************************************
2
3         copyright:      Copyright (c) 2008 Kris Bell. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6         
7         version:        Initial release: April 2008     
8         
9         author:         Kris
10
11         Since:          0.99.7
12
13 *******************************************************************************/
14
15 module tango.util.container.more.Stack;
16
17 private import tango.core.Exception : ArrayBoundsException;
18
19 /******************************************************************************
20
21         A stack of the given value-type V, with maximum depth Size. Note
22         that this does no memory allocation of its own when Size != 0, and
23         does heap allocation when Size == 0. Thus you can have a fixed-size
24         low-overhead instance, or a heap oriented instance.
25
26 ******************************************************************************/
27
28 struct Stack (V, int Size = 0)
29 {
30         alias nth              opIndex;
31         alias slice            opSlice;
32         alias rotateRight      opShrAssign;
33         alias rotateLeft       opShlAssign;
34         alias push             opCatAssign;
35          
36        
37         static if (Size == 0)
38                   {
39                   private uint depth;
40                   private V[]  stack;
41                   }
42                else
43                   {
44                   private uint     depth;
45                   private V[Size]  stack;
46                   }
47
48         /***********************************************************************
49
50                 Clear the stack
51
52         ***********************************************************************/
53
54         Stack* clear ()
55         {
56                 depth = 0;
57                 return this;
58         }
59
60         /***********************************************************************
61                 
62                 Return depth of the stack
63
64         ***********************************************************************/
65
66         uint size ()
67         {
68                 return depth;
69         }
70
71         /***********************************************************************
72                 
73                 Return remaining unused slots
74
75         ***********************************************************************/
76
77         uint unused ()
78         {
79                 return stack.length - depth;
80         }
81
82         /***********************************************************************
83                 
84                 Returns a (shallow) clone of this stack, on the stack
85
86         ***********************************************************************/
87
88         Stack clone ()
89         {       
90                 Stack s = void;
91                 static if (Size == 0)
92                            s.stack.length = stack.length;
93                 s.stack[] = stack;
94                 s.depth = depth;
95                 return s;
96         }
97
98         /***********************************************************************
99                 
100                 Push and return a (shallow) copy of the topmost element
101
102         ***********************************************************************/
103
104         V dup ()
105         {
106                 auto v = top;
107                 push (v);       
108                 return v;
109         }
110
111         /**********************************************************************
112
113                 Push a value onto the stack.
114
115                 Throws an exception when the stack is full
116
117         **********************************************************************/
118
119         Stack* push (V value)
120         {
121                 static if (Size == 0)
122                           {
123                           if (depth >= stack.length)
124                               stack.length = stack.length + 64;
125                           stack[depth++] = value;
126                           }
127                        else
128                           {                         
129                           if (depth < stack.length)
130                               stack[depth++] = value;
131                           else
132                              error (__LINE__);
133                           }
134                 return this;
135         }
136
137         /**********************************************************************
138
139                 Push a series of values onto the stack.
140
141                 Throws an exception when the stack is full
142
143         **********************************************************************/
144
145         Stack* append (V[] value...)
146         {
147                 foreach (v; value)
148                          push (v);
149                 return this;
150         }
151
152         /**********************************************************************
153
154                 Remove and return the most recent addition to the stack.
155
156                 Throws an exception when the stack is empty
157
158         **********************************************************************/
159
160         V pop ()
161         {
162                 if (depth)
163                     return stack[--depth];
164
165                 return error (__LINE__);
166         }
167
168         /**********************************************************************
169
170                 Return the most recent addition to the stack.
171
172                 Throws an exception when the stack is empty
173
174         **********************************************************************/
175
176         V top ()
177         {
178                 if (depth)
179                     return stack[depth-1];
180
181                 return error (__LINE__);
182         }
183
184         /**********************************************************************
185
186                 Swaps the top two entries, and return the top
187
188                 Throws an exception when the stack has insufficient entries
189
190         **********************************************************************/
191
192         V swap ()
193         {
194                 auto p = stack.ptr + depth;
195                 if ((p -= 2) >= stack.ptr)
196                    {
197                    auto v = p[0];
198                    p[0] = p[1];
199                    return p[1] = v;
200                    }
201
202                 return error (__LINE__);               
203         }
204
205         /**********************************************************************
206
207                 Index stack entries, where a zero index represents the
208                 newest stack entry (the top).
209
210                 Throws an exception when the given index is out of range
211
212         **********************************************************************/
213
214         V nth (uint i)
215         {
216                 if (i < depth)
217                     return stack [depth-i-1];
218
219                 return error (__LINE__);
220         }
221
222         /**********************************************************************
223
224                 Rotate the given number of stack entries
225
226                 Throws an exception when the number is out of range
227
228         **********************************************************************/
229
230         Stack* rotateLeft (uint d)
231         {
232                 if (d <= depth)
233                    {
234                    auto p = &stack[depth-d];
235                    auto t = *p;
236                    while (--d)
237                           *p++ = *(p+1);
238                    *p = t;
239                    }
240                 else
241                    error (__LINE__);
242                 return this;
243         }
244
245         /**********************************************************************
246
247                 Rotate the given number of stack entries
248
249                 Throws an exception when the number is out of range
250
251         **********************************************************************/
252
253         Stack* rotateRight (uint d)
254         {
255                 if (d <= depth)
256                    {
257                    auto p = &stack[depth-1];
258                    auto t = *p;
259                    while (--d)
260                           *p-- = *(p-1);
261                    *p = t;
262                    }
263                 else
264                    error (__LINE__);
265                 return this;
266         }
267
268         /**********************************************************************
269
270                 Return the stack as an array of values, where the first
271                 array entry represents the oldest value.
272                 
273                 Doing a foreach() on the returned array will traverse in
274                 the opposite direction of foreach() upon a stack
275                 
276         **********************************************************************/
277
278         V[] slice ()
279         {
280                 return stack [0 .. depth];
281         }
282
283         /**********************************************************************
284
285                 Throw an exception
286
287         **********************************************************************/
288
289         private V error (size_t line)
290         {
291                 throw new ArrayBoundsException (__FILE__, line);
292         }
293
294         /***********************************************************************
295
296                 Iterate from the most recent to the oldest stack entries
297
298         ***********************************************************************/
299
300         int opApply (int delegate(ref V value) dg)
301         {
302                         int result;
303
304                         for (int i=depth; i-- && result is 0;)
305                              result = dg (stack[i]);
306                         return result;
307         }
308 }
309
310
311 /*******************************************************************************
312
313 *******************************************************************************/
314
315 debug (Stack)
316 {
317         import tango.io.Stdout;
318
319         void main()
320         {
321                 Stack!(int) v;
322                 v.push(1);
323                
324                 Stack!(int, 10) s;
325
326                 Stdout.formatln ("push four");
327                 s.push (1);
328                 s.push (2);
329                 s.push (3);
330                 s.push (4);
331                 foreach (v; s)
332                          Stdout.formatln ("{}", v);
333                 s <<= 4;
334                 s >>= 4;
335                 foreach (v; s)
336                          Stdout.formatln ("{}", v);
337
338                 s = s.clone;
339                 Stdout.formatln ("pop one: {}", s.pop);
340                 foreach (v; s)
341                          Stdout.formatln ("{}", v);
342                 Stdout.formatln ("top: {}", s.top);
343
344                 Stdout.formatln ("pop three");
345                 s.pop;
346                 s.pop;
347                 s.pop;
348                 foreach (v; s)
349                          Stdout.formatln ("> {}", v);
350         }
351 }
352        
Note: See TracBrowser for help on using the browser.