GCC Code Coverage Report


Directory: src/gate/
File: src/gate/maps.hpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 156 262 59.5%
Functions: 72 144 50.0%
Branches: 14 38 36.8%

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