GCC Code Coverage Report


Directory: src/gate/
File: src/gate/maps.hpp
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 189 278 68.0%
Functions: 159 233 68.2%
Branches: 18 46 39.1%

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