Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. 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 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | /** @file | ||
30 | * @brief Arrays and other linear sequential type field | ||
31 | * @ingroup gatecore_cpp | ||
32 | */ | ||
33 | |||
34 | #ifndef GATE_ARRAYS_HPP_INCLUDED | ||
35 | #define GATE_ARRAYS_HPP_INCLUDED | ||
36 | |||
37 | #include "gate/gate_core_api.hpp" | ||
38 | #include "gate/arrays.h" | ||
39 | |||
40 | #include "gate/gatetypes.hpp" | ||
41 | #include "gate/memalloc.hpp" | ||
42 | #include "gate/results.hpp" | ||
43 | #include "gate/exceptions.hpp" | ||
44 | #include "gate/enumerators.hpp" | ||
45 | #include "gate/comparers.hpp" | ||
46 | |||
47 | namespace gate | ||
48 | { | ||
49 | |||
50 | /// @brief | ||
51 | /// @tparam T | ||
52 | template <class T> | ||
53 | class Array | ||
54 | { | ||
55 | public: | ||
56 | typedef T item_t; | ||
57 | typedef Array<T> self_t; | ||
58 | typedef item_t const* iterator; | ||
59 | typedef item_t const* const_iterator; | ||
60 | |||
61 | private: | ||
62 | gate_array_t arr; | ||
63 | |||
64 | 204 | static void check_outofmem_nullptr(void const* ptr) | |
65 | { | ||
66 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
204 | if (NULL == ptr) |
67 | { | ||
68 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
69 | } | ||
70 | 204 | } | |
71 | |||
72 | public: | ||
73 | class reverse_iterator | ||
74 | { | ||
75 | private: | ||
76 | item_t const* ptr; | ||
77 | |||
78 | public: | ||
79 | 20 | reverse_iterator(item_t const* tptr) : ptr(tptr) {} | |
80 | 5 | item_t const& operator*() { return *this->ptr; } | |
81 | 16 | item_t const* operator->() { return this->ptr; } | |
82 | 5 | reverse_iterator& operator++() | |
83 | { | ||
84 | 5 | --this->ptr; | |
85 | 5 | return *this; | |
86 | } | ||
87 | 4 | reverse_iterator operator++(int) | |
88 | { | ||
89 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
4 | reverse_iterator ret(this->ptr--); |
90 | 4 | return ret; | |
91 | } | ||
92 | 4 | reverse_iterator& operator--() | |
93 | { | ||
94 | 4 | ++this->ptr; | |
95 | 4 | return *this; | |
96 | } | ||
97 | ✗ | reverse_iterator operator--(int) | |
98 | { | ||
99 | ✗ | reverse_iterator ret(this->ptr++); | |
100 | ✗ | return ret; | |
101 | } | ||
102 | 1 | bool operator==(reverse_iterator const& that) const { return this->ptr == that.ptr; } | |
103 | 10 | bool operator!=(reverse_iterator const& that) const { return this->ptr != that.ptr; } | |
104 | }; | ||
105 | typedef reverse_iterator const_reverse_iterator; | ||
106 | |||
107 | 169 | Array() noexcept | |
108 | { | ||
109 | 169 | gate_array_t* tmp = gate_array_create_static(&arr, NULL, sizeof(item_t), 0); | |
110 | #ifdef GATE_DEBUG_MODE | ||
111 | 169 | check_outofmem_nullptr(tmp); | |
112 | #else | ||
113 | (void)tmp; | ||
114 | #endif | ||
115 | 169 | } | |
116 | 3 | Array(item_t const* items, size_t count) | |
117 | { | ||
118 | 3 | gate_arraylist_t arrlist = gate_arraylist_create(sizeof(item_t), items, count, &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | |
119 | 3 | check_outofmem_nullptr(arrlist); | |
120 | 3 | gate_array_t* result = gate_array_create(&this->arr, arrlist); | |
121 | 3 | gate_arraylist_release(arrlist); | |
122 | 3 | check_outofmem_nullptr(result); | |
123 | 3 | } | |
124 | 3 | Array(self_t const& src) noexcept | |
125 | { | ||
126 | 3 | gate_array_t* const tmp = gate_array_duplicate(&this->arr, &src.arr); | |
127 | #ifdef GATE_DEBUG_MODE | ||
128 | 3 | check_outofmem_nullptr(tmp); | |
129 | #endif | ||
130 | (void)tmp; | ||
131 | 3 | } | |
132 | |||
133 | 1 | Array(gate_array_t const& arr) | |
134 | { | ||
135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (arr.item_size != sizeof(item_t)) |
136 | { | ||
137 | ✗ | GATEXX_RAISE_ERROR(results::IncorrectType); | |
138 | } | ||
139 | 1 | gate_arraylist_t arrlist = gate_arraylist_create(sizeof(item_t), | |
140 | gate_array_get(&arr, 0), gate_array_length(&arr), | ||
141 | &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | ||
142 | 1 | check_outofmem_nullptr(arrlist); | |
143 | 1 | gate_array_t* result = gate_array_create(&this->arr, arrlist); | |
144 | 1 | gate_arraylist_release(arrlist); | |
145 | 1 | check_outofmem_nullptr(result); | |
146 | 1 | } | |
147 | 190 | ~Array() noexcept | |
148 | { | ||
149 | 190 | gate_array_release(&this->arr); | |
150 | 190 | } | |
151 | |||
152 | 4 | static self_t createStatic(item_t const* items, size_t count) noexcept | |
153 | { | ||
154 | 4 | self_t ret; | |
155 | 4 | gate_array_t* const tmp = gate_array_create_static(&ret.arr, items, sizeof(item_t), count); | |
156 | #ifdef GATE_DEBUG_MODE | ||
157 | 4 | check_outofmem_nullptr(tmp); | |
158 | #endif | ||
159 | (void)tmp; | ||
160 | 4 | return ret; | |
161 | } | ||
162 | |||
163 | #if !defined(GATE_COMPILER_SUPPORTS_CPP_ARRAY_SIZE_DEDUCTION) | ||
164 | template <class A> | ||
165 | static self_t createStaticFrom(A fixed_array) noexcept | ||
166 | { | ||
167 | return self_t::createStatic(&fixed_array[0], sizeof(fixed_array) / sizeof(fixed_array[0])); | ||
168 | } | ||
169 | #else | ||
170 | template <unsigned N> | ||
171 | 1 | static self_t createStaticFrom(item_t const (&items)[N]) noexcept | |
172 | { | ||
173 | 1 | return self_t::createStatic(&items[0], N); | |
174 | } | ||
175 | #endif | ||
176 | |||
177 | 40 | static self_t createFrom(gate_array_t& arr) | |
178 | { | ||
179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
40 | if (arr.item_size != sizeof(item_t)) |
180 | { | ||
181 | ✗ | GATEXX_RAISE_ERROR(results::IncorrectType); | |
182 | } | ||
183 | 40 | self_t ret; | |
184 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
40 | gate_mem_copy(&ret.arr, &arr, sizeof(arr)); |
185 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
40 | gate_mem_clear(&arr, sizeof(arr)); |
186 | 40 | return ret; | |
187 | } | ||
188 | |||
189 | 110 | void swap(self_t& that) noexcept | |
190 | { | ||
191 | 110 | gate::swapRefsNoExcept(this->arr, that.arr); | |
192 | 110 | } | |
193 | |||
194 | 1 | self_t& operator=(self_t const& src) noexcept | |
195 | { | ||
196 | 1 | Array that(src); | |
197 | 1 | this->swap(that); | |
198 | 1 | return *this; | |
199 | } | ||
200 | |||
201 | #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS) | ||
202 | ✗ | Array(self_t&& src) noexcept | |
203 | ✗ | : arr(src.arr) | |
204 | { | ||
205 | ✗ | gate_array_create_empty(&src.arr); | |
206 | ✗ | } | |
207 | |||
208 | 53 | self_t& operator=(self_t&& that) noexcept | |
209 | { | ||
210 | 53 | self_t tmp; | |
211 | 53 | that.swap(tmp); | |
212 | 53 | this->swap(tmp); | |
213 | 53 | return *this; | |
214 | } | ||
215 | #endif | ||
216 | 2 | gate_array_t const* c_impl() const noexcept | |
217 | { | ||
218 | 2 | return &this->arr; | |
219 | } | ||
220 | |||
221 | 2066 | item_t const* getItemPtr(size_t ndx) const noexcept | |
222 | { | ||
223 | 2066 | item_t const* ptr = (item_t const*)gate_array_get(&this->arr, ndx); | |
224 | 2066 | return ptr; | |
225 | } | ||
226 | |||
227 | 2 | bool_t contains(size_t ndx) const noexcept | |
228 | { | ||
229 | 2 | return ndx < this->length(); | |
230 | } | ||
231 | |||
232 | 1036 | item_t const& at(size_t ndx) const noexcept | |
233 | { | ||
234 | 1036 | item_t const* ptr = this->getItemPtr(ndx); | |
235 | #ifdef GATE_DEBUG_MODE | ||
236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1034 times.
|
1036 | if (ptr == NULL) |
237 | { | ||
238 | ✗ | gate::panic(results::OutOfBounds, "Array::at()"); | |
239 | } | ||
240 | #endif | ||
241 | 1036 | return *ptr; | |
242 | } | ||
243 | |||
244 | typedef Enumerator<item_t const> enumerator_t; | ||
245 | |||
246 | 7 | enumerator_t enumerate() const noexcept | |
247 | { | ||
248 | gate_enumerator_t enumerator; | ||
249 | 7 | gate_enumerator_t* const tmp = gate_array_enumerate(&this->arr, &enumerator); | |
250 | #ifdef GATE_DEBUG_MODE | ||
251 | 7 | check_outofmem_nullptr(tmp); | |
252 | #endif | ||
253 | (void)tmp; | ||
254 | 7 | return enumerator_t(enumerator); | |
255 | } | ||
256 | |||
257 | 1030 | item_t const& operator[](size_t ndx) const noexcept | |
258 | { | ||
259 | 1030 | return this->at(ndx); | |
260 | } | ||
261 | |||
262 | 1 | self_t subset(size_t offset, size_t count) const | |
263 | { | ||
264 | gate_array_t dest; | ||
265 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | check_outofmem_nullptr(gate_array_subset(&dest, &this->arr, offset, count)); |
266 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | return self_t::createFrom(dest); |
267 | } | ||
268 | |||
269 | 1 | self_t copy() const | |
270 | { | ||
271 | gate_array_t dest; | ||
272 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | check_outofmem_nullptr(gate_array_copy(&dest, &this->arr)); |
273 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | return self_t::createFrom(dest); |
274 | } | ||
275 | |||
276 | 58 | size_t length() const noexcept { return gate_array_length(&this->arr); } | |
277 | 2 | size_t size() const noexcept { return this->length(); } | |
278 | 10 | bool_t empty() const noexcept { return this->length() == 0; } | |
279 | |||
280 | 32 | const_iterator begin() const noexcept { return (item_t const*)this->arr.data_ptr; } | |
281 | 8 | const_iterator end() const noexcept { return this->begin() + this->arr.item_count; } | |
282 | 1 | const_iterator cbegin() const noexcept { return this->begin(); } | |
283 | 1 | const_iterator cend() const noexcept { return this->end(); } | |
284 | |||
285 | 6 | const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin() - 1); } | |
286 | 6 | const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->begin() + this->arr.item_count - 1); } | |
287 | 1 | const_reverse_iterator crbegin() const noexcept { return this->rbegin(); } | |
288 | 1 | const_reverse_iterator crend() const noexcept { return this->rend(); } | |
289 | }; | ||
290 | |||
291 | /// @brief | ||
292 | /// @tparam T | ||
293 | /// @param arr | ||
294 | /// @return | ||
295 | template <class T> | ||
296 | Enumerator<T const> enumerate(Array<T> const& arr) noexcept | ||
297 | { | ||
298 | return arr.enumerate(); | ||
299 | } | ||
300 | |||
301 | /// @brief | ||
302 | /// @tparam T | ||
303 | template <class T> | ||
304 | class ArrayList | ||
305 | { | ||
306 | private: | ||
307 | gate_arraylist_t impl; | ||
308 | |||
309 | 2542 | static void check_outofmem_nullptr(void const* ptr) | |
310 | { | ||
311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1293 times.
|
2542 | if (ptr == NULL) |
312 | { | ||
313 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
314 | } | ||
315 | 2542 | } | |
316 | |||
317 | public: | ||
318 | typedef T item_t; | ||
319 | typedef T* iterator; | ||
320 | typedef T const* const_iterator; | ||
321 | typedef ArrayList<T> self_t; | ||
322 | |||
323 | class reverse_iterator | ||
324 | { | ||
325 | private: | ||
326 | item_t* ptr; | ||
327 | |||
328 | public: | ||
329 | 28 | reverse_iterator(T* tptr) : ptr(tptr) {} | |
330 | 8 | item_t& operator*() { return *this->ptr; } | |
331 | 8 | item_t* operator->() { return this->ptr; } | |
332 | 1 | reverse_iterator& operator++() | |
333 | { | ||
334 | 1 | --this->ptr; | |
335 | 1 | return *this; | |
336 | } | ||
337 | 18 | reverse_iterator operator++(int) | |
338 | { | ||
339 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
18 | reverse_iterator ret(this->ptr--); |
340 | 18 | return ret; | |
341 | } | ||
342 | 1 | reverse_iterator& operator--() | |
343 | { | ||
344 | 1 | ++this->ptr; | |
345 | 1 | return *this; | |
346 | } | ||
347 | 1 | reverse_iterator operator--(int) | |
348 | { | ||
349 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1 | reverse_iterator ret(this->ptr++); |
350 | 1 | return ret; | |
351 | } | ||
352 | 1 | bool operator==(reverse_iterator const& that) const { return this->ptr == that.ptr; } | |
353 | 12 | bool operator!=(reverse_iterator const& that) const { return this->ptr != that.ptr; } | |
354 | }; | ||
355 | |||
356 | class const_reverse_iterator | ||
357 | { | ||
358 | private: | ||
359 | item_t const* ptr; | ||
360 | |||
361 | public: | ||
362 | 16 | const_reverse_iterator(item_t const* tptr) : ptr(tptr) {} | |
363 | ✗ | item_t const& operator*() const { return *this->ptr; } | |
364 | 8 | item_t const* operator->() const { return this->ptr; } | |
365 | 4 | const_reverse_iterator& operator++() | |
366 | { | ||
367 | 4 | --this->ptr; | |
368 | 4 | return *this; | |
369 | } | ||
370 | ✗ | const_reverse_iterator operator++(int) | |
371 | { | ||
372 | ✗ | const_reverse_iterator ret(this->ptr--); | |
373 | ✗ | return ret; | |
374 | } | ||
375 | 4 | const_reverse_iterator& operator--() | |
376 | { | ||
377 | 4 | ++this->ptr; | |
378 | 4 | return *this; | |
379 | } | ||
380 | 4 | const_reverse_iterator operator--(int) | |
381 | { | ||
382 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
4 | const_reverse_iterator ret(this->ptr++); |
383 | 4 | return ret; | |
384 | } | ||
385 | 1 | bool operator==(const_reverse_iterator const& that) const { return this->ptr == that.ptr; } | |
386 | 5 | bool operator!=(const_reverse_iterator const& that) const { return this->ptr != that.ptr; } | |
387 | }; | ||
388 | |||
389 | private: | ||
390 | 3 | ArrayList(gate_arraylist_t al) | |
391 | 3 | : impl(al) | |
392 | { | ||
393 | 3 | } | |
394 | |||
395 | public: | ||
396 | 68 | ArrayList(size_t prealloc = 0) | |
397 | { | ||
398 | 68 | this->impl = gate_arraylist_create(sizeof(item_t), NULL, prealloc, &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | |
399 | 68 | check_outofmem_nullptr(this->impl); | |
400 | 68 | } | |
401 | |||
402 | 3 | ArrayList(item_t const* items, size_t count) | |
403 | { | ||
404 | 3 | this->impl = gate_arraylist_create(sizeof(item_t), items, count, &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | |
405 | 3 | check_outofmem_nullptr(this->impl); | |
406 | 3 | } | |
407 | |||
408 | 2 | ArrayList(Array<item_t> const& copyFrom) | |
409 | { | ||
410 | 2 | size_t length = copyFrom.length(); | |
411 | 2 | item_t const* first = copyFrom.getItemPtr(0); | |
412 | |||
413 | 2 | this->impl = gate_arraylist_create(sizeof(item_t), first, length, &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | |
414 | 2 | check_outofmem_nullptr(this->impl); | |
415 | 2 | } | |
416 | |||
417 | 2 | ArrayList(Enumerator<item_t const> enumerator) | |
418 | { | ||
419 | 2 | this->impl = gate_arraylist_create(sizeof(item_t), NULL, 0, &TypeFunctions<item_t>::copyConstruct, &TypeFunctions<item_t>::destruct); | |
420 | 2 | check_outofmem_nullptr(this->impl); | |
421 | |||
422 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
|
10 | for (; enumerator.valid(); enumerator.next()) |
423 | { | ||
424 | 8 | this->add(*enumerator); | |
425 | } | ||
426 | 2 | } | |
427 | |||
428 | 1 | ArrayList(self_t const& src) noexcept | |
429 | 1 | : impl(src.impl) | |
430 | { | ||
431 | 1 | gate_arraylist_retain(this->impl); | |
432 | 1 | } | |
433 | |||
434 | 94 | ~ArrayList() noexcept | |
435 | { | ||
436 | 94 | gate_arraylist_release(this->impl); | |
437 | 94 | } | |
438 | |||
439 | #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS) | ||
440 | ✗ | ArrayList(self_t&& that) noexcept | |
441 | ✗ | : impl(that.impl) | |
442 | { | ||
443 | ✗ | that.impl = NULL; | |
444 | ✗ | } | |
445 | |||
446 | 1 | self_t& operator=(self_t&& that) noexcept | |
447 | { | ||
448 | 1 | this->swap(that); | |
449 | 1 | gate_arraylist_release(that.impl); | |
450 | 1 | that.impl = NULL; | |
451 | 1 | return *this; | |
452 | } | ||
453 | #endif | ||
454 | |||
455 | 3 | self_t copy() const | |
456 | { | ||
457 | 3 | gate_arraylist_t arr = gate_arraylist_copy(this->impl); | |
458 | 3 | check_outofmem_nullptr(arr); | |
459 | 3 | return self_t(arr); | |
460 | } | ||
461 | |||
462 | ✗ | gate_arraylist_t c_impl() const | |
463 | { | ||
464 | ✗ | return this->impl; | |
465 | } | ||
466 | 4 | gate_arraylist_t c_impl() | |
467 | { | ||
468 | 4 | return this->impl; | |
469 | } | ||
470 | |||
471 | 1 | void constructItem(item_t* ptr_uninitialized_item) | |
472 | { | ||
473 | 1 | size_t sz = gate_arraylist_create_item(this->impl, ptr_uninitialized_item, sizeof(item_t)); | |
474 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (sz == 0) |
475 | { | ||
476 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
477 | } | ||
478 | 1 | } | |
479 | |||
480 | 1 | void constructItem(size_t index, item_t* ptr_uninitialized_item) | |
481 | { | ||
482 | 1 | size_t sz = gate_arraylist_get_value(this->impl, index, ptr_uninitialized_item, sizeof(item_t)); | |
483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (sz == 0) |
484 | { | ||
485 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
486 | } | ||
487 | 1 | } | |
488 | |||
489 | 4 | void swap(self_t& that) noexcept | |
490 | { | ||
491 | 4 | gate::swapRefs(this->impl, that.impl); | |
492 | 4 | } | |
493 | |||
494 | 1 | self_t& operator=(self_t const& src) noexcept | |
495 | { | ||
496 | 1 | self_t that(src); | |
497 | 1 | this->swap(that); | |
498 | 1 | return *this; | |
499 | } | ||
500 | |||
501 | 4121 | size_t length() const noexcept | |
502 | { | ||
503 | 4121 | return gate_arraylist_length(this->impl); | |
504 | } | ||
505 | |||
506 | 3 | bool_t empty() const noexcept | |
507 | { | ||
508 | 3 | return this->length() == 0; | |
509 | } | ||
510 | |||
511 | 6 | iterator begin() noexcept | |
512 | { | ||
513 | 6 | size_t const len = this->length(); | |
514 | 6 | void* ptr = NULL; | |
515 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | if (len != 0) |
516 | { | ||
517 | 5 | ptr = gate_arraylist_get(this->impl, 0); | |
518 | } | ||
519 | 6 | return static_cast<iterator>(ptr); | |
520 | } | ||
521 | |||
522 | 7 | iterator end() noexcept | |
523 | { | ||
524 | 7 | size_t const len = this->length(); | |
525 | 7 | void* ptr = NULL; | |
526 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (len != 0) |
527 | { | ||
528 | 4 | ptr = gate_arraylist_get(this->impl, 0); | |
529 | 4 | ptr = ((char*)ptr + gate_arraylist_itemsize(this->impl) * len); | |
530 | } | ||
531 | 7 | return static_cast<iterator>(ptr); | |
532 | } | ||
533 | |||
534 | 2 | const_iterator begin() const noexcept | |
535 | { | ||
536 | 2 | size_t const len = this->length(); | |
537 | 2 | void const* ptr = NULL; | |
538 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (len != 0) |
539 | { | ||
540 | 1 | ptr = gate_arraylist_get(this->impl, 0); | |
541 | } | ||
542 | 2 | return static_cast<const_iterator>(ptr); | |
543 | } | ||
544 | |||
545 | 4 | const_iterator end() const noexcept | |
546 | { | ||
547 | 4 | size_t const len = this->length(); | |
548 | 4 | char const* ptr = NULL; | |
549 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (len != 0) |
550 | { | ||
551 | 1 | ptr = (char const*)gate_arraylist_get(this->impl, 0); | |
552 | 1 | ptr += gate_arraylist_itemsize(this->impl) * len; | |
553 | } | ||
554 | 4 | return reinterpret_cast<const_iterator>(ptr); | |
555 | } | ||
556 | |||
557 | 1 | const_iterator cbegin() const noexcept | |
558 | { | ||
559 | 1 | return this->begin(); | |
560 | } | ||
561 | |||
562 | 1 | const_iterator cend() const noexcept | |
563 | { | ||
564 | 1 | return this->end(); | |
565 | } | ||
566 | |||
567 | 4 | reverse_iterator rbegin() noexcept | |
568 | { | ||
569 | 4 | size_t const len = this->length(); | |
570 | 4 | char* ptr = NULL; | |
571 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | if (len != 0) |
572 | { | ||
573 | 4 | ptr = (char*)gate_arraylist_get(this->impl, len); | |
574 | 4 | ptr -= gate_arraylist_itemsize(this->impl); | |
575 | } | ||
576 | 4 | return reverse_iterator(static_cast<item_t*>(static_cast<void*>(ptr))); | |
577 | } | ||
578 | |||
579 | 4 | reverse_iterator rend() noexcept | |
580 | { | ||
581 | 4 | size_t const len = this->length(); | |
582 | 4 | char* ptr = NULL; | |
583 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | if (len != 0) |
584 | { | ||
585 | 4 | ptr = (char*)gate_arraylist_get(this->impl, 0); | |
586 | 4 | ptr -= gate_arraylist_itemsize(this->impl); | |
587 | } | ||
588 | 4 | return reverse_iterator(static_cast<item_t*>(static_cast<void*>(ptr))); | |
589 | ; | ||
590 | } | ||
591 | |||
592 | 4 | const_reverse_iterator rbegin() const noexcept | |
593 | { | ||
594 | 4 | size_t const len = this->length(); | |
595 | 4 | char const* ptr = NULL; | |
596 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
4 | if (len != 0) |
597 | { | ||
598 | 2 | ptr = (char const*)gate_arraylist_get(this->impl, len); | |
599 | 2 | ptr -= gate_arraylist_itemsize(this->impl); | |
600 | } | ||
601 | 4 | return const_reverse_iterator(static_cast<item_t const*>(static_cast<void const*>(ptr))); | |
602 | } | ||
603 | |||
604 | 4 | const_reverse_iterator rend() const noexcept | |
605 | { | ||
606 | 4 | size_t const len = this->length(); | |
607 | 4 | char const* ptr = NULL; | |
608 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
4 | if (len != 0) |
609 | { | ||
610 | 2 | ptr = (char const*)gate_arraylist_get(this->impl, 0); | |
611 | 2 | ptr -= gate_arraylist_itemsize(this->impl); | |
612 | } | ||
613 | 4 | return const_reverse_iterator(static_cast<item_t const*>(static_cast<void const*>(ptr))); | |
614 | ; | ||
615 | } | ||
616 | |||
617 | 4 | const_reverse_iterator crbegin() const noexcept | |
618 | { | ||
619 | 4 | return this->rbegin(); | |
620 | } | ||
621 | |||
622 | 4 | const_reverse_iterator crend() const noexcept | |
623 | { | ||
624 | 4 | return this->rend(); | |
625 | } | ||
626 | |||
627 | 2345 | iterator add(item_t const& item) | |
628 | { | ||
629 | 2345 | iterator ret = static_cast<iterator>(gate_arraylist_add(this->impl, static_cast<void const*>(&item))); | |
630 | 2345 | check_outofmem_nullptr(ret); | |
631 | 2345 | return ret; | |
632 | } | ||
633 | |||
634 | 1 | iterator add(item_t const& item, size_t repeat_count) | |
635 | { | ||
636 | 1 | iterator ret = static_cast<iterator>(gate_arraylist_add_n(this->impl, static_cast<void const*>(&item), repeat_count)); | |
637 | 1 | check_outofmem_nullptr(ret); | |
638 | 1 | return ret; | |
639 | } | ||
640 | |||
641 | template <class ITER> | ||
642 | 15 | void addItems(ITER begin, ITER end) | |
643 | { | ||
644 |
3/3✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1 times.
|
15 | while (begin != end) |
645 | { | ||
646 |
2/3✓ Branch 1 taken 3 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
13 | this->add(item_t(*begin)); |
647 | 13 | ++begin; | |
648 | } | ||
649 | 2 | } | |
650 | |||
651 | 3 | iterator insertAt(size_t index, item_t const& item) | |
652 | { | ||
653 | 3 | iterator ret = static_cast<iterator>(gate_arraylist_insert(this->impl, index, &item, 1)); | |
654 | 3 | check_outofmem_nullptr(ret); | |
655 | 3 | return ret; | |
656 | } | ||
657 | |||
658 | 1006 | VoidResult removeAt(size_t index) noexcept | |
659 | { | ||
660 | 1006 | result_t res = gate_arraylist_remove(this->impl, index, 1); | |
661 | 1006 | return makeResult(res); | |
662 | } | ||
663 | |||
664 | 1 | VoidResult remove(iterator iter) noexcept | |
665 | { | ||
666 | 1 | iterator const first = this->begin(); | |
667 | 1 | size_t const index = static_cast<size_t>(iter - first); | |
668 | 1 | return this->removeAt(index); | |
669 | } | ||
670 | |||
671 | 1 | void clear() noexcept | |
672 | { | ||
673 | 1 | gate_arraylist_clear(this->impl); | |
674 | 1 | } | |
675 | |||
676 | 2 | item_t const* getItemPtr(size_t index) const noexcept | |
677 | { | ||
678 | 2 | void* ptr = gate_arraylist_get(this->impl, index); | |
679 | 2 | return static_cast<item_t const*>(ptr); | |
680 | } | ||
681 | |||
682 | 6 | iterator get(size_t index) noexcept | |
683 | { | ||
684 | 6 | void* ptr = gate_arraylist_get(this->impl, index); | |
685 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (ptr == NULL) |
686 | { | ||
687 | 2 | return this->end(); | |
688 | } | ||
689 | 4 | return static_cast<iterator>(ptr); | |
690 | } | ||
691 | |||
692 | 4 | const_iterator get(size_t index) const noexcept | |
693 | { | ||
694 | 4 | void const* ptr = gate_arraylist_get(this->impl, index); | |
695 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (ptr == NULL) |
696 | { | ||
697 | 1 | return this->end(); | |
698 | } | ||
699 | 3 | return static_cast<const_iterator>(ptr); | |
700 | } | ||
701 | |||
702 | 4 | bool_t contains(size_t index) const noexcept | |
703 | { | ||
704 | 4 | return index < this->length(); | |
705 | } | ||
706 | |||
707 | 1048 | item_t& at(size_t index) noexcept | |
708 | { | ||
709 | 1048 | void* ptr = gate_arraylist_get(this->impl, index); | |
710 | #ifdef GATE_DEBUG_MODE | ||
711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1044 times.
|
1048 | if (ptr == NULL) |
712 | { | ||
713 | ✗ | panic(results::OutOfBounds, "ArrayList::at()"); | |
714 | } | ||
715 | #endif | ||
716 | 1048 | return *static_cast<item_t*>(ptr); | |
717 | } | ||
718 | |||
719 | 2 | item_t const& at(size_t index) const noexcept | |
720 | { | ||
721 | 2 | void const* ptr = gate_arraylist_get(this->impl, index); | |
722 | #ifdef GATE_DEBUG_MODE | ||
723 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ptr == NULL) |
724 | { | ||
725 | ✗ | panic(results::OutOfBounds, "ArrayList::at()"); | |
726 | } | ||
727 | #endif | ||
728 | 2 | return *static_cast<item_t const*>(ptr); | |
729 | } | ||
730 | |||
731 | 1036 | item_t& operator[](size_t index) noexcept | |
732 | { | ||
733 | 1036 | return this->at(index); | |
734 | } | ||
735 | 1 | item_t const& operator[](size_t index) const noexcept | |
736 | { | ||
737 | 1 | return this->at(index); | |
738 | } | ||
739 | |||
740 | 1026 | self_t& push(item_t const& item) | |
741 | { | ||
742 | 1026 | this->add(item); | |
743 | 1026 | return *this; | |
744 | } | ||
745 | |||
746 | 4 | self_t& pop(item_t& item) | |
747 | { | ||
748 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
|
4 | if (!this->contains(0)) |
749 | { | ||
750 | 1 | GATEXX_RAISE_ERROR(results::NotAvailable); | |
751 | } | ||
752 | 3 | item = this->at(0); | |
753 | 3 | this->removeAt(0); | |
754 | 3 | return *this; | |
755 | } | ||
756 | |||
757 | 1026 | self_t& operator<<(item_t const& item) | |
758 | { | ||
759 | 1026 | return this->push(item); | |
760 | } | ||
761 | |||
762 | 3 | self_t& operator>>(item_t& item) | |
763 | { | ||
764 | 3 | return this->pop(item); | |
765 | } | ||
766 | |||
767 | typedef Enumerator<item_t const> enumerator_t; | ||
768 | |||
769 | 2 | enumerator_t enumerate() const | |
770 | { | ||
771 | gate_enumerator_t enumerator; | ||
772 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | check_outofmem_nullptr(gate_arraylist_enumerate(this->impl, &enumerator)); |
773 | 4 | return enumerator_t(enumerator); | |
774 | } | ||
775 | |||
776 | 28 | Array<item_t> toArray() const | |
777 | { | ||
778 | 28 | Array<item_t> ret; | |
779 | gate_array_t arr; | ||
780 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
28 | gate_array_t* result = gate_array_create(&arr, this->impl); |
781 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
28 | check_outofmem_nullptr(result); |
782 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
28 | ret = Array<item_t>::createFrom(arr); |
783 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
28 | gate_array_release(&arr); |
784 | 56 | return ret; | |
785 | } | ||
786 | |||
787 | template <class FROM> | ||
788 | 2 | void importFrom(gate_arraylist_t arr) | |
789 | { | ||
790 | FROM const* ptr; | ||
791 | 2 | size_t length = gate_arraylist_length(arr); | |
792 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | for (size_t index = 0; index != length; ++index) |
793 | { | ||
794 | 8 | ptr = (FROM const*)gate_arraylist_get(arr, index); | |
795 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (ptr) |
796 | { | ||
797 |
1/3✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
8 | this->add(item_t(*ptr)); |
798 | } | ||
799 | } | ||
800 | 2 | } | |
801 | |||
802 | template <class TO> | ||
803 | 1 | size_t exportTo(gate_arraylist_t arr) const | |
804 | { | ||
805 | 1 | size_t countedExports = 0; | |
806 | |||
807 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (sizeof(TO) != gate_arraylist_itemsize(arr)) |
808 | { | ||
809 | ✗ | GATEXX_RAISE_ERROR(results::IncorrectType); | |
810 | } | ||
811 | else | ||
812 | { | ||
813 | 1 | size_t len = this->length(); | |
814 | |||
815 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (size_t index = 0; index != len; ++index) |
816 | { | ||
817 | 3 | item_t const* ptr = this->get(index); | |
818 | 3 | TO const* ptr_native = (TO const*)ptr; | |
819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!ptr_native) |
820 | { | ||
821 | ✗ | continue; | |
822 | } | ||
823 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (NULL != gate_arraylist_add(arr, ptr)) |
824 | { | ||
825 | 3 | ++countedExports; | |
826 | } | ||
827 | } | ||
828 | } | ||
829 | |||
830 | 1 | return countedExports; | |
831 | } | ||
832 | |||
833 | template <class COMPARER> | ||
834 | 6 | void sort(COMPARER comparer, bool descending = false) | |
835 | { | ||
836 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
6 | if (this->length() < 2) |
837 | { | ||
838 | ✗ | return; | |
839 | } | ||
840 | 6 | item_t* endPtr = this->end(); | |
841 | 6 | item_t* lastPtr = endPtr - 1; | |
842 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 3 times.
|
26 | for (item_t* current = this->begin(); current != lastPtr; ++current) |
843 | { | ||
844 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 10 times.
|
66 | for (item_t* next = current + 1; next != endPtr; ++next) |
845 | { | ||
846 | 46 | int result = comparer(*next, *current); | |
847 |
7/8✓ Branch 0 taken 13 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
46 | if ((!descending && (result < 0)) || (descending && (result > 0))) |
848 | { | ||
849 | 36 | gate::swapRefs(*next, *current); | |
850 | } | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | |||
855 | 1 | void sort() | |
856 | { | ||
857 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | this->sort(DefaultComparer<item_t>()); |
858 | 1 | } | |
859 | }; | ||
860 | |||
861 | |||
862 | |||
863 | /// @brief | ||
864 | /// @tparam T | ||
865 | template <class T> | ||
866 | class SlotList | ||
867 | { | ||
868 | public: | ||
869 | typedef T item_t; | ||
870 | typedef SlotList<T> self_t; | ||
871 | |||
872 | private: | ||
873 | gate_slotlist_t impl; | ||
874 | |||
875 | 43 | static void check_outofmem_nullptr(void const* ptr) | |
876 | { | ||
877 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
43 | if (NULL == ptr) |
878 | { | ||
879 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
880 | } | ||
881 | 43 | } | |
882 | |||
883 | public: | ||
884 | class const_iterator | ||
885 | { | ||
886 | friend class SlotList<T>; | ||
887 | |||
888 | protected: | ||
889 | gate_slotlist_t const* sl; | ||
890 | gate_slotlist_iterator_t iter; | ||
891 | item_t* item; | ||
892 | |||
893 | public: | ||
894 | 51 | const_iterator(gate_slotlist_t const* s, gate_slotlist_iterator_t it, item_t* ptr) noexcept | |
895 | 51 | : sl(s), iter(it), item(ptr) | |
896 | { | ||
897 | 51 | } | |
898 | |||
899 | 51 | ~const_iterator() noexcept | |
900 | { | ||
901 | 51 | } | |
902 | |||
903 | 20 | item_t const* get() const noexcept | |
904 | { | ||
905 | 20 | return this->item; | |
906 | } | ||
907 | |||
908 | 18 | item_t const& operator*() const | |
909 | { | ||
910 | 18 | return *this->get(); | |
911 | } | ||
912 | 1 | item_t const* operator->() const noexcept | |
913 | { | ||
914 | 1 | return this->get(); | |
915 | } | ||
916 | |||
917 | 20 | const_iterator& operator++() noexcept | |
918 | { | ||
919 | 20 | this->item = static_cast<item_t*>(gate_slotlist_next(this->sl, &this->iter)); | |
920 | 20 | return *this; | |
921 | } | ||
922 | const_iterator operator++(int) noexcept | ||
923 | { | ||
924 | const_iterator that(*this); | ||
925 | this->item = static_cast<item_t*>(gate_slotlist_next(this->sl, &this->iter)); | ||
926 | return that; | ||
927 | } | ||
928 | |||
929 | bool_t operator==(const_iterator const& that) const noexcept | ||
930 | { | ||
931 | return (this->sl == that.sl) && (this->item == that.item); | ||
932 | } | ||
933 | |||
934 | 43 | bool_t operator!=(const_iterator const& that) const noexcept | |
935 | { | ||
936 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
43 | return (this->item != that.item) || (this->sl != that.sl); |
937 | } | ||
938 | }; | ||
939 | |||
940 | class iterator : public const_iterator | ||
941 | { | ||
942 | friend class SlotList<T>; | ||
943 | |||
944 | public: | ||
945 | 10 | iterator(gate_slotlist_t const* s, gate_slotlist_iterator_t it, item_t* ptr) noexcept | |
946 | 10 | : const_iterator(s, it, ptr) | |
947 | { | ||
948 | 10 | } | |
949 | |||
950 | 4 | item_t* get() const noexcept | |
951 | { | ||
952 | 4 | return this->item; | |
953 | } | ||
954 | |||
955 | 4 | item_t& operator*() const | |
956 | { | ||
957 | 4 | return *this->get(); | |
958 | } | ||
959 | item_t* operator->() const noexcept | ||
960 | { | ||
961 | return this->get(); | ||
962 | } | ||
963 | }; | ||
964 | |||
965 | friend class const_iterator; | ||
966 | friend class iterator; | ||
967 | |||
968 | 18 | SlotList() noexcept | |
969 | { | ||
970 | 18 | check_outofmem_nullptr(gate_slotlist_create( | |
971 | &this->impl, sizeof(item_t), | ||
972 | &TypeFunctions<item_t>::copyConstruct, | ||
973 | &TypeFunctions<item_t>::destruct)); | ||
974 | 18 | } | |
975 | 3 | SlotList(self_t const& src) | |
976 | { | ||
977 | 3 | check_outofmem_nullptr(gate_slotlist_create_copy(&this->impl, &src.impl)); | |
978 | 3 | } | |
979 | 21 | ~SlotList() noexcept | |
980 | { | ||
981 | 21 | gate_slotlist_destroy(&this->impl); | |
982 | 21 | } | |
983 | 2 | void swap(self_t& that) noexcept | |
984 | { | ||
985 | 2 | gate::swapRefsNoExcept(this->impl, that.impl); | |
986 | 2 | } | |
987 | 1 | self_t& operator=(self_t const& src) | |
988 | { | ||
989 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (this != &src) |
990 | { | ||
991 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | self_t that(src); |
992 | 1 | this->swap(that); | |
993 | } | ||
994 | 1 | return *this; | |
995 | } | ||
996 | |||
997 | 1 | gate_slotlist_t const* c_impl() const noexcept | |
998 | { | ||
999 | 1 | return &this->impl; | |
1000 | } | ||
1001 | |||
1002 | 2 | void optimize() noexcept | |
1003 | { | ||
1004 | 2 | gate_slotlist_optimize(&this->impl); | |
1005 | 2 | } | |
1006 | |||
1007 | 21 | item_t& add(item_t const& src) | |
1008 | { | ||
1009 | 21 | void* ptr = gate_slotlist_add(&this->impl, &src); | |
1010 | 21 | check_outofmem_nullptr(ptr); | |
1011 | 21 | return *static_cast<item_t*>(ptr); | |
1012 | } | ||
1013 | |||
1014 | 1 | item_t& insertAt(size_t index, item_t const& src) | |
1015 | { | ||
1016 | 1 | void* ptr = gate_slotlist_insert_at(&this->impl, index, &src); | |
1017 | 1 | check_outofmem_nullptr(ptr); | |
1018 | 1 | return *static_cast<item_t*>(ptr); | |
1019 | } | ||
1020 | |||
1021 | item_t* getItem(iterator const& iter) noexcept | ||
1022 | { | ||
1023 | return static_cast<item_t*>(gate_slotlist_get(&this->impl, &iter.iter)); | ||
1024 | } | ||
1025 | |||
1026 | 1 | item_t const* getItem(const_iterator const& iter) noexcept | |
1027 | { | ||
1028 | 1 | return static_cast<item_t const*>(gate_slotlist_get(&this->impl, &iter.iter)); | |
1029 | } | ||
1030 | |||
1031 | 7 | item_t* getPtr(size_t index) noexcept | |
1032 | { | ||
1033 | 7 | item_t* ptr = static_cast<item_t*>(gate_slotlist_at(&this->impl, index)); | |
1034 | 7 | return ptr; | |
1035 | } | ||
1036 | 7 | item_t const* getPtr(size_t index) const noexcept | |
1037 | { | ||
1038 | 7 | item_t const* ptr = static_cast<item_t const*>(gate_slotlist_at(&this->impl, index)); | |
1039 | 7 | return ptr; | |
1040 | } | ||
1041 | |||
1042 | 5 | bool_t contains(size_t index) const noexcept | |
1043 | { | ||
1044 | 5 | item_t const* ptr = this->getPtr(index); | |
1045 | 5 | return ptr != NULL; | |
1046 | } | ||
1047 | |||
1048 | 5 | item_t& get(size_t index) noexcept | |
1049 | { | ||
1050 | 5 | item_t* const ptr = this->getPtr(index); | |
1051 | #ifdef GATE_DEBUG_MODE | ||
1052 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (ptr == NULL) |
1053 | { | ||
1054 | ✗ | panic(results::OutOfBounds, "SlotList::get()"); | |
1055 | } | ||
1056 | #endif | ||
1057 | 5 | return *ptr; | |
1058 | } | ||
1059 | 1 | item_t const& get(size_t index) const | |
1060 | { | ||
1061 | 1 | item_t const* const ptr = this->getPtr(index); | |
1062 | #ifdef GATE_DEBUG_MODE | ||
1063 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ptr == NULL) |
1064 | { | ||
1065 | ✗ | panic(results::OutOfBounds, "SlotList::get()"); | |
1066 | } | ||
1067 | #endif | ||
1068 | 1 | return *ptr; | |
1069 | } | ||
1070 | |||
1071 | 1 | void clear() noexcept | |
1072 | { | ||
1073 | 1 | gate_slotlist_clear(&this->impl); | |
1074 | 1 | } | |
1075 | |||
1076 | 6 | size_t length() const noexcept | |
1077 | { | ||
1078 | 6 | return gate_slotlist_length(&this->impl); | |
1079 | } | ||
1080 | 1 | size_t capacity() const noexcept | |
1081 | { | ||
1082 | 1 | return gate_slotlist_capacity(&this->impl); | |
1083 | } | ||
1084 | 21 | const_iterator cend() const noexcept | |
1085 | { | ||
1086 | 21 | return const_iterator(&this->impl, gate_slotlist_capacity(&this->impl), NULL); | |
1087 | } | ||
1088 | 17 | const_iterator cbegin() const noexcept | |
1089 | { | ||
1090 | gate_slotlist_iterator_t it; | ||
1091 | 17 | void* const ptr = gate_slotlist_first(&this->impl, &it); | |
1092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
17 | if (ptr == NULL) |
1093 | { | ||
1094 | ✗ | return this->cend(); | |
1095 | } | ||
1096 | 17 | return const_iterator(&this->impl, it, static_cast<item_t*>(ptr)); | |
1097 | } | ||
1098 | 5 | iterator end() noexcept | |
1099 | { | ||
1100 | 5 | return iterator(&this->impl, gate_slotlist_capacity(&this->impl), NULL); | |
1101 | } | ||
1102 | 5 | iterator begin() noexcept | |
1103 | { | ||
1104 | gate_slotlist_iterator_t it; | ||
1105 | 5 | void* const ptr = gate_slotlist_first(&this->impl, &it); | |
1106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (ptr == NULL) |
1107 | { | ||
1108 | ✗ | return this->end(); | |
1109 | } | ||
1110 | 5 | return iterator(&this->impl, it, static_cast<item_t*>(ptr)); | |
1111 | } | ||
1112 | |||
1113 | 16 | const_iterator begin() const | |
1114 | { | ||
1115 | 16 | return this->cbegin(); | |
1116 | } | ||
1117 | 16 | const_iterator end() const | |
1118 | { | ||
1119 | 16 | return this->cend(); | |
1120 | } | ||
1121 | |||
1122 | 1 | const_iterator getIterator(size_t ndx) const | |
1123 | { | ||
1124 | 1 | return const_iterator(&this->impl, ndx, static_cast<item_t*>(gate_slotlist_at(&this->impl, ndx))); | |
1125 | } | ||
1126 | |||
1127 | 4 | bool_t remove(const_iterator const& it) | |
1128 | { | ||
1129 | 4 | return gate_slotlist_remove(&this->impl, &it.iter); | |
1130 | } | ||
1131 | |||
1132 | bool_t removeAt(size_t index) | ||
1133 | { | ||
1134 | return gate_slotlist_remove_at(&this->impl, index); | ||
1135 | } | ||
1136 | |||
1137 | 1 | Enumerator<item_t const> enumerate() const noexcept | |
1138 | { | ||
1139 | gate_enumerator_t e; | ||
1140 | 1 | gate_enumerator_t* ptr = gate_slotlist_enumerate(&this->impl, &e); | |
1141 | #ifdef GATE_DEBUG_MODE | ||
1142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!ptr) |
1143 | { | ||
1144 | ✗ | panic(results::NullPointer, "SlotList::enumerator"); | |
1145 | } | ||
1146 | #endif | ||
1147 | (void)ptr; | ||
1148 | 1 | return Enumerator<item_t const>(e); | |
1149 | } | ||
1150 | }; | ||
1151 | |||
1152 | |||
1153 | |||
1154 | /// @brief | ||
1155 | /// @tparam T | ||
1156 | template <class T> | ||
1157 | class LinkedList | ||
1158 | { | ||
1159 | public: | ||
1160 | typedef T item_t; | ||
1161 | typedef LinkedList<T> self_t; | ||
1162 | |||
1163 | class iterator | ||
1164 | { | ||
1165 | protected: | ||
1166 | gate_linkedentry_t* ptr_entry; | ||
1167 | |||
1168 | public: | ||
1169 | 24 | iterator(gate_linkedentry_t* entry) noexcept : ptr_entry(entry) {} | |
1170 | 8 | iterator(iterator const& src) noexcept : ptr_entry(src.ptr_entry) {} | |
1171 | iterator& operator=(iterator const& src) noexcept | ||
1172 | { | ||
1173 | this->ptr_entry = src.ptr_entry; | ||
1174 | return *this; | ||
1175 | } | ||
1176 | 32 | ~iterator() noexcept {} | |
1177 | |||
1178 | 5 | gate_linkedentry_t* c_impl() const noexcept { return this->ptr_entry; } | |
1179 | |||
1180 | 35 | item_t* getPtr() const noexcept | |
1181 | { | ||
1182 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 13 times.
|
35 | return this->ptr_entry ? static_cast<item_t*>(this->ptr_entry->data) : NULL; |
1183 | } | ||
1184 | 9 | item_t& get() const noexcept | |
1185 | { | ||
1186 | 9 | item_t* const ptr = this->getPtr(); | |
1187 | #ifdef GATE_DEBUG_MODE | ||
1188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (!ptr) |
1189 | { | ||
1190 | ✗ | panic(results::NullPointer, "LinkedList::iterator::get"); | |
1191 | } | ||
1192 | #endif | ||
1193 | 9 | return *ptr; | |
1194 | } | ||
1195 | |||
1196 | 9 | item_t& operator*() const noexcept { return this->get(); } | |
1197 | item_t* operator->() const noexcept { return this->getPtr(); } | ||
1198 | |||
1199 | 7 | bool operator==(iterator const& src) const { return this->getPtr() == src.getPtr(); } | |
1200 | 6 | bool operator!=(iterator const& src) const { return this->getPtr() != src.getPtr(); } | |
1201 | 3 | iterator& operator++() | |
1202 | { | ||
1203 | 3 | this->ptr_entry = gate_linkedlist_next(this->ptr_entry); | |
1204 | 3 | return *this; | |
1205 | } | ||
1206 | 1 | iterator operator++(int) | |
1207 | { | ||
1208 | 1 | iterator tmp(*this); | |
1209 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ++(*this); |
1210 | 1 | return tmp; | |
1211 | } | ||
1212 | 2 | iterator& operator--() | |
1213 | { | ||
1214 | 2 | this->ptr_entry = gate_linkedlist_previous(this->ptr_entry); | |
1215 | 2 | return *this; | |
1216 | } | ||
1217 | 1 | iterator operator--(int) | |
1218 | { | ||
1219 | 1 | iterator tmp(*this); | |
1220 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | --(*this); |
1221 | 1 | return tmp; | |
1222 | } | ||
1223 | }; | ||
1224 | |||
1225 | class const_iterator | ||
1226 | { | ||
1227 | protected: | ||
1228 | gate_linkedentry_t const* ptr_entry; | ||
1229 | |||
1230 | public: | ||
1231 | 2 | const_iterator(gate_linkedentry_t const* entry) noexcept : ptr_entry(entry) {} | |
1232 | const_iterator(const_iterator const& src) noexcept : ptr_entry(src.ptr_entry) {} | ||
1233 | const_iterator& operator=(const_iterator const& src) noexcept | ||
1234 | { | ||
1235 | this->ptr_entry = src.ptr_entry; | ||
1236 | return *this; | ||
1237 | } | ||
1238 | 2 | ~const_iterator() noexcept {} | |
1239 | |||
1240 | gate_linkedentry_t const* c_impl() const noexcept { return this->ptr_entry; } | ||
1241 | |||
1242 | 5 | item_t const* getPtr() const noexcept | |
1243 | { | ||
1244 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | return this->ptr_entry ? static_cast<item_t const*>(this->ptr_entry->data) : NULL; |
1245 | } | ||
1246 | 3 | item_t const& get() const noexcept | |
1247 | { | ||
1248 | 3 | item_t const* const ptr = this->getPtr(); | |
1249 | #ifdef GATE_DEBUG_MODE | ||
1250 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!ptr) |
1251 | { | ||
1252 | ✗ | panic(results::NullPointer, "LinkedList::const_iterator::get"); | |
1253 | } | ||
1254 | #endif | ||
1255 | 3 | return *ptr; | |
1256 | } | ||
1257 | |||
1258 | item_t const* operator->() const noexcept { return this->getPtr(); } | ||
1259 | 3 | item_t const& operator*() const noexcept { return this->get(); } | |
1260 | |||
1261 | 1 | bool operator==(const_iterator const& src) const { return this->getPtr() == src.getPtr(); } | |
1262 | bool operator!=(const_iterator const& src) const { return this->getPtr() != src.getPtr(); } | ||
1263 | 3 | const_iterator& operator++() | |
1264 | { | ||
1265 | 3 | this->ptr_entry = gate_linkedlist_next(this->ptr_entry); | |
1266 | 3 | return *this; | |
1267 | } | ||
1268 | const_iterator operator++(int) | ||
1269 | { | ||
1270 | const_iterator tmp(*this); | ||
1271 | ++(*this); | ||
1272 | return tmp; | ||
1273 | } | ||
1274 | const_iterator& operator--() | ||
1275 | { | ||
1276 | this->ptr_entry = gate_linkedlist_previous(this->ptr_entry); | ||
1277 | return *this; | ||
1278 | } | ||
1279 | const_iterator operator--(int) | ||
1280 | { | ||
1281 | const_iterator tmp(*this); | ||
1282 | --(*this); | ||
1283 | return tmp; | ||
1284 | } | ||
1285 | }; | ||
1286 | |||
1287 | class reverse_iterator : public iterator | ||
1288 | { | ||
1289 | public: | ||
1290 | 13 | reverse_iterator(gate_linkedentry_t* entry) noexcept : iterator(entry) {} | |
1291 | 2 | reverse_iterator(reverse_iterator const& src) noexcept : iterator(src) {} | |
1292 | reverse_iterator& operator=(reverse_iterator const& src) noexcept | ||
1293 | { | ||
1294 | this->ptr_entry = src.ptr_entry; | ||
1295 | return *this; | ||
1296 | } | ||
1297 | |||
1298 | 2 | reverse_iterator& operator--() | |
1299 | { | ||
1300 | 2 | this->ptr_entry = gate_linkedlist_next(this->ptr_entry); | |
1301 | 2 | return *this; | |
1302 | } | ||
1303 | 1 | reverse_iterator operator--(int) | |
1304 | { | ||
1305 | 1 | reverse_iterator tmp(*this); | |
1306 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | --(*this); |
1307 | 1 | return tmp; | |
1308 | } | ||
1309 | 3 | reverse_iterator& operator++() | |
1310 | { | ||
1311 | 3 | this->ptr_entry = gate_linkedlist_previous(this->ptr_entry); | |
1312 | 3 | return *this; | |
1313 | } | ||
1314 | 1 | reverse_iterator operator++(int) | |
1315 | { | ||
1316 | 1 | reverse_iterator tmp(*this); | |
1317 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ++(*this); |
1318 | 1 | return tmp; | |
1319 | } | ||
1320 | }; | ||
1321 | |||
1322 | class const_reverse_iterator : public const_iterator | ||
1323 | { | ||
1324 | public: | ||
1325 | const_reverse_iterator(gate_linkedentry_t const* entry) noexcept : const_iterator(entry) {} | ||
1326 | const_reverse_iterator(const_reverse_iterator const& src) noexcept : const_iterator(src) {} | ||
1327 | const_reverse_iterator& operator=(const_reverse_iterator const& src) noexcept | ||
1328 | { | ||
1329 | this->ptr_entry = src.ptr_entry; | ||
1330 | return *this; | ||
1331 | } | ||
1332 | |||
1333 | const_reverse_iterator& operator--() | ||
1334 | { | ||
1335 | this->ptr_entry = gate_linkedlist_next(this->ptr_entry); | ||
1336 | return *this; | ||
1337 | } | ||
1338 | const_reverse_iterator operator--(int) | ||
1339 | { | ||
1340 | const_reverse_iterator tmp(*this); | ||
1341 | --(*this); | ||
1342 | return tmp; | ||
1343 | } | ||
1344 | const_reverse_iterator& operator++() | ||
1345 | { | ||
1346 | this->ptr_entry = gate_linkedlist_previous(this->ptr_entry); | ||
1347 | return *this; | ||
1348 | } | ||
1349 | const_reverse_iterator operator++(int) | ||
1350 | { | ||
1351 | const_reverse_iterator tmp(*this); | ||
1352 | ++(*this); | ||
1353 | return tmp; | ||
1354 | } | ||
1355 | }; | ||
1356 | |||
1357 | private: | ||
1358 | gate_linkedlist_t impl; | ||
1359 | |||
1360 | public: | ||
1361 | 1 | LinkedList() noexcept | |
1362 | { | ||
1363 | 1 | result_t ret = gate_linkedlist_create(&this->impl, sizeof(T), &TypeFunctions<T>::copyConstruct, &TypeFunctions<T>::destruct); | |
1364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | GATEXX_CHECK_ERROR(ret); |
1365 | 1 | } | |
1366 | 3 | LinkedList(self_t const& src) | |
1367 | { | ||
1368 | 3 | result_t ret = gate_linkedlist_create(&this->impl, sizeof(T), &TypeFunctions<T>::copyConstruct, &TypeFunctions<T>::destruct); | |
1369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | GATEXX_CHECK_ERROR(ret); |
1370 | |||
1371 | 3 | gate_linkedentry_t* entry = gate_linkedlist_first(&src.impl); | |
1372 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | while (entry != NULL) |
1373 | { | ||
1374 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (NULL == gate_linkedlist_add(&this->impl, entry->data)) |
1375 | { | ||
1376 | ✗ | gate_linkedlist_destroy(&this->impl); | |
1377 | ✗ | GATEXX_RAISE_ERROR(results::OutOfMemory); | |
1378 | } | ||
1379 | 6 | entry = gate_linkedlist_next(entry); | |
1380 | } | ||
1381 | 3 | } | |
1382 | 1 | void swap(self_t& that) noexcept | |
1383 | { | ||
1384 | 1 | gate::swapRefsNoExcept(this->impl, that.impl); | |
1385 | 1 | } | |
1386 | 1 | self_t& operator=(self_t const& src) | |
1387 | { | ||
1388 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (this != &src) |
1389 | { | ||
1390 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | self_t that(src); |
1391 | 1 | this->swap(that); | |
1392 | } | ||
1393 | 1 | return *this; | |
1394 | } | ||
1395 | 4 | ~LinkedList() noexcept | |
1396 | { | ||
1397 | 4 | gate_linkedlist_destroy(&this->impl); | |
1398 | 4 | } | |
1399 | |||
1400 | 3 | iterator add(item_t const& item) noexcept | |
1401 | { | ||
1402 | 3 | gate_linkedentry_t* ptr_entry = gate_linkedlist_add(&this->impl, &item); | |
1403 | 3 | return iterator(ptr_entry); | |
1404 | } | ||
1405 | |||
1406 | 1 | iterator insert(iterator insertAt, item_t const& item) noexcept | |
1407 | { | ||
1408 | 1 | gate_linkedentry_t* ptr_entry = gate_linkedlist_insert(&this->impl, insertAt.c_impl(), &item); | |
1409 | 1 | return iterator(ptr_entry); | |
1410 | } | ||
1411 | |||
1412 | 4 | VoidResult remove(iterator iter) noexcept | |
1413 | { | ||
1414 | 4 | result_t result = gate_linkedlist_remove(&this->impl, iter.c_impl()); | |
1415 | 4 | return makeResult(result); | |
1416 | } | ||
1417 | |||
1418 | 5 | bool_t empty() const noexcept | |
1419 | { | ||
1420 | 5 | return gate_linkedlist_empty(&this->impl); | |
1421 | } | ||
1422 | |||
1423 | 3 | iterator begin() noexcept | |
1424 | { | ||
1425 | 3 | gate_linkedentry_t* ptr = gate_linkedlist_first(&this->impl); | |
1426 | 3 | return iterator(ptr); | |
1427 | } | ||
1428 | 4 | iterator end() noexcept | |
1429 | { | ||
1430 | 4 | return iterator(NULL); | |
1431 | } | ||
1432 | 1 | const_iterator cbegin() const noexcept | |
1433 | { | ||
1434 | 1 | gate_linkedentry_t const* ptr = gate_linkedlist_first(&this->impl); | |
1435 | 1 | return const_iterator(ptr); | |
1436 | } | ||
1437 | 1 | const_iterator cend() const noexcept | |
1438 | { | ||
1439 | 1 | return const_iterator(NULL); | |
1440 | } | ||
1441 | 1 | const_iterator begin() const noexcept { return this->cbegin(); } | |
1442 | const_iterator end() const noexcept { return this->cend(); } | ||
1443 | |||
1444 | 6 | reverse_iterator rbegin() noexcept | |
1445 | { | ||
1446 | 6 | gate_linkedentry_t* const ptr = gate_linkedlist_last(&this->impl); | |
1447 | 6 | return reverse_iterator(ptr); | |
1448 | } | ||
1449 | 7 | reverse_iterator rend() noexcept | |
1450 | { | ||
1451 | 7 | return reverse_iterator(NULL); | |
1452 | } | ||
1453 | const_reverse_iterator crbegin() const noexcept | ||
1454 | { | ||
1455 | gate_linkedentry_t const* const ptr = gate_linkedlist_last(&this->impl); | ||
1456 | return const_reverse_iterator(ptr); | ||
1457 | } | ||
1458 | const_reverse_iterator crend() const noexcept | ||
1459 | { | ||
1460 | return const_reverse_iterator(NULL); | ||
1461 | } | ||
1462 | const_reverse_iterator rbegin() const noexcept { return this->crbegin(); } | ||
1463 | const_reverse_iterator rend() const noexcept { return this->crend(); } | ||
1464 | |||
1465 | 3 | iterator push(item_t const& item) noexcept | |
1466 | { | ||
1467 | 3 | return this->add(item); | |
1468 | } | ||
1469 | 3 | item_t pop() | |
1470 | { | ||
1471 | 3 | reverse_iterator iter = this->rbegin(); | |
1472 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | if (iter == this->rend()) |
1473 | { | ||
1474 | ✗ | GATEXX_RAISE_ERROR(results::NotAvailable); | |
1475 | } | ||
1476 | 3 | item_t ret = *iter; | |
1477 | 3 | this->remove(iter); | |
1478 | 6 | return ret; | |
1479 | } | ||
1480 | |||
1481 | 1 | Enumerator<item_t const> enumerate() const noexcept | |
1482 | { | ||
1483 | gate_enumerator_t e; | ||
1484 | 1 | gate_enumerator_t* tmp = gate_linkedlist_enumerate(&this->impl, &e); | |
1485 | #ifdef GATE_DEBUG_MODE | ||
1486 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!tmp) |
1487 | { | ||
1488 | ✗ | panic(results::NullPointer, "LinkedList::enumerate"); | |
1489 | } | ||
1490 | #else | ||
1491 | (void)tmp; | ||
1492 | #endif | ||
1493 | 1 | return Enumerator<item_t const>(e); | |
1494 | } | ||
1495 | |||
1496 | 3 | self_t& operator<<(item_t const& item) | |
1497 | { | ||
1498 | 3 | this->push(item); | |
1499 | 3 | return *this; | |
1500 | } | ||
1501 | 3 | self_t& operator>>(item_t& item) | |
1502 | { | ||
1503 | 3 | item = this->pop(); | |
1504 | 3 | return *this; | |
1505 | } | ||
1506 | }; | ||
1507 | |||
1508 | } // end of namespace gate | ||
1509 | |||
1510 | #endif | ||
1511 |