1 // SemiTwist Library
2 // Written in the D programming language.
3 
4 module semitwist.util.container;
5 
6 import semitwist.util.all;
7 
8 final class Stack(T)
9 {
10 	private T[] data;
11 	@property size_t capacity()
12 	{
13 		return data.length;
14 	}
15 	private size_t _length=0;
16 	@property size_t length()
17 	{
18 		return _length;
19 	}
20 	
21 	this(size_t initialCapacity=1024)
22 	{
23 		data.length = initialCapacity;
24 	}
25 	
26 	private this(Stack!T s)
27 	{
28 		data = s.data.dup;
29 		_length = s._length;
30 	}
31 	
32 	ref T opIndex(size_t i)
33 	{
34 		debug if(i >= _length)
35 			throw new Exception("Invalid index");
36 		
37 		return data[i];
38 	}
39 	
40 	T[] opSlice(size_t a, size_t b)
41 	{
42 		debug if(a >= _length || b > _length)
43 			throw new Exception("Invalid index");
44 		
45 		return data[a..b];
46 	}
47 	
48 	private void expand()
49 	{
50 		size_t numMore = data.length;
51 		if(numMore == 0)
52 			numMore = 1;
53 		data.length += numMore;
54 	}
55 	
56 	void clear()
57 	{
58 		_length = 0;
59 		data.clear();
60 	}
61 	
62 	void opOpAssign(string op)(T item) if(op=="~")
63 	{
64 		if(_length == data.length)
65 			expand();
66 
67 		data[_length] = item;
68 		_length++;
69 	}
70 	
71 	void opOpAssign(string op)(T[] items) if(op=="~")
72 	{
73 		while(_length + items.length >= data.length)
74 			expand();
75 
76 		data[ _length .. _length + items.length ] = items;
77 		_length += items.length;
78 	}
79 	
80 	void pop(size_t num=1)
81 	{
82 		debug if(num > _length)
83 			throw new Exception("Invalid index");
84 			
85 		_length -= num;
86 	}
87 	
88 	@property ref T top()
89 	{
90 		return data[_length-1];
91 	}
92 	
93 	@property bool empty()
94 	{
95 		return _length == 0;
96 	}
97 	
98 	void compact()
99 	{
100 		data.length = _length;
101 	}
102 	
103 	@property Stack!T dup()
104 	{
105 		return new Stack!T(this);
106 	}
107 	
108 	int opApply(int delegate(ref T) dg)
109 	{
110 		int result = 0;
111 		foreach(ref T item; data[0.._length])
112 		{
113 			result = dg(item);
114 			if(result)
115 				break;
116 		}
117 		return result;
118 	}
119 	
120 	int opApply(int delegate(ref size_t, ref T) dg)
121 	{
122 		int result = 0;
123 		foreach(size_t i, ref T item; data[0.._length])
124 		{
125 			result = dg(i, item);
126 			if(result)
127 				break;
128 		}
129 		return result;
130 	}
131 }