1 #ifndef LIBCOBALT_CONTAINERS_H |
1 /* |
2 #define LIBCOBALT_CONTAINERS_H |
2 Copyright (c) 2013-2014, Santeri Piippo |
|
3 All rights reserved. |
|
4 |
|
5 Redistribution and use in source and binary forms, with or without |
|
6 modification, are permitted provided that the following conditions are met: |
|
7 |
|
8 * Redistributions of source code must retain the above copyright |
|
9 notice, this list of conditions and the following disclaimer. |
|
10 |
|
11 * Redistributions in binary form must reproduce the above copyright |
|
12 notice, this list of conditions and the following disclaimer in the |
|
13 documentation and/or other materials provided with the distribution. |
|
14 |
|
15 * Neither the name of the <organization> nor the |
|
16 names of its contributors may be used to endorse or promote products |
|
17 derived from this software without specific prior written permission. |
|
18 |
|
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
22 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
|
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
29 */ |
|
30 |
|
31 #ifndef BOTC_CONTAINERS_H |
|
32 #define BOTC_CONTAINERS_H |
3 |
33 |
4 #include <cassert> |
34 #include <cassert> |
5 #include <algorithm> |
35 #include <algorithm> |
6 #include <deque> |
36 #include <deque> |
7 #include <initializer_list> |
37 #include <initializer_list> |
8 |
38 |
9 template<class T> class list |
39 template<class T> class list |
10 { |
40 { |
11 public: |
41 public: |
12 typedef typename ::std::deque<T> list_type; |
42 typedef typename ::std::deque<T> list_type; |
13 typedef typename list_type::iterator it; |
43 typedef typename list_type::iterator it; |
14 typedef typename list_type::const_iterator c_it; |
44 typedef typename list_type::const_iterator c_it; |
15 typedef typename list_type::reverse_iterator r_it; |
45 typedef typename list_type::reverse_iterator r_it; |
16 typedef typename list_type::const_reverse_iterator cr_it; |
46 typedef typename list_type::const_reverse_iterator cr_it; |
17 typedef T element_type; |
47 typedef T element_type; |
18 typedef list<T> self_type; |
48 typedef list<T> self_type; |
19 |
49 |
20 list() {} |
50 // ===================================================================== |
21 list (std::initializer_list<element_type> vals) |
51 // |
22 { |
52 list() {} |
23 m_data = vals; |
53 |
24 } |
54 // ===================================================================== |
25 |
55 // |
26 list (const list_type& a) : m_data (a) {} |
56 list (std::initializer_list<element_type> vals) |
27 |
57 { |
28 it begin() |
58 m_data = vals; |
29 { |
59 } |
30 return m_data.begin(); |
60 |
31 } |
61 // ===================================================================== |
32 |
62 // |
33 c_it begin() const |
63 list (const list_type& a) : |
34 { |
64 m_data (a) {} |
35 return m_data.cbegin(); |
65 |
36 } |
66 // ===================================================================== |
37 |
67 // |
38 it end() |
68 it begin() |
39 { |
69 { |
40 return m_data.end(); |
70 return m_data.begin(); |
41 } |
71 } |
42 |
72 |
43 c_it end() const |
73 // ===================================================================== |
44 { |
74 // |
45 return m_data.cend(); |
75 c_it begin() const |
46 } |
76 { |
47 |
77 return m_data.cbegin(); |
48 r_it rbegin() |
78 } |
49 { |
79 |
50 return m_data.rbegin(); |
80 // ===================================================================== |
51 } |
81 // |
52 |
82 it end() |
53 cr_it crbegin() const |
83 { |
54 { |
84 return m_data.end(); |
55 return m_data.crbegin(); |
85 } |
56 } |
86 |
57 |
87 // ===================================================================== |
58 r_it rend() |
88 // |
59 { |
89 c_it end() const |
60 return m_data.rend(); |
90 { |
61 } |
91 return m_data.cend(); |
62 |
92 } |
63 cr_it crend() const |
93 |
64 { |
94 // ===================================================================== |
65 return m_data.crend(); |
95 // |
66 } |
96 r_it rbegin() |
67 |
97 { |
68 void erase (int pos) |
98 return m_data.rbegin(); |
69 { |
99 } |
70 assert (pos < size()); |
100 |
71 m_data.erase (m_data.begin() + pos); |
101 // ===================================================================== |
72 } |
102 // |
73 |
103 cr_it crbegin() const |
74 element_type& push_front (const element_type& value) |
104 { |
75 { |
105 return m_data.crbegin(); |
76 m_data.push_front (value); |
106 } |
77 return m_data[0]; |
107 |
78 } |
108 // ===================================================================== |
79 |
109 // |
80 element_type& push_back (const element_type& value) |
110 r_it rend() |
81 { |
111 { |
82 m_data.push_back (value); |
112 return m_data.rend(); |
83 return m_data[m_data.size() - 1]; |
113 } |
84 } |
114 |
85 |
115 // ===================================================================== |
86 void push_back (const self_type& vals) |
116 // |
87 { |
117 cr_it crend() const |
88 for (const T & val : vals) |
118 { |
89 push_back (val); |
119 return m_data.crend(); |
90 } |
120 } |
91 |
121 |
92 bool pop (T& val) |
122 // ===================================================================== |
93 { |
123 // |
94 if (size() == 0) |
124 inline void erase (int pos) |
95 return false; |
125 { |
96 |
126 assert (pos < size()); |
97 val = m_data[size() - 1]; |
127 m_data.erase (m_data.begin() + pos); |
98 erase (size() - 1); |
128 } |
99 return true; |
129 |
100 } |
130 // ===================================================================== |
101 |
131 // |
102 T& operator<< (const T& value) |
132 element_type& push_front (const element_type& value) |
103 { |
133 { |
104 return push_back (value); |
134 m_data.push_front (value); |
105 } |
135 return m_data[0]; |
106 |
136 } |
107 void operator<< (const self_type& vals) |
137 |
108 { |
138 // ===================================================================== |
109 push_back (vals); |
139 // |
110 } |
140 element_type& push_back (const element_type& value) |
111 |
141 { |
112 bool operator>> (T& value) |
142 m_data.push_back (value); |
113 { |
143 return m_data[m_data.size() - 1]; |
114 return pop (value); |
144 } |
115 } |
145 |
116 |
146 // ===================================================================== |
117 self_type reverse() const |
147 // |
118 { |
148 void push_back (const self_type& vals) |
119 self_type rev; |
149 { |
120 |
150 for (const T & val : vals) |
121 for (const T & val : *this) |
151 push_back (val); |
122 val >> rev; |
152 } |
123 |
153 |
124 return rev; |
154 // ===================================================================== |
125 } |
155 // |
126 |
156 bool pop (T& val) |
127 void clear() |
157 { |
128 { |
158 if (is_empty()) |
129 m_data.clear(); |
159 return false; |
130 } |
160 |
131 |
161 val = m_data[size() - 1]; |
132 void insert (int pos, const element_type& value) |
162 m_data.erase (m_data.end() - 1); |
133 { |
163 return true; |
134 m_data.insert (m_data.begin() + pos, value); |
164 } |
135 } |
165 |
136 |
166 // ===================================================================== |
137 void makeUnique() |
167 // |
138 { |
168 T& operator<< (const T& value) |
139 // Remove duplicate entries. For this to be effective, the vector must be |
169 { |
140 // sorted first. |
170 return push_back (value); |
141 sort(); |
171 } |
142 it pos = std::unique (begin(), end()); |
172 |
143 resize (std::distance (begin(), pos)); |
173 // ===================================================================== |
144 } |
174 // |
145 |
175 void operator<< (const self_type& vals) |
146 int size() const |
176 { |
147 { |
177 push_back (vals); |
148 return m_data.size(); |
178 } |
149 } |
179 |
150 |
180 // ===================================================================== |
151 element_type& operator[] (int n) |
181 // |
152 { |
182 bool operator>> (T& value) |
153 assert (n < size()); |
183 { |
154 return m_data[n]; |
184 return pop (value); |
155 } |
185 } |
156 |
186 |
157 const element_type& operator[] (int n) const |
187 // ===================================================================== |
158 { |
188 // |
159 assert (n < size()); |
189 self_type reverse() const |
160 return m_data[n]; |
190 { |
161 } |
191 self_type rev; |
162 |
192 |
163 void resize (std::ptrdiff_t size) |
193 for (const T & val : *this) |
164 { |
194 val >> rev; |
165 m_data.resize (size); |
195 |
166 } |
196 return rev; |
167 |
197 } |
168 void sort() |
198 |
169 { |
199 // ===================================================================== |
170 std::sort (begin(), end()); |
200 // |
171 } |
201 void clear() |
172 |
202 { |
173 int find (const element_type& needle) |
203 m_data.clear(); |
174 { |
204 } |
175 int i = 0; |
205 |
176 |
206 // ===================================================================== |
177 for (const element_type & hay : *this) |
207 // |
178 { |
208 void insert (int pos, const element_type& value) |
179 if (hay == needle) |
209 { |
180 return i; |
210 m_data.insert (m_data.begin() + pos, value); |
181 |
211 } |
182 i++; |
212 |
183 } |
213 // ===================================================================== |
184 |
214 // |
185 return -1; |
215 void makeUnique() |
186 } |
216 { |
187 |
217 // Remove duplicate entries. For this to be effective, the vector must be |
188 void remove (const element_type& it) |
218 // sorted first. |
189 { |
219 sort(); |
190 int idx; |
220 it pos = std::unique (begin(), end()); |
191 |
221 resize (std::distance (begin(), pos)); |
192 if ( (idx = find (it)) != -1) |
222 } |
193 erase (idx); |
223 |
194 } |
224 // ===================================================================== |
195 |
225 // |
196 inline bool is_empty() const |
226 int size() const |
197 { |
227 { |
198 return size() == 0; |
228 return m_data.size(); |
199 } |
229 } |
200 |
230 |
201 self_type mid (int a, int b) const |
231 // ===================================================================== |
202 { |
232 // |
203 assert (a >= 0 && b >= 0 && a < size() && b < size() && a <= b); |
233 element_type& operator[] (int n) |
204 self_type result; |
234 { |
205 |
235 assert (n < size()); |
206 for (int i = a; i <= b; ++i) |
236 return m_data[n]; |
207 result << operator[] (i); |
237 } |
208 |
238 |
209 return result; |
239 // ===================================================================== |
210 } |
240 // |
211 |
241 const element_type& operator[] (int n) const |
212 inline const list_type& std_deque() const |
242 { |
213 { |
243 assert (n < size()); |
214 return m_data; |
244 return m_data[n]; |
215 } |
245 } |
216 |
246 |
217 private: |
247 // ===================================================================== |
218 list_type m_data; |
248 // |
|
249 void resize (int size) |
|
250 { |
|
251 m_data.resize (size); |
|
252 } |
|
253 |
|
254 // ===================================================================== |
|
255 // |
|
256 void sort() |
|
257 { |
|
258 std::sort (begin(), end()); |
|
259 } |
|
260 |
|
261 // ===================================================================== |
|
262 // |
|
263 int find (const element_type& needle) |
|
264 { |
|
265 int i = 0; |
|
266 |
|
267 for (const element_type & hay : *this) |
|
268 { |
|
269 if (hay == needle) |
|
270 return i; |
|
271 |
|
272 i++; |
|
273 } |
|
274 |
|
275 return -1; |
|
276 } |
|
277 |
|
278 // ===================================================================== |
|
279 // |
|
280 void remove (const element_type& it) |
|
281 { |
|
282 int idx; |
|
283 |
|
284 if ((idx = find (it)) != -1) |
|
285 erase (idx); |
|
286 } |
|
287 |
|
288 // ===================================================================== |
|
289 // |
|
290 inline bool is_empty() const |
|
291 { |
|
292 return size() == 0; |
|
293 } |
|
294 |
|
295 // ===================================================================== |
|
296 // |
|
297 self_type mid (int a, int b) const |
|
298 { |
|
299 assert (a >= 0 && b >= 0 && a < size() && b < size() && a <= b); |
|
300 self_type result; |
|
301 |
|
302 for (int i = a; i <= b; ++i) |
|
303 result << operator[] (i); |
|
304 |
|
305 return result; |
|
306 } |
|
307 |
|
308 // ===================================================================== |
|
309 // |
|
310 inline const list_type& std_deque() const |
|
311 { |
|
312 return m_data; |
|
313 } |
|
314 |
|
315 // ===================================================================== |
|
316 // |
|
317 const element_type& first() const |
|
318 { |
|
319 return *(m_data.begin()); |
|
320 } |
|
321 |
|
322 // ===================================================================== |
|
323 // |
|
324 const element_type& last() const |
|
325 { |
|
326 return *(m_data.end()); |
|
327 } |
|
328 |
|
329 // ===================================================================== |
|
330 // |
|
331 bool contains (const element_type& a) const |
|
332 { |
|
333 return find (a) != -1; |
|
334 } |
|
335 |
|
336 private: |
|
337 list_type m_data; |
219 }; |
338 }; |
220 |
339 |
|
340 // ============================================================================= |
|
341 // |
221 template<class T> list<T>& operator>> (const T& value, list<T>& haystack) |
342 template<class T> list<T>& operator>> (const T& value, list<T>& haystack) |
222 { |
343 { |
223 haystack.push_front (value); |
344 haystack.push_front (value); |
224 return haystack; |
345 return haystack; |
225 } |
346 } |
226 |
347 |
227 #endif // LIBCOBALT_CONTAINERS_H |
348 #endif // BOTC_CONTAINERS_H |