|
1 #ifndef LIBCOBALT_CONTAINERS_H |
|
2 #define LIBCOBALT_CONTAINERS_H |
|
3 |
|
4 #include <cassert> |
|
5 #include <algorithm> |
|
6 #include <deque> |
|
7 #include <initializer_list> |
|
8 |
|
9 template<class T> class list |
|
10 { |
|
11 public: |
|
12 typedef typename ::std::deque<T> list_type; |
|
13 typedef typename list_type::iterator it; |
|
14 typedef typename list_type::const_iterator c_it; |
|
15 typedef typename list_type::reverse_iterator r_it; |
|
16 typedef typename list_type::const_reverse_iterator cr_it; |
|
17 typedef T element_type; |
|
18 typedef list<T> self_type; |
|
19 |
|
20 list() {} |
|
21 list (std::initializer_list<element_type> vals) |
|
22 { |
|
23 m_data = vals; |
|
24 } |
|
25 |
|
26 list (const list_type& a) : m_data (a) {} |
|
27 |
|
28 it begin() |
|
29 { |
|
30 return m_data.begin(); |
|
31 } |
|
32 |
|
33 c_it begin() const |
|
34 { |
|
35 return m_data.cbegin(); |
|
36 } |
|
37 |
|
38 it end() |
|
39 { |
|
40 return m_data.end(); |
|
41 } |
|
42 |
|
43 c_it end() const |
|
44 { |
|
45 return m_data.cend(); |
|
46 } |
|
47 |
|
48 r_it rbegin() |
|
49 { |
|
50 return m_data.rbegin(); |
|
51 } |
|
52 |
|
53 cr_it crbegin() const |
|
54 { |
|
55 return m_data.crbegin(); |
|
56 } |
|
57 |
|
58 r_it rend() |
|
59 { |
|
60 return m_data.rend(); |
|
61 } |
|
62 |
|
63 cr_it crend() const |
|
64 { |
|
65 return m_data.crend(); |
|
66 } |
|
67 |
|
68 void erase (int pos) |
|
69 { |
|
70 assert (pos < size()); |
|
71 m_data.erase (m_data.begin() + pos); |
|
72 } |
|
73 |
|
74 element_type& push_front (const element_type& value) |
|
75 { |
|
76 m_data.push_front (value); |
|
77 return m_data[0]; |
|
78 } |
|
79 |
|
80 element_type& push_back (const element_type& value) |
|
81 { |
|
82 m_data.push_back (value); |
|
83 return m_data[m_data.size() - 1]; |
|
84 } |
|
85 |
|
86 void push_back (const self_type& vals) |
|
87 { |
|
88 for (const T & val : vals) |
|
89 push_back (val); |
|
90 } |
|
91 |
|
92 bool pop (T& val) |
|
93 { |
|
94 if (size() == 0) |
|
95 return false; |
|
96 |
|
97 val = m_data[size() - 1]; |
|
98 erase (size() - 1); |
|
99 return true; |
|
100 } |
|
101 |
|
102 T& operator<< (const T& value) |
|
103 { |
|
104 return push_back (value); |
|
105 } |
|
106 |
|
107 void operator<< (const self_type& vals) |
|
108 { |
|
109 push_back (vals); |
|
110 } |
|
111 |
|
112 bool operator>> (T& value) |
|
113 { |
|
114 return pop (value); |
|
115 } |
|
116 |
|
117 self_type reverse() const |
|
118 { |
|
119 self_type rev; |
|
120 |
|
121 for (const T & val : *this) |
|
122 val >> rev; |
|
123 |
|
124 return rev; |
|
125 } |
|
126 |
|
127 void clear() |
|
128 { |
|
129 m_data.clear(); |
|
130 } |
|
131 |
|
132 void insert (int pos, const element_type& value) |
|
133 { |
|
134 m_data.insert (m_data.begin() + pos, value); |
|
135 } |
|
136 |
|
137 void makeUnique() |
|
138 { |
|
139 // Remove duplicate entries. For this to be effective, the vector must be |
|
140 // sorted first. |
|
141 sort(); |
|
142 it pos = std::unique (begin(), end()); |
|
143 resize (std::distance (begin(), pos)); |
|
144 } |
|
145 |
|
146 int size() const |
|
147 { |
|
148 return m_data.size(); |
|
149 } |
|
150 |
|
151 element_type& operator[] (int n) |
|
152 { |
|
153 assert (n < size()); |
|
154 return m_data[n]; |
|
155 } |
|
156 |
|
157 const element_type& operator[] (int n) const |
|
158 { |
|
159 assert (n < size()); |
|
160 return m_data[n]; |
|
161 } |
|
162 |
|
163 void resize (std::ptrdiff_t size) |
|
164 { |
|
165 m_data.resize (size); |
|
166 } |
|
167 |
|
168 void sort() |
|
169 { |
|
170 std::sort (begin(), end()); |
|
171 } |
|
172 |
|
173 int find (const element_type& needle) |
|
174 { |
|
175 int i = 0; |
|
176 |
|
177 for (const element_type & hay : *this) |
|
178 { |
|
179 if (hay == needle) |
|
180 return i; |
|
181 |
|
182 i++; |
|
183 } |
|
184 |
|
185 return -1; |
|
186 } |
|
187 |
|
188 void remove (const element_type& it) |
|
189 { |
|
190 int idx; |
|
191 |
|
192 if ( (idx = find (it)) != -1) |
|
193 erase (idx); |
|
194 } |
|
195 |
|
196 inline bool is_empty() const |
|
197 { |
|
198 return size() == 0; |
|
199 } |
|
200 |
|
201 self_type mid (int a, int b) const |
|
202 { |
|
203 assert (a >= 0 && b >= 0 && a < size() && b < size() && a <= b); |
|
204 self_type result; |
|
205 |
|
206 for (int i = a; i <= b; ++i) |
|
207 result << operator[] (i); |
|
208 |
|
209 return result; |
|
210 } |
|
211 |
|
212 inline const list_type& std_deque() const |
|
213 { |
|
214 return m_data; |
|
215 } |
|
216 |
|
217 private: |
|
218 list_type m_data; |
|
219 }; |
|
220 |
|
221 template<class T> list<T>& operator>> (const T& value, list<T>& haystack) |
|
222 { |
|
223 haystack.push_front (value); |
|
224 return haystack; |
|
225 } |
|
226 |
|
227 #endif // LIBCOBALT_CONTAINERS_H |