FastEngine 0.9.3
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_property.inl
1/*
2 * Copyright 2024 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17namespace fge
18{
19
20template<class T, typename>
21Property::Property(T&& val) :
22 g_isModified(true)
23{
24 using TT = remove_cvref_t<T>;
25
26 if constexpr (std::is_integral_v<TT> || std::is_enum_v<TT>)
27 {
28 this->g_type = Types::PTYPE_INTEGERS;
29
30 if constexpr (std::is_signed_v<TT>)
31 {
32 this->g_data._i = static_cast<fge::PintType>(val);
33 this->g_isSigned = true;
34 }
35 else
36 {
37 this->g_data._u = static_cast<fge::PuintType>(val);
38 this->g_isSigned = false;
39 }
40 }
41 else if constexpr (std::is_floating_point_v<TT>)
42 {
43 if constexpr (std::is_same_v<TT, float>)
44 {
45 this->g_type = Types::PTYPE_FLOAT;
46 this->g_data._f = val;
47 }
48 else
49 {
50 this->g_type = Types::PTYPE_DOUBLE;
51 this->g_data._d = static_cast<double>(val);
52 }
53 }
54 else if constexpr (std::is_same_v<TT, std::string>)
55 {
56 this->g_type = Types::PTYPE_STRING;
57 this->g_data._ptr = new std::string(std::forward<T>(val));
58 }
59 else if constexpr (std::is_pointer_v<TT>)
60 {
61 this->g_type = Types::PTYPE_POINTER;
62 this->g_data._ptr = val;
63 }
64 else
65 {
66 this->g_type = Types::PTYPE_CLASS;
67 this->g_data.setClassWrapper(new fge::PropertyClassWrapperType<TT>(std::forward<T>(val)));
68 }
69}
70
71template<class T, typename>
72fge::Property& Property::operator=(T&& val)
73{
74 this->set(std::forward<T>(val));
75 return *this;
76}
77
78template<class T>
79T& Property::setType()
80{
81 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
82 {
83 if (this->g_type != Types::PTYPE_INTEGERS)
84 {
85 this->clear();
86 this->g_type = Types::PTYPE_INTEGERS;
87 }
88
89 if constexpr (std::is_signed_v<T>)
90 {
91 this->g_isSigned = true;
92 return this->g_data._i;
93 }
94 else
95 {
96 this->g_isSigned = true;
97 return this->g_data._u;
98 }
99 }
100 else if constexpr (std::is_floating_point_v<T>)
101 {
102 if constexpr (std::is_same_v<T, float>)
103 {
104 if (this->g_type != Types::PTYPE_FLOAT)
105 {
106 this->clear();
107 this->g_type = Types::PTYPE_FLOAT;
108 }
109
110 return this->g_data._f;
111 }
112 else
113 {
114 if (this->g_type != Types::PTYPE_DOUBLE)
115 {
116 this->clear();
117 this->g_type = Types::PTYPE_DOUBLE;
118 }
119
120 return this->g_data._d;
121 }
122 }
123 else if constexpr (std::is_same_v<T, std::string>)
124 {
125 if (this->g_type != Types::PTYPE_STRING)
126 {
127 this->clear();
128 this->g_type = Types::PTYPE_STRING;
129 this->g_data._ptr = new std::string();
130 }
131
132 return *this->g_data.getString();
133 }
134 else if constexpr (std::is_pointer_v<T>)
135 {
136 if (this->g_type != Types::PTYPE_POINTER)
137 {
138 this->clear();
139 this->g_type = Types::PTYPE_POINTER;
140 }
141
142 return reinterpret_cast<std::add_lvalue_reference_t<T>>(this->g_data._ptr);
143 }
144 else
145 {
146 using TT = remove_cvref_t<T>;
147
148 if (this->g_type != Types::PTYPE_CLASS)
149 {
150 this->clear();
151 this->g_type = Types::PTYPE_CLASS;
152 this->g_data.setClassWrapper(new fge::PropertyClassWrapperType<TT>());
153 return this->g_data.getClassWrapper<TT>()->_data;
154 }
155
156 if (this->g_data.getClassWrapper()->getType() == typeid(T))
157 {
158 return this->g_data.getClassWrapper<TT>()->_data;
159 }
160
161 this->clear();
162 this->g_type = Types::PTYPE_CLASS;
163 this->g_data.setClassWrapper(new fge::PropertyClassWrapperType<TT>());
164 return this->g_data.getClassWrapper<TT>()->_data;
165 }
166}
167
168template<class T>
169bool Property::isType() const
170{
171 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
172 {
173 return this->g_type == Types::PTYPE_INTEGERS;
174 }
175 else if constexpr (std::is_floating_point_v<T>)
176 {
177 if constexpr (std::is_same_v<T, float>)
178 {
179 return this->g_type == Types::PTYPE_FLOAT;
180 }
181 else
182 {
183 return this->g_type == Types::PTYPE_DOUBLE;
184 }
185 }
186 else if constexpr (std::is_same_v<T, std::string>)
187 {
188 return this->g_type == Types::PTYPE_STRING;
189 }
190 else if constexpr (std::is_pointer_v<T>)
191 {
192 return this->g_type == Types::PTYPE_POINTER;
193 }
194 else
195 {
196 if (this->g_type == Types::PTYPE_CLASS)
197 {
198 return this->g_data.getClassWrapper()->getType() == typeid(T);
199 }
200 return false;
201 }
202}
203
204template<class T, typename>
205bool Property::set(T&& val)
206{
207 using TT = remove_cvref_t<T>;
208
209 if constexpr (std::is_integral_v<TT> || std::is_enum_v<TT>)
210 {
211 if (this->g_type != Types::PTYPE_INTEGERS)
212 {
213 if (this->g_type == Types::PTYPE_NULL)
214 {
215 this->g_type = Types::PTYPE_INTEGERS;
216 }
217 else
218 {
219 return false;
220 }
221 }
222
223 if constexpr (std::is_signed_v<TT>)
224 {
225 this->g_data._i = static_cast<fge::PintType>(val);
226 this->g_isSigned = true;
227 return true;
228 }
229 else
230 {
231 this->g_data._u = static_cast<fge::PuintType>(val);
232 this->g_isSigned = false;
233 return true;
234 }
235 }
236 else if constexpr (std::is_floating_point_v<TT>)
237 {
238 if constexpr (std::is_same_v<TT, float>)
239 {
240 if (this->g_type != Types::PTYPE_FLOAT)
241 {
242 if (this->g_type == Types::PTYPE_NULL)
243 {
244 this->g_type = Types::PTYPE_FLOAT;
245 }
246 else
247 {
248 return false;
249 }
250 }
251
252 this->g_data._f = val;
253 return true;
254 }
255 else
256 {
257 if (this->g_type != Types::PTYPE_DOUBLE)
258 {
259 if (this->g_type == Types::PTYPE_NULL)
260 {
261 this->g_type = Types::PTYPE_DOUBLE;
262 }
263 else
264 {
265 return false;
266 }
267 }
268
269 this->g_data._d = static_cast<double>(val);
270 return true;
271 }
272 }
273 else if constexpr (std::is_same_v<TT, std::string>)
274 {
275 if (this->g_type != Types::PTYPE_STRING)
276 {
277 if (this->g_type == Types::PTYPE_NULL)
278 {
279 this->g_type = Types::PTYPE_STRING;
280 this->g_data._ptr = new std::string(std::forward<T>(val));
281 return true;
282 }
283 return false;
284 }
285
286 *this->g_data.getString() = std::forward<T>(val);
287 return true;
288 }
289 else if constexpr (std::is_pointer_v<TT>)
290 {
291 if (this->g_type != Types::PTYPE_POINTER)
292 {
293 if (this->g_type == Types::PTYPE_NULL)
294 {
295 this->g_type = Types::PTYPE_POINTER;
296 }
297 else
298 {
299 return false;
300 }
301 }
302
303 this->g_data._ptr = val;
304 return true;
305 }
306 else
307 {
308 if (this->g_type != Types::PTYPE_CLASS)
309 {
310 if (this->g_type == Types::PTYPE_NULL)
311 {
312 this->g_type = Types::PTYPE_CLASS;
313 this->g_data.setClassWrapper(new fge::PropertyClassWrapperType<TT>(std::forward<T>(val)));
314 return true;
315 }
316 return false;
317 }
318
319 if (this->g_data.getClassWrapper()->getType() == typeid(TT))
320 {
321 this->g_data.getClassWrapper<TT>()->_data = std::forward<T>(val);
322 return true;
323 }
324 return false;
325 }
326}
327
328template<class T>
329bool Property::get(T& val) const
330{
331 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
332 {
333 if (this->g_type != Types::PTYPE_INTEGERS)
334 {
335 if (this->g_type == Types::PTYPE_FLOAT)
336 {
337 val = static_cast<T>(this->g_data._f);
338 return true;
339 }
340 if (this->g_type == Types::PTYPE_DOUBLE)
341 {
342 val = static_cast<T>(this->g_data._d);
343 return true;
344 }
345 return false;
346 }
347
348 if constexpr (std::is_signed_v<T>)
349 {
350 val = static_cast<T>(this->g_data._i);
351 return true;
352 }
353 else
354 {
355 val = static_cast<T>(this->g_data._u);
356 return true;
357 }
358 }
359 else if constexpr (std::is_floating_point_v<T>)
360 {
361 if constexpr (std::is_same_v<T, float>)
362 {
363 if (this->g_type != Types::PTYPE_FLOAT)
364 {
365 if (this->g_type == Types::PTYPE_INTEGERS)
366 {
367 if (this->g_isSigned)
368 {
369 val = static_cast<T>(this->g_data._i);
370 return true;
371 }
372 val = static_cast<T>(this->g_data._u);
373 return true;
374 }
375 if (this->g_type == Types::PTYPE_DOUBLE)
376 {
377 val = static_cast<T>(this->g_data._d);
378 return true;
379 }
380 return false;
381 }
382
383 val = static_cast<T>(this->g_data._f);
384 return true;
385 }
386 else
387 {
388 if (this->g_type != Types::PTYPE_DOUBLE)
389 {
390 if (this->g_type == Types::PTYPE_INTEGERS)
391 {
392 if (this->g_isSigned)
393 {
394 val = static_cast<T>(this->g_data._i);
395 return true;
396 }
397 val = static_cast<T>(this->g_data._u);
398 return true;
399 }
400 if (this->g_type == Types::PTYPE_FLOAT)
401 {
402 val = static_cast<T>(this->g_data._f);
403 return true;
404 }
405 return false;
406 }
407
408 val = static_cast<T>(this->g_data._d);
409 return true;
410 }
411 }
412 else if constexpr (std::is_same_v<T, std::string>)
413 {
414 if (this->g_type != Types::PTYPE_STRING)
415 {
416 return false;
417 }
418
419 val = *this->g_data.getString();
420 return true;
421 }
422 else if constexpr (std::is_same_v<T, char const*>)
423 {
424 if (this->g_type != Types::PTYPE_STRING)
425 {
426 return false;
427 }
428
429 val = this->g_data.getString()->data();
430 return true;
431 }
432 else if constexpr (std::is_pointer_v<T>)
433 {
434 if (this->g_type != Types::PTYPE_POINTER)
435 {
436 return false;
437 }
438
439 val = reinterpret_cast<T>(this->g_data._ptr);
440 return true;
441 }
442 else
443 {
444 if (this->g_type == Types::PTYPE_CLASS)
445 {
446 if (this->g_data.getClassWrapper()->getType() == typeid(T))
447 {
448 using TT = remove_cvref_t<T>;
449 val = this->g_data.getClassWrapper<TT>()->_data;
450 return true;
451 }
452 }
453
454 return false;
455 }
456}
457template<class T>
458std::optional<T> Property::get() const
459{
460 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
461 {
462 if (this->g_type != Types::PTYPE_INTEGERS)
463 {
464 if (this->g_type == Types::PTYPE_FLOAT)
465 {
466 return static_cast<T>(this->g_data._f);
467 }
468 if (this->g_type == Types::PTYPE_DOUBLE)
469 {
470 return static_cast<T>(this->g_data._d);
471 }
472 return std::nullopt;
473 }
474
475 if constexpr (std::is_signed_v<T>)
476 {
477 return static_cast<T>(this->g_data._i);
478 }
479 else
480 {
481 return static_cast<T>(this->g_data._u);
482 }
483 }
484 else if constexpr (std::is_floating_point_v<T>)
485 {
486 if constexpr (std::is_same_v<T, float>)
487 {
488 if (this->g_type != Types::PTYPE_FLOAT)
489 {
490 if (this->g_type == Types::PTYPE_INTEGERS)
491 {
492 if (this->g_isSigned)
493 {
494 return static_cast<T>(this->g_data._i);
495 }
496 return static_cast<T>(this->g_data._u);
497 }
498 if (this->g_type == Types::PTYPE_DOUBLE)
499 {
500 return static_cast<T>(this->g_data._d);
501 }
502 return std::nullopt;
503 }
504
505 return static_cast<T>(this->g_data._f);
506 }
507 else
508 {
509 if (this->g_type != Types::PTYPE_DOUBLE)
510 {
511 if (this->g_type == Types::PTYPE_INTEGERS)
512 {
513 if (this->g_isSigned)
514 {
515 return static_cast<T>(this->g_data._i);
516 }
517 return static_cast<T>(this->g_data._u);
518 }
519 if (this->g_type == Types::PTYPE_FLOAT)
520 {
521 return static_cast<T>(this->g_data._f);
522 }
523 return std::nullopt;
524 }
525
526 return static_cast<T>(this->g_data._d);
527 }
528 }
529 else if constexpr (std::is_same_v<T, std::string>)
530 {
531 if (this->g_type != Types::PTYPE_STRING)
532 {
533 return std::nullopt;
534 }
535
536 return *this->g_data.getString();
537 }
538 else if constexpr (std::is_same_v<T, char const*>)
539 {
540 if (this->g_type != Types::PTYPE_STRING)
541 {
542 return std::nullopt;
543 }
544
545 return this->g_data.getString()->data();
546 }
547 else if constexpr (std::is_pointer_v<T>)
548 {
549 if (this->g_type != Types::PTYPE_POINTER)
550 {
551 return std::nullopt;
552 }
553
554 return reinterpret_cast<T>(this->g_data._ptr);
555 }
556 else
557 {
558 if (this->g_type == Types::PTYPE_CLASS)
559 {
560 if (this->g_data.getClassWrapper()->getType() == typeid(T))
561 {
562 using TT = remove_cvref_t<T>;
563 return this->g_data.getClassWrapper<TT>()->_data;
564 }
565 }
566
567 return std::nullopt;
568 }
569}
570
571template<class T>
572T* Property::getPtr()
573{
574 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
575 {
576 if constexpr (sizeof(T) != sizeof(fge::PintType))
577 {
578 return nullptr;
579 }
580
581 if (this->g_type != Types::PTYPE_INTEGERS)
582 {
583 return nullptr;
584 }
585
586 if constexpr (std::is_signed_v<T>)
587 {
588 return static_cast<T*>(&this->g_data._i);
589 }
590 else
591 {
592 return static_cast<T*>(&this->g_data._u);
593 }
594 }
595 else if constexpr (std::is_floating_point_v<T>)
596 {
597 if constexpr (std::is_same_v<T, float>)
598 {
599 if (this->g_type != Types::PTYPE_FLOAT)
600 {
601 return nullptr;
602 }
603
604 return &this->g_data._f;
605 }
606 else
607 {
608 if (this->g_type != Types::PTYPE_DOUBLE)
609 {
610 return nullptr;
611 }
612
613 return &this->g_data._d;
614 }
615 }
616 else if constexpr (std::is_same_v<T, std::string>)
617 {
618 if (this->g_type != Types::PTYPE_STRING)
619 {
620 return nullptr;
621 }
622
623 return this->g_data.getString();
624 }
625 else if constexpr (std::is_pointer_v<T>)
626 {
627 if (this->g_type != Types::PTYPE_POINTER)
628 {
629 return nullptr;
630 }
631
632 return &reinterpret_cast<T&>(this->g_data._ptr);
633 }
634 else
635 {
636 if (this->g_type == Types::PTYPE_CLASS)
637 {
638 if (this->g_data.getClassWrapper()->getType() == typeid(T))
639 {
640 using TT = remove_cvref_t<T>;
641 return &this->g_data.getClassWrapper<TT>()->_data;
642 }
643 }
644
645 return nullptr;
646 }
647}
648template<class T>
649T const* Property::getPtr() const
650{
651 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
652 {
653 if constexpr (sizeof(T) != sizeof(fge::PintType))
654 {
655 return nullptr;
656 }
657
658 if (this->g_type != Types::PTYPE_INTEGERS)
659 {
660 return nullptr;
661 }
662
663 if constexpr (std::is_signed_v<T>)
664 {
665 return static_cast<T*>(&this->g_data._i);
666 }
667 else
668 {
669 return static_cast<T*>(&this->g_data._u);
670 }
671 }
672 else if constexpr (std::is_floating_point_v<T>)
673 {
674 if constexpr (std::is_same_v<T, float>)
675 {
676 if (this->g_type != Types::PTYPE_FLOAT)
677 {
678 return nullptr;
679 }
680
681 return &this->g_data._f;
682 }
683 else
684 {
685 if (this->g_type != Types::PTYPE_DOUBLE)
686 {
687 return nullptr;
688 }
689
690 return &this->g_data._d;
691 }
692 }
693 else if constexpr (std::is_same_v<T, std::string>)
694 {
695 if (this->g_type != Types::PTYPE_STRING)
696 {
697 return nullptr;
698 }
699
700 return this->g_data.getString();
701 }
702 else if constexpr (std::is_pointer_v<T>)
703 {
704 if (this->g_type != Types::PTYPE_POINTER)
705 {
706 return nullptr;
707 }
708
709 return &reinterpret_cast<T&>(this->g_data._ptr);
710 }
711 else
712 {
713 if (this->g_type == Types::PTYPE_CLASS)
714 {
715 if (this->g_data.getClassWrapper()->getType() == typeid(T))
716 {
717 using TT = remove_cvref_t<T>;
718 return &this->g_data.getClassWrapper<TT>()->_data;
719 }
720 }
721
722 return nullptr;
723 }
724}
725
726template<class T>
727bool Property::pushType()
728{
729 if (this->g_type == Types::PTYPE_CLASS)
730 {
731 if (this->g_data.getClassWrapper()->getType() == typeid(fge::ParrayType))
732 {
733 this->g_data.getArray()->_data.emplace_back().setType<T>();
734 return true;
735 }
736 }
737 return false;
738}
739
740template<class T>
741bool Property::getData(std::size_t index, T& val) const
742{
743 if (this->g_type == Types::PTYPE_CLASS)
744 {
745 if (this->g_data.getClassWrapper()->getType() == typeid(fge::ParrayType))
746 {
747 if (this->g_data.getArray()->_data.size() > index)
748 {
749 return this->g_data.getArray()->_data[index].get<T>(val);
750 }
751 }
752 }
753 return false;
754}
755template<class T>
756T* Property::getDataPtr(std::size_t index)
757{
758 if (this->g_type == Types::PTYPE_CLASS)
759 {
760 if (this->g_data.getClassWrapper()->getType() == typeid(fge::ParrayType))
761 {
762 if (this->g_data.getArray()->_data.size() > index)
763 {
764 return this->g_data.getArray()->_data[index].getPtr<T>();
765 }
766 }
767 }
768 return nullptr;
769}
770template<class T>
771T const* Property::getDataPtr(std::size_t index) const
772{
773 if (this->g_type == Types::PTYPE_CLASS)
774 {
775 if (this->g_data.getClassWrapper()->getType() == typeid(fge::ParrayType))
776 {
777 if (this->g_data.getArray()->_data.size() > index)
778 {
779 return this->g_data.getArray()->_data[index].getPtr<T>();
780 }
781 }
782 }
783 return nullptr;
784}
785
786//PropertyClassWrapperType
787
788template<class T>
789template<typename>
790PropertyClassWrapperType<T>::PropertyClassWrapperType(T const& val) :
791 _data(val)
792{}
793template<class T>
794template<typename>
795PropertyClassWrapperType<T>::PropertyClassWrapperType(T&& val) noexcept :
796 _data(val)
797{}
798
799template<class T>
800std::type_info const& PropertyClassWrapperType<T>::getType() const
801{
802 return typeid(T);
803}
804
805template<class T>
806std::string PropertyClassWrapperType<T>::toString() const
807{
808 if constexpr (std::is_same_v<T, fge::ParrayType>)
809 {
810 return fge::string::ToStr(this->_data);
811 }
812 else
813 {
814 return typeid(T).name();
815 }
816}
817
818template<class T>
819fge::PropertyClassWrapper* PropertyClassWrapperType<T>::copy() const
820{
821 return static_cast<fge::PropertyClassWrapper*>(new fge::PropertyClassWrapperType<T>(this->_data));
822}
823
824template<class T>
825bool PropertyClassWrapperType<T>::tryToCopy(fge::PropertyClassWrapper const* val)
826{
827 if (val->getType() == typeid(T))
828 {
829 this->_data = reinterpret_cast<fge::PropertyClassWrapperType<T> const*>(val)->_data;
830 return true;
831 }
832 return false;
833}
834
835template<class T>
836bool PropertyClassWrapperType<T>::compare(fge::PropertyClassWrapper const* val)
837{
838 if (val->getType() == typeid(T))
839 {
840 if constexpr (comparisonCheck::EqualExists<T>::value)
841 {
842 return this->_data == reinterpret_cast<fge::PropertyClassWrapperType<T> const*>(val)->_data;
843 }
844 else
845 {
846 return false;
847 }
848 }
849 return false;
850}
851
852} // namespace fge
Definition C_property.hpp:241
Definition C_property.hpp:206
A class that can store any type of data.
Definition C_property.hpp:54
FGE_API std::string ToStr(bool val)
Convert efficiently a boolean to a string.