GCC Code Coverage Report


Directory: src/gate/
File: src/gate/maps.hpp
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 373 409 91.2%
Functions: 338 409 82.6%
Branches: 47 94 50.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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 Associative fields to map and resolve key entries to values
31 * @ingroup gatecore_cpp
32 */
33
34 #ifndef GATE_MAPS_HPP_INCLUDED
35 #define GATE_MAPS_HPP_INCLUDED
36
37 #include "gate/maps.h"
38 #include "gate/comparers.hpp"
39 #include "gate/memalloc.hpp"
40 #include "gate/results.hpp"
41 #include "gate/exceptions.hpp"
42 #include "gate/debugging.h"
43 #include "gate/enumerators.hpp"
44 #include "gate/hashes.hpp"
45
46 namespace gate
47 {
48
49 template<class KEY, class VALUE>
50 class Mapping
51 {
52 public:
53 typedef KEY key_t;
54 typedef VALUE value_t;
55 typedef Mapping<KEY, VALUE> self_t;
56 private:
57 #if defined(GATE_DEBUG_MODE)
58 union
59 {
60 gate_mapping_t impl;
61 struct
62 {
63 key_t const* key_shadow;
64 value_t const* value_shadow;
65 };
66 };
67 #else
68 gate_mapping_t impl;
69 #endif
70 protected:
71 1506506 void loadMapping(gate_mapping_t const& mapping) noexcept
72 {
73 #if defined(GATE_DEBUG_MODE)
74 1506506 this->key_shadow = NULL;
75 1506506 this->value_shadow = NULL;
76 #endif
77 1506506 this->impl = mapping;
78 1506506 }
79
80 public:
81 6206 Mapping() noexcept
82 {
83 6206 Mem::clear(this->impl);
84 6206 }
85
86 130 Mapping(gate_mapping_t const& mapping) noexcept
87 {
88 130 this->loadMapping(mapping);
89 130 }
90
91 130 Mapping(self_t const& src) noexcept
92 {
93 130 this->loadMapping(src.impl);
94 130 }
95
96 self_t& operator=(self_t const& src) noexcept
97 {
98 this->loadMapping(src.impl);
99 return *this;
100 }
101
102 6336 ~Mapping() noexcept
103 {
104 6336 }
105
106 996207 key_t const& key() const noexcept
107 {
108 996207 return *static_cast<key_t const*>(this->impl.key);
109 }
110
111 170 value_t const& value() const noexcept
112 {
113 170 return *static_cast<value_t const*>(this->impl.value);
114 }
115
116 gate_mapping_t const* c_impl() const noexcept
117 {
118 return &this->impl;
119 }
120 };
121
122 template<class KEY, class VALUE, class COMPARER = DefaultComparer<KEY> >
123 class Map
124 {
125 public:
126 typedef KEY key_t;
127 typedef VALUE value_t;
128 typedef Map<KEY, VALUE, COMPARER> self_t;
129 typedef Mapping<KEY, VALUE> mapping_t;
130
131 private:
132 gate_map_t impl;
133
134 public:
135
136 class const_iterator : public mapping_t
137 {
138 protected:
139 gate_map_iterator_t iter;
140
141 1506202 void loadIterator(gate_map_iterator_t mapiter) noexcept
142 {
143 1506202 this->iter = mapiter;
144
2/2
✓ Branch 1 taken 750047 times.
✓ Branch 2 taken 3063 times.
1506202 if (gate_map_iterator_valid(mapiter))
145 {
146 1500085 this->loadMapping(this->iter->mapping);
147 }
148 else
149 {
150 static gate_mapping_t const empty_mapping = GATE_INIT_EMPTY;
151 6117 this->loadMapping(empty_mapping);
152 }
153 1506202 }
154
155 public:
156 4166 const_iterator(gate_map_iterator_t mapiter) noexcept
157 4166 : iter(NULL)
158 {
159 4166 this->loadIterator(mapiter);
160 4166 }
161 2012 const_iterator(const_iterator const& src) noexcept
162 2012 : iter(NULL)
163 {
164 2012 this->loadIterator(src.iter);
165 2012 }
166 500000 const_iterator& operator=(const_iterator const& src) noexcept
167 {
168 500000 this->loadIterator(src.iter);
169 500000 return *this;
170 }
171
172 76 bool_t operator==(const_iterator const& that) const noexcept
173 {
174 76 return gate_map_iterator_equals(this->iter, that.iter);
175 }
176 501001 bool_t operator!=(const_iterator const& that) const noexcept
177 {
178 501001 return !gate_map_iterator_equals(this->iter, that.iter);
179 }
180
181 500008 const_iterator& operator++() noexcept { this->loadIterator(gate_map_iterator_next(this->iter)); return *this; }
182 4 const_iterator operator++(int) noexcept { const_iterator ret(*this); ++(*this); return ret; }
183
184 8 const_iterator& operator--() noexcept { this->loadIterator(gate_map_iterator_prev(this->iter)); return *this; }
185 4 const_iterator operator--(int) noexcept { const_iterator ret(*this); --(*this); return ret; }
186
187 20 mapping_t const& operator*() const noexcept { return *this; }
188 };
189
190 class iterator : public const_iterator
191 {
192 public:
193 4 iterator(gate_map_iterator_t mapiter) noexcept : const_iterator(mapiter) {}
194 2 iterator(iterator const& src) noexcept : const_iterator(src) {}
195 iterator& operator=(iterator const& src) noexcept
196 {
197 const_iterator::operator=(static_cast<const_iterator const&>(src));
198 return *this;
199 }
200
201 4 value_t& value() noexcept { return *static_cast<value_t*>(gate_map_iterator_value(this->iter)); }
202
203 2 iterator& operator++() noexcept { this->loadIterator(gate_map_iterator_next(this->iter)); return *this; }
204 1 iterator operator++(int) noexcept { iterator ret(*this); ++(*this); return ret; }
205
206 2 iterator& operator--() noexcept { this->loadIterator(gate_map_iterator_prev(this->iter)); return *this; }
207 1 iterator operator--(int) noexcept { iterator ret(*this); --(*this); return ret; }
208 };
209
210 50 Map() noexcept
211 {
212 50 gate_map_create(&this->impl, &COMPARER::c_compare,
213 sizeof(key_t), &TypeFunctions<key_t>::copyConstruct, &TypeFunctions<key_t>::destruct,
214 sizeof(value_t), &TypeFunctions<value_t>::copyConstruct, &TypeFunctions<value_t>::destruct
215 );
216 50 }
217
218 8 Map(self_t const& src)
219 {
220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
8 if (NULL == gate_map_copy(&this->impl, &src.impl))
221 {
222 GATEXX_RAISE_ERROR(results::OutOfMemory);
223 }
224 8 }
225
226 18 void swap(self_t& that) noexcept
227 {
228 18 gate::swapRefsNoExcept(this->impl, that.impl);
229 18 }
230
231 4 self_t& operator=(self_t const& src)
232 {
233
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 self_t that(src);
234 4 this->swap(that);
235 8 return *this;
236 }
237
238 58 ~Map() noexcept
239 {
240 58 gate_map_destroy(&this->impl);
241 58 }
242
243 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
244 Map(self_t&& that) noexcept
245 : impl(that.impl)
246 {
247 Mem::clear(that.impl);
248 }
249
250 5 self_t& operator=(self_t&& that) noexcept
251 {
252 5 self_t tmp;
253 5 that.swap(tmp);
254 5 this->swap(tmp);
255 5 return *this;
256 }
257 #endif
258
259 2 gate_map_t const* c_impl() const
260 {
261 2 return &this->impl;
262 }
263
264 1106 void add(key_t const& key, value_t const& value)
265 {
266
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 584 times.
1106 if (NULL == gate_map_add(&this->impl, &key, &value))
267 {
268 GATEXX_RAISE_ERROR(results::OutOfMemory);
269 }
270 1106 }
271 97 VoidResult tryAdd(key_t const& key, value_t const& value) noexcept
272 {
273 97 gate_map_iterator_t const iter = gate_map_add(&this->impl, &key, &value);
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 result_t const resultCode = (iter == NULL) ? results::OutOfMemory : results::Ok;
275 97 return makeResult(resultCode);
276 }
277
278 1002 bool_t remove(key_t const& key) noexcept
279 {
280 1002 return gate_map_remove(&this->impl, &key);
281 }
282
283 1 iterator get(key_t const& key) noexcept
284 {
285 1 return iterator(gate_map_get(&this->impl, &key));
286 }
287 80 const_iterator get(key_t const& key) const noexcept
288 {
289 80 return const_iterator(gate_map_get(&this->impl, &key));
290 }
291
292 4 const_iterator find(key_t const& key) const noexcept
293 {
294 4 return this->get(key);
295 }
296
297 4 value_t getValue(key_t const& key, value_t const& altvalue) const
298 {
299 8 const_iterator it = this->get(key);
300
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 if (it == this->cend())
301 {
302 return altvalue;
303 }
304 else
305 {
306 4 return it.value();
307 }
308 }
309
310 4 void clear() noexcept
311 {
312 4 gate_map_clear(&this->impl);
313 4 }
314
315 2030 size_t count() const noexcept
316 {
317 2030 return gate_map_count(&this->impl);
318 }
319
320 3 bool_t empty() const noexcept
321 {
322 3 return this->count() == 0;
323 }
324
325 2004 const_iterator cbegin() const noexcept
326 {
327 2004 return const_iterator(gate_map_first(&this->impl));
328 }
329 2076 const_iterator cend() const noexcept
330 {
331 2076 return const_iterator(NULL);
332 }
333 2 iterator begin() noexcept
334 {
335 2 return iterator(gate_map_first(&this->impl));
336 }
337 1 iterator end() noexcept
338 {
339 1 return iterator(NULL);
340 }
341 1000 const_iterator begin() const noexcept
342 {
343 1000 return this->cbegin();
344 }
345 2072 const_iterator end() const noexcept
346 {
347 2072 return this->cend();
348 }
349
350 12 bool_t contains(key_t const& key, value_t const** ptrValue = NULL) const noexcept
351 {
352 24 const_iterator iter = this->get(key);
353
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 6 times.
12 if (iter == this->end())
354 {
355 4 return false;
356 }
357 else
358 {
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
8 if (ptrValue != NULL)
360 {
361 *ptrValue = &iter.value();
362 }
363 8 return true;
364 }
365 }
366
367 typedef Enumerator<mapping_t> enumerator_t;
368
369 148 static gate_bool_t enumerator_is_valid(gate_enumerator_t const* enumerator) noexcept
370 {
371 148 return gate_map_iterator_valid(static_cast<gate_map_iterator_t>(enumerator->current_position));
372 }
373 130 static gate_bool_t enumerator_next(gate_enumerator_t* enumerator) noexcept
374 {
375 130 gate_map_iterator_t iter = static_cast<gate_map_iterator_t>(enumerator->current_position);
376 130 gate_map_iterator_t next_iter = gate_map_iterator_next(iter);
377 130 enumerator->current_position = static_cast<void*>(next_iter);
378 130 gate_bool_t ret = gate_map_iterator_valid(next_iter);
379
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 10 times.
130 if (ret)
380 {
381 224 mapping_t mapping(next_iter->mapping);
382 112 TypeFunctions<mapping_t>::copyConstruct(&enumerator->handles[0], &mapping);
383 }
384 130 return ret;
385
386 }
387 211 static void const* enumerator_get(gate_enumerator_t const* enumerator) noexcept
388 {
389 211 mapping_t const* ptr_mapping = reinterpret_cast<mapping_t const*>(&enumerator->handles[0]);
390 211 return ptr_mapping;
391 }
392 32 static void const* enumerator_get_key(gate_enumerator_t const* enumerator) noexcept
393 {
394 32 mapping_t const* ptr_mapping = reinterpret_cast<mapping_t const*>(&enumerator->handles[0]);
395 32 return &ptr_mapping->key();
396 }
397 6 static void const* enumerator_get_value(gate_enumerator_t const* enumerator) noexcept
398 {
399 6 mapping_t const* ptr_mapping = reinterpret_cast<mapping_t const*>(&enumerator->handles[0]);
400 6 return &ptr_mapping->value();
401 }
402
403 3 enumerator_t enumerate() const noexcept
404 {
405 3 gate_map_iterator_t iter_begin = gate_map_first(&this->impl);
406 gate_enumerator_t enumerator;
407 3 Mem::clear(enumerator);
408 3 enumerator.is_valid = &self_t::enumerator_is_valid;
409 3 enumerator.next = &self_t::enumerator_next;
410 3 enumerator.get = &self_t::enumerator_get;
411 3 enumerator.ptr_origin = &this->impl;
412 3 enumerator.current_position = static_cast<void*>(iter_begin);
413 3 gate_bool_t valid = gate_map_iterator_valid(iter_begin);
414
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (valid)
415 {
416 6 mapping_t mapping(iter_begin->mapping);
417 3 TypeFunctions<mapping_t>::copyConstruct(&enumerator.handles[0], &mapping);
418 }
419 3 return enumerator_t(enumerator);
420 }
421
422 12 Enumerator<key_t const> enumerateKeys() const noexcept
423 {
424 12 gate_map_iterator_t iter_begin = gate_map_first(&this->impl);
425 gate_enumerator_t enumerator;
426 12 Mem::clear(enumerator);
427 12 enumerator.is_valid = &self_t::enumerator_is_valid;
428 12 enumerator.next = &self_t::enumerator_next;
429 12 enumerator.get = &self_t::enumerator_get_key;
430 12 enumerator.ptr_origin = &this->impl;
431 12 enumerator.current_position = static_cast<void*>(iter_begin);
432 12 gate_bool_t valid = gate_map_iterator_valid(iter_begin);
433
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 if (valid)
434 {
435 24 mapping_t mapping(iter_begin->mapping);
436 12 TypeFunctions<mapping_t>::copyConstruct(&enumerator.handles[0], &mapping);
437 }
438 12 return Enumerator<key_t const>(enumerator);
439 }
440
441 1 Enumerator<value_t> enumerateValues() const noexcept
442 {
443 1 gate_map_iterator_t iter_begin = gate_map_first(&this->impl);
444 gate_enumerator_t enumerator;
445 1 Mem::clear(enumerator);
446 1 enumerator.is_valid = &self_t::enumerator_is_valid;
447 1 enumerator.next = &self_t::enumerator_next;
448 1 enumerator.get = &self_t::enumerator_get_value;
449 1 enumerator.ptr_origin = &this->impl;
450 1 enumerator.current_position = static_cast<void*>(iter_begin);
451 1 gate_bool_t valid = gate_map_iterator_valid(iter_begin);
452
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (valid)
453 {
454 2 mapping_t mapping(iter_begin->mapping);
455 1 TypeFunctions<mapping_t>::copyConstruct(&enumerator.handles[0], &mapping);
456 }
457 1 return Enumerator<value_t>(enumerator);
458 }
459 };
460
461 #define gate_map_for_each(iterator_var, map_type, map_instance) \
462 for(map_type ::const_iterator iterator_var = map_instance.begin(); iterator_var != map_instance.end(); ++iterator_var)
463
464
465
466
467
468
469 template<class KEY, class COMPARER = DefaultComparer<KEY> >
470 class Set : public Map<KEY, bool_t, COMPARER>
471 {
472 public:
473 typedef KEY key_t;
474 typedef Map<KEY, bool_t, COMPARER> base_t;
475 typedef Set<KEY, COMPARER> self_t;
476 typedef typename base_t::const_iterator const_iterator;
477 typedef typename base_t::const_iterator iterator;
478
479 typedef Enumerator<key_t const> enumerator_t;
480
481 public:
482 3 Set() noexcept
483 3 : base_t()
484 {
485 3 }
486
487 1 Set(self_t const& src)
488 1 : base_t(src)
489 {
490 1 }
491
492 Set(enumerator_t enumerator)
493 : base_t()
494 {
495 for (; enumerator.valid(); enumerator.next())
496 {
497 this->add(*enumerator);
498 }
499 }
500
501 1 void swap(self_t& that) noexcept
502 {
503 1 base_t::swap(that);
504 1 }
505
506 1 self_t& operator=(self_t const& src)
507 {
508 1 base_t::operator=(src);
509 1 return *this;
510 }
511
512 4 ~Set() noexcept
513 {
514 4 }
515
516 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
517 Set(self_t&& that) noexcept
518 : base_t(static_cast<base_t&&>(that))
519 {
520 }
521
522 self_t& operator=(self_t&& that) noexcept
523 {
524 self_t tmp;
525 that.swap(tmp);
526 this->swap(tmp);
527 return *this;
528 }
529 #endif
530
531 6 void add(key_t const& key)
532 {
533 static bool_t value = false;
534 6 base_t::add(key, value);
535 6 }
536
537 2 bool_t contains(key_t const& key) const noexcept
538 {
539 2 return base_t::contains(key);
540 }
541
542 1 enumerator_t enumerate() const noexcept
543 {
544 1 return base_t::enumerateKeys();
545 }
546 };
547
548
549
550
551
552
553
554 template<class KEY, class VALUE, class COMPARER = DefaultComparer<KEY> >
555 class FlatMap
556 {
557 public:
558 typedef KEY key_t;
559 typedef VALUE value_t;
560 typedef FlatMap<KEY, VALUE, COMPARER> self_t, seqmap_t;
561
562 private:
563 gate_flatmap_t impl;
564
565 public:
566 typedef gate_mapping_t const* const* gate_flatmap_iterator_t;
567
568 class const_iterator
569 {
570 protected:
571 #if defined(GATE_DEBUG_MODE)
572 struct typed_mapping
573 {
574 key_t const* key_ptr;
575 value_t const* value_ptr;
576 };
577 union
578 {
579 gate_flatmap_iterator_t iter;
580 typed_mapping const* const* mapping;
581 };
582 #else
583 gate_flatmap_iterator_t iter;
584 #endif
585 gate_flatmap_t const* source;
586
587 56 void loadIterator(gate_flatmap_t const* mapptr, gate_flatmap_iterator_t mapiter) noexcept
588 {
589 56 this->iter = mapiter;
590 56 this->source = mapptr;
591 56 }
592
593 public:
594 34 const_iterator(gate_flatmap_t const* mapptr = NULL, gate_flatmap_iterator_t mapiter = NULL) noexcept
595 {
596 34 this->loadIterator(mapptr, mapiter);
597 34 }
598 14 const_iterator(const_iterator const& src) noexcept
599 {
600 14 this->loadIterator(src.source, src.iter);
601 14 }
602 const_iterator& operator=(const_iterator const& src) noexcept
603 {
604 this->loadIterator(src.source, src.iter);
605 return *this;
606 }
607
608 21 key_t const& key() const noexcept { return *static_cast<key_t const*>(gate_flatmap_iterator_key(this->iter)); }
609 14 value_t const& value() const noexcept { return *static_cast<value_t const*>(gate_flatmap_iterator_value(this->iter)); }
610
611 9 bool_t operator==(const_iterator const& that) const noexcept { return this->iter == that.iter; }
612 2 bool_t operator!=(const_iterator const& that) const noexcept { return this->iter != that.iter; }
613
614 2 const_iterator& operator++() noexcept { this->loadIterator(this->source, gate_flatmap_iterator_next(this->iter)); return *this; }
615 1 const_iterator operator++(int) noexcept { const_iterator ret(*this); ++(*this); return ret; }
616
617 2 const_iterator& operator--() noexcept { this->loadIterator(this->source, gate_flatmap_iterator_prev(this->iter)); return *this; }
618 1 const_iterator operator--(int) noexcept { const_iterator ret(*this); --(*this); return ret; }
619 };
620
621 class iterator : public const_iterator
622 {
623 public:
624 3 iterator(gate_flatmap_t const* mapptr = NULL, gate_flatmap_iterator_t mapiter = NULL) noexcept : const_iterator(mapptr, mapiter) {}
625 2 iterator(iterator const& src) noexcept : const_iterator(src) {}
626 iterator& operator=(iterator const& src) noexcept
627 {
628 const_iterator::operator=(static_cast<const_iterator const&>(src));
629 return *this;
630 }
631
632 value_t& value() noexcept { return *static_cast<value_t*>(gate_flatmap_iterator_value(this->iter)); }
633
634 2 iterator& operator++() noexcept { this->loadIterator(this->source, gate_flatmap_iterator_next(this->iter)); return *this; }
635 1 iterator operator++(int) noexcept { iterator ret(*this); ++(*this); return ret; }
636
637 2 iterator& operator--() noexcept { this->loadIterator(this->source, gate_flatmap_iterator_prev(this->iter)); return *this; }
638 1 iterator operator--(int) noexcept { iterator ret(*this); --(*this); return ret; }
639 };
640
641 18 FlatMap()
642 {
643
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_flatmap_create(&this->impl, &COMPARER::c_compare,
644 sizeof(key_t), &TypeFunctions<key_t>::copyConstruct, &TypeFunctions<key_t>::destruct,
645 sizeof(value_t), &TypeFunctions<value_t>::copyConstruct, &TypeFunctions<value_t>::destruct
646 ))
647 {
648 GATEXX_RAISE_ERROR(results::OutOfMemory);
649 }
650 18 }
651
652 3 FlatMap(self_t const& src)
653 {
654
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_flatmap_copy(&this->impl, &src.impl))
655 {
656 GATEXX_RAISE_ERROR(results::OutOfMemory);
657 }
658 3 }
659
660 3 void swap(self_t& that) noexcept
661 {
662 3 gate::swapRefsNoExcept(this->impl, that.impl);
663 3 }
664
665 2 self_t& operator=(self_t const& src)
666 {
667
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 self_t that(src);
668 2 this->swap(that);
669 4 return *this;
670 }
671
672 21 ~FlatMap() noexcept
673 {
674 21 gate_flatmap_destroy(&this->impl);
675 21 }
676
677 1 gate_flatmap_t const* c_impl() const noexcept
678 {
679 1 return &this->impl;
680 }
681 1 gate_flatmap_t* c_impl() noexcept
682 {
683 1 return &this->impl;
684 }
685
686 24 void add(key_t const& key, value_t const& value)
687 {
688
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if (NULL == gate_flatmap_add(&this->impl, &key, &value))
689 {
690 GATEXX_RAISE_ERROR(results::OutOfMemory);
691 }
692 24 }
693 1 bool_t remove(key_t const& key) noexcept
694 {
695 1 return gate_flatmap_remove(&this->impl, &key);
696 }
697
698 1 iterator get(key_t const& key) noexcept
699 {
700 1 return iterator(&this->impl, gate_flatmap_get(&this->impl, &key));
701 }
702 10 const_iterator get(key_t const& key) const noexcept
703 {
704 10 return const_iterator(&this->impl, gate_flatmap_get(&this->impl, &key));
705 }
706
707 7 value_t getValue(key_t const& key, value_t const& altvalue) const
708 {
709 7 const_iterator it = this->get(key);
710
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (it == this->cend())
711 {
712 return altvalue;
713 }
714 else
715 {
716
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
7 return it.value();
717 }
718 }
719
720 1 const_iterator find(key_t const& key) const noexcept
721 {
722 1 return this->get(key);
723 }
724
725 1 void clear()
726 {
727 1 gate_flatmap_clear(&this->impl);
728 1 }
729
730 15 size_t count() const noexcept
731 {
732 15 return gate_flatmap_count(&this->impl);
733 }
734
735 1 const_iterator cbegin() const noexcept
736 {
737 1 return const_iterator(&this->impl, gate_flatmap_first(&this->impl));
738 }
739 10 const_iterator cend() const noexcept
740 {
741 10 return const_iterator(&this->impl, gate_flatmap_end(&this->impl));
742 }
743 1 iterator begin() noexcept
744 {
745 1 return iterator(&this->impl, gate_flatmap_first(&this->impl));
746 }
747 1 iterator end() noexcept
748 {
749 1 return iterator(&this->impl, gate_flatmap_end(&this->impl));
750 }
751 const_iterator begin() const noexcept
752 {
753 return this->cbegin();
754 }
755 2 const_iterator end() const noexcept
756 {
757 2 return this->cend();
758 }
759
760 2 bool_t contains(key_t const& key, value_t const** ptrValue = NULL) const
761 {
762 2 const_iterator iter = this->get(key);
763
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (iter == this->end())
764 {
765 1 return false;
766 }
767 else
768 {
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptrValue != NULL)
770 {
771 *ptrValue = &iter.value();
772 }
773 1 return true;
774 }
775 }
776
777 typedef Enumerator<const_iterator> enumerator_t;
778
779 7 static gate_bool_t enumerator_next(gate_enumerator_t* enumerator)
780 {
781
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (enumerator->current_position)
782 {
783
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 enumerator->current_position = (void*)gate_flatmap_iterator_next((gate_flatmap_iterator_t)enumerator->current_position);
784 7 const_iterator iter((gate_flatmap_t const*)enumerator->ptr_origin, (gate_flatmap_iterator_t)enumerator->current_position);
785 7 TypeFunctions<const_iterator>::copyConstruct(&enumerator->handles[0], &iter);
786 7 return true;
787 }
788 else
789 {
790 return false;
791 }
792 }
793 14 static void const* enumerator_get(gate_enumerator_t const* enumerator) noexcept
794 {
795 14 return &enumerator->handles[0];
796 }
797 10 static gate_bool_t enumerator_is_valid(gate_enumerator_t const* enumerator) noexcept
798 {
799 10 return gate_flatmap_iterator_valid((gate_flatmap_t const*)enumerator->ptr_origin, (gate_flatmap_iterator_t)enumerator->current_position);
800 }
801
802 3 enumerator_t enumerate() const
803 {
804 gate_enumerator_t enumerator;
805
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 gate_flatmap_enumerate(&this->impl, &enumerator);
806 3 enumerator.next = &self_t::enumerator_next;
807 3 enumerator.get = &self_t::enumerator_get;
808 3 enumerator.is_valid = &self_t::enumerator_is_valid;
809 3 const_iterator iter(&this->impl, (gate_flatmap_iterator_t)enumerator.current_position);
810 3 TypeFunctions<const_iterator>::copyConstruct(&enumerator.handles[0], &iter);
811 6 return enumerator_t(enumerator);
812 }
813 };
814
815
816
817
818
819
820 template<class KEY, class VALUE, class COMPARER = DefaultComparer<KEY>, class HASHGEN = TypeHash<KEY> >
821 class HashMap
822 {
823 public:
824 typedef KEY key_t;
825 typedef VALUE value_t;
826 typedef HashMap<KEY, VALUE, COMPARER, HASHGEN> self_t;
827 typedef COMPARER key_comparer_t;
828 typedef HASHGEN hash_gen_t;
829 typedef Mapping<KEY, VALUE> mapping_t;
830
831 private:
832 gate_hashmap_t impl;
833
834 public:
835 class const_iterator : public mapping_t
836 {
837 protected:
838 gate_hashmap_iterator_t iter;
839
840 22 void loadIterator(gate_hashmap_iterator_t mapiter)
841 {
842 22 this->iter = mapiter;
843
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
22 if (gate_hashmap_iterator_valid(this->iter))
844 {
845 17 this->loadMapping(*this->iter.hashmap->buckets[this->iter.bucket_index]->entries[this->iter.entry_index]);
846 }
847 else
848 {
849 static gate_mapping_t empty_mapping = { NULL, NULL };
850 5 this->loadMapping(empty_mapping);
851 }
852 22 }
853
854 public:
855
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 const_iterator(gate_hashmap_iterator_t mapiter) { this->loadIterator(mapiter); }
856
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 const_iterator(const_iterator const& src) { this->loadIterator(src.iter); }
857 const_iterator& operator=(const_iterator const& src)
858 {
859 this->loadIterator(src.iter);
860 return *this;
861 }
862
863 2 bool_t operator==(const_iterator const& that) const { return gate_hashmap_iterator_equals(this->iter, that.iter); }
864 2 bool_t operator!=(const_iterator const& that) const { return !gate_hashmap_iterator_equals(this->iter, that.iter); }
865
866 2 const_iterator& operator++() { this->loadIterator(gate_hashmap_iterator_next(this->iter)); return *this; }
867
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 const_iterator operator++(int) { const_iterator ret(*this); ++(*this); return ret; }
868
869 2 const_iterator& operator--() { this->loadIterator(gate_hashmap_iterator_prev(this->iter)); return *this; }
870
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 const_iterator operator--(int) { const_iterator ret(*this); --(*this); return ret; }
871 };
872
873 class iterator : public const_iterator
874 {
875 public:
876 3 iterator(gate_hashmap_iterator_t mapiter) : const_iterator(mapiter) {}
877 2 iterator(iterator const& src) : const_iterator(src) {}
878 iterator& operator=(iterator const& src)
879 {
880 const_iterator::operator=(static_cast<const_iterator const&>(src));
881 return *this;
882 }
883
884 value_t& value() { return *static_cast<value_t*>(gate_hashmap_iterator_value(this->iter)); }
885
886 2 iterator& operator++() { this->loadIterator(gate_hashmap_iterator_next(this->iter)); return *this; }
887
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 iterator operator++(int) { iterator ret(*this); ++(*this); return ret; }
888
889 2 iterator& operator--() { this->loadIterator(gate_hashmap_iterator_prev(this->iter)); return *this; }
890
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 iterator operator--(int) { iterator ret(*this); --(*this); return ret; }
891 };
892
893
894 public:
895 4 HashMap()
896 {
897 4 gate_type_hash_generator_t gen = hash_gen_t::c_generator();
898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (NULL == gen)
899 {
900 GATEXX_RAISE_ERROR(results::NotImplemented);
901 }
902 4 gate_hashmap_t* hashmap = gate_hashmap_create(
903 &this->impl, &key_comparer_t::c_compare, gen,
904 sizeof(key_t), &TypeFunctions<key_t>::copyConstruct, &TypeFunctions<key_t>::destruct,
905 sizeof(value_t), &TypeFunctions<value_t>::copyConstruct, &TypeFunctions<value_t>::destruct
906 );
907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (NULL == hashmap)
908 {
909 GATEXX_RAISE_ERROR(results::OutOfMemory);
910 }
911 4 }
912
913 2 HashMap(self_t const& src)
914 {
915
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_hashmap_copy(&this->impl, &src.impl))
916 {
917 GATEXX_RAISE_ERROR(results::OutOfMemory);
918 }
919 2 }
920
921 2 void swap(self_t& that) noexcept
922 {
923 2 gate::swapRefsNoExcept(this->impl, that.impl);
924 2 }
925
926 1 self_t& operator=(self_t const& src)
927 {
928
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 self_t that(src);
929 1 this->swap(that);
930 2 return *this;
931 }
932
933 6 ~HashMap() noexcept
934 {
935 6 gate_hashmap_destroy(&this->impl);
936 6 }
937
938 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
939 HashMap(self_t&& that)
940 : impl(that.impl)
941 {
942 Mem::clear(that.impl);
943 }
944
945 self_t& operator=(self_t&& that)
946 {
947 self_t tmp;
948 that.swap(tmp);
949 this->swap(tmp);
950 return *this;
951 }
952 #endif
953
954 9 void add(key_t const& key, value_t const& value)
955 {
956
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 gate_hashmap_iterator_t iter = gate_hashmap_add(&this->impl, &key, &value);
957
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 if (!gate_hashmap_iterator_valid(iter))
958 {
959 GATEXX_RAISE_ERROR(results::OutOfMemory);
960 }
961 9 }
962
963 VoidResult tryAdd(key_t const& key, value_t const& value) noexcept
964 {
965 gate_hashmap_iterator_t const iter = gate_hashmap_add(&this->impl, &key, &value);
966 result_t const resultCode = !gate_hashmap_iterator_valid(iter) ? results::OutOfMemory : results::Ok;
967 return makeResult(resultCode);
968 }
969
970 1 bool_t remove(key_t const& key) noexcept
971 {
972 1 return gate_hashmap_remove(&this->impl, &key);
973 }
974
975 1 iterator get(key_t const& key) noexcept
976 {
977 1 return iterator(gate_hashmap_get(&this->impl, &key));
978 }
979 3 const_iterator get(key_t const& key) const noexcept
980 {
981 3 return const_iterator(gate_hashmap_get(&this->impl, &key));
982 }
983 value_t getValue(key_t const& key, value_t const& altvalue) const
984 {
985 const_iterator it = this->get(key);
986 if (it == this->cend())
987 {
988 return altvalue;
989 }
990 else
991 {
992 return it.value();
993 }
994 }
995 1 const_iterator find(key_t const& key) const noexcept
996 {
997 1 return this->get(key);
998 }
999
1000 1 void clear() noexcept
1001 {
1002 1 gate_hashmap_clear(&this->impl);
1003 1 }
1004
1005 8 size_t count() const noexcept
1006 {
1007 8 return gate_hashmap_count(&this->impl);
1008 }
1009
1010 1 const_iterator cbegin() const noexcept
1011 {
1012 1 return const_iterator(gate_hashmap_first(&this->impl));
1013 }
1014 3 const_iterator cend() const noexcept
1015 {
1016 3 return const_iterator(gate_hashmap_end(&this->impl));
1017 }
1018 1 iterator begin() noexcept
1019 {
1020 1 return iterator(gate_hashmap_first(&this->impl));
1021 }
1022 1 iterator end() noexcept
1023 {
1024 1 return iterator(gate_hashmap_end(&this->impl));
1025 }
1026 const_iterator begin() const noexcept
1027 {
1028 return this->cbegin();
1029 }
1030 2 const_iterator end() const noexcept
1031 {
1032 2 return this->cend();
1033 }
1034
1035 2 bool_t contains(key_t const& key, value_t const** ptrValue = NULL) const noexcept
1036 {
1037 4 const_iterator iter = this->get(key);
1038
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 if (iter == this->end())
1039 {
1040 1 return false;
1041 }
1042 else
1043 {
1044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptrValue != NULL)
1045 {
1046 *ptrValue = &iter.value();
1047 }
1048 1 return true;
1049 }
1050 }
1051
1052 typedef Enumerator<const_iterator> enumerator_t;
1053
1054 1 enumerator_t enumerate() const
1055 {
1056 gate_enumerator_t enumerator;
1057
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (NULL == gate_hashmap_enumerate(&this->impl, &enumerator))
1058 {
1059 GATEXX_RAISE_ERROR(results::OutOfMemory);
1060 }
1061 2 return enumerator_t(enumerator);
1062 }
1063 };
1064
1065
1066
1067 } // end of namespace gate
1068
1069 #if __cplusplus >= 202002L
1070
1071 #include <utility>
1072
1073 namespace std
1074 {
1075 template<class KEY, class VALUE>
1076 struct tuple_size<gate::Mapping<KEY, VALUE> > : integral_constant<size_t, 2> {};
1077
1078 template<class KEY, class VALUE>
1079 struct tuple_element<0, gate::Mapping<KEY, VALUE> >
1080 {
1081 using type = KEY;
1082 };
1083
1084 template<class KEY, class VALUE>
1085 struct tuple_element<1, gate::Mapping < KEY, VALUE> >
1086 {
1087 using type = VALUE;
1088 };
1089
1090 template<size_t Index, class KEY, class VALUE>
1091 struct tuple_element<Index, gate::Mapping<KEY, VALUE> >
1092 : conditional<Index == 0, KEY, VALUE>
1093 {
1094 static_assert(Index < 2,
1095 "Index out of bounds for gate::Mapping");
1096 };
1097 }
1098
1099 namespace gate
1100 {
1101 template<std::size_t Index, class KEY, class VALUE>
1102 auto&& get(Mapping<KEY, VALUE> const& mapping)
1103 {
1104 if constexpr (Index == 0)
1105 {
1106 return mapping.key();
1107 }
1108 else
1109 {
1110 return mapping.value();
1111 }
1112 }
1113 }
1114
1115 #endif // __cplusplus >= 202002L
1116
1117
1118 #endif
1119