GCC Code Coverage Report


Directory: src/gate/
File: src/gate/wrappers.hpp
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 266 326 81.6%
Functions: 113 186 60.8%
Branches: 53 98 54.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 Wrappers and smart pointer objects
31 * @ingroup gatecore_cpp
32 */
33
34 #ifndef GATE_WRAPPERS_HPP_INCLUDED
35 #define GATE_WRAPPERS_HPP_INCLUDED
36
37 #include "gate/gate_core_api.hpp"
38 #include "gate/wrappers.h"
39 #include "gate/atomics.h"
40 #include "gate/gatetypes.hpp"
41 #include "gate/results.hpp"
42 #include "gate/exceptions.hpp"
43 #include "gate/memalloc.hpp"
44 #include "gate/delegates.hpp"
45 #include "gate/cxx_typeinfo.hpp"
46
47 namespace gate
48 {
49
50 /// @brief
51 /// @tparam T
52 template<class T>
53 class GATE_CORE_CPP_TEMPLATE_API Ptr : public SafeBoolBase< Ptr<T> >
54 {
55 public:
56 typedef Ptr<T> self_t;
57 typedef T value_t;
58 typedef T const* const_ptr_t;
59 typedef T* ptr_t;
60 typedef T const& const_ref_t;
61 typedef T& ref_t;
62
63
64 private:
65 ptr_t ptr;
66
67 public:
68
69 62 Ptr(ptr_t newInstance = NULL) noexcept
70 62 : ptr(newInstance)
71 {
72 62 }
73 64 void reset(ptr_t newInstance = NULL) noexcept
74 {
75
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 23 times.
64 delete this->ptr;
76 64 this->ptr = newInstance;
77 64 }
78 62 ~Ptr() noexcept
79 {
80 62 this->reset();
81 62 }
82 void swap(self_t& that) noexcept
83 {
84 gate::swapRefsNoExcept(this->ptr, that.ptr);
85 }
86 31 ptr_t release() noexcept
87 {
88 31 ptr_t tmp = this->ptr;
89 31 this->ptr = NULL;
90 31 return tmp;
91 }
92 56 ptr_t get() const noexcept
93 {
94 56 return this->ptr;
95 }
96 const_ptr_t operator->() const noexcept
97 {
98 GATE_DEBUG_ASSERT(this->hasValue());
99 return this->get();
100 }
101 ptr_t operator->() noexcept
102 {
103 GATE_DEBUG_ASSERT(this->hasValue());
104 return this->get();
105 }
106 const_ref_t operator*() const noexcept
107 {
108 GATE_DEBUG_ASSERT(this->hasValue());
109 return *this->get();
110 }
111 12 ref_t operator*() noexcept
112 {
113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 GATE_DEBUG_ASSERT(this->hasValue());
114 12 return *this->get();
115 }
116
117 4 bool_t empty() const noexcept
118 {
119 4 return this->ptr == NULL;
120 }
121 14 bool_t hasValue() const noexcept
122 {
123 14 return this->ptr != NULL;
124 }
125
126 2 self_t const& andThen(Delegate1<value_t&> const& callback) const
127 {
128
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (this->ptr != NULL)
129 {
130 1 callback.invoke(*this->ptr);
131 }
132 2 return *this;
133 }
134 2 self_t const& orElse(Delegate0 const& callback) const
135 {
136
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (this->ptr == NULL)
137 {
138 1 callback.invoke();
139 }
140 2 return *this;
141 }
142 2 self_t const& orThrow() const
143 {
144
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (this->ptr == NULL)
145 {
146 1 GATEXX_RAISE_ERROR(results::NullPointer);
147 }
148 1 return *this;
149 }
150
151 ref_t value() noexcept
152 {
153 GATE_DEBUG_ASSERT(this->ptr != NULL);
154 return *this->ptr;
155 }
156 const_ref_t value() const noexcept
157 {
158 GATE_DEBUG_ASSERT(this->ptr != NULL);
159 return *this->ptr;
160 }
161
162 const_ref_t value(const_ref_t defaultValue) const
163 {
164 if (this->ptr)
165 {
166 return defaultValue;
167 }
168 else
169 {
170 return *this->ptr;
171 }
172 }
173
174 bool_t operator!() const noexcept
175 {
176 return this->empty();
177 }
178
179
180 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
181 Ptr(self_t&& src) noexcept
182 : ptr(src.ptr)
183 {
184 src.ptr = NULL;
185 }
186 self_t& operator=(self_t&& src) noexcept
187 {
188 if (this != &src)
189 {
190 this->reset(src.ptr);
191 src.ptr = NULL;
192 }
193 return *this;
194 }
195 private: // new compilers will see copy-ctor and op= private
196 Ptr(self_t const& src) noexcept;
197 self_t& operator=(self_t const& src) noexcept;
198 public:
199 #else
200 Ptr(self_t const& src) noexcept
201 : ptr(src.ptr)
202 {
203 // dirty hack for old compilers: swap on copy-construction
204 const_cast<self_t&>(src).ptr = NULL;
205 }
206 self_t& operator=(self_t const& src) noexcept
207 {
208 if (this != &src)
209 {
210 // dirty hack for old compilers: transfer ownership on assignment
211 this->reset(src.ptr);
212 const_cast<self_t&>(src).ptr = NULL;
213 }
214 return *this;
215 }
216 #endif
217 };
218
219
220 /// @brief
221 /// @tparam T
222 template<class T>
223 class GATE_CORE_CPP_TEMPLATE_API Optional : public SafeBoolBase<Optional<T> >
224 {
225 public:
226 typedef T value_t;
227 typedef T* ptr_t;
228 typedef T const* const_ptr_t;
229 typedef T& ref_t;
230 typedef T const& const_ref_t;
231 typedef Optional<T> self_t;
232 private:
233 union
234 {
235 gate_c_maxalign_t dummy;
236 char buffer[sizeof(value_t)];
237 };
238
239 ptr_t ptr; // points to initialized value in buffer, or NULL if empty
240 public:
241 73 Optional()
242 73 : ptr(0)
243 {
244 73 Mem::clear(&this->buffer[0], sizeof(this->buffer));
245 73 }
246
247 87 void reset() noexcept
248 {
249
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 77 times.
87 if (this->ptr)
250 {
251 8 this->ptr->~T();
252 8 this->ptr = NULL;
253 }
254 87 }
255
256 self_t& create()
257 {
258 this->reset();
259 ptr_t p = reinterpret_cast<ptr_t>(&this->buffer[0]);
260 constructType(p);
261 this->ptr = p;
262 return *this;
263 }
264 6 self_t& create(const_ref_t src)
265 {
266 6 this->reset();
267 6 ptr_t p = reinterpret_cast<ptr_t>(&this->buffer[0]);
268 6 copyConstructType(p, src);
269 6 this->ptr = p;
270 6 return *this;
271 }
272
273 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
274 1 template<class A1> void emplace(A1&& a1)
275 {
276 1 this->reset();
277
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 new (&buffer[0]) T(forwardRef<A1>(a1));
278 1 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
279 1 }
280 template<class A1, class A2> void emplace(A1&& a1, A2&& a2)
281 {
282 this->reset();
283 new (&buffer[0]) T(forwardRef<A1>(a1), forwardRef<A2>(a2));
284 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
285 }
286 template<class A1, class A2, class A3> void emplace(A1&& a1, A2&& a2, A3&& a3)
287 {
288 this->reset();
289 new (&buffer[0]) T(forwardRef<A1>(a1), forwardRef<A2>(a2), forwardRef<A3>(a3));
290 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
291 }
292 template<class A1, class A2, class A3, class A4> void emplace(A1&& a1, A2&& a2, A3&& a3, A4&& a4)
293 {
294 this->reset();
295 new (&buffer[0]) T(forwardRef<A1>(a1), forwardRef<A2>(a2), forwardRef<A3>(a3), forwardRef<A4>(a4));
296 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
297 }
298 template<class A1, class A2, class A3, class A4, class A5> void emplace(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5)
299 {
300 this->reset();
301 new (&buffer[0]) T(forwardRef<A1>(a1), forwardRef<A2>(a2), forwardRef<A3>(a3), forwardRef<A4>(a4), forwardRef<A5>(a5));
302 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
303 }
304 template<class A1, class A2, class A3, class A4, class A5, class A6> void emplace(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6)
305 {
306 this->reset();
307 new (&buffer[0]) T(forwardRef<A1>(a1), forwardRef<A2>(a2), forwardRef<A3>(a3), forwardRef<A4>(a4), forwardRef<A5>(a5), forwardRef<A6>(a6));
308 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
309 }
310 #else
311 template<class A1> void emplace(A1& a1)
312 {
313 this->reset();
314 new (&buffer[0]) T(a1);
315 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
316 }
317 template<class A1, class A2> void emplace(A1& a1, A2& a2)
318 {
319 this->reset();
320 new (&buffer[0]) T(a1, a2);
321 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
322 }
323 template<class A1, class A2, class A3> void emplace(A1& a1, A2& a2, A3& a3)
324 {
325 this->reset();
326 new (&buffer[0]) T(a1, a2, a3);
327 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
328 }
329 template<class A1, class A2, class A3, class A4> void emplace(A1& a1, A2& a2, A3& a3, A4& a4)
330 {
331 this->reset();
332 new (&buffer[0]) T(a1, a2, a3, a4);
333 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
334 }
335 template<class A1, class A2, class A3, class A4, class A5> void emplace(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5)
336 {
337 this->reset();
338 new (&buffer[0]) T(a1, a2, a3, a4, a5);
339 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
340 }
341 template<class A1, class A2, class A3, class A4, class A5, class A6> void emplace(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6)
342 {
343 this->reset();
344 new (&buffer[0]) T(a1, a2, a3, a4, a5, a6);
345 this->ptr = reinterpret_cast<T*>(&this->buffer[0]);
346 }
347 #endif
348
349 31 ptr_t get() const noexcept
350 {
351 31 return this->ptr;
352 }
353
354 71 bool_t empty() const noexcept
355 {
356 71 return this->ptr == NULL;
357 }
358
359 29 bool_t hasValue() const noexcept
360 {
361 29 return this->ptr != NULL;
362 }
363
364 1 ref_t value() noexcept
365 {
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(this->ptr != NULL);
367 1 return *this->ptr;
368 }
369
370 const_ref_t value() const noexcept
371 {
372 GATE_DEBUG_ASSERT(this->ptr != NULL);
373 return *this->ptr;
374 }
375
376 1 const_ref_t value(const_ref_t defaultValue) const
377 {
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this->ptr == NULL)
379 {
380 return defaultValue;
381 }
382 else
383 {
384 1 return *this->ptr;
385 }
386 }
387
388 7 ptr_t operator->() noexcept
389 {
390
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 GATE_DEBUG_ASSERT(this->hasValue());
391 7 return this->get();
392 }
393 const_ptr_t operator->() const noexcept
394 {
395 GATE_DEBUG_ASSERT(this->hasValue());
396 return this->get();
397 }
398 13 ref_t operator*() noexcept
399 {
400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
13 GATE_DEBUG_ASSERT(this->hasValue());
401 13 return *this->get();
402 }
403 const_ref_t operator*() const noexcept
404 {
405 GATE_DEBUG_ASSERT(this->hasValue());
406 return *this->get();
407 }
408
409 4 self_t const& andThen(Delegate1<value_t&> const& callback) const
410 {
411
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (this->ptr != NULL)
412 {
413 2 callback.invoke(*this->ptr);
414 }
415 4 return *this;
416 }
417 4 self_t const& orElse(Delegate0 const& callback) const
418 {
419
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (this->ptr == NULL)
420 {
421 2 callback.invoke();
422 }
423 4 return *this;
424 }
425 2 self_t const& orThrow() const
426 {
427
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (this->ptr == NULL)
428 {
429 1 GATEXX_RAISE_ERROR(results::NullPointer);
430 }
431 1 return *this;
432 }
433
434 bool_t operator!() const noexcept
435 {
436 return this->empty();
437 }
438
439 74 ~Optional() noexcept
440 {
441 74 this->reset();
442 74 }
443
444 Optional(self_t const& src)
445 : ptr(0)
446 {
447 gate_mem_clear(&this->buffer[0], sizeof(this->buffer));
448
449 if (!src.empty())
450 {
451 this->create(*src.get());
452 }
453 }
454
455 Optional(const_ref_t native_src)
456 : ptr(0)
457 {
458 gate_mem_clear(&this->buffer[0], sizeof(this->buffer));
459 this->create(native_src);
460 }
461
462 2 self_t& operator=(self_t const& src)
463 {
464
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (this != &src)
465 {
466 2 this->reset();
467
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!src.empty())
468 {
469 2 this->create(*src.get());
470 }
471 }
472 2 return *this;
473 }
474 };
475
476 /// @brief
477 /// @tparam T
478 /// @tparam E
479 template<class T, class E>
480 class GATE_CORE_CPP_TEMPLATE_API Expected
481 {
482 public:
483 typedef T value_t;
484 typedef T* ptr_t;
485 typedef T const* const_ptr_t;
486 typedef T& ref_t;
487 typedef T const& const_ref_t;
488
489 typedef E error_t;
490 typedef Expected<value_t, error_t> self_t;
491
492 private:
493 union
494 {
495 gate_c_maxalign_t dummy;
496 char bufferValue[sizeof(value_t)];
497 char bufferError[sizeof(error_t)];
498 };
499 value_t* ptr; // pointer to expected value, or NULL if unexpected
500 #if defined(GATE_DEBUG_MODE)
501 error_t* ptrError; // pointer to unexpected value, or NULL if expected (just for debugging in IDEs)
502 #endif
503
504 2 void constructValue(value_t const& expectedValue)
505 {
506 2 ptr_t p = reinterpret_cast<ptr_t>(&this->bufferValue[0]);
507 2 copyConstructType(p, expectedValue);
508 2 this->ptr = p;
509 #if defined(GATE_DEBUG_MODE)
510 2 this->ptrError = NULL;
511 #endif
512 2 }
513 2 void constructError(error_t const& unexpectedValue)
514 {
515 2 error_t* p = reinterpret_cast<error_t*>(&this->bufferError[0]);
516 2 copyConstructType(p, unexpectedValue);
517 2 this->ptr = NULL;
518 #if defined(GATE_DEBUG_MODE)
519 2 this->ptrError = p;
520 #endif
521 2 }
522 4 void destruct() noexcept
523 {
524
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (this->ptr)
525 {
526 2 destructType(this->ptr);
527 2 this->ptr = NULL;
528 }
529 else
530 {
531 2 error_t* p = reinterpret_cast<error_t*>(&this->bufferError[0]);
532 2 destructType(p);
533 }
534 4 }
535
536 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
537 void moveConstruct(GATE_MOVEREF(self_t) src)
538 {
539 if (src.hasValue())
540 {
541 ptr_t p = reinterpret_cast<ptr_t>(&this->bufferValue[0]);
542 moveConstructType(p, src.value());
543 this->ptr = p;
544 #if defined(GATE_DEBUG_MODE)
545 this->ptrError = NULL;
546 #endif
547 }
548 else
549 {
550 error_t* p = reinterpret_cast<error_t*>(&this->bufferError[0]);
551 moveConstructType(p, src.error());
552 this->ptr = NULL;
553 #if defined(GATE_DEBUG_MODE)
554 this->ptrError = p;
555 #endif
556 }
557 }
558 #endif
559
560 public:
561 2 Expected(value_t const& expectedValue)
562 : dummy()
563 , ptr(NULL)
564 #if defined(GATE_DEBUG_MODE)
565 2 , ptrError(NULL)
566 #endif
567 {
568 2 constructValue(expectedValue);
569 2 }
570
571 2 Expected(error_t const& unexpectedValue)
572 : dummy()
573 , ptr(NULL)
574 #if defined(GATE_DEBUG_MODE)
575 2 , ptrError(NULL)
576 #endif
577 {
578 2 constructError(unexpectedValue);
579 2 }
580
581 Expected(self_t const& src)
582 {
583 if (src.hasValue())
584 {
585 constructValue(src.value());
586 }
587 else
588 {
589 constructError(src.error());
590 }
591 }
592
593 self_t& operator=(self_t const& src)
594 {
595 if (this != &src)
596 {
597 self_t backup(*this);
598 destruct();
599
600 try
601 {
602 if (src.hasValue())
603 {
604 constructValue(src.value());
605 }
606 else
607 {
608 constructError(src.error());
609 }
610 }
611 catch (...)
612 {
613 // try to restore backup:
614 if (backup.hasValue())
615 {
616 constructValue(backup.value());
617 }
618 else
619 {
620 constructError(backup.error());
621 }
622 throw;
623 }
624 }
625 return *this;
626 }
627
628 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
629 Expected(GATE_MOVEREF(self_t) src)
630 {
631 moveConstruct(moveRef(src));
632 }
633
634 self_t& operator=(GATE_MOVEREF(self_t) src)
635 {
636 if (this != &src)
637 {
638 destruct();
639 moveConstruct(moveRef(src));
640 }
641 return *this;
642 }
643 #endif
644
645 4 ~Expected() noexcept
646 {
647 4 this->destruct();
648 4 }
649
650 20 value_t* get() const noexcept
651 {
652 20 return this->ptr;
653 }
654
655 14 bool hasValue() const noexcept
656 {
657 14 return this->get() != NULL;
658 }
659 bool empty() const noexcept
660 {
661 return this->get() == NULL;
662 }
663
664 1 ref_t value() noexcept
665 {
666 1 return *this->get();
667 }
668 1 const_ref_t value() const noexcept
669 {
670 1 return *this->get();
671 }
672 2 const_ref_t value(const_ref_t defaultValue) const
673 {
674
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (this->hasValue())
675 {
676 1 return this->value();
677 }
678 else
679 {
680 1 return defaultValue;
681 }
682 }
683
684 3 error_t* getErrorPtr() const noexcept
685 {
686
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (this->hasValue())
687 {
688 1 return NULL;
689 }
690 else
691 {
692 2 return const_cast<error_t*>(reinterpret_cast<error_t const*>(&this->bufferError[0]));
693 }
694 }
695 1 error_t& error() noexcept
696 {
697 1 return *reinterpret_cast<error_t*>(&this->bufferError[0]);
698 }
699 error_t const& error() const noexcept
700 {
701 return *reinterpret_cast<error_t const*>(&this->bufferError[0]);
702 }
703
704 1 value_t* operator->() noexcept
705 {
706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 GATE_DEBUG_ASSERT(this->hasValue());
707 1 return this->get();
708 }
709 value_t const* operator->() const noexcept
710 {
711 GATE_DEBUG_ASSERT(this->hasValue());
712 return this->get();
713 }
714
715 value_t& operator*() noexcept
716 {
717 GATE_DEBUG_ASSERT(this->hasValue());
718 return *this->get();
719 }
720 value_t const& operator*() const noexcept
721 {
722 GATE_DEBUG_ASSERT(this->hasValue());
723 return *this->get();
724 }
725
726 bool operator!() const noexcept
727 {
728 return this->empty();
729 }
730
731 2 self_t const& andThen(Delegate1<value_t&> const& callback) const
732 {
733
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (this->hasValue())
734 {
735 1 callback.invoke(*this->get());
736 }
737 2 return *this;
738 }
739 2 self_t const& orElse(Delegate1<error_t&> const& callback) const
740 {
741
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (!this->hasValue())
742 {
743 1 callback.invoke(*this->getErrorPtr());
744 }
745 2 return *this;
746 }
747 2 self_t const& orThrow() const
748 {
749
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (!this->hasValue())
750 {
751 1 GATEXX_RAISE_ERROR(results::NullPointer);
752 }
753 1 return *this;
754 }
755 };
756
757
758 /// @brief
759 class GATE_CORE_CPP_API WrapperBase
760 {
761 public:
762 static gate_wrapper_t* createCppWrapper(size_t typeSize, std::type_info const& typeInfo, gate_mem_dtor_t dtor);
763 };
764
765 template<class T>
766 class GATE_CORE_CPP_TEMPLATE_API Wrapper : public SafeBoolBase< Wrapper<T> >
767 {
768 public:
769 typedef T value_t;
770 typedef T* ptr_t;
771 typedef T const* const_ptr_t;
772 typedef T& ref_t;
773 typedef T const& const_ref_t;
774 typedef Wrapper<T> self_t;
775
776 private:
777 gate_wrapper_t* impl;
778 ptr_t ptr;
779
780 private:
781 2 static void GATE_CALL destruct_external_cpp(void* ptr)
782 {
783 2 T* ptr_external = static_cast<T*>(ptr);
784
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 delete ptr_external;
785 2 }
786
787 public:
788 2 Wrapper()
789 2 : impl(NULL), ptr(NULL)
790 {
791 2 }
792 Wrapper(gate_wrapper_t* wrapper) noexcept
793 : impl(wrapper), ptr(NULL)
794 {
795 if (wrapper != NULL)
796 {
797 void* content_ptr = gate_memoryblock_get_content(wrapper);
798 this->ptr = static_cast<ptr_t>(content_ptr);
799 }
800 }
801 Wrapper(gate_wrapper_t* wrapper, T* ptr_content)
802 : impl(wrapper), ptr(ptr_content)
803 {
804 }
805 5 Wrapper(self_t const& src)
806 5 : impl(src.impl), ptr(src.ptr)
807 {
808
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (this->impl)
809 {
810 5 gate_object_retain(this->impl);
811 }
812 5 }
813 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
814 2 Wrapper(Ptr<T>&& src)
815 #else
816 Wrapper(Ptr<T>& src)
817 #endif
818 : impl(NULL),
819 2 ptr(NULL)
820 {
821 2 ptr_t local_ptr = src.get();
822 2 cxx_type_info_t const& ti = get_cxx_type_info<value_t>();
823 2 this->impl = gate_wrapper_create(local_ptr, sizeof(value_t), ti.name(), &self_t::destruct_external_cpp, NULL);
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (this->impl == NULL)
825 {
826 GATEXX_RAISE_ERROR(results::OutOfMemory);
827 }
828 else
829 {
830 2 void* content_ptr = gate_memoryblock_get_content(this->impl);
831 2 this->ptr = static_cast<ptr_t>(content_ptr);
832 2 src.release();
833 }
834 2 }
835
836 9 ~Wrapper() noexcept
837 {
838
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (this->impl)
839 {
840 7 gate_object_release(this->impl);
841 }
842 #if defined(GATE_DEBUG_MODE)
843 9 this->ptr = NULL;
844 9 this->impl = NULL;
845 #endif
846 9 }
847 1 void swap(self_t& that)
848 {
849 1 gate::swapRefs(this->impl, that.impl);
850 1 gate::swapRefs(this->ptr, that.ptr);
851 1 }
852 1 self_t& operator=(self_t const& src)
853 {
854
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (this != &src)
855 {
856
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 self_t that(src);
857
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->swap(that);
858 }
859 1 return *this;
860 }
861 4 bool hasValue() const noexcept
862 {
863 4 return this->ptr != NULL;
864 }
865 3 bool empty() const noexcept
866 {
867 3 return this->ptr == NULL;
868 }
869 1 bool operator!() const noexcept
870 {
871 1 return this->ptr == NULL;
872 }
873
874 5 ptr_t get() const noexcept
875 {
876 5 return this->ptr;
877 }
878
879 2 ref_t value() noexcept
880 {
881 2 return *this->get();
882 }
883 const_ref_t value() const noexcept
884 {
885 return *this->get();
886 }
887
888 const_ref_t value(const_ref_t defaultValue) const
889 {
890 if (this->hasValue())
891 {
892 return *this->get();
893 }
894 else
895 {
896 return defaultValue;
897 }
898 }
899
900 void const* type() const noexcept
901 {
902 return gate_wrapper_get_type(this->impl);
903 }
904 bool equalsTypeOf(self_t const& that) const noexcept
905 {
906 return gate_wrapper_is_type(this->impl, that.getType());
907 }
908 2 size_t size() const noexcept
909 {
910 2 return sizeof(value_t);
911 }
912
913 self_t const& andThen(Delegate1<value_t&> const& callback) const
914 {
915 if (this->hasValue())
916 {
917 callback.invoke(*this->get());
918 }
919 return *this;
920 }
921 self_t const& orElse(Delegate0 const& callback) const
922 {
923 if (!this->hasValue())
924 {
925 callback.invoke();
926 }
927 return *this;
928 }
929 self_t const& orThrow() const
930 {
931 if (!this->hasValue())
932 {
933 GATEXX_RAISE_ERROR(results::NullPointer);
934 }
935 return *this;
936 }
937
938
939 1 ptr_t operator->() noexcept
940 {
941
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 GATE_DEBUG_ASSERT(this->hasValue());
942 1 return this->get();
943 }
944 const_ptr_t operator->() const noexcept
945 {
946 GATE_DEBUG_ASSERT(this->hasValue());
947 return this->get();
948 }
949 ref_t operator*() noexcept
950 {
951 GATE_DEBUG_ASSERT(this->hasValue());
952 return *this->get();
953 }
954 const_ref_t operator*() const noexcept
955 {
956 GATE_DEBUG_ASSERT(this->hasValue());
957 return *this->get();
958 }
959 bool operator==(self_t const& that) const noexcept
960 {
961 return (this->impl == that.impl);
962 }
963 bool operator!=(self_t const& that) const noexcept
964 {
965 return (this->impl != that.impl);
966 }
967 bool operator<(self_t const& that) const noexcept
968 {
969 return this->impl < that.impl;
970 }
971 bool operator<=(self_t const& that) const noexcept
972 {
973 return this->impl <= that.impl;
974 }
975 bool operator>(self_t const& that) const noexcept
976 {
977 return this->impl > that.impl;
978 }
979 bool operator>=(self_t const& that) const noexcept
980 {
981 return this->impl >= that.impl;
982 }
983
984
985 Wrapper(ptr_t ptr_external, gate_mem_dtor_t specialDestructor = NULL)
986 : impl(NULL), ptr(NULL)
987 {
988 void* content_ptr = NULL;
989 cxx_type_info_t const& ti = get_cxx_type_info<value_t>();
990 this->impl = gate_wrapper_create(ptr_external, sizeof(value_t), ti.name(),
991 specialDestructor == NULL ? &self_t::destruct_external_cpp : specialDestructor,
992 NULL);
993 if (this->impl == NULL)
994 {
995 GATEXX_RAISE_ERROR(results::NullPointer);
996 }
997 else
998 {
999 content_ptr = gate_memoryblock_get_content(this->impl);
1000 }
1001 this->ptr = static_cast<ptr_t>(content_ptr);
1002 }
1003
1004 static self_t create(value_t const& src)
1005 {
1006 cxx_type_info_t const& ti = get_cxx_type_info<value_t>();
1007 gate_wrapper_t* wrapper = gate_wrapper_create_new(
1008 sizeof(value_t), ti.name(),
1009 &TypeFunctions<value_t>::destruct);
1010 void* content_ptr = gate_memoryblock_get_content(wrapper);
1011 try
1012 {
1013 TypeFunctions<value_t>::copyConstruct(content_ptr, &src);
1014 }
1015 catch (...)
1016 {
1017 gate_mem_dealloc(wrapper);
1018 throw;
1019 }
1020 self_t ret;
1021 ret.impl = wrapper;
1022 ret.ptr = static_cast<ptr_t>(content_ptr);
1023 return ret;
1024 }
1025
1026 static self_t fromPtr(ptr_t ptr)
1027 {
1028 Ptr<T> ptrwrapper(ptr);
1029 self_t ret(gate::moveRef(ptrwrapper));
1030 return ret;
1031 }
1032
1033 template<class U> Wrapper<U> staticCastTo() const
1034 {
1035 Wrapper<U> ret(this->impl, static_cast<U*>(this->get()));
1036 if (this->impl)
1037 {
1038 gate_object_retain(this->impl);
1039 }
1040 return ret;
1041 }
1042
1043 template<class U> Wrapper<U> castTo() const
1044 {
1045 Wrapper<U> ret(this->impl, dynamic_cast<U*>(this->get()));
1046 if (this->impl)
1047 {
1048 gate_object_retain(this->impl);
1049 }
1050 return ret;
1051 }
1052 };
1053
1054 #if __cplusplus >= 201103
1055 template<class T>
1056 using Ref = Wrapper<T>;
1057
1058 #else
1059 // backwards compatibility with C++03/98
1060 template<class T>
1061 class Ref : public Wrapper<T>
1062 {
1063 public:
1064 typedef Wrapper<T> base_t;
1065 typedef Ref<T> self_t;
1066
1067 Ref()
1068 : base_t()
1069 {
1070 }
1071 Ref(self_t const& src)
1072 : base_t(src)
1073 {
1074 }
1075 Ref(base_t const& src)
1076 : base_t(src)
1077 {
1078 }
1079 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
1080 Ref(Ptr<T>&& src)
1081 #else
1082 Ref(Ptr<T>& src)
1083 #endif
1084 : base_t(gate::moveRef(src))
1085 {
1086 }
1087
1088 ~Ref() noexcept
1089 {
1090 }
1091 void swap(self_t& that)
1092 {
1093 base_t::swap(that);
1094 }
1095 self_t& operator=(self_t const& src)
1096 {
1097 if (this != &src)
1098 {
1099 self_t that(src);
1100 this->swap(that);
1101 }
1102 return *this;
1103 }
1104
1105 #if defined(GATE_COMPILER_SUPPORTS_CPP_MOVEREFS)
1106 self_t& operator=(Ptr<T>&& src)
1107 #else
1108 self_t& operator=(Ptr<T>& src)
1109 #endif
1110 {
1111 self_t that(gate::moveRef(src));
1112 this->swap(that);
1113 return *this;
1114 }
1115
1116 template<class U> Ref<U> staticCastTo() const
1117 {
1118 Wrapper<T> const& w = *this;
1119 #if defined(GATE_COMPILER_WATCOM)
1120 Wrapper<U> u = w.staticCastTo<U>();
1121 #else
1122 Wrapper<U> u = w.template staticCastTo<U>();
1123 #endif
1124 return Ref<U>(u);
1125 }
1126
1127 template<class U> Ref<U> castTo()
1128 {
1129 Wrapper<T> const& w = *this;
1130 #if defined(GATE_COMPILER_WATCOM)
1131 Wrapper<U> u = w.castTo<U>();
1132 #else
1133 Wrapper<U> u = w.template castTo<U>();
1134 #endif
1135 return Ref<U>(u);
1136 }
1137
1138 };
1139
1140 #endif
1141
1142
1143 /// @brief
1144 class GATE_CORE_CPP_API Variant
1145 {
1146 protected:
1147 gate_variant_t* impl;
1148
1149 public:
1150 Variant(gate_variant_t* ptrVariant);
1151 Variant(Variant const& src);
1152 Variant& operator=(Variant const& src);
1153 ~Variant() noexcept;
1154
1155 gate_variant_t* c_impl() const;
1156
1157 size_t getSize() const;
1158 void const* getType() const;
1159
1160 1 template<class T> bool is() const noexcept
1161 {
1162 1 cxx_type_info_t const& ti = get_cxx_type_info<T>();
1163 1 return (sizeof(T) == gate_variant_get_size(this->impl))
1164
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 && (&ti == gate_variant_get_type(this->impl));
1165 }
1166
1167 template<class T> T* get() noexcept
1168 {
1169 if (!this->is<T>())
1170 {
1171 return NULL;
1172 }
1173 return static_cast<T*>(gate_variant_get_content(this->impl));
1174 }
1175 template<class T> T const* get() const noexcept
1176 {
1177 if (!this->is<T>())
1178 {
1179 return NULL;
1180 }
1181 return static_cast<T const*>(gate_variant_get_content(this->impl));
1182 }
1183
1184 template<class T> T& value()
1185 {
1186 T* ptr = this->get<T>();
1187 if (!ptr)
1188 {
1189 GATEXX_RAISE_ERROR(results::IncorrectType);
1190 }
1191 return *ptr;
1192 }
1193 template<class T> T const& value() const
1194 {
1195 T const* ptr = this->get<T>();
1196 if (!ptr)
1197 {
1198 GATEXX_RAISE_ERROR(results::IncorrectType);
1199 }
1200 return *ptr;
1201 }
1202
1203 template<class T> void set(T const& value)
1204 {
1205 cxx_type_info_t const& ti = get_cxx_type_info<T>();
1206 result_t result = gate_variant_set_content(this->impl, &value, sizeof(T), &ti);
1207 GATEXX_CHECK_ERROR(result);
1208 }
1209 };
1210
1211
1212
1213 template<unsigned N>
1214 struct VariantNoneArg
1215 {
1216 };
1217
1218 /// @brief
1219 /// @tparam T0
1220 /// @tparam T1
1221 /// @tparam T2
1222 /// @tparam T3
1223 /// @tparam T4
1224 /// @tparam T5
1225 /// @tparam T6
1226 /// @tparam T7
1227 /// @tparam T8
1228 /// @tparam T9
1229 template<class T0,
1230 class T1 = VariantNoneArg<1>,
1231 class T2 = VariantNoneArg<2>,
1232 class T3 = VariantNoneArg<3>,
1233 class T4 = VariantNoneArg<4>,
1234 class T5 = VariantNoneArg<5>,
1235 class T6 = VariantNoneArg<6>,
1236 class T7 = VariantNoneArg<7>,
1237 class T8 = VariantNoneArg<8>,
1238 class T9 = VariantNoneArg<9>
1239 >
1240 class VariantType
1241 {
1242 public:
1243 typedef VariantType<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> self_t;
1244 private:
1245 size_t type_index;
1246 size_t type_size;
1247 std::type_info const* ptr_type;
1248 gate_mem_copyctor_t cctor;
1249 gate_mem_dtor_t dtor;
1250
1251 union
1252 {
1253 gate_c_maxalign_t alignment_dummy;
1254 char t0[sizeof(T0)];
1255 char t1[sizeof(T1)];
1256 char t2[sizeof(T2)];
1257 char t3[sizeof(T3)];
1258 char t4[sizeof(T4)];
1259 char t5[sizeof(T5)];
1260 char t6[sizeof(T6)];
1261 char t7[sizeof(T7)];
1262 char t8[sizeof(T8)];
1263 char t9[sizeof(T9)];
1264 } content;
1265
1266 2 template<class U> void copyConstruct(size_t index, U const& src)
1267 {
1268 2 this->type_index = index;
1269 2 this->type_size = sizeof(U);
1270 2 cxx_type_info_t const& ti = get_cxx_type_info<U>();
1271 2 this->ptr_type = &ti;
1272 2 this->cctor = &TypeFunctions<U>::copyConstruct;
1273 2 this->dtor = &TypeFunctions<U>::destruct;
1274 2 result_t result = this->cctor(&this->content, &src);
1275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
2 GATEXX_CHECK_ERROR(result);
1276 2 }
1277 1 void destruct()
1278 {
1279 1 this->dtor(&this->content);
1280 1 Mem::clear(this->content);
1281 1 }
1282 template<class U> self_t& assign(size_t index, U const& src)
1283 {
1284 this->destruct();
1285 this->copyConstruct(index, src);
1286 return *this;
1287 }
1288
1289 public:
1290
1291 VariantType() { this->copyConstruct(0, T0()); }
1292 VariantType(T0 const& t) { this->copyConstruct(0, t); }
1293 1 VariantType(T1 const& t) { this->copyConstruct(1, t); }
1294 VariantType(T2 const& t) { this->copyConstruct(2, t); }
1295 VariantType(T3 const& t) { this->copyConstruct(3, t); }
1296 VariantType(T4 const& t) { this->copyConstruct(4, t); }
1297 VariantType(T5 const& t) { this->copyConstruct(5, t); }
1298 VariantType(T6 const& t) { this->copyConstruct(6, t); }
1299 VariantType(T7 const& t) { this->copyConstruct(7, t); }
1300 VariantType(T8 const& t) { this->copyConstruct(8, t); }
1301 VariantType(T9 const& t) { this->copyConstruct(9, t); }
1302
1303 VariantType(self_t const& that)
1304 : type_index(that.type_index),
1305 type_size(that.type_size),
1306 ptr_type(that.ptr_type),
1307 cctor(that.cctor),
1308 dtor(that.dtor)
1309 {
1310 result_t result = this->cctor(&this->content, &that.content);
1311 GATEXX_CHECK_ERROR(result);
1312 }
1313
1314 self_t& operator=(self_t const& that)
1315 {
1316 if (this != &that)
1317 {
1318 this->destruct();
1319 this->type_index = that.type_index;
1320 this->type_size = that.type_size;
1321 this->ptr_type = that.ptr_type;
1322 this->cctor = that.cctor;
1323 this->dtor = that.dtor;
1324 result_t result = this->cctor(&this->content, &that.content);
1325 GATEXX_CHECK_ERROR(result);
1326 }
1327 return *this;
1328 }
1329
1330 self_t& operator=(T0 const& t) { return this->assign(0, t); }
1331 self_t& operator=(T1 const& t) { return this->assign(1, t); }
1332 self_t& operator=(T2 const& t) { return this->assign(2, t); }
1333 self_t& operator=(T3 const& t) { return this->assign(3, t); }
1334 self_t& operator=(T4 const& t) { return this->assign(4, t); }
1335 self_t& operator=(T5 const& t) { return this->assign(5, t); }
1336 self_t& operator=(T6 const& t) { return this->assign(6, t); }
1337 self_t& operator=(T7 const& t) { return this->assign(7, t); }
1338 self_t& operator=(T8 const& t) { return this->assign(8, t); }
1339 self_t& operator=(T9 const& t) { return this->assign(9, t); }
1340
1341 1 ~VariantType()
1342 {
1343 1 destruct();
1344 1 }
1345
1346 2 std::type_info const& getTypeInfo() const
1347 {
1348 2 return *this->ptr_type;
1349 }
1350 2 size_t size() const
1351 {
1352 2 return this->type_size;
1353 }
1354
1355 template<class U> bool is() const
1356 {
1357 cxx_type_info_t const& ti = get_cxx_type_info<U>();
1358 return this->getTypeInfo() == &ti;
1359 }
1360
1361 template<class U> U* get()
1362 {
1363 if (this->is<U>())
1364 {
1365 return NULL;
1366
1367 }
1368 return reinterpret_cast<U*>(&this->content);
1369 }
1370 template<class U> U const* get() const
1371 {
1372 if (!this->is<U>())
1373 {
1374 return NULL;
1375
1376 }
1377 return reinterpret_cast<U const*>(&this->content);
1378 }
1379
1380 void* getContent()
1381 {
1382 return static_cast<void*>(&this->content);
1383 }
1384
1385 size_t getIndex() const
1386 {
1387 return this->type_index;
1388 }
1389
1390 template<class U> U& value()
1391 {
1392 if (!this->is<U>())
1393 {
1394 GATEXX_RAISE_ERROR(results::IncorrectType);
1395 }
1396 return *reinterpret_cast<U*>(&this->content);
1397 }
1398
1399 template<class U> U const& value() const
1400 {
1401 if (!this->is<U>())
1402 {
1403 GATEXX_RAISE_ERROR(results::IncorrectType);
1404 }
1405 return *reinterpret_cast<U const*>(&this->content);
1406 }
1407
1408 void set(cxx_type_info_t const* ti, void const* ptrContent)
1409 {
1410 if (ti == &get_cxx_type_info<T0>()) { *this = *static_cast<T0 const*>(ptrContent); }
1411 else if (ti == &get_cxx_type_info<T1>()) { *this = *static_cast<T1 const*>(ptrContent); }
1412 else if (ti == &get_cxx_type_info<T2>()) { *this = *static_cast<T2 const*>(ptrContent); }
1413 else if (ti == &get_cxx_type_info<T3>()) { *this = *static_cast<T3 const*>(ptrContent); }
1414 else if (ti == &get_cxx_type_info<T4>()) { *this = *static_cast<T4 const*>(ptrContent); }
1415 else if (ti == &get_cxx_type_info<T5>()) { *this = *static_cast<T5 const*>(ptrContent); }
1416 else if (ti == &get_cxx_type_info<T6>()) { *this = *static_cast<T6 const*>(ptrContent); }
1417 else if (ti == &get_cxx_type_info<T7>()) { *this = *static_cast<T7 const*>(ptrContent); }
1418 else if (ti == &get_cxx_type_info<T8>()) { *this = *static_cast<T8 const*>(ptrContent); }
1419 else if (ti == &get_cxx_type_info<T9>()) { *this = *static_cast<T9 const*>(ptrContent); }
1420 else { GATEXX_RAISE_ERROR(results::IncorrectType); }
1421 }
1422 template<class U> void set(U const& content)
1423 {
1424 cxx_type_info_t const& ti = get_cxx_type_info<U>();
1425 this->set(&ti, &content);
1426 }
1427 };
1428
1429
1430
1431
1432 /// @brief
1433 /// @tparam T0
1434 /// @tparam T1
1435 /// @tparam T2
1436 /// @tparam T3
1437 /// @tparam T4
1438 /// @tparam T5
1439 /// @tparam T6
1440 /// @tparam T7
1441 /// @tparam T8
1442 /// @tparam T9
1443 template<class T0,
1444 class T1 = VariantNoneArg<1>,
1445 class T2 = VariantNoneArg<2>,
1446 class T3 = VariantNoneArg<3>,
1447 class T4 = VariantNoneArg<4>,
1448 class T5 = VariantNoneArg<5>,
1449 class T6 = VariantNoneArg<6>,
1450 class T7 = VariantNoneArg<7>,
1451 class T8 = VariantNoneArg<8>,
1452 class T9 = VariantNoneArg<9>
1453 >
1454 class VariantFactory
1455 {
1456 public:
1457 typedef VariantFactory<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> self_t;
1458 typedef VariantType<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> variant_type_t;
1459
1460 private:
1461 struct VariantImpl : gate_variant_t
1462 {
1463 gate_variant_vtbl_t vtbl_impl;
1464 gate_atomic_int_t ref_counter;
1465
1466 variant_type_t var;
1467 };
1468
1469 static char const* get_interface_name_impl(void* obj)
1470 {
1471 return GATE_INTERFACE_NAME_VARIANT;
1472 }
1473 4 static void release_impl(void* obj)
1474 {
1475 4 VariantImpl* self = (VariantImpl*)obj;
1476
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (gate_atomic_int_dec(&self->ref_counter) == 0)
1477 {
1478 1 destructType(&self->var);
1479 1 gate_mem_dealloc(self);
1480 }
1481 4 }
1482 3 static int retain_impl(void* obj)
1483 {
1484 3 VariantImpl* self = (VariantImpl*)obj;
1485 3 return gate_atomic_int_inc(&self->ref_counter);
1486 }
1487 2 static gate_size_t get_size_impl(void* obj)
1488 {
1489 2 VariantImpl* self = (VariantImpl*)obj;
1490 2 return self->var.size();
1491 }
1492 static void* get_content_impl(void* obj)
1493 {
1494 VariantImpl* self = (VariantImpl*)obj;
1495 return self->var.getContent();
1496 }
1497 2 static void const* get_type_impl(void* obj)
1498 {
1499 2 VariantImpl* self = (VariantImpl*)obj;
1500 2 return &self->var.getTypeInfo();
1501 }
1502 static gate_bool_t is_type_impl(void* obj, void const* compare_with)
1503 {
1504 VariantImpl* self = (VariantImpl*)obj;
1505 std::type_info const* ptrType = static_cast<std::type_info const*>(compare_with);
1506 return &self->var.getTypeInfo() == ptrType;
1507 }
1508 static gate_result_t set_content_impl(void* obj, void const* ptr_content, gate_size_t size, void const* ptr_type)
1509 {
1510 VariantImpl* self = (VariantImpl*)obj;
1511 (void)size;
1512 self->var.set(static_cast<std::type_info const*>(ptr_type), ptr_content);
1513 return GATE_RESULT_NOTSUPPORTED;
1514 }
1515
1516 template<class V>
1517 1 static VariantImpl* createImpl(V const& value)
1518 {
1519 1 VariantImpl* ptr = static_cast<VariantImpl*>(gate_mem_alloc(sizeof(VariantImpl)));
1520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr)
1521 {
1522 return NULL;
1523 }
1524 1 ptr->vtbl = &ptr->vtbl_impl;
1525 1 gate_atomic_int_init(&ptr->ref_counter, 1);
1526
1527 1 ptr->vtbl_impl.get_interface_name = &get_interface_name_impl;
1528 1 ptr->vtbl_impl.release = &release_impl;
1529 1 ptr->vtbl_impl.retain = &retain_impl;
1530 1 ptr->vtbl_impl.get_size = &get_size_impl;
1531 1 ptr->vtbl_impl.get_content = &get_content_impl;
1532 1 ptr->vtbl_impl.get_type = &get_type_impl;
1533 1 ptr->vtbl_impl.is_type = &is_type_impl;
1534 1 ptr->vtbl_impl.set_content = &set_content_impl;
1535
1536 try
1537 {
1538
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 new(&ptr->var) variant_type_t(value);
1539 }
1540 catch (...)
1541 {
1542 gate_mem_dealloc(ptr);
1543 throw;
1544 }
1545 1 return ptr;
1546 }
1547
1548 public:
1549
1550 static Variant create(T0 const& value) { return Variant(self_t::createImpl(value)); }
1551 1 static Variant create(T1 const& value) { return Variant(self_t::createImpl(value)); }
1552 static Variant create(T2 const& value) { return Variant(self_t::createImpl(value)); }
1553 static Variant create(T3 const& value) { return Variant(self_t::createImpl(value)); }
1554 static Variant create(T4 const& value) { return Variant(self_t::createImpl(value)); }
1555 static Variant create(T5 const& value) { return Variant(self_t::createImpl(value)); }
1556 static Variant create(T6 const& value) { return Variant(self_t::createImpl(value)); }
1557 static Variant create(T7 const& value) { return Variant(self_t::createImpl(value)); }
1558 static Variant create(T8 const& value) { return Variant(self_t::createImpl(value)); }
1559 static Variant create(T9 const& value) { return Variant(self_t::createImpl(value)); }
1560 };
1561
1562
1563 } // end of namespace gate
1564
1565 #endif
1566